From 9f0bc9d19b4ada672cd3164e4feea79d0ed97366 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Sat, 22 Aug 2026 22:54:33 -0500 Subject: [PATCH 1/4] Correct the defect audit's status metadata, which went stale in hours R3 / #12, R12 / #21, R13 / #22. Three status claims in the audit were false against `main` at 18c53a3. The audit is read as the work queue for the ticket phase, so each correction is stated in the document rather than made quietly -- a reader who believed the old claim needs to see that it changed. R3 / #12. D5 and D7 were marked `open` and "in progress on fix/space-proxy-and-notification". Both merged hours before: b86df47 (D5) and c2e6344 (D7) are ancestors of 18c53a3 (`git merge-base --is-ancestor`), and so is the branch. Anyone working the table would have re-implemented merged work. The header count was also wrong in its own arithmetic -- "ten fixed, two in progress, one parked" covers thirteen of sixteen entries, dropping D12, D15 and D16. It now states four numbers that sum, and says the Fix column tracks `main` at a named commit so the next reader knows what it is relative to. R12 / #21. "Where the fixes live" sent the reader to `feat/defect-fixes-base`, for which `git show-ref` finds nothing -- no local ref, no remote, deleted when it merged -- and quoted 242 JVM tests. A real run on this branch gives 257 / 0 / 0 / 0 across 34 classes; the 15 missing are UnknownInputSizeTest, SpaceCheckTest and ProgressNotificationTest. The replacement names `main`, anchors the total to this commit and gives the command to re-derive it, since the number is only as fresh as the document. The same paragraph's "API 33-36 now run locally, 49 tests each" is anchored to 22c7914, the commit that measured it: androidTest is 57 `@Test` on `main`, and an unanchored total invites a reader to mistake drift for breakage. The surviving invariant -- 0 failures, 0 errors, 2 skipped, same total at every level and on the Pixel -- is stated instead. R13 / #22. D11 was marked `merged`, but 7db3200's own body says one of its four rows was deliberately skipped: "Not touched: OutputPublisher's hasSpaceFor KDoc". Still true -- nothing in OutputPublisher.kt mentions D1 -- and that row is the one place a reader of the code would learn the parked defect exists. The summary row now says "less the OutputPublisher KDoc row -- held with D1", with the reasoning at the entry. The as-found bodies are untouched throughout, including D11's own item table: corrections are carried as marked editorial notes beside them, the pattern D1's entry already uses. Gate green: ktlintCheck, detekt, lintDebug. Co-Authored-By: Claude Opus 5 (1M context) --- docs/defect-audit.md | 64 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/docs/defect-audit.md b/docs/defect-audit.md index 7ef28b2..bf91b9b 100644 --- a/docs/defect-audit.md +++ b/docs/defect-audit.md @@ -1,8 +1,11 @@ # Defect audit -**Status:** ten fixed and merged, two in progress, one parked. Fix status is per entry in the -summary table; the entry bodies below describe each defect *as found* and are deliberately not -rewritten as fixes land — this is the record of what was wrong, not a changelog. +**Status:** twelve fixed and merged, one parked, two open, one no-action. Four numbers, because +they have to sum to the sixteen entries below and the previous three did not. Fix status is per +entry in the summary table and +tracks `main`, re-checked at `18c53a3`; the entry bodies below describe each defect *as found* and +are deliberately not rewritten as fixes land — this is the record of what was wrong, not a +changelog. **Scope:** the Android-framework edge of the app, which has no JVM unit tests. **Last verified:** 2026-08-22, against `main` at `903b43c`. **Device pass:** 2026-08-22 on a physical Pixel 10 Pro XL, API 37. Four entries were driven on @@ -13,6 +16,25 @@ Instrumented baseline taken at the same time: `connectedDebugAndroidTest` on the **49 tests, 0 failures, 0 errors, 2 skipped**, no regression against the 40/0/2 recorded in `api-37-emulator-crash.md`. The 2 skips are the assumption-guarded `RealMediaBenchmark` tests. +> **Correction — 2026-08-23 (`R3 / #12`, `R12 / #21`, `R13 / #22`).** The status metadata in this +> document went stale within hours of being written, and this document is read as the work queue, +> so the corrections are stated rather than made quietly: +> +> - **D5 and D7 were marked `open`; both were already merged to `main`.** `b86df47` (D5 — +> `InputQuery` plus `hasSpaceForUnknownSize`) and `c2e6344` (D7 — `setForegroundAsync`, no direct +> `notify()` left outside a comment) are both ancestors of `18c53a3`, and +> `fix/space-proxy-and-notification`, which the old text called "in progress", is merged. +> A reader acting on the old table would have re-implemented merged work. +> - **The header count did not sum.** "Ten fixed and merged, two in progress, one parked" accounts +> for thirteen of the sixteen entries below; D12, D15 and D16 fell out of it. +> - **"Where the fixes live" named a branch with no ref and a test total 15 short.** Corrected in +> that section, with the reason it went stale. +> - **D11 was marked `merged` although one of its four rows was deliberately left undone.** Also +> corrected in the summary table; `7db3200`'s own commit body says so and this did not. +> +> The entry bodies are untouched. All 34 of their as-found citations were re-checked against +> `903b43c` and are accurate; only status metadata and claims that had become false were changed. + This is a survey, not a work order. Each entry records what is wrong, how confident we are that it is wrong, how to provoke it, and what a fix would have to decide. Acting on any of them is a separate decision, and each would be its own commit. @@ -582,6 +604,14 @@ than carried as a defect. **Severity: low · Confirmed by inspection** +*Three of the four rows below are fixed on `main` by `7db3200`; the second row is not, and the +summary table said "merged" without saying so (`R13 / #22`). `7db3200`'s own commit body records +the decision — "Not touched: `OutputPublisher`'s `hasSpaceFor` KDoc … that code belongs to a +parked branch and another change stream" — so the row is **held with D1 on +`fix/allocatable-space`**, not forgotten. It is still true today: nothing in `OutputPublisher.kt` +mentions D1, which leaves a reader of that code with no way to learn the parked defect exists. +The row itself is left as written, like every other as-found body in this file.* + | Item | Location | Note | |---|---|---| | Stale JDK claim | `README.md:111` | "Requires JDK 17+ (AGP 9 will not run on older) and the Android SDK with API 37." contradicts the Java 25 toolchain that `CLAUDE.md` documents. The same claim was already corrected once, in `CLAUDE.md`, by commit `f496291`. | @@ -781,27 +811,39 @@ out of scope for the commit that created the situation. | D4 | `publish()` can leave a truncated file at the destination | medium | not attempted | **merged** | | D6 | Rotation resets the selected tab | medium | inspection only | **merged** | | D1 | `hasSpaceFor` measures the wrong quantity | medium | **NOT reproduced — premise contradicted** | parked, see below | -| D5 | The space check can be vacuous | low-medium | **confirmed live** | open | -| D7 | Direct `notify()` on WorkManager's notification ID | low-medium | resurrection **reproduced**; undismissability unverified | open | +| D5 | The space check can be vacuous | low-medium | **confirmed live** | **merged** | +| D7 | Direct `notify()` on WorkManager's notification ID | low-medium | resurrection **reproduced**; undismissability unverified | **merged** | | D9 | Output names derived from the wrong source | low | latent | **merged** | | D10 | `CancellationException` swallowed | low | not attempted | **merged** | -| D11 | Documentation and scaffold | low | inspection only | **merged** | +| D11 | Documentation and scaffold | low | inspection only | **merged**, less the `OutputPublisher` KDoc row — held with D1 | | D12 | Two detekt findings that are wrong | n/a | inspection only | no action — correct as written | | D14 | A failed FFprobe load crashes the pick | low (rare trigger) | **confirmed on the JVM** | **merged** | | D16 | Exhausted foreground-start retries report to nobody | low-medium | found while fixing D13 | open | | D15 | An oversized suggested name fails a finished conversion | low (very narrow) | found while fixing D9 | open | -**Where the fixes live.** All merged work is on `feat/defect-fixes-base`, which now carries D2, D3, -D4, D6, D8, D9, D10, D11, D13 and D14 and gates green (**242 JVM tests, detekt 0, lint clean**, up -from 180). D5 and D7 are in progress on `fix/space-proxy-and-notification`. **D1 is parked unmerged** on +**Where the fixes live.** All twelve merged fixes — D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D13 +and D14 — are on `main`; there is no integration branch left to check out. *This paragraph used to +send the reader to `feat/defect-fixes-base`, which has no ref at all — not local, not remote, only +a reflog entry — because it was deleted when it merged, and to `fix/space-proxy-and-notification` +as still "in progress", which is merged too (its branch pointer does survive, at `c2e6344`).* The +JVM suite gates green on `main` at `18c53a3` — **257 tests, 0 failures, 0 errors, 0 skipped, +detekt 0, lint clean**, against the 242 this paragraph used to quote and the 180 before the fixes +began. That total is only as fresh as this commit; the 15 it was short are `UnknownInputSizeTest`, +`SpaceCheckTest` and `ProgressNotificationTest`. Re-derive rather than trust it: +`./gradlew :app:testDebugUnitTest`, then read `app/build/test-results/`. **D1 is parked unmerged** on `fix/allocatable-space`: the code is sound but the device pass contradicted its stated premise, so landing it needs a near-full-disk measurement first — see its entry. D15 and D16 were both found *while fixing* other entries and are recorded rather than folded in silently. Separately, `tools/local-emulator` carries the finding that **local emulators do work** — the segfault was SwiftShader's JIT against Fedora's SELinux `execheap` denial, and API 33–36 now run -locally, 49 tests each, matching the Pixel. `docs/local-emulator.md` has the backtrace and the mode -matrix, and proposes a `CLAUDE.md` correction that has not been applied. +locally, every level matching the Pixel. That branch is merged. The sweep counted **49 tests per +level at `22c7914`**, the commit that ran it — anchored here rather than left bare, because the +instrumented suite has grown since (57 `@Test` on `main`) and an unanchored total invites a reader +to mistake drift for breakage. The durable invariant is the shape, not the total: 0 failures, +0 errors, 2 skipped, and the same total at every level and on the Pixel. +`docs/local-emulator.md` has the backtrace and the mode matrix, and proposes a `CLAUDE.md` +correction that has not been applied. ### If these are fixed From 7e7f1301a758d3d30aac295576b592f718a9695f Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Sat, 22 Aug 2026 22:57:01 -0500 Subject: [PATCH 2/4] Re-date the audit's testing section, which its own follow-up falsified R14 / #23, R15 / #24. "On testing these" proposed a plan; the twelve fixes then executed it, so the section describes a state that no longer exists. It is re-dated rather than deleted -- the reasoning is why the test stack looks the way it does -- with each stale claim marked where it stands. R15 / #24, four statements, each checked against this checkout rather than against another document: - "exactly one dependency, testImplementation(libs.junit)". There are five: junit, robolectric, androidx.work.testing, the Compose BOM platform and compose-ui-test-junit4. - "a testOptions { unitTests.isIncludeAndroidResources = true } block, which this module does not currently have at all". app/build.gradle.kts:105-110. - "work-testing, compose-ui-test-junit4 and espresso-core ... have zero users." By import, work-testing has seven files under app/src/test and androidx.compose.ui.test has one. espresso-core really is still at zero, so that third is kept as the only part still standing. - The preamble's "OutputPublisher, both ViewModels, both Workers and MainActivity have no JVM unit tests at all". 25 JVM test files were added over that set, 180 tests to 257. That last one is also the derivation of CLAUDE.md's ~31% coverage figure, so the reasoning is kept verbatim and only its tense and scope are fixed: the ~31% is what those ~1,200 untested lines produced at 903b43c, it predates the new tests, and jacoco has not been re-run. The figure itself is deliberately not touched here -- re-measuring it and updating all three sites together is its own change. R14 / #23. The audit asserted in two places that instrumented tests cannot run on this host, and recorded the opposite in a third. 22c7914 is merged and tools/local-emulator/run-e2e.sh runs API 33-36 locally, so the section's impossibility argument for "pure seams plus Robolectric" is restated on the grounds that survive -- speed and determinism, which is the weaker claim and worth making honestly. D6's "it is an instrumented test, so it runs on CI, not locally" gets the same treatment, and went further the other way: the StateRestorationTester test that entry asked for is AppRootRestorationTest, which runs under Robolectric on :app:testDebugUnitTest. The API 37 rule is explicitly left standing -- that image is broken and the Pixel check before each release is unaffected. No as-found body was rewritten; D6's note is appended to its "Fix direction and test" guidance, not to its description of the defect. Gate green: ktlintCheck, detekt, lintDebug. Co-Authored-By: Claude Opus 5 (1M context) --- docs/defect-audit.md | 54 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/docs/defect-audit.md b/docs/defect-audit.md index bf91b9b..b78d4ac 100644 --- a/docs/defect-audit.md +++ b/docs/defect-audit.md @@ -6,7 +6,8 @@ entry in the summary table and tracks `main`, re-checked at `18c53a3`; the entry bodies below describe each defect *as found* and are deliberately not rewritten as fixes land — this is the record of what was wrong, not a changelog. -**Scope:** the Android-framework edge of the app, which has no JVM unit tests. +**Scope:** the Android-framework edge of the app, which had no JVM unit tests when this was +written — it has them now; see [On testing these](#on-testing-these). **Last verified:** 2026-08-22, against `main` at `903b43c`. **Device pass:** 2026-08-22 on a physical Pixel 10 Pro XL, API 37. Four entries were driven on hardware; **D1 did not reproduce and its premise is contradicted** — see its entry. Verdicts are @@ -71,9 +72,16 @@ public properties, which is the opposite of what `config/detekt/detekt.yml` says is: *"Genuine smells … are fixed in the code, not silenced."* So the linters are clean and honest, and the defects are elsewhere — in the code they cannot see -into. `OutputPublisher`, both ViewModels, both Workers and `MainActivity` have **no JVM unit tests -at all**: roughly 1,200 of ~4,000 lines of main source, and the direct explanation for the ~31% -coverage figure recorded in `CLAUDE.md`. Every entry below is in that untested set. +into. At `903b43c`, `OutputPublisher`, both ViewModels, both Workers and `MainActivity` had **no +JVM unit tests at all**: roughly 1,200 of ~4,000 lines of main source, and the direct explanation +for the ~31% coverage figure recorded in `CLAUDE.md`. Every entry below is in that untested set. + +*That derivation is why the figure was what it was, and it is kept for exactly that reason — but +the set it describes is no longer untested (`R15 / #24`). The follow-up added 25 JVM test files +over precisely those ~1,200 lines, taking the suite from 180 to 257. So the ~31% predates them and +has not been re-measured; `:app:jacocoTestReport` is the only thing that can say what it is now, +and until it is re-run the figure should be read as "the number that motivated this work", not as +current coverage.* ## How to read the confidence labels @@ -458,6 +466,12 @@ which is what makes it visibly wrong rather than merely stale. `compose-ui-test-junit4` is **already on the androidTest classpath with zero current users** — no new dependency needed. It is an instrumented test, so it runs on CI, not locally. +*Both halves of that last sentence stopped being true, and the fix went the other way (`R14 / +#23`). `compose-ui-test-junit4` is declared for the JVM source set now, and the +`StateRestorationTester` test this entry asked for is `AppRootRestorationTest`, which runs under +Robolectric on `:app:testDebugUnitTest` — not an instrumented test at all. Instrumented tests also +do run on this host now: `tools/local-emulator/run-e2e.sh`, API 33–36.* + --- ## D7 — Direct `notify()` on WorkManager's foreground notification ID @@ -861,12 +875,29 @@ through a PR, never on `main`. ### On testing these -The JVM test source set has exactly one dependency, `testImplementation(libs.junit)`. That is why -every well-tested class in this project is pure (`model/`, `FFmpegCommandBuilder`, +> **Correction — 2026-08-23 (`R14 / #23`, `R15 / #24`).** This section proposed a plan; the +> follow-up work then executed it, so four of its load-bearing statements were true at `903b43c` +> and false by `18c53a3`. It is re-dated rather than deleted, because the reasoning is *why* the +> test stack looks the way it does — but nothing below describes `main` today unless a marked note +> says so. Read the plain paragraphs as history. + +At `903b43c` the JVM test source set had exactly one dependency, `testImplementation(libs.junit)`. +That is why every well-tested class in this project is pure (`model/`, `FFmpegCommandBuilder`, `FailureOutcome`) and every untested one takes a `Context`. Instrumented tests cannot run on the development host (`CLAUDE.md`, "Instrumented tests do not run locally"), so an androidTest-only red test is not a TDD loop anyone can execute here. +*Neither sentence still holds. There are five `testImplementation` entries now — `junit`, +`robolectric`, `androidx.work.testing`, the Compose BOM platform and `compose-ui-test-junit4` — so +the one-dependency constraint that shaped this codebase no longer binds a new test. And +instrumented tests do run on this host (`R14 / #23`): `22c7914` found the cause of the segfaults, +and `tools/local-emulator/run-e2e.sh` runs the suite locally on API 33–36, recorded in +[`local-emulator.md`](local-emulator.md). The pure-seams choice below still stands, but it now +rests on speed and determinism — a JVM test is seconds against an emulator leg's minutes and a +cold boot — rather than on impossibility, which is a weaker argument and should be made honestly. +What does survive unchanged is the API 37 rule: that image is broken, so API 37 is still a +physical-Pixel check before each release.* + The approach chosen for the follow-up work is **pure seams plus Robolectric**: extract each decision into a pure function on the existing JUnit 4 stack — the pattern `work/FailureOutcome.kt` documents in its own KDoc — and add Robolectric for the file-lifecycle behaviour a pure function @@ -875,10 +906,21 @@ prerelease guard in `app/build.gradle.kts` covers only `androidx.`, `junit` and so a new group would float unguarded) and a `testOptions { unitTests.isIncludeAndroidResources = true }` block, which this module does not currently have at all. +*Executed, and both build-side predictions held. Robolectric is a pinned entry in +`libs.versions.toml`, pinned for exactly the reason given — the `componentSelection` guard does not +cover `org.robolectric`, so a `4.+` would have resolved straight to a beta — and the reasoning is +written beside it. The `testOptions` block this paragraph said the module "does not currently have +at all" is in `app/build.gradle.kts` today.* + Worth knowing before adding anything: **`androidx.work:work-testing`, `compose-ui-test-junit4` and `espresso-core` are already declared and have zero users.** `TestListenableWorkerBuilder` and `createComposeRule` are available on the androidTest classpath today with no build change. +*Two of the three have users now — and on the JVM source set, not the instrumented one: +`androidx.work.testing` is imported by seven files under `app/src/test`, and +`androidx.compose.ui.test` by one (`AppRootRestorationTest`). **`espresso-core` is still at zero**, +so that third of the sentence is the only part still standing.* + ## Not covered here - **The API 37 emulator crash** — fully documented in [`api-37-emulator-crash.md`](api-37-emulator-crash.md). From 01cbc948888ebbeb4b7e39ce234f238fe2ad96eb Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Sat, 22 Aug 2026 22:58:16 -0500 Subject: [PATCH 3/4] Say what the FFmpeg format tests have actually been run against R18 / #27. The front-page status line said the FFmpeg format tests "have been written but not yet executed on a device". They have been executed, repeatedly and green, and this is the one line a contributor uses to decide whether the FFmpeg path is trustworthy -- understating it costs more than a stale detail elsewhere would. FFmpegEngineTest's nine format tests -- mp3, gif, matroska, flac, wav, opus, H.264, H.265, and the one asserting a failure surfaces as an exception rather than a silent empty file -- were present at every commit cited below, checked by counting @Test in that file at each: - Physical Pixel 10 Pro XL, API 37, 2026-08-21 at edd6385: 40 / 0 / 0 / 2. - The audit's own Pixel pass, 2026-08-22: 49 / 0 / 0 / 2. - Four local emulator levels, API 33-36, 2026-08-22 at 22c7914: 49 / 0 / 0 / 2 each. Zero failures in all of them, and the two skips are RealMediaBenchmark's assumption-guarded tests, not these. CI's e2e matrix in status_check.yml covers API 33-36 and the workflow triggers on pull_request against main, so "on every pull request" is checked rather than assumed. The replacement names the runs instead of a count, since a total is the part that goes stale -- androidTest has moved 40 to 49 to 57 in a few days. It also keeps the API 37 caveat visible: no CI row, so that level stays a manual Pixel check before each release. Held, not decided here: whether a front-page status line should carry a verification claim at all. Fixing what it says is separable from deciding what it should be for. Gate green: ktlintCheck, detekt, lintDebug. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6f1ae20..18516d2 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,19 @@ compression, audio extraction and conversion, GIF and frame export, and file mer Android 13+ (API 33). Built with Jetpack Compose and Material 3. > **Status: working, unreleased.** Both conversion engines, the router, the background -> job queue and the join flow are implemented and building. The FFmpeg format tests have -> been written but not yet executed on a device. +> job queue and the join flow are implemented and building. The FFmpeg format tests run +> green on a physical Pixel 10 Pro XL (API 37) and on local emulators at API 33–36, and +> CI runs the instrumented suite at API 33–36 on every pull request. + +*Correction (`R18 / #27`): this line used to say the FFmpeg format tests had "been written but not +yet executed on a device". That was true when written and stopped being true at the first device +pass, which nobody came back to update — so the one line a contributor uses to decide whether the +FFmpeg path is trustworthy understated its own evidence. The nine format tests in +`FFmpegEngineTest` were in every one of those runs, all of which came back with zero failures; +they are recorded under "Verified on real API 37 hardware" in +[`docs/api-37-emulator-crash.md`](docs/api-37-emulator-crash.md) and "The sweep, run" in +[`docs/local-emulator.md`](docs/local-emulator.md). API 37 has no CI row, because that emulator +image is broken, so it stays a manual Pixel check before each release.* ## Licensing at a glance From 614af3564736f505164fb6d8b8802abc223962a1 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Sat, 22 Aug 2026 23:01:08 -0500 Subject: [PATCH 4/4] Hold the corrections themselves to the standard they impose Three defects in the three preceding commits, found on review. A commit set whose subject is stale dates and inferred status cannot carry either. Dates. Both correction blocks were stamped 2026-08-23. The commits are dated 2026-08-22, as is every other date in these two files and the review that produced them -- a day in the future, in the one place a reader checks to see how fresh a correction is. Corrected to the commit date, and the D6 note now carries one too. Coherence. The Status line was changed to say fix status "tracks main, re-checked at 18c53a3" while "Last verified: 2026-08-22, against main at 903b43c" stood two lines below it, unchanged. A reader would take the whole document as anchored to 903b43c -- exactly the failure being corrected. The two anchors now say what each covers and that they move independently: the as-found bodies are frozen at 903b43c, the status is not. Inferred count. "detekt 0, lint clean" was carried over from the old text on the strength of a BUILD SUCCESSFUL, which means "nothing above threshold", not "nothing found" -- and this project deliberately keeps a real lint finding visible (`informational += "UsableSpace"`), so "clean" was wrong as well as unmeasured. Read off the reports instead: detekt.xml has zero elements, lint-results-debug.txt says 0 errors, 0 warnings, 1 hint. Stated that way, which is also the convention the audit's own opening table already uses. README's correction note is tightened from nine lines to six. It sits on the first screen and nothing load-bearing is dropped. Gate green: ktlintCheck, detekt, lintDebug. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 14 ++++++-------- docs/defect-audit.md | 25 ++++++++++++++----------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 18516d2..7171ff0 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,13 @@ Android 13+ (API 33). Built with Jetpack Compose and Material 3. > green on a physical Pixel 10 Pro XL (API 37) and on local emulators at API 33–36, and > CI runs the instrumented suite at API 33–36 on every pull request. -*Correction (`R18 / #27`): this line used to say the FFmpeg format tests had "been written but not -yet executed on a device". That was true when written and stopped being true at the first device -pass, which nobody came back to update — so the one line a contributor uses to decide whether the -FFmpeg path is trustworthy understated its own evidence. The nine format tests in -`FFmpegEngineTest` were in every one of those runs, all of which came back with zero failures; -they are recorded under "Verified on real API 37 hardware" in +*Correction (`R18 / #27`, 2026-08-22): this line used to say the FFmpeg format tests had "been +written but not yet executed on a device" — true when written, false from the first device pass, +and never updated. `FFmpegEngineTest`'s nine format tests were in every run named above and none +of them failed; the runs are recorded under "Verified on real API 37 hardware" in [`docs/api-37-emulator-crash.md`](docs/api-37-emulator-crash.md) and "The sweep, run" in -[`docs/local-emulator.md`](docs/local-emulator.md). API 37 has no CI row, because that emulator -image is broken, so it stays a manual Pixel check before each release.* +[`docs/local-emulator.md`](docs/local-emulator.md). API 37 has no CI row — that emulator image is +broken — so it stays a manual Pixel check before each release.* ## Licensing at a glance diff --git a/docs/defect-audit.md b/docs/defect-audit.md index b78d4ac..394d46e 100644 --- a/docs/defect-audit.md +++ b/docs/defect-audit.md @@ -2,13 +2,14 @@ **Status:** twelve fixed and merged, one parked, two open, one no-action. Four numbers, because they have to sum to the sixteen entries below and the previous three did not. Fix status is per -entry in the summary table and -tracks `main`, re-checked at `18c53a3`; the entry bodies below describe each defect *as found* and -are deliberately not rewritten as fixes land — this is the record of what was wrong, not a -changelog. +entry in the summary table and tracks `main`, re-checked at `18c53a3`; the entry bodies below +describe each defect *as found* and are deliberately not rewritten as fixes land — this is the +record of what was wrong, not a changelog. **Scope:** the Android-framework edge of the app, which had no JVM unit tests when this was written — it has them now; see [On testing these](#on-testing-these). -**Last verified:** 2026-08-22, against `main` at `903b43c`. +**Last verified:** as-found evidence 2026-08-22, against `main` at `903b43c`; fix status +re-checked against `main` at `18c53a3`. The two anchors move independently — the bodies are +frozen, the status is not. **Device pass:** 2026-08-22 on a physical Pixel 10 Pro XL, API 37. Four entries were driven on hardware; **D1 did not reproduce and its premise is contradicted** — see its entry. Verdicts are marked per entry. Everything unmarked is still inspection only. @@ -17,7 +18,7 @@ Instrumented baseline taken at the same time: `connectedDebugAndroidTest` on the **49 tests, 0 failures, 0 errors, 2 skipped**, no regression against the 40/0/2 recorded in `api-37-emulator-crash.md`. The 2 skips are the assumption-guarded `RealMediaBenchmark` tests. -> **Correction — 2026-08-23 (`R3 / #12`, `R12 / #21`, `R13 / #22`).** The status metadata in this +> **Correction — 2026-08-22 (`R3 / #12`, `R12 / #21`, `R13 / #22`).** The status metadata in this > document went stale within hours of being written, and this document is read as the work queue, > so the corrections are stated rather than made quietly: > @@ -467,7 +468,7 @@ which is what makes it visibly wrong rather than merely stale. new dependency needed. It is an instrumented test, so it runs on CI, not locally. *Both halves of that last sentence stopped being true, and the fix went the other way (`R14 / -#23`). `compose-ui-test-junit4` is declared for the JVM source set now, and the +#23`, 2026-08-22). `compose-ui-test-junit4` is declared for the JVM source set now, and the `StateRestorationTester` test this entry asked for is `AppRootRestorationTest`, which runs under Robolectric on `:app:testDebugUnitTest` — not an instrumented test at all. Instrumented tests also do run on this host now: `tools/local-emulator/run-e2e.sh`, API 33–36.* @@ -840,9 +841,11 @@ and D14 — are on `main`; there is no integration branch left to check out. *Th send the reader to `feat/defect-fixes-base`, which has no ref at all — not local, not remote, only a reflog entry — because it was deleted when it merged, and to `fix/space-proxy-and-notification` as still "in progress", which is merged too (its branch pointer does survive, at `c2e6344`).* The -JVM suite gates green on `main` at `18c53a3` — **257 tests, 0 failures, 0 errors, 0 skipped, -detekt 0, lint clean**, against the 242 this paragraph used to quote and the 180 before the fixes -began. That total is only as fresh as this commit; the 15 it was short are `UnknownInputSizeTest`, +JVM suite gates green on `main` at `18c53a3` — **257 tests, 0 failures, 0 errors, 0 skipped**, +with detekt reporting 0 findings and lint `0 errors, 0 warnings, 1 hint` (the deferred +`UsableSpace` one, kept informational on purpose), against the 242 this paragraph used to quote +and the 180 before the fixes began. That total is only as fresh as this commit; the 15 it was +short are `UnknownInputSizeTest`, `SpaceCheckTest` and `ProgressNotificationTest`. Re-derive rather than trust it: `./gradlew :app:testDebugUnitTest`, then read `app/build/test-results/`. **D1 is parked unmerged** on `fix/allocatable-space`: the code is sound but the device pass contradicted its stated premise, so @@ -875,7 +878,7 @@ through a PR, never on `main`. ### On testing these -> **Correction — 2026-08-23 (`R14 / #23`, `R15 / #24`).** This section proposed a plan; the +> **Correction — 2026-08-22 (`R14 / #23`, `R15 / #24`).** This section proposed a plan; the > follow-up work then executed it, so four of its load-bearing statements were true at `903b43c` > and false by `18c53a3`. It is re-dated rather than deleted, because the reasoning is *why* the > test stack looks the way it does — but nothing below describes `main` today unless a marked note