Commit Graph
3 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
makiolajandClaude Opus 5 8c3cbcf928 docs: fix seven defects in the own-store plan
Reviewed the plan against the code it describes. Two design holes and
five errors.

Instance identity was the real one. The plan deleted the materialised
instances table without saying what replaces the instance row id, which
TasksRepositoryImpl.updateTask passes to updateInstance and which
ListsScreen keys a lazy list by. Two occurrences of one series can
appear in the same list, so taskId alone is not unique and a hash of
(taskId, start) can collide - as a Compose key that is a visible bug.
Task.id is dropped for occurrenceStart, updateInstance takes
(taskId, occurrenceStart, form), and External mode maps back to a real
instance row with one query. This is the single seam change, and the
plan's "TasksDataSource unchanged" claim was wrong.

Local lists had no account name. TaskList.accountName is non-null,
ListsViewModel groups by it and ListsScreen renders it as a section
header, so a null account_id must still report "Local".

The unique index was wrong: overrides share their master's UID, so
unique (list_id, uid) would reject the rows the recurrence design
depends on. It needs recurrence_id in the key.

Phase 0 broke background reminders. It dropped our authority from
ProviderChangeReceiver's manifest filter while the provider was still
the store, and renamed StorageMode.LOCAL to OWN four phases before OWN
meant Room. Both moved to phase 5.

Parity against the provider was overclaimed: the provider materialises
one occurrence, so multi-occurrence expansion has nothing to compare
against and is tested against RFC 5545 directly.

The phases sum to 6.5-7 weeks, not the 6-6.5 stated, and the difference
from STORAGE-DECISION.md's 4.5-6 is now explained rather than left as a
contradiction.

Gaps closed: WAL vs Auto Backup (checkpoint on ON_STOP, sidecars in the
backup rules, tested in phase 6), cascade rules for master_id and
parent_id, Instant type converters, a rollback path that re-runs the
import from tasks.db.imported, the release note for dropping the
authority and its permissions, and ICalendarWriter.uidFor's synthesis
branch becoming External-only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 15:30:37 +02:00
makiolajandClaude Opus 5 13cb27b2ab docs: decide to build our own store and delete the vendored provider
The vendored dmfs provider was kept on the grounds that it hands us the
sync bookkeeping for free. The phase-1 sync audit measured that
bookkeeping and found most of it broken, absent, or unusable: _DIRTY not
set on delete, no home for a per-collection sync token, read-only
collections inexpressible, ACCOUNT_TYPE write-once so enabling sync is a
full migration, and cleanUpLists able to delete a user's lists after a
backup restore. Sixteen findings are provider-imposed rather than
platform- or protocol-imposed.

Costing the alternative showed the swap is far smaller than assumed.
TasksDataSource is already a 14-method, domain-shaped interface;
exactly one file above the data layer references TasksContract. The
work is a second implementation behind an interface built for it, not a
rewrite. Against ~5 weeks to build, owning the store removes 2.5-4
weeks from the sync plan, and 8,200 of the vendored 14,555 lines are
things we would never write - 23 migrations from a 2013 schema, 798
lines of full-text search the app has zero call sites for, and 1,581
lines of a type-safe layer over ContentValues that Room deletes.

External mode (OpenTasks, tasks.org) is unaffected and keeps every
file that describes somebody else's schema.

STORAGE-DECISION.md is the reasoning; OWN-STORE.md is the architecture
and the six-phase plan. :provider stays in-tree until phase 5 so
recurrence parity can be tested against it before it goes.

Also corrected here: the provider's JVM test count (51 -> 56, measured
from the test-results XML) and a fourth site of the debunked "switching
sync on is never a migration" claim, in StorageMode.kt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 14:46:07 +02:00