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.
Files changed (88) hide show
  1. package/README.md +13 -0
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli/register-coordination.js +65 -1
  4. package/dist/commands/attempt-authority.js +80 -0
  5. package/dist/commands/harvest.js +140 -61
  6. package/dist/commands/loop.js +34 -0
  7. package/dist/commands/loops-handlers.js +143 -15
  8. package/dist/commands/mcp-catalog.js +52 -18
  9. package/dist/commands/mcp-schemas.generated.js +64 -0
  10. package/dist/commands/mcp-write-claims.js +128 -1
  11. package/dist/commands/mcp-write-coordination.js +149 -76
  12. package/dist/core/agent-capability.js +1 -1
  13. package/dist/core/agentrun-reconciler.js +148 -22
  14. package/dist/core/agentruns.js +254 -29
  15. package/dist/core/assignment-request-schema.js +7 -0
  16. package/dist/core/assignment-sweeper.js +5 -3
  17. package/dist/core/assignments.js +131 -33
  18. package/dist/core/claim-request-schema.js +7 -0
  19. package/dist/core/claims.js +53 -2
  20. package/dist/core/dispatch-status.js +16 -6
  21. package/dist/core/dispatcher.js +51 -51
  22. package/dist/core/entity-operations.js +20 -0
  23. package/dist/core/events.js +4 -0
  24. package/dist/core/execution-adapters.js +189 -14
  25. package/dist/core/execution-contract.js +345 -0
  26. package/dist/core/execution.js +130 -16
  27. package/dist/core/facade-schema.js +3 -0
  28. package/dist/core/harness-adapters/base.js +150 -0
  29. package/dist/core/harness-adapters/claude.js +39 -0
  30. package/dist/core/harness-adapters/codex.js +57 -0
  31. package/dist/core/harness-adapters/harvest.js +109 -0
  32. package/dist/core/harness-adapters/index.js +8 -0
  33. package/dist/core/harness-adapters/prompt-only.js +13 -0
  34. package/dist/core/harness-adapters/registry.js +48 -0
  35. package/dist/core/harness-adapters/result.js +33 -0
  36. package/dist/core/harness-adapters/types.js +2 -0
  37. package/dist/core/ideation-loop-close.js +25 -2
  38. package/dist/core/instruction-templates.js +3 -2
  39. package/dist/core/loop-turn-dispatch.js +235 -0
  40. package/dist/core/loops/artifact-contract.js +11 -0
  41. package/dist/core/loops/attempt-authority.js +496 -0
  42. package/dist/core/loops/attempt-generations.js +509 -0
  43. package/dist/core/loops/attempt-reservation.js +197 -35
  44. package/dist/core/loops/attempt-rollout.js +404 -0
  45. package/dist/core/loops/attempt-takeover.js +155 -0
  46. package/dist/core/loops/bootstrap-acquire.js +7 -3
  47. package/dist/core/loops/brief-assembly.js +21 -4
  48. package/dist/core/loops/evidence.js +188 -0
  49. package/dist/core/loops/facade-schema.js +75 -11
  50. package/dist/core/loops/gate-policy.js +533 -0
  51. package/dist/core/loops/impl-bind.js +91 -81
  52. package/dist/core/loops/index.js +9 -0
  53. package/dist/core/loops/iteration-engine.js +31 -19
  54. package/dist/core/loops/kind-policies.js +90 -0
  55. package/dist/core/loops/lock.js +71 -13
  56. package/dist/core/loops/reconcile-turn.js +237 -18
  57. package/dist/core/loops/result-reducers.js +113 -10
  58. package/dist/core/loops/store.js +34 -3
  59. package/dist/core/loops/turn-execution.js +480 -0
  60. package/dist/core/loops/types.js +127 -3
  61. package/dist/core/loops/verbs.js +335 -99
  62. package/dist/core/loops/verify-command.js +105 -20
  63. package/dist/core/loops/workspace-digest.js +54 -0
  64. package/dist/core/review-loop-close.js +25 -3
  65. package/dist/core/review-loop-turn-dispatch.js +210 -161
  66. package/dist/core/runtime-signals.js +62 -25
  67. package/dist/core/schema.js +40 -0
  68. package/dist/core/spawn-check.js +3 -2
  69. package/dist/core/upgrades/backup.js +27 -4
  70. package/dist/facts.js +9 -8
  71. package/dist/facts.json +8 -7
  72. package/docs/cli.md +49 -1
  73. package/docs/concepts/attempt-authority.md +407 -0
  74. package/docs/concepts/evidence-attestations.md +135 -0
  75. package/docs/concepts/execution-contract.md +166 -0
  76. package/docs/concepts/harness-adapters.md +166 -0
  77. package/docs/concepts/ideation-loop.md +5 -4
  78. package/docs/concepts/loop-engine.md +302 -113
  79. package/docs/index.md +4 -1
  80. package/docs/integrations/codex.md +3 -3
  81. package/docs/integrations/mcp.md +59 -5
  82. package/docs/loops/debug.md +144 -0
  83. package/docs/loops/ideation.md +158 -0
  84. package/docs/loops/implementation.md +174 -0
  85. package/docs/loops/research.md +136 -0
  86. package/docs/loops/review.md +200 -0
  87. package/docs/mcp-schema-changelog.md +18 -5
  88. package/package.json +1 -1
package/docs/index.md CHANGED
@@ -28,8 +28,11 @@ Use this page as the entry point into the packaged Markdown documentation.
28
28
  - [concepts/workspace-bootstrapping.md](concepts/workspace-bootstrapping.md)
