brainclaw 1.15.0 → 1.16.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 (57) hide show
  1. package/README.md +10 -3
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli/register-capture.js +209 -0
  4. package/dist/cli/register-code-map.js +19 -0
  5. package/dist/cli/register-coordination.js +472 -0
  6. package/dist/cli/register-federation.js +258 -0
  7. package/dist/cli/register-lifecycle.js +436 -0
  8. package/dist/cli/register-memory-context.js +502 -0
  9. package/dist/cli/register-planning.js +167 -0
  10. package/dist/cli/register-review.js +149 -0
  11. package/dist/cli/shared.js +5 -0
  12. package/dist/cli.js +212 -2183
  13. package/dist/commands/dispatch-watch.js +25 -2
  14. package/dist/commands/harvest.js +31 -6
  15. package/dist/commands/mcp-catalog.js +1438 -0
  16. package/dist/commands/mcp-contract.js +33 -0
  17. package/dist/commands/mcp-presentation.js +27 -0
  18. package/dist/commands/mcp-read-handlers.js +72 -36
  19. package/dist/commands/mcp-write-admin.js +328 -0
  20. package/dist/commands/mcp-write-claims.js +864 -0
  21. package/dist/commands/mcp-write-coordination.js +1825 -0
  22. package/dist/commands/mcp-write-entities.js +620 -0
  23. package/dist/commands/mcp-write-memory.js +451 -0
  24. package/dist/commands/mcp-write-sequences.js +116 -0
  25. package/dist/commands/mcp-write-support.js +367 -0
  26. package/dist/commands/mcp.js +261 -5584
  27. package/dist/commands/update-handoff.js +28 -42
  28. package/dist/core/agent-capability.js +31 -14
  29. package/dist/core/agent-files.js +1 -1
  30. package/dist/core/coordination.js +5 -2
  31. package/dist/core/cross-project.js +35 -1
  32. package/dist/core/dispatcher.js +34 -20
  33. package/dist/core/entity-operations.js +335 -12
  34. package/dist/core/entity-registry.js +72 -9
  35. package/dist/core/execution.js +28 -4
  36. package/dist/core/facade-schema.js +18 -4
  37. package/dist/core/handoff-review.js +35 -0
  38. package/dist/core/protocol-tool-policy.js +113 -0
  39. package/dist/core/review-loop-close.js +115 -0
  40. package/dist/core/schema.js +14 -2
  41. package/dist/core/security-detectors.js +35 -6
  42. package/dist/core/security.js +32 -12
  43. package/dist/core/worktree.js +73 -5
  44. package/dist/facts.js +13 -11
  45. package/dist/facts.json +12 -10
  46. package/docs/PROTOCOL.md +7 -3
  47. package/docs/concepts/coordinator-runbook.md +3 -0
  48. package/docs/concepts/dispatch-lifecycle.md +4 -4
  49. package/docs/concepts/loop-engine.md +3 -1
  50. package/docs/concepts/troubleshooting.md +1 -1
  51. package/docs/integrations/codex.md +3 -3
  52. package/docs/integrations/overview.md +1 -1
  53. package/docs/mcp-schema-changelog.md +137 -2
  54. package/docs/playbooks/orchestration.md +1 -1
  55. package/docs/product/entity-model-audit.md +3 -2
  56. package/docs/security.md +22 -1
  57. package/package.json +3 -1
package/README.md CHANGED
@@ -255,8 +255,10 @@ bclaw_coordinate({
255
255
  targetAgents: ["claude-code"]
256
256
  });
257
257
 
