- app/fe_walk_v11.py: self-contained headless walk — stages rich /
returns-only / dead-catalog Dbs, boots the scratch server on 9455
(OPENROUTER_API_KEY unset), and verifies all ten items on the real page:
keyboard map + guards + no-scroll, tap flow + Esc chains (deck and list
paths), contain/blur computed styles, minimal rubric + debug toggle
round-trip, the 0/25 -> 25/25 counter with undos, dry messaging, fresh
pill, loud empty2 + nightly-recovery, violet bands, B1 regressions
(flip clamps, one .topcard, no-lock storm) and the full P3 loop.
- Keyboard: ArrowDown/Backspace now no-op while a sheet is open (arrows
work on the deck only — spec note); found by the walk.
- get_section: an empty composed section (fully drained catalog)
recomposes on read once pool_counts shows stock again — the nightly
import re-lights the deck without a manual forge (item 8 recovery).
Item 7: /api/stats gains fresh (actives with no swipe row — the deck's
new-pool predicate verbatim); the header pill reads 'N live · M fresh'
(new badge unchanged); old APIs without fresh render no segment.
Item 8: sections.pool_counts() answers can-the-forge-serve-anything from
the composer's own candidate SQLs (stock answer, LAST_TWO not applied)
and rides every section_state body. The FE adds #empty2 ('No more new
bikes!' + 08:30 line + undo note): shown whenever the pile/buffer drain
and pool is 0/0/0 (report masked), on a zero-item dry forge too; undo
hides it; legacy .empty untouched. UpdateUI repaints the caption per
hydrate; the stats key-set selfcheck gains fresh.
section_state now mirrors the composed recipe at body.recipe; the forge
note appends 'catalog fully reviewed' when the batch has zero fresh cards.
The FE shows the BACKLOG sentence in the report (dryCap) and in the forge
status line whenever recipe.new===0 with cards served; a non-dry forge
behaves exactly as before. No new fetch loops.
A card is decided only when a swipe event carries THIS section's id;
the lifetime swipes.action a second look wears into its section no longer
paints it as pre-decided. progress/undecided, report counts (latest
in-section event per listing) and maybe_exhaust all use the new
section_decided_ids() set; read path only, no writes. Every section_state
item carries decided_this_section; the FE counts server truth unless a
local intent is in flight, and sectDecided is clamped to sectTotal
everywhere (commit + paintSect) so the pill can never read past N/N.
Semantics note: completing a section now means striking EVERY item in it
(returns re-struck on their second look) — the exhaust selfcheck was
updated to strike all items, matching the deck's real flow. Undo-on-a-
return residual (event stays after the DELETE) is the accepted Q5 clamp-
only behavior, covered by a dedicated selfcheck case.
- prefs API accepts the new rubric_debug key (off|on), the only new runtime
write in v1.1; every section_state body now carries prefs.rubric_debug.
- fillRank renders the tank gauge + rounded % by default; the breakdown
lines, audit footer and the quiet listing-enrichment fetch run only when
the pref is on. List rows and the card face stay rubric-free (unchanged).
- Trends 'Actions' gains a 'Why breakdown: off | on' row in the setMode
style; updateSectionUI repaints it on every section hydrate.