29
29
  - [concepts/troubleshooting.md](concepts/troubleshooting.md) — runbook for degraded coordination state
30
30
  - [concepts/memory-staleness.md](concepts/memory-staleness.md)
31
- - [concepts/loop-engine.md](concepts/loop-engine.md)
31
+ - [concepts/loop-engine.md](concepts/loop-engine.md) — shared runtime for the five loop protocols
32
+ - [concepts/attempt-authority.md](concepts/attempt-authority.md) — identity, dispatch decisions and spawn authority for every turn
33
+ - [concepts/evidence-attestations.md](concepts/evidence-attestations.md) — server-sealed loop evidence, independent attestations, and protocol gates
32
34
  - [concepts/ideation-loop.md](concepts/ideation-loop.md) — memory-confrontation ideation loop (v1.5.0+)
35
+ - Loop protocol guides — [review](loops/review.md), [ideation](loops/ideation.md), [implementation](loops/implementation.md), [research](loops/research.md), [debug](loops/debug.md)
33
36
  - [concepts/mcp-governance.md](concepts/mcp-governance.md)
34
37
  - [concepts/federation-v2-rfc.md](concepts/federation-v2-rfc.md) — contrat joint core + Cloud pour la fédération chiffrée v2
35
38
 
@@ -47,9 +47,9 @@ The `--sandbox workspace-write` setting is required, **not `read-only`** — the
47
47
 
48
48
  ### Prompt delivery: stdin_pipe (preferred)
49
49
 
50
- Since pln#475 (1.0.10+), Codex spawned as a child process receives its prompt via **stdin** rather than as an inline argument. The reason is Windows-specific: `codex.cmd` resolves through `cmd.exe`, where embedded backticks, `#`, or multi-line content can be mis-parsed and raise `unexpected argument`. Reading from stdin avoids that.
50
+ Since pln#475 (1.0.10+), Codex spawned as a child process receives its prompt via **stdin** rather than as an inline argument. The reason is Windows-specific: `codex.cmd` resolves through `cmd.exe`, where embedded backticks, `#`, or multi-line content can be mis-parsed and raise `unexpected argument`. Keeping the prompt out of argv avoids that.
51
51
 
52
- When you (or the dispatcher) calls Codex with no positional `[PROMPT]`, Codex reads stdin until EOF that's where brainclaw pipes the brief. `inline_arg` remains a fallback for short prompts on POSIX.
52
+ When you (or the dispatcher) calls Codex with no positional `[PROMPT]`, Codex reads stdin until EOF. A direct spawn pipes the brief normally. On Windows, an ack-wrapped spawn writes the brief to a private per-run file, redirects that file to Codex stdin, and deletes it after the terminal sentinel. This is still `stdin_pipe` at the harness contract: the file is a transport detail that guarantees EOF through `cmd.exe` and keeps prompt content out of shell syntax. `inline_arg` remains a fallback for short prompts on POSIX.
53
53
 
54
54
  ### Brief-ack handshake
55
55
 
@@ -89,6 +89,6 @@ The file shape is `{ "hooks": { "<Event>": [ { "matcher": "", "hooks": [ { "type
89
89
  ## Caveats
90
90
 
91
91
  - **Sandbox blocks `git commit`, not MCP** (dec#133): a sandboxed Codex run reaches brainclaw MCP (the server is a separate out-of-sandbox process; `approval_policy=never` auto-approves). What the sandbox *does* block is direct writes to paths outside the worktree root — notably `.git`, so the worker cannot `git commit`. Leave fixes uncommitted; the coordinator integrates + commits the worktree diff at harvest. A LANE-RESULT.json / filesystem-direct candidate write remains a valid fallback for reporting.
92
- - **Windows quoting**: long prompts containing backticks or `#` fail when passed as inline args through `cmd.exe`. The default stdin_pipe path avoids this.
92
+ - **Windows prompt transport**: long prompts containing backticks or `#` fail when passed as inline args through `cmd.exe`, while a parent stdin pipe can fail to propagate EOF to a native grandchild. The default ack-wrapped path uses a per-run file redirected to stdin and removes it after the terminal sentinel, avoiding both failure modes.
93
93
  - **Sandbox vs review parity**: review runs use the same `workspace-write` sandbox as execution runs (older templates forced `read-only` on reviews; that path blocked PowerShell exec on Windows).
94
94
  - **No always-allow**: each MCP tool call still respects per-call approval policy unless explicitly set with `-c approval_policy="never"`.
@@ -68,7 +68,7 @@ Each tool also has an `annotations.category` field: `session`, `context`, `memor
68
68
  | `bclaw_context` | context | Unified context read for memory, execution, board, board summary, and deltas |
69
69
  | `bclaw_coordinate` | coordination | Assign, consult, review, ideate, reroute, or summarize across agents |
70
70
  | `bclaw_dispatch` | coordination | Analyze, execute, or review dispatch work through one intent-based entry point |
71
- | `bclaw_loop` | loops | Drive multi-turn review, ideation, implementation, research, or debug loops |
71
+ | `bclaw_loop` | loops | Drive review, ideation, implementation, research, or debug loops, including fenced physical-run takeover |
72
72
  | `bclaw_setup` | session | Agent-driven onboarding wizard |
73
73
 
74
74
  ### Standard tools
@@ -86,7 +86,7 @@ Each tool also has an `annotations.category` field: `session`, `context`, `memor
86
86
  | `bclaw_write_note` | memory | Record a runtime note |
87
87
  | `bclaw_quick_capture` | memory | Capture text and classify it locally as a decision, trap, or runtime note |
88
88
  | `bclaw_claim` | coordination | Claim a work scope (advisory lock, auto-worktree) |
89
- | `bclaw_release_claim` | coordination | Release a claim, optionally updating linked plan status |
89
+ | `bclaw_release_claim` | coordination | Release a legacy/unsettled-independent claim, optionally updating linked plan status; v2 loop claims are released by settlement projections or audited coordinator override |
90
90
  | `bclaw_session_start` | session | Start a session explicitly (granular workflow) |
91
91
  | `bclaw_session_end` | session | End session, optionally auto-reflect notes or handoffs |
92
92
  | `bclaw_add_step` | coordination | Add a sub-step to a plan item |
@@ -98,7 +98,7 @@ Each tool also has an `annotations.category` field: `session`, `context`, `memor
98
98
  | `bclaw_update_sequence` | coordination | Update a sequence's status, metadata, or items |
99
99
  | `bclaw_delete_sequence` | coordination | Delete a sequence by ID |
100
100
  | `bclaw_correct_handoff` | coordination | Write an immutable correction handoff that supersedes an earlier one |
101
- | `bclaw_assignment_update` | coordination | Report assignment lifecycle status |
101
+ | `bclaw_assignment_update` | coordination | Report assignment lifecycle status; v2 logical Assignments require the full generation fence and accept only accepted/started/progress before settlement |
102
102
  | `bclaw_assignment_action` | coordination | Resolve or reject a pending ActionRequired item |
103
103
  | `bclaw_harvest_candidates` | coordination | Harvest sandboxed worktree candidate files into the main project store |
104
104
  | `bclaw_find` | memory | List canonical entities with filters |
@@ -399,7 +399,8 @@ bclaw_context({ kind: 'board_summary' })
399
399
  // Review dispatch with structured loop
400
400
  bclaw_dispatch({ intent: 'review', openLoop: true, reviewMode: 'symmetric' })
401
401
 
402
- // Open a memory-confrontation ideation loop (single-agent: champion drives manually)
402
+ // Open a single-agent ideation loop. Proposal is manual; critique, revision and
403
+ // synthesis are worker phases available through trusted turn(dispatch:true).
403
404
  bclaw_coordinate({ intent: 'ideate', task: 'Should we extract the dispatcher into a separate package?' })
404
405
 
405
406
  // Multi-agent ideation: critic gets a context-filtered, BM25-ranked brief auto-dispatched
@@ -410,7 +411,8 @@ bclaw_coordinate({
410
411
  })
411
412
 
412
413
  // Open a direct implementation loop. The caller owns subsequent bind/turn
413
- // actions, which is why allow_orphan is explicit.
414
+ // actions, which is why allow_orphan is explicit. Bind is engine-only; after
415
+ // it advances to execute, turn(dispatch:true) is the worker launch path.
414
416
  bclaw_loop({
415
417
  intent: 'open',
416
418
  kind: 'implementation',
@@ -420,6 +422,52 @@ bclaw_loop({
420
422
  verify: { command: ['npm', 'test'] },
421
423
  })
422
424
 
425
+ bclaw_loop({ intent: 'bind', loop_id: 'lop_abc' })
426
+ bclaw_loop({
427
+ intent: 'turn', loop_id: 'lop_abc', slot_id: 'lsl_worker',
428
+ dispatch: true, target_agents: ['codex', 'claude-code'],
429
+ })
430
+
431
+ // Direct research/debug loops use the same facade. A plain turn records state;
432
+ // trusted dispatch:true actually prepares, fences and launches a worker.
433
+ bclaw_loop({
434
+ intent: 'open',
435
+ kind: 'research',
436
+ title: 'Determine the safe migration boundary',
437
+ goal: 'Produce a sourced synthesis',
438
+ allow_orphan: true,
439
+ })
440
+ bclaw_loop({
441
+ intent: 'turn',
442
+ loop_id: 'lop_research',
443
+ slot_id: 'lsl_investigator',
444
+ dispatch: true,
445
+ target_agents: ['codex', 'claude-code'], // only used when the slot is unbound
446
+ })
447
+
448
+ bclaw_loop({
449
+ intent: 'open',
450
+ kind: 'debug',
451
+ title: 'Reproduce and fix the Windows dispatch failure',
452
+ allow_orphan: true,
453
+ })
454
+ bclaw_loop({ intent: 'turn', loop_id: 'lop_debug', slot_id: 'lsl_reproducer', dispatch: true })
455
+
456
+ // Fence a stale physical generation without changing the logical turn or Assignment.
457
+ // This arms the successor; dispatch the same turn afterwards to contend on launch.
458
+ bclaw_loop({
459
+ intent: 'takeover',
460
+ loop_id: 'lop_abc',
461
+ slot_id: 'lsl_abc',
462
+ turn_id: 'tat_abc',
463
+ expected_epoch: 0,
464
+ cause: 'heartbeat and process evidence are stale',
465
+ liveness_evidence: 'no heartbeat for 30m; wrapper exited',
466
+ external_effect_policy: 'idempotent',
467
+ next_workspace_path: 'C:\\worktrees\\brainclaw-retry-1',
468
+ agent: 'coordinator',
469
+ })
470
+
423
471
  // Correct a handoff instead of mutating it
424
472
  bclaw_correct_handoff({ originalId: 'hnd_xyz', reason: 'wrong contract', text: '...' })
425
473
  ```
@@ -430,6 +478,12 @@ advance gate, brief assembly, single vs multi-agent UX), see
430
478
  engine supports the five built-in `review`, `ideation`, `implementation`,
431
479
  `research`, and `debug` workflows, plus cross-cutting `request_input` /
432
480
  `provide_input`; see [docs/concepts/loop-engine.md](../concepts/loop-engine.md).
481
+ Takeover is likewise cross-cutting, not review-specific. Once a turn has an
482
+ AttemptAuthority v2 generation chain, terminal evidence must echo the complete
483
+ `assignment_id`, `turn_id`, `attempt_epoch`, `run_id`, `nonce`,
484
+ `execution_contract_hash`, and `workspace_digest` fence; a stale generation is
485
+ retained for audit but cannot converge loop state. See
486
+ [docs/concepts/attempt-authority.md](../concepts/attempt-authority.md).
433
487
 
434
488
  #### Deprecation status
435
489
 
@@ -0,0 +1,144 @@
1
+ # Debug loop
2
+
3
+ > Loop kind: `debug`. 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 use `repro`, `hypothesis`, `isolation_report`, and
9
+ `verify_report` respectively. The mutating `fix` phase remains claimed until
10
+ `harvest --integrate`; the earlier read-only phases may converge on report.
11
+
12
+ ## Purpose
13
+
14
+ A `debug` loop drives a broken system back to green. The invariant it
15
+ enforces: "bug fixed" ⟺ "the reproducing command is now green" ⟺ "a passing
16
+ `verify_report`". It mirrors [`implementation`](./implementation.md)'s
17
+ `execute ↔ verify` pattern but starts one step earlier: `reproduce` must
18
+ land a concrete repro before hypothesise-isolate-fix begins.
19
+
20
+ ## Default protocol
21
+
22
+ ```
23
+ reproduce → hypothesize ↔ isolate ↔ fix → handoff
24
+ └────── iterate (≤3) ─────┘
25
+ ```
26
+
27
+ | Phase | Purpose | Artifact | Context filter |
28
+ |---|---|---|---|
29
+ | `reproduce` | Land a reliable repro of the bug | `repro` | `traps`, `runtime_notes`, `handoffs`, `plans` |
30
+ | `hypothesize` | Propose a cause | `hypothesis` | `decisions`, `constraints`, `traps`, `runtime_notes` |
31
+ | `isolate` | Narrow to a single change | `isolation_report` | `decisions`, `constraints`, `traps`, `runtime_notes` |
32
+ | `fix` | Apply the fix; re-run the repro | edits + `verify_report` | `traps`, `runtime_notes`, `constraints` |
33
+ | `handoff` | Ship the diff to review | `handoff` | `handoffs`, `plans` |
34
+
35
+ **Iteration.** `hypothesize ↔ isolate ↔ fix` cycles up to
36
+ `max_iterations: 3`. `exit_when: 'command_green'` — the same predicate
37
+ `implementation` uses — exits early on a passing `verify_report` in the
38
+ current iteration. `advance_when: 'all'` is the default.
39
+
40
+ ## Entry points
41
+
42
+ - **Direct open (typical).**
43
+ `bclaw_loop(intent='open', kind='debug', linked={handoff_ids:[…]}, allow_orphan=true)`
44
+ followed by a `turn` for the `reproduce` phase. There is no coordinator
45
+ shortcut for `debug` today. Plain `turn` is state-only; trusted
46
+ `turn(dispatch=true)` launches a worker phase through the common
47
+ AttemptAuthority path.
48
+ - **Referred from `implementation`.** An `implementation` loop that
49
+ closes `blocked` at the cycle cap with a red `verify_report` is a
50
+ natural feeder — open a `debug` loop that links the red report as its
51
+ seed `repro` artifact.
52
+
53
+ ## Advance gates
54
+
55
+ Two phases carry gates:
56
+
57
+ **`reproduce`** — cannot start hypothesising without a concrete repro:
58
+
59
+ ```ts
60
+ { kind: 'artifact_produced', phase: 'reproduce', type: 'repro' }
61
+ ```
62
+
63
+ **`fix`** — cannot leave `fix` without a `verify_report` this iteration
64
+ (same shape as `implementation`'s verify gate):
65
+
66
+ ```ts
67
+ { kind: 'min_artifacts_by_type', type: 'verify_report', n: 1, scope: 'phase' }
68
+ ```
69
+
70
+ ## Stop condition
71
+
72
+ ```ts
73
+ { kind: 'any', conditions: [
74
+ { kind: 'artifact_produced', phase: 'handoff', type: 'handoff' },
75
+ { kind: 'max_iterations', n: 3 },
76
+ ] }
77
+ ```
78
+
79
+ - **Handoff produced** → close `completed`. The handoff carries the diff
80
+ for a downstream `review` loop.
81
+ - **Cycle cap** → close `blocked`; the last red `verify_report` stays on
82
+ the loop as evidence. A human picks up.
83
+
84
+ ## Artifacts
85
+
86
+ | Type | Phase | Body |
87
+ |---|---|---|
88
+ | `repro` | `reproduce` | inline ≤ 4 KB: the command / test / URL that fails, and the exit signature |
89
+ | `hypothesis` | `hypothesize` | inline ≤ 4 KB |
90
+ | `isolation_report` | `isolate` | inline ≤ 4 KB |
91
+ | `verify_report` | `fix` | inline JSON: `{ command, exit_code, passed, duration_ms?, stdout_tail?, stderr_tail? }` |
92
+ | `file_diff` | any phase | ref-based body (`{ref, byte_count, sha256}`) |
93
+ | `handoff` | `handoff` | `ref` to a `handoff` primitive |
94
+
95
+ ## Routing
96
+
97
+ `debug` is claim-routed: `slot.claim_id` points at the scope claim the
98
+ fixer slot holds. The scope of the claim should cover the code under
99
+ investigation so the isolation and fix turns can edit freely.
100
+ `session_id` is observability-only.
101
+
102
+ ## Recovery
103
+
104
+ - **Fixer worker crashed mid-cycle.** Launch grant lease expires;
105
+ `sweepExpiredLaunchGrants` revokes it; re-dispatch arms a new
106
+ generation at a strictly greater epoch. A prior-iteration
107
+ `verify_report` cannot satisfy the current iteration's gate.
108
+ - **Command-green mid-cycle.** `exit_when: 'command_green'`
109
+ short-circuits the cycle; the driver advances to `handoff` on the next
110
+ `advance`.
111
+ - **Reproduce blocked.** The `phase_advance_blocked` system event records
112
+ the missing `repro`. Add a repro artifact, or narrow the loop scope.
113
+ - **Red `verify_report` at cap.** Loop closes `blocked`; the accumulated
114
+ hypotheses, isolation reports, and red verify reports stay on the loop
115
+ so the next human or agent has the trail.
116
+
117
+ ## When NOT to use
118
+
119
+ - **Building something new that doesn't reproduce anything.** Use
120
+ [`implementation`](./implementation.md).
121
+ - **Investigating an open-ended "why?" with no failing command.** Use
122
+ [`research`](./research.md).
123
+ - **Choosing between two architectural fixes.** Use
124
+ [`ideation`](./ideation.md) to pressure the choice against project
125
+ memory first.
126
+ - **Validating a landed fix.** Use [`review`](./review.md); the
127
+ `handoff` a debug loop emits is exactly what a review loop consumes.
128
+
129
+ ## Reference implementation
130
+
131
+ | Component | File |
132
+ |---|---|
133
+ | Default protocol | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) (`DEFAULT_PROTOCOLS.debug`) |
134
+ | Iteration FSM (`command_green`) | [`src/core/loops/iteration-engine.ts`](../../src/core/loops/iteration-engine.ts) |
135
+ | Gate evaluator | [`src/core/loops/verbs.ts`](../../src/core/loops/verbs.ts) (`evaluatePhaseAdvanceGate`) |
136
+ | 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) |
137
+ | Result reducer | [`src/core/loops/result-reducers.ts`](../../src/core/loops/result-reducers.ts) |
138
+ | 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), [`tests/unit/loops-impl-protocol.test.ts`](../../tests/unit/loops-impl-protocol.test.ts) |
139
+
140
+ ## Related
141
+
142
+ - [Loop Engine](../concepts/loop-engine.md)
143
+ - [Attempt authority](../concepts/attempt-authority.md)
144
+ - [dispatch-lifecycle.md](../concepts/dispatch-lifecycle.md)
@@ -0,0 +1,158 @@
1
+ # Ideation loop
2
+
3
+ > Loop kind: `ideation`. 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
+ The automated critic returns `artifact_type: "critique"` with a non-empty
9
+ `body`. A narrative `summary` alone never creates a critique or opens the gate.
10
+
11
+ ## Purpose
12
+
13
+ An `ideation` loop stress-tests a proposal **before** it crystallises into a
14
+ plan. Where [`review`](./review.md) validates a finished artifact and asks
15
+ "is this good?", `ideation` takes a fresh proposal and asks "what does our
16
+ accumulated project experience say will go wrong with this?"
17
+
18
+ The adversarial substrate is the project's own memory — traps, feedback
19
+ memos, runtime notes. Even a single-agent run produces useful pressure
20
+ because the phase context filter forces the critic to confront adversarial
21
+ memory rather than the positive context that seeded the proposal. See
22
+ [ideation-loop.md](../concepts/ideation-loop.md) for the full RFC-level
23
+ design; this page is the operator-facing summary.
24
+
25
+ ## Default protocol
26
+
27
+ ```
28
+ proposal → critique ↔ revision → synthesis
29
+ └─── iterate (≤3) ────┘
30
+ ```
31
+
32
+ | Phase | Purpose | Artifact | Context filter |
33
+ |---|---|---|---|
34
+ | `proposal` | Seed: the original idea | `proposal` (text ≤ 4 KB) | `decisions`, `constraints`, `plans`, `project_vision` |
35
+ | `critique` | Adversarial review against project memory | `critique` (repeatable) | `traps`, `feedback`, `runtime_notes`, `critique_history` |
36
+ | `revision` | Champion responds to the critique batch | `revision` | `*` |
37
+ | `synthesis` | Fold the cycle's outputs into a plan draft | `plan_draft` | `*` |
38
+
39
+ **Iteration.** `critique ↔ revision` iterates up to
40
+ `max_iterations: 3`; `exit_when: 'no_new_critique_artifacts'` stops the cycle
41
+ when a full round adds no new critique. `critic_signal` is available for
42
+ explicit early exit.
43
+
44
+ ## Entry points
45
+
46
+ - **Coordinator shortcut (recommended).**
47
+ `bclaw_coordinate(intent='ideate', task=…, [targetAgents=[…]])` opens the
48
+ loop with a `champion` slot (caller) and one `critic` slot per target
49
+ agent, stores `task` as the `proposal` artifact, advances to `critique`
50
+ in multi-agent mode, and dispatches the first critic with a brief
51
+ assembled by [`buildIdeationBrief`](../../src/core/loops/brief-assembly.ts).
52
+ - **Single-agent mode** — omit `targetAgents`. The champion drives each
53
+ turn via `bclaw_loop(intent='turn'|'advance')`. A plain `turn` only records
54
+ the assignment; on a worker phase, a trusted caller can set
55
+ `dispatch=true` to launch through AttemptAuthority. Useful when you want the
56
+ loop's structure (memory filter, gate, iteration accounting) without the
57
+ coordinator shortcut.
58
+ - **Direct open.** `bclaw_loop(intent='open', kind='ideation', allow_orphan=true)`.
59
+
60
+ ## Advance gates
61
+
62
+ The `critique` phase carries a default `advance_gate`:
63
+
64
+ ```ts
65
+ { kind: 'min_artifacts_by_type', type: 'critique', n: 3, scope: 'phase' }
66
+ ```
67
+
68
+ Advance to `revision` is refused until at least 3 `critique` artifacts have
69
+ been produced **in the current iteration window**. A previous round's
70
+ critiques do not satisfy the gate for a new round. On gate failure, the
71
+ driver emits a `phase_advance_blocked` system event with a structured
72
+ `gate_reason` and throws an actionable error.
73
+
74
+ ## Stop condition
75
+
76
+ ```ts
77
+ { kind: 'artifact_produced', phase: 'synthesis', type: 'plan_draft' }
78
+ ```
79
+
80
+ The loop closes `completed` on the first `plan_draft` artifact in
81
+ `synthesis`. Override via
82
+ `bclaw_loop(intent='open', stop_condition: …)` — e.g. a
83
+ `min_artifacts_by_type { type: 'critique', n: 5, scope: 'loop' }` stops after
84
+ five critiques have accumulated loop-wide.
85
+
86
+ ## Artifacts
87
+
88
+ | Type | Phase | Body |
89
+ |---|---|---|
90
+ | `proposal` | `proposal` | inline text ≤ 4 KB |
91
+ | `critique` | `critique` | inline ≤ 4 KB; must cite memory ids used |
92
+ | `revision` | `revision` | inline ≤ 4 KB |
93
+ | `plan_draft` | `synthesis` | inline ≤ 4 KB; MUST carry `addresses_critique: [artifact_id, …]` |
94
+ | `critic_signal` | `critique` | inline ≤ 4 KB; opts an explicit early cycle exit |
95
+
96
+ `plan_draft` field-presence is enforced at the zod level on
97
+ `LoopArtifactSchema` — a synthesis that omits `addresses_critique` is
98
+ rejected at write time.
99
+
100
+ ## Brief assembly
101
+
102
+ Each critic turn ships a size-capped brief (48 KB) with a BM25-ranked
103
+ memory bundle scoped to the phase's `context_filter`. When the bundle
104
+ overflows, the assembler appends a truncation tail and surfaces `truncated`,
105
+ `includedItems`, and `droppedItems` per-slot. This mitigates
106
+ [trp#179](../../src/core/loops/brief-assembly.ts) — oversized bundles push
107
+ agents onto CLI tools instead of MCP semantics.
108
+
109
+ ## Routing
110
+
111
+ `ideation` routes turns by `slot_id`; the coordinator shortcut queues a
112
+ message per critic with the brief as body and
113
+ `{intent: 'ideate', loop_id, slot_id, phase, iteration, proposal_artifact_id}`
114
+ as payload. Dispatch failures per slot surface as `partial`; the loop stays
115
+ at the proposal phase and callers can retry manually.
116
+
117
+ ## Recovery
118
+
119
+ - **Critic worker crashed mid-turn.** Launch grant lease expires;
120
+ `sweepExpiredLaunchGrants` revokes it; the coordinator can re-dispatch
121
+ with a fresh generation.
122
+ - **Gate blocked at critique.** The `phase_advance_blocked` system event
123
+ records the structured reason. Champion adds more `critique` artifacts,
124
+ or overrides the gate on `open` for a permissive one-shot run.
125
+ - **Cycle cap hit without saturation.** `iteration-engine` emits
126
+ `max_iterations_reached`; the driver moves to `synthesis` regardless.
127
+ - **Synthesis missing `addresses_critique`.** Rejected at
128
+ `complete_turn` — the champion re-emits with the ids populated.
129
+
130
+ ## When NOT to use
131
+
132
+ - **Quick clarification.** A 2-turn message thread is cheaper.
133
+ - **Operationally urgent decisions.** The iteration block adds latency —
134
+ use `bclaw_coordinate(intent='consult')` for "the build is broken".
135
+ - **A domain with no accumulated project memory.** The critic will fetch
136
+ nothing and the brief will be a no-op; seed memory first, or run a
137
+ literal multi-agent loop where the critic brings its own perspective.
138
+ - **Validating a change that already exists.** Use
139
+ [`review`](./review.md).
140
+
141
+ ## Reference implementation
142
+
143
+ | Component | File |
144
+ |---|---|
145
+ | Default protocol | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) (`DEFAULT_PROTOCOLS.ideation`) |
146
+ | Iteration FSM | [`src/core/loops/iteration-engine.ts`](../../src/core/loops/iteration-engine.ts) |
147
+ | Gate evaluator | [`src/core/loops/verbs.ts`](../../src/core/loops/verbs.ts) (`evaluatePhaseAdvanceGate`) |
148
+ | Brief assembler | [`src/core/loops/brief-assembly.ts`](../../src/core/loops/brief-assembly.ts) |
149
+ | Driver | [`src/commands/mcp-write-coordination.ts`](../../src/commands/mcp-write-coordination.ts) (`req.intent === 'ideate'`) |
150
+ | 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) |
151
+ | Result reducer | [`src/core/loops/result-reducers.ts`](../../src/core/loops/result-reducers.ts) |
152
+ | 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), [`tests/unit/loops-brief-assembly.test.ts`](../../tests/unit/loops-brief-assembly.test.ts), [`tests/unit/ideation-loop-e2e.test.ts`](../../tests/unit/ideation-loop-e2e.test.ts) |
153
+
154
+ ## Related
155
+
156
+ - [Loop Engine](../concepts/loop-engine.md)
157
+ - [Attempt authority](../concepts/attempt-authority.md)
158
+ - [ideation-loop.md](../concepts/ideation-loop.md) — full RFC
@@ -0,0 +1,174 @@
1
+ # Implementation loop
2
+
3
+ > Loop kind: `implementation`. 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
+ The `execute` worker returns `artifact_type: "execute_report"`. Because this
9
+ phase edits its worktree, report-only harvest does not settle the turn or
10
+ release its claim; convergence happens after `harvest --integrate`.
11
+
12
+ ## Purpose
13
+
14
+ An `implementation` loop drives a bound plan+sequence to a green
15
+ verification command. It ADDS to the dispatch pipeline what that pipeline
16
+ lacked: a deterministic `command_green` gate, a bounded `execute ↔ verify`
17
+ cycle, and per-phase context sculpting. `bind` is an engine-only action: it
18
+ validates the plan/sequence link and advances to `execute`. It never launches
19
+ a worker. `execute ↔ verify` iterates until the verify command is green or
20
+ the cycle cap is hit.
21
+
22
+ Binding validates the complete graph: every sequence item must reference a
23
+ linked, existing plan (and an existing step when `stepId` is present). Explicit
24
+ sequence lanes are paired deterministically with worker slots, one slot per
25
+ lane. Each slot then carries its lane, plan/step ids, and `scope_hint`.
26
+
27
+ ## Default protocol
28
+
29
+ ```
30
+ bind → execute ↔ verify → handoff_ready
31
+ └── iterate (≤3) ───┘
32
+ ```
33
+
34
+ | Phase | Purpose | Artifact | Context filter |
35
+ |---|---|---|---|
36
+ | `bind` | Validate the linked plan + sequence; advance to `execute` | link already stored on the loop | `plans`, `decisions`, `constraints`, `project_vision` |
37
+ | `execute` | Apply the sequence's steps in the worktree | edits + `execute_report` | `decisions`, `constraints`, `traps`, `runtime_notes` |
38
+ | `verify` | Run the declared verify command | `verify_report` | `traps`, `runtime_notes` |
39
+ | `handoff_ready` | Produce the handoff for downstream review | `handoff` | `handoffs`, `plans` |
40
+
41
+ **Iteration.** `execute ↔ verify` cycles up to `max_iterations: 3`.
42
+ `exit_when: 'command_green'` exits early on a passing `verify_report` in the
43
+ current iteration. `advance_when: 'all'` on each phase means every
44
+ participating slot must produce its expected artifact before advance fires.
45
+
46
+ ## Entry points
47
+
48
+ - **Direct open (typical).**
49
+ `bclaw_loop(intent='open', kind='implementation', slots=[…], linked={plan_ids:[…], sequence_ids:[…]}, allow_orphan=true)`
50
+ followed by `bind`. `allow_orphan=true` acknowledges that the caller will
51
+ drive worker turns.
52
+ - **Via bind.** `bclaw_loop(intent='bind', loop_id=…)` validates the linked
53
+ sequence and advances `bind → execute`. Historical launch options
54
+ (`lanes`, `auto_execute`, `model`, `max_assignments`) remain accepted
55
+ during rollout but are ignored; the response carries a migration warning.
56
+ - **Explicit worker turn.** In `execute`, trusted
57
+ `bclaw_loop(intent='turn', loop_id=…, slot_id=…, dispatch=true)` is the only
58
+ worker launch path and uses the common AttemptAuthority fence. Independent
59
+ slots may be dispatched concurrently. Without `dispatch=true`, `turn` is
60
+ state-only and never starts a process.
61
+
62
+ ## Advance gates
63
+
64
+ `verify` carries an `advance_gate`:
65
+
66
+ ```ts
67
+ { kind: 'min_artifacts_by_type', type: 'verify_report', n: 1, scope: 'phase' }
68
+ ```
69
+
70
+ Advance cannot leave `verify` without a `verify_report` artifact **this
71
+ iteration** — this guards the narrated-verify anti-pattern where a slot
72
+ claims it verified without actually running the command. `command_green` in
73
+ the iteration engine reads the reports produced against this gate.
74
+
75
+ For bound lanes, call `bclaw_loop(intent='verify', slot_id=…)`. The command
76
+ runs in that slot assignment's worktree. Omitting `slot_id` when several lane
77
+ worktrees exist fails closed, and `command_green` requires a current-iteration
78
+ green report from every bound lane.
79
+
80
+ ## Stop condition
81
+
82
+ ```ts
83
+ { kind: 'any', conditions: [
84
+ { kind: 'artifact_produced', phase: 'handoff_ready', type: 'handoff' },
85
+ { kind: 'max_iterations', n: 3 },
86
+ ] }
87
+ ```
88
+
89
+ - **Handoff produced** → close `completed`. The handoff is the downstream
90
+ consumer's entry point.
91
+ - **Cycle cap** → close `blocked`; the last red `verify_report` is
92
+ attached so a human or a `debug` loop can pick up.
93
+
94
+ ## Artifacts
95
+
96
+ | Type | Phase | Body |
97
+ |---|---|---|
98
+ | `execute_report` | `execute` | inline text ≤ 4 KB, or ref-based when large |
99
+ | `verify_report` | `verify` | inline JSON: `{ command, exit_code, passed, duration_ms?, stdout_tail?, stderr_tail? }` |
100
+ | `file_diff` | any phase | ref-based body (`{ref, byte_count, sha256}`) |
101
+ | `handoff` | `handoff_ready` | `ref` to a `handoff` primitive |
102
+
103
+ ## Routing
104
+
105
+ `implementation` is claim-routed: each worker `slot.claim_id` points at the
106
+ scope claim created by `turn(dispatch=true)`, and the common driver runs in
107
+ the worktree bound to that claim. `bind` creates neither claim nor assignment.
108
+ `session_id` is observability-only.
109
+ Dispatch also uses the bound `scope_hint` to retrieve only path-related
110
+ decisions, constraints, traps and runtime context (while retaining unscoped
111
+ project-wide memory).
112
+ [Attempt authority](../concepts/attempt-authority.md#ordered-dispatch)
113
+ mints a deterministic `turn_id` from `(loop_id, slot_id, iteration)` on
114
+ every dispatch, so a concurrent re-dispatch hits `reservation_exists` and
115
+ adopts the existing attempt. If a reusable slot has already spent that legacy
116
+ identity in another worker phase of the same iteration, the common resolver
117
+ uses `(loop_id, slot_id, phase, iteration)` for a versioned successor logical
118
+ turn. This is a Loop Engine rule shared by every kind, not implementation-loop
119
+ special handling.
120
+
121
+ At `handoff_ready`, the facade emits a structured `next_actions` call for
122
+ `bclaw_coordinate(intent='review', open_loop=true)`. It remains explicit: the
123
+ engine does not invent a reviewer or silently mutate external state. The
124
+ created review loop persists `linked.source_loop_id`, while the implementation
125
+ loop received the same provenance from its ideation source, so `list/get`
126
+ surfaces the pipeline chain without a separate registry.
127
+
128
+ ## Recovery
129
+
130
+ - **Execute worker crashed mid-iteration.** Launch grant lease expires;
131
+ `sweepExpiredLaunchGrants` revokes it; a re-dispatch arms a new
132
+ generation at a strictly greater epoch. Because `execute_report` and
133
+ `verify_report` are per-iteration, a prior-iteration report never
134
+ satisfies the current iteration's gate.
135
+ - **`verify_report` red at cap.** Loop closes `blocked`; the last red
136
+ `verify_report` and the accumulated `execute_report`s stay on the loop
137
+ as evidence.
138
+ - **Command-green mid-cycle.** `exit_when: 'command_green'` short-circuits
139
+ the cycle; the driver advances to `handoff_ready` on the next `advance`.
140
+ - **Stale worker LANE-RESULT resurfaces after a cycle bump.**
141
+ `evidenceMatchesAttempt` rejects it — the current-generation nonce no
142
+ longer matches the stale token.
143
+
144
+ ## When NOT to use
145
+
146
+ - **Debugging an already-broken build.** Use [`debug`](./debug.md) — its
147
+ `reproduce` phase gives you a repro artifact the fix rides on, and its
148
+ `command_green` gate is the same shape.
149
+ - **Validating a change that already exists.** Use
150
+ [`review`](./review.md).
151
+ - **Choosing between architectural options.** Use
152
+ [`ideation`](./ideation.md) — an implementation loop with no plan is
153
+ empty.
154
+ - **Open-ended discovery.** Use [`research`](./research.md).
155
+
156
+ ## Reference implementation
157
+
158
+ | Component | File |
159
+ |---|---|
160
+ | Default protocol | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) (`DEFAULT_PROTOCOLS.implementation`) |
161
+ | Bind action | [`src/core/loops/impl-bind.ts`](../../src/core/loops/impl-bind.ts) (`runImplBind`) |
162
+ | Common worker driver | [`src/core/loop-turn-dispatch.ts`](../../src/core/loop-turn-dispatch.ts) (`dispatchLoopTurn`) |
163
+ | Iteration FSM (command_green) | [`src/core/loops/iteration-engine.ts`](../../src/core/loops/iteration-engine.ts) |
164
+ | Attempt authority | [`src/core/loops/attempt-authority.ts`](../../src/core/loops/attempt-authority.ts) |
165
+ | Turn execution policy | [`src/core/loops/kind-policies.ts`](../../src/core/loops/kind-policies.ts), [`src/core/loops/turn-execution.ts`](../../src/core/loops/turn-execution.ts) |
166
+ | Result reducer | [`src/core/loops/result-reducers.ts`](../../src/core/loops/result-reducers.ts) |
167
+ | Tests | [`tests/unit/loops-impl-bind.test.ts`](../../tests/unit/loops-impl-bind.test.ts), [`tests/unit/loops-impl-protocol.test.ts`](../../tests/unit/loops-impl-protocol.test.ts), [`tests/unit/loops-gate-content-integrity.test.ts`](../../tests/unit/loops-gate-content-integrity.test.ts) |
168
+
169
+ ## Related
170
+
171
+ - [Loop Engine](../concepts/loop-engine.md)
172
+ - [Attempt authority](../concepts/attempt-authority.md)
173
+ - [plans-and-claims.md](../concepts/plans-and-claims.md)
174
+ - [dispatch-lifecycle.md](../concepts/dispatch-lifecycle.md)