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
|
|
|
# The work cycle — what happens at the end of a piece of work
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Status: Current
|
|
|
|
|
Owner: _null
|
|
|
|
|
Last reviewed: 2026-08-18
|
|
|
|
|
Governs: what must be true before a piece of work counts as finished
|
|
|
|
|
Review trigger: Any change to what the Command Center reads, or to which of
|
|
|
|
|
those channels a person rather than an agent has to write
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> **This is a procedure, not a status board.** Nothing here records what is open,
|
|
|
|
|
> what is next, or what is blocked — those live in the tracker and on
|
|
|
|
|
> privacyllc.dev, and a copy of them in this file would be the second disagreeing
|
|
|
|
|
> record that `DOC_TRUST_MAP.md` exists to prevent.
|
|
|
|
|
|
|
|
|
|
## Why this file exists
|
|
|
|
|
|
|
|
|
|
A piece of work ends in more than one place. The code is committed; the issue
|
|
|
|
|
that asked for it is still open; the document the change contradicts still says
|
|
|
|
|
the old thing; and the project screen at
|
|
|
|
|
[privacyllc.dev](https://privacyllc.dev) still shows last week's next action to
|
|
|
|
|
whoever opens it.
|
|
|
|
|
|
|
|
|
|
None of those catch up on their own. Two of them cannot be caught up later by
|
|
|
|
|
anybody but the person who did the work, because by then nobody knows what the
|
|
|
|
|
next action was meant to be.
|
|
|
|
|
|
|
|
|
|
## The cycle
|
|
|
|
|
|
|
|
|
|
Run all of it, in this order, every time. It is short on purpose.
|
|
|
|
|
|
|
|
|
|
1. **Close what you finished.** `closes #N` in the commit that does the work, so
|
|
|
|
|
the record comes from the thing that happened rather than a date typed
|
|
|
|
|
afterwards. If no single commit finished it, close it by hand with the
|
|
|
|
|
evidence — a path, a symbol, a test name, or the command that proves it.
|
|
|
|
|
*"Done" is not a close.*
|
|
|
|
|
2. **File what you found.** A defect noticed on the way past is an issue with a
|
|
|
|
|
severity label and the build SHA it was seen at, not a memory. Filing it costs
|
|
|
|
|
a minute; the alternative is finding it again from scratch, or shipping it.
|
|
|
|
|
3. **Close the milestone if the batch landed.** A milestone with every issue
|
|
|
|
|
closed and itself still open reads as a batch still in progress — see
|
|
|
|
|
[Open and closed are not bookkeeping](#open-and-closed-are-not-bookkeeping).
|
|
|
|
|
4. **Update the documents this change triggered.** Read the `Review trigger`
|
|
|
|
|
lines: a new module, a changed data shape, a new migration, a new boundary
|
|
|
|
|
something crosses. Those edits go in **the same commit as the code**, for the
|
|
|
|
|
reason in [Docs travel with the push](#docs-travel-with-the-push).
|
|
|
|
|
5. **Push.** Nothing above is visible off this machine until you do, and step 7
|
|
|
|
|
reports on what was pushed.
|
|
|
|
|
6. **Write the log entry** in `docs/history/DEVELOPMENT_LOG.md`: what changed,
|
|
|
|
|
what it proved, **Next action**, and **Blockers**. Dated, append-only, newest
|
|
|
|
|
first.
|
|
|
|
|
7. **Tell the Command Center**, which is three calls: reconcile, so it re-reads
|
|
|
|
|
the tracker and the pushed docs; `PATCH` the project's summary and next
|
|
|
|
|
action, which nothing else writes; and a check-in if what changed is worth a
|
|
|
|
|
timestamped note. Commands are [at the bottom](#the-commands).
|
|
|
|
|
|
|
|
|
|
Steps 6 and 7 are the two that get skipped, and they are the two nobody else can
|
|
|
|
|
do afterwards.
|
|
|
|
|
|
|
|
|
|
## Next action — where it lives
|
|
|
|
|
|
|
|
|
|
| Copy | Where | What it is |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| The current one | `nextAction` on the project, privacyllc.dev | the live answer to "what happens next", shown to whoever opens the project screen |
|
|
|
|
|
| The dated one | the newest entry in `DEVELOPMENT_LOG.md` | what the next action was **at that point** — history, not status |
|
|
|
|
|
|
|
|
|
|
These are not two records of the same thing, and the distinction is worth
|
|
|
|
|
holding on to. The field is overwritten every time and always describes now. The
|
|
|
|
|
log entry is never edited and describes a moment — which is what makes it safe
|
|
|
|
|
to keep, and why an old entry naming a next action that has since been done is
|
|
|
|
|
not stale, it is a receipt.
|
|
|
|
|
|
|
|
|
|
Write the next action as an **action**: the thing a person would start on
|
|
|
|
|
Monday, specific enough to begin without asking a question. "Continue the work"
|
|
|
|
|
is not one. If the honest answer is that you do not know, that is a real answer —
|
|
|
|
|
say what has to be decided and by whom.
|
|
|
|
|
|
|
|
|
|
**Filing an issue can change what the project card says next, without anyone
|
|
|
|
|
choosing that.** The dashboard's next action is the *newest open issue in the
|
|
|
|
|
current milestone* — not the most severe one; severity labels have no influence
|
|
|
|
|
on it at all. So a routine `P2` filed into the batch you are working in replaces
|
|
|
|
|
whatever the card was showing, and it will keep showing that until something
|
|
|
|
|
newer arrives. The `nextAction` field is the only way to say something different
|
|
|
|
|
on purpose, which is most of why step 7 exists.
|
|
|
|
|
|
|
|
|
|
`currentSummary`, `nextAction` and `description` are **write-only**: they are
|
|
|
|
|
deliberately absent from every API response, because free text can name a
|
|
|
|
|
customer or an unannounced product. Only the admin screen shows them back. Never
|
|
|
|
|
report them as empty because a `GET` did not return them.
|
|
|
|
|
|
|
|
|
|
## Blockers — where they live
|
|
|
|
|
|
|
|
|
|
A blocker is recorded in up to three places, and **an agent can write only the
|
|
|
|
|
first and the third**:
|
|
|
|
|
|
|
|
|
|
| Where | What it holds | Who writes it |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| The tracker | the work itself — an issue labelled `release-blocker`, or `P0` when it ships broken | anyone, including an agent |
|
|
|
|
|
| The blockers table on privacyllc.dev | the business-facing blocker, with a severity, an owner and a resolution note | **a human, in the admin UI** |
|
|
|
|
|
| A check-in's `blockers` field | narrative: what is stuck, said in a timestamped note | anyone, including an agent |
|
|
|
|
|
|
|
|
|
|
The agent API has no route that creates, edits or resolves a blocker on the
|
|
|
|
|
site. Posting a check-in whose `blockers` field says something is stuck records
|
|
|
|
|
*narrative* — it does not touch the blockers table, and it does not clear
|
|
|
|
|
anything. An agent that reports "blocker filed" after a check-in has told the
|
|
|
|
|
truth about the note and a falsehood about the table.
|
|
|
|
|
|
|
|
|
|
So: **file the issue** — that is the copy the work is actually tracked in — and
|
|
|
|
|
when it belongs in front of a stakeholder, say so plainly and let a human enter
|
|
|
|
|
it. Before treating a site blocker as resolved, restate its title and status and
|
|
|
|
|
get explicit confirmation; the admin UI requires a resolution note that the API
|
|
|
|
|
cannot supply.
|
|
|
|
|
|
|
|
|
|
If the work is blocked and nothing is filed anywhere, the project simply looks
|
|
|
|
|
slow.
|
|
|
|
|
|
|
|
|
|
## Open and closed are not bookkeeping
|
|
|
|
|
|
|
|
|
|
Every open issue is a denominator, and not in the abstract: the percentage on
|
|
|
|
|
the project screen **is** closed issues over all issues in this tracker. Nothing
|
|
|
|
|
else produces it. That has three consequences worth stating in full:
|
|
|
|
|
|
|
|
|
|
- **An issue left open after the work is done** understates the project
|
|
|
|
|
permanently, and the understatement compounds — a fortnight of finished work
|
|
|
|
|
with unclosed issues reads as a fortnight of no progress.
|
|
|
|
|
- **An issue closed without evidence** cannot be reopened with confidence,
|
|
|
|
|
because nothing in it says what "fixed" meant. That is why the close comment
|
|
|
|
|
carries the path, symbol, test or command.
|
|
|
|
|
- **Invented future work** makes every percentage wrong, permanently and in one
|
|
|
|
|
direction. Do not pad the tracker. If the real answer is one milestone and
|
|
|
|
|
three issues, file exactly that.
|
|
|
|
|
|
|
|
|
|
Milestones are the same argument at batch scale, and they are counted the same
|
|
|
|
|
way: milestones closed over milestones total is the second figure on the project
|
|
|
|
|
screen. Closing the last issue under a milestone does not close the milestone,
|
|
|
|
|
so a tracker full of complete-but-open batches reports a project as less
|
|
|
|
|
finished than it is — and cannot answer "what shipped".
|
|
|
|
|
|
|
|
|
|
**File every issue into a milestone.** One filed outside still counts against
|
|
|
|
|
the headline percentage while being invisible to the milestone figure, which is
|
|
|
|
|
how two readings of the same project come to describe different amounts of work.
|
|
|
|
|
The site measures the gap rather than ignoring it.
|
|
|
|
|
|
|
|
|
|
One trap that costs an afternoon, and it is about a *card* rather than a figure:
|
|
|
|
|
the Milestones list on privacyllc.dev reads the Command Center's own table,
|
|
|
|
|
which only an admin can write. A repository whose milestones are being counted
|
|
|
|
|
in the figure above can still show *"No milestones have been added yet"* in that
|
|
|
|
|
list. It is not a sync failure and no amount of reconciling changes it.
|
|
|
|
|
|
|
|
|
|
## Docs travel with the push
|
|
|
|
|
|
|
|
|
|
The Command Center reads this repository's documents at a commit, and stores the
|
|
|
|
|
SHA it read them from. When that SHA falls behind the repository's newest
|
|
|
|
|
commit, the docs report is marked **stale** — not wrong, not missing, *stale*,
|
|
|
|
|
which is the honest description of a document that was accurate at a commit
|
|
|
|
|
nobody is running any more.
|
|
|
|
|
|
|
|
|
|
Two ways to produce it, and both are ordinary carelessness rather than bad luck:
|
|
|
|
|
|
|
|
|
|
- **Code pushed, documents not updated.** The report is recomputed at the new
|
|
|
|
|
SHA against prose describing the old behaviour. Nothing flags this; the
|
|
|
|
|
document is simply confidently wrong now, and its `Last reviewed` line still
|
|
|
|
|
looks recent.
|
|
|
|
|
- **Documents updated, not pushed.** The site keeps reporting the old ones. A
|
|
|
|
|
correction that exists only on your machine has not been made.
|
|
|
|
|
|
|
|
|
|
Hence step 4's insistence that documentation edits ride in the same commit as
|
|
|
|
|
the change that caused them. It is not tidiness — a doc commit that comes "after
|
|
|
|
|
this next thing" is the commit that does not get written, and the manual's
|
|
|
|
|
migration table in the project this template came from sat six migrations behind
|
|
|
|
|
before anybody noticed. Every reader in between trusted it.
|
|
|
|
|
|
|
|
|
|
## What the Command Center reads, and who writes it
|
|
|
|
|
|
|
|
|
|
Four independent channels, and **only two of them are automatic**:
|
|
|
|
|
|
|
|
|
|
| On the project screen | Source | How it gets there |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| Headline % — issues closed / all issues | the repository's tracker | automatic — on reconcile, and immediately on a webhook delivery |
|
|
|
|
|
| Second figure — milestones closed / all milestones | the repository's **milestones** | same read, same moment |
|
|
|
|
|
| Milestone coverage — issues that sit in no milestone | the repository's tracker | same read |
|
|
|
|
|
| QA verdict — round, build SHA, overall sentence | `docs/qa/ClaudeReport.md` | push the repository, then reconcile |
|
|
|
|
|
| Current summary / Next action | manual fields on the project | `PATCH /agent/projects/<slug>` — nothing else writes them |
|
|
|
|
|
| The Milestones card, and a typed weighted plan | the Command Center's **own** milestone table | admin UI only |
|
|
|
|
|
| Blockers | the Command Center's **own** blockers table | admin UI only |
|
|
|
|
|
|
|
|
|
|
The first three are why steps 1 and 3 are steps: **closing an issue and closing
|
|
|
|
|
a milestone each move a figure a stakeholder can see, that day.** The last two
|
|
|
|
|
are lists rather than figures, and they are the ones an agent cannot write — a
|
|
|
|
|
repository whose milestones are counted in the second figure can still show
|
|
|
|
|
*"No milestones have been added yet"* on the card, because that card reads a
|
|
|
|
|
table only an admin fills in.
|
|
|
|
|
|
|
|
|
|
A repository that has not adopted the four label names is reported as *not
|
|
|
|
|
adopted* rather than as zero defects, and one with its tracker switched off is
|
|
|
|
|
reported as switched off rather than as an empty backlog. Absence is never
|
|
|
|
|
rendered as a measurement — which is exactly why a real backlog nobody filed
|
|
|
|
|
looks like nothing at all.
|
|
|
|
|
|
|
|
|
|
## The commands
|
|
|
|
|
|
|
|
|
|
The tracker is the Forgejo instance at
|
|
|
|
|
**[dream.scheller.ltd](https://dream.scheller.ltd)**, and steps 1 to 3 happen
|
|
|
|
|
there. Its credentials, the Cloudflare trap and the reason it has to be that
|
|
|
|
|
instance rather than any tracker are in the project README's *Where the tracker
|
|
|
|
|
is* — one copy, named once:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
set -a; . ~/.openclaw/docker-registry.env; set +a
|
docs: correct 57 claims the code and tracker disagreed with
Every document in the tree audited against the source, the tracker and git
history, each finding then given to a second reader tasked with refuting it.
74 raised, 12 refuted, 57 applied. No code changed.
THE README DESCRIBED A SKELETON
Its Status table — the one place a claim about what is built is allowed to live
— still read "there is no usable app yet", with Not built against Room, the four
core screens, fertility and notifications, and No round run against QA. Five
batches had shipped and three QA rounds had run.
TWO DOCUMENTS WERE SILENTLY NEVER FIRING
architecture/README.md and design/README.md wrote Governs: as prose ("the Gradle
module graph", "the design tokens in core/designsystem"). Neither contains a
path token, so doc-triggers.py reduced them to globs matching nothing, and one
real glob apiece made them look path-governing rather than subject-governing —
the state the script's own header calls invisible. Editing a Room entity never
fired the document owning the migration table. Both now fire, proved by running
the script.
SECURITY.md CLAIMED FOUR UNBUILT PROTECTIONS
App lock listed among what works offline; biometric/PIN gating described as
protecting app launch; the incognito launcher as existing; Play Billing in the
third parties table without the "not yet integrated" marker its neighbours
carry. All are Batch 06/07 work.
The advertising boundary was overstated in SECURITY.md and the README alike:
both said the ads module declares no dependency and a guard proves it. There is
no ads module. The pre-declared ":core:ads" to emptySet() rule is stricter than
the sentence it replaced and matches nothing until Batch 07, which is why the
guard is proved by injection rather than trusted.
SMALLER, EACH A REAL TRAP
WORK_CYCLE.md pointed at docs/architecture/scripts/forgejo-issue.py, a template
path absent here — missed by doc-claims.sh, which reads backticked prose and not
fenced blocks. ClaudeReport.md's Round notes said "No rounds yet" after three
rounds because ClaudeQAPlan.md's after-a-round list never named that section;
the playbook is fixed first. The instrumented-test count was eight in three
places and is four. HISTORY.md said the repository had no code and that nothing
had been tried and dropped, when three approaches had.
DELIBERATELY UNCHANGED
ClaudeReport.md's last verified build SHA stays at 0451fbe — no round has run
since, and moving it would claim a verification nobody performed. Every
DEVELOPMENT_LOG entry stays as written.
Guards: ./gradlew check, schema-guard.sh, doc-claims.sh (235 claimed paths, all
present), doc-triggers.py, and a link sweep over 21 markdown files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 16:33:14 -05:00
|
|
|
python3 scripts/forgejo-issue.py list
|
|
|
|
|
python3 scripts/forgejo-issue.py close 42 "Fixed in a1b2c3d; PredictionAcceptanceTest covers it."
|
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
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Step 7 talks to the Command Center instead:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# The token lives in this machine's credential store, never in the repository.
|
|
|
|
|
TOKEN="$PRIVACY_LLC_TOKEN"
|
|
|
|
|
BASE="https://privacyllc.dev/api/internal/v1"
|
|
|
|
|
AUTH="Authorization: Bearer $TOKEN"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Reconcile** — re-read the tracker and the pushed documents. Do this after the
|
|
|
|
|
push, not before:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
curl -sk -X POST -H "$AUTH" -H "Content-Type: application/json" \
|
|
|
|
|
-d '{"kind":"reconcile_all"}' "$BASE/agent/jobs"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Summary and next action** — read the project first for its `version`, then
|
|
|
|
|
send a flat body carrying that version. A stale version is rejected rather than
|
|
|
|
|
silently overwriting somebody else's edit:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
curl -sk -H "$AUTH" "$BASE/agent/projects/<slug>" # for version + state
|
|
|
|
|
|
|
|
|
|
curl -sk -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
|
|
|
|
|
-d '{"version":<n>,"health":"on_track",
|
|
|
|
|
"currentSummary":"<where the project stands, in a sentence or two>",
|
|
|
|
|
"nextAction":"<the next concrete thing, specific enough to start>"}' \
|
|
|
|
|
"$BASE/agent/projects/<slug>"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**A check-in** — a timestamped "what changed", when there is something real to
|
|
|
|
|
report. `summary` is required and must say something; the API refuses an empty
|
2026-08-18 16:35:06 -05:00
|
|
|
"no change" update, deliberately.
|
|
|
|
|
|
|
|
|
|
**`projectId` here is the project's UUID, not its slug** — unlike every other
|
|
|
|
|
route on this API, which takes the slug in the path. A slug is rejected with
|
|
|
|
|
`{"error":{"code":"unknown","message":"Something went wrong."}}`, which says
|
|
|
|
|
nothing about which field was wrong and looks exactly like an outage. Read the
|
|
|
|
|
`id` off the project first. There is also **no route that amends a check-in**
|
|
|
|
|
once posted, so get the body right before sending it:
|
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
|
|
|
|
|
|
|
|
```bash
|
2026-08-18 16:35:06 -05:00
|
|
|
PID=$(curl -sk -H "$AUTH" "$BASE/agent/projects/<slug>" \
|
|
|
|
|
| python3 -c "import json,sys; print(json.load(sys.stdin)['project']['id'])")
|
|
|
|
|
|
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
|
|
|
curl -sk -X POST -H "$AUTH" -H "Content-Type: application/json" \
|
2026-08-18 16:35:06 -05:00
|
|
|
-d '{"projectId":"'"$PID"'","health":"on_track",
|
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
|
|
|
"summary":"<what changed>","accomplishments":"<what landed>",
|
|
|
|
|
"blockers":"<what is stuck, or omit>","nextActions":"<what is next>"}' \
|
|
|
|
|
"$BASE/agent/updates"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Health is one of `on_track`, `caution`, `off_track`, `unknown`. Never invent
|
|
|
|
|
one, and never report progress the API did not return.
|
|
|
|
|
|
|
|
|
|
## What this file is not
|
|
|
|
|
|
|
|
|
|
- **Not the work list.** That is the tracker: milestones are batches, issues are
|
|
|
|
|
deliverables.
|
docs: correct 57 claims the code and tracker disagreed with
Every document in the tree audited against the source, the tracker and git
history, each finding then given to a second reader tasked with refuting it.
74 raised, 12 refuted, 57 applied. No code changed.
THE README DESCRIBED A SKELETON
Its Status table — the one place a claim about what is built is allowed to live
— still read "there is no usable app yet", with Not built against Room, the four
core screens, fertility and notifications, and No round run against QA. Five
batches had shipped and three QA rounds had run.
TWO DOCUMENTS WERE SILENTLY NEVER FIRING
architecture/README.md and design/README.md wrote Governs: as prose ("the Gradle
module graph", "the design tokens in core/designsystem"). Neither contains a
path token, so doc-triggers.py reduced them to globs matching nothing, and one
real glob apiece made them look path-governing rather than subject-governing —
the state the script's own header calls invisible. Editing a Room entity never
fired the document owning the migration table. Both now fire, proved by running
the script.
SECURITY.md CLAIMED FOUR UNBUILT PROTECTIONS
App lock listed among what works offline; biometric/PIN gating described as
protecting app launch; the incognito launcher as existing; Play Billing in the
third parties table without the "not yet integrated" marker its neighbours
carry. All are Batch 06/07 work.
The advertising boundary was overstated in SECURITY.md and the README alike:
both said the ads module declares no dependency and a guard proves it. There is
no ads module. The pre-declared ":core:ads" to emptySet() rule is stricter than
the sentence it replaced and matches nothing until Batch 07, which is why the
guard is proved by injection rather than trusted.
SMALLER, EACH A REAL TRAP
WORK_CYCLE.md pointed at docs/architecture/scripts/forgejo-issue.py, a template
path absent here — missed by doc-claims.sh, which reads backticked prose and not
fenced blocks. ClaudeReport.md's Round notes said "No rounds yet" after three
rounds because ClaudeQAPlan.md's after-a-round list never named that section;
the playbook is fixed first. The instrumented-test count was eight in three
places and is four. HISTORY.md said the repository had no code and that nothing
had been tried and dropped, when three approaches had.
DELIBERATELY UNCHANGED
ClaudeReport.md's last verified build SHA stays at 0451fbe — no round has run
since, and moving it would claim a verification nobody performed. Every
DEVELOPMENT_LOG entry stays as written.
Guards: ./gradlew check, schema-guard.sh, doc-claims.sh (235 claimed paths, all
present), doc-triggers.py, and a link sweep over 21 markdown files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 16:33:14 -05:00
|
|
|
- **Not the release procedure.** This project has no `release.sh` — a release here is
|
2026-08-18 02:18:25 -05:00
|
|
|
a signed AAB and a Play Console submission, so
|
|
|
|
|
[`security/SECURITY_CHECKLIST.md`](security/SECURITY_CHECKLIST.md) carries it.
|
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
|
|
|
- **Not the QA procedure.** That is `docs/qa/ClaudeQAPlan.md`, which ends in its
|
|
|
|
|
own version of step 7.
|
|
|
|
|
- **Not a place to record status.** If you are about to add "current state" or a
|
|
|
|
|
list of outstanding items below this line, the tracker is where it goes.
|