hyperhive/docs/conventions.md
müde 75e7faff0c 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.
2026-05-15 22:12:40 +02:00

76 lines
2.9 KiB
Markdown

# Conventions
Code-style and process expectations across the workspace. Most of these
exist because something already went wrong without them.
## Naming
- Containers are length-bounded by `nixos-container` (≤ 11 chars).
- Sub-agents are `h-<name>` with `<name>` ≤ 9 chars.
- The manager is `hm1nd` (no `h-` prefix, fixed name).
- `MAX_AGENT_NAME` in `lifecycle.rs` enforces the cap.
- Per-agent web UI port = `WEB_PORT_BASE + FNV1a(name) % WEB_PORT_RANGE`
(8100..8999); manager fixed at 8000; dashboard `cfg.dashboardPort`
(default 7000).
## Identity = socket
There are no auth tokens on the per-agent unix sockets. The socket
*path* identifies the principal; perms come from "who has the
bind-mount." A sub-agent only sees its own `/run/hive/mcp.sock`; the
manager has access to its privileged socket; hive-c0re owns the host
admin socket.
## Wire protocol
JSON line-delimited over unix sockets in both directions (host admin
/ manager / agent). SSE streams (`/messages/stream`,
`/events/stream`) are `text/event-stream`. Request/response types
live in `hive-sh4re` — change them in one place.
## Async forms
Dashboard + per-agent mutating forms carry `data-async`; a delegated
`submit` listener in `assets/app.js` intercepts, shows a spinner,
POSTs `application/x-www-form-urlencoded` (axum's `Form` extractor
rejects multipart), calls `refreshState()` on success. New mutating
forms should add `data-async` and optionally `data-confirm` (for a
JS-side `confirm()` prompt) or `data-prompt="…"` (for a
`window.prompt()` whose answer goes into a hidden input named by
`data-prompt-field`, default `note`).
`refreshState` defers automatically when `document.activeElement`
sits inside a managed section so the operator's typing isn't lost;
collapsible `<details data-restore-key=…>` survive the re-render
via `snapshotOpenDetails` / `restoreOpenDetails`.
## `rebuild` is the reconcile verb
`lifecycle::rebuild` idempotently rewrites
`/etc/nixos-containers/<C>.conf` (`PRIVATE_NETWORK=0`, clears
`HOST_ADDRESS` / `LOCAL_ADDRESS`, sets `EXTRA_NSPAWN_FLAGS`),
regenerates `applied/<name>/flake.nix`, writes the systemd limits
drop-in, then `nixos-container update` + stop + start.
Anything that changes per-container state on the host should be
re-applied here so a manual `↻ R3BU1LD` from the dashboard is
sufficient to recover.
## Actions are factored
`approve` / `deny` / `destroy` (and the lifecycle helper) live in
`actions.rs` / `dashboard.rs`. The admin socket and the dashboard
POST handlers both call into them so the two surfaces never drift.
## Commit messages
Short, lowercase, no `Co-Authored-By` trailer. Imperative mood, no
period. Body explains *why* if non-obvious; otherwise the subject
alone is fine. Wrap at ~72 cols.
## Commit before test
Stage and commit when work *looks* ready, then run validation
(`cargo check`, `nix flake check`, real deploy). Failures get a
follow-up commit rather than an amend. The commit history is the
work log; rewriting it loses signal.