hyperhive/docs/conventions.md
müde 8b10731aa4 split claude.md into docs/ — per-topic, human-readable
claude.md was eating 400 lines of subsystem detail that's useful
when you're working on that subsystem and noise the rest of the
time. split into:

- docs/conventions.md   naming, identity, async forms, commit style
- docs/gotchas.md       nspawn / nixos-container quirks
- docs/web-ui.md        dashboard + per-agent layouts and endpoints
- docs/turn-loop.md     claude invocation, wake prompt, mcp surface
- docs/approvals.md     approval flow, manager policy, helper events
- docs/persistence.md   sqlite dbs, retention, state dir layout

claude.md is now the entry point — file map, reading paths
("pick the doc that matches your task"), quick reminders that
fit on one screen, and a small scratchpad section for in-flight
context. references the docs; the docs don't reference claude.md.

no content was lost — the docs/ files cover everything the old
claude.md did, plus things i wrote up better while extracting.
2026-05-15 20:17:11 +02:00

2.6 KiB

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 confirmation prompt.

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.