docs: record Round 3 QA and the Batch 05 log entry

Round 3 adds pass F, which became runnable for the first time. Eight
instrumented tests assert what a lock screen would render; the row says plainly
that nobody has yet looked at an actual locked screen, because the tests check
the notification object and the last mile is what the system chooses to draw.

Three guards have now failed their first proof — schema, boundaries,
permissions. Recorded as a rule rather than a run of bad luck: assume a new
guard is broken until it has been watched failing.
This commit is contained in:
null 2026-08-18 15:33:04 -05:00
parent 0451fbe00a
commit 96c0e95d5c
3 changed files with 119 additions and 15 deletions

View File

@ -32,6 +32,71 @@ written and stay true. It is exempt from review for the same reason a receipt is
## Entries
### 2026-08-18 — Batch 05 shipped, and the app got its real brand
Reminders landed and the milestone closed. **Five of eight batches are done, and
exactly one issue is open in the whole tracker** — #9, the webhook, which needs a
person.
**Notifications, and the two Android behaviours that leak if you trust the
docs.** `NotificationCopy` is a pure function, so every kind × every mode is
tested exhaustively without an emulator — including the action labels, which §31
points out are visible text too. A perfectly discreet body under a button
reading "Started my period" leaks anyway.
Then the device found what the unit tests could not:
1. **A private notification with no public version does not blank the lock
screen — it shows the private text.** `NotificationText` therefore has no
nullable title, and an instrumented test asserts every kind attaches one.
2. **A notification channel is immutable after creation.** Importance and
lock-screen visibility cannot be changed, so one shared channel would have
kept whatever the user's first privacy mode set, forever. Switching from
Direct to Maximum privacy would have *appeared* to work and changed nothing.
One channel per mode now.
**A third guard failed its first proof.** `checkPermissions` — new, and worth
having, because adding WorkManager silently brought four permissions that appear
in the Play listing — read a stale merged manifest because it did not depend on
the task that writes one. An injected `SCHEDULE_EXACT_ALARM` went unnoticed.
That is the schema guard, the boundary guard and now the permission guard: three
for three. **Assume a new guard is broken until it has been watched failing.**
**And a mistake of mine worth keeping.** While proving the pre-commit fix I
committed a throwaway and ran `git reset --hard HEAD~1`, which did not undo the
push the post-commit hook had already made and silently discarded the
uncommitted fix I was mid-proof on. Reconciled forward rather than rewriting
published history. Commit the work before proving the guard.
**The brand arrived mid-session.** The owner supplied a full visual guide and
artwork, which answers #8 — the three marks an agent must not fake now exist
because a person made them. Converted to the required webp with two things
handled rather than blindly transcoded: the sources render their rounded corners
against black, and the lockup is square so a 3:1 crop would have cut the wordmark
in half.
The guide **supersedes §39's colour direction**, and one conflict is real: §39
wants a muted teal fertile window and the guide is plum-and-rose throughout with
a pink for fertility. The guide wins, and it is safe for it to win *because the
calendar's states differ in shape rather than colour* — which is what §43
actually requires. Written down in `docs/design/README.md` rather than left to be
found.
- **Closed:** #8, #24, #25, #26, #27 — and the `Batch 05 — Notifications`
milestone.
- **Next action:** Batch 06 — Privacy and Security. File its issues first; the
milestone is empty. The work is biometric and PIN lock, export, irreversible
delete, the privacy promise in Settings, and making §45's logging rules true in
a release build. Much of the groundwork exists — `deleteAllHealthData` is
written and tested, backup is already excluded in the manifest — so this batch
is largely surfacing what the data layer can already do, plus the designed
Settings screen the Batch 05 working surface is standing in for.
- **Blockers:** One issue, and it needs a person: #9, the Command Center webhook.
Until it is registered an opened `P0` raises no alert at all. The QA gaps are
now the more pressing thing: **nobody has looked at an actual lock screen**,
TalkBack has never been run, text has never been scaled, and nothing has run
at `minSdk` 26. All four are cheap and none has ever been done.
### 2026-08-18 — Batch 04 shipped: fertility that declines, and a hook that refused every deletion
Three issues closed and the milestone with them. Four of the eight batches are

View File

