brainclaw 1.28.7 → 1.28.8

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.
Binary file
package/dist/cli.js CHANGED
@@ -180,14 +180,18 @@ program
180
180
  }
181
181
  if (!skipResolution) {
182
182
  // Resolve effective cwd (explicit > BRAINCLAW_PROJECT > active-project > process.cwd)
183
+ const resolutionStarted = performance.now();
183
184
  const effectiveCwd = resolveEffectiveCwd({ explicitCwd });
185
+ logger.debug(`Startup project resolution: ${(performance.now() - resolutionStarted).toFixed(1)}ms`);
184
186
  if (effectiveCwd !== process.cwd()) {
185
187
  // Change process.cwd() so all commands resolve the correct store
186
188
  // without needing individual --cwd plumbing
187
189
  process.chdir(effectiveCwd);
188
190
  logger.info(`Resolved effective cwd: ${effectiveCwd}`);
189
191
  }
192
+ const cleanupStarted = performance.now();
190
193
  const removed = cleanOrphanFiles(memoryDir());
194
+ logger.debug(`Startup orphan cleanup: ${(performance.now() - cleanupStarted).toFixed(1)}ms`);
191
195
  if (removed > 0) {
192
196
  logger.info(`Cleaned ${removed} orphan lock/tmp file(s) in ${memoryDir()}`);
193
197
  }
package/dist/core/io.js CHANGED
@@ -519,30 +519,32 @@ export function writeFileAtomic(filepath, content, options = {}) {
519
519
  * Call once at CLI startup. Returns count of removed files.
520
520
  */
521
521
  export function cleanOrphanFiles(dirPath) {
522
+ return cleanOrphanDirectory(dirPath, true);
523
+ }
524
+ function cleanOrphanDirectory(dirPath, root) {
522
525
  let removed = 0;
523
- if (!fs.existsSync(dirPath))
524
- return 0;
525
- // Clean .tmp files (residual from crashed writeFileAtomic)
526
+ // Historical/derived trees are not startup-maintenance targets. Their writers
527
+ // reclaim stale locks when acquiring them; scanning their contents here makes
528
+ // connection latency proportional to Git history and Code Map size.
529
+ const excluded = new Set(['.git', 'code', 'archive', 'gc-backups', 'migration-backups', 'recovery-backups']);
526
530
  try {
527
- for (const entry of fs.readdirSync(dirPath)) {
528
- const full = path.join(dirPath, entry);
529
- let stat;
530
- try {
531
- stat = fs.statSync(full);
531
+ for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
532
+ const full = path.join(dirPath, entry.name);
533
+ // Dirents avoid a stat per entity and do not follow symlinks/junctions.
534
+ if (entry.isDirectory()) {
535
+ const name = entry.name.toLowerCase();
536
+ if (name !== '.git' && !(root && excluded.has(name)))
537
+ removed += cleanOrphanDirectory(full, false);
532
538
  }
533
- catch {
534
- continue;
535
- }
536
- if (entry.endsWith('.tmp') && stat.isFile() && shouldRemoveTmp(entry, stat)) {
539
+ else if (entry.isFile() && tempOwnerPid(entry.name)) {
537
540
  try {
538
- fs.unlinkSync(full);
539
- removed++;
541
+ const stat = fs.lstatSync(full);
542
+ if (stat.isFile() && shouldRemoveTmp(entry.name, stat)) {
543
+ fs.unlinkSync(full);
544
+ removed++;
545
+ }
540
546
  }
541
- catch { /* already gone */ }
542
- }
543
- // Recurse into subdirectories
544
- if (stat.isDirectory()) {
545
- removed += cleanOrphanFiles(full);
547
+ catch { /* disappeared or unreadable — skip */ }
546
548
  }
547
549
  }
548
550
  }
package/dist/facts.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // Generated by scripts/emit-site-facts.mjs at build time. Do not edit manually.
2
- // Source: brainclaw v1.28.7 on 2026-08-31T10:15:17.297Z
2
+ // Source: brainclaw v1.28.8 on 2026-09-09T12:16:44.520Z
3
3
  export const FACTS = {
4
- "version": "1.28.7",
5
- "generated_at": "2026-08-31T10:15:17.297Z",
4
+ "version": "1.28.8",
5
+ "generated_at": "2026-09-09T12:16:44.520Z",
6
6
  "tools": {
7
7
  "count": 71,
8
8
  "published_count": 69,
@@ -479,8 +479,8 @@ export const FACTS = {
479
479
  },
480
480
  "bench": {
481
481
  "schema": "brainclaw.bench.v1",
482
- "generated_at": "2026-08-31T10:15:15.107Z",
483
- "node_version": "v24.19.0",
482
+ "generated_at": "2026-09-09T12:16:42.258Z",
483
+ "node_version": "v24.20.0",
484
484
  "platform": "linux-x64",
485
485
  "repeats": 3,
486
486
  "scenarios": [
@@ -488,7 +488,7 @@ export const FACTS = {
488
488
  "name": "cold_onboard",
489
489
  "volume": "empty",
490
490
  "description": "fresh machine → init → first useful context. Baseline for time-to-first-value.",
491
- "duration_ms_median": 82,
491
+ "duration_ms_median": 88,
492
492
  "payload_chars_median": 1640,
493
493
  "payload_tokens_est_median": 410
494
494
  },
@@ -496,7 +496,7 @@ export const FACTS = {
496
496
  "name": "warm_work",
497
497
  "volume": "medium",
498
498
  "description": "bclaw_work consult over a real-shaped store (~200 plans / 500 handoffs / 450 claims).",
499
- "duration_ms_median": 127,
499
+ "duration_ms_median": 136,
500
500
  "payload_chars_median": 2626,
501
501
  "payload_tokens_est_median": 657
502
502
  },
@@ -504,7 +504,7 @@ export const FACTS = {
504
504
  "name": "first_edit",
505
505
  "volume": "medium",
506
506
  "description": "code_find + code_brief on the fresh-agent path (missing index, first touch).",
507
- "duration_ms_median": 13,
507
+ "duration_ms_median": 12,
508
508
  "payload_chars_median": 1680,
509
509
  "payload_tokens_est_median": 420
510
510
  }
package/dist/facts.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.28.7",
3
- "generated_at": "2026-08-31T10:15:17.297Z",
2
+ "version": "1.28.8",
3
+ "generated_at": "2026-09-09T12:16:44.520Z",
4
4
  "tools": {
5
5
  "count": 71,
6
6
  "published_count": 69,
@@ -477,8 +477,8 @@
477
477
  },
478
478
  "bench": {
479
479
  "schema": "brainclaw.bench.v1",
480
- "generated_at": "2026-08-31T10:15:15.107Z",
481
- "node_version": "v24.19.0",
480
+ "generated_at": "2026-09-09T12:16:42.258Z",
481
+ "node_version": "v24.20.0",
482
482
  "platform": "linux-x64",
483
483
  "repeats": 3,
484
484
  "scenarios": [
@@ -486,7 +486,7 @@
486
486
  "name": "cold_onboard",
487
487
  "volume": "empty",
488
488
  "description": "fresh machine → init → first useful context. Baseline for time-to-first-value.",
489
- "duration_ms_median": 82,
489
+ "duration_ms_median": 88,
490
490
  "payload_chars_median": 1640,
491
491
  "payload_tokens_est_median": 410
492
492
  },
@@ -494,7 +494,7 @@
494
494
  "name": "warm_work",
495
495
  "volume": "medium",
496
496
  "description": "bclaw_work consult over a real-shaped store (~200 plans / 500 handoffs / 450 claims).",
497
- "duration_ms_median": 127,
497
+ "duration_ms_median": 136,
498
498
  "payload_chars_median": 2626,
499
499
  "payload_tokens_est_median": 657
500
500
  },
@@ -502,7 +502,7 @@
502
502
  "name": "first_edit",
503
503
  "volume": "medium",
504
504
  "description": "code_find + code_brief on the fresh-agent path (missing index, first touch).",
505
- "duration_ms_median": 13,
505
+ "duration_ms_median": 12,
506
506
  "payload_chars_median": 1680,
507
507
  "payload_tokens_est_median": 420
508
508
  }
@@ -564,4 +564,19 @@ The CLI remains valuable for:
564
564
  - release and packaging
565
565
  - debugging and fallback access
566
566
 
567
+ ### Diagnose MCP startup
568
+
569
+ Measure startup with a fresh subprocess rather than timing a tool call on an
570
+ existing connection:
571
+
572
+ ```bash
573
+ node scripts/bench-mcp-startup.mjs --cwd . --cli dist/cli.js --repeats 3 --budget-ms 20000
574
+ ```
575
+
576
+ The benchmark covers process launch, `initialize`, the initialized
577
+ notification, and `tools/list`. It requires an explicit project directory
578
+ because normal CLI startup maintenance may update that store. Pass `--debug`
579
+ before the `mcp` command to report project-resolution and orphan-cleanup
580
+ durations on stderr without corrupting JSON-RPC stdout.
581
+
567
582
  But for capable agents, MCP is the first-class path for both reads and writes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainclaw",
3
- "version": "1.28.7",
3
+ "version": "1.28.8",
4
4
  "description": "Shared project memory for humans and coding agents.",
5
5
  "type": "module",
6
6
  "repository": {