brainclaw 1.9.0 → 1.10.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 +631 -499
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +18 -1
- package/dist/commands/code-map.js +129 -0
- package/dist/commands/codev.js +7 -0
- package/dist/commands/harvest.js +1 -1
- package/dist/commands/hooks.js +73 -73
- package/dist/commands/init.js +1 -1
- package/dist/commands/install-hooks.js +78 -78
- package/dist/commands/mcp-read-handlers.js +57 -14
- package/dist/commands/mcp.js +200 -13
- package/dist/commands/run-profile.js +3 -2
- package/dist/commands/switch.js +125 -93
- package/dist/commands/version.js +1 -1
- package/dist/core/agent-capability.js +19 -4
- package/dist/core/agent-files.js +131 -119
- package/dist/core/code-map/backend.js +123 -0
- package/dist/core/code-map/core.js +81 -0
- package/dist/core/code-map/drafts.js +2 -0
- package/dist/core/code-map/extractor.js +29 -0
- package/dist/core/code-map/finalizer.js +191 -0
- package/dist/core/code-map/freshness.js +108 -0
- package/dist/core/code-map/ids.js +0 -0
- package/dist/core/code-map/importable.js +35 -0
- package/dist/core/code-map/indexes.js +197 -0
- package/dist/core/code-map/lang/java/imports.scm +17 -0
- package/dist/core/code-map/lang/java/index.js +254 -0
- package/dist/core/code-map/lang/java/tags.scm +48 -0
- package/dist/core/code-map/lang/php/imports.scm +21 -0
- package/dist/core/code-map/lang/php/index.js +251 -0
- package/dist/core/code-map/lang/php/tags.scm +44 -0
- package/dist/core/code-map/lang/provider.js +9 -0
- package/dist/core/code-map/lang/providers.js +24 -0
- package/dist/core/code-map/lang/python/imports.scm +90 -0
- package/dist/core/code-map/lang/python/index.js +364 -0
- package/dist/core/code-map/lang/python/tags.scm +81 -0
- package/dist/core/code-map/lang/query-runtime.js +374 -0
- package/dist/core/code-map/lang/registry.js +125 -0
- package/dist/core/code-map/lang/typescript/imports.scm +90 -0
- package/dist/core/code-map/lang/typescript/index.js +306 -0
- package/dist/core/code-map/lang/typescript/tags.js.scm +106 -0
- package/dist/core/code-map/lang/typescript/tags.scm +151 -0
- package/dist/core/code-map/lock.js +210 -0
- package/dist/core/code-map/materialized.js +51 -0
- package/dist/core/code-map/memory-reader.js +59 -0
- package/dist/core/code-map/paths.js +53 -0
- package/dist/core/code-map/query.js +568 -0
- package/dist/core/code-map/refresh.js +0 -0
- package/dist/core/code-map/resolve.js +177 -0
- package/dist/core/code-map/store.js +206 -0
- package/dist/core/code-map/types.js +288 -0
- package/dist/core/code-map/vocabulary.js +57 -0
- package/dist/core/code-map/wasm-loader.js +294 -0
- package/dist/core/code-map/work-section.js +206 -0
- package/dist/core/codev-prompts.js +38 -38
- package/dist/core/codev-rounds.js +4 -0
- 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/dispatcher.js +1 -1
- package/dist/core/entity-operations.js +29 -3
- package/dist/core/execution-adapters.js +11 -10
- package/dist/core/execution-profile.js +58 -0
- package/dist/core/execution.js +1 -1
- package/dist/core/facade-schema.js +9 -0
- package/dist/core/instruction-templates.js +2 -0
- package/dist/core/loops/verbs.js +0 -1
- package/dist/core/mcp-command-resolution.js +3 -1
- package/dist/core/messaging.js +2 -2
- package/dist/core/protocol-skills.js +164 -164
- package/dist/core/runtime-signals.js +1 -1
- package/dist/core/search.js +19 -2
- package/dist/core/security-guard.js +207 -207
- package/dist/core/spawn-check.js +16 -2
- package/dist/core/staleness.js +1 -1
- package/dist/core/store-resolution.js +67 -11
- package/dist/core/worktree.js +18 -18
- package/dist/facts.js +9 -5
- package/dist/facts.json +8 -4
- package/dist/vendor/web-tree-sitter/tree-sitter.js +3980 -0
- package/dist/vendor/web-tree-sitter/tree-sitter.wasm +0 -0
- package/dist/wasm/tree-sitter-java.wasm +0 -0
- package/dist/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/wasm/tree-sitter-php.wasm +0 -0
- package/dist/wasm/tree-sitter-python.wasm +0 -0
- package/dist/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/wasm/tree-sitter.wasm +0 -0
- package/docs/PROTOCOL.md +1 -1
- package/docs/adapters/openclaw.md +43 -43
- package/docs/architecture/project-refs.md +328 -328
- package/docs/cli.md +2131 -2093
- package/docs/code-map.md +198 -0
- package/docs/concepts/coordination.md +52 -52
- package/docs/concepts/coordinator-runbook.md +129 -129
- package/docs/concepts/dispatch-lifecycle.md +245 -245
- package/docs/concepts/event-log-store.md +928 -928
- 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 +84 -84
- package/docs/concepts/multi-agent-workflows.md +167 -167
- package/docs/concepts/observer-protocol.md +361 -361
- package/docs/concepts/plans-and-claims.md +217 -217
- package/docs/concepts/project-md-convention.md +35 -35
- package/docs/concepts/runtime-notes.md +38 -38
- package/docs/concepts/troubleshooting.md +254 -254
- package/docs/concepts/workspace-bootstrapping.md +142 -142
- 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 +158 -158
- package/docs/integrations/claude-code.md +23 -23
- package/docs/integrations/cline.md +77 -77
- package/docs/integrations/continue.md +55 -55
- package/docs/integrations/copilot.md +68 -68
- package/docs/integrations/cursor.md +23 -23
- package/docs/integrations/kilocode.md +72 -72
- package/docs/integrations/mcp.md +385 -378
- package/docs/integrations/mistral-vibe.md +122 -122
- package/docs/integrations/openclaw.md +92 -92
- package/docs/integrations/opencode.md +84 -84
- package/docs/integrations/overview.md +115 -115
- package/docs/integrations/roo.md +71 -71
- package/docs/integrations/windsurf.md +77 -77
- package/docs/mcp-schema-changelog.md +364 -356
- 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 +183 -183
- package/docs/release-maintenance.md +79 -79
- package/docs/reputation.md +52 -52
- package/docs/review.md +45 -45
- package/docs/security.md +212 -212
- package/docs/server-operations.md +118 -118
- package/docs/storage.md +106 -106
- package/package.json +86 -66
- package/docs/concepts/event-log-store-critique-A.md +0 -333
- package/docs/concepts/event-log-store-critique-B.md +0 -353
- package/docs/concepts/event-log-store-phase0-measurements.md +0 -58
- package/docs/concepts/event-log-store-proposal-A.md +0 -365
- package/docs/concepts/event-log-store-proposal-B.md +0 -404
- package/docs/concepts/identity-model-proposal.md +0 -371
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import { runListPlans } from './commands/list-plans.js';
|
|
|
19
19
|
import { runUpdatePlan } from './commands/update-plan.js';
|
|
20
20
|
import { runDeletePlan } from './commands/delete-plan.js';
|
|
21
21
|
import { runPlanResource } from './commands/plan-resource.js';
|
|
22
|
+
import { runCodeMap } from './commands/code-map.js';
|
|
22
23
|
import { runSequenceResource } from './commands/sequence.js';
|
|
23
24
|
import { runAddStep } from './commands/add-step.js';
|
|
24
25
|
import { runDeleteStep } from './commands/delete-step.js';
|
|
@@ -598,6 +599,20 @@ program
|
|
|
598
599
|
.action((subcommand, args, options) => {
|
|
599
600
|
runPlanResource(subcommand, args, { ...options, actualEffort: options.actualEffort, localOnly: options.localOnly });
|
|
600
601
|
});
|
|
602
|
+
// --- code-map ---
|
|
603
|
+
program
|
|
604
|
+
.command('code-map <subcommand> [args...]')
|
|
605
|
+
.description('Query the per-project Code Map (status, refresh, find, brief)')
|
|
606
|
+
.option('--json', 'Output as JSON')
|
|
607
|
+
.option('--all', 'For refresh: enumerate all supported files (full refresh)')
|
|
608
|
+
.option('--changed', 'For refresh: only changed files (default)')
|
|
609
|
+
.option('--limit <n>', 'Max results for find/brief', (v) => parseInt(v, 10))
|
|
610
|
+
.action((subcommand, args, options) => {
|
|
611
|
+
void runCodeMap(subcommand, args, options).catch((err) => {
|
|
612
|
+
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
613
|
+
process.exit(1);
|
|
614
|
+
});
|
|
615
|
+
});
|
|
601
616
|
// --- list-plans ---
|
|
602
617
|
program
|
|
603
618
|
.command('list-plans')
|
|
@@ -1806,15 +1821,17 @@ program
|
|
|
1806
1821
|
});
|
|
1807
1822
|
program
|
|
1808
1823
|
.command('switch [project]')
|
|
1809
|
-
.description('Set the active project for subsequent commands')
|
|
1824
|
+
.description('Set the active project for subsequent commands (session-scoped by default)')
|
|
1810
1825
|
.option('--list', 'List available projects in the workspace')
|
|
1811
1826
|
.option('--clear', 'Clear the active project (revert to cwd)')
|
|
1827
|
+
.option('--global', 'Set/clear the SHARED workspace default for ALL agents (writes active-project.json). Without it, switch is session-scoped and isolated.')
|
|
1812
1828
|
.option('--json', 'Output as JSON')
|
|
1813
1829
|
.action((project, options) => {
|
|
1814
1830
|
const globalOpts = options.parent?.parent ? program.opts() : {};
|
|
1815
1831
|
runSwitch(project, {
|
|
1816
1832
|
list: options.list,
|
|
1817
1833
|
clear: options.clear,
|
|
1834
|
+
global: options.global,
|
|
1818
1835
|
json: options.json,
|
|
1819
1836
|
cwd: globalOpts.cwd,
|
|
1820
1837
|
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `brainclaw code-map <subcommand>` — CLI surface over the Code Map backend
|
|
3
|
+
* (spec §9). Mirrors plan-resource.ts: a switch over the subcommand delegating
|
|
4
|
+
* to a JsonlBackend (status | refresh | find | brief). The backend owns all
|
|
5
|
+
* query logic; this file only adapts it to argv + stdout (text or --json), and
|
|
6
|
+
* every output carries the freshness_badge.
|
|
7
|
+
*/
|
|
8
|
+
import { JsonlBackend } from '../core/code-map/backend.js';
|
|
9
|
+
const KNOWN_SUBCOMMANDS = new Set(['status', 'refresh', 'find', 'brief']);
|
|
10
|
+
function backend() {
|
|
11
|
+
return new JsonlBackend();
|
|
12
|
+
}
|
|
13
|
+
function badgeLine(badge) {
|
|
14
|
+
const detailKeys = Object.keys(badge.details ?? {}).filter((k) => badge.details[k] !== null && badge.details[k] !== undefined);
|
|
15
|
+
const detail = detailKeys.length
|
|
16
|
+
? ` (${detailKeys.map((k) => `${k}=${JSON.stringify(badge.details[k])}`).join(', ')})`
|
|
17
|
+
: '';
|
|
18
|
+
return `Freshness: ${badge.status}${detail}`;
|
|
19
|
+
}
|
|
20
|
+
export async function runCodeMap(subcommand, args, options = {}) {
|
|
21
|
+
const normalized = (subcommand ?? '').trim().toLowerCase();
|
|
22
|
+
const be = backend();
|
|
23
|
+
const cwd = options.cwd;
|
|
24
|
+
if (normalized === 'status') {
|
|
25
|
+
const status = await be.status({ cwd });
|
|
26
|
+
printStatus(status, options);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (normalized === 'refresh') {
|
|
30
|
+
const scope = options.all ? 'all' : 'changed';
|
|
31
|
+
const result = await be.refresh({ scope, cwd });
|
|
32
|
+
printRefresh(result, options);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (normalized === 'find') {
|
|
36
|
+
const query = args.join(' ').trim();
|
|
37
|
+
if (!query) {
|
|
38
|
+
console.error('Error: code-map find requires <query>.');
|
|
39
|
+
console.error(' Usage: brainclaw code-map find <query>');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
const result = await be.find({ query, limit: options.limit, cwd });
|
|
43
|
+
printFind(result, options);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (normalized === 'brief') {
|
|
47
|
+
const target = args.join(' ').trim();
|
|
48
|
+
if (!target) {
|
|
49
|
+
console.error('Error: code-map brief requires <symbol-or-path>.');
|
|
50
|
+
console.error(' Usage: brainclaw code-map brief <symbol-or-path>');
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const result = await be.brief({ target, limit: options.limit, cwd });
|
|
54
|
+
printBrief(result, options);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
console.error(`Error: unknown code-map subcommand "${subcommand}".`);
|
|
58
|
+
console.error(` Available: ${[...KNOWN_SUBCOMMANDS].join(', ')}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
function printStatus(status, options) {
|
|
62
|
+
if (options.json) {
|
|
63
|
+
console.log(JSON.stringify(status, null, 2));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log('Code Map status');
|
|
67
|
+
console.log(` Store: ${status.store_exists ? 'present' : 'absent'}`);
|
|
68
|
+
console.log(` ${badgeLine(status.freshness_badge)}`);
|
|
69
|
+
if (status.stats) {
|
|
70
|
+
console.log(` Files: ${status.stats.files_indexed}`);
|
|
71
|
+
console.log(` Nodes: ${status.stats.nodes}`);
|
|
72
|
+
console.log(` Edges: ${status.stats.edges}`);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.log(' Stats: (none — index not built)');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function printRefresh(result, options) {
|
|
79
|
+
if (options.json) {
|
|
80
|
+
console.log(JSON.stringify(result, null, 2));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
console.log(`Code Map refresh [${result.scope}]`);
|
|
84
|
+
console.log(` Ran: ${result.ran}`);
|
|
85
|
+
console.log(` Lock: ${result.lock_acquired ? 'acquired' : 'not acquired'}`);
|
|
86
|
+
if (result.lock_status)
|
|
87
|
+
console.log(` Status: ${result.lock_status}`);
|
|
88
|
+
console.log(` ${badgeLine(result.freshness_badge)}`);
|
|
89
|
+
}
|
|
90
|
+
function printFind(result, options) {
|
|
91
|
+
if (options.json) {
|
|
92
|
+
console.log(JSON.stringify(result, null, 2));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
console.log(`Code Map find: "${result.query}"`);
|
|
96
|
+
console.log(` ${badgeLine(result.freshness_badge)}`);
|
|
97
|
+
if (result.matches.length === 0) {
|
|
98
|
+
console.log(' (no matches)');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
for (const m of result.matches) {
|
|
102
|
+
const sub = m.subtype ? ` ${m.subtype}` : '';
|
|
103
|
+
console.log(` [${m.score.toFixed(1)}] ${m.name}${sub} — ${m.path}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function printBrief(result, options) {
|
|
107
|
+
if (options.json) {
|
|
108
|
+
console.log(JSON.stringify(result, null, 2));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
console.log(`Code Map brief: "${result.target}"`);
|
|
112
|
+
console.log(` ${badgeLine(result.freshness_badge)}`);
|
|
113
|
+
if (result.suggested_files_to_read.length === 0) {
|
|
114
|
+
console.log(' Suggested files: (none)');
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log(' Suggested files to read:');
|
|
118
|
+
for (const f of result.suggested_files_to_read) {
|
|
119
|
+
console.log(` [${f.score.toFixed(1)}] ${f.path} — ${f.reason}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (result.related_memory.length > 0) {
|
|
123
|
+
console.log(' Related memory:');
|
|
124
|
+
for (const mem of result.related_memory) {
|
|
125
|
+
console.log(` ${mem.id} (${mem.kind}): ${mem.text.slice(0, 80)}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=code-map.js.map
|
package/dist/commands/codev.js
CHANGED
|
@@ -26,6 +26,7 @@ import { buildContext } from '../core/context.js';
|
|
|
26
26
|
import { buildCoordinationSnapshot } from '../core/coordination.js';
|
|
27
27
|
import { getDefaultInvokeTemplate, getSpawnableAgents } from '../core/agent-capability.js';
|
|
28
28
|
import { executeRound } from '../core/codev-rounds.js';
|
|
29
|
+
import { buildWorkerIdentityEnv } from '../core/execution-profile.js';
|
|
29
30
|
import { loadIdeationRound } from '../core/ideation.js';
|
|
30
31
|
import { summarizeMetrics, summarizeMetricsByRound } from '../core/codev-metrics.js';
|
|
31
32
|
import { generatePlansFromConvergence, generateSummaryNote } from '../core/codev-plan-gen.js';
|
|
@@ -422,12 +423,16 @@ function spawnConsultant(brief, threadId, personaName, cwd, agent) {
|
|
|
422
423
|
console.warn(` ⚠ Spawn error for ${agentName}/${personaName}: ${err.message}`);
|
|
423
424
|
});
|
|
424
425
|
};
|
|
426
|
+
// F7 (trp_0e5150d3): scrub coordinator identity so a consultant worker is an
|
|
427
|
+
// independent agent — these spawns previously inherited the full parent env.
|
|
428
|
+
const workerEnv = buildWorkerIdentityEnv(process.env, { agent: agentName });
|
|
425
429
|
if (agentName === 'codex') {
|
|
426
430
|
// Codex: use temp file via shell to avoid Windows .cmd ENOENT issues
|
|
427
431
|
const child = spawn('sh', ['-c', `cat "${briefFile}" | "${binaryPath}" exec --full-auto - ; rm -f "${briefFile}"`], {
|
|
428
432
|
detached: true,
|
|
429
433
|
stdio: 'ignore',
|
|
430
434
|
cwd,
|
|
435
|
+
env: workerEnv,
|
|
431
436
|
});
|
|
432
437
|
attachErrorHandler(child);
|
|
433
438
|
child.unref();
|
|
@@ -438,6 +443,7 @@ function spawnConsultant(brief, threadId, personaName, cwd, agent) {
|
|
|
438
443
|
detached: true,
|
|
439
444
|
stdio: 'ignore',
|
|
440
445
|
cwd,
|
|
446
|
+
env: workerEnv,
|
|
441
447
|
});
|
|
442
448
|
attachErrorHandler(child);
|
|
443
449
|
child.unref();
|
|
@@ -448,6 +454,7 @@ function spawnConsultant(brief, threadId, personaName, cwd, agent) {
|
|
|
448
454
|
detached: true,
|
|
449
455
|
stdio: 'ignore',
|
|
450
456
|
cwd,
|
|
457
|
+
env: workerEnv,
|
|
451
458
|
});
|
|
452
459
|
attachErrorHandler(child);
|
|
453
460
|
child.unref();
|
package/dist/commands/harvest.js
CHANGED
|
@@ -299,7 +299,7 @@ export function harvestLaneResults(options = {}) {
|
|
|
299
299
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
300
300
|
// pln#534 — worktree-as-contract: integrate a worker's lane on its behalf.
|
|
301
301
|
//
|
|
302
|
-
// LEVER #1 from
|
|
302
|
+
// LEVER #1 from a cross-project field session. The worker's contract is
|
|
303
303
|
// reduced to "edit files in this worktree + drop LANE-RESULT.json". brainclaw
|
|
304
304
|
// carries the rest for a worker that cannot (a sandboxed agent whose root
|
|
305
305
|
// excludes `.git`, i.e. dispatchCanCommit=false): it COMMITS the worktree diff
|
package/dist/commands/hooks.js
CHANGED
|
@@ -9,33 +9,33 @@ import { BRAINCLAW_SECTION_START, BRAINCLAW_SECTION_END, upsertBrainclawSection,
|
|
|
9
9
|
* deterministically into every agent conversation.
|
|
10
10
|
*/
|
|
11
11
|
export function generateCursorHook(projectName) {
|
|
12
|
-
return `---
|
|
13
|
-
description: brainclaw session bootstrap for ${projectName}
|
|
14
|
-
alwaysApply: true
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
# Brainclaw session bootstrap
|
|
18
|
-
|
|
19
|
-
Brainclaw is the shared coordination layer for this project. Use its MCP facades first — the CLI is only a fallback when MCP is unavailable.
|
|
20
|
-
|
|
21
|
-
## At the start of every session
|
|
22
|
-
|
|
23
|
-
Call \`bclaw_work(intent)\` — it handles session setup, context load, and scope claim in a single call.
|
|
24
|
-
|
|
25
|
-
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
26
|
-
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
27
|
-
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
28
|
-
|
|
29
|
-
## To coordinate with other agents
|
|
30
|
-
|
|
31
|
-
\`bclaw_coordinate(intent)\` — \`assign\`, \`consult\`, \`review\`, or \`reroute\`.
|
|
32
|
-
|
|
33
|
-
## Before finishing
|
|
34
|
-
|
|
35
|
-
- Release your claims: \`bclaw_release_claim(id)\`.
|
|
36
|
-
- Close out the session: \`bclaw_session_end\` (or let it auto-release via the session hook).
|
|
37
|
-
|
|
38
|
-
CLI fallback only: \`brainclaw context\` / \`brainclaw session-end --auto-release\` if MCP is not reachable.
|
|
12
|
+
return `---
|
|
13
|
+
description: brainclaw session bootstrap for ${projectName}
|
|
14
|
+
alwaysApply: true
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Brainclaw session bootstrap
|
|
18
|
+
|
|
19
|
+
Brainclaw is the shared coordination layer for this project. Use its MCP facades first — the CLI is only a fallback when MCP is unavailable.
|
|
20
|
+
|
|
21
|
+
## At the start of every session
|
|
22
|
+
|
|
23
|
+
Call \`bclaw_work(intent)\` — it handles session setup, context load, and scope claim in a single call.
|
|
24
|
+
|
|
25
|
+
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
26
|
+
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
27
|
+
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
28
|
+
|
|
29
|
+
## To coordinate with other agents
|
|
30
|
+
|
|
31
|
+
\`bclaw_coordinate(intent)\` — \`assign\`, \`consult\`, \`review\`, or \`reroute\`.
|
|
32
|
+
|
|
33
|
+
## Before finishing
|
|
34
|
+
|
|
35
|
+
- Release your claims: \`bclaw_release_claim(id)\`.
|
|
36
|
+
- Close out the session: \`bclaw_session_end\` (or let it auto-release via the session hook).
|
|
37
|
+
|
|
38
|
+
CLI fallback only: \`brainclaw context\` / \`brainclaw session-end --auto-release\` if MCP is not reachable.
|
|
39
39
|
`;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -44,58 +44,58 @@ CLI fallback only: \`brainclaw context\` / \`brainclaw session-end --auto-releas
|
|
|
44
44
|
* delimited "SESSION START" block acts as a deterministic trigger.
|
|
45
45
|
*/
|
|
46
46
|
export function generateWindsurfHook(projectName) {
|
|
47
|
-
return `# Brainclaw session trigger — ${projectName}
|
|
48
|
-
# This block is always active. Windsurf Cascade reads .windsurfrules on every activation.
|
|
49
|
-
|
|
50
|
-
## SESSION START (always run first)
|
|
51
|
-
|
|
52
|
-
Call the Brainclaw MCP facade before responding to any request:
|
|
53
|
-
|
|
54
|
-
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
55
|
-
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
56
|
-
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
57
|
-
|
|
58
|
-
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
59
|
-
|
|
60
|
-
## COORDINATION
|
|
61
|
-
|
|
62
|
-
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
63
|
-
|
|
64
|
-
## SESSION END (before finishing)
|
|
65
|
-
|
|
66
|
-
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
67
|
-
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
68
|
-
|
|
69
|
-
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
47
|
+
return `# Brainclaw session trigger — ${projectName}
|
|
48
|
+
# This block is always active. Windsurf Cascade reads .windsurfrules on every activation.
|
|
49
|
+
|
|
50
|
+
## SESSION START (always run first)
|
|
51
|
+
|
|
52
|
+
Call the Brainclaw MCP facade before responding to any request:
|
|
53
|
+
|
|
54
|
+
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
55
|
+
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
56
|
+
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
57
|
+
|
|
58
|
+
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
59
|
+
|
|
60
|
+
## COORDINATION
|
|
61
|
+
|
|
62
|
+
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
63
|
+
|
|
64
|
+
## SESSION END (before finishing)
|
|
65
|
+
|
|
66
|
+
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
67
|
+
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
68
|
+
|
|
69
|
+
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
70
70
|
`;
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
73
|
* Generate a generic markdown session-trigger section.
|
|
74
74
|
*/
|
|
75
75
|
export function generateMarkdownHook(agentName, projectName) {
|
|
76
|
-
return `# Brainclaw session trigger — ${projectName}
|
|
77
|
-
# This block is always active. ${agentName} reads this file on every activation.
|
|
78
|
-
|
|
79
|
-
## SESSION START (always run first)
|
|
80
|
-
|
|
81
|
-
Call the Brainclaw MCP facade before responding to any request:
|
|
82
|
-
|
|
83
|
-
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
84
|
-
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
85
|
-
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
86
|
-
|
|
87
|
-
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
88
|
-
|
|
89
|
-
## COORDINATION
|
|
90
|
-
|
|
91
|
-
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
92
|
-
|
|
93
|
-
## SESSION END (before finishing)
|
|
94
|
-
|
|
95
|
-
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
96
|
-
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
97
|
-
|
|
98
|
-
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
76
|
+
return `# Brainclaw session trigger — ${projectName}
|
|
77
|
+
# This block is always active. ${agentName} reads this file on every activation.
|
|
78
|
+
|
|
79
|
+
## SESSION START (always run first)
|
|
80
|
+
|
|
81
|
+
Call the Brainclaw MCP facade before responding to any request:
|
|
82
|
+
|
|
83
|
+
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
84
|
+
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
85
|
+
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
86
|
+
|
|
87
|
+
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
88
|
+
|
|
89
|
+
## COORDINATION
|
|
90
|
+
|
|
91
|
+
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
92
|
+
|
|
93
|
+
## SESSION END (before finishing)
|
|
94
|
+
|
|
95
|
+
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
96
|
+
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
97
|
+
|
|
98
|
+
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
99
99
|
`;
|
|
100
100
|
}
|
|
101
101
|
export function writeHook(content, relativePath, cwd) {
|
package/dist/commands/init.js
CHANGED
|
@@ -117,7 +117,7 @@ export async function runInit(options = {}) {
|
|
|
117
117
|
});
|
|
118
118
|
// Auto-detect and register the AI coding agent running in this environment
|
|
119
119
|
const detectedAi = skipAgentBootstrap ? undefined : detectAiAgent();
|
|
120
|
-
|
|
120
|
+
const registeredAiAgent = detectedAi
|
|
121
121
|
? registerAgentIdentity({
|
|
122
122
|
agentName: detectedAi.name,
|
|
123
123
|
kind: detectedAi.kind,
|
|
@@ -40,63 +40,63 @@ export function runInstallHooks(options = {}) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function generateClaudePreToolScript() {
|
|
43
|
-
return `#!/bin/sh
|
|
44
|
-
# brainclaw Claude Code preToolUse hook
|
|
45
|
-
# Generated by: brainclaw install-hooks
|
|
46
|
-
exec node -e "
|
|
47
|
-
const fs = require('fs');
|
|
48
|
-
const path = require('path');
|
|
49
|
-
const { execSync } = require('child_process');
|
|
50
|
-
|
|
51
|
-
const toolName = process.env.CLAUDE_TOOL_NAME || process.argv[2] || process.env.TOOL_NAME || '';
|
|
52
|
-
const isWrite = /edit|write|replace|bash|str_replace/i.test(toolName);
|
|
53
|
-
|
|
54
|
-
if (!isWrite || !toolName) process.exit(0);
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
const BCLAW_CMD = fs.existsSync(path.join(process.cwd(), 'node_modules', '.bin', 'brainclaw'))
|
|
58
|
-
? 'npx brainclaw' : 'brainclaw';
|
|
59
|
-
const out = execSync(BCLAW_CMD + ' claim list --json', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
60
|
-
const claims = JSON.parse(out);
|
|
61
|
-
if (claims && claims.length > 0) process.exit(0);
|
|
62
|
-
} catch (e) {
|
|
63
|
-
// ignore if brainclaw not found or fails
|
|
64
|
-
process.exit(0);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const sessionMark = path.join(process.cwd(), '.brainclaw', 'tmp', 'claude_warned');
|
|
68
|
-
if (!fs.existsSync(path.dirname(sessionMark))) fs.mkdirSync(path.dirname(sessionMark), { recursive: true });
|
|
69
|
-
|
|
70
|
-
if (fs.existsSync(sessionMark)) {
|
|
71
|
-
const mtime = fs.statSync(sessionMark).mtimeMs;
|
|
72
|
-
if (Date.now() - mtime < 2 * 60 * 60 * 1000) {
|
|
73
|
-
process.exit(0); // already warned this session
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
fs.writeFileSync(sessionMark, Date.now().toString());
|
|
77
|
-
|
|
78
|
-
process.stderr.write('\\n[Brainclaw] ⚠️ WARNING: You are about to use an Edit/Write tool (' + toolName + ') but you have NO active claim.\\n');
|
|
79
|
-
process.stderr.write('[Brainclaw] Consider running \\\`brainclaw claim create <scope>\\\` to lock your work and avoid conflicts.\\n\\n');
|
|
80
|
-
" 2>&1 || exit 0
|
|
43
|
+
return `#!/bin/sh
|
|
44
|
+
# brainclaw Claude Code preToolUse hook
|
|
45
|
+
# Generated by: brainclaw install-hooks
|
|
46
|
+
exec node -e "
|
|
47
|
+
const fs = require('fs');
|
|
48
|
+
const path = require('path');
|
|
49
|
+
const { execSync } = require('child_process');
|
|
50
|
+
|
|
51
|
+
const toolName = process.env.CLAUDE_TOOL_NAME || process.argv[2] || process.env.TOOL_NAME || '';
|
|
52
|
+
const isWrite = /edit|write|replace|bash|str_replace/i.test(toolName);
|
|
53
|
+
|
|
54
|
+
if (!isWrite || !toolName) process.exit(0);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const BCLAW_CMD = fs.existsSync(path.join(process.cwd(), 'node_modules', '.bin', 'brainclaw'))
|
|
58
|
+
? 'npx brainclaw' : 'brainclaw';
|
|
59
|
+
const out = execSync(BCLAW_CMD + ' claim list --json', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
60
|
+
const claims = JSON.parse(out);
|
|
61
|
+
if (claims && claims.length > 0) process.exit(0);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
// ignore if brainclaw not found or fails
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const sessionMark = path.join(process.cwd(), '.brainclaw', 'tmp', 'claude_warned');
|
|
68
|
+
if (!fs.existsSync(path.dirname(sessionMark))) fs.mkdirSync(path.dirname(sessionMark), { recursive: true });
|
|
69
|
+
|
|
70
|
+
if (fs.existsSync(sessionMark)) {
|
|
71
|
+
const mtime = fs.statSync(sessionMark).mtimeMs;
|
|
72
|
+
if (Date.now() - mtime < 2 * 60 * 60 * 1000) {
|
|
73
|
+
process.exit(0); // already warned this session
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
fs.writeFileSync(sessionMark, Date.now().toString());
|
|
77
|
+
|
|
78
|
+
process.stderr.write('\\n[Brainclaw] ⚠️ WARNING: You are about to use an Edit/Write tool (' + toolName + ') but you have NO active claim.\\n');
|
|
79
|
+
process.stderr.write('[Brainclaw] Consider running \\\`brainclaw claim create <scope>\\\` to lock your work and avoid conflicts.\\n\\n');
|
|
80
|
+
" 2>&1 || exit 0
|
|
81
81
|
`;
|
|
82
82
|
}
|
|
83
83
|
function generatePostMergeScript() {
|
|
84
|
-
return `#!/bin/sh
|
|
85
|
-
# brainclaw post-merge hook
|
|
86
|
-
# Auto-releases claims whose scope overlaps with files changed by the merge
|
|
87
|
-
# Generated by: brainclaw install-hooks
|
|
88
|
-
|
|
89
|
-
BCLAW_CMD=""
|
|
90
|
-
if command -v brainclaw >/dev/null 2>&1; then
|
|
91
|
-
BCLAW_CMD="brainclaw"
|
|
92
|
-
elif command -v bclaw >/dev/null 2>&1; then
|
|
93
|
-
BCLAW_CMD="bclaw"
|
|
94
|
-
else
|
|
95
|
-
BCLAW_CMD="npx --no brainclaw"
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
$BCLAW_CMD release-claims --from-git-diff 2>/dev/null || true
|
|
99
|
-
$BCLAW_CMD worktree clean 2>/dev/null || true
|
|
84
|
+
return `#!/bin/sh
|
|
85
|
+
# brainclaw post-merge hook
|
|
86
|
+
# Auto-releases claims whose scope overlaps with files changed by the merge
|
|
87
|
+
# Generated by: brainclaw install-hooks
|
|
88
|
+
|
|
89
|
+
BCLAW_CMD=""
|
|
90
|
+
if command -v brainclaw >/dev/null 2>&1; then
|
|
91
|
+
BCLAW_CMD="brainclaw"
|
|
92
|
+
elif command -v bclaw >/dev/null 2>&1; then
|
|
93
|
+
BCLAW_CMD="bclaw"
|
|
94
|
+
else
|
|
95
|
+
BCLAW_CMD="npx --no brainclaw"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
$BCLAW_CMD release-claims --from-git-diff 2>/dev/null || true
|
|
99
|
+
$BCLAW_CMD worktree clean 2>/dev/null || true
|
|
100
100
|
`;
|
|
101
101
|
}
|
|
102
102
|
function findGitRoot(cwd) {
|
|
@@ -113,30 +113,30 @@ function findGitRoot(cwd) {
|
|
|
113
113
|
function generateHookScript() {
|
|
114
114
|
// Use node directly to avoid sh.exe pipe issues on Windows (SIGPIPE).
|
|
115
115
|
// The script is a self-contained node -e that runs both checks.
|
|
116
|
-
return `#!/bin/sh
|
|
117
|
-
# brainclaw pre-commit hook — generated by brainclaw install-hooks
|
|
118
|
-
# Runs via node to avoid sh.exe SIGPIPE issues on Windows.
|
|
119
|
-
exec node -e "
|
|
120
|
-
const { execSync } = require('child_process');
|
|
121
|
-
const staged = execSync('git diff --cached --name-only', { encoding: 'utf-8' }).trim();
|
|
122
|
-
if (!staged) process.exit(0);
|
|
123
|
-
|
|
124
|
-
// Check 1: reject staged .brainclaw/ files
|
|
125
|
-
const brainclawFiles = staged.split('\\\\n').filter(f => f.startsWith('.brainclaw/'));
|
|
126
|
-
if (brainclawFiles.length > 0) {
|
|
127
|
-
process.stderr.write('\\\\nbrainclaw: .brainclaw/ files are staged — blocked.\\\\n');
|
|
128
|
-
brainclawFiles.forEach(f => process.stderr.write(' ' + f + '\\\\n'));
|
|
129
|
-
process.stderr.write(' Fix: git reset HEAD .brainclaw/\\\\n\\\\n');
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Check 2: active constraint violations
|
|
134
|
-
try {
|
|
135
|
-
execSync('brainclaw check-constraints --staged', { stdio: 'inherit' });
|
|
136
|
-
} catch (e) {
|
|
137
|
-
if (e.status) process.exit(e.status);
|
|
138
|
-
}
|
|
139
|
-
" 2>&1 || exit $?
|
|
116
|
+
return `#!/bin/sh
|
|
117
|
+
# brainclaw pre-commit hook — generated by brainclaw install-hooks
|
|
118
|
+
# Runs via node to avoid sh.exe SIGPIPE issues on Windows.
|
|
119
|
+
exec node -e "
|
|
120
|
+
const { execSync } = require('child_process');
|
|
121
|
+
const staged = execSync('git diff --cached --name-only', { encoding: 'utf-8' }).trim();
|
|
122
|
+
if (!staged) process.exit(0);
|
|
123
|
+
|
|
124
|
+
// Check 1: reject staged .brainclaw/ files
|
|
125
|
+
const brainclawFiles = staged.split('\\\\n').filter(f => f.startsWith('.brainclaw/'));
|
|
126
|
+
if (brainclawFiles.length > 0) {
|
|
127
|
+
process.stderr.write('\\\\nbrainclaw: .brainclaw/ files are staged — blocked.\\\\n');
|
|
128
|
+
brainclawFiles.forEach(f => process.stderr.write(' ' + f + '\\\\n'));
|
|
129
|
+
process.stderr.write(' Fix: git reset HEAD .brainclaw/\\\\n\\\\n');
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Check 2: active constraint violations
|
|
134
|
+
try {
|
|
135
|
+
execSync('brainclaw check-constraints --staged', { stdio: 'inherit' });
|
|
136
|
+
} catch (e) {
|
|
137
|
+
if (e.status) process.exit(e.status);
|
|
138
|
+
}
|
|
139
|
+
" 2>&1 || exit $?
|
|
140
140
|
`;
|
|
141
141
|
}
|
|
142
142
|
//# sourceMappingURL=install-hooks.js.map
|