The hive dashboard and the per-agent page lose their control-by-control UI
description and endpoint tables from the handbook. The full text moves to
4-implementation/web-ui/dashboard.md and agent-page.md, and the handbook pages
keep what an operator needs to find and use them. Code comments that named the
old sections point at the new pages.
The operator parts of the persistence and config-changes pages merge into
agents/persistence.md. The sqlite tables, state dirs, mounts and migrations move
to 4-implementation/agent-state/persistence.md, and the deploy path, meta flake,
deploy markers, startup migrations, root container, system messages and
autoupdate move to 4-implementation/agent-state/config-changes.md. Links, code
comments and nix comments that named the old sections point at the new pages.
- swarm-archive.nix, lib/archive-server.nix: deploy.archive.backend and
deploy.archive.s3.* options; the s3 server and the prune read the key from the
store into rclone's environment; the prune lists and addresses repositories
through rclone instead of a local directory
- swarm-bao.nix: the archive reads swarm/services/archive/s3/*
- docs: archive.md "External S3" section, two credentials-reference rows
- module-eval: builder.nix cases for local and s3, the missing-setting
assertion; bao-grants.nix gains the s3 read grant
- vm test: second node with a fake rclone serve s3 whose key is generated at
test time
The panels took the max or sum over the one swarm runner. A runner variable
(the series' service.instance.id) filters every panel, and uptime, job slots
and slot use show one series per runner, so a runner registered by hand shows
up beside the swarm's once its metrics reach the store.
A client chooses a snapshot's time, so snapshots dated ahead could fill
--keep-last and push the real ones out of a prune. The prune now forgets
snapshots dated more than an hour after now first, and logs their ids. The
VM test forges one and checks the real snapshot stays. The bao-grants case
that read a + path as a glob now names the literal path, and two cases that
pinned 'nothing else' list the archive grants. The ciRunner stanza is back
at its original indent.
The archive host creates a ready marker in the store and swarm-controller
writes no credentials before it exists, so a swarm without an archive, and a
mixed-version swarm, leave every hive backup a logged no-op. A hive with no
declaration no longer counts as placing nothing: its copies and its agents'
user lines stay. The restic password is pinned by tests across a revoke, a
re-placement and a move.
swarm-archive serves restic repositories with rclone, append-only, one login
and one repository per agent. swarm-controller writes each placed agent's
login and restic password to the store, replaces them on a move and removes
them when the agent is destroyed. Every hive backs its agents up hourly under
its own store identity. The archive host prunes by retention.
The jq filter used contains(), which matches substrings per element, so an agent named spawn-two satisfied spawn. It now counts the exact names iris and spawn among the fresh agents that need a login.
On a timed-out wait, diagnose() prints systemctl --failed for the machine
or container and the last 50 journal lines of the units waited on. It no
longer prints `systemctl status` for them. Only the failure path changes.
A last subtest polls GET /api/agents/status on the controller socket until
iris and spawn are fresh with needs_login true, through settle() with up to
40 minutes. The header's green condition is now this check, and its note on
what is not scripted yet drops the agents' deploy.
mara chose on the PR to test a reviewer-archetype agent named spawn first
and leave a custom root agent (ruth) for later. So the test creates spawn
with the archetype's default permissions and drops manage_root_agent, which
only ruth carried.
- hive-meta-flake/testdata/meta-flake-swarm.nix.in: the agent is spawn, and
its web port is 8316, the port the name hashes to (ruth's was 8232).
- hive-meta-flake/src/lib.rs: the unit test that compares this fixture with
the rendered flake renders spawn instead of ruth.
- nix/vm-tests/full-setup.nix: the agents list and step 8 use spawn.
- The `swarmctl setup status` expectation keeps its "9 ruth created and up"
row: that is the product's fixed step text (swarmctl/src/setup.rs), not the
test's agent. The test creates no root agent, so step 9 is expected to be
not done, and the subtest's comment says so.
The agent's settings get a claude login row: when the swarm stored the
login, read by the minter from the leaf's metadata, or that none is, with a
delete that removes every version after a confirmation. New minter steps
(status, delete), controller routes (GET claude-login, DELETE
claude-login/stored) and a read and delete grant on the leaf's metadata,
pinned in the module-eval check.
Squid logs a tunnel's bytes once, when it closes, so a large download was
one point in a small bucket and read as instantaneous. The panel now has a
5 minute minimum interval and bars, so that point is a visible bar. The
module-eval check pins both.
init prints the store's keys and root token once and keeps none; with
--and-grant it goes on to the granter bootstrap in the same process.
grant-bootstrap does that step alone, reading the root token from a
hidden prompt or stdin. The token reaches bao only as BAO_TOKEN in the
child's environment.
Adds host.json (hive and host filters over the hostmetrics series),
registers it in the provisioned dashboard list, lists it in the swarm
services handbook, and adds a module-eval case that it ships and every
query filters on both variables.