brainclaw 1.24.0 → 1.25.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/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli/register-code-map.js +9 -2
- package/dist/commands/code-map.js +119 -2
- package/dist/commands/mcp-catalog.js +46 -0
- package/dist/commands/mcp.js +54 -2
- package/dist/core/code-map/backend.js +158 -1
- package/dist/core/code-map/export.js +212 -0
- package/dist/core/code-map/freshness.js +3 -2
- package/dist/core/code-map/impact.js +377 -0
- package/dist/core/code-map/indexes.js +27 -3
- package/dist/core/code-map/lang/typescript/config.js +271 -0
- package/dist/core/code-map/lang/typescript/index.js +20 -4
- package/dist/core/code-map/query.js +76 -13
- package/dist/core/code-map/refresh.js +0 -0
- package/dist/core/code-map/resolve.js +1 -0
- package/dist/core/code-map/types.js +15 -0
- package/dist/core/federation-pull.js +151 -3
- package/dist/core/federation-push.js +16 -3
- package/dist/core/protocol-tool-policy.js +3 -0
- package/dist/core/worktree.js +89 -2
- package/dist/facts.js +13 -10
- package/dist/facts.json +12 -9
- package/docs/cli.md +8 -0
- package/docs/code-map.md +24 -1
- package/docs/integrations/mcp.md +5 -2
- package/docs/mcp-schema-changelog.md +11 -1
- package/package.json +1 -1
|
@@ -179,16 +179,22 @@ export async function pushPending(options = {}) {
|
|
|
179
179
|
throw new Error('Adresse du cloud inconnue : passez --url. Elle n\'est pas conservée par l\'appairage ' +
|
|
180
180
|
'(état de connexion sans champ d\'URL), et aucune adresse n\'est devinée.');
|
|
181
181
|
}
|
|
182
|
+
const pending = list('pending', cwd);
|
|
183
|
+
// File vide = rien à signer : sortir AVANT de résoudre l'identité. Le signataire est
|
|
184
|
+
// déduit de la première entrée pending ; le chercher sur une file vide transformait
|
|
185
|
+
// « tout est déjà parti » en erreur d'identité — vécu le 2026-08-10, juste après un
|
|
186
|
+
// envoi complet dont il ne restait que des conflits.
|
|
187
|
+
if (pending.length === 0)
|
|
188
|
+
return result;
|
|
182
189
|
// L'identité SIGNATAIRE du transport : celle de l'agent qui a produit les enveloppes.
|
|
183
190
|
// Elle est portée par l'entrée d'outbox, donc le transport n'a pas à deviner qui signe.
|
|
184
|
-
const agentId = options.agentId ??
|
|
191
|
+
const agentId = options.agentId ?? pending[0]?.origin_agent_id;
|
|
185
192
|
const identity = agentId ? loadAgentSigningKey(agentId) : undefined;
|
|
186
193
|
if (!identity) {
|
|
187
194
|
throw new Error('Identité de signature introuvable : le cloud vérifie une signature de TRANSPORT ' +
|
|
188
195
|
'liant envelope_id, rev et base_rev. Sans elle, chaque envoi est refusé en 422.');
|
|
189
196
|
}
|
|
190
197
|
const identityPem = identity.privateKeyPem;
|
|
191
|
-
const pending = list('pending', cwd);
|
|
192
198
|
const batch = options.limit ? pending.slice(0, options.limit) : pending;
|
|
193
199
|
result.attempted = batch.length;
|
|
194
200
|
if (options.dryRun)
|
|
@@ -214,7 +220,14 @@ export async function pushPending(options = {}) {
|
|
|
214
220
|
// réel en écrasement silencieux du travail d'un autre appareil.
|
|
215
221
|
if (res.status === 409) {
|
|
216
222
|
const detail = (await res.clone().json().catch(() => ({})));
|
|
217
|
-
|
|
223
|
+
// `current_head_rev` est le nom que le serveur DÉPLOYÉ répond (projection.ts,
|
|
224
|
+
// REV_CONFLICT). Les deux autres sont des noms historiques gardés en repli.
|
|
225
|
+
// Dérive constatée le 2026-08-10 : le client lisait `expected_base_rev` sur une
|
|
226
|
+
// réponse qui ne l'a jamais porté — le recalage ne se déclenchait donc JAMAIS et
|
|
227
|
+
// chaque mise à jour finissait en conflit. Le test unitaire rejoue depuis la
|
|
228
|
+
// forme de réponse RÉELLE du serveur ; leçon dec#160/162, un contrat inter-
|
|
229
|
+
// services ne se vérifie que contre le service.
|
|
230
|
+
const expected = detail['current_head_rev'] ?? detail['expected_base_rev'] ?? detail['expected'];
|
|
218
231
|
if (typeof expected === 'string' || typeof expected === 'number') {
|
|
219
232
|
// On RESIGNE avec la nouvelle base_rev : c'est précisément ce que la signature
|
|
220
233
|
// au niveau du transport rend possible, et qu'une signature figée à l'émission
|
|
@@ -48,6 +48,9 @@ export const MCP_HEADLESS_AUTO_TOOL_NAMES = [
|
|
|
48
48
|
'bclaw_code_status',
|
|
49
49
|
'bclaw_code_find',
|
|
50
50
|
'bclaw_code_brief',
|
|
51
|
+
'bclaw_code_impact',
|
|
52
|
+
'bclaw_code_export',
|
|
53
|
+
'bclaw_code_outline',
|
|
51
54
|
'bclaw_send_message',
|
|
52
55
|
'bclaw_ack_message',
|
|
53
56
|
'bclaw_write_note',
|
package/dist/core/worktree.js
CHANGED
|
@@ -7,6 +7,7 @@ import yaml from 'yaml';
|
|
|
7
7
|
import { logger } from './logger.js';
|
|
8
8
|
import { loadConfig } from './config.js';
|
|
9
9
|
import { parsePorcelainZ, isSystemDirtyPath } from './dirty-scope.js';
|
|
10
|
+
import { entityRecordDirs } from './io.js';
|
|
10
11
|
/** Normalizes a path for use in git CLI arguments (forward slashes on Windows). */
|
|
11
12
|
function gitPath(p) {
|
|
12
13
|
return p.replace(/\\/g, '/');
|
|
@@ -1548,6 +1549,68 @@ export function probeLocalBranch(mainWorktreePath, branchName) {
|
|
|
1548
1549
|
export function isGitRepo(cwd) {
|
|
1549
1550
|
return runGit(['rev-parse', '--is-inside-work-tree'], cwd).ok;
|
|
1550
1551
|
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Comparison key for worktree paths: PHYSICAL identity when the path exists
|
|
1554
|
+
* (realpath expands Windows 8.3 short names — `RUNNER~1` and `runneradmin`
|
|
1555
|
+
* are the same directory but different strings, and git always reports the
|
|
1556
|
+
* long form while a claim may carry the short one), else plain resolution.
|
|
1557
|
+
* Forward slashes, case-folded on win32.
|
|
1558
|
+
*/
|
|
1559
|
+
function worktreePathKey(p) {
|
|
1560
|
+
let resolved;
|
|
1561
|
+
try {
|
|
1562
|
+
resolved = fs.realpathSync.native(p);
|
|
1563
|
+
}
|
|
1564
|
+
catch {
|
|
1565
|
+
resolved = path.resolve(p);
|
|
1566
|
+
}
|
|
1567
|
+
resolved = resolved.replace(/\\/g, '/').replace(/\/+$/, '');
|
|
1568
|
+
return process.platform === 'win32' ? resolved.toLowerCase() : resolved;
|
|
1569
|
+
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Worktree paths referenced by an ACTIVE, non-expired claim — the set the GC
|
|
1572
|
+
* must never touch.
|
|
1573
|
+
*
|
|
1574
|
+
* Read directly from the claims record dirs (both layouts, pln#649) instead of
|
|
1575
|
+
* claims.ts: claims.ts imports worktree.ts, so the dependency can only point
|
|
1576
|
+
* this way. The parse is deliberately lenient — an unreadable claim simply does
|
|
1577
|
+
* not protect anything; it never blocks the GC of OTHER worktrees.
|
|
1578
|
+
*
|
|
1579
|
+
* Scope note: dispatch claims are project-local, so the project store is the
|
|
1580
|
+
* right authority here; workspace-level claims (cross-project) never carry a
|
|
1581
|
+
* lane worktree_path.
|
|
1582
|
+
*/
|
|
1583
|
+
function activeClaimWorktreePaths(cwd) {
|
|
1584
|
+
const out = new Set();
|
|
1585
|
+
const now = new Date();
|
|
1586
|
+
for (const dir of entityRecordDirs('claims', cwd)) {
|
|
1587
|
+
let files;
|
|
1588
|
+
try {
|
|
1589
|
+
files = fs.readdirSync(dir).filter((f) => f.endsWith('.json'));
|
|
1590
|
+
}
|
|
1591
|
+
catch {
|
|
1592
|
+
continue;
|
|
1593
|
+
}
|
|
1594
|
+
for (const f of files) {
|
|
1595
|
+
try {
|
|
1596
|
+
const claim = JSON.parse(fs.readFileSync(path.join(dir, f), 'utf-8'));
|
|
1597
|
+
if (claim.status !== 'active')
|
|
1598
|
+
continue;
|
|
1599
|
+
if (typeof claim.worktree_path !== 'string' || !claim.worktree_path)
|
|
1600
|
+
continue;
|
|
1601
|
+
// Mirror isClaimExpired: a zombie claim past its expiry must not make a
|
|
1602
|
+
// worktree un-GC-able forever.
|
|
1603
|
+
if (claim.expires_at && new Date(claim.expires_at) < now)
|
|
1604
|
+
continue;
|
|
1605
|
+
out.add(worktreePathKey(claim.worktree_path));
|
|
1606
|
+
}
|
|
1607
|
+
catch {
|
|
1608
|
+
/* lenient by design — see above */
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
return out;
|
|
1613
|
+
}
|
|
1551
1614
|
/**
|
|
1552
1615
|
* Removes worktrees whose branch has been fully merged into the current branch
|
|
1553
1616
|
* (typically master/main after a merge). Also removes brainclaw-managed
|
|
@@ -1561,6 +1624,16 @@ export function isGitRepo(cwd) {
|
|
|
1561
1624
|
* - content (`git cherry HEAD <branch>`, patch-id): catches squash merges,
|
|
1562
1625
|
* which is GitHub's default merge strategy on this repo and previously left
|
|
1563
1626
|
* every squashed lane un-GC-able forever.
|
|
1627
|
+
*
|
|
1628
|
+
* ACTIVE-CLAIM GATE (incident 2026-08-10): a freshly-dispatched lane worktree
|
|
1629
|
+
* has no commits of its own — its branch IS an ancestor of HEAD, so both merged
|
|
1630
|
+
* probes say "merged" — and before the agent's first write it has no uncommitted
|
|
1631
|
+
* changes either. Both historical gates therefore pass during a lane's startup
|
|
1632
|
+
* window, and the post-merge hook destroyed a live codex lane 7 minutes after
|
|
1633
|
+
* spawn (worktree emptied under the running agent). The coordination store is
|
|
1634
|
+
* the authority on liveness: a worktree referenced by an active claim is
|
|
1635
|
+
* untouchable — merged or not, clean or not, force or not. The escape hatch is
|
|
1636
|
+
* releasing the claim, never bypassing it.
|
|
1564
1637
|
*/
|
|
1565
1638
|
export function cleanMergedWorktrees(mainWorktreePath, options = {}) {
|
|
1566
1639
|
const result = { removed: [], skipped: [], pruned: false };
|
|
@@ -1580,9 +1653,16 @@ export function cleanMergedWorktrees(mainWorktreePath, options = {}) {
|
|
|
1580
1653
|
.filter(Boolean)
|
|
1581
1654
|
: []);
|
|
1582
1655
|
const worktrees = listWorktrees(mainWorktreePath);
|
|
1656
|
+
const protectedPaths = activeClaimWorktreePaths(mainWorktreePath);
|
|
1583
1657
|
for (const wt of worktrees) {
|
|
1584
1658
|
if (wt.is_main)
|
|
1585
1659
|
continue;
|
|
1660
|
+
// Active-claim gate — see the function doc. Checked BEFORE the merged
|
|
1661
|
+
// probes and BEFORE `force`: a live dispatched lane is never GC-able.
|
|
1662
|
+
if (protectedPaths.has(worktreePathKey(wt.path))) {
|
|
1663
|
+
result.skipped.push({ path: wt.path, reason: 'active claim' });
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1586
1666
|
// trp#926 — a lane's branch is "merged" if EITHER git says its commits are
|
|
1587
1667
|
// ancestors of HEAD (fast-forward / merge-commit) OR every commit's patch
|
|
1588
1668
|
// is already on HEAD (squash-merge, catching GitHub's default strategy).
|
|
@@ -1621,7 +1701,7 @@ export function cleanMergedWorktrees(mainWorktreePath, options = {}) {
|
|
|
1621
1701
|
}
|
|
1622
1702
|
}
|
|
1623
1703
|
// Clean orphan brainclaw worktree directories (no matching git worktree)
|
|
1624
|
-
cleanOrphanWorktreeDirs(mainWorktreePath, worktrees, result, options.dryRun);
|
|
1704
|
+
cleanOrphanWorktreeDirs(mainWorktreePath, worktrees, result, options.dryRun, protectedPaths);
|
|
1625
1705
|
return result;
|
|
1626
1706
|
}
|
|
1627
1707
|
/** A worker whose heartbeat file was touched within this window looks alive. */
|
|
@@ -1722,7 +1802,7 @@ export function gcWorktreeIfHarvested(mainWorktreePath, worktreePath, options =
|
|
|
1722
1802
|
* Removes brainclaw-managed worktree directories under ~/.brainclaw/worktrees/
|
|
1723
1803
|
* that no longer have a corresponding git worktree entry.
|
|
1724
1804
|
*/
|
|
1725
|
-
function cleanOrphanWorktreeDirs(mainWorktreePath, activeWorktrees, result, dryRun) {
|
|
1805
|
+
function cleanOrphanWorktreeDirs(mainWorktreePath, activeWorktrees, result, dryRun, protectedPaths = new Set()) {
|
|
1726
1806
|
const base = worktreesBaseDir(mainWorktreePath);
|
|
1727
1807
|
if (!fs.existsSync(base))
|
|
1728
1808
|
return;
|
|
@@ -1740,6 +1820,13 @@ function cleanOrphanWorktreeDirs(mainWorktreePath, activeWorktrees, result, dryR
|
|
|
1740
1820
|
const dirPath = path.resolve(path.join(base, entry.name));
|
|
1741
1821
|
if (activePaths.has(dirPath))
|
|
1742
1822
|
continue;
|
|
1823
|
+
// Active-claim gate: a dir whose git admin entry vanished can still host a
|
|
1824
|
+
// LIVE agent (the 2026-08-10 incident left exactly this state behind). If a
|
|
1825
|
+
// claim still points here, it is not debris.
|
|
1826
|
+
if (protectedPaths.has(worktreePathKey(dirPath))) {
|
|
1827
|
+
result.skipped.push({ path: dirPath, reason: 'active claim' });
|
|
1828
|
+
continue;
|
|
1829
|
+
}
|
|
1743
1830
|
// This directory is not referenced by any git worktree — it's orphaned
|
|
1744
1831
|
if (dryRun) {
|
|
1745
1832
|
result.removed.push(dirPath);
|
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.25.0 on 2026-08-10T23:31:26.947Z
|
|
3
3
|
export const FACTS = {
|
|
4
|
-
"version": "1.
|
|
5
|
-
"generated_at": "2026-08-
|
|
4
|
+
"version": "1.25.0",
|
|
5
|
+
"generated_at": "2026-08-10T23:31:26.947Z",
|
|
6
6
|
"tools": {
|
|
7
|
-
"count":
|
|
8
|
-
"published_count":
|
|
7
|
+
"count": 70,
|
|
8
|
+
"published_count": 68,
|
|
9
9
|
"names": [
|
|
10
10
|
"bclaw_bootstrap",
|
|
11
11
|
"bclaw_release_notes",
|
|
@@ -34,6 +34,9 @@ export const FACTS = {
|
|
|
34
34
|
"bclaw_code_status",
|
|
35
35
|
"bclaw_code_find",
|
|
36
36
|
"bclaw_code_brief",
|
|
37
|
+
"bclaw_code_impact",
|
|
38
|
+
"bclaw_code_export",
|
|
39
|
+
"bclaw_code_outline",
|
|
37
40
|
"bclaw_code_refresh",
|
|
38
41
|
"bclaw_dispatch",
|
|
39
42
|
"bclaw_send_message",
|
|
@@ -474,7 +477,7 @@ export const FACTS = {
|
|
|
474
477
|
},
|
|
475
478
|
"bench": {
|
|
476
479
|
"schema": "brainclaw.bench.v1",
|
|
477
|
-
"generated_at": "2026-08-
|
|
480
|
+
"generated_at": "2026-08-10T23:31:25.464Z",
|
|
478
481
|
"node_version": "v24.18.0",
|
|
479
482
|
"platform": "linux-x64",
|
|
480
483
|
"repeats": 3,
|
|
@@ -483,7 +486,7 @@ export const FACTS = {
|
|
|
483
486
|
"name": "cold_onboard",
|
|
484
487
|
"volume": "empty",
|
|
485
488
|
"description": "fresh machine → init → first useful context. Baseline for time-to-first-value.",
|
|
486
|
-
"duration_ms_median":
|
|
489
|
+
"duration_ms_median": 59,
|
|
487
490
|
"payload_chars_median": 1640,
|
|
488
491
|
"payload_tokens_est_median": 410
|
|
489
492
|
},
|
|
@@ -491,9 +494,9 @@ export const FACTS = {
|
|
|
491
494
|
"name": "warm_work",
|
|
492
495
|
"volume": "medium",
|
|
493
496
|
"description": "bclaw_work consult over a real-shaped store (~200 plans / 500 handoffs / 450 claims).",
|
|
494
|
-
"duration_ms_median":
|
|
495
|
-
"payload_chars_median":
|
|
496
|
-
"payload_tokens_est_median":
|
|
497
|
+
"duration_ms_median": 88,
|
|
498
|
+
"payload_chars_median": 2625,
|
|
499
|
+
"payload_tokens_est_median": 656
|
|
497
500
|
},
|
|
498
501
|
{
|
|
499
502
|
"name": "first_edit",
|
package/dist/facts.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"generated_at": "2026-08-
|
|
2
|
+
"version": "1.25.0",
|
|
3
|
+
"generated_at": "2026-08-10T23:31:26.947Z",
|
|
4
4
|
"tools": {
|
|
5
|
-
"count":
|
|
6
|
-
"published_count":
|
|
5
|
+
"count": 70,
|
|
6
|
+
"published_count": 68,
|
|
7
7
|
"names": [
|
|
8
8
|
"bclaw_bootstrap",
|
|
9
9
|
"bclaw_release_notes",
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"bclaw_code_status",
|
|
33
33
|
"bclaw_code_find",
|
|
34
34
|
"bclaw_code_brief",
|
|
35
|
+
"bclaw_code_impact",
|
|
36
|
+
"bclaw_code_export",
|
|
37
|
+
"bclaw_code_outline",
|
|
35
38
|
"bclaw_code_refresh",
|
|
36
39
|
"bclaw_dispatch",
|
|
37
40
|
"bclaw_send_message",
|
|
@@ -472,7 +475,7 @@
|
|
|
472
475
|
},
|
|
473
476
|
"bench": {
|
|
474
477
|
"schema": "brainclaw.bench.v1",
|
|
475
|
-
"generated_at": "2026-08-
|
|
478
|
+
"generated_at": "2026-08-10T23:31:25.464Z",
|
|
476
479
|
"node_version": "v24.18.0",
|
|
477
480
|
"platform": "linux-x64",
|
|
478
481
|
"repeats": 3,
|
|
@@ -481,7 +484,7 @@
|
|
|
481
484
|
"name": "cold_onboard",
|
|
482
485
|
"volume": "empty",
|
|
483
486
|
"description": "fresh machine → init → first useful context. Baseline for time-to-first-value.",
|
|
484
|
-
"duration_ms_median":
|
|
487
|
+
"duration_ms_median": 59,
|
|
485
488
|
"payload_chars_median": 1640,
|
|
486
489
|
"payload_tokens_est_median": 410
|
|
487
490
|
},
|
|
@@ -489,9 +492,9 @@
|
|
|
489
492
|
"name": "warm_work",
|
|
490
493
|
"volume": "medium",
|
|
491
494
|
"description": "bclaw_work consult over a real-shaped store (~200 plans / 500 handoffs / 450 claims).",
|
|
492
|
-
"duration_ms_median":
|
|
493
|
-
"payload_chars_median":
|
|
494
|
-
"payload_tokens_est_median":
|
|
495
|
+
"duration_ms_median": 88,
|
|
496
|
+
"payload_chars_median": 2625,
|
|
497
|
+
"payload_tokens_est_median": 656
|
|
495
498
|
},
|
|
496
499
|
{
|
|
497
500
|
"name": "first_edit",
|
package/docs/cli.md
CHANGED
|
@@ -652,6 +652,14 @@ Search the symbol index by name (function / class / component / hook / type). Re
|
|
|
652
652
|
### `brainclaw code-map brief <target> [--limit <n>]`
|
|
653
653
|
|
|
654
654
|
Given a symbol or path, return a ranked reading list (`suggested_files_to_read`) plus related memory (decisions/traps/constraints) — what to read before editing.
|
|
655
|
+
### `brainclaw code-map export <symbol-or-path> [--direction outgoing|incoming|both]`
|
|
656
|
+
|
|
657
|
+
Export a compact **local** Code Map subgraph around one symbol or file. The default
|
|
658
|
+
is one hop in both directions; hard caps always apply (depth 4, 100 nodes, 200
|
|
659
|
+
edges), so the command never defaults to a whole-graph export. `--max-nodes`,
|
|
660
|
+
`--max-edges`, and `--depth` only tighten the result; `--min-confidence` has a
|
|
661
|
+
hard floor of 0.5. JSON keeps each edge's `kind`, `source`, and `confidence`.
|
|
662
|
+
Use `--format mermaid` for a diagram projected from that same JSON model.
|
|
655
663
|
|
|
656
664
|
```bash
|
|
657
665
|
brainclaw code-map refresh --all
|
package/docs/code-map.md
CHANGED
|
@@ -24,6 +24,7 @@ rebuilds it.
|
|
|
24
24
|
brainclaw memory.
|
|
25
25
|
- **To locate** a function/class/component/hook by name without grepping:
|
|
26
26
|
`code-map find <query>` (or `bclaw_code_find`).
|
|
27
|
+
- **To inspect a bounded local dependency neighborhood**: `code-map export <symbol-or-path>` (or `bclaw_code_export`) returns compact nodes and edges, not a repository graph dump.
|
|
27
28
|
- **To check coverage / staleness**: `code-map status` (or `bclaw_code_status`).
|
|
28
29
|
- **After pulling changes or doing work**: `code-map refresh` to bring the index
|
|
29
30
|
back to `fresh`.
|
|
@@ -95,9 +96,30 @@ Read-only. Builds a reading brief for a symbol or file: a ranked
|
|
|
95
96
|
brainclaw code-map brief App
|
|
96
97
|
```
|
|
97
98
|
|
|
99
|
+
### `brainclaw code-map export <symbol-or-path>`
|
|
100
|
+
|
|
101
|
+
Read-only export of a **local** persisted subgraph around one symbol or file. It
|
|
102
|
+
never refreshes, reparses, calls a service, or silently turns into a whole-project
|
|
103
|
+
graph export. The default is one hop in both directions; limits are always
|
|
104
|
+
reported and hard-capped at depth 4, 100 nodes, and 200 edges.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
brainclaw code-map export useAuth --direction incoming --depth 2 --json
|
|
108
|
+
brainclaw code-map export src/hooks/useAuth.ts --format mermaid
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`--direction` is `outgoing`, `incoming`, or `both` (default). `--max-nodes` and
|
|
112
|
+
`--max-edges` can tighten the response only; `--min-confidence` cannot be set
|
|
113
|
+
below 0.5. JSON is canonical and includes compact `nodes`, `edges`, root IDs,
|
|
114
|
+
limits, truncation flags, and a freshness badge. Every edge retains `kind`,
|
|
115
|
+
`source`, and `confidence`; low-confidence nodes/relations are excluded so an
|
|
116
|
+
extraction heuristic cannot appear indistinguishable from a high-confidence
|
|
117
|
+
relation. `--format mermaid` adds a Mermaid rendering projected from those exact
|
|
118
|
+
JSON nodes and edges—never from a second traversal.
|
|
119
|
+
|
|
98
120
|
## MCP tools
|
|
99
121
|
|
|
100
|
-
Capable agents should prefer the MCP surface. The
|
|
122
|
+
Capable agents should prefer the MCP surface. The read tools mirror the CLI and
|
|
101
123
|
all return a `freshness_badge`:
|
|
102
124
|
|
|
103
125
|
| Tool | Kind | Purpose |
|
|
@@ -105,6 +127,7 @@ all return a `freshness_badge`:
|
|
|
105
127
|
| `bclaw_code_status` | read | Store presence, freshness badge, index stats. Never refreshes. |
|
|
106
128
|
| `bclaw_code_find` | read | Ranked symbol-index search (`query`, optional `limit`). Never refreshes. |
|
|
107
129
|
| `bclaw_code_brief` | read | Reading brief for a symbol/path (`target`, optional `limit`, files capped at 12). Never refreshes. |
|
|
130
|
+
| `bclaw_code_export` | read | Bounded local subgraph around required `target`; direction/depth/node/edge caps, confidence filtering, and optional Mermaid projection. Never refreshes. |
|
|
108
131
|
| `bclaw_code_refresh` | write | Rebuild the index. `scope` = `"changed"` (default) or `"all"`. Fails fast on a live lock. |
|
|
109
132
|
|
|
110
133
|
The read tools never trigger a parse — if `bclaw_code_status` /
|
package/docs/integrations/mcp.md
CHANGED
|
@@ -25,7 +25,7 @@ The default dynamic workflow is:
|
|
|
25
25
|
1. `bclaw_work` to start the session and load the relevant context in one call (returns compact payload by default — pass `compact: false` for the full context result)
|
|
26
26
|
2. `bclaw_context({ kind: "execution" })` early when the agent needs local tooling signals or package update visibility
|
|
27
27
|
3. `bclaw_context({ kind: "memory" })`, `bclaw_context({ kind: "board" })`, or `bclaw_context({ kind: "delta" })` when the target path changes or full memory is needed beyond the compact summary
|
|
28
|
-
4. `bclaw_code_brief({ target })` / `bclaw_code_find({ query })` before editing unfamiliar code — get a ranked reading list (with related decisions/traps) and locate symbols from the Code Map instead of grepping blind. A `missing_index` badge means run `bclaw_code_refresh` first. See [code map](../code-map.md)
|
|
28
|
+
4. `bclaw_code_brief({ target })` / `bclaw_code_find({ query })` before editing unfamiliar code — get a ranked reading list (with related decisions/traps) and locate symbols from the Code Map instead of grepping blind. Use `bclaw_code_impact({ target, depth: 2 })` when you need an explainable local blast radius; its `tests_for` separates resolved imports from low-confidence filename suggestions. Use `bclaw_code_export({ target, direction, depth, maxNodes, maxEdges })` when you need a compact bounded subgraph; every returned edge keeps `kind`, `source`, and `confidence`, and `format: 'mermaid'` is projected from that same JSON model. A `missing_index` badge means run `bclaw_code_refresh` first. See [code map](../code-map.md)
|
|
29
29
|
5. `bclaw_find` / `bclaw_get` / `bclaw_create` / `bclaw_update` / `bclaw_remove` / `bclaw_transition` for entity reads and writes
|
|
30
30
|
6. `bclaw_coordinate`, `bclaw_dispatch`, or `bclaw_loop` for assign, consult, review, reroute, summarize, dispatch, or multi-turn loop flows
|
|
31
31
|
7. `bclaw_read_inbox` when resuming delegated work
|
|
@@ -47,7 +47,7 @@ Every tool has one of three tiers in its `annotations.tier` field:
|
|
|
47
47
|
- **standard** — Day-to-day coordination tools: plans, claims, messaging, sequences, dispatch, review, memory. Returned by default alongside facades.
|
|
48
48
|
- **advanced** — Specialized governance, audit, registry, and power tools.
|
|
49
49
|
|
|
50
|
-
By default, `tools/list` returns **facade + standard** tools (
|
|
50
|
+
By default, `tools/list` returns **facade + standard** tools (49 tools). To get all tools including advanced, pass `{ "catalog": "all" }`, `{ "include": "all" }`, or `{ "advanced": true }`. To filter by a single tier, pass `{ "tier": "facade" }`, `{ "tier": "standard" }`, or `{ "tier": "advanced" }`.
|
|
51
51
|
|
|
52
52
|
Published tools remain callable regardless of catalog filtering — the tier only affects discovery via `tools/list`.
|
|
53
53
|
|
|
@@ -111,6 +111,9 @@ Each tool also has an `annotations.category` field: `session`, `context`, `memor
|
|
|
111
111
|
| `bclaw_code_status` | discovery | Code Map freshness badge + index stats (store presence, files/nodes/edges) |
|
|
112
112
|
| `bclaw_code_find` | discovery | Search the Code Map symbol index by name (function/class/component/hook/type) |
|
|
113
113
|
| `bclaw_code_brief` | discovery | Ranked reading list + related decisions/traps before editing a symbol or path |
|
|
114
|
+
| `bclaw_code_impact` | discovery | Explainable local blast radius from resolved imports: definition, direct dependents, opt-in bounded transitives, tests, and count-based risk |
|
|
115
|
+
| `bclaw_code_export` | discovery | Compact bounded local nodes/edges around one symbol or file; preserves edge kind/source/confidence, with optional Mermaid projection |
|
|
116
|
+
| `bclaw_code_outline` | discovery | Source-ordered symbols of one indexed file (span, exported, confidence) — no reparse |
|
|
114
117
|
| `bclaw_code_refresh` | discovery | Rebuild the Code Map index (`scope: changed \| all`) |
|
|
115
118
|
|
|
116
119
|
See [code map](../code-map.md) for the full Code Map reference (CLI, freshness model, supported languages).
|
|
@@ -408,7 +408,17 @@ will still succeed. A follow-up PR will strip the dead handler code.
|
|
|
408
408
|
changelog records the published MCP surface fingerprint. When a tool
|
|
409
409
|
name, tier, category, or input schema changes, the test fails until
|
|
410
410
|
this section is updated.
|
|
411
|
-
- MCP public surface fingerprint: `sha256:
|
|
411
|
+
- MCP public surface fingerprint: `sha256:b8dbb80bae8f6e36`
|
|
412
|
+
(updated 2026-08-10 for pln#665: `bclaw_code_export` — additive Tier-B read tool for a required, bounded local Code Map subgraph. Its target, direction, depth, node/edge caps, confidence threshold, and optional Mermaid projection are explicit; JSON retains each relation's kind/source/confidence and never defaults to a whole-graph export.)
|
|
413
|
+
Previous: `sha256:9ed35ed6cc49ea9a`
|
|
414
|
+
(updated 2026-08-10 for pln#661: `bclaw_code_impact` — additive Tier-B read tool
|
|
415
|
+
for local, resolved-import impact analysis. It exposes definition, direct causes,
|
|
416
|
+
optional bounded transitives, tests, and a count-based risk score; its required
|
|
417
|
+
`target` plus optional `depth` and `limit` input surface are explicitly bounded.)
|
|
418
|
+
Previous: `sha256:2a9f7d4cd72609df`
|
|
419
|
+
(updated 2026-08-10 for pln#660: `bclaw_code_outline` — new Tier-B read tool,
|
|
420
|
+
source-ordered symbols of one indexed file from the existing shard; no reparse,
|
|
421
|
+
no mutation, bounded output. Purely additive.)
|
|
412
422
|
(updated 2026-07-25 for pln#632: `bclaw_loop` gains the `bind` intent — an
|
|
413
423
|
implementation loop dispatches its linked sequence and advances bind→execute — plus
|
|
414
424
|
its typed inputSchema properties `dry_run`, `lanes`, `auto_execute`, `model`, and
|