Skip to content

The board is still not a widget: make it read the feed instead of being driven #82

Closed

Description

@aenawi

The last privileged thing on the page

Branches 1–4 of the HUD sequence are in (#77, #78, #79, #80). The board is the
one part that is still special.

hud/slots.js states the widget contract in full:

export function create({ el, feed, options }) {
  ...
  return { destroy() {} };
}

A widget gets a div, the feed, and its own options. Nothing else — no board
object, no page elements, no controller. Three widgets ship under that contract
and, since #80, all three run against a recording instead of a live lab without
a line changed, because the player offers the same on / want / status.

The board does not meet that contract. app.js builds it and drives it by
hand: setMeta, setState, probe, report, clearScratch, hold,
dimStanding, setViewInset, refreshTokens, resize, home, zoomIn — and
LabHUD.run(board, id, res, ctx) reaches into it for every set-piece. It is the
floor of the window rather than a card, and widgets.go says so at the top.

What this is

Make the board read the feed, so that it could be a widget under the same
contract as the other three.

The point is not tidiness and it is not to put the board in a dock. It is that
"driven by app.js" is the reason two pages now drive it separately. #80 added
replay-app.js, and the interesting half of that file is a second copy of the
same mapping app.js makes:

state    ->  board.setState
verdict  ->  the set-piece for its id, or probe/report as a fallback
flow     ->  board.probe
packet   ->  whatever asked to watch

Two copies, written against the same wire, that have to stay the same or a
recording stops looking like the session it recorded. That is the cost, and it
is the argument for doing this — not the cost of the board being special.

What it is not

Not publishing the twenty-five method object createBoard() returns. That
was rejected when the widget contract was designed and the reasoning has not
changed: it is the whole implementation surface of 1400 lines of coupled
three.js, and the day somebody writes against it hud/scene.js is frozen. A
privileged contract for one widget is the same mistake wearing a hat.

Not splitting hud/scene.js. It is one file on purpose.

Roughly

The seam is the mapping above, not the renderer. Something like a
hud/driver.js that takes { board, feed } and subscribes — then app.js
keeps only what is genuinely about this page (the busy guard, the rails, the
POSTs) and replay-app.js keeps only what is about a file (the transport, the
moments).

Two things that will bite, both found while building #80 and worth writing down
before anyone starts:

  • board.holding. A held set-piece frame is the answer to a question
    somebody asked, so the state poll that lands three seconds later must wait
    rather than wipe it. Both pages guard on this today; a driver has to own it.
  • set and preset draw no shot. On the live page a switch flip moves the
    board by changing the lab and letting the next state snapshot redraw it —
    the board never renders a switch as an event. A driver that played a shot per
    verdict would show something no reader ever saw.

Why it is not urgent

Nothing is broken. The board draws correctly on both pages today. This is
paying down the one asymmetry left in a seam that is otherwise honest, and the
bill only comes due when a third thing wants to drive a board.

Noted as not-in-scope at the bottom of #80.

Activity

  1. added
    enhancementNew feature or request
    control-planeThe interactive control plane — simulator and real lab
    labThe real Docker lab and its control server
    on Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    control-planeThe interactive control plane — simulator and real labenhancementNew feature or requestlabThe real Docker lab and its control server

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions