refactor(hive-agent): split the forge notification poller into its own crate
The poller was a `tokio::spawn` inside the `hive-agent` serve loop. It never needed anything from that loop except a socket path, so being in-process bought nothing and cost two things: a harness restart took forge notifications down with it, and the whole forge/HTTP dependency tree was linked into the serve-loop binary. It is now `hive-forge-notify`, a per-agent daemon with its own systemd unit, a sibling of `hive-bash-daemon` and `hive-matrix-daemon`. Same contract as those two: it reaches the harness only by upserting todos on the in-agent socket, and nowhere else. The module moves verbatim (`notify.rs`) — the formatters, the activation gates, the dedupe map and all 33 tests are unchanged. Only the socket call sites are rewritten, onto a small local `todo_client` rather than the harness's. That mirrors what both sibling daemons already do, and the etiquette differs on purpose: the harness's client carries a 60s backoff schedule sized to ride out a hive-c0re restart, which its callers need because they have no retry of their own. This poller's two call sites both sit inside the 30s poll loop and both treat a failure as "leave the thread unread, try next tick", so the poll interval already is the retry; a second backoff would only stack sleeps and delay the rest of the batch. The unit is `Restart=on-failure`, not `always`. An agent with no forge account is a supported configuration and the poller reports it by logging why and exiting 0 — under `always` that clean exit would be a restart loop on every forge-less agent. `forgejo-api`, `url` and `time` drop out of `hive-agent`'s dependencies with the module. Also corrects docs that outlived the code they described: the persisted `forge_cursor` field is long gone (forge's own read-state is the durable record of what has been delivered), but `docs/persistence.md` and the `harness_state` module docs still documented it as live.
This commit is contained in:
parent
d153d1d35f
commit
246c9471b1
18 changed files with 301 additions and 48 deletions
|
|
@ -57,6 +57,41 @@ in
|
|||
config.hyperhive.packages.hive-forge
|
||||
];
|
||||
|
||||
# Forge notification poller — a long-running sibling of
|
||||
# `hive-bash-daemon` / `hive-matrix-daemon`. Polls the agent's unread
|
||||
# notification list and upserts each thread as a todo on the harness's
|
||||
# in-agent socket; it needs nothing else from the harness, which is why
|
||||
# it is its own process rather than a task inside the serve loop.
|
||||
systemd.services.hive-forge-notify = {
|
||||
description = "Forgejo notification poller for this agent";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
# In-agent todo socket the harness serves (loose-ends v2). Must
|
||||
# match the harness's HIVE_AGENT_SOCKET (agent-service.nix) — the
|
||||
# poller upserts one todo per forge thread here rather than firing
|
||||
# a hive-c0re wake.
|
||||
HIVE_AGENT_SOCKET = "/run/hive-agent/${userName}/agent.sock";
|
||||
RUST_LOG = "info";
|
||||
# HIVE_FORGE_URL and HYPERHIVE_STATE_DIR come from
|
||||
# systemd.globalEnvironment (forwarded into every container by the
|
||||
# meta flake) — the poller reads the forge base URL from the first
|
||||
# and the agent's `forge-token` from under the second.
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = "${config.hyperhive.packages.hive-forge-notify}/bin/hive-forge-notify";
|
||||
SyslogIdentifier = "hive-forge-notify";
|
||||
# `on-failure`, NOT `always`: an agent with no forge account is a
|
||||
# supported configuration, and the poller reports that by logging
|
||||
# why and exiting 0. Under `always` that clean exit would become a
|
||||
# restart loop on every forge-less agent. A crash still restarts.
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
User = userName;
|
||||
Group = userName;
|
||||
};
|
||||
};
|
||||
|
||||
# One-shot: tea config.yml from the seeded forge token. Shape
|
||||
# contract (always exit 0, no set -e, skip-silently, re-runnable):
|
||||
# docs/conventions.md::Best-effort oneshot services.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
hyperhive package outputs consumed by the harness modules: the
|
||||
per-binary daemon/CLI packages (`hive-agent`, `hive-agent-mcp`,
|
||||
`hive-bash-daemon`,
|
||||
`hive-forge`, `hive-matrix-daemon`,
|
||||
`hive-forge`, `hive-forge-notify`, `hive-matrix-daemon`,
|
||||
`hive-metric`, `hive-screen-mcp`) plus the `assets`, `frontend` and
|
||||
`reference-docs` trees. Wired by the flake's agent-base/ruth
|
||||
nixosModules to `hyperhive.packages.<system>.*`; override an
|
||||
|
|
|
|||
Loading…
Reference in a new issue