258
- // 4. The loop progresses as agents interact and resolve findings
259
- bclaw_loop({ intent: "advance", loop_id: "lop_abc" });
258
+ // 4. The reviewer's verdict is harvested from its LANE-RESULT.json and the loop
259
+ // auto-closes on approve — no manual advance needed for the approve path.
260
+ // (bclaw_loop remains available to drive the request_changes fix cycle by hand.)
261
+ bclaw_loop({ intent: "get", loop_id: "lop_abc" }); // inspect status any time
260
262
  ```
261
263
 
262
264
  ## The Loop Engine (Multi-Turn Workflows)
@@ -268,6 +270,8 @@ Brainclaw's Loop Engine moves beyond manual ping-pong by formalizing multi-turn
268
270
 
269
271
  Each loop maintains a structured lifecycle, explicit phases, iteration bounds, and per-phase memory filters, executed seamlessly via `bclaw_loop`.
270
272
 
273
+ **Autonomous convergence (pln#628 Focus 4B):** a dispatched reviewer doesn't need to be driven by hand. It writes its verdict (`review_verdict: approve | request_changes`) into its `LANE-RESULT.json`; when the coordinator harvests the lane, brainclaw records the verdict on the loop and **auto-closes it on approve** — the review loop reaches `reviewer_green` with no human ping-pong. `request_changes` advances to the author phase (the automated fix→re-review cycle is a planned follow-up).
274
+
271
275
  ## Enterprise Ready: Mono-repo & Micro-services
272
276
 
273
277
  Brainclaw is designed to scale across complex environments. Using the **`project_mode`** setting, Brainclaw seamlessly auto-detects folder boundaries for mono-repos and applies proper environment bootstrapping.
@@ -306,7 +310,7 @@ Recent releases have moved a lot of multi-agent parallel work from "risky" to "s
306
310
 
307
311
  - **Per-claim auto-worktree** — each dispatched lane gets its own isolated git worktree; the coordinator integrates with an octopus merge.
308
312
  - **Sequenced parallel execute** — `bclaw_dispatch(intent="execute")` fans out independent lanes across several agent instances and integrates the result.
309
- - **Symmetric review-fix loops** — `bclaw_coordinate(intent="review", open_loop=true, review_mode="symmetric")` runs an alternating review-and-fix conversation across two slots without shared-checkout collisions.
313
+ - **Symmetric review-fix loops** — `bclaw_coordinate(intent="review", open_loop=true, review_mode="symmetric")` runs an alternating review-and-fix conversation across two slots without shared-checkout collisions. The reviewer's verdict is harvested from `LANE-RESULT.json` and the loop **auto-closes on approve** — no manual round-trip to converge the approve path.
310
314
  - **Cross-platform spawn** — OS-aware prompt delivery (stdin pipe / inline arg) plus a brief-ack file handshake, so spawned workers can be detected and timed out reliably on Windows and Unix.
311
315
  - **Worktree GC is scope-bounded** — symlinks and junctions are no longer followed during cleanup, so post-merge sweeps can't wipe `node_modules` or other neighboring directories.
312
316
  - **MCP runtime self-heal** — when the runtime is corrupted, the server logs an actionable repair pointer; `brainclaw doctor --repair` rebuilds dist in one step.
@@ -315,6 +319,7 @@ Still sharp:
315
319
 
316
320
  1. **Same-checkout concurrent edits** — running two agents in the *same* working tree (no per-claim worktree) is still the wrong answer. Use the dispatch path (auto-worktree per claim) instead of raw concurrent CLI sessions.
317
321
  2. **Cross-machine sync** — federation across machines is on the roadmap, not in v1.x. Today brainclaw's store is local and one-machine-per-project.
322
+ 3. **Next.js / Turbopack dev server in a worktree** — the provisioned `node_modules` symlink points outside the worktree root, which `next dev` (Turbopack) rejects (build/tsc/vitest are fine). brainclaw warns; `npm install` in the worktree or smoke-test on the merged branch. A Turbopack-compatible dependency mode is a planned follow-up.
318
323
  3. **Spawn-and-forget assumptions** — spawned workers don't always commit their work cleanly. The brief-ack file confirms the spawn started; in the worst case the coordinator harvests open changes.
319
324
  4. **Live state for hook-less agents** — supported hook-less file surfaces such as Cline, Windsurf, Continue, Antigravity/Gemini CLI, and Mistral Vibe can get live context via `.live.md` companions regenerated on session-end and handoff, not via real-time push.
320
325
 
@@ -344,6 +349,8 @@ Maven, Gradle, and Cargo are intentionally excluded — their dependency caches
344
349
 
345
350
  Build outputs like `dist` are **not** symlinked — they must be per-worktree to avoid EBUSY errors when other processes hold handles on the output directory.
346
351
 
352
+ > **Next.js / Turbopack caveat.** The `node_modules` link is a symlink to the main worktree, i.e. it points **outside** the agent worktree's root. `tsc`, `vitest`, and production `build` follow it fine, but `next dev` (Turbopack) panics on a `node_modules` link outside the worktree root. brainclaw detects Next.js projects and surfaces a `symlink_warnings` note at worktree creation. Workaround for dev-server work: run `npm install` inside the worktree (optionally with `BRAINCLAW_NO_LINK_DEPS=1`), or smoke-test on the merged branch. A Turbopack-compatible per-worktree dependency mode is a planned follow-up.
353
+
347
354
  Override detection in `.brainclaw/config.yaml`:
348
355
 
349
356
  ```yaml
