swarm-controller: own the swarm-wide forge objects; hive-c0re stops creating them
The orgs agent-configs/internal/agents (plus mirror owners), the operators team in agents and agent-configs, the pull-mirrors, internal/docs, internal/knowledge (public, README-seeded) and the agent-configs org avatar are one set per forge. hive-c0re ensured them in its boot sweep, as the core admin, and only on the hive co-located with the forge container. swarm-controller now reconciles them at start and every 5 minutes (forge/objects.rs: observe -> pure plan -> apply). A failed object logs a warn line plus a pass summary and is retried next tick. create_repo ensures the agent-configs org and its operators team first, so a config repo's merge gate never depends on the periodic pass having run. hive-c0re drops ensure_org, SEEDED_ORGS, ensure_mirrors/ensure_mirror_repo, ensure_operators_team, ensure_shared_docs_repo, ensure_knowledge_repo/ set_repo_public, seed_readme, ensure_config_org_avatar and the one-shot knowledge::remove_webhook cleanup, with their now-unused helpers. nix: the mirror list moves from the hive-c0re unit (HYPERHIVE_FORGE_MIRRORS) to the swarm-controller unit (SWARM_CONTROLLER_FORGE_MIRRORS), with an eval warning when mirrors are declared on a host that runs no controller. c0re.orgAvatarPng is renamed to deploy.swarm-controller.configOrgAvatarPng. Refs #3782
This commit is contained in:
parent
85ba45b2de
commit
20419ccd41
18 changed files with 1456 additions and 822 deletions
|
|
@ -30,11 +30,11 @@ the local clone updates automatically (see
|
|||
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, for autoseeding.
|
||||
only the `core` account has push access.
|
||||
|
||||
hive-c0re autocreates the repo at startup if it doesn't exist,
|
||||
seeding it with a `README.md` containing a contribution guide and a
|
||||
blank table of contents. Add an entry to that ToC each time you
|
||||
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
|
||||
|
|
@ -56,9 +56,10 @@ pull`, so agents see the new content on their next turn.
|
|||
**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; hive-c0re now
|
||||
removes its own leftover at startup, so migrating needs no operator
|
||||
step.
|
||||
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`.
|
||||
|
||||
2. **Periodic pull** — a background task in `hive-c0re::main`
|
||||
pulls on a fixed cadence as a fallback (webhook missed, c0re
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ Gated on `HYPERHIVE_FORGE_CI_ENABLED` (the nix module sets it on `hive-c0re.serv
|
|||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
|
||||
When `deploy.forgejo.ci.enable` is set, hive-c0re autoseeds an
|
||||
When `deploy.forgejo.ci.enable` is set, the swarm controller autoseeds an
|
||||
`actions/checkout` pull-mirror on the local forge and sets Forgejo's
|
||||
`DEFAULT_ACTIONS_URL` to point at the local instance. This means CI
|
||||
`uses: actions/checkout@vN` steps resolve entirely on loopback — no
|
||||
|
|
@ -164,13 +164,13 @@ external DNS on the CI critical path.
|
|||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
**hive-c0re** itself seeds the mirror during its forge
|
||||
provisioning sweep (`forge/repos.rs::ensure_mirrors`). The nix module
|
||||
forwards the effective mirror list as `HYPERHIVE_FORGE_MIRRORS` in the
|
||||
`hive-c0re` service environment (JSON-encoded `[{upstream, dest}]`
|
||||
list). hive-c0re already holds the admin token for the rest of the
|
||||
forge provisioning sweep (orgs, agent accounts, etc.), so mirror
|
||||
seeding lives in the same place rather than a separate host-side unit.
|
||||
The **swarm controller** seeds the mirror in its swarm-wide forge-objects
|
||||
pass (`swarm-controller/src/forge/objects.rs`), beside the orgs it ensures.
|
||||
The nix module forwards the effective mirror list as
|
||||
`SWARM_CONTROLLER_FORGE_MIRRORS` in the `swarm-controller` service
|
||||
environment (JSON-encoded `[{upstream, dest}]` list). It reads the list of
|
||||
the host the controller runs on: mirrors declared on any other host aren't
|
||||
seeded, and evaluation warns about them.
|
||||
|
||||
**General-purpose mirrors**: you can pre-seed any external repo as a
|
||||
pull-mirror via `services.hyperhive.deploy.forgejo.mirrors`:
|
||||
|
|
@ -182,10 +182,10 @@ services.hyperhive.deploy.forgejo.mirrors = [
|
|||
];
|
||||
```
|
||||
|
||||
hive-c0re creates each entry as a real Forgejo pull-mirror — not a one-off
|
||||
The controller creates each entry as a real Forgejo pull-mirror — not a one-off
|
||||
clone. Forgejo re-syncs the mirror on every pull (`git-upload-pack`
|
||||
request), so a DNS blip during that sync will propagate back to the
|
||||
runner as a hard `git clone` failure. hive-c0re
|
||||
runner as a hard `git clone` failure. The controller
|
||||
autocreates the `<owner>` org in `dest`. Keep mirror dests out of the
|
||||
hive-c0re-managed namespaces (`config/`, `shared/`, `agents/`, `core/`)
|
||||
to avoid provisioning collisions.
|
||||
|
|
|
|||
|
|
@ -453,6 +453,27 @@ Swarm-side, `GET /api/agents/<name>/state/stream` relays that subject as SSE,
|
|||
resolving the agent's hive at request time exactly as the terminal stream does.
|
||||
The payload passes through opaquely — the controller never parses a header.
|
||||
|
||||
### Swarm-wide forge objects
|
||||
|
||||
The controller also keeps the forge objects that are one per swarm, not
|
||||
one per hive. It ensures them at start and every five minutes after
|
||||
(`swarm-controller/src/forge/objects.rs`):
|
||||
|
||||
- the orgs `agent-configs`, `internal` and `agents`, plus each mirror's
|
||||
owner org;
|
||||
- the empty `operators` merge-gate team in `agents` and `agent-configs`;
|
||||
- the pull-mirrors from `deploy.forgejo.mirrors` on the controller's
|
||||
host (with the `actions/checkout` one `deploy.forgejo.ci.enable` adds);
|
||||
- `internal/docs` (private) and `internal/knowledge` (public, with a
|
||||
seed `README.md` while empty);
|
||||
- the `agent-configs` org avatar
|
||||
(`deploy.swarm-controller.configOrgAvatarPng`).
|
||||
|
||||
hive-c0re no longer creates any of them. A pass that can't finish logs a
|
||||
`warn` line per object plus `swarm forge objects: pass incomplete` in
|
||||
`journalctl -u swarm-controller`, and retries on the next tick. While the
|
||||
controller is down the objects stay as they are.
|
||||
|
||||
### Swarm-wide forge webhooks
|
||||
|
||||
At startup the controller registers two Forgejo hooks pointing at
|
||||
|
|
@ -467,8 +488,8 @@ re-derive. Approval happens once, at the swarm level: a hive receives a
|
|||
decision, not an event to adjudicate.
|
||||
|
||||
**`internal/knowledge` is on that path.** The controller's is the only
|
||||
hook on it: hives no longer register their own, and each removes its
|
||||
leftover at startup. A webhook has exactly one target URL, so per-hive
|
||||
hook on it: hives no longer register their own (see
|
||||
`docs/integrations/knowledge.md` for clearing a leftover). A webhook has exactly one target URL, so per-hive
|
||||
registration never added a recipient — it took delivery away from
|
||||
whichever hive registered before it.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue