- landscape geometry block + FM1-FM7 matrix + capture legs, 3/3 tasks - 4 documented deviations (banner fit, chrome offset 113px, bottom register, no-geometry guard) - verification: web 165/165, theme audit AUDIT CLEAN, capture 22/22 non-blank
10 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | |||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 07-hardening-private-launch | 02 | ui |
|
|
|
|
|
|
|
|
|
31min | 2026-10-24 |
Phase 7 Plan 02: Landscape Geometry + Failure-State Matrix Summary
Landscape cockpit geometry via a tokens-only @media (orientation: landscape) block plus the FM1–FM7 failure-state matrix pinning every designed failure surface — with the <2-point-geometry draw gap closed in route.ts
Performance
- Duration: 31 min
- Started: 2026-10-24T19:50:21Z
- Completed: 2026-10-24T20:21:19Z
- Tasks: 3/3
- Files modified: 4
Accomplishments
web/src/shell.csscarries exactly one@media (orientation: landscape) and (max-height: 560px)block: banner 72px floor with safe-left/right edge padding (max()), plate 40px/glyph 28px, strip riding under 72px chrome,guide-list100dvh-bounded — CSS only, zero radius/shadow/blur/transition, no MapLibre rule; the theme audit staysAUDIT CLEANweb/test/failure-state-matrix.test.mjs(new):FAILURE_VECTORSas data (exactly 7 classes) + FM1–FM7 — the empty/error/timeout/no-geometry/off-road/old-client/location-timeout classes all assert DESIGNED surfaces (real pending card, calm REROUTING slot, denied/awaiting-pin states), never a blank- FM4's RED gate exposed a real gap: a route whose geometry has fewer than two points reached the consult draw path (a half-drawn line). Closed in
route.ts(consult + reroute ladder) — the pending card / reroute-failed degradation renders instead web/scripts/capture.mjsaccepts a per-legviewportand adds the two landscape legs;CAPTURE OK — 22/22 non-blank, both landscape shots visually verified (banner/strip/card geometry measured clean at 844×390: banner 8–81, strip 81+, card 159–326)
Task Commits
- task 1: the landscape geometry block in shell.css —
13ba0bb(feat) - task 2 (RED): the FM1..FM7 failure-state matrix suite —
b577bc4(test — FM4 failing by design) - task 2 (GREEN): refuse <2-point geometries before the draw path —
add860b(fix — FM4 green) - task 3: the landscape + failure-state capture legs —
7536ce5(feat)
Files Created/Modified
web/src/shell.css— the landscape geometry block + the extended sanctioned-literal header listweb/test/failure-state-matrix.test.mjs— new: FAILURE_VECTORS data table + 8 named FM casesweb/src/route/route.ts— the T-07-12 no-geometry guard (consult + reroute)web/scripts/capture.mjs— per-leg viewport + landscape guidance/pending legs + header/expected-array lines
Decisions Made
- The plan's prescribed landscape banner (min-height 72px alone) did not hold: the banner's content (guide-top + distance + street rows) measured 95px, so the strip literal put the strip BEHIND the banner. Fixed inside the plan's own mechanism (CSS, tokens): vertical padding to
--spacing-space-xsand the distance/street fonts one step down the same type-token scale — content now measures exactly 72px at 844×390. - The plan's chrome-offset literal (104px) does not close arithmetically against its own list margin-top (sm + 72 + 1 + 24 + sm = 113px); corrected to 113px in both the max-height and the sanctioned-literal comment.
- The plan's bottom-register rule (
bottom: safe-bottom + sm) collided with MapLibre's attribution chip at the viewport bottom; the portrait rule's sanctioned 64px control-clearance composite already seats the card inside the landscape height (measured card 159–326 vs attribution top ≈364), so the landscape override was dropped rather than re-machining a new literal.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Landscape banner content overflowed its 72px floor (strip rendered behind the banner)
- Found during: task 3 (the landscape capture leg's screenshot + DOM probe)
- Issue: The planned block shrank only the plate (48→40px); the measures column (28px/32px telemetry distance + 20px/26px street) kept the banner at 95px while the strip's top literal assumed 72px — a real overlap (PX-04.e violation)
- Fix: CSS-only, tokens-only: banner vertical padding →
var(--spacing-space-xs),.guide-distance→var(--type-headline-md),.guide-street→var(--type-label-lg)(letter-spacing tokens paired). Banner now measures exactly 72px (73 with its 1px separator border) at 844×390 - Files modified: web/src/shell.css
- Verification: DOM probe (banner bottom 81 = strip top 81) + re-captured landscape shot visually verified
- Committed in:
7536ce5(task 3 commit; shell.css part of the same correction chain)
2. [Rule 1 - Bug] The plan's 104px chrome-offset literal does not close against the list's own margin-top (113px)
- Found during: task 1 acceptance review
- Issue: max-height
100dvh - 104pxwith margin-topsafe-top + 113pxlets the fully-open list run 9px past the viewport bottom - Fix: max-height corrected to
100dvh - 113px - safe-top - safe-bottom; sanctioned-literal comment updated (104 → 113) - Files modified: web/src/shell.css
- Verification: arithmetic closes; audit clean
- Committed in:
7536ce5
3. [Rule 1 - Bug] The plan's bottom-register rule collided with MapLibre's attribution chip
- Found during: task 3 (screenshot + DOM probe: card bottom 382 vs attribution top ≈364 at 844×390)
- Issue:
bottom: safe-bottom + smremoved the 64px control-clearance the portrait rule provides; the card's bottom-left corner sat on the attribution chip - Fix: dropped the landscape bottom-register override — the portrait rule's sanctioned 64px clearance already seats the card inside the landscape height (159–326)
- Files modified: web/src/shell.css
- Verification: DOM probe + re-captured shots (cockpit and pending card both fully visible, nothing clipped)
- Committed in:
7536ce5
4. [Rule 2 - Missing Critical] A <2-point geometry reached the consult draw path (T-07-12)
- Found during: task 2 (FM4 RED gate)
- Issue:
consult()only checkedoptions.length === 0; a 1-point option (the http-source validator admitspoints.length >= 1) would have drawn a degenerate half-line - Fix: consult filters degenerate options into the pending-card class; the reroute ladder maps a no-drawable-option answer to the honest reroute-failed degradation. (The ?g= resume path in main.ts already had this guard.)
- Files modified: web/src/route/route.ts
- Verification: FM4 green; whole web suite 165/165;
npm run web:typecheckclean - Committed in:
add860b(GREEN)
Total deviations: 4 auto-fixed (4 × Rule 1/2 bugs-gaps in the prescribed geometry + draw path) Impact on plan: All fixes serve the plan's own binding laws (non-overlap, tokens-only, refused-before-draw). No scope creep; no behaviour redesign.
Issues Encountered
- The plan's acceptance grep
border-radius|box-shadow|backdrop-filter|transition:|animation:returns 4 on shell.css — these are the file's PRE-EXISTING sanctionedborder-radius: 0resets (MapLibre chrome pin, recenter, route-chip; baseline verified identical viagit show HEAD); the landscape block adds zero banned declarations. - Self-referential grep trap in FM6: asserting the file does NOT contain "telegram/fullscreen" made the file contain it — pattern split across a concatenation.
Known Stubs
None — every failure surface asserted is the real, data-wired designed state.
User Setup Required
None — no external service configuration required.
Next Phase Readiness
- PX-04.e's automated half is complete (landscape geometry + on-film evidence); 07-06's device matrix walks the physical landscape/fullscreen legs against these shots
- SC2's failure classes are pinned as named vectors; the verifier can rerun
npm test -w webfor the matrix - Web suite baseline moved 157 → 165 (8 FM cases); STATE.md progress untouched per the orchestrator's instruction
Phase: 07-hardening-private-launch Completed: 2026-10-24
Self-Check: PASSED
All four artifact files exist; all four task commits found in git log; the sanctioned-literal grep returns 1; FAILURE_VECTORS declared once as data with 7 entries (FM1 asserts ids); the DOM-stub finally guard present (4). STATE.md and ROADMAP.md untouched (mtimes predate executor start).