Skip to content

Feat/shepherd supervision - #196

Merged
buchenberg merged 13 commits into
mainfrom
feat/shepherd-supervision
Aug 20, 2026
Merged

Feat/shepherd supervision#196
buchenberg merged 13 commits into
mainfrom
feat/shepherd-supervision

Conversation

@buchenberg

@buchenberg buchenberg commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added supervised task execution with checkpointing, automatic rollback, retries, and structured outcomes.
    • Added interactive review controls to continue, roll back, compare alternatives, accept, or abort work.
    • Added supervisor controls for monitoring scopes, providing guidance, and stopping agent activity.
    • Added role-based routing between standard and supervised sub-agent execution.
    • Added support for seeding sub-agent conversations with initial messages.
  • Bug Fixes

    • Failed tool runs and exhausted attempts can now restore prior work when checkpointing is enabled.
  • Documentation

    • Documented the new supervised tools and review workflows.

Integrates shepherd-kernel-go's effect bus, scope manager, and
supervisor primitives into yaah.

pipeline/trace.go:
- ShepherdTraceMiddleware now holds bus and scope manager
- Bus() and ScopeManager() accessors for tool integration

pipeline/config.go:
- shepherd_trace builder creates EffectBus and ScopeManager
- Bus attached to store via WithBus for real-time events
- ShepherdBusBuffer config field (default 64)

tools/supervisor.go (new):
- SupervisorTool with actions: list_scopes, fork, merge, discard,
  inject, halt
- Opens trace store directly, creates scope manager per call
- Registered when shepherd_trace_dir is configured

cmd/yaah/wiring.go:
- Register SupervisorTool when trace dir is set

The supervisor tool lets the orchestrator:
- List all scopes and their state
- Fork a sub-agent's execution branch
- Merge successful branches back
- Discard failed branches
- Inject guidance into a running scope
- Halt a stuck sub-agent
These operations require sandbox isolation to be meaningful. Without
it, fork/merge/discard are just trace bookkeeping — they don't isolate
or roll back filesystem changes. The underlying code in
shepherd-kernel-go still supports them for when sandboxed execution
is added.

Exposed actions: list_scopes, inject, halt, status
- Add tools.SharedScopeManager package-level variable
- Set it from the shepherd_trace pipeline builder
- SupervisorTool uses SharedScopeManager instead of opening its own store
- Runner creates scopes for sub-agents via SharedScopeManager

This fixes:
- SQLITE_BUSY from separate store connections
- Empty scope list from fresh ScopeManager each call
- Sub-agents now get scopes automatically on creation
…args

Two bugs causing TUI error popups:

1. trace_owner_id is required: PostTool/StartTurn/EndTurn/FailTurn
   now bail early when sessionID is empty, instead of passing empty
   strings to the trace store.

2. json.RawMessage panic: tool args are now validated with json.Valid()
   before wrapping in json.RawMessage. Invalid args (empty string,
   malformed JSON) are stored as a JSON-encoded string instead of
   causing a MarshalJSON panic.
Trace recording is best-effort. Failures (SQLITE_BUSY, schema errors)
should not surface as raw stderr in the TUI. The noop fallback already
handles graceful degradation — debug logging is sufficient for diagnosis.
Introduce session-wide shepherd infrastructure and a new supervised
task tool with checkpoint/rollback/retry. Trace store, effect bus,
and scope manager are now initialized once during wiring instead of
per-loop, preventing SQLITE_BUSY contention from concurrent writers.

Changes:
- Add InitShepherdInfrastructure in internal/agent/pipeline/scope_init.go
  to centralize store and scope manager creation.
- Register SupervisedTaskTool in cmd/yaah/wiring.go alongside the
  existing SupervisorTool.
- Add a curated sub-agent middleware pipeline for sub-agent loops,
  excluding orchestrator-only middleware (steer, approval, etc.).
- Add IsSubAgent flag to LoopConfig to select the pipeline builder.
- Refactor ShepherdTraceMiddleware to use tools.SharedTraceStore and
  track store ownership so sub-agent loops don't close the shared store.
- Replace SubAgentConfig.TraceDir/TraceSessionID with SessionID.
- Add SupervisedMaxRetries and SupervisedRepoPath config options.
- Bump github.com/buchenberg/shepherd-kernel-go to v0.2.0.
Introduce a blocking sub-agent tool that guarantees workspace safety:
before each attempt a git checkpoint is taken, on failure the workspace
is rolled back and the sub-agent retried with failure-derived guidance.
This addresses the prior gap where spawn_subagent changes persisted even
when a sub-agent failed, leaving the workspace in a broken state.

Changes:
- Add SupervisedTaskTool in internal/tools/supervised_task.go with
  checkpoint/rollback/retry semantics, timeout and iteration caps, and
  blocking execution that prevents concurrent filesystem writes.
- Add orchestrator guidance (internal/prompts/subagent_tools.md) that
  explains when to prefer supervised_task over spawn_subagent; injected
  into the main prompt only when tracing (and thus the tool) is enabled.
- Add supervised_task tool description doc for the model prompt.
- Restrict the sub-agent middleware pipeline to tool_concurrency and
  shepherd_trace, excluding orchestrator-only middleware (steer,
  approval, compaction, etc.).
- Expand config parity and pipeline tests; add buildpipeline and
  supervised_task tests covering success, retry, rollback, and prompt
  reuse.
- Expand ~ in SupervisedRepoPath during config load.
- Bump github.com/buchenberg/shepherd-kernel-go to v0.2.1.
… groundwork

Lay the foundation for per-turn checkpoint/restore in sub-agent loops (.agents/plans/per-turn-checkpoint-restore) and make supervised_task return a uniform JSON envelope for every outcome.

Changes: - Return a single always-JSON envelope {status, attempts, result?, error?, partial?} from supervised_task; success is now status=completed with the output in result, so callers can tell a clean run from a failed-and-rolled-back one without inspecting the worktree. Track the last non-empty partial across attempts. - Add agent.TurnCheckpointer (opaque []byte snapshots) and the ShepherdTurnCheckpointer adapter over the shared ScopeManager, with git-repo tests covering workspace revert, snapshot round-trip, and the single-use restore contract. - Plumb TurnCheckpointer/TurnCheckpointEnabled/TurnCheckpointMax through SubAgentConfig into LoopConfig; the loop integration (checkpoint before turn, restore on failure) is not wired yet. - Update the supervised_task tool description for the envelope.
Sub-agent loops can now snapshot the workspace and conversation before each model turn and rewind a failed turn instead of failing the whole attempt. Gated behind turn_checkpoint (default off) pending benchmarks.

Changes: - Loop.Run takes a git checkpoint (serialized messages as snapshot) before each model turn; on a hard tool-phase error or iteration exhaustion it restores the last checkpoint, appends supervisor guidance, and retries, bounded by MaxTurnRestores (default 3). TurnCheckpointMax caps live checkpoints; unconsumed checkpoints are pruned at run end. - Runner wires ShepherdTurnCheckpointer on the sub-agent's own scope when turn_checkpoint is enabled, keeping turn checkpoints separate from supervised_task's attempt-level scope. - jobs.TurnRestoreStats flows restore counts from the loop through the context into the supervised_task envelope (new optional restores/restored_from fields). - Config knobs: turn_checkpoint, turn_checkpoint_max, max_turn_restores. - Tests: 6 loop-level tests (fake checkpointer/provider), snapshot round-trip, jobs ctx stats tests, tool envelope test, and a full-stack integration test (supervised_task -> runner -> real loop -> real git repo) verifying a corrupting turn write is rewound while earlier progress survives. - Docs: per-turn appendix in docs/supervised-task-plan.md, updated tool description, plan status -> in_progress.
…oints)

Replace the global turn_checkpoint toggle with per-role shepherding under agents.subagent.roles.<name>, and land the phase-9 checkpoint-cost benchmarks that justify keeping per-turn checkpointing off by default.

Config model: - RoleConfig gains supervised (default false) and turn_checkpoints (default false). Routing is exclusive: supervised roles dispatch only via supervised_task (attempt checkpointing always on); plain roles only via spawn_subagent (no checkpoints). - Remove the global turn_checkpoint bool. Numeric knobs (supervised_max_retries, turn_checkpoint_max, max_turn_restores) and supervised_repo_path stay global.

Implementation: - wiring.go adds splitRolesBySupervised, filtering each tool's static role list and live RoleResolver so schemas and role validation enforce the split. - runner gates the turn checkpointer on the role's TurnCheckpoints flag and extracts RoleDescriptionsFor for both tools.

Benchmarks (Intel Ultra 7 265H, Windows, -benchtime=10x): checkpoint ~241-385ms/op, restore ~447ms-1.5s/op, dominated by spawning three git subprocesses per checkpoint. Decision: keep per-turn checkpointing off by default (per-role opt-in only).

Tests: config parsing of the new flags, routing partition (exclusive buckets), per-role gate on/off via integration tests, plus the existing full-stack integration test updated to the per-role model.
supervised_task gains review:true: run ONE work unit, return a review
envelope (session_id, bounded diff, report, allowed verdicts) instead
of auto-retrying. The supervisor tool drives the verdict cycle:

- continue: accept the unit, run the next one seeded with the prior
  conversation (jobs.SubAgentParams.SeedMessages -> LoopConfig.
  InitialMessages), guidance as the new user message
- rollback: restore the unit-start git checkpoint (files AND
  conversation), rerun with the orchestrator's more specific prompt
- fork/choose: rewind to the unit-start checkpoint, run two prompt
  variants from the same tree, apply the winner's tree + conversation
- review_diff / accept / abort round out the lifecycle

One open session at a time; cancelled units stay resumable; review mode
never auto-retries. Requires shepherd-kernel-go v0.3.1 (TreeState
capture/apply + DiffSince, non-consuming) which replaces raw git calls
in yaah.
Picks up the non-mutating checkpoint fix (unstage after stash create)
and drops the temporary local replace directive.
…ard rails

- Route supervised roles out of spawn_subagent only after shepherd infra
  initializes successfully, so a role is never unreachable when tracing
  is unset or init fails; gate the prompt guidance on the same state.
- Hold the session mutex across the sub-agent runner call so concurrent
  verdict actions serialize instead of rewinding a live workspace.
- Reject a fork variant whose tree snapshot failed to capture, instead of
  calling ApplyTree(nil).
- Seed InitialMessages on any empty history, not just nil.
- Restrict shepherd trace dir/store to the session owner (0700/0600).
- Return the os.Getwd error instead of discarding it.
- Document review_diff in the verdict lists.
@buchenberg
buchenberg merged commit c1f2595 into main Aug 20, 2026
7 of 8 checks passed
@buchenberg
buchenberg deleted the feat/shepherd-supervision branch August 20, 2026 15:11
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c287639-baa9-442a-9190-b778b81b8146

📥 Commits

Reviewing files that changed from the base of the PR and between ba18e43 and 96371ec.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (46)
  • .agents/plans/per-turn-checkpoint-restore/PLAN.md
  • AGENTS.md
  • cmd/yaah/build_loop.go
  • cmd/yaah/config_parity_test.go
  • cmd/yaah/tui2.go
  • cmd/yaah/wiring.go
  • cmd/yaah/wiring_routing_test.go
  • docs/features.md
  • docs/supervised-task-plan.md
  • go.mod
  • internal/agent/buildpipeline_test.go
  • internal/agent/initial_messages_test.go
  • internal/agent/lifecycle_init.go
  • internal/agent/loop.go
  • internal/agent/options.go
  • internal/agent/pipeline/config.go
  • internal/agent/pipeline/config_test.go
  • internal/agent/pipeline/scope_init.go
  • internal/agent/pipeline/trace.go
  • internal/agent/runner/checkpoint.go
  • internal/agent/runner/checkpoint_bench_test.go
  • internal/agent/runner/checkpoint_integration_test.go
  • internal/agent/runner/checkpoint_test.go
  • internal/agent/runner/runner.go
  • internal/agent/runner/runner_test.go
  • internal/agent/subagent_loop.go
  • internal/agent/turn_checkpoint.go
  • internal/agent/turn_checkpoint_loop.go
  • internal/agent/turn_checkpoint_test.go
  • internal/agent/types.go
  • internal/config/load.go
  • internal/config/load_test.go
  • internal/jobs/context.go
  • internal/jobs/context_test.go
  • internal/jobs/output.go
  • internal/prompts/prompts.go
  • internal/prompts/subagent_tools.md
  • internal/prompts/tools/supervised_task.md
  • internal/tools/subagent_aliases.go
  • internal/tools/subagent_trace.go
  • internal/tools/supervised_session.go
  • internal/tools/supervised_session_test.go
  • internal/tools/supervised_task.go
  • internal/tools/supervised_task_test.go
  • internal/tools/supervisor.go
  • internal/tools/supervisor_shared.go

📝 Walkthrough

Walkthrough

The PR adds supervised sub-agent execution with shared Shepherd tracing, per-role routing, Git-backed attempt and turn checkpoints, automatic restore/retry behavior, conversation capture, and interactive review sessions with rollback and fork selection.

Changes

Supervised sub-agent execution

Layer / File(s) Summary
Contracts and configuration
internal/agent/..., internal/config/..., internal/jobs/..., internal/prompts/...
Adds checkpoint, restore, role-routing, conversation-seeding, and supervised-task configuration contracts.
Shared Shepherd infrastructure and routing
cmd/yaah/..., internal/agent/pipeline/..., internal/tools/supervisor_shared.go
Initializes shared Shepherd stores and scopes, separates sub-agent and orchestrator pipelines, and routes roles by their supervision settings.
Per-turn checkpoint and restore loop
internal/agent/loop.go, internal/agent/turn_checkpoint_*.go, internal/agent/lifecycle_init.go
Snapshots conversation state before model turns and restores workspace and messages after tool failures or iteration exhaustion within configured limits.
Runner integration
internal/agent/runner/..., internal/agent/subagent_loop.go
Creates sub-agent scopes and optional Shepherd checkpointers, passes checkpoint and seed settings into loops, and captures completed conversations.
Blocking supervised task
internal/tools/supervised_task.go, internal/tools/supervised_task_test.go
Adds validation, Git checkpoints, timeout handling, rollback, retries, structured JSON outcomes, and role-aware schemas.
Interactive review sessions
internal/tools/supervised_session.go, internal/tools/supervised_session_test.go, internal/tools/supervisor.go
Adds session continuation, rollback, diff review, fork selection, acceptance, abort, cancellation, and workspace/conversation state management.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SupervisorTool
  participant SupervisedTaskTool
  participant SubAgentRunner
  participant AgentLoop
  participant Shepherd
  SupervisorTool->>SupervisedTaskTool: submit supervised task or review action
  SupervisedTaskTool->>Shepherd: create attempt checkpoint
  SupervisedTaskTool->>SubAgentRunner: execute role with prompt
  SubAgentRunner->>AgentLoop: run sub-agent loop
  AgentLoop->>Shepherd: checkpoint and restore turns when enabled
  AgentLoop-->>SubAgentRunner: conversation and restore diagnostics
  SubAgentRunner-->>SupervisedTaskTool: task result
  SupervisedTaskTool-->>SupervisorTool: structured review envelope
Loading

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/shepherd-supervision

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant