Skip to content

Harden and simplify delegation, Autopilot, and recovery - #51

Merged
elkaix merged 13 commits into
mainfrom
fix/principal-review-hardening
Sep 25, 2026
Merged

elkaix merged 13 commits into
mainfrom
fix/principal-review-hardening

Conversation

@elkaix

@elkaix elkaix commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Applies the principal review: closes trust gaps, cuts Autopilot's shipping half, and removes duplicated or dead machinery.

Breaking (protocol 2.0.0 → 3.0.0)

  • autopilotStart drops pullRequest; Autopilot spec/state v2; Final Branch Report v2 (ready-for-human-review). Older versions are refused with explicit diagnostics.
  • Run archives recorded under protocol 2.x are refused; decide and integrate pending candidates before upgrading.
  • Acceptances without an artifact hash are no longer integrable.

Changes

  • Autopilot ends at a final-reviewed local branch; promotions use the user's Git identity; one state machine owns resume and cleanup; the remote is read only at create; it refuses to run under the human decision authority.
  • Managed worktrees live under <checkout>/.worktrees/claude-architect/.
  • Opt-in Jev screen (CLAUDE_ARCHITECT_JEV=on) can only withdraw autonomous acceptance.
  • recovery-manager.ts (3,880 lines) is split into one module per concern; declarations moved verbatim.
  • Shared error, directory-flush, identity, and Git helpers replace per-file copies; the GitHub shipping adapter is removed.
  • CI pins every action to a commit SHA and the Claude Code CLI to a version.
  • Test isolation: a per-file state dir, serialized worktree cleanups, and explicit e2e budgets.

Verification

  • npx tsc --noEmit clean.
  • Full Vitest suite: 1817 passed, 0 failed.
  • validate-release.sh exit 0 on a committed copy.
  • claude plugin validate . passed.

elkaix added 13 commits August 27, 2026 21:25
The macOS Seatbelt backend decided which host directories a Producer could
write by sniffing basename(executable) and requiredEnv names — four
producer-specific functions living inside src/platform/sandbox/. An adapter
the sandbox failed to recognize silently ran with no state access, and every
new lane had to edit the sandbox.

ProducerInvocation.inheritedStateWritablePaths is now the declaration: each
adapter states its own auth/config/state paths and the sandbox grants exactly
those when no temporary home is in effect. The four OS-confined CLI probes
also collapse into probeOsConfinedCli (resolve -> --version -> optional
surface check -> confinement backend -> auth), with Pythinker's --help
inspection supplied as a hook.

Seatbelt tests now prove the seam (grants exactly the declared paths, ignores
them under a temp home, never derives paths from identity or env names); each
adapter test asserts its own declaration. The win32-separator HOME test moved
with the join into the adapters, which never run on win32.
claude-implementer runs `claude -p --output-format json` as an untrusted
Producer, so the architect can delegate implementation to Opus or Sonnet
(producerOverrides.model) with an optional --effort override, under the same
invariants as every other lane: fresh context, isolated worktree, frozen
candidate, independent verification.

Isolation is enforced by argv, each flag confirmed live against claude 2.1.250:
--strict-mcp-config (no MCP servers, so no nested delegate tool),
--tools without Agent (no nested subagents, no web), --setting-sources ""
(no user/project/local settings, hooks, or CLAUDE.md discovery — the Producer
sees only the rendered spec), --no-session-persistence, and
--disable-slash-commands. Auth needs USER plus the real HOME (a temp HOME
reports "Not logged in"), so the lane is inherited-config-only and declares
~/.claude and ~/.claude.json as its writable state. The result envelope can
report is_error with exit 0, so normalizeEvents keys on both.

darwin/arm64 only via the macos-seatbelt backend; a confined smoke run created
a worktree file and got EPERM outside it. Opt-in real-CLI smoke test behind
CLAUDE_ARCHITECT_CLAUDE_SMOKE=1.

Design: docs/superpowers/specs/2026-08-27-claude-producer-adapter-design.md
The delegate skill now states that the architect session — whatever model it
runs, Fable included — may dispatch Opus or Sonnet subagents through the host
Agent tool for non-writing roles: scout, spec drafter, candidate reviewer,
and advisor. A new read-only candidate-reviewer agent (opus; Read/Grep/Glob +
reviewCandidate) reviews one frozen candidate without Producer context and
returns two verdicts plus a recommendation; it never decides or integrates.

An Opus/Sonnet implementer is the claude-implementer lane, never a bare
subagent: the skill says so explicitly so the roster and the subagent roles
cannot be confused.
…broke

The slice lifecycle now lives in SliceRunner: plan wave, create worktree,
launch Producer, freeze, verify, review, compose, release anchor. Run-scoped
facts travel as a RunContext value rather than a shared closure, and
pipeline-runtime.ts drops from 2464 to 1545 lines.

Finishing the extraction surfaced five defects in the seams between the new
runner and the pipeline, none of which any test could reach while the tree did
not compile:

- runSliceReview was called without the run's borrowed checkout lease, so the
  review worktree blocked on the lock the same process already held. The
  parameter is now required-but-nullable, so omitting it is a type error.
- Temporary slice refs were cleaned up inside the runner, before the final
  review round that resolves them. The runner hands them back; the pipeline's
  finally block remains the single place they are deleted.
- The slice ref namespace was written as refs/claude-architect/runs/ while
  recovery swept refs/claude-architect/slices/ from its own copy of the
  literal. Orphaned refs would have accumulated with nothing failing. One
  declaration now lives in src/git/ref-namespace.ts.
- Unparseable structured output was reclassified from invalid-output to
  producer-failure, losing the distinction between a malformed report and a
  crashed process, and the reported log ref pointed at the repair attempt
  rather than the output that failed validation.
- The pipeline gate clearance was built twice with independent timestamps, so
  the archived record and the returned result disagreed on clearedAt. Neither
  reader could detect it alone.

Two implementations that could diverge are now one. withManagedWorktree lives
beside WorktreeManager and is borrowed by the pipeline, the slice runner, and
candidate verification, which also gains the creation serialization it lacked;
the queue is keyed per repository so unrelated repositories do not block each
other. The superseded runSlicePhase/SlicePhaseDeps loop is deleted, and the
suite that exercised it now drives the real runner.

Also lands RunDecision, typed gate clearance, named verification modes, the
RecoveryDependencies cleanup, and the documentation and skill work recorded
under [Unreleased].
…ound reads

runPipelineWithLease is 345 lines, down from 1048. Increments, review rounds,
candidate promotion, the halted-slice path, salvage and archive, and the final
gate are named functions over one explicit PipelineRunState value; each phase
returns continue or a terminal PipelineResult instead of writing into a shared
closure. RunContext gains a default sliceIndex so post-wave status lines no
longer need a pipeline-local emitter.

ArtifactStore is descriptor-driven: one ArtifactDescriptor per archived kind
names the file, the read validator, the write-side redaction and validation,
and the write mode. Every typed façade is one line over readArtifact and
writeArtifact, reads share readEvidence's traversal and identity guards, and
writes sit on PlatformSafety.writeAtomic. artifact-store-bytes.test.ts pins
hashes recorded from the hand-written façades, so the rewrite is proven
byte-identical.

The store is bound to its run once. Read façades take no run id; the tool,
review-snapshot, run-decision, and advisor-stage store interfaces follow, and
prune reads each candidate run through a store bound to that run rather than
through the caller's.

tests/README.md maps every test file to the interface it crosses and records a
verdict for each site that reaches past one. All fifteen call through to the
real implementation and only observe or inject a fault, so nothing moved.
Apply the principal review: close trust gaps, cut the Autopilot shipping
half, and remove duplicated or dead machinery.

- Protocol 2.0.0 -> 3.0.0: autopilotStart drops pullRequest; Autopilot
  spec/state v2 and Final Branch Report v2 (status ready-for-human-review).
  Older versions are refused with explicit diagnostics.
- Autopilot ends at a final-reviewed local branch handed to the delivery
  gate; promotions carry the user's Git identity; one state machine owns
  resume and cleanup; the remote is read only at create; it refuses to run
  under the human decision authority.
- Managed worktrees live under <checkout>/.worktrees/claude-architect/.
- Opt-in Jev screen can only withdraw autonomous acceptance.
- Integration refuses acceptances without an artifact hash.
- Split recovery-manager.ts (3,880 lines) into one module per concern;
  declarations moved verbatim.
- Shared error, directory-flush, identity, and Git helpers replace copies.
- CI pins every action to a commit and the Claude Code CLI to a version.
- Tests: per-file isolated state dir, serialized worktree cleanups, and
  explicit e2e budgets remove cross-file flakiness.
…hardening

# Conflicts:
#	README.md
#	assets/banner.svg
@coderabbitai

coderabbitai Bot commented Sep 25, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Repository: PyModel/claude-architect/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: a03f07a8-8ca5-4c92-8344-fe27cc89c25b

📥 Commits

Reviewing files that changed from the base of the PR and between e09a402 and a23a6b4.

⛔ Files ignored due to path filters (10)
  • assets/banner.svg is excluded by !**/*.svg
  • runtime/bootstrap.mjs is excluded by !runtime/**
  • runtime/schemas/autopilot-spec.v2.json is excluded by !runtime/**
  • runtime/schemas/autopilot-workflow-state.v1.json is excluded by !runtime/**
  • runtime/schemas/autopilot-workflow-state.v2.json is excluded by !runtime/**
  • runtime/schemas/delegation-spec.v1.json is excluded by !runtime/**
  • runtime/schemas/final-branch-report.v2.json is excluded by !runtime/**
  • runtime/schemas/pipeline-gate-cleared.v1.json is excluded by !runtime/**
  • runtime/server.mjs is excluded by !runtime/**
  • runtime/watchdog.mjs is excluded by !runtime/**
📒 Files selected for processing (195)
  • .claude-plugin/marketplace.json
  • .claude-plugin/plugin.json
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .nvmrc
  • AGENTS.md
  • CHANGELOG.md
  • CONTEXT.md
  • README.md
  • agents/candidate-reviewer.md
  • docs/ARCHITECTURE.md
  • docs/MARKETPLACE_REVIEW.md
  • docs/PLUGIN_COMPONENTS.md
  • docs/PRIVACY.md
  • docs/README.md
  • docs/SECURITY_MODEL.md
  • docs/THREAT_MODEL.md
  • docs/TRUST_BOUNDARIES.md
  • docs/autopilot-terminal-states.md
  • docs/decision-authority.md
  • docs/delegation-monitoring.md
  • docs/delegation-presentation.md
  • docs/operations.md
  • docs/sliced-pipeline.md
  • docs/superpowers/specs/2026-08-27-claude-producer-adapter-design.md
  • docs/verification-preflight.md
  • skills/delegate/SKILL.md
  • skills/subagent-driven-delegation/SKILL.md
  • src/autopilot/autopilot-controller.ts
  • src/autopilot/autopilot-eligibility.ts
  • src/autopilot/branch-manager.ts
  • src/autopilot/candidate-promoter.ts
  • src/autopilot/final-branch-reviewer.ts
  • src/autopilot/types.ts
  • src/autopilot/workflow-store.ts
  • src/git/candidate-tree.ts
  • src/git/checked-git.ts
  • src/git/git-exec.ts
  • src/git/ref-namespace.ts
  • src/git/repo-preconditions.ts
  • src/git/worktree-registration.ts
  • src/integrate/controlled-integrator.ts
  • src/mcp/allowlist-sufficiency.ts
  • src/mcp/decision-authority.ts
  • src/mcp/doctor.ts
  • src/mcp/jev-screen.ts
  • src/mcp/server.ts
  • src/mcp/tools.ts
  • src/pipeline/advisor-stage.ts
  • src/pipeline/candidate-provenance.ts
  • src/pipeline/candidate-verifier.ts
  • src/pipeline/gates.ts
  • src/pipeline/pipeline-roles.ts
  • src/pipeline/pipeline-runtime.ts
  • src/pipeline/role-runner.ts
  • src/pipeline/run-context.ts
  • src/pipeline/slice-runner.ts
  • src/platform/bound-directory-cleanup.ts
  • src/platform/durable-directory.ts
  • src/platform/durable-write.ts
  • src/platform/lock-owner.ts
  • src/platform/lock-ownership.ts
  • src/platform/platform-safety.ts
  • src/platform/posix-platform-services.ts
  • src/platform/sandbox/seatbelt.ts
  • src/producers/agy-adapter.ts
  • src/producers/capability-probe.ts
  • src/producers/claude-adapter.ts
  • src/producers/cli-probe.ts
  • src/producers/codex-adapter.ts
  • src/producers/host-store.ts
  • src/producers/opencode-adapter.ts
  • src/producers/pi-adapter.ts
  • src/producers/plain-text.ts
  • src/producers/producer-adapter.ts
  • src/producers/producer-registry.ts
  • src/producers/producer-runtime.ts
  • src/producers/prompt-renderer.ts
  • src/producers/pythinker-adapter.ts
  • src/protocol/autopilot-spec.ts
  • src/protocol/pipeline-gate-cleared.ts
  • src/protocol/schema-loader.ts
  • src/protocol/spec-validator.ts
  • src/protocol/versions.ts
  • src/runtime/artifact-store.ts
  • src/runtime/attempt-runtime.ts
  • src/runtime/environment-policy.ts
  • src/runtime/managed-worktree-root.ts
  • src/runtime/producer-preflight.ts
  • src/runtime/recovery-autopilot.ts
  • src/runtime/recovery-manager.ts
  • src/runtime/recovery-prune-journal.ts
  • src/runtime/recovery-quarantine.ts
  • src/runtime/recovery-runs.ts
  • src/runtime/recovery-shared.ts
  • src/runtime/recovery-worktree-removals.ts
  • src/runtime/recovery-worktree-sweep.ts
  • src/runtime/reproducibility.ts
  • src/runtime/review-snapshot.ts
  • src/runtime/run-decision.ts
  • src/runtime/run-start.ts
  • src/runtime/run-status.ts
  • src/runtime/worktree-manager.ts
  • src/runtime/worktree-mutation-gate.ts
  • src/runtime/worktree-removal-manifest.ts
  • src/ship/github-cli-adapter.ts
  • src/ship/hosting-adapter.ts
  • src/util/errors.ts
  • src/verify/acceptance-verifier.ts
  • src/verify/baseline-verifier.ts
  • src/verify/dependency-link.ts
  • src/verify/project-verifier.ts
  • src/verify/structural-verifier.ts
  • src/verify/verification-inputs.ts
  • tests/README.md
  • tests/delegate-routing.test.mjs
  • tests/helpers/platform-services-double.ts
  • tests/lane-launchers.test.sh
  • tests/runtime/acceptance-verifier.test.ts
  • tests/runtime/agy-adapter.test.ts
  • tests/runtime/artifact-store-bytes.test.ts
  • tests/runtime/artifact-store.test.ts
  • tests/runtime/attempt-runtime.test.ts
  • tests/runtime/autopilot/autopilot-adversarial.test.ts
  • tests/runtime/autopilot/autopilot-controller.test.ts
  • tests/runtime/autopilot/autopilot-doctor.test.ts
  • tests/runtime/autopilot/autopilot-e2e.test.ts
  • tests/runtime/autopilot/autopilot-mcp.test.ts
  • tests/runtime/autopilot/autopilot-recovery-cutpoints.test.ts
  • tests/runtime/autopilot/autopilot-recovery.test.ts
  • tests/runtime/autopilot/autopilot-windows.test.ts
  • tests/runtime/autopilot/branch-manager.test.ts
  • tests/runtime/autopilot/candidate-promoter.test.ts
  • tests/runtime/autopilot/final-branch-reviewer.test.ts
  • tests/runtime/autopilot/workflow-state-schema.test.ts
  • tests/runtime/autopilot/workflow-store.test.ts
  • tests/runtime/bootstrap.smoke.test.ts
  • tests/runtime/candidate-tree.test.ts
  • tests/runtime/capability-probe.test.ts
  • tests/runtime/checked-git.test.ts
  • tests/runtime/claude-adapter.test.ts
  • tests/runtime/codex-adapter.test.ts
  • tests/runtime/cross-lane-launch.test.ts
  • tests/runtime/cross-lane-probe.test.ts
  • tests/runtime/cross-lane-prompt.test.ts
  • tests/runtime/decision-authority.test.ts
  • tests/runtime/dependency-link.test.ts
  • tests/runtime/doctor.test.ts
  • tests/runtime/durable-write.test.ts
  • tests/runtime/e2e-pipeline.test.ts
  • tests/runtime/e2e-vertical-slice.test.ts
  • tests/runtime/environment-policy.test.ts
  • tests/runtime/gates.test.ts
  • tests/runtime/git-exec.test.ts
  • tests/runtime/handshake.smoke.test.ts
  • tests/runtime/jev-screen.test.ts
  • tests/runtime/legacy-decision-provenance.test.ts
  • tests/runtime/lock-contention.test.ts
  • tests/runtime/lock-ownership.test.ts
  • tests/runtime/mcp-decision-gate.test.ts
  • tests/runtime/mcp-input-schema.test.ts
  • tests/runtime/opencode-adapter.test.ts
  • tests/runtime/pi-adapter.test.ts
  • tests/runtime/pipeline-runtime.test.ts
  • tests/runtime/pipeline/advisor-stage.test.ts
  • tests/runtime/pipeline/autopilot-eligibility.test.ts
  • tests/runtime/pipeline/slice-runner.test.ts
  • tests/runtime/platform-safety.test.ts
  • tests/runtime/plugin-wiring.test.mjs
  • tests/runtime/probe-cache.test.ts
  • tests/runtime/producer-adapter.test.ts
  • tests/runtime/project-verifier.test.ts
  • tests/runtime/protocol/autopilot-schema.test.ts
  • tests/runtime/pythinker-adapter.test.ts
  • tests/runtime/recovery-manager.test.ts
  • tests/runtime/review-manifest-echo.test.ts
  • tests/runtime/review-snapshot.test.ts
  • tests/runtime/run-decision.test.ts
  • tests/runtime/run-manifest.test.ts
  • tests/runtime/run-status.test.ts
  • tests/runtime/schema-loader.test.ts
  • tests/runtime/seatbelt.test.ts
  • tests/runtime/shipping/github-cli-adapter-red-paths.test.ts
  • tests/runtime/shipping/github-cli-adapter.test.ts
  • tests/runtime/spec-validator.test.ts
  • tests/runtime/structural-verifier.test.ts
  • tests/runtime/tools.test.ts
  • tests/runtime/verification-mode.test.ts
  • tests/runtime/watchdog.test.ts
  • tests/runtime/worktree-manager.test.ts
  • tests/runtime/worktree-removal-manifest.test.ts
  • tests/runtime/worktree-sweep.test.ts
  • tests/support/isolated-state-dir.ts
  • tsconfig.json
  • vitest.config.ts
 ________________________________________________________
< PR looks good? I'll just summon three more edge cases. >
 --------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

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

@elkaix
elkaix merged commit d4e3b84 into main Sep 25, 2026
5 of 10 checks passed
@elkaix
elkaix deleted the fix/principal-review-hardening branch September 25, 2026 01:19
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