Commit Graph
7 Commits
Author SHA1 Message Date
makiolaj 3150781376 docs: say what actually shipped, and what 1.0.0 actually is
The branch's documents describe a world where the vendored provider reached
users. It never did, and several claims follow from that mistake.

`ROADMAP.md`:
- Phase 5's "**Breaking:** the authority and both custom permissions no longer
  exist — anyone who pointed DAVx5 at that authority loses it, and the release
  notes have to say so" is wrong in the way that *removes* work: they were
  added and deleted inside this unreleased cycle, so nobody could have pointed
  anything at them. The release notes must not warn about losing something that
  never shipped. The per-locale release-notes item went with it.
- "Run the instrumented suite on a device … none has ever executed" was stale:
  52 tests, 0 failures, Pixel 10 / API 36, 13 Aug. What is genuinely open is a
  re-run against the tip, since the 4 Sep commits reworked the store and added
  instrumented cases that have never run. Both now say so, with the ARM64 aapt
  exit-code trap noted where someone will hit it.
- The device-verification item described upgrading from a v0.3.2 APK with
  seeded data, which cannot be the real path. Replaced with the four cases that
  matter, including the one that only exists on a device that side-loaded a dev
  build of this branch.
- M6's Glance item claimed "deps present in build.gradle.kts" — not any more.
  Translations and the language picker shipped in 0.4.0 and are marked done.

`OWN-STORE.md` gets a correction banner over "Migrating existing users" saying
the premise is wrong, and a section for the copy that replaces it.
`STORAGE-AND-SYNC.md`'s banner said the vendored-provider decision was "made,
shipped, and then costed properly" — built, not shipped.

`PRIVACY.md` had the opposite problem: it describes CalDAV sync, Nextcloud
Login Flow v2, RFC 6764 discovery and a Keystore-held password, none of which
exist in 1.0.0 — the app holds no `INTERNET` permission at all. The permissions
section listed six it does not declare. Since it is a legal document users are
sent to from Settings → About, section 4 is now marked as describing a planned
feature, section 9 lists exactly what the manifest declares (and says what is
*not* there), and the backup and crash-report sections no longer assume network
access or sync bookkeeping. Kept forward-looking rather than cut, so it does
not have to change underneath anyone when sync lands. **Worth a read before
merging** — it is the one change here with legal weight.

`fastlane/.../full_description.txt` still opened with "It works directly on an
existing tasks provider (OpenTasks / tasks.org) … no own account, no own sync"
as the app's premise. That is the F-Droid listing for a release whose headline
is that it needs nothing installed. Rewritten, with the feature list and the
no-internet-permission point that is now literally true.

`README.md` and `ExportWriter`'s "ships in eleven locales" (it is three) follow.
2026-09-21 13:38:23 +02:00
makiolaj 1ed192f150 feat(store)!: delete the vendored dmfs provider
Phase 5 of docs/OWN-STORE.md. The :provider module goes — 84 Java files,
14,555 lines, its <provider>, its two custom permissions, its 13
translated strings and its three dmfs runtime dependencies. Room has been
the default since the previous commit and every v0.3.x install has been
imported, so nothing reads it any more.

StorageMode.LOCAL is gone with it; OWN and EXTERNAL are what remain.
ProviderResolver narrows to what it was always really for — discovering
external providers — and answers null in OWN mode, where there is no
authority to resolve. Callers that need to tell that apart from "External
with nothing installed" ask mode(). ProviderStatus is unconditionally
READY in OWN mode: the permission gate only ever applied to External, and
that is now visibly true rather than a special case inside it.

A stored LOCAL is read as OWN rather than as an unparseable value. Left
to fall through to autoMode, someone who had explicitly chosen local
storage while also having OpenTasks granted would have been sent to
OpenTasks instead.

ProviderChangeReceiver's manifest filter drops our own authority — safe
now, because nothing of ours broadcasts ACTION_PROVIDER_CHANGED. In OWN
mode Room's InvalidationTracker covers foreground changes and nothing
outside the app can change our data. When SYNC.md phase 3 lands, the sync
worker must call ReminderScheduler.sync() itself; that is the replacement
for the broadcast and it belongs in the sync work.

