feat(fleet): security/trust + headless-worker foundation; unify recursion depth

Lands the Agent Fleet security/trust boundary and the headless-worker bridge on
the v0.8.60 line, and collapses the sub-agent and fleet recursion model into a
single shared axis (Hunter steer: "not two moving targets").

Security & trust (#3165):
- FleetTrustLevel, FleetSecurityPolicy, FleetSecretRef (redacted), FleetWorkerAuth,
  FleetCapabilityGrant, FleetAlertEndpoint (redacted) in protocol.
- secrets: resolve_direct(key, source_hint) — fleet secret resolution, never logged.
- Host adapters refuse secret-bearing env keys; SSH uses SendEnv (no argv secrets).

Roles & delegation (#3167):
- fleet role -> SubAgentType mapping; reviewer/verifier default read-only.

Headless worker bridge (#3096/#3154, partial — still simulation, real spawn next):
- worker_runtime: FleetTaskSpec -> AgentWorkerSpec, status -> ledger events,
  exec hardening (mirrors #3027), parallel-safe read-only tool set (#2983).
- FleetManager carries an optional SharedSubAgentManager + exec config.

Recursion depth — ONE axis:
- codewhale_config now owns DEFAULT_SPAWN_DEPTH (3) + MAX_SPAWN_DEPTH_CEILING (3).
- sub-agent DEFAULT_MAX_SPAWN_DEPTH and the fleet clamp both source these consts.
- fleet default raised 1 -> 3 to match standalone sub-agents; root runs at depth 0,
  budget gates child delegation. End-to-end test proves a depth-0 fleet worker
  reaches 3 nested levels (afford >= 3).

Dogfood scaffolding (#3166, partial): docs/examples/fleet-dogfood.toml.

Tests green: codewhale-config fleet, codewhale-tui fleet (58), subagent max_depth;
cargo fmt + git diff --check clean; cargo check --workspace ok.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hunter B
2026-06-13 01:10:30 -07:00
parent 344e89c93d
commit e8b52ac57a
21 changed files with 2223 additions and 123 deletions
+51
View File
@@ -915,6 +915,57 @@ default_text_model = "deepseek-ai/deepseek-v4-pro"
# printf '%s\n' '{"content":"audit wrapper placeholder: configure an executor","success":false}'
# ```
# ─────────────────────────────────────────────────────────────────────────────────
# Agent Fleet trust, security, and role registry (#3165, #3167)
# ─────────────────────────────────────────────────────────────────────────────────
# [fleet]
# # Default trust level for fleet workers: "sandbox" | "local" | "remote-verified" | "operator"
# default_trust_level = "sandbox"
# # Require SSH host-key verification before granting remote-verified trust
# require_identity_verification = true
# # Maximum trust level any worker may have
# max_trust_level = "operator"
#
# # Headless worker execution hardening (#3027)
# [fleet.exec]
# # Tools always allowed regardless of role
# allowed_tools = []
# # Tools always disallowed (overrides role and task spec)
# disallowed_tools = ["exec_shell"]
# # Hard ceiling on worker steps (tool calls + model turns)
# max_turns = 500
# # Recursive child-agent depth for fleet workers. Shares ONE recursion axis
# # with standalone sub-agents (a fleet worker IS a headless sub-agent).
# # 0 blocks child agents (the root worker still runs); 3 is the default and the
# # cap, affording at least three nested delegation levels.
# max_spawn_depth = 3
# # Extra system prompt injected into every headless worker
# append_system_prompt = "Never modify .git/config or change remotes."
# # Output format: "text" (default) or "stream-json" for ndjson events
# output_format = "text"
#
# # Built-in role presets are always available: smoke-runner, reviewer, builder, read-only.
# # User-defined roles here override or extend the built-in set. Any key under
# # [fleet.roles] becomes a valid role name that task specs can reference.
# [fleet.roles.ci-linter]
# description = "Runs linters and formatters"
# tool_profile = "read-only"
# tools = ["cargo", "cargo-clippy", "cargo-fmt"]
# capabilities = ["rust"]
# max_tokens = 12000
# max_tool_calls = 20
# timeout_seconds = 600
#
# [fleet.roles.pr-reviewer]
# description = "Reviews PRs with GitHub access"
# tool_profile = "read-only"
# tools = ["git", "gh", "rg"]
# capabilities = ["git", "github"]
# max_tokens = 16000
# max_tool_calls = 30
# timeout_seconds = 900
# trust_level = "local"
# ─────────────────────────────────────────────────────────────────────────────────
# Requirements (admin constraints) example file
# ─────────────────────────────────────────────────────────────────────────────────