Phase N — (what is true when it closes, in words a user would recognise)
Sequence lives in PLAN.md; the live worklist lives in DOD.md. (Name the
ADRs this phase relies on or reopens, and what CONTEXT.md is owed — a new term, or
“nothing, and why”.)
What closing this phase means. (One paragraph: the app as it is today, the app after this phase, and the difference stated as something a device can be asked about.)
(If PLAN.md’s paragraph for this phase is already wrong — an item shipped early, one turned out to
be something else — say so here, first. Planning a phase is when that is found.)
0. What this phase inherits
(What earlier phases left that this one leans on or has to work around: a mechanism, a device finding, a promise already made in copy or in the listing. The asymmetry that shapes the phase usually lives here — “this ask can be read back and that one cannot”, “this path is covered by a test and that one only by the phone”.)
What is in, and what is deliberately not
In: (one paragraph.)
Not in, and each with a reason rather than a phase:
- (Item.) (Why it is out: a refusal, a dependency on something outside this phase, or cost against what it buys. “Later” is not a reason.)
(The tempting one — the item that looks like a free upgrade — gets its own paragraph, because it is the one a later session will try to add back.)
Checkpoints
(Each checkpoint leaves the app working, and ships its copy complete in every shipped language —
scripts/translation-gate.py enforces that at merge. The commit type column is what release-please
reads, so it decides whether this phase cuts a release at all.)
| Checkpoint | Merges | Depends on | |
|---|---|---|---|
| A | The gate — (the one question that could veto the rest) | (often no commit: the verdict is a reading) | — |
| B | (…) | feat: |
A |
(A paragraph per non-obvious ordering. Put the gate first — a gate taken after the work answers the
same question a week later, with that week’s work already written on a bet. If two halves of a
checkpoint cost wildly different amounts, they are two checkpoints — PLAN.md rule 2 applies here
too.)
1. The gate: (the question)
(Only if the phase has something that could veto it — a platform behaviour nobody has measured, a pipeline path never exercised. Most phases worth a file have one.)
The question, in the form that can be measured
(Not “does scheduling work” but “does an inexact alarm start a foreground service at 22:00 with the app swiped away, on this ROM”. A question that cannot be answered by a command is not a gate yet.)
The apparatus
(What takes the reading, and where it lives — developer-only surface goes under app/src/debug/,
never behind BuildConfig.DEBUG in main/.)
The verdicts, decided now rather than argued about later
(Two or three outcomes, and what the phase does under each — written before the reading is taken. Deciding after is how a bad result gets argued into a good one.)
- (Outcome.) → (what happens.)
- (Outcome.) → (what happens.)
The verdict, taken (date)
(Which one, the reading behind it, and anything it found that neither verdict anticipated.)
2. (A section per piece of work)
(The shape, the rule it follows, the call sites, and what the user sees. A table for anything a
reader would otherwise have to re-derive — a state crossed with a moment, an ask crossed with its
phase (PLAN.md rule 4). The copy, in English, at the end of the section it belongs to.)
Tests
(PLAN.md rule 3’s second clause: a pure function that computes or bounds a safety value gets its
test in the phase that introduces it. Name each one and the direction it fails in. Device behaviour is
not listed here; it is a reading.)
Documents this phase amends
(ADRs, CONTEXT.md, the privacy policy, the listing, docs/play-app-content.md. A phase that adds a
permission, a stored key or a new surface owes at least one of them, and the pipeline will not notice.)
Known gaps, deliberately
- (A gap, why it is accepted, and what closing it would cost. Named here so a reader does not have to find the ADR to learn it.)
Readings
PLAN.md rule 3: filled in as the phase runs, from the device, with the command that read it — not
“it looked right”. Derivations are proven by a test, not recorded here.
(Name the device state a reading depends on and how it is set — a screen timeout, an autostart grant
that lapses, a battery exemption. CLAUDE.md’s environment notes list the readings that look like a
pass and are nothing at all.)
| # | Reading | Command | Result |
|---|---|---|---|
| R1 | (what is being asked) | (the exact command) | (what it said) (date) |
(A reading that could not be taken says so, with why and what answered the question instead. A reading struck because it was the wrong question is struck here, not deleted.)