versionName 1.0.0, versionCode 10000. Merging this to main triggers
.gitea/workflows/release.yaml, which builds it, publishes to the F-Droid repo,
and mints the v1.0.0 tag — and this is the release where `prerelease` flips to
false on its own, since the pipeline derives it from MAJOR.
CHANGELOG's 1.0.0 section covers the own store, list management, recurrence,
iCalendar export, the storage picker and the copy path, then the fixes to the
external-provider mode that 0.4.0 and earlier used for everything — the
reverting due times, the all-day drift, the silent save failure on tasks with a
duration, recurrence detection on tasks.org, the inert reminder field, and the
provider-failure recovery.
Nothing about the dropped authority or the custom permissions: they never
reached a release, so there is nothing for a user to have lost.
`changelogs/10000.txt` is `scripts/sync_changelog_to_fastlane.sh` output, for
the official F-Droid listing, at 471 of the 500 characters F-Droid will show —
the section is written to that budget rather than trimmed to fit it, since the
same text is the Gitea release notes. The detail behind each line is in the
commit messages, CHANGELOG's older entries stay as they were.
Still open before this merges, per docs/RELEASING.md step 4 and ROADMAP:
`./gradlew :app:connectedDebugAndroidTest` against the tip, and
`scripts/verify-release.sh` on a real device.
Ships the first community translations: German (98%) and Brazilian
Portuguese (100%), both from Weblate, plus the translation infrastructure
and the Codeberg forge move that had accumulated under Unreleased.
A minor bump rather than a patch: two new user-facing languages is a
feature, the way 0.3.0 was cut for Reminders.
versionCode is the derived 400 (MAJOR*10000 + MINOR*100 + PATCH), and
scripts/sync_changelog_to_fastlane.sh generated changelogs/400.txt so the
official F-Droid listing shows this version's "What's New". At 908 chars
it exceeds the script's 500-char advisory and may be truncated in-client
— consistent with past feature releases (0.2.0 ran 1811, 0.3.0 692).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146mhMLZ5AqJSZkADDc92Jz
Makes Codeberg canonical for git, issues, PRs, tags and releases. The self-hosted Gitea instance stays build infrastructure: signing key, F-Droid publishing, release pipeline. Ports the setup Calendula already runs on, adapted where Agendula genuinely differs.
**This PR is its own test.** It is the first PR opened on Codeberg, so a green `CI` check proves the new runner works *and* that the submodule resolves from its new home.
### 1 · Workflows split by directory
Forgejo's lookup is first-match-wins across `.forgejo/` → `.gitea/` → `.github/`, and Gitea cannot see `.forgejo/` at all. So each forge sees exactly one set, with no duplicated files and no expression to keep in sync:
| Directory | Runs on | Contains | Secrets |
| --- | --- | --- | --- |
| `.forgejo/workflows/` | Codeberg | `ci.yaml`, `translations.yaml` | **none** |
| `.gitea/workflows/` | Gitea | `release.yaml`, `renovate.yml` | all of them |
The line is drawn at **secrets, not CI-vs-release** — that is what makes fork PRs safe. Renovate deliberately does *not* move despite opening PRs here; it keeps running where its token already lives and merely talks to Codeberg's API.
CI also gains three fixes: an explicit `SKIP_RE` skip-list that names the build-relevant files in the log, base-ref normalisation, and a fully-qualified `android-actions/setup-android` — Codeberg resolves bare `uses:` refs against `data.forgejo.org`, which does not carry that action.
### 2 · Three release-pipeline safety changes
- `detect` and the Renovate job get an explicit `repository_owner` guard. The directory split only holds while `.forgejo/` is non-empty; empty it and Codeberg would fall back to `.gitea/` and start running these on the contributor-facing runner, without secrets.
- `detect` now reads tags from **Codeberg**, not from the Gitea instance it runs on. Push mirroring is `git push --mirror`, so a tag minted on Gitea is deleted by the next sync until the Codeberg tag push propagates back — asking Gitea inside that window reports "no tag" for an already-shipped release and would cut it twice. It also now fails on any status other than 200/404 rather than reading a transient error as "no tag": a failed job is recoverable, a duplicate release is not.
- **The Codeberg publish step pushes the tag itself** instead of waiting for it to arrive by mirror. That wait was correct while Gitea mirrored *to* Codeberg; under Codeberg-canonical the mirror runs the other way and it would never resolve. Attaching the release to an already-pushed ref (no `target_commitish`) is what avoids the empty-bodied 500s, and the create call retries with backoff because Codeberg 500s on a tag it has only just received. The step stays **fail-loud**, not `continue-on-error` — it reported green through 0.2.1–0.3.2 while never once publishing, and that must not be possible again.
### 3 · Renovate
`renovate.json5` plus a Gitea-side job targeting Codeberg's API. `managerFilePatterns` covers **both** workflow directories, so the pinned Renovate image tag and the action versions in either file keep getting bumped.
Needs two new Gitea secrets: `RENOVATE_TOKEN` (Codeberg bot, repo read/write + PR scope) and `GITHUB_COM_TOKEN` (read-only github.com PAT, for changelog lookups).
### 4 · Weblate
A parity check (`scripts/check_translations.py`) runs on every PR without a path filter, so the required `Translations` status is always reported. Partial translations are expected, so `MissingTranslation` and `MissingQuantity` become informational — `ExtraTranslation` stays fatal. Agendula had no `lint` block at all, so the first locale to land would otherwise have failed the build.
**Settings → App language** now opens a picker carrying a "Help translate" header. That is why it drops floret-kit's `LanguagePickerRow` for a local row: the shared recipe has no `header` slot, and the framing is app-specific rather than a family primitive.
### 5 · Links repointed
In-app Source / License / report-issue URLs, F-Droid metadata, README (now with a Codeberg CI badge), and the docs.
`floret-kit` follows suit — `.gitmodules` points at `codeberg.org/jlmakiola/floret-kit`, so a clone no longer needs to reach the personal Gitea instance to resolve it. The Gitea copy is **kept**: every existing tag records the old submodule URL, so rebuilds of past releases still resolve.
### 6 · Housekeeping
Drops `release-notes.md` — a release-pipeline scratch file that got committed — and gitignores the five others the release job writes into the workspace.
### Not in this PR
The Codeberg → Gitea push mirror, the Weblate component, and the Codeberg bot account (all browser-side). Until the mirror is flipped, merging this does **not** reach the Gitea runner.
Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/agendula/pulls/2
No app-code change from 0.3.1: this exists to re-run the release pipeline
now that the Codeberg publish step is fixed. 0.3.1's APK reached F-Droid but
its Codeberg release 500'd, so anyone installing from Codeberg or Obtainium
is still on the crashing 0.3.0 — cutting 0.3.2 gets them the fix and proves
the workflow fix in the only way that counts, a real release.
Chosen over hand-patching the 0.3.1 release onto Codeberg: same outcome for
users, minus a manual APK upload, and it actually exercises the pipeline.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
R8 kept androidx.work.impl.WorkDatabase_Impl but pruned its no-arg
constructor: nothing calls it directly, Room only reaches it reflectively.
Room then threw InstantiationException, surfacing as "Failed to create an
instance of androidx.work.impl.WorkDatabase". WorkManager builds that
database from a startup ContentProvider, so 0.3.0 died before any of our
code ran — every install, every launch.
We don't depend on WorkManager directly; it arrives via Glance. AGP 9's
stricter R8 is what tipped this over, which is why 0.3.0 was the first
release to hit it.
Keep the Room no-arg constructor, and the ListenableWorker constructor
alongside it — same pruning hazard on the path WorkManager uses to
instantiate workers by name, which would have bitten once a Glance widget
update actually ran.
Reproduced the reporter's stack trace frame-for-frame on a releaseTest
build, then confirmed it launches clean afterwards. Fixes #1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships the M5 reminders onboarding + Settings screen alongside the reworked
overview (Today progress ring, live Upcoming preview, unfurling search) and
the real launcher mark.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-cut after 0.2.1's Codeberg publish failed (500 on pre-synced tag,
fixed in the previous commit). Validates the fix end to end and ships
the Codeberg direct-download channel (signed APK + SHA-256).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Publish releases to the Codeberg mirror (signed APK + SHA-256 checksum)
as a direct-download channel. Bumps versionName to 0.2.1; the pipeline
mints the v0.2.1 tag on merge to main.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Port Calendula's current CI/release pipeline:
- ci.yaml: pull_request-triggered, change-scope classification
(docs/metadata-only PRs skip the Android build but still report a
green CI), and a reproducible-release invariant guard.
- release.yaml: the committed versionName is the source of truth — a
bump reaching main triggers the release, which builds, signs,
publishes to the F-Droid repo, then mints the vX.Y.Z tag + Gitea
release and mirrors it to Codeberg with the signed APK + SHA-256
checksum. workflow_dispatch runs the re-sign-only recovery path.
- Gitea releases are flagged as pre-releases while MAJOR is 0.
- build.gradle.kts: reproducible-release invariants (vcsInfo,
dependenciesInfo) + a releaseTest variant for the on-device gate.
- fastlane/ becomes the single source of truth for store metadata;
the localized F-Droid layout is generated from it at release time.
- Port scripts/, .gitea/ISSUE_TEMPLATE/, and rewrite docs/RELEASING.md
for the versionName-in-main model; fix stale references elsewhere.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Floret is promoted to the family / design-language (shared-kit) name; the
tasks app itself becomes Agendula (de.jeanlucmakiola.agendula) — agenda
('things to be done') + Calendula's -ula, a twin of the Calendula name.
Renames the package, namespace, applicationId, rootProject.name, app_name,
FloretApp/FloretNavHost/FloretTransitions classes, theme, F-Droid metadata
dir, CI artifact name, and docs. The botanical word 'florets' is preserved in
the name-origin prose, which is rewritten to Agendula's etymology. Clean
build + unit tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reminders onboarding & polish, plus the Settings screen (landed early).
- One-time reminder onboarding gate after the provider grant
(ReminderOnboardingScreen + OnboardingScaffold), requesting
POST_NOTIFICATIONS on API 33+; choice recorded in prefs.
- Settings screen, structured after Calendula as a category hub with
sliding sub-screens (CollapsingScaffold + grouped rows + full-screen
OptionPicker): About card, Appearance (theme, dynamic colour), Task
form (default edit-form fields, default list, add-a-subtask-row
opt-out), Reminders, Language, and Report a problem. Reached via an
expressive shaped action button (MaterialShapes.Cookie4Sided) on the
lists overview. Back from a sub-screen returns to the hub.
- Reminders: master enable toggle (gates the whole engine; re-requests
the notification permission), a default lead time with a Custom
amount/unit editor, an Android-12 exact-alarm status row, and
per-list overrides of the default (Inherit / None / custom lead),
honoured by ReminderScheduler per task.
- Per-app language (AppLanguage + locales_config.xml + appcompat
locales service); add-a-subtask-row opt-out wired into the task list.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote [Unreleased] → [0.2.0] in the changelog (M2 UI + M3/M4 + fixes) and
bump the dev-default version to 0.2.0 / 200. The pushed tag drives the released
version per docs/RELEASING.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M3 detail/edit polish:
- "Progress" slider on the edit form writes Tasks.PERCENT_COMPLETE (clamped
0-100, 5% detents); status stays owned by the complete toggle.
- Conflict-safe saves: updateTask re-checks the provider's last_modified against
the value captured when the form loaded and throws TaskConflictException; the
editor offers overwrite-or-cancel instead of clobbering an external change.
M4 subtasks (UI):
- Reparent: a "Parent task" picker files a task under any top-level task in its
list (or "None" to promote it); candidates stay top-level to keep nesting one
level deep. Switching list clears the now-invalid parent.
- Tapping a subtask opens its own detail (a new TaskDetail entry, own VM).
Tests: percent clamping, parent-id write, populatedFields reveal logic.
Docs: ROADMAP M2/M3/M4 reconciled to the codebase; CHANGELOG [Unreleased].
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Non-visual stack (backoffice) complete and verified against the real
provider semantics (tasks.org's bundled dmfs TaskProvider, authority
org.tasks.opentasks, org.tasks.permission.* dangerous):
- TaskContract subset + ProviderResolver (runtime authority/permission)
- AndroidTasksDataSource (Instances query, ContentObserver) + TasksRepository
with live Flows; domain models, smart-list filtering, sorting, form validation
- Self-scheduled due-reminder engine (AlarmManager, boot/provider-change)
- Render-only ViewModels + UiState for every screen
- 24 JVM unit tests; assembleDebug + lintDebug + testDebugUnitTest green
- RootScreen is a functional scaffold over real data, to be replaced with the
Material 3 Expressive screens one by one
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sibling to Calendula. Pure front-end posture; TaskContract data layer,
task screens and reminder engine to follow (see docs/PLAN.md).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>