From e1206fea78e88067f1c7964b7ff500166b71a68b Mon Sep 17 00:00:00 2001 From: type-two Date: Fri, 17 Jul 2026 16:16:02 +1000 Subject: [PATCH] [ui] round 1 notes Shipped/verified list, and the honest parts: click-to-inspect is blocked on reaching renderer.pickTile, 12 of 21 machines have no hotkey, and the lane has no DOM test env. Four contract requests (pickTile, MachineDef .color, MachineDef.flavor, jsdom) and a build-bar paging proposal. Co-Authored-By: Claude Opus 4.8 --- fktry/lanes/LANE-UI.md | 87 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/fktry/lanes/LANE-UI.md b/fktry/lanes/LANE-UI.md index 0c31e02..e401822 100644 --- a/fktry/lanes/LANE-UI.md +++ b/fktry/lanes/LANE-UI.md @@ -63,3 +63,90 @@ NOTES written. ### Round N — YYYY-MM-DD — [your model] SHIPPED: / DECISIONS: / BLOCKED/BROKEN: / CONTRACT REQUEST: / PROPOSAL: / NEXT: ``` + +### Round 1 — 2026-07-17 — Opus 4.8 + +**SHIPPED:** All five ordered surfaces, in `src/ui/**`, verified in a browser (screenshots +taken of each). Modules: `index.ts` (root/wiring), `style.ts` (injected CSS), `voice.ts` +(all player-facing copy), `hotkeys.ts` (the keymap, one file as ordered), `buildbar.ts`, +`topstrip.ts`, `inspector.ts`, `fax.ts`, `toasts.ts`, `chips.ts` (shared item chip), +`selection.ts` (writes `bus._sel`), `palette.ts`, `pick.ts`, `dom.ts`, `fixture.ts` (dev). + +1. Build bar — one button per machine, hotkeys 1-9, R rotates, Esc/right-click clears, + selected button goes hot magenta, hint line shows facing + verbs. +2. Top strip — bandwidth meter (cyan → amber ≥85% → red + flashing BROWNOUT over 100%), + buffer, shipped ticker + per-item chips, TICK / HALTED. +3. Inspector — name, codex flavor, INTAKE/OUTPUT chips w/ live buffers, process bar, + heat readout w/ THROTTLING, jam reason in amber. Esc or X closes. +4. Commission fax — fax-paper card under THE SCREEN, wants as chips w/ `1/1` progress, + reward line, and a FAX SENT rubber stamp on `commissionDone`. +5. Toasts — max 4, 6s TTL, colored per event kind, house voice. + +**VERIFIED:** `npm run check` clean; `npm test` 70/70 (other lanes' suites). Dev server on +:8151 (8150 was another lane's session). Confirmed with own eyes: hotkey 1 → `bus._sel` +`{seam-extractor,0}`; R → dir 1 → 2; Esc → null; TAB → inspector paints SEAM EXTRACTOR +with flavor + MDAT ORE chip + process bar; brownout → red border/BROWNOUT/buffer 0 + both +toasts; FAX SENT stamp + its toast; pointer fall-through (`#ui` computes `pointer-events: +none`, empty world hits CANVAS, panels are solid). No console errors. + +**DECISIONS:** +- All player-facing strings live in `voice.ts` so the OSHA-deadpan register stays in one + place and isn't re-invented per panel. +- The UI keeps its own flattened `roster` (pick.ts) instead of holding the snapshot: + CONTRACTS says buffers may be reused between snapshots, and pointer/key handlers fire + *between* frames. The backing array is reused so 500 entities don't allocate per frame. +- Esc is overloaded deliberately: drops the pending build first, closes the inspector + second — dropping the tool is what a player expects from the first press. + +**BLOCKED/BROKEN (read this part):** +- **Click-to-inspect does not work.** `ui.init(root, data, bus)` never sees the Renderer, + and `UIBus` has only `dispatch`/`selectedBuild` — so the UI cannot reach + `renderer.pickTile`, which is the only thing that knows the camera. LANE-RENDER has a + working `pickTile` this round; I just can't call it. `pick.ts` opportunistically probes + `window.__fktryRenderer.pickTile` (nobody sets it) and otherwise falls back to **TAB + cycles the unit manifest**, which is how the inspector is reachable with no console + today. Tile→entity hit-testing (incl. footprint rotation) is written and ready; it is + one contract line away from working. See CONTRACT REQUEST 1. +- **LANE-DATA shipped 21 machines; hotkeys only cover 9.** Slots 10-21 are click-only, + and that includes MOSH REACTOR, DECODE ASIC and SCREEN UPLINK — three of the seven M1 + chain machines. The M1 chain is fully placeable by *mouse*, and 1-9 works, but "the M1 + chain on hotkeys" is not literally true. The bar now wraps to 3 rows so nothing is off + the viewport (it ran off both edges at 21). See PROPOSAL. +- **No DOM tests for `src/ui`.** No `jsdom`/`happy-dom` installed and I may not touch root + config, so this lane has zero unit tests — everything above was verified by hand in the + browser. See CONTRACT REQUEST 4. +- `?uifixture` is dev scaffolding I wrote (`fixture.ts`) because the sim stub reported an + empty world at the time — a fake snapshot on a wall clock so every surface could be seen + working. It is inert without the query param and dispatches nothing. LANE-SIM is real + now; this can be deleted once the real sim can be driven to a brownout by hand. +- Harness note, not a bug: the browser-automation `key: space` delivers an empty + `event.key`, so pause could only be exercised via a dispatched `' '` KeyboardEvent + (works: HALTED renders) and via `dispatch({setPaused})` (works). Real spacebar sends + `' '` per spec; the handler matches that. + +**CONTRACT REQUEST:** +1. **`UIBus.pickTile(clientX, clientY): Vec2 | null`** (or pass the `Renderer` to + `ui.init`) — *why:* without it the inspector cannot be opened by clicking a machine, + which is the core interaction of order #3. Renderer already implements it; only the + plumbing is missing. This is my only real blocker. +2. **`MachineDef.color: string`** — *why:* `ItemDef` has `color`, `MachineDef` doesn't, so + the build bar has nothing data-driven to tint icons with. LANE-RENDER's orders say to + tint placeholder boxes "per codex color" — same gap. Right now `palette.ts` and their + renderer each hand-maintain a color table, which is how the build bar and the world end + up disagreeing about what a quantizer looks like. Data should own it once. +3. **`MachineDef.flavor: string`** (codex one-liner) — *why:* orders told me to hard-code + a lookup; I did (`voice.ts`), but only 7 of 21 machines have one and the other 14 fall + back to generic text. This is LANE-DATA's material, not mine. +4. **`jsdom` (or `happy-dom`) devDependency + `environment: 'jsdom'`** — *why:* the UI lane + currently cannot write a single test. Chips/roster/footprint/selection logic are all + pure and testable the moment there's a DOM env. + +**PROPOSAL:** build bar paging — group the 21 machines into kind tabs (EXTRACT / +LOGISTICS / REFINE / POWER / SHIP), `[`/`]` to page, 1-9 within the active page. Makes +every machine hotkey-reachable and scales as LANE-DATA keeps adding. Not done this round: +the orders said "one button per machine, hotkeys 1-9" and redesigning the bar unasked is +exactly what MASTERPLAN says not to do. Say the word and it's a small round-2 change. + +**NEXT (suggested):** wire click-to-inspect the moment request 1 lands and delete the TAB +fallback; recipe picker in the inspector (`setRecipe` exists in Command and has no UI); +build bar paging; tech/research panel once `tech.json` is populated (it's `[]`).