docs: full sync ahead of compaction + config-management overhaul
readme: manager mcp surface picks up update; operator-surface recap mentions /model + last-turn + model chip + the three collapsibles (inbox / journald / agent.nix). web-ui.md: details-restore-key story under shape; port-conflict banner mention on containers; agent.nix viewer alongside journald; notifications use per-event tags + console.debug log on block/show; deny endpoint takes note=<reason>; data-prompt / data-prompt-field generalisation noted. conventions.md: data-prompt and snapshot/restoreOpenDetails added to the async-forms section. persistence.md: operator_questions row picks up deadline_at (ttl) column with a migration note. todo.md: new 'Bugs' section captures the manager-question not-rendering issue with three suspect paths to chase. claude.md scratchpad rewritten as a clean handoff for the compaction + the upcoming config-git overhaul. flags the two-repo (proposed/ + applied/) split as the thing to reconsider.
This commit is contained in:
parent
6a2ffd521b
commit
75e7faff0c
6 changed files with 120 additions and 35 deletions
|
|
@ -30,6 +30,16 @@ and, if so, skips the refresh (defers 2s). The operator never has
|
|||
the form yanked out from under them mid-type; the update lands as
|
||||
soon as they blur.
|
||||
|
||||
**`<details>` open-state preservation:** any collapsible element
|
||||
tagged with `data-restore-key="<stable-key>"` survives the
|
||||
refresh. `snapshotOpenDetails()` walks managed sections before
|
||||
render, `restoreOpenDetails()` re-applies after. Used today for
|
||||
the journald viewer (`journal:<container>`), the agent-config
|
||||
viewer (`agent-config:<name>`), and approval diff blocks
|
||||
(`approval-diff:<id>`). Setting `.open = true` programmatically
|
||||
also fires the `toggle` event, so any lazy-fetch wired to it
|
||||
re-runs cleanly on restore.
|
||||
|
||||
Both bind their listeners with `SO_REUSEADDR` via
|
||||
`tokio::net::TcpSocket` plus a retry loop on `AddrInUse` (12 tries,
|
||||
exponential backoff capped at 2s) so an nspawn restart that races
|
||||
|
|
@ -42,6 +52,11 @@ the previous process's socket release resolves itself.
|
|||
inline "unsupported / blocked" message when applicable. Sits
|
||||
under the banner.
|
||||
2. **C0NTAINERS** — live containers with their action surface.
|
||||
Pulsing red banner at the top of this section if any two
|
||||
sub-agents hash to the same port (`port_conflicts` from
|
||||
`/api/state`): the operator must rename one of them and
|
||||
rebuild. `lifecycle::{spawn,rebuild}` also preflight this and
|
||||
refuse with a clear error message naming the conflicting agent.
|
||||
3. **K3PT ST4T3** — destroyed-but-state-kept tombstones (size +
|
||||
age + claude-creds badge). Two actions: `⊕ R3V1V3` (queues a
|
||||
Spawn approval; existing state is reused), `PURG3` (wipes
|
||||
|
|
@ -73,12 +88,16 @@ Two-line layout (`assets/app.js::renderContainers`):
|
|||
on sub-agents, `↺ R3ST4RT` + (sub-agents) `■ ST0P` when running,
|
||||
`▶ ST4RT` when stopped. Buttons dim + disable while a transient
|
||||
lifecycle action is in flight.
|
||||
- Plus a collapsible `↳ logs · <container>` `<details>` block.
|
||||
Expanding lazy-fetches journald output via `GET
|
||||
/api/journal/{name}?unit=...&lines=...` (`journalctl -M
|
||||
<container> -b --no-pager --output=short-iso`). A unit dropdown
|
||||
switches between the harness service (default) and the full
|
||||
machine journal; refresh button re-fetches.
|
||||
- Plus two collapsible `<details>` blocks:
|
||||
- `↳ logs · <container>` — lazy-fetches journald output via
|
||||
`GET /api/journal/{name}?unit=...&lines=...` (`journalctl -M
|
||||
<container> -b --no-pager --output=short-iso`). A unit
|
||||
dropdown switches between the harness service (default) and
|
||||
the full machine journal; refresh button re-fetches.
|
||||
- `↳ agent.nix · <name>` — lazy-fetches the applied config
|
||||
file via `GET /api/agent-config/{name}` (read-only mirror of
|
||||
`/var/lib/hyperhive/applied/<name>/agent.nix`). Mutating
|
||||
this still requires `request_apply_commit` + approval.
|
||||
|
||||
`↻ UPD4TE 4LL` button appears above the containers list when any
|
||||
agent is stale. Banner pulses on each broker SSE event
|
||||
|
|
@ -94,15 +113,27 @@ Pure frontend (`Notification` API). Three signals trigger them:
|
|||
|
||||
First `/api/state` after page load seeds "seen" sets without
|
||||
firing — only items that arrive while the page is open count.
|
||||
`tag: "hyperhive"` collapses bursts; click focuses the dashboard
|
||||
tab. localStorage-backed mute toggle silences without revoking
|
||||
the OS permission. Requires a secure context (HTTPS or
|
||||
localhost); on other origins the controls hide themselves.
|
||||
Per-event tags (`hyperhive:approval:<id>`, `hyperhive:question:<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,
|
||||
permission ungranted, muted) for in-browser debugging. Click
|
||||
focuses the dashboard tab. localStorage-backed mute toggle
|
||||
silences without revoking the OS permission. Requires a secure
|
||||
context (HTTPS or localhost); on other origins the controls hide
|
||||
themselves. Browsers typically suppress notifications while the
|
||||
originating tab is focused — that's a browser-level decision,
|
||||
not ours.
|
||||
|
||||
### Dashboard endpoints
|
||||
|
||||
- `POST /{approve,deny}/{id}` — approve/deny a pending approval.
|
||||
- `POST /approve/{id}` — approve a pending approval.
|
||||
- `POST /deny/{id}` (`note=<reason>`, optional) — deny a pending
|
||||
approval with an optional operator-supplied reason. The reason
|
||||
travels to the manager as `HelperEvent::ApprovalResolved.note`.
|
||||
Dashboard prompts via `window.prompt()` on click.
|
||||
- `POST /{rebuild,kill,restart,start,destroy}/{name}` — lifecycle.
|
||||
`destroy` accepts `purge=on` to also wipe state dirs.
|
||||
- `POST /purge-tombstone/{name}` — wipe a tombstone's state dirs.
|
||||
- `POST /answer-question/{id}` — answer a pending operator question.
|
||||
- `POST /cancel-question/{id}` — cancel a pending question with
|
||||
|
|
@ -111,6 +142,13 @@ localhost); on other origins the controls hide themselves.
|
|||
- `POST /update-all` — rebuild every stale container.
|
||||
- `GET /api/journal/{name}?unit=&lines=` — journalctl viewer for
|
||||
a managed container.
|
||||
- `GET /api/agent-config/{name}` — read-only view of the applied
|
||||
`agent.nix`.
|
||||
|
||||
Generalised form helpers: `form[data-confirm="…"]` pops
|
||||
`confirm()` before submit; `form[data-prompt="…"]` pops
|
||||
`prompt()` and stashes the answer in a hidden input named by
|
||||
`data-prompt-field` (default `note`).
|
||||
|
||||
## Per-agent page
|
||||
|
||||
|
|
@ -134,7 +172,9 @@ Layout, top to bottom:
|
|||
POSTs `/api/cancel`.
|
||||
- Inbox `<details>` block (collapsed): `inbox · N` — last 30
|
||||
messages addressed to this agent, fetched via
|
||||
`AgentRequest::Recent { limit: 30 }`.
|
||||
`AgentRequest::Recent { limit: 30 }`. (Separate from
|
||||
`AgentRequest::Recv { wait_seconds }` which the harness uses
|
||||
internally to long-poll the broker.)
|
||||
- Terminal-wrap: live event tail (sticky-bottom auto-scroll +
|
||||
`↓ N new` pill when not at bottom) followed by an
|
||||
operator-input textarea acting as a prompt.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue