Watch
0
0
Fork
You've already forked hyperhive
0
Commit graph hyperhive/hive-c0re/src/socket_server/mod.rs
Author SHA1 Message Date
atlas
efbfec6d01 config PRs: remove the hive's config-PR webhook, poll and core merge
An operator's merge on the forge deploys a config PR through
swarm-controller's DeployRequest{rev}. The hive-side path that queued a
MergeConfigPr approval and merged the PR as `core` goes:

- the `/webhook/config-pr` receiver, its HMAC secret, the WebhookRegister
  boot node and the org-hook registration; the hive vhost's `/webhook/`
  location
- the 5-minute config-PR poll
- ApprovalKind::MergeConfigPr, its dashboard card, and the deploy DAG it
  drove (DeployWindow, MergeVerify, DeployApply, FinalizeDeploy,
  DeployTail), with verify_commit, the two-phase meta deploy, rollback
  refs, the PR-failure comment and forge/pr_merge.rs
- `fetched_sha`, `sha_short`/`pr_number` on approval events, and
  `sha`/`tag` on HelperEvent::ApprovalResolved: only the merge path set
  them

`config_repo`, `merged_pr_for_commit` and `post_pr_comment` move to
forge/pr_comment.rs for the merged-rev deploy's refusal comment.
Approvals v5 drops stored `merge_config_pr` rows; a test reopens a v4
database holding them.

Closes #4850
2026-10-02 23:13:03 +02:00
atlas
a40c0026cf hive-c0re: test verify_hmac guards and webhook status mapping
`verify_hmac` is the only authentication gate on the public
`/webhook/config-pr` endpoint, and neither of its guard clauses nor the
handler's "unavailable" → 503 / otherwise → 401 mapping had a test.

The tests build a real `AppState` over the tempdir `Coordinator` that
the socket_server schedule tests already use. That helper is widened
from `pub(in crate::socket_server)` to `pub(crate)` and re-exported from
`socket_server` under `#[cfg(test)]`, so non-test code is unchanged.

Removing the missing-secret guard (replacing it with
`unwrap_or_default()`) fails
verify_hmac_rejects_every_delivery_when_no_secret_is_loaded and
config_pr_answers_503_when_no_secret_is_loaded. Deleting the
missing-header guard fails
verify_hmac_rejects_a_delivery_with_no_usable_signature_header. Breaking
the "unavailable" match fails the 503 test.

Without the missing-header guard, an unsigned delivery is still refused
by `verify_signature` (no `sha256=` prefix). The test therefore pins the
guard's own message rather than the bare rejection.

Closes #4654
2026-10-02 18:20:31 +02:00
atlas
7d217f8267 remove the create_repo agent tool
mara ruled on #4849 (c88934): "remove create_repo tool". The tool ran in
hive-c0re with the hive's core token, so it only ever worked for agents
on the hive that runs the forge.

Removed:

- the create_repo MCP tool and CreateRepoArgs (hive-agent-mcp)
- wire variants Request::CreateRepo and Response::RepoCreated
  (hive-core-agent-sock)
- hive-c0re's handle_create_repo, its valid_repo_name check and the
  dispatch arm
- forge::create_agent_repo and apply_operator_branch_protection, which
  had no other caller, plus AGENTS_ORG and OPERATORS_TEAM, whose only
  users they were
