Both tabs were rendering Explore. They now take the whole screen, as the
reference does by hiding the unit on each: a list or a page of prose
wants the room more than the panel does. Picking a search result jumps
to Explore with that combo lit, which is the reference's data-go.
The rules text is extracted verbatim rather than retyped or reworded.
Two bugs on the way there, both worth recording:
- RULES is a template literal that itself contains template literals
inside a ${} interpolation, so the bracket scanner used for the combo
table stops at the first inner backtick. The nine title and body pairs
are matched out of the source instead, with a count assertion so drift
fails loudly rather than silently dropping a rule.
- PADMAP was read with g() but never added to the list of declarations
evaluated into the vm, so it was simply not in scope.
The extractor now asserts 9 rules and 4 pad-map rows alongside the 159
combos.
141 tests, typecheck clean. Both tabs verified by rendering them, Find
with a seeded query since headless Firefox cannot type.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vite + React + TypeScript + Vitest. No router, state library or UI kit.
The 159-row combo table is extracted from reference/index.html by
scripts/extract-reference-data.mjs rather than retyped: it balances
brackets past string literals to slice out the pure-data declarations and
evaluates them in a vm with no DOM. raw.ts and labels.ts are generated.
The extracted count matches the 159 the Phase 1 app reported on device.
Entry.id keeps the reference's format verbatim (shift>p1@S#FIX VEL),
built from the unsplit context string, so drill progress already on the
phone migrates instead of being orphaned.
The domain is pure where the reference was not: boxes go in and new
boxes come out, and the random source is injected. That is what made
card selection testable.
Two bugs found by doing so:
- pickCard returned the card just answered when random() gave exactly 0.
A zero-weight card does not move the accumulator, so "r <= 0" matched
it. The reference has this; at one draw in 2^53 it is invisible in use,
but a pinned random source hits it every time. Fixed to "r < 0".
- boxDistribution incremented through an index that
noUncheckedIndexedAccess types as possibly undefined.
65 tests. Several assert numbers observed on the device: 159 entries,
sample-mode layers of 3 / 35 / 2, a 16-card SHIFT+pads deck.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>