docs: fix genuine passive-voice hits in docs/agent-lifecycle
Ninth batch of the ongoing write-good.Passive pass (hyperhive#4042):
read all 75 hits across agent-hierarchy.md/persistence.md/approvals.md
in context and rewrote 46 with a clearly nameable actor -- mostly
hive-c0re, a specific fn/type named right there or a sentence or two
earlier (approvals.md's numbered "Reminder delivery" list all share
hive-c0re as the established actor across three consecutive bullets),
or "the worker"/"the daemon" reused from the section's own established
subject.
Left 29 alone. Recurring buckets: predicate-adjective state pairs
("is wedged"/"is stopped", "is unaffected", "are unrelated", "is
overloaded" -- matches the established "is trusted"/"is privileged"
family), negative-capability/invariant idioms ("no X is needed",
"can't be removed/started", "no such transient was cleared"),
forward-looking design-intent statements about not-yet-built
enforcement (agent-hierarchy.md's whole "Planned topology semantics"
section leans on this: "are meant to run", "once enforcement is
finished", "will be gated"), the "audit trail, not cache" policy
invariant restated twice verbatim ("Approvals are kept forever" /
"indefinitely" -- left both alone consistently), and a config-
conditional state idiom ("when interval_seconds is set"). One more
false-positive tokenization, same bug as knowledge.md's earlier case:
persistence.md's "`config` is read-only" trips vale's "is read" match
inside the compound adjective -- not a real passive at all.
One deliberately-conservative leave: agent-hierarchy.md's "Reminder
cancellation is handled fully in-agent" had an ambiguous actor (the
in-agent socket vs. the hive-c0re source file the doc points readers
to for detail) -- left alone rather than risk a wrong attribution,
unlike the higher-confidence rewrites elsewhere in the same batch.
Verified via vale before/after: 75 -> 29 write-good.Passive hits,
exactly the 29 left alone above; error count and other warning
categories unchanged. Re-read every changed line in full surrounding
context after editing before running the final vale check.
This commit is contained in:
parent
09196a44fe
commit
0ad0376fe3
3 changed files with 67 additions and 68 deletions
|
|
@ -1,8 +1,8 @@
|
|||
# Agent hierarchy & privileges
|
||||
|
||||
Every agent has a place in an operator-editable parent/child tree, used
|
||||
to scope which agents can manage which others. This doc covers how the
|
||||
tree is stored and edited today, the rules that are meant to run on top
|
||||
to scope which agents can manage which others. This doc covers how
|
||||
hive-c0re stores and edits the tree today, the rules that are meant to run on top
|
||||
of it once enforcement is finished, and where the manager still gets
|
||||
special-cased in the meantime. Tracking issue: hyperhive#361
|
||||
(`$HIVE_FORGE_URL/hyperhive/hyperhive/issues/361`).
|
||||
|
|
@ -24,7 +24,7 @@ Topology lives in the hive-c0re-owned **meta repo**, alongside
|
|||
structural manager that everything hangs under. Hierarchy is built
|
||||
explicitly: an agent that requests a sub-agent gets a
|
||||
requester-as-parent edge written at its `init_config` approval (so
|
||||
`bob` above was spawned by `alice`), and the operator can reparent any
|
||||
`alice` spawned `bob` above), and the operator can reparent any
|
||||
agent, including the bootstrap container (`ruth`) — it's just another
|
||||
root. The manager is reparentable like any other agent; there's no
|
||||
"structurally root" carve-out. Its privileges live on its MCP socket,
|
||||
|
|
@ -64,11 +64,11 @@ where system-level facts live.
|
|||
install that hasn't synced yet).
|
||||
- **Reconcile** — runs alongside the periodic meta/flake regeneration.
|
||||
New agents default to root unless they already carry an explicit
|
||||
parent edge from an `init_config` approval; existing entries
|
||||
(including operator overrides) are preserved; removed agents drop.
|
||||
parent edge from an `init_config` approval; Reconcile preserves existing entries
|
||||
(including operator overrides); removed agents drop.
|
||||
Agents that are approved but not yet spawned keep their edge too, so
|
||||
it survives the gap until the container actually appears.
|
||||
- **Inject** — each container's parent (if any) is exposed to its own
|
||||
- **Inject** — hive-c0re exposes each container's parent (if any) to its own
|
||||
environment as `HIVE_PARENT`, so the harness / system-prompt
|
||||
renderer can see it.
|
||||
- **Surface** — every rescan re-reads `topology.json` and populates
|
||||
|
|
@ -98,8 +98,8 @@ umount-old / mount-new / restart-cascade step.
|
|||
| `send` / `recv` routing | parent ↔ same-parent siblings ↔ self ↔ descendants; explicit allow-list for anyone else |
|
||||
| `request_update_meta_inputs` (bump meta lock) | root agents only (today: just `manager`) |
|
||||
|
||||
"Ancestor" walks `ContainerView.parent` chains; cycles are guarded by a
|
||||
visited-set at dispatch time (a malformed `topology.json` can't lock
|
||||
"Ancestor" walks `ContainerView.parent` chains; a visited-set guards against
|
||||
cycles at dispatch time (a malformed `topology.json` can't lock
|
||||
the dispatcher into a loop).
|
||||
|
||||
## Manager special-casing today
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ CLI) before it takes effect. What you'll see, and what to do with it:
|
|||
|
||||
Don't want to approve something? **Deny it** (`DENY` on the dashboard
|
||||
card, or `hivectl approvals deny <id>`) — nothing runs. Either way the
|
||||
submitting agent is always notified their request was denied; what's
|
||||
submitting agent is always notified that the operator denied their request; what's
|
||||
optional is only the reason text, which you can add on the dashboard's
|
||||
prompt (cancelling that prompt aborts the whole deny, not just the
|
||||
reason) but not from the CLI. Denying is final: a denied approval
|
||||
|
|
@ -76,8 +76,8 @@ request.
|
|||
`MergeConfigPr` approval; a poll fallback catches any missed webhook.
|
||||
The approval row stores the PR **number** (`commit_ref`) and the PR
|
||||
**head sha at queue time** (`fetched_sha` — the "reviewed" sha). If
|
||||
the PR head later moves, the stale approval is superseded by a fresh
|
||||
one pinned to the new head, so the operator always reviews what will
|
||||
the PR head later moves, a fresh approval pinned to the new head supersedes
|
||||
the stale one, so the operator always reviews what will
|
||||
actually deploy.
|
||||
3. The operator reviews the PR **on the forge** (native diff, threaded
|
||||
comments, CI status) and sees a matching card on the dashboard with a
|
||||
|
|
@ -118,13 +118,13 @@ request.
|
|||
### Withdrawing a pending approval
|
||||
|
||||
The submitting agent can call `cancel_loose_end(kind: "approval", id)` to
|
||||
withdraw an approval that hasn't been acted on yet.
|
||||
withdraw an approval the operator hasn't acted on yet.
|
||||
The row transitions to `ApprovalStatus::Cancelled` (distinct from
|
||||
`Denied`/`Failed`), the dashboard pulls the card out of the
|
||||
pending pane, and `ApprovalResolved { status: "cancelled" }` fires
|
||||
on the root agent + dashboard channels. Approvals that have already
|
||||
been approved/denied/failed return an error — the resolution is
|
||||
final once the operator (or a lifecycle failure) acted on the row.
|
||||
on the root agent + dashboard channels. Approvals that the operator
|
||||
(or a lifecycle failure) has already approved, denied, or failed return an error — the resolution is
|
||||
final once acted on.
|
||||
|
||||
The socket refuses the `approval` kind with a clear error for any
|
||||
agent that lacks the `approvals` tool group: only an agent with that
|
||||
|
|
@ -178,7 +178,7 @@ kind-specific payload carrier.
|
|||
operator approval. Step 1 of the two-step spawn flow above.
|
||||
- `UpdateMetaInputs` — `commit_ref` stores the JSON-encoded inputs
|
||||
array (`"[]"` = all inputs, `"[\"nixpkgs\"]"` = just nixpkgs,
|
||||
etc.). `agent` field is set to the requesting root agent.
|
||||
etc.). hive-c0re sets the `agent` field to the requesting root agent.
|
||||
On approve hive-c0re runs `nix flake update [inputs...]` on the
|
||||
meta flake and commits the resulting lock changes.
|
||||
- `SchedulePrompt` — `commit_ref` stores the JSON-encoded
|
||||
|
|
@ -194,15 +194,15 @@ kind-specific payload carrier.
|
|||
Two ways a row lands in `scheduled_prompts`:
|
||||
|
||||
- **Operator-direct** (`source = "operator"`): the operator adds a schedule through the dashboard form. Lands in the table immediately, no approval gate — operator action is already the trust boundary.
|
||||
- **Agent-requested** (`source = "approval:<id>"`): an agent submits a `RequestSchedulePrompt` through its MCP socket (the `request_schedule_prompt` tool, `scheduling` group). An `ApprovalKind::SchedulePrompt` row is queued; on approve, hive-c0re inserts the schedule row with `source = approval:<id>` so the audit trail points back at the operator decision (above).
|
||||
- **Agent-requested** (`source = "approval:<id>"`): an agent submits a `RequestSchedulePrompt` through its MCP socket (the `request_schedule_prompt` tool, `scheduling` group). hive-c0re queues an `ApprovalKind::SchedulePrompt` row; on approve, it inserts the schedule row with `source = approval:<id>` so the audit trail points back at the operator decision (above).
|
||||
|
||||
No self-target shortcut: even agent-self schedules need approval. The existing `remind` MCP tool stays the quick self-wake path (no approval, lands directly in the agent's own inbox); this module is the bigger, multi-recipient, operator-visible thing.
|
||||
|
||||
### Scheduled prompt worker (catch-up clamp)
|
||||
|
||||
When hive-c0re comes back from being down, the worker sees rows whose `next_fire_at_unix` is well in the past. For recurring rows that would mean firing N delayed pulses in a row — spammy and useless. Instead the worker fires **once** per row and bumps `next_fire_at_unix` to the next interval slot ≥ `now`, recording how many cycles were skipped in `last_result` (per-target). Operators see "fired late, caught up from 17 skipped" instead of 17 wake-up storms.
|
||||
When hive-c0re comes back from being down, the worker sees rows whose `next_fire_at_unix` is well in the past. For recurring rows that would mean firing N delayed pulses in a row — spammy and useless. Instead the worker fires **once** per row and bumps `next_fire_at_unix` to the next interval slot ≥ `now`, recording how many cycles it skipped in `last_result` (per-target). Operators see "fired late, caught up from 17 skipped" instead of 17 wake-up storms.
|
||||
|
||||
One-shot rows fire once (if past due, on the next worker pass) and are deleted by the worker; recurring rows survive until cancelled.
|
||||
The worker fires one-shot rows once (if past due, on the next worker pass) and deletes them; recurring rows survive until cancelled.
|
||||
|
||||
`targets` is its own table (`scheduled_prompt_targets`) so partial cancellation flips a single row and the dashboard can show last-fired / last-result per recipient. Cancelling every target reaps the parent row on the next worker pass.
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ Transient broker errors (sqlite lock contention, etc.) get the same
|
|||
|
||||
- **Recurring rows** re-arm to the next interval slot — the retry
|
||||
self-heals on the next worker pass.
|
||||
- **One-shot rows** are deleted unconditionally after their single
|
||||
- **One-shot rows**: the worker deletes them unconditionally after their single
|
||||
fan-out pass; a broker error on a one-shot isn't retried (the
|
||||
operator advisory and `last_result` are the only audit trail).
|
||||
|
||||
|
|
@ -253,19 +253,18 @@ container, for example `/agents/<name>/state/foo.md`). On delivery hive-c0re:
|
|||
from outside the container.
|
||||
2. **Validates** the path: rejects anything outside the agent's own state
|
||||
subtree, containing `..` (path traversal), or with an empty relative
|
||||
tail. On rejection the write is skipped and the original message is
|
||||
delivered inline with a warning — the reminder still fires.
|
||||
3. **Defends against symlink escape**: after `create_dir_all`, the parent
|
||||
dir is canonicalized and re-verified to live under the agent's host
|
||||
state root. The final file is opened with
|
||||
tail. On rejection hive-c0re skips the write and delivers the
|
||||
original message inline with a warning — the reminder still fires.
|
||||
3. **Defends against symlink escape**: after `create_dir_all`, hive-c0re
|
||||
canonicalizes the parent dir and re-verifies it lives under the agent's host
|
||||
state root. hive-c0re opens the final file with
|
||||
`O_NOFOLLOW | O_CREAT | O_TRUNC` so an existing symlink at the
|
||||
basename can't redirect the write to an arbitrary host path.
|
||||
4. **Writes the body to disk** and delivers a short pointer message in its
|
||||
place, keeping the agent's inbox / wake-prompt small while the bulky
|
||||
payload is read out of band.
|
||||
place, keeping the agent's inbox / wake-prompt small while the agent
|
||||
reads the bulky payload out of band.
|
||||
|
||||
Atomicity of the inbox INSERT + `reminders.sent_at` UPDATE is handled
|
||||
inside `Broker::deliver_reminders_batch`; the scheduler only computes the
|
||||
`Broker::deliver_reminders_batch` handles atomicity of the inbox INSERT + `reminders.sent_at` UPDATE; the scheduler only computes the
|
||||
body strings before calling it.
|
||||
|
||||
### Destroy semantics
|
||||
|
|
@ -354,7 +353,7 @@ from the agent list; if it differs from disk, runs
|
|||
The root agent has `/meta` RO-bound inside its container:
|
||||
`git -C /meta log --oneline` is the swarm-wide deploy log,
|
||||
`cat /meta/flake.lock | jq '.nodes["agent-<n>"].locked'`
|
||||
resolves which sha each agent is pinned at right now.
|
||||
resolves which sha the flake pins each agent at right now.
|
||||
Dashboard surfaces the same info as a `deployed:<sha12>` chip
|
||||
per container row.
|
||||
|
||||
|
|
@ -409,7 +408,7 @@ repo:
|
|||
| `deployed/<id>` | rebuild succeeded — `main` ff's here | no |
|
||||
| `failed/<id>` | rebuild failed | yes (body = error) |
|
||||
|
||||
`deployed/0` is planted at first spawn. `applied/main` is always the
|
||||
hive-c0re plants `deployed/0` at first spawn. `applied/main` is always the
|
||||
latest `deployed/*`. A `failed/` tree stays browsable forever — `git log
|
||||
--tags` in the applied repo is the audit trail. A denied or failed config
|
||||
PR carries no extra state on the forge side: the PR stays open, and the
|
||||
|
|
@ -477,8 +476,8 @@ repo — so it can push a branch and open a config PR — but not a member
|
|||
of any other agent's, so it can't reach another agent's config through
|
||||
the forge. Branch protection keeps `main` push/merge `core`-only with
|
||||
operator-team approval, so an agent can't fast-forward its own config or
|
||||
self-merge its PR (see the End-to-end flow + #1787). The tokenised push
|
||||
URL is passed inline to `git push`, never written into
|
||||
self-merge its PR (see the End-to-end flow + #1787). hive-c0re passes the tokenised push
|
||||
URL inline to `git push`, never writing it into
|
||||
`applied/<n>/.git/config`; that repo is RO-bind-mounted into the root
|
||||
agent, and a stored token would leak core's admin credential to an
|
||||
agent.
|
||||
|
|
@ -497,7 +496,7 @@ for each entry in
|
|||
current config — not an editing surface.
|
||||
|
||||
An agent with the `approvals` tool group submits a change the same way
|
||||
any other change is made: **clone the child's config repo from the
|
||||
it makes any other change: **clone the child's config repo from the
|
||||
forge into its own state dir, commit on a branch, open a PR**, and let
|
||||
the operator review and approve it. By design, no second, mount-shaped
|
||||
path reaches the same file without the review.
|
||||
|
|
@ -543,7 +542,7 @@ host set up before the tag-driven-deploy + meta-flake scheme (both
|
|||
described above) converges to it automatically. Each phase is a no-op
|
||||
once already applied:
|
||||
|
||||
- **Tags**: agents from before the tag-driven scheme are tagged
|
||||
- **Tags**: hive-c0re tags agents from before the tag-driven scheme
|
||||
`deployed/0` on `main` once. Non-destructive — it doesn't touch live
|
||||
containers, state dirs, or claude creds.
|
||||
- **Meta flake**: rewrites each `applied/<n>/flake.nix` to the
|
||||
|
|
@ -579,7 +578,7 @@ Differences from sub-agents:
|
|||
authoritative applied repo (see "Root-agent view of applied" below).
|
||||
- First-deploy spawn bypasses the approval queue (the root agent is
|
||||
required infrastructure).
|
||||
- The root agent's socket is bound by `socket_server::start_manager`,
|
||||
- `socket_server::start_manager` binds the root agent's socket,
|
||||
pure transport with no dedicated helpers — it uses the same
|
||||
per-agent runtime dir as any other agent (`/run/hyperhive/agents/ruth/`),
|
||||
not a special manager-only path.
|
||||
|
|
@ -592,7 +591,7 @@ updates the root agent itself.
|
|||
|
||||
The system prompt (`hive-agent/prompts/system.md`, rendered by
|
||||
`hive-agent/src/prompt.rs`) is the **same for every agent**; what
|
||||
varies is which MCP tools are surfaced (gated by tool groups and
|
||||
varies is which MCP tools it surfaces (gated by tool groups and
|
||||
capabilities in `agent.nix`). No `role:manager` block renders only
|
||||
for the root agent. The root agent's approval-gating
|
||||
behaviour comes from its CLAUDE.md / agent-specific instructions, not
|
||||
|
|
@ -648,7 +647,7 @@ commit (spawn / init_config / meta-update / deny, and the autoupdate
|
|||
sweep's `job_queue::templates::rebuild` reapplying the existing main,
|
||||
or the dashboard `↻ R3BU1LD` button when the lock didn't move). When set,
|
||||
`git show <sha>` against `/applied/<n>/.git` inside the
|
||||
bootstrap container yields the exact tree that was referenced.
|
||||
bootstrap container yields the exact tree the sha referenced.
|
||||
|
||||
To add a new lifecycle notice: if it needs to drive an immediate turn
|
||||
(something genuinely urgent, like `ContainerCrash`), add a
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ power-intent registry:
|
|||
next_fire_at_unix / created_at_unix / source ("operator" or
|
||||
"approval:<id>") / cancelled_at_unix / description`. `owner`
|
||||
drives cancel-permission checks (operator vs the submitting
|
||||
agent). Cancelled rows are tombstoned and reaped by the worker
|
||||
agent). The worker tombstones and reaps cancelled rows
|
||||
on its next pass.
|
||||
- `scheduled_prompt_targets` — per-target state for each schedule.
|
||||
`schedule_id / target / cancelled_at_unix /
|
||||
|
|
@ -87,16 +87,16 @@ Retention:
|
|||
`hive-c0re::main`. Drops acked message rows older than 30 days
|
||||
(`acked_at IS NOT NULL`). Undelivered + delivered-but-not-acked
|
||||
rows are always kept — the harness `ack_turn`s only after a
|
||||
successful turn, so an unacked row can still be requeued via
|
||||
`requeue_inflight` on a crash.
|
||||
successful turn, so `requeue_inflight` can still requeue
|
||||
an unacked row on a crash.
|
||||
- Approvals are kept indefinitely — an audit trail. `actions::destroy`
|
||||
rows stay visible to anything that queries by id.
|
||||
- Scheduled prompts: one-shot rows are deleted on fire by the
|
||||
worker; recurring rows live until the operator cancels them
|
||||
- Scheduled prompts: the worker deletes one-shot rows on fire;
|
||||
recurring rows live until the operator cancels them
|
||||
(`cancel_schedule` MCP / dashboard ✗) which tombstones via
|
||||
`cancelled_at_unix`, then `reap_cancelled` drops the row on
|
||||
the next worker pass.
|
||||
- `agent_power` rows live until the agent is destroyed (one row per
|
||||
- `agent_power` rows live until the operator destroys the agent (one row per
|
||||
agent — nothing to vacuum).
|
||||
|
||||
### `/harness/hyperhive-events.sqlite` (per agent)
|
||||
|
|
@ -148,9 +148,9 @@ Bin-loop helpers `build_row` + `record` land each row at
|
|||
`turn_end`; writes are best-effort, a sqlite hiccup logs + lets
|
||||
the turn loop continue.
|
||||
|
||||
A sibling `bash_commands(ts INTEGER, head TEXT)` table in the same
|
||||
file is written by the `hive-bash-daemon` (not the harness): one
|
||||
row per executed bash task recording the normalised command head -
|
||||
The `hive-bash-daemon` (not the harness) writes a sibling
|
||||
`bash_commands(ts INTEGER, head TEXT)` table in the same
|
||||
file: one row per executed bash task recording the normalised command head -
|
||||
the basename of the first real command, looking past `cd repo &&`
|
||||
prefixes, env-assignments, and prefix-runners like `sudo`/`env`. It
|
||||
backs the "favorite tools" view on the /stats page (aggregated
|
||||
|
|
@ -215,7 +215,7 @@ Three indices:
|
|||
as part of the existing hourly vacuum.
|
||||
- `(node_id)` — added by a later migration so a build log row can be
|
||||
looked up by the job-queue node it belongs to (a `hive_jobq` node is
|
||||
immutable after insert, so the link is recorded on the log row
|
||||
immutable after insert, so hive-c0re records the link on the log row
|
||||
instead); legacy rows predating the column keep `node_id IS NULL`.
|
||||
|
||||
Writes are best-effort: `append_stdout` / `append_stderr` / `finish`
|
||||
|
|
@ -313,15 +313,15 @@ Under `/var/lib/hyperhive/agents/<name>/`:
|
|||
store + wake `Notify` directly rather than dialling its own socket.
|
||||
`disk_watch` raises a keyed `disk` todo when the filesystem backing
|
||||
this agent's state gets tight, naming the agent's own biggest
|
||||
directories; the summary is bucketed and carries no raw byte
|
||||
directories; it buckets the summary and carries no raw byte
|
||||
counts, so an unchanged situation re-upserts as `changed == false`
|
||||
and never re-wakes.
|
||||
|
||||
Retention, same hourly `hive-agent::vacuum::run` sweep as
|
||||
`hyperhive-events.sqlite` below: delivered (soft-deleted) reminder
|
||||
rows are reaped 14 days after delivery, kept that long only to serve
|
||||
the trailing-window `ReminderRollup` stats; acked todo rows are
|
||||
reaped 30 days after acking (long enough that only a genuinely quiet
|
||||
`hyperhive-events.sqlite` below: it reaps delivered (soft-deleted) reminder
|
||||
rows 14 days after delivery, kept that long only to serve
|
||||
the trailing-window `ReminderRollup` stats, and reaps acked todo rows
|
||||
30 days after acking (long enough that only a genuinely quiet
|
||||
month triggers the "one spurious re-announcement" fallback a
|
||||
reconciled producer like `disk_watch` relies on — see `todos.rs`'s
|
||||
module doc). Un-acked todos and undelivered reminders are never
|
||||
|
|
@ -371,8 +371,8 @@ files committed via the approval flow. `.git/` carries the proposal /
|
|||
approved / building / deployed / failed / denied tag history.
|
||||
|
||||
Under `/var/lib/hyperhive/meta/` — the swarm-wide deploy flake plus
|
||||
system-level config files. Single git repo for the whole host; every
|
||||
hive-c0re mutation that should survive a restart is committed here.
|
||||
system-level config files. Single git repo for the whole host; hive-c0re
|
||||
commits every mutation that should survive a restart here.
|
||||
Contents:
|
||||
|
||||
- `flake.nix` — declares one `nixpkgs` input per agent + one
|
||||
|
|
@ -396,8 +396,8 @@ Contents:
|
|||
var. Absent agents have no extra capabilities.
|
||||
- `resource-limits.json` — per-agent container resource overrides
|
||||
(`{ "sock": { "cpu_quota": "400%", "memory_max": "8G" } }`).
|
||||
Written by `resource_limits::set_limits`; read where the systemd
|
||||
drop-in is generated (`lifecycle::write_dropins`), **not** injected
|
||||
Written by `resource_limits::set_limits`; read where
|
||||
`lifecycle::write_dropins` generates the systemd drop-in, **not** injected
|
||||
into the container — these are host-side caps on the container, so
|
||||
the capped party never sees or sets them. Fallback is per *field*:
|
||||
an absent file, absent agent, or absent field falls back to the
|
||||
|
|
@ -411,7 +411,7 @@ The root agent has the meta dir RO-mounted at `/meta/`.
|
|||
|
||||
The `.meta-migration-done` marker no longer exists: the
|
||||
one-shot container repoint it guarded has been removed, since
|
||||
containers are rendered onto `meta#<n>` at creation. A stale
|
||||
hive-c0re renders containers onto `meta#<n>` at creation. A stale
|
||||
marker file left over from an older hive is inert and can be
|
||||
deleted.
|
||||
|
||||
|
|
@ -426,8 +426,8 @@ an agent's state. The mechanics, for completeness:
|
|||
- `PURG3` wipes `/var/lib/hyperhive/{agents,applied}/<name>/` — the
|
||||
union of everything `DESTR0Y` left behind.
|
||||
|
||||
The root/bootstrap agent's specialness is implemented as a soft policy
|
||||
guard in `actions::destroy` that refuses to destroy it, backstopped by
|
||||
`actions::destroy` implements the root/bootstrap agent's specialness as a soft policy
|
||||
guard that refuses to destroy it, backstopped by
|
||||
`auto_update::ensure_root_agent`, which recreates it on the next
|
||||
hive-c0re startup if it's ever absent (bypassing the approval queue,
|
||||
as required infrastructure) — so even without the guard, destroying it
|
||||
|
|
@ -435,7 +435,7 @@ would only be transient.
|
|||
|
||||
### btrfs subvolumes for `/var/lib/hyperhive/agents/<name>`
|
||||
|
||||
On a btrfs host, a brand-new agent's state root is created as a
|
||||
On a btrfs host, `lifecycle::ensure_agent_state_subvolume` creates a brand-new agent's state root as a
|
||||
**btrfs subvolume** instead of a plain directory (progressive
|
||||
enhancement — see the #1762 lane). This is a no-op fallback on
|
||||
non-btrfs hosts and for any agent whose root already exists, so
|
||||
|
|
@ -443,7 +443,7 @@ nothing is automigrated: existing agents keep their plain dirs
|
|||
until an explicit opt-in upgrade.
|
||||
|
||||
- **Creation:** `lifecycle::ensure_agent_state_subvolume` runs before
|
||||
the per-agent subdirs are created (spawn / rebuild / InitConfig).
|
||||
hive-c0re creates the per-agent subdirs (spawn / rebuild / InitConfig).
|
||||
It skips the work when the root already exists; otherwise it asks
|
||||
hive-priv (`EnsureAgentSubvolume`) to `btrfs subvolume create` the
|
||||
root when the FS is btrfs (`statfs` magic gate) and chown it to the
|
||||
|
|
@ -475,8 +475,8 @@ Only present on the one host running
|
|||
`services.hyperhive.deploy.swarm-controller.enable`. systemd `StateDirectory=`,
|
||||
so it survives restarts and redeploys.
|
||||
|
||||
- `webhook-secret` — the HMAC key the swarm's forge webhooks are signed
|
||||
with. **Keep it.** It's handed to Forgejo when a hook is registered,
|
||||
- `webhook-secret` — the HMAC key Forgejo signs the swarm's forge webhooks
|
||||
with. **Keep it.** It's handed to Forgejo when swarm-controller registers a hook,
|
||||
so replacing the file means every subsequent delivery fails
|
||||
verification until the hook is re-registered with the new value. It's
|
||||
generated automatically on first start; there is nothing to configure.
|
||||
|
|
@ -565,8 +565,8 @@ avatar (see below).
|
|||
|
||||
### matrix avatar (set by the daemon over the live Client)
|
||||
|
||||
The agent icon (`hyperhive.icon`, an SVG) is published as each matrix
|
||||
account's profile avatar by `hive-matrix-daemon` itself
|
||||
`hive-matrix-daemon` itself publishes the agent icon (`hyperhive.icon`, an SVG) as each matrix
|
||||
account's profile avatar
|
||||
(`hive-matrix-mcp::client::sync_avatar`), not a separate oneshot. After
|
||||
the daemon builds + restores an account's `Client` (authenticated,
|
||||
pointed at that account's resolved homeserver), it calls matrix-sdk's
|
||||
|
|
@ -574,7 +574,7 @@ pointed at that account's resolved homeserver), it calls matrix-sdk's
|
|||
`avatar_url`. Because it reuses the live Client, there is no hardcoded
|
||||
homeserver URL, no token re-read, and no token-file globbing: the daemon
|
||||
already iterates every configured + dashboard-discovered account in its
|
||||
bring-up loop, so the avatar is set for **every** account.
|
||||
bring-up loop, so it sets the avatar for **every** account.
|
||||
|
||||
Nix rasterizes the SVG to a 512x512 PNG at build time (`iconPng`, via
|
||||
librsvg) and forwards its store path as `HIVE_ICON_PNG` on the daemon
|
||||
|
|
@ -588,6 +588,6 @@ skips the upload when unchanged, because every upload mints a fresh
|
|||
re-uploading identical bytes is timeline spam. A dashboard-provisioned
|
||||
account gets its avatar when the `systemd.paths.hive-matrix-daemon` token
|
||||
watcher restarts the daemon (which re-runs the per-account bring-up), so
|
||||
no separate avatar trigger is needed. Avatar failures are swallowed
|
||||
no separate avatar trigger is needed. The daemon swallows avatar failures
|
||||
(logged, non-fatal) so they never break account bring-up or sync.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue