Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Unreleased

### Secondary Objective Builder — vNext.10.2 Phase 4

- Added an explicit-only, provider-neutral `SecondaryModelInference` and
`SecondaryObjectiveBuilder` path. The existing managed, loopback-only
llama.cpp/GGUF service is its first production adapter; normal Objective
BUILDER routing remains on the large agent unless a caller explicitly
selects the secondary backend.
- Added bounded approved-context/source-context packets with content hashes,
strict CREATE/REPLACE full-file proposals, shared direct-model path and
authority validation, isolated Objective worktree application, and the
existing trusted verification/candidate/evaluation/integration lifecycle.
- Added durable secondary attempt, proposal, verification, telemetry, and
candidate provenance records for honest failure diagnosis and resume.
Direct models receive no shell, git, filesystem tool, credential, approval,
contract, Mission, closure, or completion authority.

### Research-Augmented Lifecycle — vNext.10.2 Phase 3

- Integrated the governed Research Layer across repository-aware
Expand Down
24 changes: 24 additions & 0 deletions contracts/orchestration-contract.json
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@
"runtime_research_eligible",
"scheduler_mode_changed",
"scheduling_decision_created",
"secondary_builder_attempted",
"secondary_candidate_succeeded",
"self_heal_applied",
"semantic_review_completed",
"supervisor_attached",
Expand Down Expand Up @@ -1039,6 +1041,28 @@
"WEEKLY_EXHAUSTED",
"WEEKLY_QUOTA_PRESSURE"
],
"secondaryBuilderAttemptStatuses": [
"CANDIDATE_READY",
"EDITS_APPLIED",
"FAILED",
"INFERENCE_COMPLETED",
"PREPARED",
"PROPOSAL_VALIDATED",
"VERIFICATION_FAILED"
],
"secondaryBuilderFailures": [
"APPLY_FAILURE",
"CANCELLED",
"CONTEXT_TOO_LARGE",
"EMPTY_EDIT_SET",
"FORBIDDEN_EDIT",
"INFERENCE_UNAVAILABLE",
"INVALID_STRUCTURED_OUTPUT",
"STALE_APPROVED_PROJECTION",
"STALE_SOURCE_CONTEXT",
"TIMEOUT",
"VERIFICATION_FAILURE"
],
"stateInvariantIds": [
"API_BUDGET_RECONCILES",
"ATTEMPTS_REFERENCE_KNOWN_NODES",
Expand Down
5 changes: 4 additions & 1 deletion contracts/schema-versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"attemptRecord": "1.0.0",
"autonomyTelemetry": "1.0.0",
"browserScenario": "1.0.0",
"candidateArtifact": "1.0.0",
"candidateArtifact": "1.1.0",
"closureLedger": "1.0.0",
"contextMetrics": "1.0.0",
"contextPackage": "1.0.0",
Expand Down Expand Up @@ -60,6 +60,9 @@
"runnerContextCapabilities": "1.0.0",
"runnerOutput": "1.0.0",
"schedulingDecision": "1.0.0",
"secondaryBuilderAttempt": "1.0.0",
"secondaryBuilderPacket": "1.0.0",
"secondaryBuilderResult": "1.0.0",
"specIntakeApproval": "1.0.0",
"specIntakeDelta": "1.0.0",
"specIntakeGrounding": "1.0.0",
Expand Down
3 changes: 3 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ the intent in the evening, run one command, read the report in the morning.
compiler that turns contracts into a Kiro spec of Objectives.
- [Objective decomposition](orchestration/objective-decomposition.md) — the
dynamic work graph between an approved objective and worker dispatches.
- [Secondary Objective Builder](orchestration/secondary-objective-builder.md)
— explicit direct-model edits inside the existing governed worktree and
candidate lifecycle; capability without automatic routing.
- [Context projection](orchestration/context-projection.md) — share truth,
not context: what each isolated worker sees, hashed and staleness-checked.
- [Sub-agent isolation](orchestration/subagent-isolation.md) — worker
Expand Down
6 changes: 4 additions & 2 deletions docs/local-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

SpecBridge can manage a local llama.cpp server as the inexpensive reasoning
tier for long-running jobs: classification, planning, critique, diagnosis,
and replanning run against a model on your machine, and only complex work
and actual implementation reach Claude Code. One managed server serves
and replanning run against a model on your machine. Normal Objective
implementation still reaches the configured large agent; the explicit-only
[Secondary Objective Builder](orchestration/secondary-objective-builder.md)
can also use this endpoint for bounded worktree edits. One managed server serves
every logical role — roles are prompts, not processes.

The local model is a **worker**, never an authority: its answers are
Expand Down
6 changes: 6 additions & 0 deletions docs/orchestration/objective-decomposition.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ and fail-closed; two edges carry the architecture:
- `VERIFIED_CANDIDATE` is reachable only from evaluation statuses — a unit
can never be born verified.

Build units normally use the large-agent builder. Phase 4 also provides an
explicit-only [Secondary Objective Builder](secondary-objective-builder.md):
a direct model returns bounded structured edits which SpecBridge applies in
the same isolated worktree and feeds into this exact lifecycle. Merely enabling
local inference does not select that backend.

## Runtime replanning within the objective

Within one approved objective the runtime may split, merge, supersede, or
Expand Down
129 changes: 129 additions & 0 deletions docs/orchestration/secondary-objective-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Secondary Objective Builder

Phase 4 of vNext.10.2 adds a second implementation backend to the governed
Objective runtime. A bounded direct model can propose concrete file edits for
one build WorkUnit, while SpecBridge retains every authority-bearing action:

```text
ContextProjection (approved truth) + explicit bounded source context
↓ one SecondaryModelInference request
strict CREATE/REPLACE proposal
↓ SpecBridge validates and writes
isolated Objective worktree
↓ trusted configured verification
normal candidate → evaluation → aggregation → single-writer integration
```

Phase 4 creates capability. It does **not** automatically route Objective work
to the secondary backend. With no explicit `secondaryObjectiveBuilder`
selection, BUILDER behavior remains the existing large-agent path. Automatic
packet compilation, eligibility, routing, repair, and fallback belong to later
phases.

## Not an Agent Harness

`SecondaryModelInference` is a provider-neutral, one-request inference
boundary. The first production adapter reuses the configured managed
llama.cpp service and therefore preserves its existing meaning: disabled by
default, same-host, loopback-only, a local GGUF model, and no credentials.
The Objective runtime does not know whether that local model is Qwen, and a
future provider can implement the same boundary without changing candidate
execution.

The model receives no shell, git, filesystem tools, MCP tools, arbitrary
repository reads or writes, package-manager/test authority, or credentials.
Its complete output must be one schema-valid JSON document. Markdown fences,
prose, multiple JSON documents, unknown fields, delete/rename/chmod/symlink
operations, and command/tool fields are refused rather than recovered
heuristically.

## Input and source freshness

`SecondaryBuilderPacket` is versioned, bounded, schema-validated, and hashed.
It carries WorkUnit and Objective identity, goal, expected artifacts/areas,
acceptance criteria, projected contracts, ADRs and approved decisions,
constitution constraints, verified dependency evidence, fixed forbidden
changes, verification names, and explicitly prepared source files.

`ContextProjection` remains approved durable truth. Source is deliberately a
separate `sourceContext` list of worktree-relative path, SHA-256 content hash,
and bounded current UTF-8 content. Phase 4 callers choose those files
explicitly; there is no automatic repository retrieval or target inference.
Immediately before inference, SpecBridge reloads approved Mission truth and
checks projection freshness, then re-reads every source file and checks its
hash and bytes. Stale approved truth or source fails the attempt before the
model runs.

## Edit and authority firewall

`SecondaryBuilderResult` permits only a summary, optional bounded notes, and
bounded full-file `CREATE` or `REPLACE` edits. The shared direct-model
validator rejects:

- absolute, empty, duplicate, traversal, and workspace-escaping paths;
- `.git`, `.kiro`, `.specbridge`, `.codex`, and `.claude` control-plane paths;
- configured protected paths and credential-shaped paths;
- symlink targets or existing symlink ancestors;
- missing `REPLACE` targets, existing `CREATE` targets, non-regular files,
NUL/binary content, and per-file/total/output size excesses.

This blocks generic direct-model mutation of Mission state, Product Contracts,
approved decisions, approvals, Mission Seals, closure/autonomy records, and
SpecBridge/Claude/Codex configuration. Those domains retain their dedicated
governed mechanisms.

## Worktree, verification, and candidate compatibility

The driver creates the same detached Objective worktree used by the large
builder and applies already-verified dependency patches through the existing
path. SpecBridge applies accepted edits only there. It observes the actual Git
diff against the recorded baseline and runs the existing configured trusted
verification commands; provider notes and completion claims are never
evidence. The canonical checkout changes only later through the existing
single-writer integrator.

A successful result becomes the ordinary `CandidateArtifact`. Evaluation,
aggregation, integration, evidence, and closure contain no secondary-specific
branch. Optional `builderProvenance` identifies the backend, provider/profile,
model label, packet/source hashes, duration, sizes, and token usage without
changing candidate meaning.

## Durable attempts and failures

Each explicitly selected attempt is updated atomically under:

```text
.specbridge/jobs/<jobId>/objectives/<nodeId>/secondary-attempts/
```

The record retains the packet, bounded raw response, validated proposal,
actually applied files, trusted verification tails, telemetry, and a structured
failure. This remains after disposable worktree cleanup and lets normal resume
reconcile an interrupted `BUILDING` unit without claiming completion. A
persisted candidate resumes through the existing candidate evaluation path;
it is not rebuilt merely because the process restarted.

Failure kinds distinguish inference unavailability, timeout, cancellation,
invalid structured output, empty edits, forbidden edits, stale approved/source
context, application failure, verification failure, and an oversized context.
Phase 4 performs no secondary repair retry and no automatic large-model
fallback.

## Qualification

Deterministic tests cover strict parsing, bounds, authority and traversal
refusal, symlink escape, source freshness, managed-local unavailability,
worktree isolation, failure preservation, ordinary candidate evaluation, and
full evaluator/aggregator/integrator compatibility. The real managed-local
coding qualification is opt-in:

```powershell
$env:SPECBRIDGE_TEST_LOCAL_BUILDER = '1'
$env:SPECBRIDGE_TEST_LLAMA_SERVER = 'C:\tools\llama.cpp\llama-server.exe'
$env:SPECBRIDGE_TEST_QWEN_GGUF = 'D:\models\qwen.gguf'
pnpm vitest run tests/orchestration/secondary-objective-builder.test.ts
```

The qualification uses the same managed loopback adapter and asks the model
to update a small DTO/mapper. It is gated because CI does not carry a local
GGUF model.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
"bytes": 155994
},
"cli.cjs": {
"sha256": "fab1e074ffae87dc195bf01a911fe8a0ddb22f81d8ad667b03375b23e2ac9b33",
"bytes": 5545968
"sha256": "6379044267e76482b59da2c3b57ce97fe5f758815d10a9fefa0c8267bb53e9a9",
"bytes": 5588127
},
"mcp-server.cjs": {
"sha256": "01f873f0c9a07fc176cd34a6bf9edb43edf8ac84505a4b1819b4e8ba8c80fa16",
"bytes": 3636098
"sha256": "6b8a8ce0992a5cefa9e15aadbe2e0aa22a97bf341c0db8c8a599a5ba9a8024d5",
"bytes": 3644860
}
}
}
Loading
Loading