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.
This commit is contained in:
@@ -332,6 +332,17 @@ gain.
|
||||
|
||||
## Migrating existing users
|
||||
|
||||
> ⚠️ **Corrected, 2026-09-21.** The premise below is wrong, and it was wrong when
|
||||
> it was written: **no release ever bundled the provider.** It was added and
|
||||
> deleted inside this one unreleased cycle, so `databases/tasks.db` exists on no
|
||||
> published install and `OneShotImport` finds nothing to do for every real user.
|
||||
> Anyone on 0.3.x or 0.4.0 keeps their tasks in OpenTasks or tasks.org, which
|
||||
> `ProviderResolver.autoMode()` correctly keeps them on. The path onto the new
|
||||
> store for those users is `ExternalImport` — see
|
||||
> [Copying from an external provider](#copying-from-an-external-provider) below.
|
||||
> Everything in this section still applies to a device that ran a dev build of
|
||||
> this branch, which is why the import, its fixture and its tests stay.
|
||||
|
||||
Anyone on v0.3.x has their tasks inside the bundled provider's SQLite file at
|
||||
`/data/data/de.jeanlucmakiola.agendula/databases/tasks.db` (dmfs schema
|
||||
version 23). Removing the Gradle module does **not** remove that file — an app
|
||||
@@ -384,6 +395,38 @@ still exist:
|
||||
3. Only after a release with no import defects reported does a subsequent
|
||||
version delete `tasks.db.imported`.
|
||||
|
||||
A failure is no longer invisible, either. `runIfNeeded` used to hand back an
|
||||
`ImportResult.Failed` that `StartupGate` discarded — an upgrading user got an
|
||||
empty app, no message, and their tasks in a file only a developer could name. The
|
||||
outcome is now recorded in DataStore and logged, and Settings → Storage offers the
|
||||
retry, which is what makes `reimportFromArchive()` reachable at all.
|
||||
|
||||
### Copying from an external provider
|
||||
|
||||
The migration that actually matters for 1.0.0, since the one above serves nobody.
|
||||
`ExternalImport` (`data/tasks/transfer/`) reads the external provider through the
|
||||
existing `exportTasks` seam and writes lists, tasks and alarms into Room in one
|
||||
transaction with verified counts — the same shape as `OneShotImport`, for the
|
||||
same reason. Task `uid`s are preserved, so the rows can be attached to a CalDAV
|
||||
collection once sync lands rather than duplicating server-side.
|
||||
|
||||
- **User-initiated, once.** Settings → Storage → *Copy tasks from …*, behind a
|
||||
confirm that names the real task count. Offered only while a provider is
|
||||
installed and permitted and no copy has succeeded; a second run would duplicate
|
||||
everything, because what it writes is indistinguishable from hand-typed tasks
|
||||
the moment it finishes.
|
||||
- **A copy, not a sync.** The source is untouched, whatever syncs it keeps
|
||||
syncing it, and the two sets drift from that moment. Switching stores now asks
|
||||
first for the same reason: neither store hands its rows to the other.
|
||||
- **One-directional.** Writing a *list* into a third-party provider means
|
||||
impersonating its sync adapter, and the external store is already the one that
|
||||
can sync.
|
||||
- **What does not come across**, because the read seam is shaped for iCalendar
|
||||
output: per-occurrence `RECURRENCE-ID` overrides (a series arrives as master +
|
||||
rule), `EXDATE`, `CLASS`, `DURATION`, the per-task timezone, and a task's exact
|
||||
`PRIORITY` digit (`Priority` buckets 1–4 as HIGH). Nothing the app itself
|
||||
displays is lost.
|
||||
|
||||
This is the reason phase 5 (deleting `:provider`) ships *after* phase 4 rather
|
||||
than with it — and the reason the deletion is its own release.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user