Build TV Requests under Settings #32

Merged
justinzeus merged 5 commits from fm/tv-slice7-requests into main 2026-11-05 20:06:37 +01:00
Owner

Outcome

Build household Requests under Settings and repair the measured design-review blockers against the locked prototype. Ready for scoped re-review; not a release or TV-install request.

AI-assisted (fork-internal)

Verified/pushed head: 924c90a9e0c9f7cca76def0196314fa30c3bab4f. Merged origin/main before final validation; the merged Libraries tree remains integrated. No worker-side merge or PR-status mutation.

Refs: approved Wolfskin TV spec, sections 3.5–3.6, 6.11–6.12, 7.6, 8–10 and screens/requests.json; locked Opus prototype.

Readiness geometry repair (B8)

Only the readiness item layout changed: the 26px glyph bottom aligns to the text baseline, with no flex gap. Removed the unused readinessItemGap token and regenerated Kotlin/CSS/hash artifacts; documented the natural wrapping. No shared Type, Glyph, focus/state, data or tests changed.

Firstmate decision: preserve intrinsic Roboto wrapping, two native lines rather than three reference lines. No forced Request / Download / Library+Playback grouping, font change or per-row compensation. The later baselines, shorter focused row and following-card shift are explicitly accepted font-caused differences.

Current-head B8 evidence archive · Reference / before / after 4× detail. Glyph boxes use exclusive right/bottom bounds; text distances below start at the rightmost painted pixel.

Measurement Locked reference Native 924c90a9
Request glyph [left,top,right,bottom) [1322,475,1341,489) [1322,475,1341,489) — exact
Request glyph right boundary → first text ink; painted-pixel distance 1341 → 1346; 6px 1341 → 1346; 6px
Download clock glyph y and its label baseline [515,537), baseline 538 (second line) [471,493), baseline 494 (first line, approved wrap)
Clock glyph y relative to its label baseline, inclusive −23..−2px −23..−2px — exact
Clock right boundary → first text ink; painted-pixel distance 1342 → 1346; 5px 1557 → 1561; 5px — same item geometry, different line position
Readiness line baselines 494 / 538 / 581 494 / 537; no third native line — approved font exception
Focused row full-fill y, same pixel probe 331..603, height 273px 330..559, height 230px — approved font exception

The review's nominal reference row was 332..602; the same-method table above scans x1690 with min RGB≥235, retaining full-fill edge pixels. Its measured reference bottom is 603, native 559. Both measurement definitions are stated rather than silently comparing different edges. The 43px shorter filled row explains the upward shift of following cards and the higher whole-frame diff, not a new stroke/font-size change. Request baseline 494 and both glyph-to-text distances match exactly.

Isolation: st-081/082/083/084/085/088/111 each have 0 changed pixels versus independently reviewed b8d5d8a1, after the full final capture run. B1–B7 remain fixed; B6 remains Justin-approved 3 open.

Verified B1–B7 repairs

The prior evidence at 439eea3f is historical. The independently verified B1–B7 measurements at b8d5d8a1, originals, before/after crops, reports and logs are in the prior repair evidence archive. Each crop has reference, before and after panels; 4× nearest-neighbour enlargement preserves native pixels.

Finding Repair and observed result
Actor separator colour (B1) Removed the extra 40% alpha: actor dots now equal surrounding secondary text. Abbott dot/text peak is RGB185,185,188 / RGB185,185,188, rather than the reviewed dark dot RGB86,86,91. Reference dot/text peaks are RGB196,197,202 / RGB200,201,205. Font/JPEG ink peaks are recorded, not claimed equal. Native crops.
Scoped line-box rhythm (B2) Actual CSS-sized, baseline-anchored line boxes, confined to Coming in. Four unwrapped native rows now measure 45/77/112px title/facts/stage ink bottoms from the poster top, correcting 47/80/118px; facts-to-stage is 35px, not 38. Locally registered reference rows differ by at most 1px; low-coverage glyph edges retain at most 1px differences, fully tabulated. Receipt top is native y154, correcting y156; the JPEG threshold crosses at y155. Shared typography is untouched. Native crops.
Stage glyph/label spacing (B3) Stage gap 10px remains unchanged. The later B8 repair removes readiness flex spacing entirely. Abbott label first ink is x1361, reference x1362; glyph-to-label ink gap is 15/16px because glyph side bearings differ. Native crops.
Frozen rating-chip bleed (B4) Reproduce the actual frozen CSS: surface3 dark rounded backgrounds, 12px radius, 26px mark height and the locked contain fit (.rr .rb outranks .crow img). The TMDB pill and tomato/popcorn circles are deliberately present, not classified as a source bug. Native background RGB37,37,50; reference JPEG samples span RGB37..40,35..38,48..49. Original SVGs retained; native-size contained PNGs and hashes verified. Native crops.
Settings avatar initial (B5) Settings alone passes C.muted, retaining the approved existing letter-colour parameter. The initial is no longer RGB5,5,7; st-081 lightest red-channel letter sample is RGB79,88,94 versus reference RGB81,89,100. Nav/picker defaults remain dark. Native crops.
Partial count (B6) Justin approved “3 open” for the three actually observed records. Retained that honest count; the reference “5” is an approved exception, not pending.
Loaded poster fringe (B7) Surface3 is placeholder-only; a successful loaded image has no underpaint. In the edge-aligned Shared poster transition, native pre-white minimum channel is 244, reference 243, correcting the reviewed 197 fringe. Absolute poster position differs with the approved font wrapping. Native crops.

