brainclaw 1.14.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.
- package/README.md +16 -263
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli/register-capture.js +209 -0
- package/dist/cli/register-code-map.js +19 -0
- package/dist/cli/register-coordination.js +472 -0
- package/dist/cli/register-federation.js +258 -0
- package/dist/cli/register-lifecycle.js +436 -0
- package/dist/cli/register-memory-context.js +502 -0
- package/dist/cli/register-planning.js +167 -0
- package/dist/cli/register-review.js +149 -0
- package/dist/cli/shared.js +5 -0
- package/dist/cli.js +212 -2015
- package/dist/commands/dispatch-watch.js +25 -2
- package/dist/commands/harvest.js +31 -6
- package/dist/commands/mcp-catalog.js +1438 -0
- package/dist/commands/mcp-contract.js +33 -0
- package/dist/commands/mcp-presentation.js +27 -0
- package/dist/commands/mcp-read-handlers.js +72 -36
- package/dist/commands/mcp-write-admin.js +328 -0
- package/dist/commands/mcp-write-claims.js +864 -0
- package/dist/commands/mcp-write-coordination.js +1825 -0
- package/dist/commands/mcp-write-entities.js +620 -0
- package/dist/commands/mcp-write-memory.js +451 -0
- package/dist/commands/mcp-write-sequences.js +116 -0
- package/dist/commands/mcp-write-support.js +367 -0
- package/dist/commands/mcp.js +261 -5570
- package/dist/commands/update-handoff.js +28 -42
- package/dist/core/agent-capability.js +31 -14
- package/dist/core/agent-files.js +1 -1
- package/dist/core/agent-registry.js +51 -3
- package/dist/core/claims.js +18 -0
- package/dist/core/coordination.js +5 -2
- package/dist/core/cross-project.js +35 -1
- package/dist/core/dispatcher.js +34 -20
- package/dist/core/entity-operations.js +335 -12
- package/dist/core/entity-registry.js +72 -9
- package/dist/core/execution.js +28 -4
- package/dist/core/facade-schema.js +30 -4
- package/dist/core/federation-cloud.js +142 -11
- package/dist/core/federation-outbox.js +292 -0
- package/dist/core/federation-signing.js +115 -0
- package/dist/core/handoff-review.js +35 -0
- package/dist/core/io.js +6 -0
- package/dist/core/protocol-tool-policy.js +113 -0
- package/dist/core/review-loop-close.js +115 -0
- package/dist/core/schema.js +25 -2
- package/dist/core/security-detectors.js +35 -6
- package/dist/core/security.js +32 -12
- package/dist/core/worktree.js +98 -9
- package/dist/facts.js +13 -11
- package/dist/facts.json +12 -10
- package/docs/PROTOCOL.md +7 -3
- package/docs/concepts/coordinator-runbook.md +3 -0
- package/docs/concepts/dispatch-lifecycle.md +4 -4
- package/docs/concepts/loop-engine.md +3 -1
- package/docs/concepts/troubleshooting.md +1 -1
- package/docs/integrations/codex.md +3 -3
- package/docs/integrations/overview.md +1 -1
- package/docs/mcp-schema-changelog.md +153 -2
- package/docs/playbooks/orchestration.md +1 -1
- package/docs/product/entity-model-audit.md +3 -2
- package/docs/security.md +22 -1
- package/package.json +3 -1
package/dist/core/worktree.js
CHANGED
|
@@ -25,17 +25,38 @@ function gitPath(p) {
|
|
|
25
25
|
* landed on the dot before `astro`, yielding `…IntegrationHubPage.` — a trailing
|
|
26
26
|
* dot git rejects (`fatal: not a valid branch name`). Truncating first, then
|
|
27
27
|
* stripping, guarantees the cap can never re-introduce an invalid ref.
|
|
28
|
+
*
|
|
29
|
+
* trp#950 (dogfood 2026-07-15): a plain truncation makes two DISTINCT scopes
|
|
30
|
+
* that share a >48-char prefix collapse to the SAME branch → same worktree path
|
|
31
|
+
* → the second claim/assign is refused. When (and only when) the cleaned slug
|
|
32
|
+
* exceeds the cap, a deterministic 8-char digest of the FULL cleaned slug is
|
|
33
|
+
* appended so distinct scopes diverge, while the same scope stays stable
|
|
34
|
+
* (resume/re-assign still resolves its worktree). Short scopes are unchanged.
|
|
35
|
+
* 8 hex chars = 32 bits: comfortably collision-safe for the realistic case
|
|
36
|
+
* (a handful of scopes sharing a deep directory prefix) while keeping a
|
|
37
|
+
* 39-char readable head.
|
|
28
38
|
*/
|
|
39
|
+
const BRANCH_COMPONENT_CAP = 48;
|
|
29
40
|
export function sanitizeBranchComponent(raw, fallback = 'scope') {
|
|
30
|
-
|
|
41
|
+
const cleaned = raw
|
|
31
42
|
.replace(/[\s~^:?*[\]\\]/g, '-') // chars forbidden by check-ref-format
|
|
32
43
|
.replace(/@\{/g, '-') // reflog syntax
|
|
33
44
|
.replace(/\.\.+/g, '.') // no double dots
|
|
34
45
|
.replace(/[^a-zA-Z0-9._-]/g, '-') // conservative whitelist for the rest
|
|
35
46
|
.replace(/-+/g, '-') // collapse dashes
|
|
36
|
-
.replace(/^[.-]+/, '') // no leading dot/dash
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
.replace(/^[.-]+/, ''); // no leading dot/dash
|
|
48
|
+
let slug;
|
|
49
|
+
if (cleaned.length <= BRANCH_COMPONENT_CAP) {
|
|
50
|
+
slug = cleaned.replace(/[.-]+$/, ''); // no trailing dot/dash
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Truncation drops characters → reserve room for a collision-resistant
|
|
54
|
+
// suffix derived from the full cleaned slug (trp#950). The digest is hex, so
|
|
55
|
+
// it can never re-introduce a trailing dot/dash or a `.lock` suffix.
|
|
56
|
+
const suffix = crypto.createHash('sha1').update(cleaned).digest('hex').slice(0, 8);
|
|
57
|
+
const head = cleaned.slice(0, BRANCH_COMPONENT_CAP - suffix.length - 1).replace(/[.-]+$/, '');
|
|
58
|
+
slug = `${head}-${suffix}`;
|
|
59
|
+
}
|
|
39
60
|
if (/\.lock$/i.test(slug))
|
|
40
61
|
slug = slug.slice(0, -'.lock'.length).replace(/[.-]+$/, '');
|
|
41
62
|
if (!slug)
|
|
@@ -348,14 +369,42 @@ export function commitWorktreeOnBehalf(worktreePath, message, options = {}) {
|
|
|
348
369
|
return { committed: false, files_changed: [], reason: 'worktree clean — nothing to commit' };
|
|
349
370
|
}
|
|
350
371
|
// Stage everything, then UNSTAGE the transient files that must never land on
|
|
351
|
-
// the lane branch: the worker's own `LANE-RESULT.json` report
|
|
352
|
-
// `.brainclaw/` coordination state
|
|
353
|
-
// (and master, on merge) with
|
|
372
|
+
// the lane branch: the worker's own `LANE-RESULT.json` report, any
|
|
373
|
+
// `.brainclaw/` coordination state, and the `.brainclaw-worktree.json` marker.
|
|
374
|
+
// Committing those would pollute the branch (and master, on merge) with
|
|
375
|
+
// non-deliverable artefacts — a field report (Codex on macOS) caught them
|
|
376
|
+
// landing in a lane commit (trp_01a2ba2a). `.brainclaw-worktree.json` sits at
|
|
377
|
+
// the worktree ROOT (NOT inside `.brainclaw/`), so the `.brainclaw` pathspec
|
|
378
|
+
// does not cover it — it needs its own entry. These are ALWAYS transient, so
|
|
379
|
+
// the unstage is unconditional.
|
|
354
380
|
const add = runGit(['add', '-A'], worktreePath);
|
|
355
381
|
if (!add.ok) {
|
|
356
382
|
return { committed: false, files_changed: [], reason: `git add failed: ${add.stderr.trim()}` };
|
|
357
383
|
}
|
|
358
|
-
runGit([
|
|
384
|
+
runGit([
|
|
385
|
+
'reset', '-q', '--',
|
|
386
|
+
'LANE-RESULT.json',
|
|
387
|
+
'.brainclaw',
|
|
388
|
+
'.brainclaw-worktree.json',
|
|
389
|
+
'.brainclaw-heartbeat-*',
|
|
390
|
+
], worktreePath);
|
|
391
|
+
// node_modules needs a TRACKED-AWARE exclusion (Codex review of #88, BLOCKING).
|
|
392
|
+
// Unstage the links/dirs brainclaw provisions — but a project that VENDORS
|
|
393
|
+
// node_modules tracks those files, and a worker's change to a TRACKED
|
|
394
|
+
// node_modules file is a REAL deliverable; dropping it would silently omit
|
|
395
|
+
// work. Strategy: unstage every node_modules path, then RE-ADD only the ones
|
|
396
|
+
// already tracked at HEAD and modified/deleted (never the fresh provisioned
|
|
397
|
+
// link/dir, which is `A` vs HEAD). The component-bounded pathspecs never match
|
|
398
|
+
// a similarly-named deliverable such as `src/node_modules_helper.ts` — the
|
|
399
|
+
// plain `node_modules` is root-leading-dir only, the `:(glob)` forms match the
|
|
400
|
+
// `node_modules` path component exactly (nested link entry + nested contents).
|
|
401
|
+
const NODE_MODULES_SPECS = ['node_modules', ':(glob)**/node_modules', ':(glob)**/node_modules/**'];
|
|
402
|
+
runGit(['reset', '-q', '--', ...NODE_MODULES_SPECS], worktreePath);
|
|
403
|
+
const trackedNm = runGit(['diff', '--name-only', '--diff-filter=MD', 'HEAD', '--', ...NODE_MODULES_SPECS], worktreePath);
|
|
404
|
+
const keepNm = trackedNm.stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
405
|
+
if (keepNm.length > 0) {
|
|
406
|
+
runGit(['add', '--', ...keepNm], worktreePath);
|
|
407
|
+
}
|
|
359
408
|
// The files actually staged for this commit (post-exclusion) — also the
|
|
360
409
|
// truthful files_changed report.
|
|
361
410
|
const staged = runGit(['diff', '--cached', '--name-only'], worktreePath);
|
|
@@ -364,7 +413,7 @@ export function commitWorktreeOnBehalf(worktreePath, message, options = {}) {
|
|
|
364
413
|
// Only transient files changed — nothing deliverable to commit. Restore the
|
|
365
414
|
// index so the worktree is left exactly as the worker left it.
|
|
366
415
|
runGit(['reset', '-q'], worktreePath);
|
|
367
|
-
return { committed: false, files_changed: [], reason: 'no committable changes (only transient LANE-RESULT.json / .brainclaw)' };
|
|
416
|
+
return { committed: false, files_changed: [], reason: 'no committable changes (only transient LANE-RESULT.json / .brainclaw / node_modules links)' };
|
|
368
417
|
}
|
|
369
418
|
const authorName = options.authorName ?? 'brainclaw (on behalf)';
|
|
370
419
|
const authorEmail = options.authorEmail ?? 'brainclaw@on-behalf.local';
|
|
@@ -482,6 +531,30 @@ export function findWorktreePathForBranch(worktrees, branchName) {
|
|
|
482
531
|
*
|
|
483
532
|
* Returns the absolute path to the newly created worktree.
|
|
484
533
|
*/
|
|
534
|
+
/**
|
|
535
|
+
* Whether the project looks like a Next.js app — a `next` dependency in
|
|
536
|
+
* package.json or a `next.config.*` at the root. Used to warn that the
|
|
537
|
+
* out-of-root `node_modules` symlink brainclaw provisions is rejected by
|
|
538
|
+
* `next dev` / Turbopack (trp_37b05a15), even though tsc / vitest / build accept
|
|
539
|
+
* it. Best-effort + defensive: any read/parse error → false (never blocks
|
|
540
|
+
* worktree creation over a heuristic).
|
|
541
|
+
*/
|
|
542
|
+
export function projectUsesNextjs(projectRoot) {
|
|
543
|
+
try {
|
|
544
|
+
for (const cfg of ['next.config.js', 'next.config.mjs', 'next.config.ts', 'next.config.cjs']) {
|
|
545
|
+
if (fs.existsSync(path.join(projectRoot, cfg)))
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
549
|
+
if (!fs.existsSync(pkgPath))
|
|
550
|
+
return false;
|
|
551
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
552
|
+
return Boolean(pkg.dependencies?.next ?? pkg.devDependencies?.next);
|
|
553
|
+
}
|
|
554
|
+
catch {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
485
558
|
export function createWorktree(mainWorktreePath, branchName, options = {}) {
|
|
486
559
|
// pln#614: resolve the true git toplevel first, so an in-tree project (project
|
|
487
560
|
// dir ≠ git root) creates its worktree from the real repo root — `git worktree
|
|
@@ -610,6 +683,22 @@ export function createWorktree(mainWorktreePath, branchName, options = {}) {
|
|
|
610
683
|
for (const entry of sharedPaths) {
|
|
611
684
|
trySymlinkSharedPath(entry);
|
|
612
685
|
}
|
|
686
|
+
// trp_37b05a15 (field report, Next.js 16 / Turbopack) — the node_modules link
|
|
687
|
+
// brainclaw provisions is an out-of-worktree-root symlink to the main repo.
|
|
688
|
+
// tsc / vitest / build follow it fine, but `next dev` (Turbopack) PANICS on a
|
|
689
|
+
// node_modules link that points outside the worktree root. Surface a warning
|
|
690
|
+
// (not a failure — the link is still correct for build/typecheck) so a worker
|
|
691
|
+
// or operator doing dev-server work knows the workaround up front. A full
|
|
692
|
+
// Turbopack-compatible per-worktree dependency mode is a planned follow-up.
|
|
693
|
+
const linkedNodeModules = sharedPaths.some((p) => p === 'node_modules' || p.endsWith('/node_modules'));
|
|
694
|
+
if (linkedNodeModules && projectUsesNextjs(mainWorktreePath)) {
|
|
695
|
+
const msg = 'Next.js detected: node_modules is linked as an out-of-worktree-root symlink, which '
|
|
696
|
+
+ '`next dev` / Turbopack rejects (it requires node_modules under the worktree root). '
|
|
697
|
+
+ 'tsc / vitest / build are unaffected. For dev-server work in this worktree, run '
|
|
698
|
+
+ '`npm install` here (optionally with BRAINCLAW_NO_LINK_DEPS=1), or smoke-test on the merged branch.';
|
|
699
|
+
symlinkWarnings.push(msg);
|
|
700
|
+
logger.warn(`[worktree] ${msg}`);
|
|
701
|
+
}
|
|
613
702
|
// NOTE: .brainclaw/ is intentionally NOT symlinked.
|
|
614
703
|
// Symlinking .brainclaw/ causes hooks and session_start to trigger on the
|
|
615
704
|
// shared store, creating session conflicts and potentially blocking agents
|
package/dist/facts.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Generated by scripts/emit-site-facts.mjs at build time. Do not edit manually.
|
|
2
|
-
// Source: brainclaw v1.
|
|
2
|
+
// Source: brainclaw v1.16.0 on 2026-07-18T18:21:20.312Z
|
|
3
3
|
export const FACTS = {
|
|
4
|
-
"version": "1.
|
|
5
|
-
"generated_at": "2026-07-
|
|
4
|
+
"version": "1.16.0",
|
|
5
|
+
"generated_at": "2026-07-18T18:21:20.312Z",
|
|
6
6
|
"tools": {
|
|
7
7
|
"count": 67,
|
|
8
|
-
"published_count":
|
|
8
|
+
"published_count": 65,
|
|
9
9
|
"names": [
|
|
10
10
|
"bclaw_bootstrap",
|
|
11
11
|
"bclaw_release_notes",
|
|
@@ -77,7 +77,7 @@ export const FACTS = {
|
|
|
77
77
|
]
|
|
78
78
|
},
|
|
79
79
|
"entities": {
|
|
80
|
-
"count":
|
|
80
|
+
"count": 18,
|
|
81
81
|
"names": [
|
|
82
82
|
"plan",
|
|
83
83
|
"step",
|
|
@@ -95,6 +95,7 @@ export const FACTS = {
|
|
|
95
95
|
"assignment",
|
|
96
96
|
"agent_run",
|
|
97
97
|
"action",
|
|
98
|
+
"agent",
|
|
98
99
|
"cross_project_link"
|
|
99
100
|
],
|
|
100
101
|
"short_label_prefixes": {
|
|
@@ -114,6 +115,7 @@ export const FACTS = {
|
|
|
114
115
|
"assignment": "asgn",
|
|
115
116
|
"agent_run": "run",
|
|
116
117
|
"action": "act",
|
|
118
|
+
"agent": "agt",
|
|
117
119
|
"cross_project_link": "xpl"
|
|
118
120
|
}
|
|
119
121
|
},
|
|
@@ -472,7 +474,7 @@ export const FACTS = {
|
|
|
472
474
|
},
|
|
473
475
|
"bench": {
|
|
474
476
|
"schema": "brainclaw.bench.v1",
|
|
475
|
-
"generated_at": "2026-07-
|
|
477
|
+
"generated_at": "2026-07-18T18:21:18.026Z",
|
|
476
478
|
"node_version": "v24.18.0",
|
|
477
479
|
"platform": "linux-x64",
|
|
478
480
|
"repeats": 3,
|
|
@@ -481,15 +483,15 @@ export const FACTS = {
|
|
|
481
483
|
"name": "cold_onboard",
|
|
482
484
|
"volume": "empty",
|
|
483
485
|
"description": "fresh machine → init → first useful context. Baseline for time-to-first-value.",
|
|
484
|
-
"duration_ms_median":
|
|
485
|
-
"payload_chars_median":
|
|
486
|
-
"payload_tokens_est_median":
|
|
486
|
+
"duration_ms_median": 82,
|
|
487
|
+
"payload_chars_median": 1640,
|
|
488
|
+
"payload_tokens_est_median": 410
|
|
487
489
|
},
|
|
488
490
|
{
|
|
489
491
|
"name": "warm_work",
|
|
490
492
|
"volume": "medium",
|
|
491
493
|
"description": "bclaw_work consult over a real-shaped store (~200 plans / 500 handoffs / 450 claims).",
|
|
492
|
-
"duration_ms_median":
|
|
494
|
+
"duration_ms_median": 146,
|
|
493
495
|
"payload_chars_median": 2626,
|
|
494
496
|
"payload_tokens_est_median": 657
|
|
495
497
|
},
|
|
@@ -497,7 +499,7 @@ export const FACTS = {
|
|
|
497
499
|
"name": "first_edit",
|
|
498
500
|
"volume": "medium",
|
|
499
501
|
"description": "code_find + code_brief on the fresh-agent path (missing index, first touch).",
|
|
500
|
-
"duration_ms_median":
|
|
502
|
+
"duration_ms_median": 9,
|
|
501
503
|
"payload_chars_median": 442,
|
|
502
504
|
"payload_tokens_est_median": 111
|
|
503
505
|
}
|
package/dist/facts.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"generated_at": "2026-07-
|
|
2
|
+
"version": "1.16.0",
|
|
3
|
+
"generated_at": "2026-07-18T18:21:20.312Z",
|
|
4
4
|
"tools": {
|
|
5
5
|
"count": 67,
|
|
6
|
-
"published_count":
|
|
6
|
+
"published_count": 65,
|
|
7
7
|
"names": [
|
|
8
8
|
"bclaw_bootstrap",
|
|
9
9
|
"bclaw_release_notes",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
77
|
"entities": {
|
|
78
|
-
"count":
|
|
78
|
+
"count": 18,
|
|
79
79
|
"names": [
|
|
80
80
|
"plan",
|
|
81
81
|
"step",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"assignment",
|
|
94
94
|
"agent_run",
|
|
95
95
|
"action",
|
|
96
|
+
"agent",
|
|
96
97
|
"cross_project_link"
|
|
97
98
|
],
|
|
98
99
|
"short_label_prefixes": {
|
|
@@ -112,6 +113,7 @@
|
|
|
112
113
|
"assignment": "asgn",
|
|
113
114
|
"agent_run": "run",
|
|
114
115
|
"action": "act",
|
|
116
|
+
"agent": "agt",
|
|
115
117
|
"cross_project_link": "xpl"
|
|
116
118
|
}
|
|
117
119
|
},
|
|
@@ -470,7 +472,7 @@
|
|
|
470
472
|
},
|
|
471
473
|
"bench": {
|
|
472
474
|
"schema": "brainclaw.bench.v1",
|
|
473
|
-
"generated_at": "2026-07-
|
|
475
|
+
"generated_at": "2026-07-18T18:21:18.026Z",
|
|
474
476
|
"node_version": "v24.18.0",
|
|
475
477
|
"platform": "linux-x64",
|
|
476
478
|
"repeats": 3,
|
|
@@ -479,15 +481,15 @@
|
|
|
479
481
|
"name": "cold_onboard",
|
|
480
482
|
"volume": "empty",
|
|
481
483
|
"description": "fresh machine → init → first useful context. Baseline for time-to-first-value.",
|
|
482
|
-
"duration_ms_median":
|
|
483
|
-
"payload_chars_median":
|
|
484
|
-
"payload_tokens_est_median":
|
|
484
|
+
"duration_ms_median": 82,
|
|
485
|
+
"payload_chars_median": 1640,
|
|
486
|
+
"payload_tokens_est_median": 410
|
|
485
487
|
},
|
|
486
488
|
{
|
|
487
489
|
"name": "warm_work",
|
|
488
490
|
"volume": "medium",
|
|
489
491
|
"description": "bclaw_work consult over a real-shaped store (~200 plans / 500 handoffs / 450 claims).",
|
|
490
|
-
"duration_ms_median":
|
|
492
|
+
"duration_ms_median": 146,
|
|
491
493
|
"payload_chars_median": 2626,
|
|
492
494
|
"payload_tokens_est_median": 657
|
|
493
495
|
},
|
|
@@ -495,7 +497,7 @@
|
|
|
495
497
|
"name": "first_edit",
|
|
496
498
|
"volume": "medium",
|
|
497
499
|
"description": "code_find + code_brief on the fresh-agent path (missing index, first touch).",
|
|
498
|
-
"duration_ms_median":
|
|
500
|
+
"duration_ms_median": 9,
|
|
499
501
|
"payload_chars_median": 442,
|
|
500
502
|
"payload_tokens_est_median": 111
|
|
501
503
|
}
|
package/docs/PROTOCOL.md
CHANGED
|
@@ -131,9 +131,13 @@ offered → accepted → started → (progress)* → completed
|
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
Each transition is emitted via `transition('assignment', id, <status>)`.
|
|
134
|
-
A worker
|
|
135
|
-
|
|
136
|
-
coordinator
|
|
134
|
+
A worker MAY drop a `LANE-RESULT.json` file at the worktree root and let the
|
|
135
|
+
coordinator harvest it instead of emitting transitions itself. This is the
|
|
136
|
+
coordinator-owned contract for a sandboxed worker: its sandbox makes `.git`
|
|
137
|
+
read-only (so it cannot `git commit`), and the file is the harvestable signal —
|
|
138
|
+
NOT because MCP is unreachable (a sandboxed worker does reach the MCP server,
|
|
139
|
+
which runs out-of-process; dec#133). A genuinely MCP-less agent uses the same
|
|
140
|
+
file as its only channel.
|
|
137
141
|
|
|
138
142
|
### 5.3 Claim sentinels
|
|
139
143
|
|
|
@@ -41,6 +41,9 @@ worker presumed dead
|
|
|
41
41
|
│
|
|
42
42
|
├─ 1. LANE-RESULT.json at the worktree root?
|
|
43
43
|
│ yes → it FINISHED. `brainclaw harvest <asgn> [--integrate]`. Done.
|
|
44
|
+
│ (review lane: a `review_verdict` in the file is mapped onto the review
|
|
45
|
+
│ loop by harvest — a `verdict` artifact is recorded and the loop
|
|
46
|
+
│ auto-closes on `approve`; no manual bclaw_loop drive needed.)
|
|
44
47
|
│
|
|
45
48
|
├─ 2. git evidence (shared helper: commits_ahead + dirty_tracked,
|
|
46
49
|
│ surfaced by dispatch-status / dispatch watch):
|
|
@@ -152,16 +152,16 @@ You called `bclaw_coordinate(intent="review", open_loop=true, …)` and got back
|
|
|
152
152
|
|
|
153
153
|
## Worktree-as-contract harvest
|
|
154
154
|
|
|
155
|
-
Some dispatched workers cannot self-commit
|
|
155
|
+
Some dispatched workers cannot self-commit. For example, a sandboxed Codex run has `dispatchCanCommit=false` because its writable root is the linked worktree, while `.git` lives outside that root — so it cannot `git commit`. (It *can* still call brainclaw MCP — dec#133 — but the file-based contract below is used regardless, so harvesting stays coordinator-owned and does not depend on the worker's MCP writes.) In that case the worker contract is intentionally small:
|
|
156
156
|
|
|
157
157
|
1. Edit files inside the dispatched worktree.
|
|
158
|
-
2. Write `LANE-RESULT.json` at the worktree root.
|
|
158
|
+
2. Write `LANE-RESULT.json` at the worktree root — `{ assignment_id, status: completed|blocked|failed, summary, files_changed?, artifacts?, notes? }`. For a **review** lane, the worker also sets `review_verdict` (`approve` | `request_changes`) and `review_summary`; harvest maps those onto the review loop and auto-closes it on `approve` (pln#628 Focus 4B — see [loop-engine.md](./loop-engine.md#automation-extending-bclaw_coordinateintentreview)).
|
|
159
159
|
|
|
160
160
|
The worker does not need to commit, call `bclaw_assignment_update`, or release the claim itself. The worktree is the contract.
|
|
161
161
|
|
|
162
162
|
When the coordinator runs `brainclaw harvest <assignment_id> --integrate`, brainclaw reads the worker's `LANE-RESULT.json`, commits the linked worktree diff on the worker's behalf onto the lane branch, then completes the assignment and releases the claim, including the normal plan-status cascade.
|
|
163
163
|
|
|
164
|
-
The on-behalf commit is guarded by the linked-worktree check (`isLinkedWorktree`): integration only targets the worktree associated with the assignment, never the main repository. This keeps sandboxed-worker harvesting from turning into an accidental main-repo commit path.
|
|
164
|
+
The on-behalf commit is guarded by the linked-worktree check (`isLinkedWorktree`): integration only targets the worktree associated with the assignment, never the main repository. This keeps sandboxed-worker harvesting from turning into an accidental main-repo commit path. It also excludes brainclaw's own transient/provisioned files from the lane commit — `LANE-RESULT.json`, `.brainclaw/`, `.brainclaw-worktree.json`, heartbeat files, and the `node_modules` link(s) brainclaw provisions (top-level + monorepo `**/node_modules`). The `node_modules` exclusion is tracked-aware: a project that *vendors* (commits) `node_modules` keeps a worker's change to a tracked file — only the freshly-provisioned link/dir is dropped.
|
|
165
165
|
|
|
166
166
|
Integration is strictly additive and opt-in. Plain `brainclaw harvest <assignment_id>` remains report-only; it reads and reports the lane result without committing or mutating assignment / claim state. The on-behalf commit and lifecycle completion happen only when the coordinator passes `--integrate`.
|
|
167
167
|
|
|
@@ -255,7 +255,7 @@ A dead dispatch needs four cleanup steps (no single facade does all of them toda
|
|
|
255
255
|
|
|
256
256
|
Spawn behaviour varies by agent. The capability profile in `src/core/agent-capability.ts` describes each agent's prompt delivery, sandbox model, and MCP availability. Per-agent caveats:
|
|
257
257
|
|
|
258
|
-
- [codex.md](../integrations/codex.md#caveats) — `--sandbox workspace-write` required;
|
|
258
|
+
- [codex.md](../integrations/codex.md#caveats) — `--sandbox workspace-write` required; sandboxed codex reaches MCP but cannot `git commit` (dec#133 — coordinator harvests the worktree diff); stdin_pipe prompt delivery; brief-ack required for headless dispatch detection.
|
|
259
259
|
- [claude-code.md](../integrations/claude-code.md) — interactive vs `-p` headless modes; tools whitelist.
|
|
260
260
|
- [copilot.md](../integrations/copilot.md), [windsurf.md](../integrations/windsurf.md), [cline.md](../integrations/cline.md), [opencode.md](../integrations/opencode.md), [roo.md](../integrations/roo.md), [kilocode.md](../integrations/kilocode.md), [continue.md](../integrations/continue.md) — per-agent specifics.
|
|
261
261
|
- [mistral-vibe.md](../integrations/mistral-vibe.md) — EU/GDPR self-hosted option.
|
|
@@ -332,6 +332,8 @@ When `bclaw_coordinate(intent='review', open_loop: true)` is called, it:
|
|
|
332
332
|
5. On turn completion with a verdict artifact, auto-advances; `reviewer_green` stop closes.
|
|
333
333
|
6. On non-green verdict with `iteration_count < max`, advances to `author_response`, dispatches to author.
|
|
334
334
|
|
|
335
|
+
**How the verdict reaches the loop (shipped, pln#628 Focus 4B).** A dispatched reviewer worker does not call `bclaw_loop` itself — it writes its outcome to `LANE-RESULT.json` at the worktree root, now including an optional `review_verdict` (`approve` | `request_changes`) and `review_summary`. When the coordinator runs `brainclaw harvest <assignment_id>` (both the report-only path and `--integrate`), a review lane carrying a `review_verdict` is mapped onto its loop: brainclaw records a `verdict` artifact on the reviewer slot (`approve` → an `accepted…` body) and calls `advance`, which **auto-closes the loop on `reviewer_green` for `approve`** — no human driving `complete_turn`/`advance`. `request_changes` records the verdict and advances to `author_response` (the automated fix→re-review cycle is a follow-up). The mapping is idempotent, resolves the reviewer slot strictly by `assignment_id` (so symmetric multi-reviewer loops target the right slot), and runs the `complete_turn`+`advance` pair under the loop lock so an interrupted pass resumes rather than stalls.
|
|
336
|
+
|
|
335
337
|
### Symmetric review-AND-fix mode
|
|
336
338
|
|
|
337
339
|
By default, the phases `findings` and `author_response` follow the classical asymmetric split — the reviewer identifies issues, the author applies fixes on the next turn. That doubles the number of round-trips: every issue needs one full turn to be identified, then another to be fixed.
|
|
@@ -514,7 +516,7 @@ Status after Codex schema review (cnd#574 / `dec_be66ccbf`, verdict `needs_revis
|
|
|
514
516
|
|
|
515
517
|
The loop surface exposed over MCP is intentionally narrow:
|
|
516
518
|
|
|
517
|
-
- **Review loops** — `bclaw_coordinate(intent="review", open_loop=true, review_mode="asymmetric"|"symmetric", targetAgents=[…])` opens the loop and dispatches the first turn.
|
|
519
|
+
- **Review loops** — `bclaw_coordinate(intent="review", open_loop=true, review_mode="asymmetric"|"symmetric", targetAgents=[…])` opens the loop and dispatches the first turn. The reviewer's verdict is then harvested from `LANE-RESULT.json` (`review_verdict`) and **auto-advances/closes the loop on approve** — no manual driving needed for the approve path (pln#628 Focus 4B). `bclaw_loop(intent="turn"|"complete_turn"|"advance"|"close")` remains available to drive turns by hand (e.g. the `request_changes` fix cycle, or a human-operated slot).
|
|
518
520
|
- **Ideation loops** — `bclaw_coordinate(intent="ideate", preset="bootstrap")` opens an ideation loop from a preset.
|
|
519
521
|
|
|
520
522
|
Custom phase lists (`LoopPhase[]`) and bespoke `StopCondition` logic exist in the loop engine internally, but are **not** exposed through the MCP facade today: `CoordinateRequestSchema` accepts only `open_loop`, `review_mode`, `preflight`, `ref`, and `preset` — no `phases` or `stop_condition` — and the standalone `bclaw_loop` tool does not expose an `open` intent. Programmatic construction of ad-hoc loops is therefore internal / future work until the facade is extended.
|
|
@@ -206,7 +206,7 @@ brainclaw stale resolve <plan_id> # → dropped (default for stale)
|
|
|
206
206
|
|
|
207
207
|
**Symptom**: a dispatched assignment shows `running` indefinitely, and `bclaw_assignment_events` shows `run_running` but no further progress.
|
|
208
208
|
|
|
209
|
-
**Why**: the spawned worker process either (a) crashed before reading its inbox, (b)
|
|
209
|
+
**Why**: the spawned worker process either (a) crashed before reading its inbox, (b) started but the brief-ack sentinel never fired (spawn wrapper died, wrong CODEX_HOME/auth, or the CLI exited early — NOT because the sandbox blocks MCP: dec#133 shows a sandboxed codex reaches MCP fine), or (c) is genuinely still working but slow.
|
|
210
210
|
|
|
211
211
|
**Diagnostic order**:
|
|
212
212
|
|
|
@@ -43,7 +43,7 @@ Codex is CLI-spawnable for parallel lanes and dispatched workflows. The canonica
|
|
|
43
43
|
codex exec -c approval_policy="never" --sandbox workspace-write "{prompt}"
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
The `--sandbox workspace-write` setting is required, **not `read-only`** — the
|
|
46
|
+
The `--sandbox workspace-write` setting is required, **not `read-only`** — the worker needs to write files in its own worktree (the edits it produces, plus its `LANE-RESULT.json`) so the coordinator has a harvestable diff. This is about the worker's *file* writes, not MCP: the brainclaw MCP server runs out-of-sandbox and is reachable under either sandbox mode (dec#133). What the sandbox does block is `git commit` (`.git` is outside the writable root), so the coordinator commits the worktree diff at harvest.
|
|
47
47
|
|
|
48
48
|
### Prompt delivery: stdin_pipe (preferred)
|
|
49
49
|
|
|
@@ -53,7 +53,7 @@ When you (or the dispatcher) calls Codex with no positional `[PROMPT]`, Codex re
|
|
|
53
53
|
|
|
54
54
|
### Brief-ack handshake
|
|
55
55
|
|
|
56
|
-
Since pln#476 (1.0.13+), spawned Codex workers are marked `delivered_and_started` once the wrapping shell touches a brief-ack sentinel at `.brainclaw/coordination/runtime/ack/<assignmentId>.ack`. This proves the spawn actually executed and decouples the handshake from
|
|
56
|
+
Since pln#476 (1.0.13+), spawned Codex workers are marked `delivered_and_started` once the wrapping shell touches a brief-ack sentinel at `.brainclaw/coordination/runtime/ack/<assignmentId>.ack`. This proves the spawn actually executed and decouples the handshake from whatever the worker does next — the spawn is confirmed even before the worker makes its first MCP call. (Note — dec#133: a sandboxed Codex run **does** reach brainclaw MCP; the server runs out-of-sandbox and `approval_policy=never` auto-approves. The sentinel is about confirming the spawn, not about MCP being unavailable.)
|
|
57
57
|
|
|
58
58
|
## Capability profile
|
|
59
59
|
|
|
@@ -72,7 +72,7 @@ Since pln#476 (1.0.13+), spawned Codex workers are marked `delivered_and_started
|
|
|
72
72
|
|
|
73
73
|
## Caveats
|
|
74
74
|
|
|
75
|
-
- **Sandbox blocks MCP
|
|
75
|
+
- **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.
|
|
76
76
|
- **Windows quoting**: long prompts containing backticks or `#` fail when passed as inline args through `cmd.exe`. The default stdin_pipe path avoids this.
|
|
77
77
|
- **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).
|
|
78
78
|
- **No always-allow**: each MCP tool call still respects per-call approval policy unless explicitly set with `-c approval_policy="never"`.
|
|
@@ -103,7 +103,7 @@ The developer can dial back individual surfaces if needed, but the default is fu
|
|
|
103
103
|
|
|
104
104
|
brainclaw's store mutations are serialized (MCP single-writer queue + file-based lock), so memory writes are safe even under contention.
|
|
105
105
|
|
|
106
|
-
For **parallel work**, dispatch a sequence with `bclaw_dispatch(intent="execute")` — each lane gets its own auto-worktree under `~/.brainclaw/worktrees/<project-hash>/`, and the coordinator integrates with an octopus merge. For **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. These are the supported parallel paths today.
|
|
106
|
+
For **parallel work**, dispatch a sequence with `bclaw_dispatch(intent="execute")` — each lane gets its own auto-worktree under `~/.brainclaw/worktrees/<project-hash>/`, and the coordinator integrates with an octopus merge. For **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 — and the loop **auto-closes on reviewer approve** (the verdict is harvested from `LANE-RESULT.json`, no manual drive). These are the supported parallel paths today.
|
|
107
107
|
|
|
108
108
|
For **sequential work** in the same project, let one agent claim at a time and rely on handoffs to keep continuity across sessions.
|
|
109
109
|
|
|
@@ -10,6 +10,122 @@ guarantees this changelog follows.
|
|
|
10
10
|
|
|
11
11
|
## Unreleased
|
|
12
12
|
|
|
13
|
+
**Added — `LaneResultSchema.review_verdict` / `review_summary` (pln#628 Focus 4B)**
|
|
14
|
+
- `LANE-RESULT.json` (the worktree-root file a dispatched worker writes) gains two
|
|
15
|
+
optional fields: `review_verdict` (`approve` | `request_changes`) and
|
|
16
|
+
`review_summary` (one-line rationale). Absent on non-review lanes.
|
|
17
|
+
- Consumed by `brainclaw harvest` (report path + `--integrate`): a review lane
|
|
18
|
+
carrying a `review_verdict` is mapped onto its review loop — a `verdict` artifact
|
|
19
|
+
is recorded and the loop advances, auto-closing on `reviewer_green` for
|
|
20
|
+
`approve`. Additive + backward-compatible; no tool added/removed/renamed and no
|
|
21
|
+
surface-fingerprint change (LaneResultSchema is not part of the read/write
|
|
22
|
+
contract fingerprint).
|
|
23
|
+
|
|
24
|
+
**Added — `bclaw_update(entity='handoff')` incl. review/contract (pln#625 Phase 3)**
|
|
25
|
+
- The handoff update path is now wired. Previously `bclaw_update(entity='handoff')`
|
|
26
|
+
fell through to "not yet wired" (the field check passed for narrative/tags but
|
|
27
|
+
there was no handler case). `handoff.updatable` now also includes `review` and
|
|
28
|
+
`contract`, each validated against `HandoffReviewSchema` / `HandoffContractSchema`
|
|
29
|
+
and merged onto the record.
|
|
30
|
+
- This **restores the review-state write capability lost at v1.0** when
|
|
31
|
+
`bclaw_update_handoff` was removed: an agent can write a review verdict via
|
|
32
|
+
`bclaw_update(entity='handoff', data={ review: { verdict, summary, … } })`.
|
|
33
|
+
A verdict auto-stamps `review.reviewed_at`. The review loop's core
|
|
34
|
+
(`applyHandoffUpdates`) is unchanged — this is the canonical-grammar front door
|
|
35
|
+
onto the same record.
|
|
36
|
+
- Tip guard: a superseded (tombstoned) handoff is refused, pointing at the tip.
|
|
37
|
+
- No tool added/removed/renamed; `updatable` is not part of the surface
|
|
38
|
+
fingerprint, so no fingerprint change.
|
|
39
|
+
|
|
40
|
+
**Removed — `bclaw_list_agents` (pln#625; migrate to `bclaw_find(entity='agent')`)**
|
|
41
|
+
- `bclaw_list_agents` — the last surviving `bclaw_list_*` tool — is retired into
|
|
42
|
+
`REMOVED_IN_V1_TOOLS`: hidden from every `tools/list`, with a direct-call
|
|
43
|
+
deprecation warning pointing at `bclaw_find(entity='agent')`. The handler
|
|
44
|
+
stays as a redacted read escape-hatch (`LEGACY_READ_TOOL_HANDLERS`), same as
|
|
45
|
+
its `list_*` siblings.
|
|
46
|
+
- To preserve its one unique capability, `bclaw_find(entity='agent')` gains an
|
|
47
|
+
agent-only `includeReputation` filter that attaches the public reputation
|
|
48
|
+
summary per agent (same join the CLI `list-agents --with-reputation` uses).
|
|
49
|
+
- Net surface coherence: `agent` reads now flow through one grammar path with a
|
|
50
|
+
single redacted projection (`projectAgentForRead`), closing the divergent
|
|
51
|
+
double-surface (the old tool leaked raw `identity_key`/`invoke.env`).
|
|
52
|
+
|
|
53
|
+
**Changed — governance guard now covers grammar entities AND the filter contract (pln#625)**
|
|
54
|
+
- `tests/unit/mcp-governance.test.ts` folds two free-form parts of the callable
|
|
55
|
+
contract into the public-surface fingerprint: the set of addressable grammar
|
|
56
|
+
entities (`ENTITY_NAMES`) and the find/get filter grammar
|
|
57
|
+
(`GRAMMAR_FILTER_CONTRACT` — accepted keys, entity-scoping, constrained
|
|
58
|
+
values). Both were previously invisible (the `entity` and `filter` args are
|
|
59
|
+
free-form and their enumerating descriptions are stripped), so wiring a new
|
|
60
|
+
`bclaw_find/get(entity='…')` target or adding/re-scoping/re-valuing a filter
|
|
61
|
+
key (e.g. the Phase 2c `scope`) could ship without a changelog entry.
|
|
62
|
+
- `GRAMMAR_FILTER_CONTRACT` (exported from `entity-operations.ts`) is now the
|
|
63
|
+
single source of truth for the handler's filter validation AND the
|
|
64
|
+
fingerprint, so the two can never drift. A mutation test proves the
|
|
65
|
+
fingerprint reacts to an added entity, key, re-scope, and new value.
|
|
66
|
+
- Closes the blind spot surfaced by the Phase 2c ideation loop; the filter-grammar
|
|
67
|
+
extension came from the Codex review of PR #82.
|
|
68
|
+
|
|
69
|
+
**Added — read-only `agent` entity in the canonical grammar (pln#625 Phase 2c)**
|
|
70
|
+
- `bclaw_find/get(entity='agent')` are now wired. They return a REDACTED,
|
|
71
|
+
read-only projection: `id`, `name`, `kind`, `trust_level`, `capabilities`,
|
|
72
|
+
`fingerprint` (full sha256(PEM) — the public canonical key id), `model`,
|
|
73
|
+
`context_profile`, `created_at`. The private key material (`identity_key`,
|
|
74
|
+
`public_key` PEM) and `invoke` (unpopulated dead field; would leak
|
|
75
|
+
`invoke.command`) are never surfaced. Writes (`create/update/remove/transition`)
|
|
76
|
+
return the `SystemManagedError` boundary — agents are managed via
|
|
77
|
+
`bclaw_setup` / `enable-agent`, not the grammar.
|
|
78
|
+
- New agent-only filter `scope`: `bclaw_find(entity='agent')` defaults to the
|
|
79
|
+
current project's registry; `filter.scope='global'` additionally unions the
|
|
80
|
+
static dispatchable catalog (`getSpawnableAgents`) and annotates each entry
|
|
81
|
+
with `dispatchable` (canBeSpawnedCli) + `registered`. `scope` is rejected for
|
|
82
|
+
any other entity, and its value must be `project` (default) or `global`.
|
|
83
|
+
- `bclaw_list_agents` now redacts through the SAME projection (one source of
|
|
84
|
+
truth). It previously spread the raw identity document, leaking
|
|
85
|
+
`identity_key.public_key` and `invoke.env` in the clear — a pre-existing
|
|
86
|
+
disclosure, now closed. `includeReputation` still attaches the reputation
|
|
87
|
+
add-on.
|
|
88
|
+
- This supersedes the Phase 1a stopgap that reported `agent` as "not addressable
|
|
89
|
+
via the canonical grammar" (never released; last tag v1.15.0).
|
|
90
|
+
|
|
91
|
+
**Fixed — `bclaw_transition(entity='handoff')` wired (pln#625 Phase 2a)**
|
|
92
|
+
- The handoff lifecycle (`open→accepted|closed`, `accepted→closed`) is now
|
|
93
|
+
wired. It previously fell to the "not yet wired" default, which also broke
|
|
94
|
+
`brainclaw stale resolve <handoff-id>` (that command routes through the
|
|
95
|
+
canonical transition). A tip guard refuses to transition a handoff carrying
|
|
96
|
+
`superseded_by` (an immutable correction tombstone) and points at the tip.
|
|
97
|
+
- No tool was added, removed, or renamed; no required argument changed.
|
|
98
|
+
|
|
99
|
+
**Fixed — `bclaw_coordinate` published-schema parity (pln#622 PR0b)**
|
|
100
|
+
- The published inputSchema of `bclaw_coordinate` now declares `preset`
|
|
101
|
+
(loop preset selector, valid only with `intent='ideate'`; v1 ships the
|
|
102
|
+
single preset `bootstrap`; unknown names are rejected with
|
|
103
|
+
`unknown_preset`, other intents with `preset_kind_mismatch`) and
|
|
104
|
+
`client_request_id` (caller-minted ULID/UUIDv7 for idempotent retries,
|
|
105
|
+
observed on `intent='review'` + `open_loop=true`, safe elsewhere). Both
|
|
106
|
+
were already accepted by `CoordinateRequestSchema` and used by the
|
|
107
|
+
handler — and `next_actions` literally recommended
|
|
108
|
+
`bclaw_coordinate(intent='ideate', preset='bootstrap')` — but the catalog
|
|
109
|
+
never declared them, so strict MCP clients could not follow the product's
|
|
110
|
+
own recommendation.
|
|
111
|
+
- New guard: `tests/unit/mcp-facade-structural-parity.test.ts` asserts
|
|
112
|
+
bidirectional structural parity (keys + shared enum values) between the
|
|
113
|
+
hand-written facade schemas (`bclaw_work`, `bclaw_coordinate`) and their
|
|
114
|
+
zod sources, with an explicit allowlist for adapter-envelope fields
|
|
115
|
+
(`agent`, `agentId`).
|
|
116
|
+
- No tool was added, removed, or renamed; no required argument changed.
|
|
117
|
+
- Surface fingerprint bumped in the `(current)` section below.
|
|
118
|
+
|
|
119
|
+
**Changed — MCP model selection parity (pln#520/#606)**
|
|
120
|
+
- `bclaw_dispatch` and `bclaw_coordinate` gain an optional `model` string that
|
|
121
|
+
selects the spawned worker's model (e.g. `sonnet`, `gpt-5-codex`), decoupled
|
|
122
|
+
from agent identity — closing the CLI/MCP gap (the CLI `dispatch run --model`
|
|
123
|
+
already existed). Injected only for agents that declare a `model_flag`
|
|
124
|
+
(claude-code / codex / github-copilot); no-op otherwise, and consistent with
|
|
125
|
+
the dispatcher's resolveModel chain.
|
|
126
|
+
- No tool was removed or renamed; no required argument changed.
|
|
127
|
+
- Surface fingerprint bumped in the `(current)` section below.
|
|
128
|
+
|
|
13
129
|
**Added — `bclaw_move` cross-project relocation (pln#595)**
|
|
14
130
|
- New canonical-grammar verb `bclaw_move(entity, id, to_project, from_project?, force?)`:
|
|
15
131
|
relocates a brainclaw item to another project in a multi-project workspace,
|
|
@@ -122,8 +238,43 @@ will still succeed. A follow-up PR will strip the dead handler code.
|
|
|
122
238
|
changelog records the published MCP surface fingerprint. When a tool
|
|
123
239
|
name, tier, category, or input schema changes, the test fails until
|
|
124
240
|
this section is updated.
|
|
125
|
-
- MCP public surface fingerprint: `sha256:
|
|
126
|
-
(updated 2026-07-
|
|
241
|
+
- MCP public surface fingerprint: `sha256:468f0103414e97e8`
|
|
242
|
+
(updated 2026-07-18 for pln#625 PR #83 + Codex review: `bclaw_list_agents`
|
|
243
|
+
retired and `bclaw_find(entity='agent')` gains `includeReputation` — now typed
|
|
244
|
+
as a boolean in `GRAMMAR_FILTER_CONTRACT.booleanKeys` and validated at the MCP
|
|
245
|
+
front door, so a non-boolean value is rejected instead of silently coercing to
|
|
246
|
+
a no-op. The added boolean-type declaration moves the fingerprint.)
|
|
247
|
+
Previous: `sha256:be0df1e4cc33936f`
|
|
248
|
+
(updated 2026-07-17 for pln#625 PR #83: `bclaw_list_agents` retired from the
|
|
249
|
+
published surface — migrated to `bclaw_find(entity='agent')` which gains an
|
|
250
|
+
agent-only `includeReputation` filter. Both the removed tool and the new
|
|
251
|
+
filter key move the fingerprint via the guard now covering PUBLISHED_TOOLS +
|
|
252
|
+
ENTITY_NAMES + GRAMMAR_FILTER_CONTRACT.)
|
|
253
|
+
Previous: `sha256:e12fd2f34dae1ac0`
|
|
254
|
+
(updated 2026-07-17 for pln#625 Phase 2c + PR #82: the fingerprint now folds in
|
|
255
|
+
two parts of the callable contract that the tool inputSchema cannot express —
|
|
256
|
+
the set of grammar-addressable entities (`ENTITY_NAMES`) and the find/get
|
|
257
|
+
filter grammar (`GRAMMAR_FILTER_CONTRACT`: accepted keys, entity-scoping, and
|
|
258
|
+
constrained values such as `scope=project|global`). Both were invisible to the
|
|
259
|
+
fingerprint before (`entity` and `filter` are free-form and their enumerating
|
|
260
|
+
descriptions are stripped), so wiring a new addressable entity — or adding /
|
|
261
|
+
re-scoping / re-valuing a filter key like the Phase 2c `scope` — slipped past
|
|
262
|
+
this guard. Additive: no tool added, removed, or renamed.)
|
|
263
|
+
Previous: `sha256:45c02576aff36244`
|
|
264
|
+
(updated 2026-07-15 for pln#622 PR0b: `preset` and `client_request_id` added
|
|
265
|
+
to the published `bclaw_coordinate` input schema. Both were already accepted
|
|
266
|
+
by `CoordinateRequestSchema` and used by the handler — and `next_actions`
|
|
267
|
+
recommended `bclaw_coordinate(intent='ideate', preset='bootstrap')` — but
|
|
268
|
+
the catalog never declared them. Additive: no tool added, removed, or
|
|
269
|
+
renamed; no required argument changed.
|
|
270
|
+
Previous: `sha256:b53eb56d4391b5a6`
|
|
271
|
+
updated 2026-07-15 for pln#520/#606: optional `model` string added to
|
|
272
|
+
`bclaw_dispatch` and `bclaw_coordinate` input schemas — selects the spawned
|
|
273
|
+
worker's model, decoupled from agent identity (CLI/MCP parity with
|
|
274
|
+
`dispatch run --model`). Additive: no tool added, removed, or renamed; no
|
|
275
|
+
required argument changed.
|
|
276
|
+
Previous: `sha256:2b0dfbd62acd71b7`
|
|
277
|
+
updated 2026-07-04 for trp#928: explicit `coordinator_override` boolean added
|
|
127
278
|
to `bclaw_release_claim` and `bclaw_transition` input schemas — the coordinator
|
|
128
279
|
path to release/stale a non-owned claim is now opt-in and audited rather than
|
|
129
280
|
auto-derived from trust level. Additive: no tool added, removed, or renamed; no
|
|
@@ -24,7 +24,7 @@ With the plan and sequences established, assign the work to execution agents.
|
|
|
24
24
|
|
|
25
25
|
- **Sequence-driven execution:** Use `bclaw_dispatch(intent="execute")` to parallelize plans across your defined sequence lanes automatically.
|
|
26
26
|
- **Direct orchestration:** For ad-hoc delegation, use `bclaw_coordinate(intent="assign")` to assign specific tasks to target agents. This seamlessly generates the necessary claims and dispatch briefs.
|
|
27
|
-
- **Reviews & Loops:** To open a structured review process on completed work, use `bclaw_coordinate(intent="review", open_loop=true)`.
|
|
27
|
+
- **Reviews & Loops:** To open a structured review process on completed work, use `bclaw_coordinate(intent="review", open_loop=true)`. The reviewer's verdict is harvested from its `LANE-RESULT.json` (`review_verdict`) and the loop **auto-closes on approve** — no manual `complete_turn`/`advance` round-trip to close the approve path (pln#628 Focus 4B).
|
|
28
28
|
- Use `bclaw_dispatch_status` to verify worker liveness, examine log tails, and ensure dispatches are progressing healthily.
|
|
29
29
|
|
|
30
30
|
## Step 4: Manage the Inbox
|