From 96c0e95d5cdb5053a01195b8fb576008eb8dceb3 Mon Sep 17 00:00:00 2001 From: null Date: Tue, 18 Aug 2026 15:33:04 -0500 Subject: [PATCH] docs: record Round 3 QA and the Batch 05 log entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- docs/history/DEVELOPMENT_LOG.md | 65 +++++++++++++++++++++++++++++++++ docs/qa/ClaudeQACoverage.md | 40 ++++++++++++++++++++ docs/qa/ClaudeReport.md | 29 +++++++-------- 3 files changed, 119 insertions(+), 15 deletions(-) diff --git a/docs/history/DEVELOPMENT_LOG.md b/docs/history/DEVELOPMENT_LOG.md index 9ff152e..ca734db 100644 --- a/docs/history/DEVELOPMENT_LOG.md +++ b/docs/history/DEVELOPMENT_LOG.md @@ -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 diff --git a/docs/qa/ClaudeQACoverage.md b/docs/qa/ClaudeQACoverage.md index 72f722d..52b68a8 100644 --- a/docs/qa/ClaudeQACoverage.md +++ b/docs/qa/ClaudeQACoverage.md @@ -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 diff --git a/docs/qa/ClaudeReport.md b/docs/qa/ClaudeReport.md index 611c6b5..77e6a25 100644 --- a/docs/qa/ClaudeReport.md +++ b/docs/qa/ClaudeReport.md @@ -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