No global font/weight adjustment or per-row compensation was used. Full numeric RGB traces, correlation anchors and glyph bounds are included; a 1px local poster-registration ambiguity is visible in the Die My Love reference measurements. These are measured residuals, not a pixel-equality claim.

Implemented behaviour

  • Replace the labelled Requests placeholder with Coming in: empty/loading/unavailable/partial/populated states, snapshot-derived Settings count, readiness expansion and stable request-id focus across refresh and title round trips. Failed, Downloading/Almost ready, Checking/Searching, Waiting, Ready order; five rows, or four with readiness expanded. Tail focus is bounded.
  • Reuse shell key/hold guards, Back ladder, root/person abandonment rules and library image loader/cache/concurrency/RGB565 policy. Shared actor records render by Shared, never by you; there is no new nav entry or second focus adapter.
  • Debug-only locked fixture projection and local posters; release supplier is honestly unavailable. No live Conductarr or Jellyfin calls in this slice’s tests, no Seerr fallback or handwritten HTTP. Foreground/30-second refresh is lifecycle-cancelled and does not re-decode the fixture on each poll.

Approved specification decisions

Ratings timing: frozen page and spec 6.12 / screen contract take precedence over the conflicting no-dwell sentence in 7.8. Uncached focus waits 350ms, moving away cancels, cached title ratings show immediately; sign-out suppresses visibility.

Font fidelity: retain platform Roboto; browser system-ui resolved to DejaVu Sans. Heading ink width is 239px reference / 194px native, ink height 43 / 42px. Source 600/650 retains the merged shell’s explicit Bold 700 mapping; 800 is unchanged. No font bundle or size/weight fudge. Host wrapping/ellipsis parity is not claimed; affected frames are identified below. This structural difference is not explained away as rasterisation.

Exit-check capture pairs

Every half is 1920×1080 at density 2.0, rendered by existing Robolectric SDK34/Roborazzi. Prototype left, current-head Compose right. All eight final pairs were inspected. Mean error uses RGB channels 0–255; >12 means max channel difference exceeds 12; sheet band is x≥1120. Prototype-only example pills are omitted by contract. Button focus scale is approved 1.05 rather than frozen 1.06. RGB565 photo decoding, JPEG quantisation and platform shadow kernels remain additional pixel-level differences.

Pair / state Mean RGB error Pixels >12 Nav mean error Sheet mean error Difference explanation
st-081 pair 4.1136 5.2693% 5.4665 1.8960 Same empty content and sheet geometry. Roboto changes heading/body widths and ink bounds; inherited Settings/nav text also differs from the browser. Settings avatar now uses the approved muted initial.
st-082 pair 9.9872 10.8726% 6.3850 15.8403 Example-stages pill omitted by contract. Roboto lets three ratings share the stage line instead of wrapping below, shifting the title block and focused row height; other titles have different widths. Five open requests match.
st-083 pair 4.8888 6.1131% 5.4721 3.7563 Same warning and recovery. Roboto changes warning/button widths. Scoped CSS line boxes place the receipt at native y154, correcting y156; reference first JPEG threshold crossing is y155. Button scale is approved 1.05 rather than prototype 1.06.
st-084 pair 4.2436 5.4489% 5.4665 2.2079 Three 96x144 skeleton thumbs and secondary Close match. Roboto changes Close width; approved button scale is 1.05 rather than prototype 1.06. Scoped sheet heading uses its actual 56px line box, not a shared typography offset.
st-085 pair 6.8417 8.2698% 6.3804 8.2910 Example-stages pill omitted. Roboto changes warning wrapping and title ellipsis. Justin explicitly approved three observed open requests instead of the reference five. Stacked native title/facts/stage ink bottoms are now 45/77/112px, not 47/80/118.
st-086 pair 12.1346 11.7714% 6.3791 20.9942 Readiness glyphs are baseline-aligned with no gap. Firstmate approved intrinsic Roboto wrapping into two lines: Request+Download, then Library+Playback. Native baselines 494/537 versus reference 494/538/581; no native third line. Full-fill row bottom is 559 versus reference 603 by the same pixel probe (review nominal 602); following cards move up with the shorter text block. No artificial grouping or font compensation.
st-088 pair 6.2167 6.6728% 5.3811 6.8224 Shared actor and Justin recipient match. Roboto fits the three ratings beside Waiting instead of below it, changing text-block position and row height.
st-111 pair 6.5605 7.0066% 5.4724 7.6210 Exact held-title request fixture. Roboto fits the full title where the browser ellipsises it and fits three ratings beside Waiting instead of below, changing text-block position and row height.

