tabs.js: scrub #398/#432 cookies from container-card render path (#712 batch 4)

Seven cookies removed across the container-card rendering code (4
#398, 3 #432). All point at existing docs/web-ui.md::Container row
prose (rebuild_queue building badge, stopped-container state
clearing). Each comment shrinks to either a short docs ref or just
drops the cookie where the substantive content already explains
itself.

Net ±0 lines in tabs.js (rewrites are similar length); the win is
each comment now reads as 'what this code does' rather than 'why
PR #N decided this'. tabs.js is now at 48 #NNN refs (down from
55 at start of this batch, 73 at start of the milestone).

refs #712, builds on #722 + #724 + #728
This commit is contained in:
iris 2026-05-31 12:35:08 +02:00
commit 4c30b52e48

View file

@ -217,17 +217,18 @@ window.marked = marked;
function applyRebuildQueueChanged(ev) { function applyRebuildQueueChanged(ev) {
rebuildQueueState = (ev.queue || []).slice(); rebuildQueueState = (ev.queue || []).slice();
renderRebuildQueueFromState(); renderRebuildQueueFromState();
// Container cards surface in-flight rebuild / meta-update ops as // Re-render the SW4RM tab so newly-queued / newly-running
// a "building..." badge (#398) — re-render the SW4RM tab so // rebuild-queue ops light up the right card with a building…
// newly-queued / newly-running ops light up the right card, // badge, and finished ops fall back to the regular state badges.
// and finished ops fall back to the regular state badges. // See docs/web-ui.md::Container row for the badge taxonomy.
renderContainersFromState(); renderContainersFromState();
} }
// Map from agent name → highest-priority in-flight queue entry // Map from agent name → highest-priority in-flight queue entry
// (`running` beats `queued`). Used by the container row renderer // (`running` beats `queued`). Used by the container row renderer
// to surface "building..." / "meta-updating..." badges on the // to surface "building..." / "meta-updating..." badges on the
// SW4RM tab when an op is still in the rebuild queue but no // SW4RM tab when an op is still in the rebuild queue but no
// operator-initiated transient is set (#398). // operator-initiated transient is set — see docs/web-ui.md::Container
// row for the badge cross-reference between SW4RM and SYST3M.
function inFlightOpsByAgent() { function inFlightOpsByAgent() {
const out = new Map(); const out = new Map();
for (const e of rebuildQueueState) { for (const e of rebuildQueueState) {
@ -477,22 +478,20 @@ window.marked = marked;
const hostname = (s && s.hostname) || window.location.hostname; const hostname = (s && s.hostname) || window.location.hostname;
const ul = el('ul', { class: 'containers' }); const ul = el('ul', { class: 'containers' });
const tree = buildAgentTree(containers); const tree = buildAgentTree(containers);
// In-flight rebuild / meta-update / destroy ops per agent name. // In-flight rebuild / meta-update / destroy ops per agent name —
// Surface them as "building..." style badges on the container // see docs/web-ui.md::Container row for the building… badge
// card when no operator-initiated transient already covers the // rationale (covers the SYST3M-shows-rebuild-but-SW4RM-shows-stopped
// row (#398). Mara: the SW4RM tab showed an agent as stopped // gap when no operator transient is set).
// while SYST3M showed an active rebuild; cross-reference fixes
// that.
const inFlight = inFlightOpsByAgent(); const inFlight = inFlightOpsByAgent();
for (const node of tree) { for (const node of tree) {
const c = node.container; const c = node.container;
const url = `http://${hostname}:${c.port}/`; const url = `http://${hostname}:${c.port}/`;
// Pending state is overlaid from the transient store first // Pending state is overlaid from the transient store first
// (operator-initiated spawn/destroy/rebuild — covers the // (operator-initiated spawn/destroy/rebuild — covers the
// create+start window where the container literally isn't up // create+start window when the container literally isn't up
// yet), then from the rebuild_queue (#398 — covers in-flight // yet), then from the rebuild_queue (covers worker-driven ops
// ops the worker is running even if no transient was set). // even if no transient was set). `ContainerStateChanged`
// `ContainerStateChanged` doesn't carry either signal. // doesn't carry either signal.
const transientKind = transientsState.get(c.name)?.kind || null; const transientKind = transientsState.get(c.name)?.kind || null;
const op = !transientKind ? inFlight.get(c.name) : null; const op = !transientKind ? inFlight.get(c.name) : null;
const pending = transientKind const pending = transientKind
@ -565,8 +564,8 @@ window.marked = marked;
iconImg.src = '/favicon.svg'; iconImg.src = '/favicon.svg';
}); });
} else { } else {
// Container stopped (#432) — skip the doomed `${url}icon` fetch // Container stopped — skip the doomed `${url}icon` fetch and
// and go straight to the dimmed hyperhive mark. Avoids a noisy // go straight to the dimmed hyperhive mark. Avoids a noisy
// failed request in the console + the brief broken-image flash. // failed request in the console + the brief broken-image flash.
icon.classList.add('icon-unreachable'); icon.classList.add('icon-unreachable');
iconImg.src = '/favicon.svg'; iconImg.src = '/favicon.svg';
@ -618,9 +617,10 @@ window.marked = marked;
// (start / stop / restart / rebuild is in progress). Otherwise, // (start / stop / restart / rebuild is in progress). Otherwise,
// when the container is stopped, surface a single `■ not // when the container is stopped, surface a single `■ not
// running` badge; the backend has already cleared rate_limited / // running` badge; the backend has already cleared rate_limited /
// needs_login / ctx_tokens / status_text in that case (#432) so // needs_login / ctx_tokens / status_text in that case (see
// the rest of the chain is a no-op for stopped containers — but // docs/web-ui.md::Container row) so the rest of the chain is a
// we still want SOME badge there so the row doesn't look empty. // no-op for stopped containers — but we still want SOME badge
// there so the row doesn't look empty.
if (pending) { if (pending) {
head.append(el('span', { class: 'pending-state' }, head.append(el('span', { class: 'pending-state' },
el('span', { class: 'spinner' }, '◐'), ' ', pending + '…')); el('span', { class: 'spinner' }, '◐'), ' ', pending + '…'));
@ -681,9 +681,9 @@ window.marked = marked;
// ── agent status text ───────────────────────────────────────── // ── agent status text ─────────────────────────────────────────
// Self-reported status (via set_status MCP tool) — only fresh // Self-reported status (via set_status MCP tool) — only fresh
// while the harness is up. The backend already clears // while the harness is up. The backend already clears
// `status_text` on stopped containers (#432) so we can render // `status_text` on stopped containers (docs/web-ui.md::Container
// unconditionally here: a stopped container simply has no // row) so we can render unconditionally here: a stopped
// `status_text` and skips this block naturally. // container simply has no `status_text` and skips naturally.
if (c.status_text) { if (c.status_text) {
const nowUnix = Math.floor(Date.now() / 1000); const nowUnix = Math.floor(Date.now() / 1000);
const ageStr = c.status_set_at != null const ageStr = c.status_set_at != null