brainclaw 1.26.2 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli/register-coordination.js +65 -1
- package/dist/commands/attempt-authority.js +80 -0
- package/dist/commands/harvest.js +140 -61
- package/dist/commands/loop.js +34 -0
- package/dist/commands/loops-handlers.js +143 -15
- package/dist/commands/mcp-catalog.js +52 -18
- package/dist/commands/mcp-schemas.generated.js +64 -0
- package/dist/commands/mcp-write-claims.js +128 -1
- package/dist/commands/mcp-write-coordination.js +149 -76
- package/dist/core/agent-capability.js +1 -1
- package/dist/core/agentrun-reconciler.js +148 -22
- package/dist/core/agentruns.js +254 -29
- package/dist/core/assignment-request-schema.js +7 -0
- package/dist/core/assignment-sweeper.js +5 -3
- package/dist/core/assignments.js +131 -33
- package/dist/core/claim-request-schema.js +7 -0
- package/dist/core/claims.js +53 -2
- package/dist/core/dispatch-status.js +16 -6
- package/dist/core/dispatcher.js +51 -51
- package/dist/core/entity-operations.js +20 -0
- package/dist/core/events.js +4 -0
- package/dist/core/execution-adapters.js +189 -14
- package/dist/core/execution-contract.js +345 -0
- package/dist/core/execution.js +130 -16
- package/dist/core/facade-schema.js +3 -0
- package/dist/core/harness-adapters/base.js +150 -0
- package/dist/core/harness-adapters/claude.js +39 -0
- package/dist/core/harness-adapters/codex.js +57 -0
- package/dist/core/harness-adapters/harvest.js +109 -0
- package/dist/core/harness-adapters/index.js +8 -0
- package/dist/core/harness-adapters/prompt-only.js +13 -0
- package/dist/core/harness-adapters/registry.js +48 -0
- package/dist/core/harness-adapters/result.js +33 -0
- package/dist/core/harness-adapters/types.js +2 -0
- package/dist/core/ideation-loop-close.js +25 -2
- package/dist/core/instruction-templates.js +3 -2
- package/dist/core/loop-turn-dispatch.js +235 -0
- package/dist/core/loops/artifact-contract.js +11 -0
- package/dist/core/loops/attempt-authority.js +496 -0
- package/dist/core/loops/attempt-generations.js +509 -0
- package/dist/core/loops/attempt-reservation.js +197 -35
- package/dist/core/loops/attempt-rollout.js +404 -0
- package/dist/core/loops/attempt-takeover.js +155 -0
- package/dist/core/loops/bootstrap-acquire.js +7 -3
- package/dist/core/loops/brief-assembly.js +21 -4
- package/dist/core/loops/evidence.js +188 -0
- package/dist/core/loops/facade-schema.js +75 -11
- package/dist/core/loops/gate-policy.js +533 -0
- package/dist/core/loops/impl-bind.js +91 -81
- package/dist/core/loops/index.js +9 -0
- package/dist/core/loops/iteration-engine.js +31 -19
- package/dist/core/loops/kind-policies.js +90 -0
- package/dist/core/loops/lock.js +71 -13
- package/dist/core/loops/reconcile-turn.js +237 -18
- package/dist/core/loops/result-reducers.js +113 -10
- package/dist/core/loops/store.js +34 -3
- package/dist/core/loops/turn-execution.js +480 -0
- package/dist/core/loops/types.js +127 -3
- package/dist/core/loops/verbs.js +335 -99
- package/dist/core/loops/verify-command.js +105 -20
- package/dist/core/loops/workspace-digest.js +54 -0
- package/dist/core/review-loop-close.js +25 -3
- package/dist/core/review-loop-turn-dispatch.js +210 -161
- package/dist/core/runtime-signals.js +62 -25
- package/dist/core/schema.js +40 -0
- package/dist/core/spawn-check.js +3 -2
- package/dist/core/upgrades/backup.js +27 -4
- package/dist/facts.js +9 -8
- package/dist/facts.json +8 -7
- package/docs/cli.md +49 -1
- package/docs/concepts/attempt-authority.md +407 -0
- package/docs/concepts/evidence-attestations.md +135 -0
- package/docs/concepts/execution-contract.md +166 -0
- package/docs/concepts/harness-adapters.md +166 -0
- package/docs/concepts/ideation-loop.md +5 -4
- package/docs/concepts/loop-engine.md +302 -113
- package/docs/index.md +4 -1
- package/docs/integrations/codex.md +3 -3
- package/docs/integrations/mcp.md +59 -5
- package/docs/loops/debug.md +144 -0
- package/docs/loops/ideation.md +158 -0
- package/docs/loops/implementation.md +174 -0
- package/docs/loops/research.md +136 -0
- package/docs/loops/review.md +200 -0
- package/docs/mcp-schema-changelog.md +18 -5
- package/package.json +1 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Research loop
|
|
2
|
+
|
|
3
|
+
> Loop kind: `research`. One of five equal protocols driven by the shared
|
|
4
|
+
> [Loop Engine](../concepts/loop-engine.md). Identity, dispatch decisions and
|
|
5
|
+
> spawn authority belong to [`AttemptAuthority`](../concepts/attempt-authority.md);
|
|
6
|
+
> nothing on this page overrides them.
|
|
7
|
+
|
|
8
|
+
Worker results are explicit: `finding` for `investigate` and `synthesis` for
|
|
9
|
+
`synthesize`. Both are read-only results and may converge during report harvest.
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
A `research` loop converges an open-ended question into a synthesised
|
|
14
|
+
answer. It runs findings-then-synthesis rounds until the synthesiser
|
|
15
|
+
declares the question sufficiently answered. Unlike
|
|
16
|
+
[`implementation`](./implementation.md) or [`debug`](./debug.md), `research`
|
|
17
|
+
has no "green command" — the exit is an explicit sufficiency signal from
|
|
18
|
+
the synthesiser, and there is no `blocked` outcome: every research loop
|
|
19
|
+
lands in `conclude`.
|
|
20
|
+
|
|
21
|
+
## Default protocol
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
investigate ↔ synthesize → conclude
|
|
25
|
+
└── iterate (≤3) ──┘
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Phase | Purpose | Artifact | Context filter |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `investigate` | Gather findings against the question | `finding` (repeatable) | `plans`, `decisions`, `constraints`, `project_vision`, `candidates`, `runtime_notes`, `traps` |
|
|
31
|
+
| `synthesize` | Fold findings; assess sufficiency | `synthesis`, optional `critic_signal` | `*` |
|
|
32
|
+
| `conclude` | Publish the final synthesis | `synthesis` | `*` |
|
|
33
|
+
|
|
34
|
+
**Iteration.** `investigate ↔ synthesize` cycles up to
|
|
35
|
+
`max_iterations: 3`. `exit_when: 'critic_signal'` — the synthesiser opts an
|
|
36
|
+
explicit early exit by emitting a `critic_signal` artifact when it judges
|
|
37
|
+
the question answered. Explicit sufficiency beats saturation-by-absence for
|
|
38
|
+
open-ended research.
|
|
39
|
+
|
|
40
|
+
## Entry points
|
|
41
|
+
|
|
42
|
+
- **Direct open.**
|
|
43
|
+
`bclaw_loop(intent='open', kind='research', title=…, goal=…, allow_orphan=true)`
|
|
44
|
+
followed by `turn`/`advance`. There is no coordinator shortcut for
|
|
45
|
+
`research` today; the caller drives each round. Plain `turn` is state-only;
|
|
46
|
+
trusted `turn(dispatch=true)` launches an investigator or synthesiser
|
|
47
|
+
through the common AttemptAuthority path.
|
|
48
|
+
- **Custom stop_condition** — override the default artifact-produced stop
|
|
49
|
+
with any [`StopCondition`](../../src/core/loops/types.ts) — e.g.
|
|
50
|
+
`min_artifacts_by_type { type: 'finding', n: 5, scope: 'loop' }` for a
|
|
51
|
+
"harvest at least five findings" pattern.
|
|
52
|
+
|
|
53
|
+
## Advance gates
|
|
54
|
+
|
|
55
|
+
`investigate` carries an `advance_gate`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
{ kind: 'min_artifacts_by_type', type: 'finding', n: 1, scope: 'phase' }
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Advance cannot leave `investigate` without at least one `finding` produced
|
|
62
|
+
in the current iteration window. This prevents synthesising an empty round.
|
|
63
|
+
|
|
64
|
+
## Stop condition
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
{ kind: 'artifact_produced', phase: 'conclude', type: 'synthesis' }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The loop closes `completed` on the first `synthesis` artifact in `conclude`.
|
|
71
|
+
There is **no `max_iterations` in the stop condition** — research always
|
|
72
|
+
lands in `conclude` and produces a synthesis, even if the cycle cap was
|
|
73
|
+
reached earlier (the driver advances anyway).
|
|
74
|
+
|
|
75
|
+
## Artifacts
|
|
76
|
+
|
|
77
|
+
| Type | Phase | Body |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `finding` | `investigate` | inline ≤ 4 KB; cites the source memory / files used |
|
|
80
|
+
| `synthesis` | `synthesize` / `conclude` | inline ≤ 4 KB, or ref-based when large |
|
|
81
|
+
| `critic_signal` | `synthesize` | inline signal that the question is answered |
|
|
82
|
+
|
|
83
|
+
Findings should cite the memory ids or file paths they draw from so the
|
|
84
|
+
final synthesis is auditable.
|
|
85
|
+
|
|
86
|
+
## Routing
|
|
87
|
+
|
|
88
|
+
`research` routes turns by `slot_id`; the caller assigns investigator and
|
|
89
|
+
synthesiser slots when opening the loop. Multiple investigator slots may
|
|
90
|
+
run in parallel per iteration when `advance_when: 'any'` is set on the
|
|
91
|
+
phase — otherwise the default `all` requires every investigator to turn
|
|
92
|
+
in before synthesise fires.
|
|
93
|
+
|
|
94
|
+
## Recovery
|
|
95
|
+
|
|
96
|
+
- **Investigator worker crashed mid-turn.** Launch grant lease expires;
|
|
97
|
+
`sweepExpiredLaunchGrants` revokes it; a re-dispatch arms a new
|
|
98
|
+
generation. Prior-iteration findings never satisfy the current
|
|
99
|
+
iteration's gate.
|
|
100
|
+
- **Synthesiser did not emit `critic_signal` by cap.** The cycle exits on
|
|
101
|
+
`max_iterations_reached` (system event) and the driver advances to
|
|
102
|
+
`conclude`; the last `synthesis` becomes the concluding artifact.
|
|
103
|
+
- **`finding` gate blocked with zero findings.** The
|
|
104
|
+
`phase_advance_blocked` system event records the structured reason.
|
|
105
|
+
Add a finding, or open a new loop with the gate overridden.
|
|
106
|
+
- **Stale prior-generation LANE-RESULT.** Rejected by
|
|
107
|
+
[`evidenceMatchesAttempt`](../concepts/attempt-authority.md#functional-api).
|
|
108
|
+
|
|
109
|
+
## When NOT to use
|
|
110
|
+
|
|
111
|
+
- **The question already has a candidate answer to validate.** Use
|
|
112
|
+
[`review`](./review.md).
|
|
113
|
+
- **The question is "how do we build X?" with an architectural choice
|
|
114
|
+
hidden inside.** Use [`ideation`](./ideation.md) — memory-driven
|
|
115
|
+
critique surfaces conflicts that generic research does not.
|
|
116
|
+
- **The question is "why is the build broken?"** Use
|
|
117
|
+
[`debug`](./debug.md) — its `reproduce` phase is exactly the
|
|
118
|
+
find-the-cause pattern.
|
|
119
|
+
- **Executing an already-planned change.** Use
|
|
120
|
+
[`implementation`](./implementation.md).
|
|
121
|
+
|
|
122
|
+
## Reference implementation
|
|
123
|
+
|
|
124
|
+
| Component | File |
|
|
125
|
+
|---|---|
|
|
126
|
+
| Default protocol | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) (`DEFAULT_PROTOCOLS.research`) |
|
|
127
|
+
| Iteration FSM (`critic_signal`) | [`src/core/loops/iteration-engine.ts`](../../src/core/loops/iteration-engine.ts) |
|
|
128
|
+
| Gate evaluator | [`src/core/loops/verbs.ts`](../../src/core/loops/verbs.ts) (`evaluatePhaseAdvanceGate`) |
|
|
129
|
+
| Attempt + execution policy | [`src/core/loops/attempt-authority.ts`](../../src/core/loops/attempt-authority.ts), [`src/core/loops/kind-policies.ts`](../../src/core/loops/kind-policies.ts) |
|
|
130
|
+
| Result reducer | [`src/core/loops/result-reducers.ts`](../../src/core/loops/result-reducers.ts) |
|
|
131
|
+
| Tests | [`tests/unit/loops-iteration-engine.test.ts`](../../tests/unit/loops-iteration-engine.test.ts), [`tests/unit/loops-phase-advance-gate.test.ts`](../../tests/unit/loops-phase-advance-gate.test.ts) |
|
|
132
|
+
|
|
133
|
+
## Related
|
|
134
|
+
|
|
135
|
+
- [Loop Engine](../concepts/loop-engine.md)
|
|
136
|
+
- [Attempt authority](../concepts/attempt-authority.md)
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Review loop
|
|
2
|
+
|
|
3
|
+
> Loop kind: `review`. One of five equal protocols driven by the shared
|
|
4
|
+
> [Loop Engine](../concepts/loop-engine.md). Identity, dispatch decisions and
|
|
5
|
+
> spawn authority belong to [`AttemptAuthority`](../concepts/attempt-authority.md);
|
|
6
|
+
> nothing on this page overrides them.
|
|
7
|
+
|
|
8
|
+
Reviewer phases return the structured verdict fields; `author_response`
|
|
9
|
+
returns `artifact_type: "author_response"` with its evidence in `body`. Since
|
|
10
|
+
that phase changes the worktree, it converges only after `harvest --integrate`.
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
|
|
14
|
+
A `review` loop validates a change that already happened. The change lives on
|
|
15
|
+
a candidate, a handoff, a diff, or another primitive the caller passes in; the
|
|
16
|
+
loop drives a reviewer through evidence, findings, an author response, and a
|
|
17
|
+
verdict, until either the reviewer greenlights or an iteration cap forces the
|
|
18
|
+
loop to stop.
|
|
19
|
+
|
|
20
|
+
`review` is the workflow with the most automated coordinator shortcut, but it
|
|
21
|
+
runs on the same engine as `ideation`, `implementation`, `research`, and
|
|
22
|
+
`debug`: same phases model, same artifacts, same lifecycle verbs, same
|
|
23
|
+
authority record for each dispatched turn.
|
|
24
|
+
|
|
25
|
+
## Default protocol
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
change_summary → findings → author_response → followup_review → verdict
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Phase | Purpose | Typical artifact |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `change_summary` | Recap the change under review; anchor the reviewer | inline `change_summary` |
|
|
34
|
+
| `findings` | Reviewer records issues against the change | `finding` (repeatable) |
|
|
35
|
+
| `author_response` | Author responds to each finding | `author_response` |
|
|
36
|
+
| `followup_review` | Reviewer re-inspects after fixes | `finding` or `verdict` |
|
|
37
|
+
| `verdict` | Convergence phase: `approve` or `request_changes` | `verdict` |
|
|
38
|
+
|
|
39
|
+
**Iteration.** `review` uses `max_iterations: 3` at the loop level rather than
|
|
40
|
+
a phase-local iteration block. The default `stop_condition` is
|
|
41
|
+
`any([reviewer_green, max_iterations n=3])`: an accepted verdict closes with
|
|
42
|
+
`completed`; three rounds without acceptance close with `blocked`.
|
|
43
|
+
|
|
44
|
+
## Entry points
|
|
45
|
+
|
|
46
|
+
- **Coordinator shortcut (recommended).**
|
|
47
|
+
`bclaw_coordinate(intent='review', open_loop=true, mode?='symmetric' | 'asymmetric')`
|
|
48
|
+
creates the candidate, opens a review loop with an `author` slot and a
|
|
49
|
+
`reviewer` slot, links the candidate as the `change_summary` artifact,
|
|
50
|
+
advances to `findings`, and dispatches the reviewer.
|
|
51
|
+
- **Dispatch shortcut.** `bclaw_dispatch(intent='review', openLoop=true, …)`
|
|
52
|
+
produces the same result on the dispatch code path.
|
|
53
|
+
- **Direct open.** `bclaw_loop(intent='open', kind='review', allow_orphan=true)`
|
|
54
|
+
followed by manual `turn`/`complete_turn`. Use only when neither shortcut
|
|
55
|
+
fits — `allow_orphan=true` is the explicit acknowledgement that you will
|
|
56
|
+
drive the loop yourself.
|
|
57
|
+
|
|
58
|
+
The default review mode is `asymmetric` (reviewer finds, author fixes).
|
|
59
|
+
`symmetric` mode collapses find + fix into one turn per side — see
|
|
60
|
+
[Symmetric review-and-fix](#symmetric-review-and-fix) below.
|
|
61
|
+
|
|
62
|
+
## Advance gates
|
|
63
|
+
|
|
64
|
+
`review` ships no `advance_gate` on any phase — advance is driven by the
|
|
65
|
+
`change_summary`, `finding`, `author_response`, and `verdict` artifacts and by
|
|
66
|
+
the shared `advance_when: 'all'` slot policy. The gate that matters lives on
|
|
67
|
+
the reducer: a `verdict` artifact converts to an `accepted…` body only when
|
|
68
|
+
the reviewer wrote `review_verdict: 'approve'`. `reviewer_green` in the stop
|
|
69
|
+
condition tests exactly that.
|
|
70
|
+
|
|
71
|
+
## Stop condition
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
{ kind: 'any', conditions: [{ kind: 'reviewer_green' }, { kind: 'max_iterations', n: 3 }] }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- **`reviewer_green`** — closes the loop `completed` on the first `verdict`
|
|
78
|
+
artifact with an `accepted…` body.
|
|
79
|
+
- **`max_iterations n=3`** — closes the loop `blocked` after three rounds
|
|
80
|
+
without acceptance; a human takes over.
|
|
81
|
+
|
|
82
|
+
## Artifacts
|
|
83
|
+
|
|
84
|
+
| Type | Phase | Body |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `change_summary` | `change_summary` | inline text ≤ 4 KB |
|
|
87
|
+
| `finding` | `findings` / `followup_review` | inline text ≤ 4 KB |
|
|
88
|
+
| `author_response` | `author_response` | inline text ≤ 4 KB |
|
|
89
|
+
| `verdict` | `verdict` | inline; `accepted…` for approve, otherwise `request_changes` |
|
|
90
|
+
| `changes_applied` | any phase (symmetric only) | inline turn summary; at most one per turn |
|
|
91
|
+
| `file_diff` | any phase | ref-based body (`{ref, byte_count, sha256}`) |
|
|
92
|
+
|
|
93
|
+
Artifacts either link a primitive (`ref`) or carry an inline `body` ≤ 4 KB;
|
|
94
|
+
larger content must move behind a `ref` — see the ref-based body shape in
|
|
95
|
+
[loop-engine.md](../concepts/loop-engine.md#artifact-body-shapes).
|
|
96
|
+
|
|
97
|
+
## How verdicts reach the loop
|
|
98
|
+
|
|
99
|
+
A turn-owned dispatched reviewer worker does **not** call `bclaw_loop`
|
|
100
|
+
directly. It writes its outcome to `LANE-RESULT.json` at the worktree root,
|
|
101
|
+
including `review_verdict: 'approve' | 'request_changes'` and
|
|
102
|
+
`review_summary`. `brainclaw harvest <assignment_id>` — both the report-only
|
|
103
|
+
path and `--integrate` — maps that lane onto its loop and calls
|
|
104
|
+
`reconcileTurn`, which:
|
|
105
|
+
|
|
106
|
+
1. Validates the LANE evidence against
|
|
107
|
+
[`evidenceMatchesAttempt`](../concepts/attempt-authority.md#functional-api)
|
|
108
|
+
(`turn_id`, `run_id`, current-generation nonce all match).
|
|
109
|
+
2. Runs the review reducer to record a `verdict` artifact on the reviewer
|
|
110
|
+
slot.
|
|
111
|
+
3. Calls `advance`, which auto-closes on `reviewer_green` when the verdict is
|
|
112
|
+
`approve`.
|
|
113
|
+
|
|
114
|
+
## Autonomous fix cycle
|
|
115
|
+
|
|
116
|
+
On a `request_changes` verdict, `harvest --integrate` may re-dispatch the
|
|
117
|
+
reviewer slot into the **same worktree** (symmetric mode) or the author slot
|
|
118
|
+
(asymmetric). The claim and the worktree stay alive, the round counter bumps,
|
|
119
|
+
and a fresh turn is prepared through the full
|
|
120
|
+
`reserve → commit → arm → consume` sequence — a new generation, so a stale
|
|
121
|
+
prior-generation LANE-RESULT can never terminate the new round. The cycle
|
|
122
|
+
repeats until `approve` (→ `reviewer_green` close) or the `max_iterations`
|
|
123
|
+
cap (→ `blocked`, handed to a human). The report-only harvest path never
|
|
124
|
+
cycles: it can neither re-dispatch nor retain the claim, so it defers
|
|
125
|
+
`request_changes` to `--integrate` and still closes on `approve`.
|
|
126
|
+
|
|
127
|
+
Set `BRAINCLAW_TURN_OWNED_LOOPS=off` to disable the common path, or `review`
|
|
128
|
+
to limit it to review. `BRAINCLAW_TURN_OWNED_REVIEW=0` (also
|
|
129
|
+
`false`/`off`/`no`) remains the backward-compatible kill switch.
|
|
130
|
+
|
|
131
|
+
## Symmetric review-and-fix
|
|
132
|
+
|
|
133
|
+
When both slots are coding agents with write access to the reviewed artifact
|
|
134
|
+
(the common case for spec, doc, and small refactor reviews),
|
|
135
|
+
`mode: 'symmetric'` collapses the two phases `findings` and `author_response`
|
|
136
|
+
into one behavior per turn: the reviewer reviews **and** applies whatever
|
|
137
|
+
fixes it can make directly, then hands back a `changes_applied` summary
|
|
138
|
+
alongside its remaining `finding` artifacts. The next slot picks up from that
|
|
139
|
+
committed state and does the same. Exit: a reviewer turn produces an
|
|
140
|
+
accepted `verdict` with no unapplied findings and no `changes_applied` in the
|
|
141
|
+
turn, or `max_iterations` fires.
|
|
142
|
+
|
|
143
|
+
The phase sequence is unchanged; `mode` is persisted on
|
|
144
|
+
`loop.protocol.review_mode` at `open` time so resume and turn handlers do not
|
|
145
|
+
depend on the original request envelope. A slot that lacks write authority
|
|
146
|
+
degrades gracefully to asymmetric behavior for that turn: findings/verdicts
|
|
147
|
+
are still allowed, `changes_applied` is omitted, and the loop continues.
|
|
148
|
+
|
|
149
|
+
## Routing and project resolution
|
|
150
|
+
|
|
151
|
+
`review` routes turns by `slot_id`, using the reviewer/author slot pointer;
|
|
152
|
+
`session_id` is observability-only. The shortcut path applies the
|
|
153
|
+
[project resolution gate](../concepts/loop-engine.md#project-resolution-gate)
|
|
154
|
+
before writing anything — a review loop cannot land in the wrong store.
|
|
155
|
+
|
|
156
|
+
## Recovery
|
|
157
|
+
|
|
158
|
+
- **Reviewer worker crashed before writing LANE-RESULT.** The launch grant
|
|
159
|
+
lease expires; `sweepExpiredLaunchGrants` revokes the grant
|
|
160
|
+
(`reserved_never_launched`). A subsequent dispatch arms a new generation
|
|
161
|
+
at a strictly greater epoch.
|
|
162
|
+
- **LANE-RESULT written, harvest not yet run.** Idempotent: any harvest
|
|
163
|
+
trigger — the wrapper completion signal, `brainclaw harvest`, session-end
|
|
164
|
+
— calls `reconcileTurn`, and its convergence body is idempotent under the
|
|
165
|
+
loop lock (a superseded turn no-ops; a terminal loop no-ops).
|
|
166
|
+
- **Completed lane + failed sentinel present.** `reconcileTurn` withholds
|
|
167
|
+
convergence (§13 R4), journals a `run_blocked` runtime event with
|
|
168
|
+
`status_reason: turn_evidence_contradiction`, and escalates to a human.
|
|
169
|
+
- **Iteration cap hit.** Loop closes to `blocked`; the coordinator claim
|
|
170
|
+
is released; the worktree becomes ordinary once the harvest pass runs.
|
|
171
|
+
|
|
172
|
+
Every one of these outcomes is a total function of the reservation record
|
|
173
|
+
plus the run status — never a decision on marker-file presence.
|
|
174
|
+
|
|
175
|
+
## When NOT to use
|
|
176
|
+
|
|
177
|
+
- **Ideation before a decision is made** — use [`ideation`](./ideation.md).
|
|
178
|
+
- **Adversarial pressure on a proposal that has no candidate yet** — use
|
|
179
|
+
[`ideation`](./ideation.md); a review loop with no `change_summary`
|
|
180
|
+
artifact is empty.
|
|
181
|
+
- **Running the failing repro of a bug** — use [`debug`](./debug.md).
|
|
182
|
+
- **Executing a bound plan** — use [`implementation`](./implementation.md).
|
|
183
|
+
- **Open-ended discovery** — use [`research`](./research.md).
|
|
184
|
+
|
|
185
|
+
## Reference implementation
|
|
186
|
+
|
|
187
|
+
| Component | File |
|
|
188
|
+
|---|---|
|
|
189
|
+
| Default protocol | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) (`DEFAULT_PROTOCOLS.review`) |
|
|
190
|
+
| Coordinator dispatch | [`src/core/review-loop-turn-dispatch.ts`](../../src/core/review-loop-turn-dispatch.ts) |
|
|
191
|
+
| Common attempt + projections | [`src/core/loops/attempt-authority.ts`](../../src/core/loops/attempt-authority.ts), [`src/core/loops/turn-execution.ts`](../../src/core/loops/turn-execution.ts) |
|
|
192
|
+
| Close / reducer | [`src/core/loops/reconcile-turn.ts`](../../src/core/loops/reconcile-turn.ts), [`src/core/review-loop-close.ts`](../../src/core/review-loop-close.ts) |
|
|
193
|
+
| Result reducer | [`src/core/loops/result-reducers.ts`](../../src/core/loops/result-reducers.ts) |
|
|
194
|
+
| Tests | [`tests/unit/review-loop-close.test.ts`](../../tests/unit/review-loop-close.test.ts), [`tests/unit/loops-mcp-facade.test.ts`](../../tests/unit/loops-mcp-facade.test.ts) |
|
|
195
|
+
|
|
196
|
+
## Related
|
|
197
|
+
|
|
198
|
+
- [Loop Engine](../concepts/loop-engine.md)
|
|
199
|
+
- [Attempt authority](../concepts/attempt-authority.md)
|
|
200
|
+
- [Dispatch lifecycle](../concepts/dispatch-lifecycle.md)
|
|
@@ -408,7 +408,20 @@ will still succeed. A follow-up PR will strip the dead handler code.
|
|
|
408
408
|
changelog records the published MCP surface fingerprint. When a tool
|
|
409
409
|
name, tier, category, or input schema changes, the test fails until
|
|
410
410
|
this section is updated.
|
|
411
|
-
- MCP public surface fingerprint: `sha256:
|
|
411
|
+
- MCP public surface fingerprint: `sha256:681c47cba85b79c3`
|
|
412
|
+
(`LoopSlotInput` gains optional `lane`, `scope_hint`, `plan_ids`, and
|
|
413
|
+
`step_ids` fields so implementation-loop lane scope and provenance survive
|
|
414
|
+
through the public facade. Existing callers remain valid.)
|
|
415
|
+
Previous: `sha256:81243f3d507c274e`
|
|
416
|
+
(updated 2026-08-23 for the common Loop Engine worker driver: `turn` exposes
|
|
417
|
+
real dispatch/model/candidate controls and `complete_turn` exposes the full
|
|
418
|
+
AttemptAuthority fence; bind remains engine-only with compatibility inputs.)
|
|
419
|
+
Previous: `sha256:47fa4e8a66fae55d`
|
|
420
|
+
(updated 2026-08-23 for AttemptAuthority v2: the public Loop Engine surface
|
|
421
|
+
exposes `open`, `verify`, `request_input`, and `provide_input`; Assignment and
|
|
422
|
+
Claim mutations carry the complete attempt fence and coordinator override is
|
|
423
|
+
explicit.)
|
|
424
|
+
Previous: `sha256:b8dbb80bae8f6e36`
|
|
412
425
|
(updated 2026-08-10 for pln#665: `bclaw_code_export` — additive Tier-B read tool for a required, bounded local Code Map subgraph. Its target, direction, depth, node/edge caps, confidence threshold, and optional Mermaid projection are explicit; JSON retains each relation's kind/source/confidence and never defaults to a whole-graph export.)
|
|
413
426
|
Previous: `sha256:9ed35ed6cc49ea9a`
|
|
414
427
|
(updated 2026-08-10 for pln#661: `bclaw_code_impact` — additive Tier-B read tool
|
|
@@ -420,10 +433,10 @@ will still succeed. A follow-up PR will strip the dead handler code.
|
|
|
420
433
|
source-ordered symbols of one indexed file from the existing shard; no reparse,
|
|
421
434
|
no mutation, bounded output. Purely additive.)
|
|
422
435
|
(updated 2026-07-25 for pln#632: `bclaw_loop` gains the `bind` intent — an
|
|
423
|
-
implementation loop
|
|
424
|
-
|
|
425
|
-
`max_assignments
|
|
426
|
-
|
|
436
|
+
implementation loop validates its linked sequence and advances bind→execute.
|
|
437
|
+
Historical launch-shaped properties `lanes`, `auto_execute`, `model`, and
|
|
438
|
+
`max_assignments` remain accepted but are ignored; worker launch now goes through
|
|
439
|
+
`turn(dispatch=true)` and AttemptAuthority. Additive — no tool removed/renamed.)
|
|
427
440
|
Previous: `sha256:f3d49b28d2d366bb`
|
|
428
441
|
(updated 2026-07-24 for pln#630 PR2b-a: `LoopSlotSchema` gains an optional
|
|
429
442
|
`current_turn_id`, which flows through the zod-derived `LoopSlotInput` into
|