Key, data and regression proof

  • Approved nine-key path replayed from JSON through real Android key handling: launch OK plus the exact eight-key shell suffix from Home content. The independent Home hero is not claimed as an integrated end-to-end path.
  • Real shell replays cover readiness collapse/expansion, bounded tail focus, same-request Back, root abandonment, loading Close, unavailable retry, refresh-stable ids, rendered Dutch ratings and sign-out suppression.
  • Deterministic production-gate tests prove the 350ms boundary, cancellation, uncached re-entry, immediate cached return, sign-out/new data, English/Dutch formatting, offline saved data and title-cache sharing between household records. Refresh policy uses a fake clock, not sleeps/network.
  • All pre-slice tests retained; no assertion weakened. Non-Requests baseline captures st-001/002/010/021/022 are pixel-identical before/after this repair. Settings st-091 intentionally changes its initial colour.

Commands and results

Command / scenario Observed result
python3 wolfskin-design/generate_tokens.py --check Passed; approved tokens untouched, supplemental/generated artifacts agree.
sha256sum -c request-marks.sha256 in design module All six original SVGs and six regenerated PNGs passed.
make test — one final B8 run Passed: 62 design + 558 app = 620 tests, zero failures/errors/skips. BUILD SUCCESSFUL in 2m 8s. Existing tests retained.
Native Requests screenshots and reused compare script All eight dimensions/pairs measured; repair-specific geometry/RGB report and 4× crops retained.
make apk-debug — one final B8 run Passed: four debug APKs, BUILD SUCCESSFUL in 51s; packaged-branding guard passed.
Packaged fixture smoke Exact JSON and eight local posters verified in each of four debug APK ZIPs. No APK attached/distributed.

The table reports ONE final make test and ONE make apk-debug at the exact B8 head above. Prior delivery and B1–B7 gate logs remain historical evidence in the earlier archive. Maven 429 workaround used only this checkout’s approved temporary untracked Gradle init hook; removed after validation. No shared daemon, wrapper, Dockerfile or volume definition changed. Existing MPV stub/decoder limits remain: compile proof, not playback certification.

Upstream files touched

None under app/src/main. No upstream hook, destination, preference, player or manifest changed in this slice. Work remains in app/src/wolfskin, debug assets, fork tests, :wolfskin-design and feature documentation docker/README.md. LibraryImages.request accepts optional slot dimensions/model input so Requests reuses the existing image policy; previous callers retain defaults. This review repair adds only scoped Coming-in line boxes/tokens, local rendering fixes, regenerated marks and the corresponding documentation.

Not done / deployment boundary

  • Conductarr TV sign-in/authenticated production reads are outside this fixture-backed slice. Release Requests shows unavailable, never fake empty success. The generated Conductarr client remains the only permitted future network path.
  • Actual title-page integration is the independent title slice. Requests currently pushes explicitly labelled request-title/{type}/{tmdb}; title-return focus is proved, not a real title page.
  • No Home implementation, spec-source edit, device performance measurement, ADB/device interaction, install, release build/tag/asset publication, signing/explicit version change, PR merge or Actions/PR-status change.