@ -13,6 +13,42 @@ Review trigger: Any QA round run
> like a pass that succeeded, and that is how untested code ships believing it
> was tested.
## Round 3 — 2026-08-18 at `0451fbe`, partial
Batches 04 and 05 landed: fertility estimates and the reminder system. Pass F
became runnable for the first time.
**Environment:** emulator `PeriodQA`, API 36, Pixel 6 profile, debug build, plus
8 instrumented tests on the same device.
| Pass | Result | Notes |
| --- | --- | --- |
| A — First run | **Pass** | Re-run after the brand change; onboarding reaches a forecast, relaunch skips it. |
| B — Core loop | **Pass** | Unchanged and re-driven. Fertility appears on Today and the calendar once the forecast is tight enough. |
| C — Failure paths | **Partial** | As Round 2. Airplane mode, denied notification permission and a killed process still untried. |
| D — Persistence | **Partial** | As Round 2. Reboot and update-over-install untried — the second matters more now that WorkManager holds scheduled work. |
| E — Forecast under hard histories | **Partial** | Unit-tested against both engines; the §51 histories still have not been entered by hand. |
| F — Notification privacy | **Partial, and this is the important row** | Eight instrumented tests on a device assert what a lock screen *would* render: every kind × both private modes attaches a public version, is marked `VISIBILITY_PRIVATE`, and leaks no health word — including the action labels. **Nobody has yet looked at an actual locked screen.** That is a real gap: the tests check the notification object, and the last mile is what the system chooses to draw. |
| G — Accessibility | **Partial** | Unchanged. Calendar verified in real greyscale again after the palette change. TalkBack and font scaling still never run. |
| H — Data ownership | **Partial** | Unchanged. |
### What this round found
Two defects, both in how Android behaves rather than in the app's logic, and
both found by running on a device:
1. **A notification channel is immutable after creation.** Importance and
lock-screen visibility cannot be changed once set, so a single shared channel
would have kept whatever the user's first privacy mode chose — switching from
Direct to Maximum privacy would have appeared to work and changed nothing.
One channel per mode now.
2. **`checkPermissions` was green over its own target**, reading a stale merged
manifest because it did not depend on the task that writes one. The third
guard in this project to fail its first proof.
Also confirmed: a seventeen-day "fertile window" was on screen for a user one
cycle in. Arithmetically correct, useless, and only visible by looking.
## Round 2 — 2026-08-18 at `19edf4c`, partial
Batch 03 built every screen the app has, and each was driven by hand on the
@ -108,6 +144,10 @@ at its own `minSdk`.**
Things no round has ever covered, carried forward until they are. This list
existing is not a failure; it not existing while the gaps do is.
- **No lock screen has been looked at.** Pass F's instrumented tests assert the
notification object is built correctly, which is most of the risk and not all
of it. What the system actually draws on a locked device — including heads-up
behaviour and any launcher's own preview — has never been seen by anybody.
- **TalkBack has never actually been run.** Content descriptions are written and
were checked by reading the view hierarchy, which proves they exist and not
that they make sense in sequence. Pass G is not complete until somebody

View File

@ -19,22 +19,21 @@ Review trigger: Any QA round run
## Current run-state
- **Last QA round:** Round 2 — 2026-08-18, partial (A and B pass; C, D, E, G and H partial; F not applicable yet)
- **Last verified build SHA:** `19edf4c`
- **Last QA round:** Round 3 — 2026-08-18, partial (A and B pass; C, D, E, F, G and H partial)
- **Last verified build SHA:** `0451fbe`
- **Last tested device / environment:** emulator `PeriodQA`, API 36, Pixel 6 profile, debug build
- **Overall status:** Three batches are done and the app is now a real product
you can use end to end: onboarding that ends in a forecast, a Today screen
whose six states each say something different and true, two-tap logging, a
calendar whose marks survive greyscale, and an Insights screen that mostly
declines to make claims it has not earned. The prediction engine is the one
§12 specifies and is measurably better than the prototype it replaced. What
the rounds keep showing is that this project's defects are found by opening
the app rather than by reading it — dark mode was broken for an entire batch
with 129 tests green, and the calendar's marks collided in a way only a
greyscale screenshot revealed. The gaps that matter now are the ones nothing
has touched: TalkBack has never been run, text has never been scaled up, and
nothing has run on a device at the minimum Android version this app claims to
support.
- **Overall status:** Five of eight batches are done and the app is a coherent
product: onboarding to a forecast, a Today screen with six honest states,
two-tap logging, a calendar readable in greyscale, insights that decline to
overstate, fertility estimates that refuse to appear when the forecast is too
vague to support them, and discreet reminders. It now wears its real brand,
supplied by the owner. Eight instrumented tests assert that nothing about a
period reaches a lock screen in either private mode — but **nobody has yet
looked at an actual locked screen**, and that last mile is the single most
valuable thing left to check, because a notification read over a shoulder is
the likeliest real privacy failure in this product. The other standing gaps
are of the same kind: TalkBack has never been run, text has never been scaled,
and nothing has run at the minimum Android version this app claims to support.
## Open defects