[ui] round 3 notes
Shipped 1-4, skipped the tech panel (tech.json is still []). The honest parts: the reference factory can't ship anchor slabs so the SANITISING premise didn't hold; live pressure verification is impractical in the browser pane (paused rAF + HMR churn) so it's headless against the real sim; and I nearly reported commissionQueue as unpublished before a probe caught SIM landing it mid-round. Two contract requests (setGhostMode to kill the __remove magic string, MachineDef.accent) and a ?uidemo proposal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9f3a254d85
commit
34e8b39fed
@ -243,3 +243,123 @@ closes the last build-verb gap.
|
||||
**NEXT (suggested):** remove-by-mouse; heat/scram + SANITISING confirmation once a chain
|
||||
can be fed; commission queue UI becomes real once requests 1-2 land; tech panel when
|
||||
`tech.json` fills (still `[]`).
|
||||
|
||||
### Round 3 — 2026-07-17 — Opus 4.8
|
||||
|
||||
**SHIPPED:** Orders 1-4. Order 5 (tech panel) skipped — see BLOCKED. New: `live.test.ts`
|
||||
(real sim + real HUD), `chips.test.ts`, `hotkeys.dom.test.ts`, `fax.test.ts`. **105 UI
|
||||
tests** (was 57); full suite 238/238; `npm run check` clean.
|
||||
|
||||
1. **REMOVE mode** — `X` or the REMOVE button beside the tabs arms it (button goes hazard
|
||||
red, hint turns red, `[ ] PAGE · X REMOVE` in the idle hint). Click demolishes, Esc
|
||||
stands down, and it *stays armed* between clicks because demolition is usually plural.
|
||||
Toast: "UNIT RECLAIMED. THE FLOOR REMEMBERS." Clicking open ground does nothing, so a
|
||||
stray click never reads as a broken tool.
|
||||
2. **NEXT IN TRAY reads truth** — `snap.commissionQueue[1]`. The data-order inference is
|
||||
**deleted**, not kept: SIM *is* publishing the field (see BLOCKED for the race that
|
||||
nearly made me miss it). No queue → no peek. A fax that lies quietly is worse than one
|
||||
that says nothing.
|
||||
3. **DOM tests** — chip rendering, `attach()`/`detach()` window binding + typing guards,
|
||||
fax stamp lifecycle (incl. back-to-back stamps not clearing early), all under
|
||||
happy-dom.
|
||||
4. **Live pressure verification** — see VERIFIED.
|
||||
|
||||
**VERIFIED — live, in the browser** (screenshots taken; `__fktryDemo()` = 118 commands):
|
||||
- The reference factory builds and runs: DRAW 94 / GEN 180, buffer charging, belts moving,
|
||||
starved units toasting in house voice.
|
||||
- **REMOVE end-to-end:** armed the mode (button red, `bus._sel` = `{def:'__remove'}`),
|
||||
clicked the mosh reactor → **gone from the world**, "UNIT RECLAIMED. THE FLOOR
|
||||
REMEMBERS." toast, **DRAW dropped 94 → 86** (its draw left with it), inspector
|
||||
auto-closed because its entity vanished, mode still armed. That's the round's DoD.
|
||||
- Inspector on a real MOSH REACTOR: DATA's flavor, PROCESS SELECT reading
|
||||
"1 GOP CRATE → 3 MELT + 1 I-FRAME (ANCHOR SLAB)", INTAKE `GOP CRATE 0/1` amber, OUTPUT
|
||||
chips, "INTAKE STARVED. NOTHING IS ARRIVING."
|
||||
- Paging tabs + NEXT IN TRAY (DUST ALLOWANCE) + REMOVE all legible in one bar.
|
||||
|
||||
**VERIFIED — headless, against the REAL sim** (`live.test.ts`; boots `createSim()` +
|
||||
`createUI()` on the real `data/*.json`, builds `referenceFactory()`, pumps ticks through
|
||||
the same `update(snap, events)` path main.ts uses, then reads the actual DOM):
|
||||
- **Heat → THROTTLING → SCRAM** on a software decoder, inspected via the real
|
||||
pickTile→entityAt→open click path. Also pinned: the unit **still reads SCRAM while
|
||||
cooling back below 1.0** — the exact case `heat >= 1` got wrong, now read off
|
||||
`EntityState.scrammed` per contracts v3.
|
||||
- **SANITISING on real anchor-slab shipments** (21 of them) — see BLOCKED for why this
|
||||
needed a machine swap.
|
||||
- **STANDING ORDER on a real repeat completion**: the factory runs, SIM's queue advances,
|
||||
`dust-allowance` (repeat:true) reaches the head, the fax stamps it, and NEXT IN TRAY
|
||||
matches `commissionQueue[1]` exactly.
|
||||
- **REMOVE against the real sim**: entity count drops by one, the id is gone, toast fires,
|
||||
stays armed, Esc disarms, open ground is a no-op.
|
||||
|
||||
**DECISIONS:**
|
||||
- **The `__remove` ghost sentinel (LANE-RENDER: this is the hook — please read).** The UI
|
||||
has no Renderer reference; the only channel to the ghost is `bus.selectedBuild()`, which
|
||||
main.ts feeds to `setGhost`. So while remove is armed, `_sel` reads
|
||||
**`{ def: '__remove', dir: 0 }`** — key your demolition tint off that def id. It is safe
|
||||
because sim's place handler is `const def = defs.get(cmd.def); if (def) ...`, so main.ts's
|
||||
click-to-place fires a `place` for `__remove`, matches no machine, and does nothing; the
|
||||
real removal is dispatched by the UI. Exported as `REMOVE_DEF` from `src/ui/selection.ts`
|
||||
and pinned by a test. A magic string is not how I'd design this — CONTRACT REQUEST 1.
|
||||
- **Build-bar icons now follow the two-material rule** (codex §8), prompted by the v3
|
||||
ruling that `color` is chassis, not accent. DATA's chassis values are all desaturated
|
||||
neutrals — correct for the world, but 21 icons in `#4a4e52`/`#3f4348` is an unreadable
|
||||
grey wall. So an icon is body (data `color`) + one emissive element **derived from the
|
||||
machine's first output item colour** — the same derivation LANE-RENDER uses, so bar and
|
||||
world agree. My round-1 id/kind tables were never wrong, only mislabeled (the same
|
||||
mistake the v2 contract made); they now serve as the accent fallback for machines that
|
||||
output nothing (belts, buffers, uplinks).
|
||||
- Inspector reads `EntityState.scrammed`, not `heat >= 1`. Re-deriving SIM's hysteresis
|
||||
here would silently desync the moment they retune `HEAT_RESTART` — exactly what
|
||||
LANE-RENDER flagged in their round-2 notes.
|
||||
|
||||
**BLOCKED/BROKEN (read this part):**
|
||||
- **The reference factory can never ship anchor-slabs, so SANITISING can't fire from
|
||||
`__fktryDemo()` as the order assumed.** It recycles them on purpose — reference.ts:
|
||||
*"Recovered anchor slabs come back out of the reactor. Rather than sell them, feed the
|
||||
i-only assembler."* Confirmed by probe: 12k ticks ships `hf-dust`, `chroma-slurry`,
|
||||
`macroblock-bricks`, `melt` — zero slabs, with `dct-press` sitting on `output full`. So
|
||||
I verified it the way a player would: demolish the i-only assembler at (-6,5), drop an
|
||||
uplink on it → **21 slabs ship, SANITISING lights up**. That's what `live.test.ts` does.
|
||||
Nobody's bug; the order's premise just didn't hold.
|
||||
- **Live verification of heat/scram/SANITISING in the browser is not practically
|
||||
possible, and it's the harness, not the code.** The browser pane keeps the tab
|
||||
backgrounded (`document.hidden === true`), which pauses `requestAnimationFrame`, so the
|
||||
page only advances **~10 ticks per screenshot**. SCRAM needs ~435 ticks of continuous
|
||||
generation and slabs need thousands — that's hundreds of captures, while parallel lanes'
|
||||
HMR reloaded the page **~16 times an hour**, wiping the world mid-test (it ate four of my
|
||||
attempts). Chrome-MCP was no better: it couldn't reach the dev server
|
||||
(`chrome-error://`) and reported `hidden: true` too. Hence `live.test.ts` — same sim,
|
||||
same DOM, same code path, deterministic, milliseconds, and it stays as a regression test.
|
||||
I'd rather hand you that than a screenshot I had to fight the harness for.
|
||||
- **I nearly reported `commissionQueue` as unpublished.** My first grep for
|
||||
`snap.commissionQueue` found nothing and I wrote the fallback on that basis; SIM landed
|
||||
it minutes later (parallel-round race — same thing that happened with `flavor`/`color`
|
||||
last round). A probe against the real sim caught it. Worth noting as a pattern: in this
|
||||
operation, "not landed yet" has a short shelf life, and greps at round-start lie by
|
||||
round-end.
|
||||
- **Order 5 (tech panel) skipped.** `tech.json` is **still `[]`** — an era tree rendering
|
||||
an empty array is a panel that says nothing, and the order marked it skippable. It's
|
||||
~30 lines whenever DATA fills the file.
|
||||
- The `?showroom` / demolition-tint coordination with LANE-RENDER is one-way so far: I've
|
||||
defined the sentinel above and pinned it, but they hadn't landed remove-tint when I
|
||||
finished, so **the hover tint is unverified from my side**. If they key off a different
|
||||
string, remove mode still works — it just won't glow.
|
||||
|
||||
**CONTRACT REQUEST:**
|
||||
1. **`UIBus.setGhostMode(mode: 'build' | 'remove' | null)`** (or let `setGhost` take a
|
||||
mode) — *why:* remove-mode hover currently rides a magic def id through
|
||||
`selectedBuild()`, and main.ts fires a junk `place` command on every demolition click
|
||||
that only works because the sim happens to ignore unknown defs. It's two lanes agreeing
|
||||
on a string in a NOTES file. One typed field kills it.
|
||||
2. **`MachineDef.accent?: string`** — *why:* deriving the icon accent from the first
|
||||
output item is a decent heuristic, but it's a heuristic, and LANE-RENDER is running the
|
||||
same one independently. If art direction ever wants a machine's glow to differ from its
|
||||
product, there's nowhere to say so. (LANE-RENDER asked for this in round 2 as well.)
|
||||
|
||||
**PROPOSAL:** `?uidemo` — a URL param that runs `__fktryDemo()` on boot. Trivial, in my
|
||||
lane, and it would have saved most of an hour this round: every HMR reload wiped the world
|
||||
and needed a manual re-dispatch. Say the word.
|
||||
|
||||
**NEXT (suggested):** tech panel the moment `tech.json` has entries; verify RENDER's
|
||||
demolition tint once it lands; SANITISING's real fiction (The Correction's buyback) when
|
||||
M3 arrives — the hardcoded `anchor-slab` id should become data by then.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user