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.
Files changed (63) hide show
  1. package/README.md +16 -263
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli/register-capture.js +209 -0
  4. package/dist/cli/register-code-map.js +19 -0
  5. package/dist/cli/register-coordination.js +472 -0
  6. package/dist/cli/register-federation.js +258 -0
  7. package/dist/cli/register-lifecycle.js +436 -0
  8. package/dist/cli/register-memory-context.js +502 -0
  9. package/dist/cli/register-planning.js +167 -0
  10. package/dist/cli/register-review.js +149 -0
  11. package/dist/cli/shared.js +5 -0
  12. package/dist/cli.js +212 -2015
  13. package/dist/commands/dispatch-watch.js +25 -2
  14. package/dist/commands/harvest.js +31 -6
  15. package/dist/commands/mcp-catalog.js +1438 -0
  16. package/dist/commands/mcp-contract.js +33 -0
  17. package/dist/commands/mcp-presentation.js +27 -0
  18. package/dist/commands/mcp-read-handlers.js +72 -36
  19. package/dist/commands/mcp-write-admin.js +328 -0
  20. package/dist/commands/mcp-write-claims.js +864 -0
  21. package/dist/commands/mcp-write-coordination.js +1825 -0
  22. package/dist/commands/mcp-write-entities.js +620 -0
  23. package/dist/commands/mcp-write-memory.js +451 -0
  24. package/dist/commands/mcp-write-sequences.js +116 -0
  25. package/dist/commands/mcp-write-support.js +367 -0
  26. package/dist/commands/mcp.js +261 -5570
  27. package/dist/commands/update-handoff.js +28 -42
  28. package/dist/core/agent-capability.js +31 -14
  29. package/dist/core/agent-files.js +1 -1
  30. package/dist/core/agent-registry.js +51 -3
  31. package/dist/core/claims.js +18 -0
  32. package/dist/core/coordination.js +5 -2
  33. package/dist/core/cross-project.js +35 -1
  34. package/dist/core/dispatcher.js +34 -20
  35. package/dist/core/entity-operations.js +335 -12
  36. package/dist/core/entity-registry.js +72 -9
  37. package/dist/core/execution.js +28 -4
  38. package/dist/core/facade-schema.js +30 -4
  39. package/dist/core/federation-cloud.js +142 -11
  40. package/dist/core/federation-outbox.js +292 -0
  41. package/dist/core/federation-signing.js +115 -0
  42. package/dist/core/handoff-review.js +35 -0
  43. package/dist/core/io.js +6 -0
  44. package/dist/core/protocol-tool-policy.js +113 -0
  45. package/dist/core/review-loop-close.js +115 -0
  46. package/dist/core/schema.js +25 -2
  47. package/dist/core/security-detectors.js +35 -6
  48. package/dist/core/security.js +32 -12
  49. package/dist/core/worktree.js +98 -9
  50. package/dist/facts.js +13 -11
  51. package/dist/facts.json +12 -10
  52. package/docs/PROTOCOL.md +7 -3
  53. package/docs/concepts/coordinator-runbook.md +3 -0
  54. package/docs/concepts/dispatch-lifecycle.md +4 -4
  55. package/docs/concepts/loop-engine.md +3 -1
  56. package/docs/concepts/troubleshooting.md +1 -1
  57. package/docs/integrations/codex.md +3 -3
  58. package/docs/integrations/overview.md +1 -1
  59. package/docs/mcp-schema-changelog.md +153 -2
  60. package/docs/playbooks/orchestration.md +1 -1
  61. package/docs/product/entity-model-audit.md +3 -2
  62. package/docs/security.md +22 -1
  63. package/package.json +3 -1
@@ -0,0 +1,436 @@
1
+ import { runInit } from '../commands/init.js';
2
+ import { runSetup, runSetupMachine } from '../commands/setup.js';
3
+ import { runUpgrade } from '../commands/upgrade.js';
4
+ import { patchAllMcpConfigs } from '../core/agent-files.js';
5
+ import { runReconcile } from '../commands/reconcile.js';
6
+ import { buildMachineProfile, saveMachineProfile, loadMachineProfile, renderMachineProfileSummary } from '../core/machine-profile.js';
7
+ import { buildAgentInventory, saveAgentInventory, loadAgentInventory, renderAgentInventorySummary } from '../core/agent-inventory.js';
8
+ import { scanAndRegister, scanProject, upsertProject, loadGlobalRegistry, renderGlobalRegistrySummary } from '../core/global-registry.js';
9
+ import { runStatus } from '../commands/status.js';
10
+ import { runDoctor, runDoctorSpawnCheck } from '../commands/doctor.js';
11
+ import { runRepair } from '../commands/repair.js';
12
+ import { runStale } from '../commands/stale.js';
13
+ import { runRebuild } from '../commands/rebuild.js';
14
+ import { runVersion } from '../commands/version.js';
15
+ import { runReleaseNotes } from '../commands/release-notes.js';
16
+ import { runUninstall } from '../commands/uninstall.js';
17
+ import { runEnv } from '../commands/env.js';
18
+ import { runCheckConstraints } from '../commands/check-constraints.js';
19
+ import { runCheckPolicy } from '../commands/check-policy.js';
20
+ import { runCheckSecurity } from '../commands/check-security.js';
21
+ import { runSetupSecurity } from '../commands/setup-security.js';
22
+ import { runInstallHooks } from '../commands/install-hooks.js';
23
+ import { runMcp } from '../commands/mcp.js';
24
+ import { runHooks } from '../commands/hooks.js';
25
+ import { runDiscover } from '../commands/discover.js';
26
+ import { runMigrate } from '../commands/migrate.js';
27
+ export function registerLifecycleCommands(program) {
28
+ // --- init ---
29
+ program
30
+ .command('init')
31
+ .description('Initialize or refresh project memory in .brainclaw/ storage directory')
32
+ .option('-y, --yes', 'Skip interactive wizard and use defaults')
33
+ .option('--force', 'Rebuild managed Brainclaw config and generated files from defaults')
34
+ .option('--compact', 'Enable compact markdown mode')
35
+ .option('--topology <mode>', 'Topology mode: embedded, sidecar, local-only')
36
+ .option('--project-mode <mode>', 'Project mode: single-project, multi-project, auto')
37
+ .option('--project-strategy <strategy>', 'Project strategy for multi-project mode: manual, folder')
38
+ .option('--no-analyze-repo', 'Skip repository analysis when suggesting a project mode')
39
+ .option('--no-ai-scan', 'Skip AI surface scan during init')
40
+ .option('--scan', 'Scan subdirectories for service boundaries and suggest init targets')
41
+ .option('--cwd <path>', 'Override working directory for init scaffolding (parity with other CLI commands)')
42
+ .action(async (options) => {
43
+ // pln#515 step 1: commander binds --cwd to the program-level option even
44
+ // when it appears after `init`, so resolve via program.opts() and feed
45
+ // runInit's existing options.cwd plumb.
46
+ const programCwd = program.opts().cwd;
47
+ await runInit({ ...options, cwd: options.cwd ?? programCwd });
48
+ });
49
+ // --- setup ---
50
+ program
51
+ .command('setup')
52
+ .description('Interactive onboarding wizard — machine bootstrap plus multi-repo init')
53
+ .option('--roots <paths>', 'Comma-separated root directories to scan (skips interactive prompt)')
54
+ .option('--agents <agents>', 'Agents to configure: all, detected, or comma-separated names')
55
+ .option('--repos <mode>', 'Repo selection: all, current, or comma-separated numbers')
56
+ .option('-y, --yes', 'Accept all defaults non-interactively')
57
+ .action(async (options) => {
58
+ await runSetup(options);
59
+ });
60
+ // --- setup-machine ---
61
+ program
62
+ .command('setup-machine')
63
+ .description('Machine-only onboarding — detect/configure agents and MCP without scanning or initializing repositories')
64
+ .option('--agents <agents>', 'Agents to configure: all, detected, or comma-separated names')
65
+ .option('-y, --yes', 'Accept all defaults non-interactively')
66
+ .action(async (options) => {
67
+ await runSetupMachine(options);
68
+ });
69
+ // --- upgrade ---
70
+ program
71
+ .command('upgrade')
72
+ .description('Upgrade project memory structure and refresh managed workspace agent files without losing data')
73
+ .option('--json', 'Output as JSON')
74
+ .option('--dry-run', 'Show what would be done without making changes')
75
+ .option('--self-update', 'Check for a newer brainclaw package version and install it before upgrading memory')
76
+ .option('--to <version>', 'One-shot target schema version (e.g. --to=1.0). Real runs require a backup.')
77
+ .option('--backup', 'Create a timestamped backup of .brainclaw/ before any write (always on for --to runs)')
78
+ .option('--no-backup', 'Disable the automatic backup for housekeeping-only upgrade runs')
79
+ .option('--rollback', 'Restore the most recent backup, park the current live store, exit')
80
+ .option('--yes', 'Skip interactive confirmations (reserved for later prompt additions)')
81
+ .action((options) => {
82
+ runUpgrade({
83
+ json: options.json,
84
+ dryRun: options.dryRun,
85
+ selfUpdate: options.selfUpdate,
86
+ to: options.to,
87
+ backup: options.backup,
88
+ rollback: options.rollback,
89
+ yes: options.yes,
90
+ });
91
+ });
92
+ // --- patch-configs ---
93
+ program
94
+ .command('patch-configs')
95
+ .description('Patch all MCP config files to use the current brainclaw binary path')
96
+ .option('--json', 'Output as JSON')
97
+ .action((options) => {
98
+ const cwd = process.env.BRAINCLAW_CWD ?? process.cwd();
99
+ const results = patchAllMcpConfigs(cwd);
100
+ if (options.json) {
101
+ console.log(JSON.stringify(results, null, 2));
102
+ }
103
+ else if (results.length === 0) {
104
+ console.log('✔ All MCP configs are already up to date.');
105
+ }
106
+ else {
107
+ for (const r of results) {
108
+ const tag = r.created ? 'created' : 'updated';
109
+ console.log(`✔ ${r.filePath} (${tag}) — ${r.label}`);
110
+ }
111
+ console.log(`\n${results.length} MCP config(s) patched.`);
112
+ }
113
+ });
114
+ // --- machine-profile ---
115
+ program
116
+ .command('machine-profile')
117
+ .description('Detect and persist machine capabilities (OS, shells, git users, SSH keys, toolchains, WSL, AI surfaces)')
118
+ .option('--refresh', 'Force regeneration even if profile exists')
119
+ .option('--json', 'Output as JSON')
120
+ .action(async (options) => {
121
+ const existing = loadMachineProfile();
122
+ if (existing && !options.refresh) {
123
+ if (options.json) {
124
+ console.log(JSON.stringify(existing, null, 2));
125
+ }
126
+ else {
127
+ console.log(renderMachineProfileSummary(existing));
128
+ console.log('\nUse --refresh to regenerate.');
129
+ }
130
+ return;
131
+ }
132
+ console.log('Detecting machine capabilities...');
133
+ const profile = buildMachineProfile();
134
+ const filePath = saveMachineProfile(profile);
135
+ if (options.json) {
136
+ console.log(JSON.stringify(profile, null, 2));
137
+ }
138
+ else {
139
+ console.log(renderMachineProfileSummary(profile));
140
+ console.log(`\n✔ Profile saved to ${filePath}`);
141
+ }
142
+ });
143
+ // --- agent-inventory ---
144
+ program
145
+ .command('agent-inventory')
146
+ .description('Detect all installed AI coding agents and their capabilities')
147
+ .option('--refresh', 'Force regeneration even if inventory exists')
148
+ .option('--json', 'Output as JSON')
149
+ .action(async (options) => {
150
+ const existing = loadAgentInventory();
151
+ if (existing && !options.refresh) {
152
+ if (options.json) {
153
+ console.log(JSON.stringify(existing, null, 2));
154
+ }
155
+ else {
156
+ console.log(renderAgentInventorySummary(existing));
157
+ console.log('\nUse --refresh to regenerate.');
158
+ }
159
+ return;
160
+ }
161
+ console.log('Detecting installed agents...');
162
+ const inventory = buildAgentInventory();
163
+ const filePath = saveAgentInventory(inventory);
164
+ if (options.json) {
165
+ console.log(JSON.stringify(inventory, null, 2));
166
+ }
167
+ else {
168
+ console.log(renderAgentInventorySummary(inventory));
169
+ console.log(`\n✔ Inventory saved to ${filePath}`);
170
+ }
171
+ });
172
+ // --- projects ---
173
+ program
174
+ .command('projects')
175
+ .description('List all brainclaw-initialized projects on this machine')
176
+ .option('--scan <roots>', 'Comma-separated directories to scan for projects')
177
+ .option('--register', 'Register the current project in the global registry')
178
+ .option('--json', 'Output as JSON')
179
+ .action(async (options) => {
180
+ if (options.register) {
181
+ const entry = scanProject(process.cwd());
182
+ if (!entry) {
183
+ console.error('No brainclaw project found in current directory. Run brainclaw init first.');
184
+ process.exit(1);
185
+ }
186
+ upsertProject(entry);
187
+ console.log(`✔ Registered ${entry.project_name} (${entry.project_id})`);
188
+ return;
189
+ }
190
+ if (options.scan) {
191
+ const roots = options.scan.split(',').map((r) => r.trim());
192
+ console.log(`Scanning ${roots.join(', ')}...`);
193
+ const registry = scanAndRegister(roots);
194
+ if (options.json) {
195
+ console.log(JSON.stringify(registry, null, 2));
196
+ }
197
+ else {
198
+ console.log(renderGlobalRegistrySummary(registry));
199
+ }
200
+ return;
201
+ }
202
+ // Default: show existing registry
203
+ const registry = loadGlobalRegistry();
204
+ if (!registry || registry.projects.length === 0) {
205
+ console.log('No projects registered. Use --scan <roots> or --register to add projects.');
206
+ return;
207
+ }
208
+ if (options.json) {
209
+ console.log(JSON.stringify(registry, null, 2));
210
+ }
211
+ else {
212
+ console.log(renderGlobalRegistrySummary(registry));
213
+ }
214
+ });
215
+ // --- status ---
216
+ program
217
+ .command('status')
218
+ .description('Show project memory status')
219
+ .option('--json', 'Output as JSON')
220
+ .option('--markdown', 'Output as Markdown')
221
+ .action((options) => {
222
+ runStatus(options);
223
+ });
224
+ // --- doctor ---
225
+ program
226
+ .command('doctor')
227
+ .description('Check memory health and security')
228
+ .option('--json', 'Output as JSON dashboard')
229
+ .option('--migration-check', 'Report versioned documents that need schema migration')
230
+ .option('--fix-agent-ignore', 'Add missing .gitignore entries for generated local Brainclaw agent files')
231
+ .option('--fix-hooks', 'Purge stale/broken/duplicate brainclaw session hooks across all Claude Code settings scopes (user + cwd) and rewrite the canonical ones')
232
+ .option('--fix', 'Fix auto-resolvable issues (e.g. drifting MCP configs)')
233
+ .option('--repair', 'Rebuild dist/ when the MCP runtime is missing or stale')
234
+ .option('--after-migration', 'Run the v1.0 post-migration health check only (exits non-zero on any failure)')
235
+ .option('--dispatch', 'Run dispatch-health diagnostic only: reconcile open agent_runs and report stuck/unverified/silent failures (pln#496 step stp_8c072d75)')
236
+ .option('--verify-journal', 'Phase-2 cutover gate (pln#565): rebuild state from the event journal and diff vs live projections; exits non-zero on any drift')
237
+ .option('--spawn-check', 'Real spawn round-trip per installed agent before dispatch (pln#520 step 2): validates delivery + handshake on this host, exits non-zero on any installed-agent failure')
238
+ .option('--spawn-check-timeout <ms>', 'Per-agent timeout for --spawn-check (default 15000)', parseInt)
239
+ .option('--hygiene', 'Coordination-hygiene snapshot (pln#602): counts per family, park candidates, serve-count aging stats. Read-only.')
240
+ .action(async (options) => {
241
+ if (options.spawnCheck) {
242
+ await runDoctorSpawnCheck({ cwd: options.cwd, json: options.json, timeoutMs: options.spawnCheckTimeout });
243
+ return;
244
+ }
245
+ runDoctor({ ...options, afterMigration: options.afterMigration, dispatch: options.dispatch, verifyJournal: options.verifyJournal, hygiene: options.hygiene });
246
+ });
247
+ // --- repair (Phase 4 Sprint 2 Lane C / pln#397) ---
248
+ program
249
+ .command('repair')
250
+ .description('Apply safe, non-destructive fixes for the repair candidates surfaced by doctor')
251
+ .option('--dry-run', 'Print the plan without executing anything')
252
+ .option('--include-unsafe', 'Also apply candidates flagged unsafe (preserves data but requires confirmation)')
253
+ .option('--json', 'Output as JSON')
254
+ .action((options) => {
255
+ runRepair({
256
+ dryRun: options.dryRun,
257
+ includeUnsafe: options.includeUnsafe,
258
+ json: options.json,
259
+ });
260
+ });
261
+ // --- stale (Phase 4 Sprint 1 Lane A / pln#390) ---
262
+ program
263
+ .command('stale [subcommand] [id]')
264
+ .description('List or resolve stale memory items (plans, traps, handoffs, candidates, runtime notes). Subcommands: list (default), resolve <id>.')
265
+ .option('--json', 'Output as JSON')
266
+ .action((subcommand, id, options) => {
267
+ runStale(subcommand, id, { json: options.json });
268
+ });
269
+ // --- version ---
270
+ program
271
+ .command('version')
272
+ .description('Show the installed brainclaw version and the project version policy')
273
+ .option('--check', 'Check the configured installable update source')
274
+ .option('--publish-local', 'Create/update the local installable .releases channel via npm pack')
275
+ .option('--release-notes <text>', 'Attach plain-text release notes to the generated local-pack manifest')
276
+ .option('--agent-release-notes <json>', 'Attach structured agent-first release notes (JSON) to the generated local-pack manifest')
277
+ .option('--auto-release-notes', 'Auto-generate agent-first release notes from git log (use with --publish-local)')
278
+ .option('--json', 'Output as JSON')
279
+ .action((options) => {
280
+ runVersion(options);
281
+ });
282
+ // --- release-notes ---
283
+ program
284
+ .command('release-notes')
285
+ .description('Show or generate agent-first release notes')
286
+ .option('--generate', 'Generate release notes from git log instead of showing configured ones')
287
+ .option('--since <ref>', 'Git ref to generate from (default: last version tag)')
288
+ .option('--json', 'Output as JSON')
289
+ .action((options) => {
290
+ runReleaseNotes(options);
291
+ });
292
+ // --- uninstall ---
293
+ program
294
+ .command('uninstall')
295
+ .description('Remove brainclaw from a project and/or machine')
296
+ .option('--project', 'Remove brainclaw from the current project (.brainclaw/, agent files, configs)')
297
+ .option('--machine', 'Remove brainclaw global config (~/.brainclaw/)')
298
+ .option('-y, --yes', 'Skip confirmation prompts')
299
+ .action(async (options) => {
300
+ await runUninstall(options);
301
+ });
302
+ // --- rebuild ---
303
+ program
304
+ .command('rebuild')
305
+ .description('Rebuild project.md from canonical memory state')
306
+ .action(() => {
307
+ runRebuild();
308
+ });
309
+ // --- env ---
310
+ program
311
+ .command('env')
312
+ .description('Show the local execution context and optionally detected agent tooling')
313
+ .option('--json', 'Output as JSON')
314
+ .option('--agent-tooling', 'Include AGENTS.md, local skills, and local MCP inventory')
315
+ .action((options) => {
316
+ runEnv({ ...options, agentTooling: options.agentTooling });
317
+ });
318
+ // --- check-constraints ---
319
+ program
320
+ .command('check-constraints')
321
+ .description('Check if staged files (or given files) violate active constraints')
322
+ .option('--staged', 'Check git staged files (git diff --cached --name-only)')
323
+ .option('--files <files...>', 'Explicit list of files to check')
324
+ .option('--json', 'Output as JSON')
325
+ .action((options) => {
326
+ runCheckConstraints({ staged: options.staged, files: options.files, json: options.json });
327
+ });
328
+ // --- check-policy ---
329
+ program
330
+ .command('check-policy')
331
+ .description('Pre-execution policy check: verify claims, constraints, traps and instructions for a scope')
332
+ .requiredOption('--scope <path>', 'File or directory scope to check')
333
+ .option('--agent <name>', 'Agent name to check claims for')
334
+ .option('--agent-id <id>', 'Agent id to check claims for')
335
+ .option('--action <action>', 'Intended action: edit, create, delete')
336
+ .option('--json', 'Output as JSON')
337
+ .action((options) => {
338
+ runCheckPolicy({
339
+ scope: options.scope,
340
+ agent: options.agent,
341
+ agentId: options.agentId,
342
+ action: options.action,
343
+ json: options.json,
344
+ });
345
+ });
346
+ // --- check-security ---
347
+ program
348
+ .command('check-security')
349
+ .description('Check supply chain security scores for packages via Socket.dev')
350
+ .option('--packages <names>', 'Comma-separated package names (e.g. "axios,express" or "axios@1.14.1")')
351
+ .option('--requirements <file>', 'Path to a pip-style requirements.txt to scan')
352
+ .option('--lockfile <file>', 'Path to a package-lock.json (npm) to scan top-level deps')
353
+ .option('--ecosystem <type>', 'Package ecosystem: npm or pypi', 'npm')
354
+ .option('--mode <mode>', 'Override security mode: advisory or enforced (defaults to config)')
355
+ .option('--json', 'Output as JSON')
356
+ .action(async (options) => {
357
+ await runCheckSecurity({
358
+ packages: options.packages,
359
+ requirements: options.requirements,
360
+ lockfile: options.lockfile,
361
+ ecosystem: options.ecosystem,
362
+ mode: options.mode,
363
+ json: options.json,
364
+ });
365
+ });
366
+ // --- setup-security ---
367
+ program
368
+ .command('setup-security')
369
+ .description('Enable supply chain security gate: generate wrapper scripts and configure preinstall checks')
370
+ .option('--mode <mode>', 'Security mode: advisory (default) or enforced', 'advisory')
371
+ .action((options) => {
372
+ runSetupSecurity({ mode: options.mode });
373
+ });
374
+ // --- install-hooks ---
375
+ program
376
+ .command('install-hooks')
377
+ .description('Install a Git pre-commit hook that blocks sensitive content in .brainclaw/ and checks active constraints')
378
+ .option('--force', 'Overwrite existing pre-commit hook')
379
+ .action((options) => {
380
+ runInstallHooks(options);
381
+ });
382
+ // --- mcp ---
383
+ program
384
+ .command('mcp')
385
+ .description('Start the standalone MCP server over stdio')
386
+ .action(() => {
387
+ runMcp();
388
+ });
389
+ program
390
+ .command('reconcile')
391
+ .description('Refresh machine and workspace bootstrap state after updates or onboarding on complex installs')
392
+ .option('--json', 'Output as JSON')
393
+ .option('--dry-run', 'Preview the reconciliation plan without writing machine or bootstrap state')
394
+ .option('--apply-bootstrap', 'Apply bootstrap suggestions across all selected stores after refresh')
395
+ .option('-y, --yes', 'Skip confirmation prompts for multi-store bootstrap apply')
396
+ .option('--skip-machine-profile', 'Skip machine-profile refresh')
397
+ .option('--skip-agent-inventory', 'Skip agent-inventory refresh')
398
+ .action(async (options) => {
399
+ await runReconcile({
400
+ json: options.json,
401
+ dryRun: options.dryRun,
402
+ applyBootstrap: options.applyBootstrap,
403
+ yes: options.yes,
404
+ skipMachineProfile: options.skipMachineProfile,
405
+ skipAgentInventory: options.skipAgentInventory,
406
+ });
407
+ });
408
+ // --- hooks ---
409
+ program
410
+ .command('hooks')
411
+ .description('Write deterministic session-trigger hooks for Cursor, Windsurf, and Claude Code (PostToolUse event check)')
412
+ .option('--target <target>', 'Which hooks to write: cursor, windsurf, claude-code, all (default: all)')
413
+ .action((options) => {
414
+ runHooks(options);
415
+ });
416
+ // --- discover ---
417
+ program
418
+ .command('discover')
419
+ .description('Scan workspace for MCP configs, instruction files, skills, hooks, and agent integrations')
420
+ .option('--json', 'Output as JSON')
421
+ .option('--no-save', 'Do not persist discovery profile to .brainclaw/discovery/')
422
+ .action((options) => {
423
+ runDiscover({ json: options.json, save: options.save });
424
+ });
425
+ // --- migrate ---
426
+ program
427
+ .command('migrate')
428
+ .description('Migrate memory items between stores (e.g. promote machine-scoped items to user store)')
429
+ .option('--promote-machine-items', 'Move items with scope:machine from project store to user store (~/.brainclaw/)')
430
+ .option('--enable-journal', 'Turn on the event journal (mode=dual) for this existing store and backfill it (pln#567)')
431
+ .option('--dry-run', 'Show what would be done without writing')
432
+ .action((options) => {
433
+ runMigrate({ promoteMachineItems: options.promoteMachineItems, enableJournal: options.enableJournal, dryRun: options.dryRun });
434
+ });
435
+ }
436
+ //# sourceMappingURL=register-lifecycle.js.map