feat: governed agent orchestration (v1.1.0) - #13
Merged
Conversation
v1.0 controlled *what* may be executed and whether a result counts as
complete. It did not control the middle: an agent could implement an
underspecified requirement, silently choose between two valid
architectures, retry a deterministic failure forever, broaden scope while
debugging, or present a fresh run as a continuation.
v1.1 adds a bounded, observable, resumable control loop around that middle,
as a reusable domain package rather than logic smeared across adapters.
New package @specbridge/orchestration:
- a 12-phase fail-closed state machine plus a per-phase allowed-action
table, which is what makes "no source edits before the plan gate" a
hard-enforced rule rather than a line in a Markdown file
- intent assessment with four strictly distinct outcomes (READY,
NEEDS_CLARIFICATION, REJECTED, BLOCKED); the host proposes a structured
assessment, SpecBridge validates it against approvals, staleness, task
existence, and lock ownership, and may override it -- always towards
caution, never towards READY
- structural provenance instead of a numeric confidence score: a READY
claim resting on inferred, unknown, or conflicting facts is downgraded
automatically
- bounded clarification with durable structured decisions; an ambiguity
cannot be resolved by inference, and a decision never amends an
approved .kiro document
- execution plans bound to task fingerprint, approved stage hashes, Git
baseline, and policy fingerprint, with staleness detection and a plan
review gate (review by default)
- material-change replanning: a changed goal, subsystem, or strategy
re-opens review; a reorder or wording fix does not
- an 18-category failure taxonomy driving a deterministic retry / repair
/ replan engine -- exactly two categories are retryable, a failing
verifier enters bounded repair rather than a rerun, and cancellation is
never auto-restarted
- deterministic no-progress detection from normalized failure
fingerprints and diff fingerprints, never text similarity
- explicit budgets for iterations, repairs, replans, retries, stagnation,
clarification rounds, elapsed time, and event history
Surfaces (thin adapters, no duplicated logic):
- CLI: specbridge orchestrate status|show|explain|policy|events|phases --
read-only and deterministic; none invokes a model or advances a run
- MCP: 10 orchestration_* tools with versioned schemas, bounds, and
SBMCP021-030 mapped from the SBO### domain registry
- Plugin: /specbridge:develop added; /specbridge:implement unchanged;
/specbridge:continue is now orchestration-aware
Deliberately unchanged, and asserted by tests: .kiro stays the source of
truth, stage approval stays human-only with no agent-accessible path,
task_complete stays the sole completion authority, and no arbitrary shell,
filesystem, or Git tool exists at any version. No private chain-of-thought
is persisted -- no schema has a field for it.
Additive throughout: no persisted schema version moved, so v1.0 workspaces
load with no migration.
Two defects found and fixed rather than worked around: the orchestration
fixtures were doing a full git init per test, which pushed the suite into
vitest worker-RPC starvation (test time 1052s -> 856s after making git
opt-in); and OrchestrationError reached the CLI's fallback handler and
printed a stack trace instead of a stable SBO code with remediation.
StepRelay readiness fixture and scenarios A-L cover ambiguity, approved-spec
conflict, planned implementation, implementation defect, transient failure,
no-progress, stale plan, repository divergence, interruption, auto-approval
refusal, prompt injection, and budget exhaustion.
Tests: 1254 -> 1479 (+225).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SpecBridge v1.0 controlled what may be executed and whether a result counts as complete. It did not control the middle. An agent could implement an underspecified requirement, silently choose between two valid architectural interpretations, retry a deterministic failure indefinitely, broaden scope while debugging, or start a fresh run and present it as a continuation.
This PR adds a bounded, observable, resumable control loop around that middle, as a reusable domain package (
@specbridge/orchestration) rather than logic smeared across the CLI, MCP handlers, and skill prose. The goal is not more agent autonomy — it is more reliable, observable, bounded, and governable agent execution. SpecBridge owns state, policy, boundaries, and the completion decision; the coding agent owns interpretation and edits; Git and the trusted verifiers own evidence.Additive throughout: no persisted schema version moved, so v1.0 workspaces load with no migration.
What changed
New package
@specbridge/orchestration(~4,500 LOC)EDITis absent from the allowed set of every pre-plan phase, which is what makes "no source edits before the plan gate" a hard-enforced rule rather than a line in a Markdown file.READY/NEEDS_CLARIFICATION/REJECTED/BLOCKED). The host agent proposes a structured assessment; SpecBridge validates it against facts it checks itself — approvals, staleness, task existence, lock ownership, hard product boundaries — and may override it. Overrides only ever move towards caution.READYclaim resting oninferred,unknown, orconflictingfacts is downgraded automatically, with the offending facts listed..kirodocument — spec-changing answers route back to re-authoring and human approval.reviewby default). Reviews bind to the exact plan hash.Surfaces — thin adapters, no duplicated logic
specbridge orchestrate status | show | explain | policy show|validate | events | phases. Read-only and deterministic; a test asserts no read command advances a run.orchestration_*tools with versioned schemas, annotations, bounds, andSBMCP021–SBMCP030mapped from theSBO###domain registry in one place./specbridge:developadded./specbridge:implementis unchanged — the governed workflow is a new skill rather than a silent repurposing of an existing command./specbridge:continueis now orchestration-aware.Reviewer notes
Invariants this touches (all preserved, all asserted by tests):
.kiroremains the source of truth — no orchestration metadata in any Kiro document; byte-identical round trips still hold.*_approve,*_shell,*_exec,*_git, or*_write_file.task_completeremains the sole completion authority.orchestration_finalizerefusescompletedwithout averified/manually-acceptedstatus it actually returned (SBO022).docs/orchestration/react-tao-execution.md.Two rules are honestly documented as not hard-enforced: whether the user was genuinely asked before a plan review is recorded, and whether a clarification question is genuinely load-bearing. SpecBridge binds the review to the exact plan hash and records how it arrived, but it cannot observe the conversation. See
docs/orchestration/enforcement-boundaries.md, which classifies every rule ashard-enforced,contract-enforced, orskill-guided. No Claude Code hooks are used; the rationale is documented there too.Two defects found and fixed rather than worked around:
git initper test (7 subprocess spawns), which pushed the suite into the worker-RPC starvation this repo already documents invitest.perf.config.ts— every test passed butpnpm testexited 1. Confirmed mine by bisecting, then fixed by making git opt-in for orchestration fixtures. Test time 1052s to 856s; git-dependent tests opt back in explicitly. No test was weakened or skipped.OrchestrationErrorreached the CLI's fallback handler and printed a stack trace instead of a stableSBOcode with remediation. Caught by smoke, fixed inpackages/cli/src/cli.ts, and now asserted.StepRelay readiness: a small synthetic fixture (two specs — one deliberately ambiguous, one committed to a mechanism — plus adversarial prompt-injection content) drives scenarios A–L: ambiguity, approved-spec conflict, planned implementation, implementation defect, transient failure, no-progress, stale plan, repository divergence, interruption, auto-approval refusal, prompt injection, budget exhaustion. It is a fixture, not a second product.
Contract snapshots changed intentionally:
contracts/orchestration-contract.jsonis new;mcp-contract,plugin-skills,schema-versions, andcli-commandsare extended additively. The pinned tests were strengthened, not relaxed — they now assert the v1.0 surface survives intact alongside the additions.Not verified: live-model verification of
/specbridge:developis BLOCKED, not passed. No model server was running (nothing on 8080/8081/11434/8000, no.gguffound), and the harness fixture lives in a separate repository. The full case set (10 answered + 9 guard) and skill contract are committed underdocs/skill-verification/cases/and statically validate clean;docs/skill-verification/README.mdrecords this honestly./specbridge:continuewas materially modified and also carries no v1.1 live-model result.Validation — every command below was actually run, on Windows, at the final commit:
pnpm lintpnpm typecheckpnpm testpnpm buildpnpm check:public-contractspnpm check:mcp-docspnpm validate:pluginpnpm verify:plugin-bundlepnpm check:securitypnpm smokepnpm test:perfChecklist
pnpm lint,pnpm typecheck, andpnpm testpass locallypnpm check:public-contractspasses — stable contracts changed intentionally and additively; snapshots updated in this PRSecurity-relevant: yes. Adds T30–T32 to
docs/security/threat-model.md, a "v1.1 governed orchestration safety" section todocs/security.md, and one new explicit non-claim (orchestration governs an agent; it does not make one trustworthy). No existing mitigation was weakened; every new code path can only make execution stop sooner.