swarm-controller now gives every hive in its directory a forge account, `hive-<hive>`, in a new `hives` team of `agent-configs` (read on `repo.code` + `repo.pulls`, every repo including later ones), and mints one `read:repository` token named `swarm-hive` into the store at `swarm/hives/<hive>/forge/token`. A five-minute pass queues a `MintHiveForgeToken` node for a hive whose token is missing or no longer matches the forge, whose account is missing, or whose team membership or team settings drifted. A hive whose store or forge read failed is never queued, so an outage cannot rotate every hive's token. The token decision reuses `agent_token`'s classifier and replace step, now parameterised by name and scopes. An agent may be called `hive-<x>`. The hive account is created with `hive-<hive>@hives.hyperhive.local` and the job refuses an account by that name with any other email before it locks it down, adds it to the team or mints for it; agent creation already refuses the hive's account by the same email check. The controller's bao policy gains the `swarm/hives/+/forge/token` leaf (create/read/update), pinned by the bao-grants module-eval assertion. The hive's own policy already reads `swarm/hives/<hive>/*`. hive-c0re reads that token through `forge::reader_token()`, falling back to the core token file when the store holds none, and uses it for: fetching a merged config rev (swarm deploy, `hivectl forge reconcile-config`), reseeding a purged `applied`, the meta-update cascade's fast-forward, seeding `proposed` on first deploy, and finding the PR that merged a refused rev. Those reads no longer require a local `hive-forge` container. The `/knowledge` clone moves from the forge host's boot sweep into the knowledge pull, so every hive clones it. Posting the deploy-failure comment on that PR stays on the core token. Refs #4851
6.4 KiB
Hive-wide knowledge repository
internal/knowledge on the forge is a shared reference doc repo
readable by every agent. hive-c0re clones it to the host and
bind-mounts the clone read-only into every agent container at
/knowledge.
Agent access
Inside any agent container:
/knowledge/ # read-only bind-mount of the local clone
/knowledge/README.md # table of contents (seeded on first use)
Agents read documents directly from that path. The mount is
read-only — agents never write through it. To contribute, use the
hive-forge AGit flow (no fork needed — see
Contributing); the operator reviews and merges, and
the local clone updates automatically (see
Sync mechanism below).
Repository layout
Canonical forge location: internal/knowledge (org internal,
repo knowledge). The repo is public, so every agent's forge account
has read access without an explicit per-agent collaborator grant;
only the core account has push access.
The swarm controller creates the repo if it doesn't exist, at startup
and every few minutes after, and seeds an empty one with a README.md
containing a contribution guide and a blank table of contents. Add an entry to that ToC each time you
create a new document.
Sync mechanism
hive-c0re maintains the local clone at
/var/lib/hyperhive/knowledge via two paths:
-
Swarm event — the swarm controller holds the single push hook on
internal/knowledge(seedocs/swarm/README.md§ Swarm-wide forge webhooks). On any push to main, including merge commits, it sends an event to every hive over the swarm queue and each hive runsgit pull, so agents see the new content on their next turn.A hive that's offline when the swarm controller sends the event doesn't get it on reconnect — the periodic pull below is what closes that gap. One hive briefly showing older
/knowledgecontent than another is expected, and resolves by itself within the fallback interval.don't add a per-hive hook. A webhook has exactly one target URL, so a second registration against the same repo doesn't add a recipient — it takes delivery away from whoever registered first. Earlier versions had each hive register its own, and later ones removed that leftover at startup. A hive upgraded straight past those versions still holds its old hook: delete any hook on the repo that points at a hive's own
/webhook/knowledge. -
Periodic pull — a background task in
hive-c0re::mainqueues a pull on a fixed cadence as a fallback (webhook missed, c0re restarted between pushes). The pull is best-effort — a failure shows as a failedKnowledgePullnode on the job queue, counts toward the knowledge-pull banner, and doesn't affect the rest of the daemon.
Both paths, and the one pull at boot, queue the same KnowledgePull job
node. It holds the working tree for its duration, so two pulls never run
over each other — each trigger queues its own pass, and a pass that lands
while another is already queued or running waits its turn, since the
one ahead of it may have fetched before the push. The node runs
knowledge::pull(), which also handles the change notice below.
Change notice
When a pull actually moves the local clone's HEAD (a real change,
not a no-op — for example the periodic pull finding nothing new), hive-c0re
broadcasts a short notice to every currently registered agent's inbox:
sender system, body [system] /knowledge updated: followed by a
git diff --stat <old>..<new> summary of what changed (or a generic
"see the repo" fallback if computing the diff itself fails). This is
the same broadcast mechanism used for other hive-wide notices — inbox
message only, no forced wake, and it carries the standard "this was a
broadcast" hint. hive-c0re logs a diff or per-agent send failure
without blocking the pull itself.
On a hive with no local clone yet, knowledge::pull() takes the clone
instead of pulling, so every hive gets /knowledge from its first pull,
whether or not it runs the forge. It authenticates with the hive's forge
read token when it has one (see
forge.md) and clones the public
repo anonymously otherwise.
State
- Host clone:
/var/lib/hyperhive/knowledge— persists across hive-c0re restarts and agent destroy/recreate. Deleted only by manual operator action. - In-container mount:
/knowledge— bind-mounted read-only from the host clone on every container start. Gone when container is stopped; reappears on next start with the current clone state.
The mount deliberately excludes .git: the host clone embeds the core
token in .git/config (it rides the clone URL), so hive-priv overlays an empty
tmpfs at /knowledge/.git — agents see the documents, not the repo metadata or
token.
Contributing
Agents have read access to internal/knowledge (it's public) but no
write access, so they can't push a branch directly. The supported path
is Forgejo's AGit flow through the hive-forge CLI — no fork
required.
-
Clone the repo (
hive-forgeinjects credentials automatically; the-rflag selects the repo, the clone lands in./knowledge):hive-forge -r internal/knowledge clone cd knowledge -
Create a branch and add or update a document, then commit normally.
-
Open (or update) a PR with
--agit. This pushes the currentHEADtorefs/for/<base>/<topic>, which Forgejo turns into a PR even though you can't push a branch:hive-forge -r internal/knowledge pr create --agit \ --title "docs: add the X runbook" \ --topic add-x-runbook \ --body-file - <<'EOF' What this document adds and why. EOFRe-running with the same
--topicupdates the open PR (it force-pushes the AGit scratch ref). The base defaults tomain; in--agitmode the push goes to theoriginremote thathive-forge cloneset up. -
The operator reviews and merges. The webhook fires on merge; every running container sees the updated content within seconds (see Sync mechanism).
Do not try to git push a branch directly — lacking write access,
it's rejected. The --agit flow above is the no-fork path that works
from any agent.