## Outcome Build household Requests under Settings and repair the measured design-review blockers against the locked prototype. **Ready for scoped re-review; not a release or TV-install request.** AI-assisted (fork-internal) Verified/pushed head: `924c90a9e0c9f7cca76def0196314fa30c3bab4f`. Merged `origin/main` before final validation; the merged Libraries tree remains integrated. No worker-side merge or PR-status mutation. Refs: [approved Wolfskin TV spec](https://pages.justinvisser.org/wolfskin/tv-spec), sections 3.5–3.6, 6.11–6.12, 7.6, 8–10 and `screens/requests.json`; [locked Opus prototype](https://pages.justinvisser.org/wolfskin/tv-prototype-v2-opus/). ## Readiness geometry repair (B8) Only the readiness item layout changed: the 26px glyph bottom aligns to the text baseline, with **no flex gap**. Removed the unused `readinessItemGap` token and regenerated Kotlin/CSS/hash artifacts; documented the natural wrapping. No shared Type, Glyph, focus/state, data or tests changed. **Firstmate decision:** preserve intrinsic Roboto wrapping, **two native lines** rather than three reference lines. No forced Request / Download / Library+Playback grouping, font change or per-row compensation. The later baselines, shorter focused row and following-card shift are explicitly accepted font-caused differences. [Current-head B8 evidence archive](https://git.justinvisser.org/attachments/71d910ff-b852-453c-96c4-d92419b79423) · [Reference / before / after 4× detail](https://git.justinvisser.org/attachments/d337ae30-a8c4-4c6b-9d80-a22b76f336fc). Glyph boxes use **exclusive right/bottom bounds**; text distances below start at the rightmost painted pixel. | Measurement | Locked reference | Native `924c90a9` | |---|---|---| | Request glyph `[left,top,right,bottom)` | `[1322,475,1341,489)` | `[1322,475,1341,489)` — exact | | Request glyph right boundary → first text ink; painted-pixel distance | `1341 → 1346`; **6px** | `1341 → 1346`; **6px** | | Download clock glyph y and its label baseline | `[515,537)`, baseline **538** (second line) | `[471,493)`, baseline **494** (first line, approved wrap) | | Clock glyph y relative to its label baseline, inclusive | **−23..−2px** | **−23..−2px** — exact | | Clock right boundary → first text ink; painted-pixel distance | `1342 → 1346`; **5px** | `1557 → 1561`; **5px** — same item geometry, different line position | | Readiness line baselines | **494 / 538 / 581** | **494 / 537**; no third native line — approved font exception | | Focused row full-fill y, same pixel probe | **331..603**, height **273px** | **330..559**, height **230px** — approved font exception | The review's nominal reference row was **332..602**; the same-method table above scans x1690 with min RGB≥235, retaining full-fill edge pixels. Its measured reference bottom is 603, native 559. Both measurement definitions are stated rather than silently comparing different edges. The 43px shorter filled row explains the upward shift of following cards and the higher whole-frame diff, not a new stroke/font-size change. Request baseline **494** and both glyph-to-text distances match exactly. **Isolation:** st-081/082/083/084/085/088/111 each have **0 changed pixels** versus independently reviewed `b8d5d8a1`, after the full final capture run. B1–B7 remain fixed; B6 remains Justin-approved **3 open**. ## Verified B1–B7 repairs The prior evidence at `439eea3f` is historical. The independently verified B1–B7 measurements at `b8d5d8a1`, originals, before/after crops, reports and logs are in the [prior repair evidence archive](https://git.justinvisser.org/attachments/3f1baf23-9477-42c0-ade0-ee316f8fa893). Each crop has reference, before and after panels; 4× nearest-neighbour enlargement preserves native pixels. | Finding | Repair and observed result | |---|---| | Actor separator colour (B1) | Removed the extra 40% alpha: actor dots now equal surrounding secondary text. Abbott dot/text peak is **RGB185,185,188 / RGB185,185,188**, rather than the reviewed dark dot RGB86,86,91. Reference dot/text peaks are RGB196,197,202 / RGB200,201,205. Font/JPEG ink peaks are recorded, not claimed equal. [Native crops](https://git.justinvisser.org/attachments/733ae4c5-5e9f-4ddb-a9f4-033ec2bf0e1e). | | Scoped line-box rhythm (B2) | Actual CSS-sized, baseline-anchored line boxes, confined to Coming in. Four unwrapped native rows now measure **45/77/112px** title/facts/stage ink bottoms from the poster top, correcting **47/80/118px**; facts-to-stage is **35px**, not 38. Locally registered reference rows differ by at most 1px; low-coverage glyph edges retain at most 1px differences, fully tabulated. Receipt top is native **y154**, correcting y156; the JPEG threshold crosses at y155. Shared typography is untouched. [Native crops](https://git.justinvisser.org/attachments/93f6e55f-ea91-46a7-ac4f-2c1e80d56c07). | | Stage glyph/label spacing (B3) | Stage gap **10px** remains unchanged. The later B8 repair removes readiness flex spacing entirely. Abbott label first ink is x1361, reference x1362; glyph-to-label ink gap is 15/16px because glyph side bearings differ. [Native crops](https://git.justinvisser.org/attachments/e3b7d745-628c-43db-b25e-3cfe57e5b482). | | Frozen rating-chip bleed (B4) | Reproduce the actual frozen CSS: surface3 dark rounded backgrounds, 12px radius, 26px mark height and the locked contain fit (`.rr .rb` outranks `.crow img`). The TMDB pill and tomato/popcorn circles are deliberately present, not classified as a source bug. Native background RGB37,37,50; reference JPEG samples span RGB37..40,35..38,48..49. Original SVGs retained; native-size contained PNGs and hashes verified. [Native crops](https://git.justinvisser.org/attachments/6730336e-92ee-4fb5-b194-b881a32a4daf). | | Settings avatar initial (B5) | Settings alone passes `C.muted`, retaining the approved existing letter-colour parameter. The initial is no longer RGB5,5,7; st-081 lightest red-channel letter sample is RGB79,88,94 versus reference RGB81,89,100. Nav/picker defaults remain dark. [Native crops](https://git.justinvisser.org/attachments/99c7207f-a05c-4047-9bd2-198ea4caf47a). | | Partial count (B6) | **Justin approved “3 open”** for the three actually observed records. Retained that honest count; the reference “5” is an approved exception, **not pending**. | | Loaded poster fringe (B7) | Surface3 is placeholder-only; a successful loaded image has no underpaint. In the edge-aligned Shared poster transition, native pre-white minimum channel is **244**, reference **243**, correcting the reviewed **197** fringe. Absolute poster position differs with the approved font wrapping. [Native crops](https://git.justinvisser.org/attachments/a6f90ce1-461f-423e-b11c-12be890ce0d9). | No global font/weight adjustment or per-row compensation was used. Full numeric RGB traces, correlation anchors and glyph bounds are included; a 1px local poster-registration ambiguity is visible in the Die My Love reference measurements. These are measured residuals, not a pixel-equality claim. ## Implemented behaviour - Replace the labelled Requests placeholder with Coming in: empty/loading/unavailable/partial/populated states, snapshot-derived Settings count, readiness expansion and stable request-id focus across refresh and title round trips. Failed, Downloading/Almost ready, Checking/Searching, Waiting, Ready order; five rows, or four with readiness expanded. Tail focus is bounded. - Reuse shell key/hold guards, Back ladder, root/person abandonment rules and library image loader/cache/concurrency/RGB565 policy. Shared actor records render **by Shared**, never by you; there is no new nav entry or second focus adapter. - Debug-only locked fixture projection and local posters; release supplier is honestly unavailable. No live Conductarr or Jellyfin calls in this slice’s tests, no Seerr fallback or handwritten HTTP. Foreground/30-second refresh is lifecycle-cancelled and does not re-decode the fixture on each poll. ## Approved specification decisions **Ratings timing:** frozen page and spec 6.12 / screen contract take precedence over the conflicting no-dwell sentence in 7.8. Uncached focus waits **350ms**, moving away cancels, cached title ratings show immediately; sign-out suppresses visibility. **Font fidelity:** retain platform **Roboto**; browser system-ui resolved to **DejaVu Sans**. Heading ink width is **239px reference / 194px native**, ink height **43 / 42px**. Source 600/650 retains the merged shell’s explicit Bold 700 mapping; 800 is unchanged. No font bundle or size/weight fudge. **Host wrapping/ellipsis parity is not claimed**; affected frames are identified below. This structural difference is not explained away as rasterisation. ## Exit-check capture pairs Every half is **1920×1080 at density 2.0**, rendered by existing Robolectric SDK34/Roborazzi. Prototype left, current-head Compose right. All eight final pairs were inspected. Mean error uses RGB channels 0–255; >12 means max channel difference exceeds 12; sheet band is x≥1120. Prototype-only example pills are omitted by contract. Button focus scale is approved 1.05 rather than frozen 1.06. RGB565 photo decoding, JPEG quantisation and platform shadow kernels remain additional pixel-level differences. | Pair / state | Mean RGB error | Pixels >12 | Nav mean error | Sheet mean error | Difference explanation | |---|---:|---:|---:|---:|---| | [st-081 pair](https://git.justinvisser.org/attachments/b6c27d07-7867-4cc1-ac01-d5909ceccb19) | 4.1136 | 5.2693% | 5.4665 | 1.8960 | Same empty content and sheet geometry. Roboto changes heading/body widths and ink bounds; inherited Settings/nav text also differs from the browser. Settings avatar now uses the approved muted initial. | | [st-082 pair](https://git.justinvisser.org/attachments/14133f07-d769-4e8c-8f5c-9f5ed701ac55) | 9.9872 | 10.8726% | 6.3850 | 15.8403 | Example-stages pill omitted by contract. Roboto lets three ratings share the stage line instead of wrapping below, shifting the title block and focused row height; other titles have different widths. Five open requests match. | | [st-083 pair](https://git.justinvisser.org/attachments/fb64bc9f-0866-4b60-b2e5-7c3d588043f2) | 4.8888 | 6.1131% | 5.4721 | 3.7563 | Same warning and recovery. Roboto changes warning/button widths. Scoped CSS line boxes place the receipt at native y154, correcting y156; reference first JPEG threshold crossing is y155. Button scale is approved 1.05 rather than prototype 1.06. | | [st-084 pair](https://git.justinvisser.org/attachments/ea8be0a5-d04e-46e6-a8c2-45e3323aae62) | 4.2436 | 5.4489% | 5.4665 | 2.2079 | Three 96x144 skeleton thumbs and secondary Close match. Roboto changes Close width; approved button scale is 1.05 rather than prototype 1.06. Scoped sheet heading uses its actual 56px line box, not a shared typography offset. | | [st-085 pair](https://git.justinvisser.org/attachments/b313691d-ad96-44e8-b0d8-27765e69320e) | 6.8417 | 8.2698% | 6.3804 | 8.2910 | Example-stages pill omitted. Roboto changes warning wrapping and title ellipsis. Justin explicitly approved three observed open requests instead of the reference five. Stacked native title/facts/stage ink bottoms are now 45/77/112px, not 47/80/118. | | [st-086 pair](https://git.justinvisser.org/attachments/90f11123-a1fe-459d-a881-6a6e2622ea65) | 12.1346 | 11.7714% | 6.3791 | 20.9942 | Readiness glyphs are baseline-aligned with no gap. Firstmate approved intrinsic Roboto wrapping into two lines: Request+Download, then Library+Playback. Native baselines 494/537 versus reference 494/538/581; no native third line. Full-fill row bottom is 559 versus reference 603 by the same pixel probe (review nominal 602); following cards move up with the shorter text block. No artificial grouping or font compensation. | | [st-088 pair](https://git.justinvisser.org/attachments/2ad0ad5b-828d-4d85-b991-0151112ed093) | 6.2167 | 6.6728% | 5.3811 | 6.8224 | Shared actor and Justin recipient match. Roboto fits the three ratings beside Waiting instead of below it, changing text-block position and row height. | | [st-111 pair](https://git.justinvisser.org/attachments/dda137e8-3c91-4570-bb78-bad7ac9b1ac2) | 6.5605 | 7.0066% | 5.4724 | 7.6210 | Exact held-title request fixture. Roboto fits the full title where the browser ellipsises it and fits three ratings beside Waiting instead of below, changing text-block position and row height. | ## Key, data and regression proof - Approved **nine-key** path replayed from JSON through real Android key handling: launch OK plus the exact **eight-key shell suffix from Home content**. The independent Home hero is not claimed as an integrated end-to-end path. - Real shell replays cover readiness collapse/expansion, bounded tail focus, same-request Back, root abandonment, loading Close, unavailable retry, refresh-stable ids, rendered Dutch ratings and sign-out suppression. - Deterministic production-gate tests prove the 350ms boundary, cancellation, uncached re-entry, immediate cached return, sign-out/new data, English/Dutch formatting, offline saved data and title-cache sharing between household records. Refresh policy uses a fake clock, not sleeps/network. - All pre-slice tests retained; no assertion weakened. Non-Requests baseline captures st-001/002/010/021/022 are pixel-identical before/after this repair. Settings st-091 intentionally changes its initial colour. ## Commands and results | Command / scenario | Observed result | |---|---| | `python3 wolfskin-design/generate_tokens.py --check` | Passed; approved tokens untouched, supplemental/generated artifacts agree. | | `sha256sum -c request-marks.sha256` in design module | All six original SVGs and six regenerated PNGs passed. | | `make test` — **one final B8 run** | Passed: **62 design + 558 app = 620 tests**, zero failures/errors/skips. BUILD SUCCESSFUL in **2m 8s**. Existing tests retained. | | Native Requests screenshots and reused compare script | All eight dimensions/pairs measured; repair-specific geometry/RGB report and 4× crops retained. | | `make apk-debug` — **one final B8 run** | Passed: **four debug APKs**, BUILD SUCCESSFUL in **51s**; packaged-branding guard passed. | | Packaged fixture smoke | Exact JSON and eight local posters verified in each of four debug APK ZIPs. No APK attached/distributed. | The table reports ONE final `make test` and ONE `make apk-debug` at the exact B8 head above. Prior delivery and B1–B7 gate logs remain historical evidence in the earlier archive. Maven 429 workaround used only this checkout’s approved temporary untracked Gradle init hook; removed after validation. No shared daemon, wrapper, Dockerfile or volume definition changed. Existing MPV stub/decoder limits remain: compile proof, not playback certification. ## Upstream files touched **None under `app/src/main`.** No upstream hook, destination, preference, player or manifest changed in this slice. Work remains in `app/src/wolfskin`, debug assets, fork tests, `:wolfskin-design` and feature documentation `docker/README.md`. `LibraryImages.request` accepts optional slot dimensions/model input so Requests reuses the existing image policy; previous callers retain defaults. This review repair adds only scoped Coming-in line boxes/tokens, local rendering fixes, regenerated marks and the corresponding documentation. ## Not done / deployment boundary - Conductarr TV sign-in/authenticated production reads are outside this fixture-backed slice. Release Requests shows unavailable, never fake empty success. The generated Conductarr client remains the only permitted future network path. - Actual title-page integration is the independent title slice. Requests currently pushes explicitly labelled `request-title/{type}/{tmdb}`; title-return focus is proved, not a real title page. - No Home implementation, spec-source edit, device performance measurement, ADB/device interaction, install, release build/tag/asset publication, signing/explicit version change, PR merge or Actions/PR-status change.
justinzeus added 2 commits 2026-11-05 18:04:47 +01:00
Merge library slice and reuse shared image policy
Some checks failed
review/design-claude Changes requested: 7 design-parity findings (separator opacity, line-box rhythm, stage gap, mark chips, avatar, count, thumb fringe)
439eea3ff8
Author
Owner

