agent surface: create_repo through hive-c0re (#1787)

Closes the #1787 loop — the sanctioned create path now that agents
can't create repos directly. Adds:

- wire: Request::CreateRepo{repo} + Response::RepoCreated{full_name,
  clone_url} (hive-sh4re).
- agent_server: dispatch_shared arm + handle_create_repo — validates the
  repo name, then forge::create_agent_repo (org-owned repo, agent=write
  collaborator, operator-team branch protection). Returns the full name
  + clone url so the agent can git clone immediately.
- MCP: create_repo tool + CreateRepoArgs in the harness.
- a new opt-in ToolGroup::Forge (=[create_repo]) so the operator
  controls which agents can spin up repos (least privilege).

Workspace clippy -D warnings, cargo test, nix fmt all green.
This commit is contained in:
atlas 2026-06-19 12:57:01 +02:00 committed by mara
commit f1d54ce12c
4 changed files with 115 additions and 3 deletions

View file

@ -572,6 +572,13 @@ pub enum Request {
/// per-kind semantics in
/// `docs/conventions.md::Loose-ends wire shape`.
CancelLooseEnd { kind: CancelLooseEndKind, id: i64 },
/// Create a git repo *through hive-c0re* (#1787). Agents can't create
/// repos with their own forge token (`max_repo_creation = 0`); this is
/// the sanctioned path. hive-c0re creates `repo` in the c0re-owned
/// `agents` org, adds the calling agent as a write collaborator (not
/// owner), and applies operator-team branch protection so the author
/// can't merge its own PRs. Returns the new repo's full name.
CreateRepo { repo: String },
/// Mark every message popped since the last `AckTurn` as handled.
/// Harness↔broker pairing fired after `TurnOutcome::Ok`. See
/// `docs/conventions.md::Broker delivery + ack cycle`.
@ -753,6 +760,12 @@ pub enum Response {
/// `ListSchedules` result. Snapshot of every schedule.
/// Returned on the manager socket only.
Schedules { schedules: Vec<WireSchedule> },
/// `CreateRepo` result: the new repo's full name (`agents/<repo>`)
/// and clone URL, so the agent can immediately `git clone` it.
RepoCreated {
full_name: String,
clone_url: String,
},
/// `ListDescendants` result: all descendant containers, with running
/// status. Ordered by topology depth (parents before children), then
/// alphabetically within each depth tier.
@ -952,6 +965,10 @@ pub enum ToolGroup {
Scheduling,
/// `get_logs` - *(privileged)*
Diagnostics,
/// `create_repo` — create git repos through hive-c0re (the only path
/// now that agents can't create them directly; see #1787). Opt-in per
/// agent so the operator controls who can spin up repos.
Forge,
/// `run`, `status` (via `mcp__bash__*`)
Execution,
/// Claude built-in web egress tools: `WebFetch` (retrieve a URL) and
@ -991,6 +1008,7 @@ impl ToolGroup {
"list_schedules",
],
Self::Diagnostics => &["get_logs"],
Self::Forge => &["create_repo"],
Self::Execution => &["run", "status"],
Self::WebTools => &[],
}
@ -1044,6 +1062,7 @@ impl ToolGroup {
Self::Approvals,
Self::Scheduling,
Self::Diagnostics,
Self::Forge,
Self::Execution,
Self::WebTools,
];
@ -1060,6 +1079,7 @@ impl ToolGroup {
Self::Approvals => "approvals",
Self::Scheduling => "scheduling",
Self::Diagnostics => "diagnostics",
Self::Forge => "forge",
Self::Execution => "execution",
Self::WebTools => "web_tools",
}
@ -1088,6 +1108,9 @@ impl ToolGroup {
Self::Diagnostics => {
"get_logs — read a sub-agent container's systemd journal (privileged)"
}
Self::Forge => {
"create_repo — create git repos through hive-c0re (operator-gated merge)"
}
Self::Execution => {
"run, status — run shell commands via mcp__bash__run / mcp__bash__status"
}