The schedule pause/resume button (added in PR #2053) was missing from
the dashboard.md SCH3DUL3S tab docs. The action column listed only three
actions (fire-now, edit, cancel); the pause/resume toggle was undocumented.
Add the full action-column breakdown with the pause/resume semantics:
- paused rows show a 'paused' badge in the next column
- sorted middle bucket (after active, before cancelled)
- fire-now button is disabled while paused
- routes to /api/schedules/{id}/pause or /resume
Two operator-visible strings and one code comment still referenced 'the
manager' in the approval card UI:
- init_config card description: 'manager customises agent.nix before
spawn' -> 'submitting agent customises agent.nix before spawn'
- deny form data-prompt: 'sent to manager' -> 'sent to submitter'
(the deny note goes to the ApprovalResolved submitter, not a fixed
manager role)
- code comment: 'surfaced to the manager via' -> 'surfaced to the
submitting agent via'
- builds.html meta text: 'manager learns each outcome' -> 'the
submitting agent learns each outcome'
The 'manager' role is no longer structural — root-ness is topological.
Any agent with the approvals tool group can submit; the note/event routes
to the submitter.
The QueueKind enum has graceful_stop, start, and stop variants but the
dashboard QUEUE_KIND_GLYPH map only covered rebuild/meta_update/spawn/
destroy/restart/startup_sweep/perm_change — the three missing kinds
rendered as '?' in the build queue UI.
This became visible with the deferred start-after-rebuild change: a fast-lane
Start entry now appears as a child of its Rebuild parent, but showed the
fallback '?' glyph.
Glyphs assigned: graceful_stop=⏹, start=▶, stop=■.
Also update the dashboard.md kind-glyph list to include all nine kinds and
note that deferred start-after-rebuild entries also use parent_id grouping.
The human-readable matrix MCP reference was missing three behaviours
documented only in the MCP server instructions string:
- send_file / download_file tools (issues 1829, 1830)
- [file:]/[image:]/[audio:]/[video:] attachment markers in read_room (issue 1830)
- unread guard: send_message, send_dm, send_file, send_reply all
reject if the room has unread messages (issue 1828)
- send_redact (omitted from the tool list entirely)
Add all four to docs/tools/matrix.md to match the MCP server
instructions added in the previous commit.
The MCP server instructions string omitted three behaviours added in
earlier PRs, leaving agents without context on them:
- send_file / download_file tools (#1829, #1830)
- [file:]/[image:]/[audio:]/[video:] attachment markers in read_room (#1830)
- unread guard: send_message, send_dm, send_file, send_reply all
reject if the room has unread messages; read_room + mark_read
are required first (#1828)
Closes#1828. Closes#1829. Closes#1830.
fix(dashboard): update 'view queue' link to /builds.html
The build queue moved to its own /builds.html page. The queue-summary
'view queue →' link in tabs.js still pointed at /core.html, so clicking
it landed on the wrong page.
fix(broker): filter agent inbox to unread (acked_at IS NULL)
recent_for was returning all messages regardless of ack state, so the
agent inbox showed everything even after 'mark all read'. Now filters
to acked_at IS NULL — mirroring exactly what mark_all_read drains —
so the inbox empties on reload after the operator drains it.
When a tool call fails, claude wraps the result text in
<tool_use_error>...</tool_use_error> XML tags. The terminal was
displaying these raw, producing output like:
'<tool_use_error>File has not been read yet.</tool_use_error>'
Fix renderToolResult in app.js:
- Check c.is_error on the tool_result content block.
- Strip the <tool_use_error>...</tool_use_error> wrapper from the text.
- Render error results with a '✗' prefix under '.tool-result.error'
(flat, ≤120c) or '.tool-result-block.error' (<details>, longer text).
Add .live .tool-result.error { color: var(--red); } to terminal.css
so error results are visually distinct (red, same as turn-end-fail).
Update terminal-rendering.md row taxonomy to document the two new
error row classes.
Closes#2104.
mode_of mapped .nix to hash-mode (# only); nix also supports /* */ block
comments, so a long one would slip past. Split .nix into its own 'nix' mode
that handles BOTH # line comments and /* */ blocks. .sh stays hash (no block
comments in sh). Verified: tree still 6 offenders (no nix block offenders), and
a 33-line nix /* */ block is now caught.
Flags any contiguous comment block longer than 30 lines — the threshold
above which a why/impl-notes block should move to docs/ rather than live
in-code (the #2077 rubric, made self-enforcing).
- scripts/check-comment-blocks.sh: git+awk, mirrors check-issue-refs.sh's
capture-output shape (robust to xargs batching). Handles # line comments
(nix/sh), // line comments (rs/js/ts), and /* */ (rs/js/ts/css) + <!-- -->
(html) block comments. Blank separates line-comment blocks; a blank inside
a /* */ / <!-- --> block stays part of it. lint:allow-long-comment escape
hatch. Threshold is a tunable constant.
- ci.yml: own 'comment-block lint' job, kept OUT of required checks while the
tree settles (red signal, not a merge gate), like the tracker-tag lint.
Current tree has 6 blocks > 30 (all in the frontend + hive-c0re-core #2077
slices, none in nix/infra): matrix-accounts.js, permissions.js,
stream-worker.js, terminal.js, hivectl.rs:1036, assets.rs. Non-required, so
non-blocking — they're the remaining #2077 targets for those area owners.
'Mirrors the logic previously embedded in hive-ag3nt' is pure provenance
(where the code moved from) — the #2077 rubric says drop impl-history. The
rest of my slice (nix modules + hive-priv/matrix-mcp/bash-mcp + forge.rs) is
already lean: surveyed it, the long comment blocks are all legit why/invariant/
contract docs under the 30-line threshold, not bloat.
ensure_mirror_repo treated 409|422 as success (copied from ensure_org, where
422 *does* mean 'org exists'). For the migrate endpoint 422 is a validation
error (bad clone_addr/service); the GET-first check is the real idempotency
guard, so 409 stays as a race guard but 422 now falls through to the bail arm
(→ caller warns) instead of silently dropping a misconfigured mirror.