lib-recur stays as a direct dependency and is still Apache-2.0 dmfs, so
the attribution is still owed — now as a normal third-party dependency.
provider/PROVENANCE.md is replaced by a postscript in STORAGE-DECISION.md
recording that the fork existed, why, and the one detail that still binds
us: tasks.org is DB 22 and has no is_recurring, so TaskMapper must keep
deriving recurrence from rrule/rdate.

BREAKING: the de.jeanlucmakiola.agendula.tasks authority and both custom
permissions are gone. Anyone who pointed DAVx5 or another app at that
authority loses it; External mode is the answer. Needs calling out in the
release notes.

Verified: the APK declares no ContentProvider, no custom permission and
no agendula.tasks authority, and carries no dmfs provider classes.
2026-08-13 16:33:19 +02:00
makiolajandClaude Opus 5 98ed339346 docs: bring the docs in line with what shipped
STORAGE-AND-SYNC.md asked for a follow-up pass on ARCHITECTURE.md §7 and the
ProviderResolver KDoc, which still defined Posture B as "bundle OpenTasks and
find org.dmfs.tasks first" — the plan that was withdrawn as a dead end. That pass,
plus the status the doc left open.

ARCHITECTURE.md now describes the app as built: two modules, the storage-mode
table with the permission each needs, the autoMode rule and why it keys on
holding an external provider's permission, the two-not-three mode vocabulary, and
a manifest section that says what :provider contributes and what is deliberately
absent (GET_ACCOUNTS, INTERNET). §7 records squatting the dmfs authority as a
dead end rather than a road not yet taken, so it doesn't get re-proposed.

ROADMAP.md turns "Posture B, later" into what actually landed and lists what
didn't: the frontend surfaces, the DAVx5 issue, the sync adapter, and device
verification. Two open decisions resolved and struck through — the authority
choice, and recurrence-aware editing, which fix/provider-interaction-review made
stale.

STORAGE-AND-SYNC.md gets per-step status. Open question 3 ("does it work with no
account?") is answered, with the caveat that the test proving it is Robolectric
and skips on ARM64 — answered by construction, not yet on a device.

PLAN.md gets a banner. It's the original design document and still holds the
reasoning behind the layering, but two of its premises are overturned and it
should not be read as current.

README.md was telling users they need a tasks provider installed. They don't, and
that's the headline feature: a table of where tasks can live, that our provider
coexists with OpenTasks rather than replacing it, and that everything exports as
standard .ics.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 21:32:17 +02:00
Jean-Luc Makiolaandmakiolaj 217d5d7afd Move the canonical forge to Codeberg, and add Renovate + Weblate (#2)
Release — F-Droid repo + Gitea/Codeberg release / release (push) Has been skipped
Release — F-Droid repo + Gitea/Codeberg release / detect (push) Successful in 7s
Renovate / renovate (push) Failing after 43s
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
2026-08-01 16:34:20 +02:00
makiolajandClaude Opus 4.8 76a0139fda Rename app Floret → Agendula
CI / ci (push) Successful in 8m33s
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>
2026-06-27 23:10:24 +02:00
makiolajandClaude Opus 4.8 b784a77329 docs: add architecture, roadmap, releasing, contributing + docs index
CI / ci (push) Successful in 5m34s
Add a grounded doc set under docs/ plus a root CONTRIBUTING.md:
- docs/ARCHITECTURE.md: current code shape (layers, data seam, provider
  resolution, reminder engine, DI, build/tooling, manifest)
- docs/ROADMAP.md: status view (M0/M1 done, M2 in progress, open decisions)
- docs/RELEASING.md: tag-driven release flow, CI jobs, F-Droid repo, secrets
  (was referenced by build.gradle.kts and CHANGELOG but missing)
- docs/README.md: docs index and how the docs relate
- CONTRIBUTING.md: build/test/lint, layer rules, style, PR conventions

Also refresh the stale "M0 — skeleton" status note in README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 08:49:05 +02:00
Jean-Luc MakiolaandClaude Opus 4.8 01d1f558b8 M0: Floret skeleton — Material 3 Expressive scaffold over OpenTasks (planned)
CI / ci (push) Successful in 6m39s
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>
2026-06-17 19:40:53 +02:00