docs: prune landed todos + refresh scratchpad + as-built terminal-rendering
todo: drop landed entries (terminal coherence pass, get_state_file defense-in-depth, self-management of loose ends, persist+cold-load ctx-badge). claude.md: - scratchpad: new just-landed entries for ctx+cost badge split, terminal coherence pass, loose_ends rename + cancel_loose_end, whoami, reminder failure persistence, path linkify, tombstones+ meta_inputs events, agent open-threads section + container pending- reminder chip + task event rendering. drops the meta-flake "just landed" — structural facts live in the file map + approvals.md, the narrative was no longer load-bearing. - file map: hive-fr0nt now lists MARKED_JS + marked.min.js + the unified prefix-column terminal.css update. - reading paths: terminal-rendering.md description matches as-built. docs/terminal-rendering.md: rewritten as as-built reference. layout contract documents the padding-left + negative text-indent prefix column + how details inherits it. row taxonomy reflects current state (notes split into .note / .note.stderr / .note.op; .sys is amber; recv tool_results default-open with markdown body via tool_use_id correlation; rich send/ask/answer renderers). new sections for renderer dispatch flow, markdown integration, fmtArgsGeneric extra-MCP fallback, dashboard msgrow text-indent reset.
This commit is contained in:
parent
2b38805c00
commit
69a3ca7469
3 changed files with 195 additions and 212 deletions
5
TODO.md
5
TODO.md
|
|
@ -18,13 +18,11 @@
|
|||
|
||||
## Dashboard
|
||||
|
||||
- ~~**Per-agent terminal coherence pass**~~ ✓ landed — unified prefix column (padding-left + negative text-indent so every row kind aligns), `<details>` summaries drop directional glyph (CSS `▸/▾` sits in prefix column instead), turn boundaries de-weighted (border-left only, no bold/margin/tint), stderr lines render orange `!`, operator-initiated notes mauve italic, catch-all `.sys` escalated to orange so unrecognised stream-json surfaces. Message-bearing tool calls (`send`/`ask`/`answer`/`recv`) render default-open with markdown bodies via vendored `marked` v4.0.2; assistant text also markdown-rendered. Extra-MCP tools get a generic args pretty-printer instead of raw JSON. See [`docs/terminal-rendering.md`](docs/terminal-rendering.md) for the as-built taxonomy.
|
||||
- **Delivered-reminder rollups**: per-agent delivered-count chip (last 24h) + histogram of attempts-vs-successes on the container row. Needs `Broker::count_delivered_reminders_since(agent, ts)` (cheap COUNT against the `reminders` table, `WHERE agent = ?1 AND sent_at >= ?2`).
|
||||
|
||||
## Security
|
||||
|
||||
- **Privsep the dashboard from the privileged daemon**: hive-c0re runs as root (it has to — `nixos-container` create / start / destroy, the meta git repo, every per-agent bind mount). The HTTP server lives in the same process, so every read-endpoint (`/api/state-file`, `/api/journal/{name}`, `/api/agent-config/{name}`) is one allow-list bug away from serving arbitrary host files. Split the architecture: keep the privileged daemon doing lifecycle + git + ipc, run the web UI as an unprivileged user that talks to the daemon over a unix socket with a narrow request surface (`ReadAgentStateFile { agent, rel_path }` etc.). The unprivileged process can't read `/etc/shadow` even if every check in `get_state_file` is bypassed — it doesn't have the bits. Container-lifecycle POSTs (`/restart`, `/destroy`, etc.) become forwarded RPCs the privileged side authorises on its terms.
|
||||
- ~~**Defense in depth on `get_state_file`**~~ ✓ landed — `resolve_state_path` (shared by `get_state_file` + `scan_validated_paths`) now: (a) walks each path component below the matched root via `symlink_metadata` and refuses outright if any is a symlink (so an agent planting `ln -s /var/lib/hyperhive/agents/other/state/secret /agents/me/state/peek` can't have its target proxied — `canonicalize` would happily resolve past the allow-list check otherwise); (b) refuses any `..` traversal below the root with a friendlier error than "escapes allow-list"; (c) refuses files whose mode isn't world-readable (`mode & 0o004 == 0`) so a 0600 file inside `state/` doesn't leak via the endpoint; (d) bundles the metadata fetch into the resolve helper so callers don't restat. New tests in `hive-c0re/src/dashboard.rs::tests` cover leaf-symlink, mid-path-symlink, `..` traversal, and plain-dir-passthrough cases.
|
||||
|
||||
## Harness Ergonomics (agent-side wishlist)
|
||||
|
||||
|
|
@ -40,7 +38,6 @@ how often the friction bites in normal use.
|
|||
into the prompt builder in `hive-ag3nt::turn.rs`. Even better: add a
|
||||
one-shot `recv_batch(max: u32)` MCP tool that returns up to `max`
|
||||
pending messages in a single round-trip.
|
||||
- ~~**Self-management of own asks + reminders**~~ ✓ landed — unified with `get_loose_ends` (renamed from `get_open_threads` per the naming pass). `LooseEnd` enum (renamed from `OpenThread`) gained a `Reminder { id, owner, message, due_at, age_seconds }` variant (sub-agent flavour filters by `owner == self`; manager unfiltered). New `mcp__hyperhive__cancel_loose_end(kind, id)` on both surfaces — `kind` is `"question"` (asker gets `[cancelled by <self>]` answer, unblocks) or `"reminder"` (hard-deleted before fire). Auth: sub-agent must own the row; manager bypasses for hive-wide cleanup. New helpers `OperatorQuestions::cancel` + `Broker::cancel_reminder_as` push the auth check down so both flavours stay aligned. Shared dispatch in `hive-c0re/src/questions.rs::handle_cancel_loose_end`. Per-agent web UI's `/api/open-threads` → `/api/loose-ends` too, with reminder-row rendering added.
|
||||
- **Optional `in_reply_to: <msg_id>` on send** — pure wire addition; no
|
||||
behavioural change. The dashboard could render conversation threads
|
||||
(already wants this for the agent-to-agent question UI in the
|
||||
|
|
@ -57,8 +54,6 @@ how often the friction bites in normal use.
|
|||
|
||||
## Harness Behaviour
|
||||
|
||||
- **Persist + cold-load current context size on the per-agent page**: the `ctx-badge` (Claude Code's bottom-right "N tokens" indicator) currently only populates after the first `TokenUsageChanged` SSE event arrives, which is the *next* turn — until then the badge is empty. Operator can't see "this agent is at 78% context" before deciding to manually compact / reset / message it. Last known token usage should be persisted (likely a small `/state/hyperhive-token-usage` blob, or a row in turn_stats already has it — pull last row's totals on cold load) and returned by `/api/state` so the badge paints with real numbers on first render.
|
||||
|
||||
- **Auto session-reset when context is large and cache is cold**: today every turn uses `--continue`, so a long-lived agent carries its entire transcript forward indefinitely. When the next turn's context is above some threshold (rough starting point: ~50% of the session limit — hive startup alone burned ~15%, so the headroom disappears fast) *and* the prompt cache is no longer warm (last turn ended past the cache TTL), it's cheaper to start fresh than to re-send the whole history uncached. Open question: drop `--continue` vs. trigger `--compact` first — needs measurement of what each actually costs (uncached re-read of N tokens vs. a compact turn's own token spend + the post-compact uncached re-read). Decision should be data-driven, not guessed. Needs: a context-size estimate per turn (turn_stats already tracks token usage), a cache-warmth heuristic (time since last turn vs. cache TTL), and a one-shot fresh-session path in `turn.rs` mirroring the existing `↻ new session` button.
|
||||
|
||||
## Bugs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue