tabs.js + docs: drop rebuild-queue cookies (#712 batch 10)

#437 (multi-step progress on rebuild_queue entries — closed) ×2:
in tabs.js current-step comment + in docs/web-ui.md prose
referencing the phase annotation.

#501 (PR — merged for #437) ×1: paired with #437 in the same
tabs.js current-step comment.

#575 (X button to cancel pending builds — closed) ×2: in tabs.js
cancel-form comment + in docs/web-ui.md cancel-button prose.

#436 (route approval execution through rebuild_queue — closed)
×1 in docs/web-ui.md: scrubbed the parenthetical "; #436" next
to the approval source-chip description (small freebie since I
was editing that paragraph anyway). The approval-as-source-chip
is the implementation of #436; the cookie was just history.

Pre-scanned docs for matching cookies; caught all 3 doc cookies
in the same PR.
This commit is contained in:
iris 2026-05-31 14:16:30 +02:00
commit 68c2b3284e
2 changed files with 24 additions and 26 deletions

View file

@ -264,21 +264,20 @@ shows a state glyph (`⏸` queued / `▶` running / `✔` done /
`✖` failed / `⊘` cancelled), kind glyph + verb (`↻ rebuild`, `✖` failed / `⊘` cancelled), kind glyph + verb (`↻ rebuild`,
`◆ meta_update`, `✨ spawn`, `🗑 destroy`), agent name, source `◆ meta_update`, `✨ spawn`, `🗑 destroy`), agent name, source
chip (`manual | meta_update | auto_update | crash_recover | approval` chip (`manual | meta_update | auto_update | crash_recover | approval`
— green for operator-approved config changes; #436), — green for operator-approved config changes), timing, and an
timing, and an optional reason / error. Meta-update cascade optional reason / error. Meta-update cascade rebuilds nest under
rebuilds nest under their parent entry (`parent_id` grouping; their parent entry (`parent_id` grouping; `rqe-child` CSS class).
`rqe-child` CSS class). Dedup: re-enqueueing a still-queued op Dedup: re-enqueueing a still-queued op for the same agent
for the same agent collapses into the existing entry. Running collapses into the existing entry. Running entries tick elapsed
entries tick elapsed seconds live, and when the worker has seconds live, and when the worker has annotated the current phase
annotated the current phase (#437) a cyan `↳ <step>` sub-line a cyan `↳ <step>` sub-line appears under the main row showing the
appears under the main row showing the in-flight step name in-flight step name (e.g. `↳ meta prepare_deploy``↳ nixos-container update`
(e.g. `↳ meta prepare_deploy``↳ nixos-container update` `↳ finalize deploy`). Terminal transitions clear `step` on the
`↳ finalize deploy`). Terminal transitions clear `step` on the
backend so Done / Failed rows don't render stale labels. backend so Done / Failed rows don't render stale labels.
Queued entries carry a `✗` cancel button on the right edge Queued entries carry a `✗` cancel button on the right edge;
(#575); running / done / failed / cancelled entries don't show running / done / failed / cancelled entries don't show it — the
it — the backend refuses cancellation for non-`Queued` rows backend refuses cancellation for non-`Queued` rows anyway
anyway (`POST /api/rebuild-queue/{id}/cancel`). Successful (`POST /api/rebuild-queue/{id}/cancel`). Successful
cancel flips the row to `⊘ cancelled` via the next cancel flips the row to `⊘ cancelled` via the next
`rebuild_queue_changed` snapshot. `rebuild_queue_changed` snapshot.
Cold-loaded from `/api/state.rebuild_queue`; live updates via Cold-loaded from `/api/state.rebuild_queue`; live updates via

View file

@ -1931,8 +1931,8 @@ window.marked = marked;
const r = entry.reason.split('\n')[0]; const r = entry.reason.split('\n')[0];
li.append(' ', el('span', { class: 'rqe-reason', title: entry.reason }, '— ' + truncate(r, 60))); li.append(' ', el('span', { class: 'rqe-reason', title: entry.reason }, '— ' + truncate(r, 60)));
} }
// Current step (#437 / #501): backend annotates the in-flight // Current step: backend annotates the in-flight phase on
// phase on `running` entries — sub-line below the main row so the // `running` entries — sub-line below the main row so the
// operator can see "what's happening right now" inside a long // operator can see "what's happening right now" inside a long
// build. Terminal transitions clear `step` on the backend so this // build. Terminal transitions clear `step` on the backend so this
// doesn't render stale labels on Done / Failed rows. // doesn't render stale labels on Done / Failed rows.
@ -1943,16 +1943,15 @@ window.marked = marked;
if (entry.error) { if (entry.error) {
li.append(el('pre', { class: 'rqe-error', title: entry.error }, truncate(entry.error, 200))); li.append(el('pre', { class: 'rqe-error', title: entry.error }, truncate(entry.error, 200)));
} }
// #575: cancel-X for queued entries. Backend // Cancel-X for queued entries. Backend
// `POST /api/rebuild-queue/{id}/cancel` is already implemented // `POST /api/rebuild-queue/{id}/cancel` refuses Running /
// (refuses Running / terminal entries); we surface it only on // terminal entries, so we surface it only on `queued` rows here
// `queued` rows here so the operator never sees a dead button. // — the operator never sees a dead button. Uses the same
// Uses the same `data-async` form + `data-confirm` pattern as the // `data-async` form + `data-confirm` pattern as the reminder
// reminder cancel, so the global async-form handler takes care // cancel, so the global async-form handler takes care of POST +
// of POST + spinner + error toast. A successful cancel flips // spinner + error toast. A successful cancel flips `state` from
// `state` from `queued` → `cancelled` via the live // `queued` → `cancelled` via the live RebuildQueueChanged
// RebuildQueueChanged snapshot and the row re-renders without // snapshot and the row re-renders without this button.
// this button.
if (entry.state === 'queued') { if (entry.state === 'queued') {
const cancelForm = el('form', { const cancelForm = el('form', {
method: 'POST', method: 'POST',