- the tool's docs (docs/tools/forge.md repo management, docs/turn-loop/
  mcp.md, the conventions tool-group table) and the doc comments that
  named it (hive-sock-client's response timeout, ensure_repo_creation_
  disabled, the security doc's merge-gate bullet)

ToolGroup::Forge is kept with no tools, the same way b88a5b24 kept
Lifecycle, so existing meta/capabilities.json grants still parse.

Forge state is untouched: existing agents/* repos keep their collaborators
and operators-team branch protection. The swarm-controller's own
create_repo (config-org repos) is a different path and is unchanged.

Closes #4849
2026-10-01 09:04:17 +02:00
atlas
386741d38f hive-c0re: keep agent and manager listeners alive across accept errors
Both accept loops returned on the first accept() error. The AgentSocket
stayed in Coordinator.agents, so mcp_sockets::sync_on_start skipped the
agent, and only a Start node or a hive-c0re restart bound it again. The
unit sets no LimitNOFILE, so a single EMFILE at the 1024-fd soft limit
cut the agent off from send/recv/ack with one warn line as the only
trace.

Both loops now share accept_until_fatal. Connection errors
(ECONNABORTED/ECONNRESET/ECONNREFUSED) retry at once, any other error
retries after 1 s, following axum's serve loop that the dashboard
already runs. Errors that leave the listening fd unusable (EBADF,
EFAULT, EINVAL, ENOTSOCK, EOPNOTSUPP) log at error and exit the
process: nothing re-binds a listener while hive-c0re runs, the manager
listener has no re-bind path at all, and the unit's Restart=on-failure
restart runs start_manager and sync_on_start, which re-bind every
socket.

mcp_sockets.rs now states that invariant instead of asserting that a
listener can only disappear on restart.

LimitNOFILE is left unset: per-agent fd use is a listener plus a
Recv long-poll plus short-lived requests, and a higher limit would raise
the memory ceiling of the per-line bound (bound x open connections).

Closes #4721
2026-09-27 03:48:56 +02:00
atlas
65a1f8d902 hive-c0re: bound request lines on the agent and manager sockets
serve() read each request with read_line into an unbounded String, so
size checks such as the 4 KiB Send body limit ran only after the whole
line was buffered. Any process in an agent container can write to
/run/hive/mcp.sock, and one stream with no newline grew hive-c0re's heap
until the host OOM-killed it.

Read at most 16 MiB per line. The largest request a client sends is an
OperatorMsg from the agent web UI's /send, whose body axum's default
limit caps at 2 MiB (the gateway's nginx admits 10 MiB); JSON escaping
can roughly double that, and the cap is 4x the result. A longer line
gets a Response::Err, the same shape as the parse-error path, and the
connection is closed because the rest of the line is still unread.

The line is read as bytes and parsed with serde_json::from_slice, so a
line with invalid UTF-8 now gets a parse-error response instead of the
connection being dropped.

Closes #4718
2026-09-27 03:48:56 +02:00
atlas
e0b08fe362 hive-c0re: fail on an unparseable permission file, write it atomically
tool_groups::read and capabilities::read returned an empty map when
their file existed but didn't parse. Every set_*/remove_agent is a
read-modify-write, and write() rewrote the file in place, so a crash or
ENOSPC mid-write left a truncated file, and the next write (e.g. the
manager-spawn seed of ruth's tool groups) replaced it with a map holding
only one agent. The scheduling and approval gates then denied every
other agent, recoverable only from meta git history.

- Both registries now read through agent_config::read_map: a missing
  file is still the empty map, any other read failure or a parse
  failure is an io::Error. set_groups / set_caps / remove_agent fail
  without writing.
- Writes go through agent_config::write_map: temp file in the same
  directory, fsync, rename, fsync the directory. hive-c0re had no
  shared atomic-write helper (the existing tmp+rename sites are inline
  and don't fsync).
- Callers of read / groups_for / has_cap now handle the error:
  * dashboard GET /api/tool-groups, /api/capabilities,
    /api/permissions/stale return 500 instead of an empty table;
  * the SSE permission snapshots are skipped with a warn;
  * render_flake returns Result, so sync_agents fails instead of
    rendering every agent without its tool groups / capabilities;
  * set_nspawn_flags propagates has_cap's error;
  * the socket tool-group gates deny with the read error as message;
  * seed_manager_tool_groups logs and does not seed.
- capabilities::write had no callers left once set_caps writes through
  write_map, and is removed.

Closes #4719
2026-09-26 21:11:54 +02:00
atlas
d2c4c8d4a3 docs: drop dead-claim narration for the retired loose-ends override
The PR retiring loose-ends' manager-only visibility replaced the false
claim with prose narrating its retirement, which still adds lines for
a removal. Delete the dead claim outright instead of documenting that
it used to be true: drop the three added sentences in
agent-hierarchy.md, and shorten socket_server/mod.rs's authority
comment to state only what's true now (tool-group membership for the
orchestration verbs) rather than adding an explanatory clause for the
removed capability check.
2026-09-24 12:24:32 +02:00
atlas
f53508cb2b docs, hive-c0re: retire prose describing the removed get_loose_ends target
Follow-up to 729c5b4f42, which dropped the
`agent` parameter from get_loose_ends and deleted Capability::QueryAgentState
with it. Three prose sites still describe the interface that commit removed:

- socket_server/mod.rs's module doc claimed authority on this socket derives
  from "capabilities for the hive-wide queries and tool-group membership for
  the orchestration verbs". There are no capability-gated queries left —
  `git grep -n has_cap -- hive-c0re/src/socket_server/` returns nothing, and
  require_group("scheduling") is the only gate in dispatch_orchestration.
- agent-hierarchy.md listed loose-ends visibility ("manager sees hive-wide,
  sub-agents only their own") as one of the manager-only overrides that
  "exist across hive-c0re today". It doesn't, and the sentence pointed a
  reader at loose_ends.rs for owner-check logic that is no longer there.
- conventions.md's Loose-ends wire shape still spoke of "the agent-flavour
  and manager-flavour requests" and "the agent-flavour list". There is one
  request shape.

No behaviour change: prose only.

Refs #4480
2026-09-24 12:24:32 +02:00
atlas
d94bc2188d topology: drop the parent field and the hierarchy it fed
`topology.json` was a map of `name -> parent | null`, and that value fed
the whole agent hierarchy: `<parent>` / `<children>` recipient sentinels,
the reparenting API (CLI verb, wire verb, dashboard endpoints, DAG node),
the dashboard tree, the rebuild depth sort, and an unconditional
bind-mount grant giving every agent RW on its direct children's state.

Per the operator's ruling the field goes, and with it all of the above.
The file survives as what remains once the value is gone: the roster of
agent names, which is the set `ManageRootAgent` grants mounts over. It is
now a JSON array; `read` still accepts the old map shape and keeps its
keys, so a hive that upgrades across this does not blank its roster (and
so no capability holder loses its mounts for the length of that window).

Two sites kept their behaviour under a different recipient rather than
losing it. Both addressed `<parent>`, which the broker already resolved to
`operator` for a root agent, and every agent is now what that fallback
called a root:

- the harness's turn-failure / plugin-failure notification
  (`Surface::send_to_parent` -> `send_to_operator`), and
- the send allow-list's always-permitted escape hatch, so an agent with a
  restrictive allow-list still has a way to say it is stuck.

What is NOT preserved, deliberately: an agent with no capability no longer
sees any other agent's dirs. `ManageRootAgent`'s own grant is unchanged --
still every agent in the roster, still state RW + config RO, still no
`harness`.

The dashboard's reparenting control (the M0V3 picker) is deleted with its
CSS. The tree rendering that reads `ContainerView.parent` is left for the
frontend owner -- it degrades to a flat list with the field gone.
2026-09-21 22:08:47 +02:00
atlas
11097ed336 remove the get_host_journal MCP tool and its capability
swarm-logs covers every host-tier unit this tool could reach, so the
second, capability-gated path into host journald earns nothing and is
removed outright rather than disabled behind a flag.

Removed end to end: the MCP tool definition + handler, the
GetHostJournal/HostJournal wire variants, hive-c0re's
dispatch_host_journal handler, the ReadHostJournal capability, and the
harness-side capability->--allowedTools gate. get_host_journal was the
only capability that mapped to an MCP tool, so allowed_capability_tools
could only ever return an empty vec; it goes too rather than linger as a
function that provably does nothing.

capabilities::has_cap/caps_for stay: #4624 gave ManageRootAgent's
bind-mount enforcement (hive-c0re/src/lifecycle/host_config.rs) a
second caller of has_cap, so they're no longer callerless once this
lands on top of it.

hive-sh4re's journal module (JournalPriority) had no consumer outside
this tool and is deleted.

An existing capabilities.json still naming read_host_journal does not
error: capabilities::prune_unknown drops unrecognised names with a
warn!, and an agent left with no capabilities has its entry removed. No
migration step is needed.

Untouched: hive-c0re/src/dashboard/journal.rs's
read_host_journal_response, which matches the name but is the private
helper behind the operator-only GET /api/journal-host dashboard route
and carries no capability check.
2026-09-21 19:31:45 +02:00
atlas
4121e11d87 hive-c0re: drop the subtree check from the scheduling verbs
The topology predicate `is_descendant_of` gated the four schedule-
managing verbs: a caller could only name a schedule owned by an agent at
or below itself in `topology.json`. Those gates now permit any requester,
so the predicate, its pure `_in` form and the `schedule_authorized`
wrapper built on it are gone rather than left returning a constant. The
other two wrappers went earlier with the verbs they served —
`require_descendant` with the lifecycle MCP verbs in 87970a8c, and
`resolve_agent_state_target` with `get_loose_ends`'s agent parameter.

`require_group(agent, "scheduling", ...)` is untouched and still fires at
dispatch for every one of the five scheduling verbs, so holding the tool
group remains the gate; what goes is the ownership restriction layered on
top of it.

The three schedule-mutating verbs keep their row lookup as a plain
existence check, so a caller naming a schedule that does not exist still
gets `not found` rather than a message from deeper in the cancel path.
`list_schedules` stops filtering per row: it would only have hidden rows
the requester may act on anyway.

Error messages, tool descriptions and docs that described the subtree
relation are reworded — a refusal message naming a topology that no
longer decides anything is worse than none.

The six `is_descendant_of_in` unit tests go with the function they test;
the permit behaviour they leave unasserted is picked up by the next
commit.

Refs #4472
2026-09-21 17:20:44 +02:00
atlas
b88a5b2430 remove the list_containers and request_update_meta_inputs MCP tools
Both agent-facing tools go away end to end, with no replacement. This is
an intentional capability removal: agents can no longer enumerate their
own subtree, and can no longer queue a meta-flake input bump.

The system prompt and docs/tools/lifecycle.md land in this same commit
on purpose. A tool named in the prompt but absent from the server makes
agents confidently call something that doesn't exist, and the failure
then surfaces far from its cause.

Removed:

- MCP registrations and bodies (hive-agent-mcp), plus the now-unused
  UpdateMetaInputsArgs.
- Wire variants Request::ListDescendants,
  Request::RequestUpdateMetaInputs and Response::Containers, plus
  ContainerInfo, whose only consumer was that response.
- hive-c0re's handle_list_descendants (its whole module) and
  handle_request_update_meta_inputs, the two dispatch arms, and the
  require_group(agent, "approvals", ...) gate on the meta-inputs verb.
- The stream_enrich emoji entry and argument formatter.
- docs/tools/lifecycle.md (both tools it documented are gone), its two
  referrers, the tool-group tables and the agent-hierarchy prose.

Tool groups are kept, deliberately. ToolGroup::Lifecycle listed exactly
one tool and now lists none — it is vestigial, but the variant stays so
existing meta/capabilities.json grants still parse; retiring it is a
separate decision. ToolGroup::Approvals also listed exactly one tool,
but the group is NOT dead: check_can_cancel_approval still gates
cancel_loose_end's approval-cancel arm on it server-side.

ApprovalKind::UpdateMetaInputs stays too. Nothing in production code
produces it any more, but pre-existing approval rows may still carry it,
and the operator's own path to a meta update is unaffected — the
dashboard's POST /api/meta-update inserts the meta_update job directly,
bypassing approvals entirely.

The two format_ack tests in hive-agent-mcp that named
request_update_meta_inputs were only using it as a label string while
exercising the generic OkWarn/Ok renderer, so they are retargeted to a
surviving tool rather than deleted.

Note hive-c0re's priv_client::list_containers is a different thing (the
host-side privileged container listing behind hive-priv) and is
untouched.

Closes #4591
2026-09-20 22:47:46 +02:00
atlas
f7843d727d hive-c0re: fix stale GetLooseEnds example in dispatch_shared doc comment
The parenthetical claimed the manager can target other agents via
GetLooseEnds — true before 65481273, false since. It was the only
socket-specific example that comment ever had, so rewrite the sentence
to name what dispatch_shared actually defers: ListDescendants and the
orchestration verbs, which need per-verb tool-group gating, plus
host-admin/unknown requests.
2026-09-20 05:36:49 +02:00
atlas
729c5b4f42 hive-agent-mcp, hive-c0re, hive-sh4re: drop agent param from get_loose_ends
get_loose_ends now always returns the caller's own loose ends, for every
caller including the manager (ruth) — there is no separate manager
surface, ruth is a normal agent with different default capabilities.

- AgentGetLooseEndsArgs removed; get_loose_ends takes no args.
- Wire Request::GetLooseEnds collapses from an Option<String> target to
  a unit variant.
- hive-c0re's handle_get_loose_ends drops the "*" hive-wide branch and
  the subtree/capability resolver (resolve_agent_state_target); both
  are gone since there is no longer a target to resolve.
- loose_ends::hive_wide and Capability::QueryAgentState removed as
  dead code — their only callers were the two functions above.
- is_descendant_of is untouched (still used by lifecycle_handlers.rs
  and schedules.rs independently of this change).
- Docs updated: docs/turn-loop/mcp.md, docs/web-ui/dashboard.md,
  docs/process/conventions.md (Loose-ends wire shape + capabilities
  table), plus the doc comments in hive-core-agent-sock, mcp_config.rs
  and capabilities.rs that described the old shape.

Refs #4480
2026-09-20 05:36:49 +02:00
atlas
87970a8c93 mcp: remove the restart/kill/start/update/get_logs agent verbs
Container lifecycle from inside an agent goes away: an agent no longer
starts, stops, restarts or rebuilds a container in its subtree, and no
longer reads another container's journal. Those are operator actions —
the dashboard and hivectl keep their own paths to the same job-queue
and hive-priv plumbing, which is why none of that machinery is removed
here, only the five MCP verbs and what they alone reached.

What went with them: the `Request` variants and `Response::Logs` on the
agent socket, the five tool definitions and their arg structs, the four
lifecycle handlers plus `handle_get_logs`, and `require_descendant` —
the topology guard those five were the only remaining callers of.
`ToolGroup::Diagnostics` goes too: `get_logs` was its only tool, so it
would otherwise be a grantable group that grants nothing. `lifecycle`
stays, now carrying `list_containers` alone.

An agent that gets a `needs_update` or `container_crash` helper event
has no remedy of its own left, so the system prompt and the docs now
send it to the operator instead of to a tool that no longer exists.

Refs #4480
2026-09-19 10:47:39 +02:00
atlas
a3b672d1d5 refactor(hive-c0re): drop the request_init_config tool and InitConfig approval
swarm-controller's `InitAgentConfigRepo` node already covers config-repo
creation, so this deletes a duplicate rather than a capability; old
`init_config` rows are skipped by `collect_lenient` with no migration, by
operator decision.

Refs #4398
2026-09-14 19:03:44 +02:00
damocles
46456f75ce remove as_str() legacy wrappers, callers use .into() directly 2026-09-12 00:06:31 +02:00
atlas
c28da210b4 scheduling: clamp get_logs host-side, and fix two authorization claims
`docs/tools/scheduling.md` said three things about who may do what. Two
were wrong prose; the third was the code.

"All scheduling ops go through the operator approval queue" — one of the
five does. Cancel, edit, list and fire are `require_group("scheduling")`
and nothing else (socket_server/mod.rs:594-643), which is what the MCP
tool descriptions already tell an agent. The page pushed in the cautious
direction: someone watching a runaway recurring schedule would wait for
an operator rather than cancel it themselves.

The authorization sentence covered "read/cancel/edit". Cancel, edit and
fire really do check `cancel_authorized` (self, operator, or subtree) from
three call sites. `handle_list_schedules` takes no requester at all and
returns every row — now stated, along with the part that matters: the
snapshot includes other agents' schedule bodies.

`lines` was documented as "host-capped at 500" and the 500 was in the
agent's own MCP layer, not the host; `handle_get_logs` passed any u32
straight into JournalQuery. A limit in the caller is not a limit, so the
host clamps instead of the sentence changing. That also makes args.rs's
arg doc and the tool description agents read correct, untouched. The
sibling `get_host_journal` already clamps host-side at 100, which is both
the precedent and the control that the missing clamp here was real.

Closes #4230.
2026-09-11 18:43:10 +02:00
damocles
79c43a15d8 hive-c0re: scope list_schedules to what the requester can actually act on
handle_list_schedules took no requester and returned every schedule
unfiltered, unlike cancel_schedule/edit_schedule/fire_schedule_now
which all gate on the shared ownership predicate (self, operator, or
subtree via topology::is_descendant_of). list_schedules now filters
through the same predicate, renamed cancel_authorized ->
schedule_authorized since it backs all four verbs now, not just
cancel.

Fixed five stale 'every schedule' / 'unfiltered' claims found while in
here: filter_ghost_schedule_targets's doc comment, the list_schedules
MCP tool description, docs/tools/scheduling.md's per-verb section
(already self-contradicting its own top-of-file subtree-scoping claim
before this fix), and hive-core-agent-sock's ListSchedules/Schedules
wire-type doc comments (including a stale '(privileged)' marker from
the pre-topology-subtree model).

Credit to atlas: independently found the same fix while finishing
PR #4233 (which documents this bug per mara's 'fix it, don't document
it' ruling) and caught two stale doc spots I'd missed
(hive-core-agent-sock's comments) plus proposed the
schedule_authorized rename. Compared diffs directly before either of
us pushed; he dropped his scheduling.rs changes so we didn't collide.

fixes #4237
2026-09-11 18:05:13 +02:00
atlas
0a80f21003 prompts+docs: the lifecycle tools reach the whole subtree, not just direct children
`require_descendant` (`socket_server/mod.rs:666`) authorises
kill/start/restart/update/get_logs with `topology::is_descendant_of` — the
caller's whole subtree, itself included. That has been true since `53b4e752`
(#1865), whose message says "a parent owns its whole subtree; the root covers
every agent as a consequence, no positional privilege", and two tests pin it
(`is_descendant_of_in_grandchild`, `is_descendant_of_in_self_is_true`).

The prose never followed. The four lifecycle tool descriptions, their
`// IMPORTANT:` comments, `docs/tools/lifecycle.md`, the tools README,
hive-agent-mcp's README and the system prompt every agent is rendered from all
still said "direct children only" — while `list_containers`, four tools away in
the same file, said "direct children + their subtrees".

`lifecycle.md` also taught the model #1865 deleted: "Privileged agents (for
example ruth) may operate on any sub-agent — the topology scope applies to all
others." There is no privileged class to belong to; ruth reaches every agent
because the check is transitive and everything sits under it.

Same drift on the state-query side: `resolve_agent_state_target` is
subtree-scoped by the same commit, so `get_loose_ends`' argument doc, the
`QueryAgentState` capability doc and `docs/turn-loop/mcp.md` were all telling a
parent it needs a capability to read a grandchild's threads.

Two smaller corrections found on the way:

* `list_containers` returns the caller itself. `is_descendant_of` is true for
  `candidate == ancestor` and `handle_list_descendants` filters the topology
  with it; called from a leaf agent it answers one row, that agent.
* `request_init_config` accepts any unused name — the requester becomes its
  parent — or an existing agent already in the caller's subtree, not "a direct
  child". The editing surface is narrower than the guard, though: only direct
  children's config repos are bind-mounted, so re-seeding deeper in the subtree
  leaves no local copy to edit. `lifecycle.md` now says so.

The prompt's other stale claim, the dead `request_apply_commit`, is #4226 and
was fixed independently by damocles in #4227 while this was being gated. This
branch keeps only the scope wording on that line.

Closes #4225.
2026-09-11 15:23:50 +02:00
iris
07b62612b0 docs: restructure into topic subdirectories, collapse duplicated index
Per mara's go-ahead on hyperhive#3902 ("getting started is good, but
terminal rendering does not go in there i think"):

Moved 21 top-level docs/*.md files into 7 new topic subdirectories
(existing web-ui/, turn-loop/, swarm/, tools/, crates/ untouched):
  getting-started/  setup.md
  agent-lifecycle/  agent-hierarchy.md, approvals.md, persistence.md
  trust-boundary/   boundary.md, security.md
  integrations/     forge.md, matrix.md, github.md, knowledge.md
  networking/       gateway.md, network.md, snapshot-store.md
  scheduler/        jobq.md, coordinator.md, ci.md, observability.md
  process/          conventions.md, gotchas.md, pr-review-gate.md
  web-ui/           terminal-rendering.md (moved into the EXISTING dir,
                    per mara's correction to the original getting-started
                    guess -- it's UI implementation detail, not onboarding)

The physical layout now matches docs/README.md's own topical headers,
which already amounted to this taxonomy -- see the scoping comment on
the issue for the two findings that motivated this (a genuine
duplication between CLAUDE.md's old "Reading paths" list and
docs/README.md's grouped one, since drifted out of sync with each
other; and the flat layout not matching the grouping we already had).

Fixed every cross-reference this moved across the whole repo (~120
files: docs/ internal links at every depth, Rust doc comments, nix
module option docs, crate READMEs) -- verified two ways: a grep sweep
confirming zero remaining references to any old path, and a script
that resolves every markdown link in docs/**/*.md + CLAUDE.md +
README.md against the filesystem and reports anything that doesn't
exist (zero broken links).

Collapsed CLAUDE.md's "Reading paths" section (the duplicate) down to
a pointer at docs/README.md, now the single index. Rewrote
docs/README.md itself to use the new subdirectory paths and added the
one doc it was missing that CLAUDE.md's old copy had (pr-review-gate.md).

Classified all 22 docs/*.md files first via a haiku subagent (mara's
suggestion) on two axes -- proposed grouping and operator-vs-
implementation focus -- before finalizing the taxonomy; spot-checked
the report and found internal inconsistencies (its classification
table disagreed with its own summary section for a few files), so this
taxonomy is my original proposal + the one correction mara gave
directly, not a blind application of the subagent's table. The
operator-focus data it gathered is still useful for a follow-up
content pass (docs skewing 'mixed' rather than pure operator-facing),
not addressed in this PR -- structure only.

nix fmt clean, both pre-push lints clean.
2026-09-02 01:55:37 +02:00
damocles
2850270829 hive-c0re/hive-sh4re: remove the ask/answer wire protocol + core routing 2026-08-30 01:18:17 +02:00
damocles
47cac50e6e hive-c0re: remove the dashboard's ask/answer surface 2026-08-29 23:20:17 +02:00
damocles
20a7a21053 hive-c0re/hivectl/hive-agent: pause as a job-queue DAG node (closes #3056) 2026-08-11 23:47:09 +02:00
damocles
80f16094f1 hive-sh4re: split inbox, container, journal, and schedule wire shapes into their own modules
Closes the #3110 split — lib.rs is now just the crate doc comment and
the pub mod list.

journal.rs's new doc comment fixes a pre-existing bug: the old
JournalPriority doc text in lib.rs was actually half Capability's doc
(a leftover from an earlier reorder that moved the code but not the
comment above it).
2026-08-10 23:26:15 +02:00
damocles
d3ac4de8fb hive-sh4re: split tool-group + capability enums into their own topic module 2026-08-10 23:05:18 +02:00
damocles
138f6b6c10 hive-sh4re: split manager-socket constants + HelperEvent into their own topic module 2026-08-10 23:05:18 +02:00
damocles
66a3c2409c rename JournalPriority::as_str to as_journald_str 2026-08-10 16:19:40 +02:00
damocles
4835ca8c91 hive-c0re: list_descendants reads cached container snapshot instead of live systemctl calls 2026-08-01 15:30:57 +02:00
damocles
a80d0b0fed delete c0re-side reminder plumbing (#2635 inc 1 commit 6) 2026-07-23 00:12:30 +02:00
damocles
4989bcdb5e type Message.from as Ident 2026-07-22 21:10:17 +02:00
damocles
8c1979f05c type get_agent_meta target as Ident (#2621) 2026-07-22 21:10:17 +02:00
damocles
3df565789c type ask to target as Ident (#2621) 2026-07-22 21:10:17 +02:00
damocles
0977006ec6 refactor(#2569): remove the c0re todo store + handlers (todos now owned in-container) 2026-07-20 23:29:26 +02:00
damocles
795dd882bb refactor(#2569): rename hive-agent-sock to hive-core-agent-sock 2026-07-20 21:58:28 +02:00
damocles
84b750fba5 refactor(#2302): type socket wire fields as ident, validated by serde on deserialize 2026-07-20 21:46:18 +02:00
damocles
bf644cc126 feat(#2302): thread &Ident through agent path builders 2026-07-20 21:46:18 +02:00
damocles
1286029947 feat(#2302): migrate dashboard to the single hive-host-sock Ident newtype 2026-07-20 21:46:18 +02:00
damocles
cfac917b4d feat(#2302): parse agent names into AgentName newtype at dashboard boundary 2026-07-20 21:46:18 +02:00
damocles
144912f8e0 address review: drop backwards-compat request/response aliases, use canonical names 2026-07-19 15:53:09 +02:00
damocles
d0beec8a40 refactor(#2581): carve per-agent mcp.sock protocol into hive-agent-sock crate 2026-07-19 15:53:09 +02:00
damocles
8149dc7633 fix(#2569): wake body points at get_loose_ends (get_todos rename is a later increment); strip tracker tags from source comments per hive-rules 2026-07-19 13:28:17 +02:00
damocles
6685b33c9d feat(#2569): DB-backed per-agent todo store + mcp.sock upsert/clear/list/mark-done ops 2026-07-19 13:28:17 +02:00
damocles
c2bd7db998 refactor(#2416): remove the non-pr config-change flow (request_apply_commit / applycommit) 2026-07-15 21:03:52 +02:00
atlas
860484a193 refactor(#2439): build hive-wide stop/start/restart DAGs dynamically
Hive-wide `stop` / `start` / `restart` emit ONE DAG with a per-agent
subgraph each (concurrent on their own leases) instead of N DAGs — and each
subgraph is now built dynamically from the agent's live running state rather
than a fixed template shape:

- online agent: the full stop→reconcile (restart: stop-for-update→reconcile)
  chain; `graceful` prepends signal→drain.
- offline agent: just `SetWanted → Reconcile` (nothing to quiesce/stop; a
  restart of a down agent is really a start).

The head `SetWanted` (intent) and tail `Reconcile` (convergence guarantee)
are always present; only the mechanical `Signal`/`Drain`/`StopForUpdate`
nodes are state-conditional. Keeping `Reconcile` in every shape closes the
TOCTOU window — a race-up between the `is_running` read and node exec is
still converged in-DAG (with `StopForUpdate`-noop as the backstop) — with no
reliance on an external reconcile sweep.

The state-aware assembly needs an async `is_running` read, so it moves out
of the pure/sync `templates.rs` into `submit.rs`, layered as pure
`*_chain(running)` → pure `*_spec(targets)` (the unit-test seam) → async
`*_many` (reads live state + submits). `templates.rs` keeps only the shared
pure primitives (`node`/`after_ok`/`rebuild_nodes`).

Callers await the now-async submit fns (server, dashboard, socket_server).
Tests exercise both the online and offline shapes via the pure `*_spec`
seam. docs/coordinator.md shapes updated.
2026-07-15 00:29:54 +02:00
atlas
e0461e1af6 refactor(#2431): extract hive-priv-sock crate from hive-sh4re
Split the priv-socket wire types (PrivRequest/PrivResponse/PrivEvent and
friends) out of hive-sh4re into their own hive-priv-sock crate, mirroring
the existing hive-host-sock split. hive-priv — the root-privileged
helper — now depends on just this narrow protocol crate instead of the
much larger daemon-shared crate, shrinking its dependency surface and
making the privsep boundary easier to audit. No server/client
implementation lives here, only the wire contract; hive-c0re still
depends on hive-sh4re directly for everything else.
2026-07-14 20:02:20 +02:00
atlas
949fcf2f16 fix(#2377): remove unused submit_init_config re-export from socket_server
submit_init_config is only called within config_approvals.rs itself;
the pub(crate) re-export on mod.rs was unused (clippy unused_imports).
2026-07-11 12:19:52 +02:00
atlas
d5a81f9195 feat(#2377): forge-webhook-triggered config-PR merge flow
Replace the request_merge_config_pr MCP tool with a Forgejo
pull_request webhook on the agent-configs org. Agents now open a
config PR normally; hive-c0re auto-queues the MergeConfigPr approval
from the webhook event — no extra tool call needed.

Changes:
- dashboard/webhook.rs: add POST /webhook/config-pr handler
  - parses Forgejo pull_request payload (opened/synchronize)
  - strips agent-configs/<agent> prefix to extract agent name
  - calls submit_merge_config_pr → queues dashboard approval card
  - always 200 to prevent Forgejo retries; errors logged at warn
- dashboard/mod.rs: wire /webhook/config-pr route
- forge/mod.rs: add ensure_config_pr_webhook() — idempotent org-level
  hook registration on agent-configs at startup; CONFIG_ORG now
  pub(crate) for webhook handler
- main.rs: call ensure_config_pr_webhook alongside knowledge webhook
- socket_server/config_approvals.rs: drop handle_request_merge_config_pr;
  make submit_merge_config_pr pub(crate) for webhook handler
- socket_server/mod.rs: re-export submit_merge_config_pr; drop dispatch arm
- hive-sh4re/src/lib.rs: remove AgentRequest::RequestMergeConfigPr
  wire type; drop from ToolGroup::Approvals tool list
- hive-ag3nt/src/mcp/: drop request_merge_config_pr tool + args struct
- docs: update approvals.md (webhook trigger), conventions.md (tool
  group), agent-hierarchy.md, tools/lifecycle.md

Hardening from #2375-merge-config-pr-hardening branch preserved:
- pr_is_open check at queue time (rejects closed/merged PRs)
- atomic fetched_sha INSERT via submit_kind(fetched_sha: Some(&sha))

Approve-handler machinery unchanged (run_merge_config_pr,
ff_push_to_main, fetch_pr_head_into_applied, mark_pr_merged).
2026-07-11 12:19:52 +02:00
atlas
97edd6baac feat(#2346): request_merge_config_pr — submission path for the PR-based config flow
MergeConfigPr approvals had a fully-implemented approve handler
(run_merge_config_pr, ff_push_to_main, mark_pr_merged) and dashboard
display, but no way to submit one.  An agent with the `approvals` tool
group calling request_merge_config_pr(agent, pr_number) is the missing
piece.

What this adds:
- RequestMergeConfigPr variant in hive-sh4re AgentRequest + ToolGroup::Approvals
- submit_merge_config_pr: fetches PR head sha (the drift-gate reviewed sha),
  queues a MergeConfigPr row, sets fetched_sha, emits approval_added with
  pr_number so the dashboard card links to the forge PR
- handle_request_merge_config_pr: topology (require_descendant) +
  tool-group (require_group(approvals)) guards before submit
- socket_server/mod.rs: dispatch arm for RequestMergeConfigPr
- hive-ag3nt MCP tool: request_merge_config_pr with full description
- docs/tools/lifecycle.md: documents the new tool + boundary table row

Unlike submit_apply_commit, no flake pre-flight at submission time (eval-
verify happens at approval time inside run_merge_config_pr, same as the
rest of the merge pipeline).  Applied repo must already exist (guard added
with a clear error message pointing at request_apply_commit for first-spawn).
2026-07-11 12:19:52 +02:00
damocles
cfb84b420a refactor(#2285): drop coordinator 1:1 path accessors, callers use paths:: directly 2026-07-10 20:32:03 +02:00