dashboard: remove the Y3R C4LL questions pane (ask/answer removal, frontend)

This commit is contained in:
damocles 2026-08-29 20:32:34 +02:00 committed by mara
commit ff0a6660aa
16 changed files with 74 additions and 680 deletions

View file

@ -246,9 +246,10 @@ hyperhive tools have their own cases and skip this path.
An `mcp__hyperhive__ask(to: "operator", ...)` row has no inline
answer form in this terminal — it renders like any other tool call.
The operator answers a pending question from the main dashboard's
own question surfacing (`dashboard/src/swarm.js` + `call.js`, the
Y3R C4LL tab), not from the per-agent page.
The dashboard's own question-surfacing UI that used to let the
operator answer from the Y3R C4LL tab is gone (hyperhive#3721); there
is currently no UI path to answer an operator-targeted `ask()` at
all.
## Dashboard side (not covered here)

View file

@ -19,8 +19,8 @@ of your time. It's a single page with exactly four tabs:
- **SW4RM** — every agent, live. This is the default tab and the one
you'll check most.
- **Y3R C4LL** — anything waiting on *you*: pending approvals and
agent questions. If an agent needs a decision from you, it's here.
- **Y3R C4LL** — anything waiting on *you*: pending approvals. If an
agent needs a decision from you, it's here.
- **P3RM1SS10NS** — what tools and system-level access each agent has.
- **SCH3DUL3S** — scheduled prompts and agent self-reminders.
@ -46,10 +46,10 @@ whether it's running, what it's currently doing (a live status pill —
and quick links (stats, screen, forge profile). Click the name to open
its terminal and watch it work in real time.
**Answer something an agent is waiting on.** Y3R C4LL is the one tab
**Approve something an agent is waiting on.** Y3R C4LL is the one tab
worth checking regularly — it's everything that needs *you*: approvals
for config changes, and questions an agent has asked and is blocked on.
The tab's count pill tells you at a glance if anything's pending.
for config changes. The tab's count pill tells you at a glance if
anything's pending.
**Approve or reject a config change.** Agent config changes (new
packages, env vars, MCP servers) go through an approval queue rather

View file

@ -172,9 +172,12 @@ from the harness-local store (same effect as `cancel_loose_end(kind:
The todos flyout is the only per-agent flyout — there is no separate
"loose-ends" or "tasks" list. There is also no inline answer form for
`ask` tool calls in this terminal: an `ask` renders like any other
tool call, and the operator answers a pending question from the
dashboard's Y3R C4LL tab instead (see
tool call (see
[`terminal-rendering.md`](../terminal-rendering.md#inline-ask-operator-answer)).
The dashboard's own Y3R C4LL questions pane that used to let the
operator answer from there is gone (hyperhive#3721) — an
operator-targeted `ask()` currently has no UI path to an answer at
all until the removal finishes or a replacement lands.
## Live view

View file

@ -20,7 +20,7 @@ from the dashboard tab strip.
standalone **C0R3** page (`/core.html`), and FL0W / L0GS / ST4TS /
S3TT1NGS / M4TR1X live on their own pages too, all reachable from the
H0M3 hub (not the tab strip). Count pills on SW4RM
(container count), Y3R C4LL (pending approvals + questions + unread
(container count), Y3R C4LL (pending approvals + unread
operator messages), and SCH3DUL3S (active schedules); S3TT1NGS has no
count.
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
@ -43,14 +43,13 @@ from the dashboard tab strip.
snapshot. Hidden when there are no warnings.
- **Browser tab title**`hyperhive // h1ve-c0re` by default; updated
to `<swarm> / <hive> // h1ve-c0re` once `hive_name` / `swarm_name`
arrive in the state snapshot. When there are pending approvals or
unanswered questions, a `(N)` prefix is prepended — `(3) pr1ma //
h1ve-c0re` — so the operator can see the call count in an unfocused
browser tab without opening the dashboard. The prefix is set on the
initial `/api/state` cold-load and updated live by
`approval_added` / `approval_resolved` / `question_added` /
`question_resolved` SSE events; it's preserved when
`hive_name` / `swarm_name` later replace the raw title.
arrive in the state snapshot. When there are pending approvals, a
`(N)` prefix is prepended — `(3) pr1ma // h1ve-c0re` — so the
operator can see the call count in an unfocused browser tab without
opening the dashboard. The prefix is set on the initial `/api/state`
cold-load and updated live by `approval_added` / `approval_resolved`
SSE events; it's preserved when `hive_name` / `swarm_name` later
replace the raw title.
The FL0W and L0GS pages use a slim header (a `← home` back-link + the
page title) rather than the dashboard tab strip — they're standalone
@ -82,9 +81,7 @@ agent is stale.
## Y3R C4LL tab
Things blocked on operator decision — approvals and questions
share a tab because they're the same concept ("something is
waiting on you").
Things blocked on operator decision — the approval queue.
**P3NDING APPR0VALS** — the queue (see "Approval card" below).
The R3QU3ST SP4WN form lives at the top of this section. A
@ -92,31 +89,6 @@ The R3QU3ST SP4WN form lives at the top of this section. A
queue and the last 30 resolved approvals (see "Approval card" for
the history row shape).
**M1ND H4S QU3STI0NS** — pending `ask` calls waiting on the
operator, with amber pulsing border. Anatomy of each card:
- **Filter chips**`all · N`, `@operator · N`, `@peer · N`,
plus one chip per participant name (`@asker · N` / `@target · N`).
Every chip shows its own count so the operator can see the
distribution at a glance. Clicking a chip narrows the visible
list; selection persists in localStorage so a tab switch doesn't
lose the filter.
- **Question card** — timestamp · asker → target · body text
(with file-path links). Operator-targeted questions (`target =
null`) show `▸ ANSW3R`; peer-targeted questions (`target =
agent`) show `⤿ 0V3RR1D3` so the operator can unblock an
agent-to-agent exchange. Questions with a `ttl_seconds` show a
`⏳ MM:SS` live countdown chip; the host-side watchdog resolves
with `answerer = "ttl-watchdog"` on expiry.
- **Answer form** — free-text textarea (Enter = submit,
Shift+Enter = newline) + optional option list (radio for
single-select, checkboxes for `multi=true`). Submit merges
selected options + free text comma-joined into a single
`answer` field. `✗ CANC3L` is a separate form so the submit
merge handler doesn't interfere.
- **◆ answ3red (N)** — collapsible `<details>` below the pending
list; shows the last 20 resolved questions with their answers.
**0PER4T0R 1NB0X** — messages agents have sent to `to="operator"` but
the operator hasn't read yet. Cold-loaded from `/api/operator-inbox` on
tab activation + page load; appended live from the broker `sent` stream
@ -570,8 +542,7 @@ The `next` column cell (`.sched-due`) carries a `data-due-at`
Unix timestamp attribute; a shared 1s ticker rewrites it
in-place showing `fmtDuration` while in the future and
`overdue X ago` once the fire time has passed — same
zero-re-render pattern as the reminder due-at labels and the
question TTL chip.
zero-re-render pattern as the reminder due-at labels.
The table's last row is a permanent inline creation row:
inputs live directly in table cells (targets as checkboxes,
@ -1156,10 +1127,9 @@ between the live queue and the last 30 resolved approvals.
## Browser notifications
Pure frontend (`Notification` API). Three signals trigger them:
Pure frontend (`Notification` API). Two signals trigger them:
- new pending approval (per id, delta on `/api/state`)
- new pending operator question (per id)
- new broker message sent `to: "operator"` (live via SSE)
The toggle controls live in the `S3TT1NGS` tab (`#settings`); see
@ -1168,7 +1138,7 @@ in `common.js::NOTIF`.
First `/api/state` after page load seeds "seen" sets without
firing — only items that arrive while the page is open count.
Per-event tags (`hyperhive:approval:<id>`, `hyperhive:question:<id>`,
Per-event tags (`hyperhive:approval:<id>`,
`hyperhive:msg:<at>:<rand>`) so distinct events stack in the OS
notification center instead of overwriting each other.
`console.debug` logs at every block point (unsupported,
@ -1203,8 +1173,12 @@ below — some endpoints aren't in it yet.
`destroy` accepts `purge=on` to also wipe state dirs.
- `POST /api/purge-tombstone/{name}` — wipe a tombstone's state dirs.
- `POST /api/answer-question/{id}` — answer a pending operator question.
No dashboard UI calls this any more (the questions pane is gone —
see hyperhive#3721); kept as long as the backend `ask`/`answer`
mechanism itself still exists.
- `POST /api/cancel-question/{id}` — cancel a pending question with
the sentinel `[cancelled]`. Same code path as a real answer.
the sentinel `[cancelled]`. Same code path as a real answer. Same
no-UI-consumer note as above.
- `POST /api/request-spawn` — queue a Spawn approval.
- `POST /api/update-all` — rebuild every stale container.
- `POST /api/rebuild-queue/{id}/cancel` — drop a `Queued` entry.
@ -1411,14 +1385,10 @@ payload):
re-renders only the approvals section.
- `question_added` (id, asker, question, options, multi,
asked_at, deadline_at, target) / `question_resolved` (id,
answer, answerer, answered_at, cancelled, target) — both
operator-targeted and peer (agent-to-agent) threads fire
these. The dashboard's questions pane surfaces both, with
filter chips (all / @operator / @peer / per-participant) and
an `0V3RR1D3` button on peer rows so the operator can
answer when an agent is stuck. The ttl watchdog fires
`question_resolved` with `answerer = "ttl-watchdog"` on
expiry.
answer, answerer, answered_at, cancelled, target) — still
fired by the backend `ask`/`answer` mechanism, but the
dashboard no longer subscribes to either kind: the questions
pane that used to surface them is gone (hyperhive#3721).
- `transient_set` (name, transient_kind, since_unix) /
`transient_cleared` (name) — lifecycle action spinners. The
client ticks the elapsed-seconds badge off `since_unix`
@ -1488,7 +1458,7 @@ payload):
`/api/state` is **only fetched on cold-load and on the few
forms that mutate non-event-derived state** (PURG3 +
meta-update, since tombstones + meta_inputs aren't event-
shaped yet). Every other section — approvals, questions,
shaped yet). Every other section — approvals,
transients, containers, operator inbox, message flow —
derives from `/api/dashboard/stream` after the initial snapshot,
maintaining its own client-side store and applying events on

View file

@ -51,8 +51,7 @@
dashboard stream carries broker `Sent` / `Delivered` (mirrored
by a forwarder task from the broker's intra-process channel)
plus mutation events (`approval_added` / `approval_resolved`,
`question_added` / `question_resolved`, `transient_set` /
`transient_cleared`). Each frame carries a `seq`. The
`transient_set` / `transient_cleared`). Each frame carries a `seq`. The
matching backfill endpoint is `GET /api/dashboard/history` (last
~200 broker messages wrapped in `{ seq, events }`) on the
dashboard and `GET /events/history` (last 2000 `LiveEvent`s
@ -233,8 +232,7 @@ where the fingerprint is `JSON.stringify({...visible fields...})`.
On each render: cache-hit rows are reused verbatim (preserving
textarea draft, checkbox state, and event listeners); only cache-miss
rows are rebuilt and inserted. Used for: containers (`containerRowCache`),
rebuild-queue entries (`rebuildQueueRowCache`), and question rows
(`questionRowCache`). The spawn-form input+focus and meta-input
rebuild-queue entries (`rebuildQueueRowCache`). The spawn-form input+focus and meta-input
checkboxes use a lighter snapshot-then-restore pattern (snapshot
before `replaceChildren`, restore after) since they are single
values rather than per-row caches.
@ -244,9 +242,12 @@ tagged with `data-restore-key="<stable-key>"` survives the
refresh. `snapshotOpenDetails()` walks managed sections before
render, `restoreOpenDetails()` re-applies after. Long-content
drill-ins (file previews, diffs, journald logs) now open in the
**side panel** (see below) rather than expanding inline, so the
only restore-keyed `<details>` left is the answered-questions
history list.
**side panel** (see below) rather than expanding inline. The
dashboard's own answered-questions history list was the only
`<details data-restore-key>` consumer and is gone (hyperhive#3721)
`snapshotOpenDetails()` / `restoreOpenDetails()` currently have
nothing to restore, kept in place for the next collapsible section
that needs it rather than ripped out along with their one caller.
**Side panel (dashboard):** long content opens in a drawer that
swipes in from the right — a singleton `#side-panel` with a