143 lines
8.0 KiB
Markdown
143 lines
8.0 KiB
Markdown
# Development log — Period
|
|
|
|
```
|
|
Status: Current
|
|
Owner: _null
|
|
Last reviewed: 2026-08-18
|
|
Governs: the dated record of what happened
|
|
Review trigger: Nothing. This file is appended to, never revised.
|
|
```
|
|
|
|
## How to use this
|
|
|
|
Newest first. **One entry per work session**, written before you stop — that is
|
|
step 6 of `docs/WORK_CYCLE.md`, and the two lines it insists on are `Next
|
|
action` and `Blockers`.
|
|
|
|
Those two are not decoration. The next session starts by reading the top of this
|
|
file, and a session that ended without saying what came next hands the one after
|
|
it a re-derivation instead of a starting point — which is where drift enters.
|
|
Neither line competes with anything: the live next action is the field on the
|
|
project at privacyllc.dev and the live blockers are issues in the tracker, while
|
|
these say what both were **at this date**. A record of then never disagrees with
|
|
a record of now.
|
|
|
|
**Append-only by convention.** Correcting an old entry rewrites the record of
|
|
what was known at the time, which is the one thing this file is for. If an entry
|
|
turns out to be wrong, add a later entry saying so; do not edit the first.
|
|
|
|
Note the Review trigger above says "nothing", deliberately. A dated log cannot
|
|
rot the way a description of current state can — the entries were true when
|
|
written and stay true. It is exempt from review for the same reason a receipt is.
|
|
|
|
## Entries
|
|
|
|
### 2026-08-18 — Batch 01 foundation: seven of nine issues, and three guards that were wrong
|
|
|
|
Room, DataStore, the repository layer, period CRUD end to end on a device, and
|
|
the module boundary guard. #3 to #7 closed; #8 (branding) and #9 (webhook) are
|
|
the two that need a person rather than an agent.
|
|
|
|
**What was built.** `core/database` with the four entities from §10, DAOs
|
|
returning `Flow`, and the schema exported and committed. `core/datastore` for
|
|
settings, deliberately separate from the cycle database so Delete My Data cannot
|
|
reset a privacy choice the user made. `core/data` as the seam: domain types out,
|
|
cycles derived rather than stored, the forecast a function of the data instead
|
|
of a field somebody has to refresh. Hilt wiring and a working Today surface that
|
|
says "Batch 01 · working surface" so nobody mistakes it for the designed screen.
|
|
|
|
**Three guards were written, and all three were wrong at first.** This is the
|
|
day's real lesson and it is worth carrying forward:
|
|
|
|
1. `SchemaTest` looked like a Room schema-drift guard. Room regenerates the
|
|
schema export during compilation, so both sides of every comparison agreed by
|
|
construction — adding a column without bumping the version left it green.
|
|
`scripts/schema-guard.sh` asks git instead, which Room cannot overwrite.
|
|
2. `checkModuleBoundaries` reported "7 modules checked, no violations" while
|
|
checking nothing: the root project is configured before its subprojects, so
|
|
every configuration read as empty. Caught by `prove-guard.sh` on its first
|
|
run. Collection moved to `afterEvaluate`, and the task now throws rather than
|
|
passing when it examined nothing.
|
|
3. The repository let `SQLiteConstraintException` escape into
|
|
`viewModelScope.launch`, so **tapping the primary button twice killed the
|
|
app** — found by hand on an emulator, with 70 unit tests green.
|
|
|
|
Each was caught by actually trying to break it. None would have been caught by
|
|
reading the code, and two of them would have been trusted for months.
|
|
|
|
**Two more bugs came from wiring the guard into `./gradlew check`**, which ran
|
|
Android lint for the first time: `LocalDate.ofInstant` and `LocalDate.EPOCH` are
|
|
API 34 and `minSdk` is 26. Both sit on the recalculation path — a crash on every
|
|
device below Android 14, invisible to the unit tests and to an API 36 emulator.
|
|
|
|
**QA.** Round 1 recorded as partial in `docs/qa/`. Passes A and B green, C and D
|
|
and H partial, the rest not run and each saying why.
|
|
|
|
- **Closed:** #3, #4, #5, #6, #7
|
|
- **Next action:** Batch 02 — replace `BaselinePredictionEngine` with the engine
|
|
§12 specifies: recency weighting, a robust centre, variability-driven windows,
|
|
trend detection, and "not yet" as a real conditioning step rather than a floor
|
|
on the window. The §51 acceptance tests already exist and must keep passing
|
|
against the new engine, which is what makes the replacement demonstrably
|
|
better rather than merely different. Before that, one cheap thing worth doing:
|
|
run the app once on a device at `minSdk` 26, because nothing here ever has.
|
|
- **Blockers:** None for code. #8 needs the three branding marks drawn — an
|
|
agent must not fake them, so the project card shows an initials tile until
|
|
somebody does. #9 needs the Command Center's webhook URL and secret, which are
|
|
not readable from this machine; until it is registered an opened `P0` raises
|
|
no alert at all.
|
|
|
|
### 2026-08-18 — Template adopted; Kotlin/Compose skeleton builds
|
|
|
|
Period went from a bare directory holding one specification file to a git
|
|
repository with the standard documentation tree, a tracker, and a project that
|
|
compiles. Adoption followed `Projects/Template/START-HERE-New-Project.md`.
|
|
|
|
**Documents.** `scaffold.sh` created 19 paths, 0 skipped. The specification moved
|
|
from `Docs/period_tracker_product_plan.md` to `docs/planning/PRODUCT_PLAN.md`
|
|
unchanged in substance, with a status header added; the capitalised `Docs/` is
|
|
gone, since every script and the Command Center expect the lowercase tree. Every
|
|
scaffolded document was filled in for Period rather than left with placeholders.
|
|
docs/OPERATIONS.md was deleted — an offline app is not a deployed service.
|
|
`docs/DOC_TRUST_MAP.md` was written last and describes what is actually here,
|
|
including a section naming what this project deliberately does **not** have.
|
|
|
|
**Code.** Four Gradle modules: `app`, `core/designsystem`, and `domain/cycle`
|
|
and `domain/prediction` as `kotlin("jvm")` so the engine is testable without an
|
|
emulator. 17 tests pass, 12 of them the acceptance cases from `PRODUCT_PLAN.md`
|
|
§51. `BaselinePredictionEngine` is a robust-median prototype and is explicitly
|
|
not the product — it exists so Batch 02's replacement can be shown to be better
|
|
rather than merely different.
|
|
|
|
**Three things that cost time and are worth knowing next session:**
|
|
|
|
- **AGP 9 ships Kotlin built in.** Applying `org.jetbrains.kotlin.android` is now
|
|
a hard error, not a redundancy. The Compose compiler plugin is still separate.
|
|
- **Current AndroidX requires `compileSdk 37`.** Only up to 36 was installed;
|
|
`platforms;android-37.0` and `build-tools;37.0.0` were installed into
|
|
`~/Android/Sdk`. `targetSdk` stays at 36 — Play's floor from 2026-08-31 — and
|
|
the two being different is deliberate, not an oversight to tidy up.
|
|
- **Versions were verified, not inherited.** Kotlin 2.4.10, AGP 9.3.1, Gradle
|
|
9.7.0, Compose BOM 2026.08.00, Room 2.8.4, Hilt 2.60.1 — each checked against
|
|
its official source today, which `PRODUCT_PLAN.md` asks for rather than
|
|
trusting its own numbers.
|
|
|
|
**Tracker.** Eight milestones opened, `Batch 01 — Foundation` through
|
|
`Batch 08 — Polish`, and nine issues filed under Batch 01 only. Seven milestones
|
|
are deliberately empty: the roadmap is genuinely known and worth being visible,
|
|
but the work items under it are not, and inventing them would make every tracker
|
|
percentage permanently wrong. `forgejo-issue.py check` warns about this, and the
|
|
warning is correct about the mechanism and expected here.
|
|
|
|
- **Closed:** #1, #2
|
|
- **Next action:** Start issue #3 — core/database with Room entities for
|
|
`PeriodRecord`, `SpottingRecord`, `PredictionRecord` and `NotYetObservation`,
|
|
DAOs returning `Flow`, schema export committed, and a version-1 migration test
|
|
that proves the harness works before there is a migration that matters. Its row
|
|
goes in `docs/architecture/README.md`'s migration table in the same commit.
|
|
- **Blockers:** None for the code. Two things need a person rather than an agent:
|
|
the three branding marks (#8), which cannot be drawn here and must not be
|
|
faked, and the Command Center webhook (#9), whose URL and secret are not in any
|
|
credential file readable from this machine. Without the webhook an opened `P0`
|
|
raises no alert at all — it waits for the next reconcile.
|