Skip to content

Clear the strict audit: test-file shapes, Android recaptures, JDK floor - #11

Merged
jaredcosulich merged 4 commits into
mainfrom
chore/recapture-android-scenarios
Aug 11, 2026
Merged

Clear the strict audit: test-file shapes, Android recaptures, JDK floor#11
jaredcosulich merged 4 commits into
mainfrom
chore/recapture-android-scenarios

Conversation

@jaredcosulich

Copy link
Copy Markdown
Collaborator

Takes the strict audit from 152 findings to 0 and produces the first clean full finalize, which is what main's red Merge-readiness gates check has been waiting on.

The dominant blocker was a false positive

99 of the 152 findings were SOURCE_TEST_FILE_MATCHED_BY_NO_RUNNER, naming every non-test source file in the repo (32 Kotlin + 67 Swift) as "a test file no runner executes". None contain a single test.

The cause is in the invariant, not this repo. It derives its test-file recognizer by discarding every directory segment of each testFilePattern and keeping the basename:

**/Tests/**/*.swift          ->  *.swift
android/**/src/test/**/*.kt  ->  *.kt

Both of this project's test conventions are directory-scoped (SwiftPM Tests/, Gradle src/test/), so both collapse to bare extensions and match everything. The guard against over-broad shapes only rejects a basename that is entirely wildcard, so it catches tests/** but not **/Tests/**/*.swift. It reproduces identically on the production channel, so it is not a dev-build regression.

Setting audit.testFileShapes explicitly replaces that derivation. This is a declaration of the project's real convention, not a suppression - a genuinely unrun test file matching either shape is still reported. Verified it covers all 17 real test files with no gaps.

Commits

Commit Change
badd86c testFileShapes + capture-script sync + 23 glossarySkip entries + registered defaultContentInsets
9f360c2 Recaptured all 26 Android screenshots
005141f Corrected the declared JDK floor 17 -> 21
b09ebc0 Finalize state

The screenshots were genuinely stale

The Android goldens were 16 days older than their source and predated the edge-to-edge / API 36 work in #8. All 26 shifted by 5.26-5.55% - a tight uniform band consistent with a systematic inset change.

Captured on codeyam_pixel (pixel_6, API 34, 1080x2400 @ 420dpi), animations disabled. API 34 is representative because the app opts in explicitly via AndroidX enableEdgeToEdge, which applies from API 21 rather than relying on API 35's unconditional enforcement.

The first attempt captured a "System UI isn't responding" ANR dialog overlaying the app - the emulator had booted while a Gradle build saturated the host. That frame was discarded, the emulator cold-restarted, and every capture re-verified. All 26 were scanned for the dialog signature (a bright band spanning ~87% of frame width); the widest bright row in the set is 59.3%, which is the hero numeral.

Also fixed along the way

Unregistered tests from #8. The four CounterScreenInsetsTest cases - the edge-to-edge tests - were never added to the test registry, and blocked Phase 2 as RUNNER_HAS_UNREGISTERED_TEST. Now registered with descriptions of what each asserts.

The declared JDK floor was wrong. stack.json claimed "Java 17+" while CI has required 21 since #8 (Paparazzi 2.0.0-alpha05 is a JDK 21 artifact; 1.3.5 cannot compile against compileSdk 36). A fresh clone provisioned from stack.json installs 17 and then fails the first Android build with nothing pointing at the cause.

Verification

Full suite green: 298 tests, 0 failures. session-finalize passes all five phases; screenshot coverage reports 0 stale / 0 missing. Pushed with no deferred-finalize override.

Known remaining

One non-blocking advisory: ne--os-neutral-privacy-policy was archived by a hollow commit.