Cross-family design review (Claude Sonnet): CHANGES REQUESTED on head 439eea3ff8b3b148844cea5fcef029e3e176d05a.

Spec fidelity, architecture and hygiene pass (nine-key path replays real shell keys, ratings dwell test fails without the dwell, Shared reads "by Shared", hold guard and back ladder correct, no upstream app/src/main file touched, no test removed). Design parity fails: measured at native resolution against the locked frames, these are not font-caused.

Blocking:

  1. Actor separator dot is drawn at 40% opacity; the locked frames draw it at full muted (ref dot 195 vs native 86, same as text 185). Every row of st-082/085/086/088/111.
  2. Text-row line-box rhythm is off: title/sub/stage baselines from thumb top are 45/77/112 in the frames vs 47/80/118 native (sub-to-stage 35 vs 38 px); sheet content also starts 1-2 px low (receipt panel 154 vs 156 in st-083).
  3. Stage glyph-to-label gap is 8 px; locked CSS is 10 px (token cites the wrong source line).
  4. Rating marks lack the dark rounded chip the frames show behind each mark (TMDB wordmark as a dark pill on the light row in st-085/086). Captain ruling needed: replicate or approve bare marks.
  5. Settings-header avatar initial is dark; frames (st-081 to st-088, st-091) show a muted light initial. Pre-existing in the shell, but inside this exit check.
  6. st-085 Settings row reads "3 open"; the frame reads "5 open". Disclosed by the lane; needs captain approval.
  7. 1 px grey hairline around white-edged poster thumbs on the focused row (st-088); none in the frame.

