diff --git a/docs/history/DEVELOPMENT_LOG.md b/docs/history/DEVELOPMENT_LOG.md index 65bf888..12b9d46 100644 --- a/docs/history/DEVELOPMENT_LOG.md +++ b/docs/history/DEVELOPMENT_LOG.md @@ -32,6 +32,69 @@ written and stay true. It is exempt from review for the same reason a receipt is ## Entries +### 2026-08-18 — Batch 03 shipped: every screen the app has, and three defects only looking could find + +All six Batch 03 issues closed and the milestone with them. Period stopped being +a data layer with a debug surface and became something you can actually use: +onboarding that ends in a forecast, a Today screen whose six states each say +something different and true, two-tap logging, a calendar, and Insights. + +**Placeholder artwork, as §42 asks for it.** Every illustration and calendar +marker is a Compose vector path behind a replaceable name — no raster anywhere +under `src/`. The visual language is overlapping circular forms and nothing +else, because §42's forbidden list is a product decision: this app gets opened +in public and a glance over a shoulder should learn nothing. Note the deliberate +contrast with `docs/data/img/`, where a placeholder is still forbidden and #8 +stays open; `docs/design/README.md` now explains why the two differ rather than +leaving it looking inconsistent. + +**Three defects, none findable by reading:** + +1. **Dark mode was broken for the whole of Batch 01.** `PeriodTheme` never + wrapped its content in a `Surface`, so any `Text` without an explicit colour + inherited Material's default — black — and the app's background never + painted. Light mode looked right by accident, because dark-on-cream is what + was wanted anyway. 129 tests were green throughout. +2. **"Period ended" appeared to do nothing.** The logic was correct: a period + that ends today still includes today, so the state genuinely does not change. + The screen was identical afterwards and the button read as broken, which is + worse than being broken somewhere visible. +3. **The today-underline collided with the spotting dot** on the one day that + was both. Invisible in the colour screenshot and obvious the moment it was + converted to greyscale — which is how §43 says to check, and why the check is + written that way rather than trusting that shapes differ because they were + designed to. + +Two more came from tests doing their job: the typical-range quartiles were +indexed off `size` rather than `size - 1`, so a regular cycle with one long gap +was reported as "typical range 29–61 days" on the screen whose only job is to +say what has been learned; and Room's own executor meant a test's virtual clock +returned before the writes landed, which read as an empty database rather than +as a timing bug. + +**The habit is now five pieces of work old and worth writing down as a rule: the +defects in this project are found by running it.** Three guards were green over +exactly what they claimed to check, dark mode was broken for a whole batch, and +a button looked broken while behaving correctly. None of it was visible in the +source. + +- **Closed:** #15, #16, #17, #18, #19, #20 — and the `Batch 03 — Core UX` + milestone. +- **Next action:** Batch 04 — Fertility. File its issues first; the milestone is + empty. The work is estimated ovulation and the fertile window from the + forecast and a configurable luteal-phase assumption (§17, §18), the calendar + and Today states that already have their shapes and their `null` placeholders + waiting, and the not-contraception disclaimer everywhere fertility appears. + `CycleStatus` and `CalendarMarks` both already take fertility parameters and + currently receive null — Batch 04 is largely filling those in rather than + adding surfaces. +- **Blockers:** Unchanged. #8 needs the three branding marks drawn by a person. + #9 needs the Command Center webhook URL and secret, which are not readable + from this machine. Neither blocks Batch 04. Worth doing before much more UI: + run TalkBack once, scale the font to maximum once, and run the app once on a + device at `minSdk` 26 — all three are recorded as standing gaps and none has + ever been done. + ### 2026-08-18 — Batch 02 shipped: the prediction engine, and three bugs the tests found All five Batch 02 issues closed and the milestone closed with them. The app now diff --git a/docs/qa/ClaudeQACoverage.md b/docs/qa/ClaudeQACoverage.md index 0eb1195..72f722d 100644 --- a/docs/qa/ClaudeQACoverage.md +++ b/docs/qa/ClaudeQACoverage.md @@ -13,6 +13,40 @@ Review trigger: Any QA round run > like a pass that succeeded, and that is how untested code ships believing it > was tested. +## Round 2 — 2026-08-18 at `19edf4c`, partial + +Batch 03 built every screen the app has, and each was driven by hand on the +emulator as it landed rather than in one pass at the end. Same environment: +`PeriodQA`, API 36, Pixel 6 profile, debug build. + +| Pass | Result | Notes | +| --- | --- | --- | +| A — First run | **Pass** | Clean install reaches onboarding; all seven screens walked; the flow produces a forecast and a relaunch goes straight to Today. | +| B — Core loop | **Pass** | Two-tap logging confirmed on the device: "Started period" → "Yes — today" → "Logged ✓". Editing, ending, and spotting reclassification all exercised. | +| C — Failure paths | **Partial** | Duplicate-date logging, an end date before a start, and a future date in the picker all handled. Airplane mode, denied permissions and a process killed mid-write still untried. | +| D — Persistence | **Partial** | Onboarding completion, records and settings all survive force-stop and relaunch. Reboot and update-over-install untried. | +| E — Forecast under hard histories | **Partial** | The §51 cases pass as unit tests against both engines, and the not-yet path was driven through the UI. The variable and outlier histories have still not been entered by hand. | +| F — Notification privacy | **Not run** | Nothing sends a notification yet — Batch 05. The onboarding *choice* was verified: Discreet is selected before the user touches anything. | +| G — Accessibility | **Partial** | Every calendar day, the confidence indicator and the hero countdown carry content descriptions, checked by reading the view hierarchy. **The calendar was verified in actual greyscale** and all five marks remain distinguishable. TalkBack itself, and font scaling, still untried. | +| H — Data ownership | **Partial** | Delete-all covered by an instrumented test. Export, app lock and artifact inspection do not exist yet. | + +### What driving it found that tests did not + +Three defects, none of which any unit test would have caught: + +1. **Dark mode was broken for the whole of Batch 01.** `PeriodTheme` never + wrapped its content in a `Surface`, so text without an explicit colour + inherited black and the app background never painted. Light mode looked + correct by accident. +2. **"Period ended" appeared to do nothing.** The logic was right — a period + ending today still includes today — but the screen was identical afterwards, + so the button read as broken. +3. **Today's underline collided with the spotting dot**, on the one day that was + both. Invisible in the colour screenshot, obvious in greyscale. + +The pattern is now four rounds old and worth stating as a rule: **the defects in +this project are found by opening it, not by reading it.** + ## Round 1 — 2026-08-18 at `adc5075`, partial Not a full round. Batch 01 produced the first build, and this covered the two @@ -74,6 +108,12 @@ 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. +- **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 + navigates a screen with their eyes shut. +- **Font scaling untried.** The hero number is 72sp; at the largest accessibility + scale it may not fit beside anything. - **No device at `minSdk`.** Everything so far ran on API 36. The two NewApi bugs above would have crashed on Android 8 through 13 and nothing except lint could see them. Lint is a good guard and it is not a substitute for one run on diff --git a/docs/qa/ClaudeReport.md b/docs/qa/ClaudeReport.md index 244e314..611c6b5 100644 --- a/docs/qa/ClaudeReport.md +++ b/docs/qa/ClaudeReport.md @@ -19,19 +19,22 @@ Review trigger: Any QA round run ## Current run-state -- **Last QA round:** Round 1 — 2026-08-18, partial (passes A and B; C, D and H partial) -- **Last verified build SHA:** `adc5075` +- **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 tested device / environment:** emulator `PeriodQA`, API 36, Pixel 6 profile, debug build -- **Overall status:** The Batch 01 foundation works end to end on a device — log - a period, see a forecast with an honest window and confidence, edit it and - watch the forecast move — and the first partial QA round found two defects - that 70 passing unit tests could not: tapping the app's primary button twice - crashed it, and two date APIs on the recalculation path would have crashed - every device below Android 14. Both are fixed, with regression tests. That - ratio is the honest summary of where this project stands: the logic is well - covered and the product has barely been used, so the next round matters more - than the last one. Nothing has been tested at the minimum Android version this - app claims to support. +- **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. ## Open defects