brainclaw 1.8.0 → 1.9.1
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 +592 -505
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +138 -13
- package/dist/commands/add-step.js +1 -1
- package/dist/commands/bootstrap.js +2 -26
- package/dist/commands/check-security-mcp.js +50 -33
- package/dist/commands/check-security.js +86 -43
- package/dist/commands/claim.js +22 -21
- package/dist/commands/confirm.js +26 -0
- package/dist/commands/context-diff.js +1 -1
- package/dist/commands/dispatch-watch.js +142 -0
- package/dist/commands/doctor.js +113 -2
- package/dist/commands/estimation-report.js +115 -16
- package/dist/commands/harvest.js +286 -23
- package/dist/commands/hooks.js +73 -73
- package/dist/commands/init.js +124 -22
- package/dist/commands/install-hooks.js +78 -78
- package/dist/commands/loops-handlers.js +4 -0
- package/dist/commands/mcp-read-handlers.js +253 -41
- package/dist/commands/mcp.js +664 -102
- package/dist/commands/memory.js +21 -17
- package/dist/commands/migrate.js +81 -17
- package/dist/commands/prune.js +78 -4
- package/dist/commands/reflect.js +26 -20
- package/dist/commands/register-agent.js +57 -1
- package/dist/commands/repair.js +20 -0
- package/dist/commands/session-end.js +15 -6
- package/dist/commands/session-start.js +18 -1
- package/dist/commands/setup-security.js +39 -18
- package/dist/commands/setup.js +26 -27
- package/dist/commands/stale.js +16 -2
- package/dist/commands/switch.js +26 -5
- package/dist/commands/uninstall.js +126 -34
- package/dist/commands/update-step.js +6 -0
- package/dist/commands/version.js +1 -1
- package/dist/commands/worktree.js +60 -0
- package/dist/core/actions.js +12 -3
- package/dist/core/agent-capability.js +30 -17
- package/dist/core/agent-files.js +963 -666
- package/dist/core/agent-integrations.js +0 -3
- package/dist/core/agent-inventory.js +67 -0
- package/dist/core/agent-registry.js +163 -29
- package/dist/core/agentrun-reconciler.js +33 -2
- package/dist/core/agentruns.js +7 -1
- package/dist/core/ai-agent-detection.js +31 -44
- package/dist/core/archival.js +15 -9
- package/dist/core/assignment-reconciler.js +56 -0
- package/dist/core/assignment-sweeper.js +127 -4
- package/dist/core/assignments.js +69 -11
- package/dist/core/bootstrap.js +233 -67
- package/dist/core/brainclaw-version.js +22 -0
- package/dist/core/candidates.js +21 -1
- package/dist/core/claims.js +313 -150
- package/dist/core/codev-prompts.js +38 -38
- package/dist/core/config.js +6 -1
- package/dist/core/context-diff.js +148 -20
- package/dist/core/context.js +129 -8
- package/dist/core/coordination.js +22 -3
- package/dist/core/default-profiles/doctor.yaml +11 -11
- package/dist/core/default-profiles/janitor.yaml +11 -11
- package/dist/core/default-profiles/onboarder.yaml +11 -11
- package/dist/core/default-profiles/reviewer.yaml +13 -13
- package/dist/core/dispatch-status.js +79 -5
- package/dist/core/dispatcher.js +65 -12
- package/dist/core/entity-operations.js +74 -27
- package/dist/core/entity-registry.js +31 -5
- package/dist/core/event-log.js +138 -21
- package/dist/core/events/checkpoint.js +258 -0
- package/dist/core/events/genesis.js +220 -0
- package/dist/core/events/journal.js +507 -0
- package/dist/core/events/materialize.js +126 -0
- package/dist/core/events/registry-post-image.js +110 -0
- package/dist/core/events/verify.js +109 -0
- package/dist/core/execution-adapters.js +23 -0
- package/dist/core/execution.js +1 -1
- package/dist/core/facade-schema.js +38 -0
- package/dist/core/gc-semantic.js +130 -5
- package/dist/core/handoff-snapshot.js +68 -0
- package/dist/core/ids.js +19 -8
- package/dist/core/instruction-templates.js +34 -115
- package/dist/core/io.js +39 -3
- package/dist/core/json-store.js +10 -1
- package/dist/core/lock.js +153 -28
- package/dist/core/loops/bootstrap-acquire.js +25 -1
- package/dist/core/loops/facade-schema.js +2 -0
- package/dist/core/loops/hooks/survey-signals-baseline.js +36 -0
- package/dist/core/loops/index.js +1 -0
- package/dist/core/loops/presets/bootstrap.js +7 -0
- package/dist/core/loops/store.js +17 -0
- package/dist/core/loops/verbs.js +24 -2
- package/dist/core/markdown.js +8 -76
- package/dist/core/mcp-command-resolution.js +245 -0
- package/dist/core/memory-compactor.js +5 -3
- package/dist/core/memory-lifecycle.js +282 -0
- package/dist/core/merge-risk.js +150 -0
- package/dist/core/messaging.js +10 -3
- package/dist/core/migration.js +11 -1
- package/dist/core/observer-mode.js +26 -0
- package/dist/core/operations/memory-mutation.js +90 -65
- package/dist/core/operations/plan.js +27 -1
- package/dist/core/protocol-skills.js +210 -0
- package/dist/core/reflection-safety.js +6 -7
- package/dist/core/reputation.js +84 -2
- package/dist/core/runtime-signals.js +72 -10
- package/dist/core/runtime.js +84 -1
- package/dist/core/schema.js +114 -0
- package/dist/core/search.js +19 -2
- package/dist/core/security-detectors.js +125 -0
- package/dist/core/security-extract.js +189 -0
- package/dist/core/security-guard.js +217 -139
- package/dist/core/security-packages.js +121 -0
- package/dist/core/security-scoring.js +76 -9
- package/dist/core/security.js +34 -2
- package/dist/core/sequence.js +11 -2
- package/dist/core/setup-flow.js +141 -13
- package/dist/core/spawn-check.js +16 -2
- package/dist/core/staleness.js +73 -2
- package/dist/core/state.js +250 -54
- package/dist/core/store-resolution.js +45 -12
- package/dist/core/worktree.js +90 -26
- package/dist/facts.js +8 -8
- package/dist/facts.json +7 -7
- package/docs/PROTOCOL.md +223 -0
- package/docs/adapters/openclaw.md +43 -43
- package/docs/architecture/project-refs.md +328 -328
- package/docs/cli.md +2097 -2096
- package/docs/concepts/coordination.md +52 -52
- package/docs/concepts/coordinator-runbook.md +129 -0
- package/docs/concepts/dispatch-lifecycle.md +245 -245
- package/docs/concepts/event-log-store.md +928 -0
- package/docs/concepts/ideation-loop.md +317 -317
- package/docs/concepts/loop-engine.md +520 -511
- package/docs/concepts/mcp-governance.md +268 -268
- package/docs/concepts/memory.md +89 -88
- package/docs/concepts/multi-agent-workflows.md +167 -167
- package/docs/concepts/observer-protocol.md +361 -0
- package/docs/concepts/parallel-merge-protocol.md +71 -0
- package/docs/concepts/plans-and-claims.md +217 -174
- package/docs/concepts/project-md-convention.md +35 -35
- package/docs/concepts/runtime-notes.md +38 -38
- package/docs/concepts/skills.md +78 -0
- package/docs/concepts/troubleshooting.md +254 -254
- package/docs/concepts/workspace-bootstrapping.md +142 -81
- package/docs/context-format-changelog.md +35 -35
- package/docs/context-format.md +48 -48
- package/docs/index.md +65 -65
- package/docs/integrations/agents.md +162 -162
- package/docs/integrations/claude-code.md +23 -23
- package/docs/integrations/cline.md +87 -88
- package/docs/integrations/codex.md +2 -2
- package/docs/integrations/continue.md +60 -60
- package/docs/integrations/copilot.md +82 -80
- package/docs/integrations/cursor.md +23 -23
- package/docs/integrations/kilocode.md +72 -72
- package/docs/integrations/mcp.md +377 -377
- package/docs/integrations/mistral-vibe.md +122 -122
- package/docs/integrations/openclaw.md +99 -98
- package/docs/integrations/opencode.md +84 -84
- package/docs/integrations/overview.md +122 -122
- package/docs/integrations/roo.md +74 -74
- package/docs/integrations/windsurf.md +83 -83
- package/docs/mcp-schema-changelog.md +360 -329
- package/docs/playbooks/integration/index.md +121 -121
- package/docs/playbooks/orchestration.md +37 -0
- package/docs/playbooks/productivity/index.md +99 -99
- package/docs/playbooks/team/index.md +117 -117
- package/docs/product/agent-first-model.md +184 -184
- package/docs/product/entity-model-audit.md +462 -462
- package/docs/product/positioning.md +86 -86
- package/docs/quickstart-existing-project.md +107 -107
- package/docs/quickstart.md +148 -147
- package/docs/release-maintenance.md +79 -79
- package/docs/reputation.md +52 -52
- package/docs/review.md +45 -45
- package/docs/security.md +212 -53
- package/docs/server-operations.md +118 -118
- package/docs/storage.md +110 -108
- package/package.json +86 -69
|
@@ -1,317 +1,317 @@
|
|
|
1
|
-
# Ideation_loop
|
|
2
|
-
|
|
3
|
-
> Status: MVP shipped in **v1.5.0** (pln#492). Reframer phase (v1.1) tracked as pln#493.
|
|
4
|
-
|
|
5
|
-
The ideation_loop is brainclaw's structured-deliberation primitive. Where
|
|
6
|
-
the [review_loop](./loop-engine.md#automation-extending-bclaw_coordinateintentreview)
|
|
7
|
-
exists to validate work that already happened, the ideation_loop exists
|
|
8
|
-
to **stress-test work before it happens** — proposals get adversarial
|
|
9
|
-
pressure from project memory before they crystallise into plans.
|
|
10
|
-
|
|
11
|
-
A useful mental model: it's the [`review_loop`](./loop-engine.md#default-protocols)'s
|
|
12
|
-
inverse. Review takes a finished artifact and asks "is this good?" Ideation
|
|
13
|
-
takes a fresh proposal and asks "what does our accumulated experience say
|
|
14
|
-
will go wrong with this?"
|
|
15
|
-
|
|
16
|
-
## Why
|
|
17
|
-
|
|
18
|
-
In agentic workflows, two failure modes recur:
|
|
19
|
-
|
|
20
|
-
1. **AI slop.** A proposal that sounds plausible but ignores hard-won
|
|
21
|
-
constraints, contradicts past decisions, or repeats a known trap.
|
|
22
|
-
2. **Echo chamber.** A single agent generating *and* evaluating its own
|
|
23
|
-
proposal — useful pressure is structurally absent because no
|
|
24
|
-
adversarial perspective is in scope.
|
|
25
|
-
|
|
26
|
-
Multi-agent diversity (champion vs critic with different model providers)
|
|
27
|
-
fixes #2 but most adopters only have one model on hand. The ideation_loop
|
|
28
|
-
sidesteps that by making the **adversarial substrate the project's
|
|
29
|
-
memory itself**: traps, feedback memos, runtime notes — accumulated
|
|
30
|
-
evidence of "what's gone wrong here before" — get pulled into the
|
|
31
|
-
critic's working set automatically. A single agent can produce useful
|
|
32
|
-
adversarial pressure if the context filter forces it to confront
|
|
33
|
-
adversarial memory rather than positive context.
|
|
34
|
-
|
|
35
|
-
This was validated empirically before any code was written (see
|
|
36
|
-
`feedback_ideation_loop_single_agent_method` in user auto-memory): a
|
|
37
|
-
3-round simulated ideation produced 12 substantive critique artifacts
|
|
38
|
-
all citing real memory ids, against a single-model setup.
|
|
39
|
-
|
|
40
|
-
## Phases
|
|
41
|
-
|
|
42
|
-
The default protocol has four phases:
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
proposal → critique ↔ revision → synthesis
|
|
46
|
-
└─── iterate (≤3) ────┘
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
| Phase | Purpose | What the slot produces |
|
|
50
|
-
|---|---|---|
|
|
51
|
-
| `proposal` | Seed: the original idea / decision under consideration | A `proposal` artifact (the task text from the caller) |
|
|
52
|
-
| `critique` | Adversarial review against project memory | One or more `critique` artifacts citing real memory ids |
|
|
53
|
-
| `revision` | Champion's response to the critique batch | A `revision` artifact addressing the points raised |
|
|
54
|
-
| `synthesis` | Final plan_draft folding the cycle's outputs | A `plan_draft` artifact with `addresses_critique:[ids]` |
|
|
55
|
-
|
|
56
|
-
`critique ↔ revision` is the iteration block: the loop loops there,
|
|
57
|
-
incrementing `iteration_count`, until exit criteria are met.
|
|
58
|
-
|
|
59
|
-
## Per-phase context filter
|
|
60
|
-
|
|
61
|
-
Each phase pulls a **filtered slice** of memory rather than the full
|
|
62
|
-
project context. This is what makes single-agent ideation produce real
|
|
63
|
-
adversarial pressure.
|
|
64
|
-
|
|
65
|
-
| Phase | `context_filter` (memory categories visible) | Why |
|
|
66
|
-
|---|---|---|
|
|
67
|
-
| `proposal` | `decisions`, `constraints`, `plans`, `project_vision` | Positive context — what we want to build, what's already settled |
|
|
68
|
-
| `critique` | `traps`, `feedback`, `runtime_notes`, `critique_history` | Adversarial-only — known failure modes, prior critiques |
|
|
69
|
-
| `revision` | `*` (everything) | Champion needs full picture to address findings |
|
|
70
|
-
| `synthesis` | `*` (everything) | Final plan_draft must reflect all signal |
|
|
71
|
-
|
|
72
|
-
The closed-enum vocabulary lives in [`LOOP_CONTEXT_CATEGORIES`](../../src/core/loops/types.ts).
|
|
73
|
-
The wildcard `*` expands to every user-facing category. Loop-internal
|
|
74
|
-
categories (`critique_history` / `revision_history` / `synthesis_artifact`)
|
|
75
|
-
refer to artifacts produced earlier in the same loop and are pulled
|
|
76
|
-
from the thread directly, not from project memory.
|
|
77
|
-
|
|
78
|
-
If a phase declares no `context_filter`, the driver falls back to the
|
|
79
|
-
wildcard set — same behaviour as a non-ideation loop.
|
|
80
|
-
|
|
81
|
-
## Iteration block
|
|
82
|
-
|
|
83
|
-
The `LoopProtocolConfig.iteration` block describes the inner cycle:
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
iteration: {
|
|
87
|
-
cycle: ['critique', 'revision'],
|
|
88
|
-
max_iterations: 3,
|
|
89
|
-
exit_when: 'no_new_critique_artifacts',
|
|
90
|
-
}
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
- `cycle` lists the phase names that repeat in order.
|
|
94
|
-
- `max_iterations` caps the number of rounds. The default is 3 — past
|
|
95
|
-
empirical work (`runtime_note 'ideation_loop_mvp_simulation_transcript'`)
|
|
96
|
-
found 3 rounds is the saturation point at which a memory-driven
|
|
97
|
-
critique stops surfacing new conflicts on a typical proposal.
|
|
98
|
-
- `exit_when` chooses the convergence criterion:
|
|
99
|
-
- `'no_new_critique_artifacts'` — a full cycle completes without
|
|
100
|
-
adding any critique-typed artifact. Stable saturation.
|
|
101
|
-
- `'critic_signal'` — the critic produced a `critic_signal` artifact
|
|
102
|
-
declaring the proposal sufficient. Explicit early exit.
|
|
103
|
-
|
|
104
|
-
The [iteration engine FSM](../../src/core/loops/iteration-engine.ts)
|
|
105
|
-
(`decideNextPhase`) returns one of five outcomes at each transition:
|
|
106
|
-
linear `advance_to`, intra-cycle `iterate_to`, `exit_cycle` when
|
|
107
|
-
`exit_when` fires, `max_iterations` when the cap hits, or throws when
|
|
108
|
-
the current phase is the last with no successor.
|
|
109
|
-
|
|
110
|
-
## Phase-advance gate
|
|
111
|
-
|
|
112
|
-
The critique phase carries a default `advance_gate`:
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
advance_gate: {
|
|
116
|
-
kind: 'min_artifacts_by_type',
|
|
117
|
-
type: 'critique',
|
|
118
|
-
n: 3,
|
|
119
|
-
scope: 'phase',
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
The driver refuses to leave critique until at least 3 critique artifacts
|
|
124
|
-
have been produced in the current iteration. Below that floor the
|
|
125
|
-
adversarial pressure hasn't accumulated enough to make revision useful.
|
|
126
|
-
|
|
127
|
-
Gate evaluation is **iteration-window-aware**: counts only the artifacts
|
|
128
|
-
produced in the current iteration window, so a previous round's
|
|
129
|
-
critiques don't satisfy the gate for the new round.
|
|
130
|
-
|
|
131
|
-
When the gate fails, the driver:
|
|
132
|
-
- Emits a `phase_advance_blocked` system event with a structured
|
|
133
|
-
`gate_reason` (e.g. `min_artifacts_by_type unmet: phase-scope count of
|
|
134
|
-
type "critique" = 1 < n=3`).
|
|
135
|
-
- Throws an actionable error so the caller knows what's missing.
|
|
136
|
-
|
|
137
|
-
System events live in the same event journal as `turn_assigned` /
|
|
138
|
-
`phase_advanced`; they are NOT first-class artifacts (which would force
|
|
139
|
-
every consumer to filter `is_system` before processing content).
|
|
140
|
-
|
|
141
|
-
## Brief assembly
|
|
142
|
-
|
|
143
|
-
When a turn fires, the driver assembles a brief for the slot agent via
|
|
144
|
-
[`buildIdeationBrief`](../../src/core/loops/brief-assembly.ts). The
|
|
145
|
-
brief is the message the slot reads from its inbox.
|
|
146
|
-
|
|
147
|
-
```
|
|
148
|
-
# ideation_loop brief
|
|
149
|
-
loop: lop_…
|
|
150
|
-
phase: critique
|
|
151
|
-
iteration: 0
|
|
152
|
-
slot: critic
|
|
153
|
-
title: …
|
|
154
|
-
goal: …
|
|
155
|
-
|
|
156
|
-
## proposal
|
|
157
|
-
<proposal seed text>
|
|
158
|
-
|
|
159
|
-
## memory bundle (BM25-ranked, filtered by phase context)
|
|
160
|
-
### traps
|
|
161
|
-
- [trp_…] <trap text>
|
|
162
|
-
### feedback
|
|
163
|
-
- [fb_…] <feedback text>
|
|
164
|
-
### runtime_notes
|
|
165
|
-
…
|
|
166
|
-
|
|
167
|
-
## prior loop artifacts ← only when iteration > 0
|
|
168
|
-
### critique_history (prior iterations)
|
|
169
|
-
- [art_…] (iter 0) <truncated body>
|
|
170
|
-
|
|
171
|
-
## what to produce
|
|
172
|
-
- Phase "critique" expects you to act in role "critic".
|
|
173
|
-
- Emit findings as LoopArtifacts via bclaw_loop intent='complete_turn'…
|
|
174
|
-
- Cite the memory ids you relied on so the synthesis can audit coverage.
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
The bundle is **size-capped** at 48 000 chars (~12 000 tokens at
|
|
178
|
-
~4 chars/token English). The cap is greedy: if the assembled bundle
|
|
179
|
-
overflows, the assembler appends a "memory bundle truncated…" tail and
|
|
180
|
-
reports `truncated`, `includedItems`, and `droppedItems` to the caller
|
|
181
|
-
so a per-slot warning can surface. The cap exists to mitigate
|
|
182
|
-
[trp#179](../../src/core/loops/brief-assembly.ts) — when memory
|
|
183
|
-
bundles get too large, agents fall back to CLI tools instead of
|
|
184
|
-
honouring MCP semantics.
|
|
185
|
-
|
|
186
|
-
Memory categories are fetched via an injectable `BriefMemoryProvider`.
|
|
187
|
-
The production implementation (in [`src/commands/mcp.ts`](../../src/commands/mcp.ts)
|
|
188
|
-
under the `intent='ideate'` handler) maps categories onto
|
|
189
|
-
[`src/core/search.ts`](../../src/core/search.ts) sections and uses
|
|
190
|
-
its BM25 ranking with the proposal text as the query. Top-K defaults
|
|
191
|
-
to 8 per category. Categories without a search-section mapping
|
|
192
|
-
(`runtime_notes`, `feedback`, `project_vision` in v1) silently return
|
|
193
|
-
empty — they will plug in when the corresponding stores get a search
|
|
194
|
-
index.
|
|
195
|
-
|
|
196
|
-
## Driver: `bclaw_coordinate(intent='ideate')`
|
|
197
|
-
|
|
198
|
-
The driver entry point is the existing coordinate facade with a new
|
|
199
|
-
intent. It opens an ideation_loop, registers slots, stores the task
|
|
200
|
-
as the proposal seed, and (in multi-agent mode) advances to critique
|
|
201
|
-
and dispatches the first turn.
|
|
202
|
-
|
|
203
|
-
### Single-agent mode (default)
|
|
204
|
-
|
|
205
|
-
```
|
|
206
|
-
bclaw_coordinate(intent='ideate', task='Should we extract the dispatcher into a separate package?')
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
- Opens a loop with one `champion` slot = caller.
|
|
210
|
-
- Stores `task` as a `proposal` artifact (sliced to fit the 4 KB
|
|
211
|
-
artifact body cap).
|
|
212
|
-
- Stops at the proposal phase. The champion drives the loop manually
|
|
213
|
-
via `bclaw_loop(intent='turn'|'advance')`.
|
|
214
|
-
- Returns `{loop_id, proposal_artifact_id, mode: 'single_agent',
|
|
215
|
-
dispatched_critics: 0, current_phase: 'proposal'}`.
|
|
216
|
-
- Surfaces a single-agent warning so the caller knows dispatch is
|
|
217
|
-
manual.
|
|
218
|
-
|
|
219
|
-
This is the right mode when you want the loop's structure (memory
|
|
220
|
-
filter, gate, iteration accounting) but want to drive each turn
|
|
221
|
-
yourself — useful for one-shot consultations or when you don't have
|
|
222
|
-
a separate critic agent on hand.
|
|
223
|
-
|
|
224
|
-
### Multi-agent mode
|
|
225
|
-
|
|
226
|
-
```
|
|
227
|
-
bclaw_coordinate(intent='ideate',
|
|
228
|
-
task='Should we adopt approach A or approach B?',
|
|
229
|
-
targetAgents=['codex'])
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
- Opens a loop with `champion` slot (caller) + one `critic` slot per
|
|
233
|
-
target agent.
|
|
234
|
-
- Stores `task` as a `proposal` artifact.
|
|
235
|
-
- Advances proposal → critique.
|
|
236
|
-
- For each critic slot: assembles the brief via `buildIdeationBrief`
|
|
237
|
-
honouring the critique phase's context_filter, calls
|
|
238
|
-
`bclaw_loop(intent='turn')` to flip the slot to `assigned`, and
|
|
239
|
-
queues a coordinate message with the brief as body and
|
|
240
|
-
`{intent: 'ideate', loop_id, slot_id, phase, iteration,
|
|
241
|
-
proposal_artifact_id}` payload.
|
|
242
|
-
- Returns `{loop_id, …, mode: 'multi_agent',
|
|
243
|
-
dispatched_critics: N, current_phase: 'critique'}`.
|
|
244
|
-
|
|
245
|
-
When the critique phase brief is truncated for any slot, a per-slot
|
|
246
|
-
warning surfaces. When dispatch fails (e.g. an agent is unknown), the
|
|
247
|
-
overall response degrades to `partial` and the loop stays at the
|
|
248
|
-
proposal phase — callers can retry manually.
|
|
249
|
-
|
|
250
|
-
### Custom stop_condition
|
|
251
|
-
|
|
252
|
-
You can override the default `artifact_produced { phase: synthesis,
|
|
253
|
-
type: plan_draft }` stop_condition with anything from the
|
|
254
|
-
[`StopCondition`](../../src/core/loops/types.ts) vocabulary:
|
|
255
|
-
|
|
256
|
-
```ts
|
|
257
|
-
bclaw_loop(intent='open', kind='ideation', stop_condition: {
|
|
258
|
-
kind: 'min_artifacts_by_type',
|
|
259
|
-
type: 'critique',
|
|
260
|
-
n: 5,
|
|
261
|
-
scope: 'loop', // counts across phases / iterations
|
|
262
|
-
})
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
This stops the loop after 5 critique artifacts have accumulated
|
|
266
|
-
loop-wide, regardless of phase or iteration. Useful for "harvest as
|
|
267
|
-
many criticisms as possible, then stop" patterns.
|
|
268
|
-
|
|
269
|
-
## Synthesis schema
|
|
270
|
-
|
|
271
|
-
The synthesis phase's `plan_draft` artifact MUST carry an
|
|
272
|
-
`addresses_critique: string[]` field listing the critique artifact ids
|
|
273
|
-
it folded in (or explicitly waived). Field-presence is enforced at
|
|
274
|
-
the zod level on `LoopArtifactSchema`. v1 enforces the field; v1.1
|
|
275
|
-
will add semantic validation (each id maps to a real critique
|
|
276
|
-
artifact). This makes synthesis auditable: a reviewer can check
|
|
277
|
-
which critiques were honoured vs ignored.
|
|
278
|
-
|
|
279
|
-
## When NOT to use
|
|
280
|
-
|
|
281
|
-
- **Quick clarifications.** A 2-turn back-and-forth in a normal
|
|
282
|
-
message thread is cheaper than spinning up a loop.
|
|
283
|
-
- **Operationally urgent decisions.** The iteration block adds
|
|
284
|
-
latency. For "the build is broken, what's the fix?" the right tool
|
|
285
|
-
is `bclaw_coordinate(intent='consult')`.
|
|
286
|
-
- **Architectural debates with no project memory.** If you've never
|
|
287
|
-
recorded any traps / feedback / runtime_notes for this domain, the
|
|
288
|
-
critic will fetch nothing and the brief will be a no-op. Seed the
|
|
289
|
-
memory first, or use a literal multi-agent loop where the critic
|
|
290
|
-
brings its own perspective.
|
|
291
|
-
|
|
292
|
-
## Future direction
|
|
293
|
-
|
|
294
|
-
- **Reframer phase** ([pln#493](https://github.com/jberdah/brainclaw/blob/master/.brainclaw/coordination/plans/pln_36c9a4d1.json)).
|
|
295
|
-
A fresh-eyes phase between iteration exit and synthesis. Sees only
|
|
296
|
-
`project_vision`, `constraints`, and the synthesis_artifact — no
|
|
297
|
-
critique/revision history. Surfaces simplifications, alternative
|
|
298
|
-
framings, and "wrong question" findings that memory-driven critique
|
|
299
|
-
is structurally unable to produce. Validated empirically; ships on
|
|
300
|
-
its own cadence after MVP usage telemetry.
|
|
301
|
-
- **Profile-based slot diversity.** Champion / simplifier / pessimist
|
|
302
|
-
as separate slot types with their own context filters. Deferred
|
|
303
|
-
until the single-slot model is validated in production.
|
|
304
|
-
- **Cross-loop memory.** Promoting validated plan_drafts back into
|
|
305
|
-
the project memory store with provenance. Today the synthesis
|
|
306
|
-
artifact lives only in the loop event journal.
|
|
307
|
-
|
|
308
|
-
## Reference implementation
|
|
309
|
-
|
|
310
|
-
| Component | File |
|
|
311
|
-
|---|---|
|
|
312
|
-
| Schema (categories, iteration, gate, system events) | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) |
|
|
313
|
-
| FSM (decideNextPhase, exit predicates) | [`src/core/loops/iteration-engine.ts`](../../src/core/loops/iteration-engine.ts) |
|
|
314
|
-
| Gate evaluator (`evaluatePhaseAdvanceGate`) | [`src/core/loops/verbs.ts`](../../src/core/loops/verbs.ts) |
|
|
315
|
-
| Brief assembler (`buildIdeationBrief`) | [`src/core/loops/brief-assembly.ts`](../../src/core/loops/brief-assembly.ts) |
|
|
316
|
-
| Driver (`bclaw_coordinate intent='ideate'`) | [`src/commands/mcp.ts`](../../src/commands/mcp.ts) (search `req.intent === 'ideate'`) |
|
|
317
|
-
| Tests (schema, FSM, assembler, dispatch, e2e) | [`tests/unit/loops-types.test.ts`](../../tests/unit/loops-types.test.ts), [`loops-iteration-engine.test.ts`](../../tests/unit/loops-iteration-engine.test.ts), [`loops-phase-advance-gate.test.ts`](../../tests/unit/loops-phase-advance-gate.test.ts), [`loops-advance-iteration.test.ts`](../../tests/unit/loops-advance-iteration.test.ts), [`loops-brief-assembly.test.ts`](../../tests/unit/loops-brief-assembly.test.ts), [`bclaw-coordinate.test.ts`](../../tests/unit/bclaw-coordinate.test.ts), [`ideation-loop-e2e.test.ts`](../../tests/unit/ideation-loop-e2e.test.ts) |
|
|
1
|
+
# Ideation_loop
|
|
2
|
+
|
|
3
|
+
> Status: MVP shipped in **v1.5.0** (pln#492). Reframer phase (v1.1) tracked as pln#493.
|
|
4
|
+
|
|
5
|
+
The ideation_loop is brainclaw's structured-deliberation primitive. Where
|
|
6
|
+
the [review_loop](./loop-engine.md#automation-extending-bclaw_coordinateintentreview)
|
|
7
|
+
exists to validate work that already happened, the ideation_loop exists
|
|
8
|
+
to **stress-test work before it happens** — proposals get adversarial
|
|
9
|
+
pressure from project memory before they crystallise into plans.
|
|
10
|
+
|
|
11
|
+
A useful mental model: it's the [`review_loop`](./loop-engine.md#default-protocols)'s
|
|
12
|
+
inverse. Review takes a finished artifact and asks "is this good?" Ideation
|
|
13
|
+
takes a fresh proposal and asks "what does our accumulated experience say
|
|
14
|
+
will go wrong with this?"
|
|
15
|
+
|
|
16
|
+
## Why
|
|
17
|
+
|
|
18
|
+
In agentic workflows, two failure modes recur:
|
|
19
|
+
|
|
20
|
+
1. **AI slop.** A proposal that sounds plausible but ignores hard-won
|
|
21
|
+
constraints, contradicts past decisions, or repeats a known trap.
|
|
22
|
+
2. **Echo chamber.** A single agent generating *and* evaluating its own
|
|
23
|
+
proposal — useful pressure is structurally absent because no
|
|
24
|
+
adversarial perspective is in scope.
|
|
25
|
+
|
|
26
|
+
Multi-agent diversity (champion vs critic with different model providers)
|
|
27
|
+
fixes #2 but most adopters only have one model on hand. The ideation_loop
|
|
28
|
+
sidesteps that by making the **adversarial substrate the project's
|
|
29
|
+
memory itself**: traps, feedback memos, runtime notes — accumulated
|
|
30
|
+
evidence of "what's gone wrong here before" — get pulled into the
|
|
31
|
+
critic's working set automatically. A single agent can produce useful
|
|
32
|
+
adversarial pressure if the context filter forces it to confront
|
|
33
|
+
adversarial memory rather than positive context.
|
|
34
|
+
|
|
35
|
+
This was validated empirically before any code was written (see
|
|
36
|
+
`feedback_ideation_loop_single_agent_method` in user auto-memory): a
|
|
37
|
+
3-round simulated ideation produced 12 substantive critique artifacts
|
|
38
|
+
all citing real memory ids, against a single-model setup.
|
|
39
|
+
|
|
40
|
+
## Phases
|
|
41
|
+
|
|
42
|
+
The default protocol has four phases:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
proposal → critique ↔ revision → synthesis
|
|
46
|
+
└─── iterate (≤3) ────┘
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
| Phase | Purpose | What the slot produces |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `proposal` | Seed: the original idea / decision under consideration | A `proposal` artifact (the task text from the caller) |
|
|
52
|
+
| `critique` | Adversarial review against project memory | One or more `critique` artifacts citing real memory ids |
|
|
53
|
+
| `revision` | Champion's response to the critique batch | A `revision` artifact addressing the points raised |
|
|
54
|
+
| `synthesis` | Final plan_draft folding the cycle's outputs | A `plan_draft` artifact with `addresses_critique:[ids]` |
|
|
55
|
+
|
|
56
|
+
`critique ↔ revision` is the iteration block: the loop loops there,
|
|
57
|
+
incrementing `iteration_count`, until exit criteria are met.
|
|
58
|
+
|
|
59
|
+
## Per-phase context filter
|
|
60
|
+
|
|
61
|
+
Each phase pulls a **filtered slice** of memory rather than the full
|
|
62
|
+
project context. This is what makes single-agent ideation produce real
|
|
63
|
+
adversarial pressure.
|
|
64
|
+
|
|
65
|
+
| Phase | `context_filter` (memory categories visible) | Why |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `proposal` | `decisions`, `constraints`, `plans`, `project_vision` | Positive context — what we want to build, what's already settled |
|
|
68
|
+
| `critique` | `traps`, `feedback`, `runtime_notes`, `critique_history` | Adversarial-only — known failure modes, prior critiques |
|
|
69
|
+
| `revision` | `*` (everything) | Champion needs full picture to address findings |
|
|
70
|
+
| `synthesis` | `*` (everything) | Final plan_draft must reflect all signal |
|
|
71
|
+
|
|
72
|
+
The closed-enum vocabulary lives in [`LOOP_CONTEXT_CATEGORIES`](../../src/core/loops/types.ts).
|
|
73
|
+
The wildcard `*` expands to every user-facing category. Loop-internal
|
|
74
|
+
categories (`critique_history` / `revision_history` / `synthesis_artifact`)
|
|
75
|
+
refer to artifacts produced earlier in the same loop and are pulled
|
|
76
|
+
from the thread directly, not from project memory.
|
|
77
|
+
|
|
78
|
+
If a phase declares no `context_filter`, the driver falls back to the
|
|
79
|
+
wildcard set — same behaviour as a non-ideation loop.
|
|
80
|
+
|
|
81
|
+
## Iteration block
|
|
82
|
+
|
|
83
|
+
The `LoopProtocolConfig.iteration` block describes the inner cycle:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
iteration: {
|
|
87
|
+
cycle: ['critique', 'revision'],
|
|
88
|
+
max_iterations: 3,
|
|
89
|
+
exit_when: 'no_new_critique_artifacts',
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- `cycle` lists the phase names that repeat in order.
|
|
94
|
+
- `max_iterations` caps the number of rounds. The default is 3 — past
|
|
95
|
+
empirical work (`runtime_note 'ideation_loop_mvp_simulation_transcript'`)
|
|
96
|
+
found 3 rounds is the saturation point at which a memory-driven
|
|
97
|
+
critique stops surfacing new conflicts on a typical proposal.
|
|
98
|
+
- `exit_when` chooses the convergence criterion:
|
|
99
|
+
- `'no_new_critique_artifacts'` — a full cycle completes without
|
|
100
|
+
adding any critique-typed artifact. Stable saturation.
|
|
101
|
+
- `'critic_signal'` — the critic produced a `critic_signal` artifact
|
|
102
|
+
declaring the proposal sufficient. Explicit early exit.
|
|
103
|
+
|
|
104
|
+
The [iteration engine FSM](../../src/core/loops/iteration-engine.ts)
|
|
105
|
+
(`decideNextPhase`) returns one of five outcomes at each transition:
|
|
106
|
+
linear `advance_to`, intra-cycle `iterate_to`, `exit_cycle` when
|
|
107
|
+
`exit_when` fires, `max_iterations` when the cap hits, or throws when
|
|
108
|
+
the current phase is the last with no successor.
|
|
109
|
+
|
|
110
|
+
## Phase-advance gate
|
|
111
|
+
|
|
112
|
+
The critique phase carries a default `advance_gate`:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
advance_gate: {
|
|
116
|
+
kind: 'min_artifacts_by_type',
|
|
117
|
+
type: 'critique',
|
|
118
|
+
n: 3,
|
|
119
|
+
scope: 'phase',
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The driver refuses to leave critique until at least 3 critique artifacts
|
|
124
|
+
have been produced in the current iteration. Below that floor the
|
|
125
|
+
adversarial pressure hasn't accumulated enough to make revision useful.
|
|
126
|
+
|
|
127
|
+
Gate evaluation is **iteration-window-aware**: counts only the artifacts
|
|
128
|
+
produced in the current iteration window, so a previous round's
|
|
129
|
+
critiques don't satisfy the gate for the new round.
|
|
130
|
+
|
|
131
|
+
When the gate fails, the driver:
|
|
132
|
+
- Emits a `phase_advance_blocked` system event with a structured
|
|
133
|
+
`gate_reason` (e.g. `min_artifacts_by_type unmet: phase-scope count of
|
|
134
|
+
type "critique" = 1 < n=3`).
|
|
135
|
+
- Throws an actionable error so the caller knows what's missing.
|
|
136
|
+
|
|
137
|
+
System events live in the same event journal as `turn_assigned` /
|
|
138
|
+
`phase_advanced`; they are NOT first-class artifacts (which would force
|
|
139
|
+
every consumer to filter `is_system` before processing content).
|
|
140
|
+
|
|
141
|
+
## Brief assembly
|
|
142
|
+
|
|
143
|
+
When a turn fires, the driver assembles a brief for the slot agent via
|
|
144
|
+
[`buildIdeationBrief`](../../src/core/loops/brief-assembly.ts). The
|
|
145
|
+
brief is the message the slot reads from its inbox.
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
# ideation_loop brief
|
|
149
|
+
loop: lop_…
|
|
150
|
+
phase: critique
|
|
151
|
+
iteration: 0
|
|
152
|
+
slot: critic
|
|
153
|
+
title: …
|
|
154
|
+
goal: …
|
|
155
|
+
|
|
156
|
+
## proposal
|
|
157
|
+
<proposal seed text>
|
|
158
|
+
|
|
159
|
+
## memory bundle (BM25-ranked, filtered by phase context)
|
|
160
|
+
### traps
|
|
161
|
+
- [trp_…] <trap text>
|
|
162
|
+
### feedback
|
|
163
|
+
- [fb_…] <feedback text>
|
|
164
|
+
### runtime_notes
|
|
165
|
+
…
|
|
166
|
+
|
|
167
|
+
## prior loop artifacts ← only when iteration > 0
|
|
168
|
+
### critique_history (prior iterations)
|
|
169
|
+
- [art_…] (iter 0) <truncated body>
|
|
170
|
+
|
|
171
|
+
## what to produce
|
|
172
|
+
- Phase "critique" expects you to act in role "critic".
|
|
173
|
+
- Emit findings as LoopArtifacts via bclaw_loop intent='complete_turn'…
|
|
174
|
+
- Cite the memory ids you relied on so the synthesis can audit coverage.
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The bundle is **size-capped** at 48 000 chars (~12 000 tokens at
|
|
178
|
+
~4 chars/token English). The cap is greedy: if the assembled bundle
|
|
179
|
+
overflows, the assembler appends a "memory bundle truncated…" tail and
|
|
180
|
+
reports `truncated`, `includedItems`, and `droppedItems` to the caller
|
|
181
|
+
so a per-slot warning can surface. The cap exists to mitigate
|
|
182
|
+
[trp#179](../../src/core/loops/brief-assembly.ts) — when memory
|
|
183
|
+
bundles get too large, agents fall back to CLI tools instead of
|
|
184
|
+
honouring MCP semantics.
|
|
185
|
+
|
|
186
|
+
Memory categories are fetched via an injectable `BriefMemoryProvider`.
|
|
187
|
+
The production implementation (in [`src/commands/mcp.ts`](../../src/commands/mcp.ts)
|
|
188
|
+
under the `intent='ideate'` handler) maps categories onto
|
|
189
|
+
[`src/core/search.ts`](../../src/core/search.ts) sections and uses
|
|
190
|
+
its BM25 ranking with the proposal text as the query. Top-K defaults
|
|
191
|
+
to 8 per category. Categories without a search-section mapping
|
|
192
|
+
(`runtime_notes`, `feedback`, `project_vision` in v1) silently return
|
|
193
|
+
empty — they will plug in when the corresponding stores get a search
|
|
194
|
+
index.
|
|
195
|
+
|
|
196
|
+
## Driver: `bclaw_coordinate(intent='ideate')`
|
|
197
|
+
|
|
198
|
+
The driver entry point is the existing coordinate facade with a new
|
|
199
|
+
intent. It opens an ideation_loop, registers slots, stores the task
|
|
200
|
+
as the proposal seed, and (in multi-agent mode) advances to critique
|
|
201
|
+
and dispatches the first turn.
|
|
202
|
+
|
|
203
|
+
### Single-agent mode (default)
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
bclaw_coordinate(intent='ideate', task='Should we extract the dispatcher into a separate package?')
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- Opens a loop with one `champion` slot = caller.
|
|
210
|
+
- Stores `task` as a `proposal` artifact (sliced to fit the 4 KB
|
|
211
|
+
artifact body cap).
|
|
212
|
+
- Stops at the proposal phase. The champion drives the loop manually
|
|
213
|
+
via `bclaw_loop(intent='turn'|'advance')`.
|
|
214
|
+
- Returns `{loop_id, proposal_artifact_id, mode: 'single_agent',
|
|
215
|
+
dispatched_critics: 0, current_phase: 'proposal'}`.
|
|
216
|
+
- Surfaces a single-agent warning so the caller knows dispatch is
|
|
217
|
+
manual.
|
|
218
|
+
|
|
219
|
+
This is the right mode when you want the loop's structure (memory
|
|
220
|
+
filter, gate, iteration accounting) but want to drive each turn
|
|
221
|
+
yourself — useful for one-shot consultations or when you don't have
|
|
222
|
+
a separate critic agent on hand.
|
|
223
|
+
|
|
224
|
+
### Multi-agent mode
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
bclaw_coordinate(intent='ideate',
|
|
228
|
+
task='Should we adopt approach A or approach B?',
|
|
229
|
+
targetAgents=['codex'])
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
- Opens a loop with `champion` slot (caller) + one `critic` slot per
|
|
233
|
+
target agent.
|
|
234
|
+
- Stores `task` as a `proposal` artifact.
|
|
235
|
+
- Advances proposal → critique.
|
|
236
|
+
- For each critic slot: assembles the brief via `buildIdeationBrief`
|
|
237
|
+
honouring the critique phase's context_filter, calls
|
|
238
|
+
`bclaw_loop(intent='turn')` to flip the slot to `assigned`, and
|
|
239
|
+
queues a coordinate message with the brief as body and
|
|
240
|
+
`{intent: 'ideate', loop_id, slot_id, phase, iteration,
|
|
241
|
+
proposal_artifact_id}` payload.
|
|
242
|
+
- Returns `{loop_id, …, mode: 'multi_agent',
|
|
243
|
+
dispatched_critics: N, current_phase: 'critique'}`.
|
|
244
|
+
|
|
245
|
+
When the critique phase brief is truncated for any slot, a per-slot
|
|
246
|
+
warning surfaces. When dispatch fails (e.g. an agent is unknown), the
|
|
247
|
+
overall response degrades to `partial` and the loop stays at the
|
|
248
|
+
proposal phase — callers can retry manually.
|
|
249
|
+
|
|
250
|
+
### Custom stop_condition
|
|
251
|
+
|
|
252
|
+
You can override the default `artifact_produced { phase: synthesis,
|
|
253
|
+
type: plan_draft }` stop_condition with anything from the
|
|
254
|
+
[`StopCondition`](../../src/core/loops/types.ts) vocabulary:
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
bclaw_loop(intent='open', kind='ideation', stop_condition: {
|
|
258
|
+
kind: 'min_artifacts_by_type',
|
|
259
|
+
type: 'critique',
|
|
260
|
+
n: 5,
|
|
261
|
+
scope: 'loop', // counts across phases / iterations
|
|
262
|
+
})
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
This stops the loop after 5 critique artifacts have accumulated
|
|
266
|
+
loop-wide, regardless of phase or iteration. Useful for "harvest as
|
|
267
|
+
many criticisms as possible, then stop" patterns.
|
|
268
|
+
|
|
269
|
+
## Synthesis schema
|
|
270
|
+
|
|
271
|
+
The synthesis phase's `plan_draft` artifact MUST carry an
|
|
272
|
+
`addresses_critique: string[]` field listing the critique artifact ids
|
|
273
|
+
it folded in (or explicitly waived). Field-presence is enforced at
|
|
274
|
+
the zod level on `LoopArtifactSchema`. v1 enforces the field; v1.1
|
|
275
|
+
will add semantic validation (each id maps to a real critique
|
|
276
|
+
artifact). This makes synthesis auditable: a reviewer can check
|
|
277
|
+
which critiques were honoured vs ignored.
|
|
278
|
+
|
|
279
|
+
## When NOT to use
|
|
280
|
+
|
|
281
|
+
- **Quick clarifications.** A 2-turn back-and-forth in a normal
|
|
282
|
+
message thread is cheaper than spinning up a loop.
|
|
283
|
+
- **Operationally urgent decisions.** The iteration block adds
|
|
284
|
+
latency. For "the build is broken, what's the fix?" the right tool
|
|
285
|
+
is `bclaw_coordinate(intent='consult')`.
|
|
286
|
+
- **Architectural debates with no project memory.** If you've never
|
|
287
|
+
recorded any traps / feedback / runtime_notes for this domain, the
|
|
288
|
+
critic will fetch nothing and the brief will be a no-op. Seed the
|
|
289
|
+
memory first, or use a literal multi-agent loop where the critic
|
|
290
|
+
brings its own perspective.
|
|
291
|
+
|
|
292
|
+
## Future direction
|
|
293
|
+
|
|
294
|
+
- **Reframer phase** ([pln#493](https://github.com/jberdah/brainclaw/blob/master/.brainclaw/coordination/plans/pln_36c9a4d1.json)).
|
|
295
|
+
A fresh-eyes phase between iteration exit and synthesis. Sees only
|
|
296
|
+
`project_vision`, `constraints`, and the synthesis_artifact — no
|
|
297
|
+
critique/revision history. Surfaces simplifications, alternative
|
|
298
|
+
framings, and "wrong question" findings that memory-driven critique
|
|
299
|
+
is structurally unable to produce. Validated empirically; ships on
|
|
300
|
+
its own cadence after MVP usage telemetry.
|
|
301
|
+
- **Profile-based slot diversity.** Champion / simplifier / pessimist
|
|
302
|
+
as separate slot types with their own context filters. Deferred
|
|
303
|
+
until the single-slot model is validated in production.
|
|
304
|
+
- **Cross-loop memory.** Promoting validated plan_drafts back into
|
|
305
|
+
the project memory store with provenance. Today the synthesis
|
|
306
|
+
artifact lives only in the loop event journal.
|
|
307
|
+
|
|
308
|
+
## Reference implementation
|
|
309
|
+
|
|
310
|
+
| Component | File |
|
|
311
|
+
|---|---|
|
|
312
|
+
| Schema (categories, iteration, gate, system events) | [`src/core/loops/types.ts`](../../src/core/loops/types.ts) |
|
|
313
|
+
| FSM (decideNextPhase, exit predicates) | [`src/core/loops/iteration-engine.ts`](../../src/core/loops/iteration-engine.ts) |
|
|
314
|
+
| Gate evaluator (`evaluatePhaseAdvanceGate`) | [`src/core/loops/verbs.ts`](../../src/core/loops/verbs.ts) |
|
|
315
|
+
| Brief assembler (`buildIdeationBrief`) | [`src/core/loops/brief-assembly.ts`](../../src/core/loops/brief-assembly.ts) |
|
|
316
|
+
| Driver (`bclaw_coordinate intent='ideate'`) | [`src/commands/mcp.ts`](../../src/commands/mcp.ts) (search `req.intent === 'ideate'`) |
|
|
317
|
+
| Tests (schema, FSM, assembler, dispatch, e2e) | [`tests/unit/loops-types.test.ts`](../../tests/unit/loops-types.test.ts), [`loops-iteration-engine.test.ts`](../../tests/unit/loops-iteration-engine.test.ts), [`loops-phase-advance-gate.test.ts`](../../tests/unit/loops-phase-advance-gate.test.ts), [`loops-advance-iteration.test.ts`](../../tests/unit/loops-advance-iteration.test.ts), [`loops-brief-assembly.test.ts`](../../tests/unit/loops-brief-assembly.test.ts), [`bclaw-coordinate.test.ts`](../../tests/unit/bclaw-coordinate.test.ts), [`ideation-loop-e2e.test.ts`](../../tests/unit/ideation-loop-e2e.test.ts) |
|