The upstream basename_shape bug is unfixed and will hit any client repo with directory-scoped test conventions. A second latent false-positive source sits next to it: matching_test_files uses raw glob::glob, which does not brace-expand, so a pattern like **/*_{test,spec}.kt would light up every matching file the same way.

🤖 Generated with Claude Code

https://claude.ai/code/session_0164CaGthrJAHNbacwgkRcLv

jaredcosulich and others added 4 commits August 11, 2026 14:06
Cuts the strict audit from 152 findings to 26.

The dominant blocker was 99 SOURCE_TEST_FILE_MATCHED_BY_NO_RUNNER findings
naming every non-test source file in the repo (32 Kotlin + 67 Swift) as "a
test file no runner executes". None of them contain a single test.

Root cause is in the invariant, not this repo's config. It derives its
test-file recognizer by discarding every directory segment of each
testFilePattern and keeping only the basename, so a pattern scoped by
directory collapses to a bare extension and then matches every source file
of that language. Both of this project's test conventions are
directory-scoped (SwiftPM Tests/, Gradle src/test/), so both collapse. The
guard against over-broad shapes only rejects a basename that is entirely
wildcard, which catches a bare directory pattern but not a directory-scoped
one ending in an extension.

Setting audit.testFileShapes explicitly replaces that derivation. The two
shapes cover all 17 real test files with no gaps - every test in this repo
is named *Test.kt or *Tests.swift. This is a declaration of the project's
actual convention, not a suppression: a genuinely unrun test file matching
either shape is still reported.

Also in this pass:
- sync-capture-scripts, clearing 3 CAPTURE_SCRIPT_SOURCE_DRIFT findings
- 23 glossarySkip entries for helpers the tooling refresh added to
  .claude/hooks/editor-pretool-hook.py, matching the 25 entries already
  recorded for that same file
- registered defaultContentInsets (CounterScreen.kt), real app code from
  the edge-to-edge work in #8, covered by CounterScreenInsetsTest.kt

Remaining: 26 AGED_STALE_SCREENSHOTS (Android, genuinely stale since #8)
and 1 non-blocking plan advisory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0164CaGthrJAHNbacwgkRcLv
…edge

The Android goldens were 16 days older than their source and predated the
edge-to-edge / API 36 work that landed in #8. Recaptured all 26 against the
current build so they show what the app actually renders today.

Every scenario shifted by 5.26-5.55% of pixels - a tight, uniform band
consistent with a systematic inset change rather than per-screen churn,
which is what enableEdgeToEdge plus the systemBars/displayCutout inset
padding in CounterScreen should produce.

Captured on the codeyam_pixel AVD (pixel_6, API 34, 1080x2400 @ 420dpi)
with animations disabled. API 34 is representative here because the app
opts in explicitly via AndroidX enableEdgeToEdge, which applies from API 21
rather than depending on the unconditional enforcement added in API 35.

Verification: the first attempt captured a "System UI isn't responding"
ANR dialog overlaying the app - the emulator had booted while a Gradle
build saturated the host, and SystemUI never recovered. That frame was
discarded, the emulator cold-restarted on an idle host, and every capture
re-verified. All 26 were then scanned for the dialog signature (a bright
band spanning ~87% of the frame width); the widest bright row across the
set is 59.3%, which is the hero numeral, so none carry the artifact.

Clears all 26 AGED_STALE_SCREENSHOTS findings. The strict audit is now
clean; one non-blocking plan advisory remains.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0164CaGthrJAHNbacwgkRcLv
The Android build has required JDK 21 since #8: Paparazzi 2.0.0-alpha05 is
a JDK 21 artifact, and the app is on alpha05 because 1.3.5 cannot compile
against compileSdk 36 (cashapp/paparazzi#1877). ci.yml already sets up
JDK 21 and says so; stack.json was left behind claiming 17.

The gap is not cosmetic - stack.json is what the setup flow reads, so a
fresh clone provisioned per its instructions installs 17 and then fails
the first Android build with "Run this build using a Java 21 or newer
JVM", with nothing pointing at the real cause. That is exactly what
happened on this machine.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0164CaGthrJAHNbacwgkRcLv
@jaredcosulich
jaredcosulich merged commit 3578233 into main Aug 11, 2026
3 checks passed
@jaredcosulich
jaredcosulich deleted the chore/recapture-android-scenarios branch August 11, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant