diff --git a/docs/history/DEVELOPMENT_LOG.md b/docs/history/DEVELOPMENT_LOG.md index eef0d93..5993956 100644 --- a/docs/history/DEVELOPMENT_LOG.md +++ b/docs/history/DEVELOPMENT_LOG.md @@ -32,6 +32,65 @@ written and stay true. It is exempt from review for the same reason a receipt is ## Entries +### 2026-08-18 — The app ran at `minSdk` for the first time + +A second emulator exists — `PeriodMinSdk26`, API 26, Pixel 6 — and the app was +built, installed and driven on it start to finish. Everything before today ran on +API 36, which the standing gaps list has said since Batch 01. + +**It works.** Onboarding from *Get Started* to a first forecast, the Material 3 +date picker, Today, Calendar, Insights and Settings, all rendering correctly on +Android 8.0. The forecast was right — 4 August plus 28 days is 1 September, an +11-day window, confidence honestly **Low** on one cycle of history — and +fertility declined to estimate rather than inventing one. No crash, and no +`NoSuchMethodError`, `VerifyError` or `NoClassDefFoundError` attributable to the +app. The one `NoClassDefFoundError` in logcat is +`com.google.android.googlequicksearchbox` failing to resolve `TracingController`, +an API 28 class, in its own process. + +That is a genuinely useful negative result: the two `NewApi` bugs found in Batch +01 were exactly this shape and would have crashed here. + +**Three mechanical traps, all now in the QA playbook** rather than in somebody's +memory: + +1. **A windowed emulator dies with the session's X server.** The first one was + killed by `XIO: fatal IO error on X server ":0"` mid-flow. `-no-window` has no + such dependency and screenshots still work through `adb exec-out screencap`. +2. **`adb` regularly has three devices attached here**, because other projects + keep their own emulators running, and a bare `adb shell` then fails with *more + than one device/emulator*. The serial has to be resolved from the AVD name; + assuming `emulator-5554` targets somebody else's work. +3. **The debug build's application id carries a `.debug` suffix**, so + `monkey -p dev.privacyllc.period` aborts with *No activities found to run* + after a successful install — which reads as a broken app rather than a wrong + package name. + +**And a free persistence result.** The emulator was killed and cold-booted with +onboarding half finished. The install survived, and the app restarted at the +beginning of onboarding with nothing partial committed — which is correct, and is +the first reboot evidence pass D has ever had. + +**A guard failure of my own, from the entry above.** That entry named the bad +`forgejo-issue.py` path in backticks, and `doc-claims.sh` reads a backticked path +as a claim the file exists — so commit `ad085fb` shipped with the guard failing. +I had run it before writing the log entry and not after. The path is named bare +now, which is the convention `DOC_TRUST_MAP.md` already documents for +deliberately-absent files, and the guard reports 251 claimed paths all present. + +- **Closed:** nothing. This closes no issue; it partly closes a standing QA gap, + which lives in `docs/qa/ClaudeQACoverage.md` rather than the tracker. +- **Next action:** Batch 06 — Privacy and Security, unchanged. File its issues + first; the milestone is empty. Biometric and PIN lock, export, irreversible + delete, the privacy promise in Settings, and making §45's logging rules true in + a release build. +- **Blockers:** #9, the Command Center webhook, still needs a person. Three of the + four QA gaps are unchanged and remain the cheaper spend: nobody has looked at a + real lock screen, TalkBack has never been run, and text has never been scaled. + The fourth — nothing has run at `minSdk` — is now partly answered, though + notifications, the instrumented suites and any multi-cycle history are still + unreached at API 26. + ### 2026-08-18 — A doc audit against the code: 57 wrong claims in eighteen files No code changed. Every document in the tree was checked against the source, the @@ -73,11 +132,13 @@ emptySet()` is pre-declared in the root build script, stricter than the sentence it replaced, and matching no module until Batch 07 — which is exactly why the guard is proved by injection rather than trusted. -**Smaller, and each a real trap.** `WORK_CYCLE.md` told the reader to run -`docs/architecture/scripts/forgejo-issue.py`, a template path that does not -exist here — missed by `doc-claims.sh` because it only reads backticked prose, -not fenced blocks. `ClaudeReport.md`'s Round notes said "No rounds yet" after -three rounds, because `ClaudeQAPlan.md`'s after-a-round list never mentioned that +**Smaller, and each a real trap.** `WORK_CYCLE.md` told the reader to run a +`forgejo-issue.py` under docs/architecture/scripts/ — a template path that does +not exist here, named bare above because `doc-claims.sh` reads a backticked path +as a claim the file is present and this sentence says the opposite. The guard +missed it in `WORK_CYCLE.md` for the neighbouring reason: it reads backticked +prose, not fenced code blocks. `ClaudeReport.md`'s Round notes said "No rounds +yet" after three rounds, because `ClaudeQAPlan.md`'s after-a-round list never mentioned that section; both are fixed, the playbook 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. The diff --git a/docs/qa/ClaudeQACoverage.md b/docs/qa/ClaudeQACoverage.md index fc71c8e..2e00bef 100644 --- a/docs/qa/ClaudeQACoverage.md +++ b/docs/qa/ClaudeQACoverage.md @@ -155,10 +155,17 @@ existing is not a failure; it not existing while the gaps do is. 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 - an old API level. +- **~~No device at `minSdk`~~ — partly closed on 2026-08-18 at `0d280d5`.** The + app has now been built, installed and driven on `PeriodMinSdk26`, an API 26 + emulator: onboarding start to first forecast, the Material 3 date picker, + Today, Calendar, Insights and Settings, plus a relaunch after the emulator was + killed and cold-booted. No crash, and no `NoSuchMethodError`, `VerifyError` or + `NoClassDefFoundError` attributable to the app — the only `NoClassDefFoundError` + in logcat belongs to `com.google.android.googlequicksearchbox`. What is still + unreached at API 26: notifications and their lock-screen rendering, the + instrumented suites, and anything needing more than one cycle of history, so + fertility never became visible. Passes C, E, F, G and H have never run at this + API level. - **Physical-device coverage is undecided.** Passes F and G need a real device with a lock screen and TalkBack; which device that is has not been chosen, and an emulator is not a substitute for either. diff --git a/docs/qa/ClaudeQAPlan.md b/docs/qa/ClaudeQAPlan.md index 0ce886e..6506d4d 100644 --- a/docs/qa/ClaudeQAPlan.md +++ b/docs/qa/ClaudeQAPlan.md @@ -24,6 +24,44 @@ Review trigger: Any new user-facing surface, or a defect class that got through - Seed the cycle history deliberately. A round run against three cycles and a round run against twelve are not comparable, and the forecast is the product. +### The emulators, by name + +Rounds cite these by name, so they are defined here rather than in the round +that happened to use one. Both are Pixel 6 profiles, x86_64, no Play Store. + +| AVD | API | Why it exists | +| --- | --- | --- | +| `PeriodQA` | 36 | The everyday round. Current Android, and what Rounds 1–3 ran on. | +| `PeriodMinSdk26` | 26 | **`minSdk`.** The floor the app claims to support, and the level lint's `NewApi` findings are about — two of which were real crashes on every device below Android 14, invisible to the unit tests and to an API 36 emulator. | + +Recreate either with: + +```bash +SDK=$ANDROID_HOME +$SDK/cmdline-tools/latest/bin/sdkmanager --install "system-images;android-26;google_apis;x86_64" +$SDK/cmdline-tools/latest/bin/avdmanager create avd \ + -n PeriodMinSdk26 -k "system-images;android-26;google_apis;x86_64" -d pixel_6 +``` + +**Launch headless, and target it by serial.** Other projects on this machine keep +their own emulators running, so `adb` regularly has three devices attached and a +bare `adb shell` fails with *more than one device/emulator*. Resolve the serial +by AVD name rather than assuming `emulator-5554`: + +```bash +$SDK/emulator/emulator -avd PeriodMinSdk26 -no-window -no-audio -no-boot-anim & +D=$(adb devices | awk '/emulator-/{print $1}' \ + | while read d; do [ "$(adb -s $d emu avd name | head -1 | tr -d '\r')" \ + = PeriodMinSdk26 ] && echo $d; done) +adb -s "$D" install -r app/build/outputs/apk/debug/app-debug.apk +``` + +`-no-window` is not only for headless convenience: a windowed emulator dies with +`XIO: fatal IO error on X server ":0"` if the launching session's display goes +away, which killed one mid-round. And the debug build's application id carries a +`.debug` suffix, so it is `dev.privacyllc.period.debug` that must be launched — +`monkey -p dev.privacyllc.period` aborts with *No activities found to run*. + ## The passes Each pass gets a letter, so `ClaudeQACoverage.md` can report per pass and a