Binary file
@@ -0,0 +1,209 @@
1
+ import { runDecision } from '../commands/decision.js';
2
+ import { runConstraint } from '../commands/constraint.js';
3
+ import { runTrap } from '../commands/trap.js';
4
+ import { runHandoff } from '../commands/handoff.js';
5
+ import { runUpdateHandoff } from '../commands/update-handoff.js';
6
+ import { runReflect } from '../commands/reflect.js';
7
+ import { runReflectRuntimeNote } from '../commands/reflect-runtime-note.js';
8
+ import { runInstruction } from '../commands/instruction.js';
9
+ import { runListInstructions } from '../commands/list-instructions.js';
10
+ import { runRuntimeNote } from '../commands/runtime-note.js';
11
+ import { runRuntimeStatus } from '../commands/runtime-status.js';
12
+ import { collect } from './shared.js';
13
+ export function registerCaptureCommands(program) {
14
+ // --- decision ---
15
+ program
16
+ .command('decision <text>')
17
+ .description('Add a recent decision')
18
+ .option('--outcome <outcome>', 'Outcome: approved, rejected, deferred, pending')
19
+ .option('--tag <tags...>', 'Tags for this decision')
20
+ .option('--path <paths...>', 'Related file paths')
21
+ .option('--author <author>', 'Author name')
22
+ .option('--plan <id>', 'Optional linked plan item ID')
23
+ .option('--store <target>', 'Target store level: local (default), repo, workspace, user')
24
+ .action((text, options) => {
25
+ runDecision(text, options);
26
+ });
27
+ // --- constraint ---
28
+ program
29
+ .command('constraint <text>')
30
+ .description('Add an active constraint')
31
+ .option('--category <category>', 'Category: architecture, performance, security, reliability, compatibility, process, other')
32
+ .option('--tag <tags...>', 'Tags for this constraint')
33
+ .option('--path <paths...>', 'Related file paths')
34
+ .option('--author <author>', 'Author name')
35
+ .option('--store <target>', 'Target store level: local (default), repo, workspace, user')
36
+ .action((text, options) => {
37
+ runConstraint(text, options);
38
+ });
39
+ // --- trap ---
40
+ program
41
+ .command('trap <text>')
42
+ .description('Add a known trap')
43
+ .option('--status <status>', 'Status: active, resolved, expired', 'active')
44
+ .option('--severity <severity>', 'Severity: low, medium, high', 'medium')
45
+ .option('--visibility <visibility>', 'Visibility: shared, machine, private', 'shared')
46
+ .option('--host <host>', 'Optional host identifier override for machine/private traps')
47
+ .option('--tag <tags...>', 'Tags for this trap')
48
+ .option('--path <paths...>', 'Related file paths')
49
+ .option('--author <author>', 'Author name')
50
+ .option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d (trap auto-expires after this duration)')
51
+ .option('--store <target>', 'Target store level: local (default), repo, workspace, user')
52
+ .action((text, options) => {
53
+ runTrap(text, options);
54
+ });
55
+ // --- handoff ---
56
+ program
57
+ .command('handoff <text>')
58
+ .description('Create a handoff')
59
+ .requiredOption('--from <from>', 'Source of the handoff')
60
+ .requiredOption('--to <to>', 'Destination of the handoff')
61
+ .option('--tag <tags...>', 'Tags for this handoff')
62
+ .option('--path <paths...>', 'Related file paths')
63
+ .option('--project <project>', 'Optional project namespace')
64
+ .option('--plan <id>', 'Optional linked plan item ID')
65
+ .option('--author <author>', 'Author name')
66
+ .option('--capture-diff', 'Capture current git diff into the handoff snapshot')
67
+ .option('--files <files...>', 'Files touched in this handoff')
68
+ .option('--pre-condition <conditions...>', 'Pre-conditions for the receiving agent')
69
+ .option('--post-condition <conditions...>', 'Post-conditions the receiving agent must satisfy')
70
+ .option('--test <tests...>', 'Tests the receiving agent should verify')
71
+ .option('--linked-plan <plans...>', 'Linked plan IDs')
72
+ .action((text, options) => {
73
+ runHandoff(text, options);
74
+ });
75
+ // --- update-handoff ---
76
+ program
77
+ .command('update-handoff <id>')
78
+ .description('Update the status, recipient, or review state of a handoff')
79
+ .option('--status <status>', 'Status: open, accepted, closed')
80
+ .option('--to <agent>', 'Change the receiving agent')
81
+ .option('--narrative <text>', 'Update the narrative attached to the handoff')
82
+ .option('--reviewer <agent>', 'Set or override the assigned reviewer')
83
+ .option('--review-verdict <verdict>', 'Set review verdict: approve or request_changes')
84
+ .option('--reviewed-by <agent>', 'Set the reviewer identity that produced the verdict')
85
+ .option('--review-summary <text>', 'Attach a short review summary')
86
+ .option('--blocking-issue <text>', 'Add a blocking review issue (repeatable)', collect, [])
87
+ .option('--suggestion <text>', 'Add a non-blocking review suggestion (repeatable)', collect, [])
88
+ .action((id, options) => {
89
+ runUpdateHandoff(id, {
90
+ ...options,
91
+ review_verdict: options.reviewVerdict,
92
+ reviewed_by: options.reviewedBy,
93
+ review_summary: options.reviewSummary,
94
+ blocking_issues: options.blockingIssue,
95
+ suggestions: options.suggestion,
96
+ });
97
+ });
98
+ // --- reflect ---
99
+ program
100
+ .command('reflect [text]')
101
+ .description('Create a memory candidate for review')
102
+ .option('--type <type>', 'Type: constraint, decision, trap, handoff')
103
+ .option('--batch <file>', 'Import runtime events from JSON file')
104
+ .option('--session <id>', 'Import runtime events by session id from .brainclaw/runtime/')
105
+ .option('--tag <tags...>', 'Tags')
106
+ .option('--author <author>', 'Author name')
107
+ .option('--source <source>', 'Source context (e.g. agent name)')
108
+ .option('--severity <severity>', 'Severity for traps: low, medium, high')
109
+ .option('--from <from>', 'Handoff source')
110
+ .option('--to <to>', 'Handoff destination')
111
+ .option('--path <paths...>', 'Related file paths')
112
+ .action((text, options) => {
113
+ runReflect(text, options);
114
+ });
115
+ // --- reflect-runtime-note ---
116
+ program
117
+ .command('reflect-runtime-note <id> [text]')
118
+ .description('Turn a visible runtime note into a shared review candidate')
119
+ .option('--type <type>', 'Type: constraint, decision, trap, handoff')
120
+ .option('--host <host>', 'Look up machine-local runtime note for a specific host')
121
+ .option('--all-hosts', 'Look up runtime notes across all hosts')
122
+ .option('--suggest', 'Show candidate type suggestions before or instead of creation')
123
+ .option('--json', 'Output suggestions as JSON when used with --suggest or without --type')
124
+ .option('--tag <tags...>', 'Additional tags to merge with the runtime note tags')
125
+ .option('--author <author>', 'Author name for the candidate')
126
+ .option('--source <source>', 'Source context for the candidate')
127
+ .option('--severity <severity>', 'Severity for traps: low, medium, high')
128
+ .option('--from <from>', 'Handoff source')
129
+ .option('--to <to>', 'Handoff destination')
130
+ .option('--path <paths...>', 'Related file paths')
131
+ .action((id, text, options) => {
132
+ runReflectRuntimeNote(id, text, options);
133
+ });
134
+ // --- instruction ---
135
+ program
136
+ .command('instruction <text>')
137
+ .description('Add a layered shared instruction')
138
+ .option('--layer <layer>', 'Instruction layer: global, project, agent', 'global')
139
+ .option('--project <project>', 'Project namespace when --layer project is used')
140
+ .option('--agent <agent>', 'Agent name when --layer agent is used')
141
+ .option('--tag <tags...>', 'Tags for this instruction')
142
+ .option('--author <author>', 'Author name')
143
+ .option('--supersedes <id>', 'Supersede an older instruction entry')
144
+ .option('--store <target>', 'Target store level: local (default), repo, workspace, user')
145
+ .action((text, options) => {
146
+ runInstruction(text, options);
147
+ });
148
+ // --- list-instructions ---
149
+ program
150
+ .command('list-instructions')
151
+ .description('List raw or resolved shared instructions')
152
+ .option('--json', 'Output as JSON')
153
+ .option('--layer <layer>', 'Filter by layer: global, project, agent')
154
+ .option('--project <project>', 'Project namespace filter')
155
+ .option('--agent <agent>', 'Agent name filter')
156
+ .option('--active', 'Only show active entries')
157
+ .option('--resolved', 'Resolve effective instructions for the given scope')
158
+ .option('--for <target>', 'Infer project namespace from target path when strategy=folder')
159
+ .action((options) => {
160
+ runListInstructions(options);
161
+ });
162
+ // --- runtime-note ---
163
+ program
164
+ .command('runtime-note <text>')
165
+ .description('Add a runtime note for an agent')
166
+ .option('--agent <agent>', 'Agent name; defaults to the configured current agent')
167
+ .option('--project <project>', 'Optional project namespace')
168
+ .option('--plan <id>', 'Optional linked plan item ID')
169
+ .option('--visibility <visibility>', 'Visibility: shared, machine, private', 'shared')
170
+ .option('--host <host>', 'Optional host identifier override for machine/private runtime notes')
171
+ .option('--tag <tags...>', 'Tags')
172
+ .option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d (note auto-expires after this duration)')
173
+ .option('--auto-reflect', 'Attempt to turn this runtime note into durable memory immediately')
174
+ .action((text, options) => {
175
+ runRuntimeNote(text, { ...options, autoReflect: options.autoReflect });
176
+ });
177
+ // --- note create ---
178
+ const noteCommand = program
179
+ .command('note')
180
+ .description('Manage runtime notes');
181
+ noteCommand
182
+ .command('create <text>')
183
+ .description('Alias for runtime-note')
184
+ .option('--agent <agent>', 'Agent name; defaults to the configured current agent')
185
+ .option('--project <project>', 'Optional project namespace')
186
+ .option('--plan <id>', 'Optional linked plan item ID')
187
+ .option('--visibility <visibility>', 'Visibility: shared, machine, private', 'shared')
188
+ .option('--host <host>', 'Optional host identifier override for machine/private runtime notes')
189
+ .option('--tag <tags...>', 'Tags')
190
+ .option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d (note auto-expires after this duration)')
191
+ .option('--auto-reflect', 'Attempt to turn this runtime note into durable memory immediately')
192
+ .action((text, options) => {
193
+ runRuntimeNote(text, { ...options, autoReflect: options.autoReflect });
194
+ });
195
+ // --- runtime-status ---
196
+ program
197
+ .command('runtime-status')
198
+ .description('Show runtime notes')
199
+ .option('--agent <agent>', 'Filter by agent')
200
+ .option('--plan <id>', 'Filter by linked plan item')
201
+ .option('--visibility <visibility>', 'Visibility filter: shared, machine, private, all')
202
+ .option('--host <host>', 'Include machine-local notes for a specific host')
203
+ .option('--all-hosts', 'Include machine-local notes from all hosts')
204
+ .option('--json', 'Output as JSON')
205
+ .action((options) => {
206
+ runRuntimeStatus(options);
207
+ });
208
+ }
209
+ //# sourceMappingURL=register-capture.js.map
@@ -0,0 +1,19 @@
1
+ import { runCodeMap } from '../commands/code-map.js';
2
+ export function registerCodeMapCommands(program) {
3
+ // --- code-map ---
4
+ program
5
+ .command('code-map <subcommand> [args...]')
6
+ .description('Query the per-project Code Map (status, refresh, find, brief)')
7
+ .option('--json', 'Output as JSON')
8
+ .option('--all', 'For refresh: enumerate all supported files (full refresh)')
9
+ .option('--changed', 'For refresh: only changed files (default)')
10
+ .option('--cascade', 'For refresh/status in a multi-project workspace: cascade across every nested project (each gets its own store; the root store is scoped to files no child owns)')
11
+ .option('--limit <n>', 'Max results for find/brief', (v) => parseInt(v, 10))
12
+ .action((subcommand, args, options) => {
13
+ void runCodeMap(subcommand, args, options).catch((err) => {
14
+ console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
15
+ process.exit(1);
16
+ });
17
+ });
18
+ }
19
+ //# sourceMappingURL=register-code-map.js.map