chore: adopt the project template and add the Kotlin/Compose skeleton
Period was a bare directory holding one 2,527-line specification, with no git
repository, no tracker and no documentation convention. This is the adoption
from Projects/Template/START-HERE-New-Project.md, plus a project that compiles
so the hooks and future guards have something real to run against.
Documents. scaffold.sh created 19 paths, 0 skipped. The specification moved to
docs/planning/PRODUCT_PLAN.md unchanged in substance, with a status header; the
capitalised Docs/ is gone. Every scaffolded document was filled in for Period.
docs/OPERATIONS.md deleted — an offline app is not a deployed service.
DOC_TRUST_MAP.md written last, describing what is actually here, including what
this project deliberately does not have.
Code. Four Gradle modules. domain/cycle and domain/prediction are kotlin("jvm")
and cannot see the Android SDK, 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 explicitly not the
product; it exists so Batch 02's replacement can be shown to be better rather
than merely different.
Versions verified against their official sources today rather than inherited
from the specification's own numbers, which that document asks for: 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. AGP 9 ships Kotlin built in, so org.jetbrains.kotlin.android is no
longer applied. compileSdk is 37 because current AndroidX requires it; targetSdk
stays 36, Play's floor from 2026-08-31, and the difference is deliberate.
Six scripts taken into scripts/; the rest declined and named in docs/TOOLS.md.
Three hooks in .githooks/, with pre-commit adapted to Gradle.
closes #1
closes #2
2026-08-18 02:16:47 -05:00
|
|
|
# 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 03:01:33 -05:00
|
|
|
### 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.
|
|
|
|
|
|
chore: adopt the project template and add the Kotlin/Compose skeleton
Period was a bare directory holding one 2,527-line specification, with no git
repository, no tracker and no documentation convention. This is the adoption
from Projects/Template/START-HERE-New-Project.md, plus a project that compiles
so the hooks and future guards have something real to run against.
Documents. scaffold.sh created 19 paths, 0 skipped. The specification moved to
docs/planning/PRODUCT_PLAN.md unchanged in substance, with a status header; the
capitalised Docs/ is gone. Every scaffolded document was filled in for Period.
docs/OPERATIONS.md deleted — an offline app is not a deployed service.
DOC_TRUST_MAP.md written last, describing what is actually here, including what
this project deliberately does not have.
Code. Four Gradle modules. domain/cycle and domain/prediction are kotlin("jvm")
and cannot see the Android SDK, 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 explicitly not the
product; it exists so Batch 02's replacement can be shown to be better rather
than merely different.
Versions verified against their official sources today rather than inherited
from the specification's own numbers, which that document asks for: 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. AGP 9 ships Kotlin built in, so org.jetbrains.kotlin.android is no
longer applied. compileSdk is 37 because current AndroidX requires it; targetSdk
stays 36, Play's floor from 2026-08-31, and the difference is deliberate.
Six scripts taken into scripts/; the rest declined and named in docs/TOOLS.md.
Three hooks in .githooks/, with pre-commit adapted to Gradle.
closes #1
closes #2
2026-08-18 02:16:47 -05:00
|
|
|
### 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.
|
2026-08-18 02:18:25 -05:00
|
|
|
docs/OPERATIONS.md was deleted — an offline app is not a deployed service.
|
chore: adopt the project template and add the Kotlin/Compose skeleton
Period was a bare directory holding one 2,527-line specification, with no git
repository, no tracker and no documentation convention. This is the adoption
from Projects/Template/START-HERE-New-Project.md, plus a project that compiles
so the hooks and future guards have something real to run against.
Documents. scaffold.sh created 19 paths, 0 skipped. The specification moved to
docs/planning/PRODUCT_PLAN.md unchanged in substance, with a status header; the
capitalised Docs/ is gone. Every scaffolded document was filled in for Period.
docs/OPERATIONS.md deleted — an offline app is not a deployed service.
DOC_TRUST_MAP.md written last, describing what is actually here, including what
this project deliberately does not have.
Code. Four Gradle modules. domain/cycle and domain/prediction are kotlin("jvm")
and cannot see the Android SDK, 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 explicitly not the
product; it exists so Batch 02's replacement can be shown to be better rather
than merely different.
Versions verified against their official sources today rather than inherited
from the specification's own numbers, which that document asks for: 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. AGP 9 ships Kotlin built in, so org.jetbrains.kotlin.android is no
longer applied. compileSdk is 37 because current AndroidX requires it; targetSdk
stays 36, Play's floor from 2026-08-31, and the difference is deliberate.
Six scripts taken into scripts/; the rest declined and named in docs/TOOLS.md.
Three hooks in .githooks/, with pre-commit adapted to Gradle.
closes #1
closes #2
2026-08-18 02:16:47 -05:00
|
|
|
`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
|
2026-08-18 02:18:25 -05:00
|
|
|
- **Next action:** Start issue #3 — core/database with Room entities for
|
chore: adopt the project template and add the Kotlin/Compose skeleton
Period was a bare directory holding one 2,527-line specification, with no git
repository, no tracker and no documentation convention. This is the adoption
from Projects/Template/START-HERE-New-Project.md, plus a project that compiles
so the hooks and future guards have something real to run against.
Documents. scaffold.sh created 19 paths, 0 skipped. The specification moved to
docs/planning/PRODUCT_PLAN.md unchanged in substance, with a status header; the
capitalised Docs/ is gone. Every scaffolded document was filled in for Period.
docs/OPERATIONS.md deleted — an offline app is not a deployed service.
DOC_TRUST_MAP.md written last, describing what is actually here, including what
this project deliberately does not have.
Code. Four Gradle modules. domain/cycle and domain/prediction are kotlin("jvm")
and cannot see the Android SDK, 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 explicitly not the
product; it exists so Batch 02's replacement can be shown to be better rather
than merely different.
Versions verified against their official sources today rather than inherited
from the specification's own numbers, which that document asks for: 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. AGP 9 ships Kotlin built in, so org.jetbrains.kotlin.android is no
longer applied. compileSdk is 37 because current AndroidX requires it; targetSdk
stays 36, Play's floor from 2026-08-31, and the difference is deliberate.
Six scripts taken into scripts/; the rest declined and named in docs/TOOLS.md.
Three hooks in .githooks/, with pre-commit adapted to Gradle.
closes #1
closes #2
2026-08-18 02:16:47 -05:00
|
|
|
`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.
|