Plainer wording in contributor docs, templates and privacy policy (#285)

This commit is contained in:
2026-09-30 19:44:44 +02:00
parent d66116eb8f
commit be797bb82d
13 changed files with 66 additions and 69 deletions
+2 -2
View File
@@ -21,9 +21,9 @@ labels:
- Calendula version: <!-- Settings → bottom of the screen --> - Calendula version: <!-- Settings → bottom of the screen -->
- Android version: - Android version:
- Device: - Device:
- Installed from: <!-- official F-Droid / the self-hosted repo / built from source --> - Installed from: <!-- official F-Droid / the self-hosted repo / Google Play / Codeberg APK or Obtainium / built from source -->
- Affected calendar: <!-- Google, CalDAV (DAVx5, Nextcloud, …), on-device/local, - Affected calendar: <!-- Google, CalDAV (DAVx5, Nextcloud, …), on-device/local,
subscribed/WebCal, birthdays — provider behaviour differs subscribed/WebCal, birthdays. Provider behaviour differs
a lot per account type, so this often points straight at a lot per account type, so this often points straight at
the cause --> the cause -->
- Time zone: <!-- only if the problem involves dates or all-day events --> - Time zone: <!-- only if the problem involves dates or all-day events -->
+2 -2
View File
@@ -6,8 +6,8 @@ contact_links:
- name: Translate Calendula - name: Translate Calendula
url: https://weblate.dev.jeanlucmakiola.de/engage/calendula/ url: https://weblate.dev.jeanlucmakiola.de/engage/calendula/
about: >- about: >-
Translations are managed on Weblate, not here — it owns every values-* Translations are managed on Weblate. It owns every values-* file, so a
file, so a hand-edited translation gets overwritten on the next sync. hand-edited translation gets overwritten on the next sync.
No coding needed: pick or request a language and translate in the browser. No coding needed: pick or request a language and translate in the browser.
- name: Contributing guide - name: Contributing guide
+3 -3
View File
@@ -1,6 +1,6 @@
--- ---
name: Crash report name: Crash report
about: Report a crash. Calendula can capture this for you (Settings → Report a problem, or the prompt after a crash) — it copies the report to your clipboard and prefills this form. about: Report a crash. Calendula can capture this for you (Settings → Report a problem, or the prompt after a crash). It copies the report to your clipboard and prefills this form.
title: "Crash: " title: "Crash: "
labels: labels:
- bug - bug
@@ -11,10 +11,10 @@ labels:
<!-- <!--
Thanks for reporting a crash in Calendula! Thanks for reporting a crash in Calendula!
If the app prefilled this for you, the crash report is already below — just add If the app prefilled this for you, the crash report is already below. Add
what you were doing and submit. Otherwise, paste the report from your clipboard what you were doing and submit. Otherwise, paste the report from your clipboard
into the code block. The report contains only app/Android/device versions and the into the code block. The report contains only app/Android/device versions and the
stack trace — no personal data or calendar content. stack trace, with no personal data or calendar content.
--> -->
### What happened ### What happened
+1 -1
View File
@@ -9,7 +9,7 @@ labels:
### What would you like Calendula to do? ### What would you like Calendula to do?
### Why — what problem does it solve? ### What problem does it solve?
### Anything else ### Anything else
+3 -3
View File
@@ -5,7 +5,7 @@ Please skim CONTRIBUTING.md if you haven't:
https://codeberg.org/jlmakiola/calendula/src/branch/main/CONTRIBUTING.md https://codeberg.org/jlmakiola/calendula/src/branch/main/CONTRIBUTING.md
Two things it's easy to get wrong: Two things it's easy to get wrong:
• Features need a discussed issue first — an undiscussed feature PR may be • Features need a discussed issue first. An undiscussed feature PR may be
closed unmerged even when the code is good. closed unmerged even when the code is good.
• Target the release branch for your issue's milestone (milestone 2.18.0 → • Target the release branch for your issue's milestone (milestone 2.18.0 →
release/v2.18.0), not main. If you targeted main, just say so below and it release/v2.18.0), not main. If you targeted main, just say so below and it
@@ -17,7 +17,7 @@ Two things it's easy to get wrong:
### Why ### Why
<!-- Closes #123 — link the issue this implements or fixes. --> <!-- Closes #123: link the issue this implements or fixes. -->
### How it was tested ### How it was tested
@@ -34,7 +34,7 @@ are especially useful for UI changes.
### Checklist ### Checklist
- [ ] There's an issue for this, and (for a feature) it got a go-ahead - [ ] There's an issue for this, and (for a feature) it got a go-ahead
- [ ] Targeting the release branch for that issue's milestone — or `main`, noted above - [ ] Targeting the release branch for that issue's milestone (or `main`, noted above)
- [ ] `./gradlew lint test assembleDebug` passes locally - [ ] `./gradlew lint test assembleDebug` passes locally
- [ ] No `values-*/strings.xml` touched (Weblate owns those; new English strings in `values/` are fine) - [ ] No `values-*/strings.xml` touched (Weblate owns those; new English strings in `values/` are fine)
- [ ] `CHANGELOG.md` updated under `## [Unreleased]`, if the change is user-visible - [ ] `CHANGELOG.md` updated under `## [Unreleased]`, if the change is user-visible
+29 -29
View File
@@ -1,13 +1,13 @@
# Contributing to Calendula # Contributing to Calendula
Calendula is a Material 3 Expressive calendar app that lives strictly on top of Calendula is a Material 3 Expressive calendar app that lives strictly on top of
Android's `CalendarContract` — no app database, no sync stack, no network access. Android's `CalendarContract`, with no app database, sync stack or network access.
That constraint shapes most review comments, so That constraint shapes most review comments, so skim
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) is worth skimming before you write [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) before you write code. This file
code. This file is the practical how. covers the practical side.
**[Codeberg](https://codeberg.org/jlmakiola/calendula) is the canonical home** — [Codeberg](https://codeberg.org/jlmakiola/calendula) is the canonical home for
issues, pull requests, releases. The self-hosted Gitea instance referenced in the issues, pull requests and releases. The self-hosted Gitea instance referenced in the
release docs is build infrastructure only; there is nothing to contribute there. release docs is build infrastructure only; there is nothing to contribute there.
Be decent to the people you meet in the tracker. Be decent to the people you meet in the tracker.
@@ -18,20 +18,20 @@ Be decent to the people you meet in the tracker.
| Add a feature | **Open an issue first** and wait for a go-ahead | | Add a feature | **Open an issue first** and wait for a go-ahead |
| Fix a bug | Open an issue, then a pull request | | Fix a bug | Open an issue, then a pull request |
| Fix a typo, a comment, or docs | Just open the pull request | | Fix a typo, a comment, or docs | Just open the pull request |
| Add or fix a translation | **Don't** — [use Weblate](#translations) | | Add or fix a translation | Use [Weblate](#translations), not a pull request |
Features get an opinion before they get code: whether Calendula should do a Features get an opinion before they get code: whether Calendula should do a
thing at all is the one decision a patch can't make. A feature PR that arrives thing at all is the one decision a patch can't make. A feature PR that arrives
without a discussed issue may be closed unmerged even when the code is good — without a discussed issue may be closed unmerged even when the code is good, so
please don't spend a weekend on one first. please don't spend a weekend on one first.
Bugs are more straightforward, but still start with an issue: it's what carries Bugs are more straightforward, but still start with an issue: it's what carries
the milestone and gives the changelog something to link. the milestone and gives the changelog something to link.
Issue templates cover bug, crash, feature and question. For a crash, let the app Issue templates cover bug, crash, feature and question. For a crash, let the app
do the work — **Settings → Report a problem**, or the prompt shown after a crash, do the work: *Settings → Report a problem*, or the prompt shown after a crash,
captures the stack trace and prefills the form. The report contains app, Android captures the stack trace and prefills the form. The report contains app, Android
and device versions plus the trace; no calendar content, no personal data. and device versions plus the trace, and no calendar content or personal data.
## Which branch to target ## Which branch to target
@@ -45,20 +45,20 @@ Once your issue has a milestone, that milestone names your branch:
| `2.18.0` | `release/v2.18.0` | | `2.18.0` | `release/v2.18.0` |
Every milestone has a matching branch. If it's somehow missing, target `main` and Every milestone has a matching branch. If it's somehow missing, target `main` and
mention it in the PR — it will be retargeted. Don't pick an older release branch: mention it in the PR, and it will be retargeted. Don't pick an older release branch:
they're kept after shipping, so the newest one isn't necessarily yours. they're kept after shipping, so the newest one isn't necessarily yours.
## Translations ## Translations
**Never edit a `values-*/strings.xml` file in a pull request** — German included. **Never edit a `values-*/strings.xml` file in a pull request**, German included.
Translations are owned by a self-hosted Weblate that writes to this repository Translations are owned by a self-hosted Weblate that writes to this repository
directly, and a hand-edit is overwritten on the next sync. directly, and a hand-edit is overwritten on the next sync.
→ **[Translate Calendula on Weblate](https://weblate.dev.jeanlucmakiola.de/engage/calendula/)** [Translate Calendula on Weblate](https://weblate.dev.jeanlucmakiola.de/engage/calendula/)
Adding a *new* English string to `values/strings.xml` is normal PR work; Weblate Adding a *new* English string to `values/strings.xml` is normal PR work; Weblate
picks it up and offers it to translators. Partial translations are expected and picks it up and offers it to translators. Partial translations are expected and
fine — missing keys are informational. Stale and orphaned keys are not, so run fine; missing keys are informational. Stale and orphaned keys are not, so run
```sh ```sh
python3 scripts/check_translations.py python3 scripts/check_translations.py
@@ -67,7 +67,7 @@ python3 scripts/check_translations.py
before pushing. It reports those more clearly than lint's `MissingTranslation` before pushing. It reports those more clearly than lint's `MissingTranslation`
does. does.
## Build & test ## Build and test
```sh ```sh
git clone --recurse-submodules https://codeberg.org/jlmakiola/calendula.git git clone --recurse-submodules https://codeberg.org/jlmakiola/calendula.git
@@ -77,11 +77,11 @@ The `floret-kit` submodule is a composite build compiled from source. An
existing clone needs `git submodule update --init --recursive`, or nothing existing clone needs `git submodule update --init --recursive`, or nothing
resolves. resolves.
- **JDK 17** — not newer; the Android Gradle Plugin requires exactly 17. Set - **JDK 17**, not newer: the Android Gradle Plugin requires exactly 17. Set
`JAVA_HOME` if your default differs. `JAVA_HOME` if your default differs.
- **Android SDK** — platform 37 (`compileSdk`) and build-tools 36.0.0, located - **Android SDK**: platform 37 (`compileSdk`) and build-tools 36.0.0, located
via `ANDROID_HOME` or a gitignored `local.properties` with `sdk.dir`. If you via `ANDROID_HOME` or a gitignored `local.properties` with `sdk.dir`. If you
go the `local.properties` route the included build needs its own copy at go the `local.properties` route, the included build needs its own copy at
`floret-kit/local.properties`; `ANDROID_HOME` covers both at once and is the `floret-kit/local.properties`; `ANDROID_HOME` covers both at once and is the
easier path. easier path.
@@ -109,21 +109,21 @@ These are the ones that turn into review comments.
1. **No network.** Calendula holds no `INTERNET` permission, and that's a 1. **No network.** Calendula holds no `INTERNET` permission, and that's a
feature rather than an oversight. Anything that would need one is a product feature rather than an oversight. Anything that would need one is a product
decision before it's a patch — the crash reporter deliberately opens a decision before it's a patch. The crash reporter opens a prefilled web issue
prefilled web issue instead of posting anything itself. on purpose instead of posting anything itself.
2. **The provider is the only database.** No Room, no cache, no local mirror of 2. **The provider is the only database.** No Room, no cache, no local mirror of
events. `CalendarContract` is the single source of truth, which is also why events. `CalendarContract` is the single source of truth, which is also why
externally synced changes work for free. externally synced changes work for free.
3. **Don't patch UI state after a write.** A `ContentObserver` re-queries and 3. **Don't patch UI state after a write.** A `ContentObserver` re-queries and
views recompose from fresh provider state. Hand-patching a list after saving views recompose from fresh provider state. Hand-patching a list after saving
appears to work, then quietly diverges from what the provider actually stored. appears to work, then drifts away from what the provider stored.
4. **`domain/` has no Android imports.** Models, validation, recurrence 4. **`domain/` has no Android imports.** Models, validation, recurrence
rendering, conflict snapshots and the `.ics` codec stay pure Kotlin so they rendering, conflict snapshots and the `.ics` codec stay pure Kotlin so they
remain JVM-testable. remain JVM-testable.
5. **Tests run on the JVM.** JUnit 5 + Truth + Turbine. The seams exist for you: 5. **Tests run on the JVM.** JUnit 5 + Truth + Turbine. The seams exist for you:
fake the data source (`FakeCalendarDataSource`), and feed mappers plain maps fake the data source (`FakeCalendarDataSource`), and feed mappers plain maps
through `ColumnReader` instead of cursors. Instrumented tests are a last through `ColumnReader` instead of cursors. Instrumented tests are a last
resort, not a default. resort.
6. **Read before touching the subtle pipelines.** Recurring writes (UNTIL vs 6. **Read before touching the subtle pipelines.** Recurring writes (UNTIL vs
DURATION, exception URIs, series splits), save-conflict detection and reminder DURATION, exception URIs, series splits), save-conflict detection and reminder
delivery (post-before-mark) follow provider-driven rules that are documented delivery (post-before-mark) follow provider-driven rules that are documented
@@ -138,14 +138,14 @@ These are the ones that turn into review comments.
## UI conventions ## UI conventions
Material 3 Expressive throughout, built from the system's own tokens and Material 3 Expressive throughout, built from the system's own tokens and
components — colour-scheme tokens rather than hardcoded colours, `ListItem` for components: colour-scheme tokens rather than hardcoded colours, `ListItem` for
settings rows. settings rows.
**Selection pickers are full-screen.** Every browse-style "choose one" surface **Selection pickers are full-screen.** Every browse-style "choose one" surface
uses floret-kit's `FullScreenPicker` / `OptionPicker`; one that needs a commit or uses floret-kit's `FullScreenPicker` / `OptionPicker`; one that needs a commit or
extra action passes it through the picker's `actions` slot. The exception is the extra action passes it through the picker's `actions` slot. The exception is the
recurring-scope chooser (*this / this and following / all*), which stays a recurring-scope chooser (*this / this and following / all*), which stays a
compact dialog — a two- or three-option decision reads better as a popup than as compact dialog, because a two- or three-option decision reads better as a popup than as
a nearly empty screen. `AlertDialog` is for plain confirmations only, and radio- a nearly empty screen. `AlertDialog` is for plain confirmations only, and radio-
or text-list dialogs aren't used at all. or text-list dialogs aren't used at all.
@@ -154,7 +154,7 @@ Shared UI machinery lives in the `floret-kit` submodule and has
changing it means a pull request against that repository plus a submodule bump changing it means a pull request against that repository plus a submodule bump
here. here.
## Commits & pull requests ## Commits and pull requests
Conventional commits, scoped to the area you touched: Conventional commits, scoped to the area you touched:
@@ -165,13 +165,13 @@ docs(architecture): record what the second review pass changed
``` ```
Types in use: `feat` `fix` `docs` `refactor` `style` `chore` `ci` `build` Types in use: `feat` `fix` `docs` `refactor` `style` `chore` `ci` `build`
`revert`. Reference the issue in the subject or the body. Keep commits small — `revert`. Reference the issue in the subject or the body. Keep commits small.
small commits revert cleanly, which matters more here than a tidy history. Small commits revert cleanly, which matters more here than a tidy history.
If your change is user-visible, add an entry under `## [Unreleased]` in If your change is user-visible, add an entry under `## [Unreleased]` in
[`CHANGELOG.md`](CHANGELOG.md). Match the surrounding voice: entries describe [`CHANGELOG.md`](CHANGELOG.md). Match the surrounding voice: entries describe
what changed *for the person using the app*, and why, not what changed in the what changed *for the person using the app*, and why. Code changes don't go
code. Link the issue and add its reference at the bottom of the file. It may get there. Link the issue and add its reference at the bottom of the file. It may get
reworded when the release is cut, so don't agonise over it. reworded when the release is cut, so don't agonise over it.
Please don't commit planning or design documents. Code, tests, architecture notes Please don't commit planning or design documents. Code, tests, architecture notes
Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

+7 -7
View File
@@ -1,7 +1,7 @@
# Building from source # Building from source
Calendula builds with the standard Android Gradle toolchain — no extra setup Calendula builds with the standard Android Gradle toolchain. You need the SDK,
beyond the SDK, a JDK, and the submodule. a JDK and the submodule, nothing else.
## Clone ## Clone
@@ -9,9 +9,9 @@ beyond the SDK, a JDK, and the submodule.
git clone --recurse-submodules https://codeberg.org/jlmakiola/calendula.git git clone --recurse-submodules https://codeberg.org/jlmakiola/calendula.git
``` ```
Calendula depends on **[floret-kit](https://codeberg.org/jlmakiola/floret-kit)**, Calendula depends on [floret-kit](https://codeberg.org/jlmakiola/floret-kit),
the shared Material 3 Expressive kit, as a git submodule wired in as a Gradle the shared Material 3 Expressive kit, as a git submodule wired in as a Gradle
composite build (`includeBuild("floret-kit")` in `settings.gradle.kts`) — it is composite build (`includeBuild("floret-kit")` in `settings.gradle.kts`). It is
compiled from source, not resolved from a repository. A clone without the compiled from source, not resolved from a repository. A clone without the
submodule fails to configure. For an existing clone: submodule fails to configure. For an existing clone:
@@ -21,14 +21,14 @@ git submodule update --init --recursive
## Requirements ## Requirements
- **JDK 17** — not newer; the Android Gradle Plugin requires exactly 17. If your - **JDK 17**, not newer: the Android Gradle Plugin requires exactly 17. If your
default JDK differs, set `JAVA_HOME` explicitly. default JDK differs, set `JAVA_HOME` explicitly.
- **Android SDK** — platform **37** (`compileSdk`) and **build-tools 36.0.0**. - **Android SDK**: platform 37 (`compileSdk`) and build-tools 36.0.0.
`minSdk` is 29, `targetSdk` 36. `minSdk` is 29, `targetSdk` 36.
The SDK is located via `ANDROID_HOME` (or `ANDROID_SDK_ROOT`), or via a The SDK is located via `ANDROID_HOME` (or `ANDROID_SDK_ROOT`), or via a
gitignored `local.properties` with `sdk.dir`. If you use `local.properties`, note gitignored `local.properties` with `sdk.dir`. If you use `local.properties`, note
that the composite build needs **its own** copy at `floret-kit/local.properties`; that the composite build needs its own copy at `floret-kit/local.properties`;
setting `ANDROID_HOME` covers both builds at once and is the simpler route. setting `ANDROID_HOME` covers both builds at once and is the simpler route.
The Gradle wrapper is checked in, so you don't need a system Gradle. The Gradle wrapper is checked in, so you don't need a system Gradle.
+13 -13
View File
@@ -26,7 +26,7 @@ Applies to the Android app **Calendula** (package `de.jeanlucmakiola.calendula`)
## In short ## In short
Calendula collects nothing, sends nothing, and has no user accounts. It has **no internet permission at all** — the app is technically incapable of transmitting your data anywhere. Everything it shows you is read from the calendars that already exist on your device. Calendula collects nothing, sends nothing, and has no user accounts. It has **no internet permission at all**, so it cannot transmit your data anywhere. Everything it shows you is read from the calendars that already exist on your device.
## 1. Controller ## 1. Controller
@@ -47,9 +47,9 @@ All of the following is processed **locally on your device only**. None of it is
### Calendar data ### Calendar data
Calendula is a viewer and editor for the calendars Android already manages. It reads and writes events, reminders and calendar settings through Android's system calendar provider. The app keeps **no database of its own** — your events live in the system calendar, exactly where they lived before you installed Calendula, and they remain there if you uninstall it. Calendula is a viewer and editor for the calendars Android already manages. It reads and writes events, reminders and calendar settings through Android's system calendar provider. The app keeps **no database of its own**. Your events live in the system calendar, where they were before you installed Calendula, and they stay there if you uninstall it.
Note: if one of those system calendars is itself synchronised with an online account (for example a Google account, or a CalDAV server via DAVx5), that synchronisation is performed by Android and that other app — not by Calendula. The privacy policy of the respective provider applies to it. Note: if one of those system calendars is itself synchronised with an online account (for example a Google account, or a CalDAV server via DAVx5), that synchronisation is performed by Android and that other app, not by Calendula. The privacy policy of the respective provider applies to it.
### Contacts (optional) ### Contacts (optional)
@@ -67,7 +67,7 @@ When you import or export an ICS file, Calendula reads or writes exactly the fil
Your preferences (view options, theme, reminder defaults and similar) are stored locally on your device and are removed when you uninstall the app. Your preferences (view options, theme, reminder defaults and similar) are stored locally on your device and are removed when you uninstall the app.
## 4. Crash reports — the only case where data can leave your device ## 4. Crash reports: the only case where data can leave your device
If Calendula crashes, it offers to report the problem. Nothing is sent automatically. The report is copied to your clipboard and your browser is opened with the project's issue tracker, the text pre-filled. **You see the full content, you decide whether to submit it, and you can edit or discard it.** If Calendula crashes, it offers to report the problem. Nothing is sent automatically. The report is copied to your clipboard and your browser is opened with the project's issue tracker, the text pre-filled. **You see the full content, you decide whether to submit it, and you can edit or discard it.**
@@ -86,19 +86,19 @@ If you choose to submit it, the report becomes a public issue on the project's i
## 5. External links ## 5. External links
The settings screen contains links to the source code, the licence, the issue tracker and a voluntary donation page (Ko-fi). Following one of these links opens your browser and leaves the app; the privacy policy of the respective website then applies. Calendula transmits no data of yours in the process — it only opens the address. The settings screen contains links to the source code, the licence, the issue tracker and a voluntary donation page (Ko-fi). Following one of these links opens your browser and leaves the app; the privacy policy of the respective website then applies. Calendula transmits none of your data in the process; it only opens the address.
## 6. Permissions and why they exist ## 6. Permissions and why they exist
- `READ_CALENDAR`, `WRITE_CALENDAR` — display and edit your events; the core function. - `READ_CALENDAR`, `WRITE_CALENDAR`: display and edit your events (the core function).
- `POST_NOTIFICATIONS` — show reminders. - `POST_NOTIFICATIONS`: show reminders.
- `READ_CONTACTS` — optional, only for the “Contact special dates” feature. - `READ_CONTACTS`: optional, only for the “Contact special dates” feature.
- `USE_EXACT_ALARM`, `SCHEDULE_EXACT_ALARM` — deliver reminders at the exact time, including after snoozing. - `USE_EXACT_ALARM`, `SCHEDULE_EXACT_ALARM`: deliver reminders at the exact time, including after snoozing.
- `RECEIVE_BOOT_COMPLETED` — re-register pending reminders after a restart. - `RECEIVE_BOOT_COMPLETED`: re-register pending reminders after a restart.
- `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` — only to open the system dialog for the “Reliable delivery” setting. - `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS`: only to open the system dialog for the “Reliable delivery” setting.
- `WAKE_LOCK`, `FOREGROUND_SERVICE`, `ACCESS_NETWORK_STATE` — required by the Android system component used for scheduled background work (WorkManager). - `WAKE_LOCK`, `FOREGROUND_SERVICE`, `ACCESS_NETWORK_STATE`: required by the Android system component used for scheduled background work (WorkManager).
`ACCESS_NETWORK_STATE` allows reading *whether* a network connection exists — it does **not** permit using one. Without `INTERNET`, no connection is possible. `ACCESS_NETWORK_STATE` allows reading *whether* a network connection exists. It does **not** permit using one. Without `INTERNET`, no connection is possible.
## 7. Distribution channels ## 7. Distribution channels
+6 -9
View File
@@ -9,17 +9,14 @@ Where to look for what:
| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Orientation tour: principles, layers, navigation, recurring-write / conflict / reminder pipelines, testing | | [`ARCHITECTURE.md`](ARCHITECTURE.md) | Orientation tour: principles, layers, navigation, recurring-write / conflict / reminder pipelines, testing |
| [`RELEASING.md`](RELEASING.md) | Release process: versioning, the merge-driven pipeline, the two-forge split, secrets, key custody | | [`RELEASING.md`](RELEASING.md) | Release process: versioning, the merge-driven pipeline, the two-forge split, secrets, key custody |
| [`../CHANGELOG.md`](../CHANGELOG.md) | Release history (Keep a Changelog, SemVer) | | [`../CHANGELOG.md`](../CHANGELOG.md) | Release history (Keep a Changelog, SemVer) |
| [Issues](https://codeberg.org/jlmakiola/calendula/issues) + [milestones](https://codeberg.org/jlmakiola/calendula/milestones) | **The roadmap.** What's planned, in progress, and shipped — a milestone maps to its `release/vX.Y.Z` branch | | [Issues](https://codeberg.org/jlmakiola/calendula/issues) + [milestones](https://codeberg.org/jlmakiola/calendula/milestones) | The roadmap: what's planned, in progress and shipped. A milestone maps to its `release/vX.Y.Z` branch |
| [`../.planning/PROJECT.md`](../.planning/PROJECT.md) | What the project is: core value, stack + version pins, constraints, naming, forge/release infrastructure | | [`../.planning/PROJECT.md`](../.planning/PROJECT.md) | What the project is: core value, stack + version pins, constraints, naming, forge/release infrastructure |
| [`design/`](design/) | Per-feature design notes kept for features whose provider behaviour is worth recording | | [`design/`](design/) | Per-feature design notes kept for features whose provider behaviour is worth recording |
| [`../fastlane/metadata/android/`](../fastlane/metadata/android/) | Store metadata (single source of truth) for every app language, mapped in `store-locales.txt`: descriptions, title, graphics. Harvested directly by the official F-Droid repo, pushed to Google Play with every release, validated by [`../scripts/check_store_listing.py`](../scripts/check_store_listing.py); transformed into the self-hosted repo layout at release time by [`../scripts/fastlane_to_fdroid_localized.sh`](../scripts/fastlane_to_fdroid_localized.sh) | | [`../fastlane/metadata/android/`](../fastlane/metadata/android/) | Store metadata (single source of truth) for every app language, mapped in `store-locales.txt`: descriptions, title, graphics. Harvested directly by the official F-Droid repo, pushed to Google Play with every release, validated by [`../scripts/check_store_listing.py`](../scripts/check_store_listing.py); transformed into the self-hosted repo layout at release time by [`../scripts/fastlane_to_fdroid_localized.sh`](../scripts/fastlane_to_fdroid_localized.sh) |
| [`../fdroid-metadata/`](../fdroid-metadata/) | App-level F-Droid control file (`*.yml`: Categories, License, links) for the self-hosted repo's `fdroid update` | | [`../fdroid-metadata/`](../fdroid-metadata/) | App-level F-Droid control file (`*.yml`: Categories, License, links) for the self-hosted repo's `fdroid update` |
| [`fdroid-official/`](fdroid-official/) | Recipe + notes for publishing to the **official** F-Droid repo (reproducible build + developer-signed binary) | | [`fdroid-official/`](fdroid-official/) | Recipe and notes for publishing to the official F-Droid repo (reproducible build + developer-signed binary) |
Conventions: planning lives in the **issue tracker**, not in this repository. The Planning lives in the issue tracker and its milestones, not in this repository.
`.planning/` files that predated it (a roadmap, a development-state snapshot, and `.planning/PROJECT.md` describes the project itself.
a per-milestone requirement checklist) are gone — issues and milestones say the `ARCHITECTURE.md` is updated with the code and is the place to record a lesson
same thing without going stale. `PROJECT.md` is what remains, and it describes learned about the calendar provider.
the project rather than its plan.
`ARCHITECTURE.md` is the authoritative orientation tour: it is updated with the
code, and is the right place for a lesson learned about the calendar provider.