Non-blocking: no test covers items arriving after the sheet is opened (code handles it); second rating-mark set duplicates the library's; stage-to-ratings margin reuses the readiness glyph token.

Full report with numbers, file:line references and the measuring method: /root/.treehouse/firstmate-7bab20/2/firstmate/data/review-wolfskin-32/report.md.

**Cross-family design review (Claude Sonnet): CHANGES REQUESTED** on head `439eea3ff8b3b148844cea5fcef029e3e176d05a`. Spec fidelity, architecture and hygiene pass (nine-key path replays real shell keys, ratings dwell test fails without the dwell, Shared reads "by Shared", hold guard and back ladder correct, no upstream `app/src/main` file touched, no test removed). Design parity fails: measured at native resolution against the locked frames, these are not font-caused. Blocking: 1. Actor separator dot is drawn at 40% opacity; the locked frames draw it at full muted (ref dot 195 vs native 86, same as text 185). Every row of st-082/085/086/088/111. 2. Text-row line-box rhythm is off: title/sub/stage baselines from thumb top are 45/77/112 in the frames vs 47/80/118 native (sub-to-stage 35 vs 38 px); sheet content also starts 1-2 px low (receipt panel 154 vs 156 in st-083). 3. Stage glyph-to-label gap is 8 px; locked CSS is 10 px (token cites the wrong source line). 4. Rating marks lack the dark rounded chip the frames show behind each mark (TMDB wordmark as a dark pill on the light row in st-085/086). Captain ruling needed: replicate or approve bare marks. 5. Settings-header avatar initial is dark; frames (st-081 to st-088, st-091) show a muted light initial. Pre-existing in the shell, but inside this exit check. 6. st-085 Settings row reads "3 open"; the frame reads "5 open". Disclosed by the lane; needs captain approval. 7. 1 px grey hairline around white-edged poster thumbs on the focused row (st-088); none in the frame. Non-blocking: no test covers items arriving after the sheet is opened (code handles it); second rating-mark set duplicates the library's; stage-to-ratings margin reuses the readiness glyph token. Full report with numbers, file:line references and the measuring method: `/root/.treehouse/firstmate-7bab20/2/firstmate/data/review-wolfskin-32/report.md`.
justinzeus added 2 commits 2026-11-05 19:18:54 +01:00
Preserve contained rating marks inside dark chips
Some checks failed
review/design-claude B1-B5,B7 fixed; B8 readiness item glyph/gap geometry deviates from locked st-086
b8d5d8a124
Author
Owner

Scoped re-review of head b8d5d8a12438343c459bbf6b61df098c61c3ef2a: CHANGES REQUESTED (one new blocking deviation)

Reviewer: Claude Sonnet (cross-family). Judged by my own native-resolution (1920x1080) measurement of the refreshed pairs against the locked frames; no Gradle run. Full report: data/review-wolfskin-32-r2/report.md in the firstmate home.

Verified fixed

  • Actor separator dot (B1): native dot (185,185,188) equals the text on every row; focused inverse row dot (11,11,16) equals the row text.
  • Vertical rhythm (B2): title/facts/stage ink bottoms 45/77/112 on all four unwrapped rows vs locked 44-45/76-77/111-112 (the locked frames vary by 1 px themselves); receipt panel 154-304 identical; 086 focused row title/facts/stage 374/407/443 identical.
  • Stage glyph-to-label gap (B3): token is 10 px; glyph edge identical, label first ink 0-1 px (letter bearing).
  • Rating chips (B4): dark circles behind tomato/popcorn, TMDB dark pill, IMDb rim match side by side; contain fit undistorted (TMDB pill 44 px both).
  • Settings avatar initial (B5): light initial now matches locked st-091 and 081/088; nav/picker avatars untouched (code diff and 0 changed px on st-001/002/010/021/022).
  • Poster fringe (B7): no ring on the white-edged poster (min channel before white 244, was 197).
  • "3 open" approved by Justin, not flagged.

Blocking (new, not font-caused): B8 readiness item geometry (st-086)
In the locked prototype .crow .tx span{display:block} outranks .ready4 span{inline-flex; gap:8px}, so the readiness glyph is an inline 26 px svg on the text baseline with no gap. Locked: glyph right edge to text first ink 5-6 px, glyph raised on the baseline. Native: 12-13 px gap, glyph centred. First readiness line baseline 494 vs 492, pitch 1 px short per line (third line 581 vs 577), focused row 3 px shorter (332-602 vs 331-598). Title/facts/stage above it are identical. Same class as the rating-chip bleed. I missed it in round 1 (I wrote that readiness mapping and colours match; the geometry does not).
Fix: render each readiness item as a block line with an inline baseline-aligned 26 px glyph and no gap (pitch about 43.5 px), then re-measure with the numbers above.

Scope and hygiene: delta is 9 files, 86+/26-, all inside the Requests sheet, WolfskinTokens.Requests, one SettingsList argument and docs; no shared Type tokens/components touched; merged captures st-001/002/010/021/022 pixel-identical; st-091 changes only the avatar initial, toward the locked frame. No test deleted or weakened, nine-press path and 350 ms gate test unchanged, no public API removed. Token drift and mark checksums pass. Lane's 620 tests and four APK smokes not re-run.

Non-blocking: no test for the first-read arrival focus entry (carried), sheet content about 1 px high, facts line has no maxLines, no regression test for the new geometry.

**Scoped re-review of head `b8d5d8a12438343c459bbf6b61df098c61c3ef2a`: CHANGES REQUESTED (one new blocking deviation)** Reviewer: Claude Sonnet (cross-family). Judged by my own native-resolution (1920x1080) measurement of the refreshed pairs against the locked frames; no Gradle run. Full report: `data/review-wolfskin-32-r2/report.md` in the firstmate home. **Verified fixed** - Actor separator dot (B1): native dot (185,185,188) equals the text on every row; focused inverse row dot (11,11,16) equals the row text. - Vertical rhythm (B2): title/facts/stage ink bottoms 45/77/112 on all four unwrapped rows vs locked 44-45/76-77/111-112 (the locked frames vary by 1 px themselves); receipt panel 154-304 identical; 086 focused row title/facts/stage 374/407/443 identical. - Stage glyph-to-label gap (B3): token is 10 px; glyph edge identical, label first ink 0-1 px (letter bearing). - Rating chips (B4): dark circles behind tomato/popcorn, TMDB dark pill, IMDb rim match side by side; contain fit undistorted (TMDB pill 44 px both). - Settings avatar initial (B5): light initial now matches locked st-091 and 081/088; nav/picker avatars untouched (code diff and 0 changed px on st-001/002/010/021/022). - Poster fringe (B7): no ring on the white-edged poster (min channel before white 244, was 197). - "3 open" approved by Justin, not flagged. **Blocking (new, not font-caused): B8 readiness item geometry (st-086)** In the locked prototype `.crow .tx span{display:block}` outranks `.ready4 span{inline-flex; gap:8px}`, so the readiness glyph is an inline 26 px svg on the text baseline with no gap. Locked: glyph right edge to text first ink 5-6 px, glyph raised on the baseline. Native: 12-13 px gap, glyph centred. First readiness line baseline 494 vs 492, pitch 1 px short per line (third line 581 vs 577), focused row 3 px shorter (332-602 vs 331-598). Title/facts/stage above it are identical. Same class as the rating-chip bleed. I missed it in round 1 (I wrote that readiness mapping and colours match; the geometry does not). Fix: render each readiness item as a block line with an inline baseline-aligned 26 px glyph and no gap (pitch about 43.5 px), then re-measure with the numbers above. **Scope and hygiene**: delta is 9 files, 86+/26-, all inside the Requests sheet, `WolfskinTokens.Requests`, one `SettingsList` argument and docs; no shared Type tokens/components touched; merged captures st-001/002/010/021/022 pixel-identical; st-091 changes only the avatar initial, toward the locked frame. No test deleted or weakened, nine-press path and 350 ms gate test unchanged, no public API removed. Token drift and mark checksums pass. Lane's 620 tests and four APK smokes not re-run. Non-blocking: no test for the first-read arrival focus entry (carried), sheet content about 1 px high, facts line has no maxLines, no regression test for the new geometry.
justinzeus added 1 commit 2026-11-05 20:01:50 +01:00
Align readiness glyphs to inline text baselines
All checks were successful
review/design-claude B1-B5/B7 verified fixed by Sonnet re-review at b8d5d8a1; B8 readiness block-line replication checked by firstmate: 6-file delta, baseline/no-gap code only, st-086 pair viewed, two-line wrap is font-caused and recorded; B6 approved by Justin
924c90a9e0
justinzeus merged commit 1c77f21df3 into main 2026-11-05 20:06:37 +01:00
Sign in to join this conversation.
No reviewers
No labels
exploring
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: justinzeus/wolfskin#32
No description provided.