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,502 @@
1
+ import { getMemoryLog, rollbackMemory, hasMemoryRepo } from '../core/memory-git.js';
2
+ import { requireRegisteredAgentIdentity } from '../core/agent-registry.js';
3
+ import { runContext } from '../commands/context.js';
4
+ import { runBootstrap } from '../commands/bootstrap.js';
5
+ import { runMemoryCommand } from '../commands/memory.js';
6
+ import { runRegisterAgent, runRemoveAgent } from '../commands/register-agent.js';
7
+ import { runEnableAgent } from '../commands/enable-agent.js';
8
+ import { runListAgents } from '../commands/list-agents.js';
9
+ import { runSync } from '../commands/sync.js';
10
+ import { runDiff } from '../commands/changes.js';
11
+ import { runPrune } from '../commands/prune.js';
12
+ import { runCompact } from '../commands/compact.js';
13
+ import { runSetTrust } from '../commands/set-trust.js';
14
+ import { runSessionStart } from '../commands/session-start.js';
15
+ import { runSessionEnd } from '../commands/session-end.js';
16
+ import { runWhoami } from '../commands/whoami.js';
17
+ import { runUsage } from '../commands/usage.js';
18
+ import { runSearch } from '../commands/search.js';
19
+ import { runExport, runRefresh } from '../commands/export.js';
20
+ import { runMetrics } from '../commands/metrics.js';
21
+ import { runRollback } from '../commands/rollback.js';
22
+ import { runPull } from '../commands/pull.js';
23
+ import { runPush } from '../commands/push.js';
24
+ import { runAuditCommand } from '../commands/audit.js';
25
+ import { runHistory } from '../commands/history.js';
26
+ import { runContextDiff } from '../commands/context-diff.js';
27
+ import { runCapability } from '../commands/capability.js';
28
+ import { runLink } from '../commands/link.js';
29
+ import { runTool } from '../commands/tool.js';
30
+ import { runExplore } from '../commands/explore.js';
31
+ import { runSwitch } from '../commands/switch.js';
32
+ import { collect } from './shared.js';
33
+ export function registerMemoryContextCommands(program) {
34
+ // --- memory-log ---
35
+ program
36
+ .command('memory-log')
37
+ .description('Show recent memory change history (from internal git repo)')
38
+ .option('-n, --limit <count>', 'Number of entries to show', '20')
39
+ .action((options) => {
40
+ const entries = getMemoryLog(parseInt(options.limit, 10));
41
+ if (entries.length === 0) {
42
+ console.log('No memory history available. Run `brainclaw init --force` to enable memory versioning.');
43
+ return;
44
+ }
45
+ console.log(`Memory history (${entries.length} entries):\n`);
46
+ for (const entry of entries) {
47
+ console.log(` ${entry}`);
48
+ }
49
+ });
50
+ // --- memory-rollback ---
51
+ program
52
+ .command('memory-rollback <ref>')
53
+ .description('Restore live project memory from a previous git snapshot without deleting audit or archive artifacts')
54
+ .option('--actor <name>', 'Registered human identity required to authorize the rollback')
55
+ .action((ref, options) => {
56
+ const cwd = process.cwd();
57
+ if (!hasMemoryRepo()) {
58
+ console.error('Error: no memory git repo. Run `brainclaw init --force` to enable.');
59
+ process.exit(1);
60
+ }
61
+ let actor;
62
+ try {
63
+ actor = requireRegisteredAgentIdentity({
64
+ agentName: options.actor,
65
+ allowCurrent: true,
66
+ allowEnv: true,
67
+ cwd,
68
+ });
69
+ }
70
+ catch (err) {
71
+ console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
72
+ process.exit(1);
73
+ }
74
+ if (actor.kind !== 'human') {
75
+ console.error(`Error: memory-rollback is reserved to registered human identities. Resolved actor '${actor.agent_name}' is kind='${actor.kind}'.`);
76
+ process.exit(1);
77
+ }
78
+ const success = rollbackMemory(ref, cwd);
79
+ if (success) {
80
+ console.log(`✔ Live project memory restored to ${ref} (audit, archives, backups preserved)`);
81
+ }
82
+ else {
83
+ console.error(`Error: failed to rollback to '${ref}'. Check memory-log for valid refs.`);
84
+ process.exit(1);
85
+ }
86
+ });
87
+ // --- context ---
88
+ program
89
+ .command('context')
90
+ .description('Generate compact context for agents')
91
+ .option('--for <target>', 'Task/path/goal to prioritize')
92
+ .option('--project <project>', 'Explicit project namespace for layered instructions')
93
+ .option('--agent <agent>', 'Agent name for agent-layer instructions')
94
+ .option('--host <host>', 'Include machine-local runtime notes for a specific host')
95
+ .option('--all-hosts', 'Include machine-local runtime notes from all hosts')
96
+ .option('--profile <profile>', 'Profile: dev, openclaw, ops, research')
97
+ .option('--include-pending', 'Include pending candidates')
98
+ .option('--max-items <count>', 'Limit number of items', parseInt)
99
+ .option('--max-chars <count>', 'Approximate output budget for selected item content', parseInt)
100
+ .option('--digest', 'Include a short deterministic digest ahead of the detailed context')
101
+ .option('--since-session <id>', 'Include a compact memory diff since the given session started')
102
+ .option('--no-bootstrap', 'Disable brownfield bootstrap fallback when canonical memory is sparse')
103
+ .option('--refresh-bootstrap', 'Refresh brownfield bootstrap profile before building context')
104
+ .option('--template', 'Output prompt-ready context template')
105
+ .option('--compact-template', 'Use compact template format (default for openclaw profile)')
106
+ .option('--explain', 'Show ranking reasons in human-readable output')
107
+ .option('--json', 'Output as JSON')
108
+ .action((options) => {
109
+ runContext(options);
110
+ });
111
+ // --- bootstrap ---
112
+ program
113
+ .command('bootstrap')
114
+ .description('Derive brownfield bootstrap signals and optionally import them into canonical memory')
115
+ .option('--for <target>', 'Target path or scope to tailor the bootstrap')
116
+ .option('--json', 'Output as JSON')
117
+ .option('--refresh', 'Force a fresh bootstrap scan instead of reusing the current profile')
118
+ .option('--interview', 'Render the adaptive interview prompts instead of the bootstrap summary')
119
+ .option('--audience <audience>', 'Target interview prompts for cli, ide_chat, or any')
120
+ .option('--answers-file <path>', 'Load structured bootstrap interview answers from a JSON file')
121
+ .option('--apply', 'Import the current bootstrap proposal into canonical memory')
122
+ .option('--uninstall', 'Deactivate the last bootstrap import managed by this workspace')
123
+ .option('-y, --yes', 'Skip confirmation prompts for apply/uninstall')
124
+ .action(async (options) => {
125
+ await runBootstrap(options);
126
+ });
127
+ // --- memory ---
128
+ program
129
+ .command('memory <subcommand> [args...]')
130
+ .description('Manage canonical memory items (create, list, update, delete)')
131
+ .option('--json', 'Output as JSON for list')
132
+ .option('--type <type>', 'Memory type/filter: decision, constraint, trap, handoff')
133
+ .option('--text <text>', 'Replacement text for memory update')
134
+ .option('--tag <tags...>', 'Tags')
135
+ .option('--path <paths...>', 'Related file paths')
136
+ .option('--author <author>', 'Author name')
137
+ .option('--outcome <outcome>', 'Decision outcome: approved, rejected, deferred, pending')
138
+ .option('--category <category>', 'Constraint category: architecture, performance, security, reliability, compatibility, process, other')
139
+ .option('--status <status>', 'Constraint, trap, or handoff status')
140
+ .option('--severity <severity>', 'Trap severity: low, medium, high')
141
+ .option('--project <project>', 'Optional project namespace')
142
+ .option('--plan <id>', 'Optional linked plan item ID')
143
+ .option('--from <from>', 'Handoff source')
144
+ .option('--to <to>', 'Handoff destination')
145
+ .option('--visibility <visibility>', 'Trap visibility: shared, machine, private', 'shared')
146
+ .option('--host <host>', 'Optional host identifier override for machine/private traps')
147
+ .option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d')
148
+ .option('--store <target>', 'Target store level: local (default), repo, workspace, user')
149
+ .action((subcommand, args, options) => {
150
+ runMemoryCommand(subcommand, args, options);
151
+ });
152
+ // --- register-agent ---
153
+ program
154
+ .command('register-agent <name>')
155
+ .description('Register an agent or human identity in project memory')
156
+ .option('--kind <kind>', 'Identity kind: agent, human, unknown', 'unknown')
157
+ .option('--capability <value>', 'Declare a capability on the agent profile (repeatable)', collect, [])
158
+ .option('--replace-capabilities', 'Replace existing capabilities instead of merging')
159
+ .option('--generate-fingerprint', 'Generate or rotate a local public identity fingerprint for this agent')
160
+ .option('--set-current', 'Set this identity as the current agent in config')
161
+ .option('--curator', 'Register this agent as a curator (project owner with direct-write access)')
162
+ .option('--remove', 'Remove this identity instead of registering (guarded: debris identities only unless --force)')
163
+ .option('--force', 'With --remove: allow removing a non-debris identity')
164
+ .option('--json', 'Output as JSON')
165
+ .action((name, options) => {
166
+ if (options.remove) {
167
+ runRemoveAgent(name, { force: options.force, json: options.json });
168
+ return;
169
+ }
170
+ runRegisterAgent(name, options);
171
+ });
172
+ // --- enable-agent ---
173
+ program
174
+ .command('enable-agent <name>')
175
+ .description('Activate a supported coding agent on an already initialized project')
176
+ .option('--kind <kind>', 'Identity kind: agent, human, unknown', 'agent')
177
+ .option('--context-profile <profile>', 'Default context profile: dev, dense, compact, copilot, quick, openclaw, ops, research')
178
+ .option('--capability <value>', 'Declare a capability on the agent profile (repeatable)', collect, [])
179
+ .option('--replace-capabilities', 'Replace existing capabilities instead of merging')
180
+ .option('--generate-fingerprint', 'Generate or rotate a local public identity fingerprint for this agent')
181
+ .option('--set-current', 'Set this identity as the current agent in config')
182
+ .option('--json', 'Output as JSON')
183
+ .action((name, options) => {
184
+ runEnableAgent(name, options);
185
+ });
186
+ // --- list-agents ---
187
+ program
188
+ .command('list-agents')
189
+ .description('List registered agent identities')
190
+ .option('--json', 'Output as JSON')
191
+ .option('--with-reputation', 'Include bounded reputation summaries when available')
192
+ .action((options) => {
193
+ runListAgents(options);
194
+ });
195
+ // --- sync ---
196
+ program
197
+ .command('sync')
198
+ .description('Summarize memory changes and optionally commit')
199
+ .option('--commit', 'Create a local git commit')
200
+ .option('--message <message>', 'Custom commit message')
201
+ .option('--summary-only', 'Print summary only; skip git status and commit checks')
202
+ .option('--scope <scope>', 'Scope: all, state, config, project, inbox, archive, claims, runtime, runtime-local, trap-local')
203
+ .option('--include-machine-runtime', 'Include machine-local runtime memory in sync scope for all')
204
+ .option('--remote', 'Pull + push from/to remote memory repo in one step')
205
+ .action((options) => {
206
+ runSync({ ...options, remote: options.remote });
207
+ });
208
+ // --- diff ---
209
+ program
210
+ .command('diff')
211
+ .description('Show what changed in .brainclaw/ since a timestamp or last context read')
212
+ .option('--since <timestamp>', 'ISO 8601 timestamp to diff from')
213
+ .option('--json', 'Output as JSON')
214
+ .action((options) => {
215
+ runDiff(options);
216
+ });
217
+ // --- prune ---
218
+ program
219
+ .command('prune')
220
+ .description('Prune expired constraints and stale memory')
221
+ .option('--expired', 'Also prune expired runtime notes and traps')
222
+ .option('--archive', 'Archive done plans and closed handoffs (>30 days) to cold storage JSONL')
223
+ .option('--semantic', 'Detect near-duplicate clusters and stale items via semantic analysis')
224
+ .option('--dry-run', 'Preview compaction without applying (use with --semantic)')
225
+ .action((options) => {
226
+ runPrune(options);
227
+ });
228
+ // --- compact ---
229
+ program
230
+ .command('compact')
231
+ .description('LLM-driven semantic memory compaction — archive old items and get a summary template')
232
+ .option('--assess', 'Show pressure assessment and compaction template without archiving')
233
+ .option('--dry-run', 'Preview eligible items without archiving')
234
+ .option('--max-items <n>', 'Maximum items to compact (default: 20)', parseInt)
235
+ .option('--min-age <days>', 'Minimum age in days for eligibility (default: 7)', parseInt)
236
+ .option('--no-dedup-handoffs', 'Skip deduplication of auto-generated session-end handoffs')
237
+ .option('--no-purge-claims', 'Skip archival of released claims')
238
+ .option('--no-purge-session-notes', 'Skip archival of session-lifecycle runtime_notes')
239
+ .action((options) => {
240
+ runCompact(options);
241
+ });
242
+ // --- set-trust ---
243
+ program
244
+ .command('set-trust <agent>')
245
+ .description('Set the trust level for a registered agent or manage circuit-breaker state')
246
+ .option('--level <level>', 'Trust level: observer, contributor, trusted, curator')
247
+ .option('--reset-breaker', 'Reset circuit-breaker suspension for the agent (restores auto-promote)')
248
+ .option('--json', 'Output as JSON')
249
+ .action((agent, options) => {
250
+ runSetTrust(agent, { level: options.level, resetBreaker: options.resetBreaker, json: options.json });
251
+ });
252
+ // --- session-start ---
253
+ program
254
+ .command('session-start')
255
+ .description('Start a memory session and capture initial context')
256
+ .option('--agent <agent>', 'Agent name (defaults to current configured agent)')
257
+ .option('--context <path>', 'Context target path for initial hash capture')
258
+ .option('--model <id>', 'Model identifier (e.g. claude-sonnet-4-6)')
259
+ .option('--maintenance-mode <mode>', 'Maintenance mode: full (default) or fast')
260
+ .option('--include-context', 'Output full project context after starting session (replaces separate context call)')
261
+ .option('--hook', 'Hook mode: degrade to exit 0 + ~/.brainclaw/hook.log on failure (advisory session hooks)')
262
+ .option('--json', 'Output as JSON')
263
+ .action(async (options) => {
264
+ await runSessionStart(options);
265
+ });
266
+ // --- session-end ---
267
+ program
268
+ .command('session-end')
269
+ .description('End a memory session and optionally auto-reflect observations')
270
+ .option('--session <id>', 'Session ID (defaults to BRAINCLAW_SESSION_ID env var)')
271
+ .option('--agent <agent>', 'Agent name')
272
+ .option('--summary <text>', 'Session summary text')
273
+ .option('--auto-reflect', 'Auto-reflect session notes as pending candidates')
274
+ .option('--auto-release', 'Auto-release any active claims at session end')
275
+ .option('--reflect-handoff', 'Materialize an open handoff from git commits since session start')
276
+ .option('--dispatch-review', 'When used with --reflect-handoff, auto-dispatch a code review if the handoff is reviewable')
277
+ .option('--reviewer <name>', 'Explicit reviewer to route the reflected handoff review to')
278
+ .option('--no-reflect', 'Suppress the dogfooding reflection prompt (project + your surfaces/skills/tools), shown by default')
279
+ .option('--hook', 'Hook mode: degrade to exit 0 + ~/.brainclaw/hook.log on failure (advisory Stop hook)')
280
+ .option('--json', 'Output as JSON')
281
+ .action(async (options) => {
282
+ await runSessionEnd({
283
+ ...options,
284
+ autoReflect: options.autoReflect,
285
+ autoRelease: options.autoRelease,
286
+ reflectHandoff: options.reflectHandoff,
287
+ dispatchReview: options.dispatchReview,
288
+ reviewer: options.reviewer,
289
+ reflect: options.reflect,
290
+ hook: options.hook,
291
+ });
292
+ });
293
+ // --- whoami ---
294
+ program
295
+ .command('whoami')
296
+ .description('Show the current resolved agent identity and trust level')
297
+ .option('--json', 'Output as JSON')
298
+ .action((options) => {
299
+ runWhoami(options);
300
+ });
301
+ // --- usage ---
302
+ program
303
+ .command('usage')
304
+ .description('Show brainclaw context volume stats (tokens injected per agent/tool)')
305
+ .option('--agent <name>', 'Filter by agent name')
306
+ .option('--tool <name>', 'Filter by tool name')
307
+ .option('--days <n>', 'Limit to last N days', parseInt)
308
+ .option('--json', 'Output as JSON')
309
+ .action((options) => {
310
+ runUsage(options);
311
+ });
312
+ // --- search ---
313
+ program
314
+ .command('search <query>')
315
+ .description('Full-text search across project memory')
316
+ .option('--section <section>', 'Filter by section: constraints, decisions, traps, handoffs, plans')
317
+ .option('--since <timestamp>', 'ISO timestamp filter')
318
+ .option('--tag <tags...>', 'Filter by tags')
319
+ .option('--pending', 'Include pending candidates')
320
+ .option('--max-results <count>', 'Maximum results to return', parseInt)
321
+ .option('--json', 'Output as JSON')
322
+ .action((query, options) => {
323
+ runSearch(query, options);
324
+ });
325
+ // --- export ---
326
+ program
327
+ .command('export')
328
+ .description('Export memory as instructions for IDE/AI tools')
329
+ .option('--format <format>', 'Format: copilot-instructions, cursor-rules, agents-md, claude-md, gemini-md, windsurf, cline, roo, continue, openclaw, nanoclaw, nemoclaw, picoclaw, zeroclaw')
330
+ .option('--detect', 'Auto-detect agent environment and write to its native file')
331
+ .option('--all', 'Write all known agent instruction files at once (claude-md, agents-md, copilot-instructions, cursor-rules, etc.)')
332
+ .option('--write', 'Write to canonical file path instead of stdout (when --format is given); local files are gitignored by default')
333
+ .option('--include-live', 'Also write the native live companion file when the target agent supports one')
334
+ .option('--shared', 'Keep the main exported instruction file versionable instead of auto-ignoring it (companions remain local)')
335
+ .option('--output <file>', 'Write to a specific file path instead of stdout')
336
+ .option('--project <project>', 'Project namespace filter')
337
+ .option('--agent <agent>', 'Agent name for agent-layer instructions')
338
+ .action((options) => {
339
+ runExport(options);
340
+ });
341
+ program
342
+ .command('refresh')
343
+ .description('Refresh live companion files with current state (plans, claims, traps, sequences). Gitignored, safe to run frequently.')
344
+ .action(() => {
345
+ runRefresh();
346
+ });
347
+ // --- metrics ---
348
+ program
349
+ .command('metrics')
350
+ .description('Show memory health metrics dashboard')
351
+ .option('--json', 'Output as JSON')
352
+ .option('--since <timestamp>', 'Filter audit log stats from this ISO timestamp')
353
+ .action((options) => {
354
+ runMetrics(options);
355
+ });
356
+ // --- rollback ---
357
+ program
358
+ .command('rollback')
359
+ .description('Restore a memory item to a previous state from audit log')
360
+ .option('--audit-id <timestamp>', 'Audit log entry timestamp to roll back')
361
+ .option('--item-id <id>', 'Memory item ID to roll back (uses most recent audit entry with before-state)')
362
+ .option('--dry-run', 'Preview rollback without applying changes')
363
+ .option('--json', 'Output as JSON')
364
+ .action((options) => {
365
+ runRollback({ auditId: options.auditId, itemId: options.itemId, dryRun: options.dryRun, json: options.json });
366
+ });
367
+ // --- pull ---
368
+ program
369
+ .command('pull')
370
+ .description('Pull memory updates from a git remote')
371
+ .option('--remote <remote>', 'Remote name (defaults to origin)')
372
+ .option('--json', 'Output as JSON')
373
+ .action((options) => {
374
+ runPull(options);
375
+ });
376
+ // --- push ---
377
+ program
378
+ .command('push')
379
+ .description('Push memory updates to a git remote')
380
+ .option('--remote <remote>', 'Remote name (defaults to origin)')
381
+ .option('--message <message>', 'Custom commit message')
382
+ .option('--json', 'Output as JSON')
383
+ .action((options) => {
384
+ runPush(options);
385
+ });
386
+ // --- audit ---
387
+ program
388
+ .command('audit')
389
+ .description('View the append-only audit log, or generate a governance posture report with --governance')
390
+ .option('--since <date>', 'Show entries since this ISO date')
391
+ .option('--actor <agent>', 'Filter by actor name or agent ID')
392
+ .option('--action <action>', 'Filter by action type (create, accept, reject, etc.)')
393
+ .option('--limit <n>', 'Show last N entries', parseInt)
394
+ .option('--json', 'Output as JSON')
395
+ .option('--governance', 'Generate a governance posture report (aggregated view of claims, constraints, traps, instructions)')
396
+ .option('--scope <path>', 'Filter governance report by scope (used with --governance)')
397
+ .action((options) => {
398
+ runAuditCommand({ since: options.since, actor: options.actor, action: options.action, limit: options.limit, json: options.json, governance: options.governance, scope: options.scope });
399
+ });
400
+ // --- history ---
401
+ program
402
+ .command('history <id>')
403
+ .description('Show full mutation history of a memory item from the audit log')
404
+ .action((id) => {
405
+ runHistory(id);
406
+ });
407
+ // --- context-diff ---
408
+ program
409
+ .command('context-diff')
410
+ .description('Show what changed in memory since last context read, a session start, or a given timestamp')
411
+ .option('--since <date>', 'Show changes since this ISO date')
412
+ .option('--session <id>', 'Show changes since the start of this session')
413
+ .option('--hook', 'Hook mode: exit 0 silently when there is no diff baseline (advisory session hooks)')
414
+ .option('--json', 'Output as JSON')
415
+ .action((options) => {
416
+ runContextDiff({ since: options.since, session: options.session, json: options.json, hook: options.hook });
417
+ });
418
+ program
419
+ .command('capability <subcommand> [args...]')
420
+ .description('Manage project capabilities (list, add, describe)')
421
+ .option('--tag <tag>', 'Tag for categorization (repeatable)', (val, prev) => [...(prev || []), val])
422
+ .option('--author <name>', 'Author name')
423
+ .option('--store <target>', 'Store level: local (default), repo, workspace, user')
424
+ .action((subcommand, args, options) => {
425
+ runCapability(subcommand, args, {
426
+ tag: options.tag,
427
+ author: options.author,
428
+ store: options.store,
429
+ });
430
+ });
431
+ program
432
+ .command('link <subcommand> [args...]')
433
+ .description('Manage cross-project federation links (add, list, remove)')
434
+ .option('--name <slug>', 'Override the auto-derived link name')
435
+ .option('--role <role>', 'Link role: publisher (push signals out) or subscriber (default)')
436
+ .option('--channels <list>', 'Comma-separated allow-list of channels: candidate,handoff,runtime_note', (val) => val.split(',').map((s) => s.trim()).filter(Boolean))
437
+ .option('--force', 'Replace an existing link of the same name/path')
438
+ .option('--json', 'Output as JSON')
439
+ .option('--store <target>', 'Store level: local (default), repo, workspace, user')
440
+ .action((subcommand, args, options) => {
441
+ runLink(subcommand, args, {
442
+ name: options.name,
443
+ role: options.role,
444
+ channels: options.channels,
445
+ force: options.force,
446
+ json: options.json,
447
+ store: options.store,
448
+ });
449
+ });
450
+ program
451
+ .command('tool <subcommand> [args...]')
452
+ .description('Manage project tools (list, add, describe, search)')
453
+ .option('--tag <tag>', 'Tag for categorization (repeatable)', (val, prev) => [...(prev || []), val])
454
+ .option('--type <type>', 'Tool type: workflow, validator, generator, utility, explorer')
455
+ .option('--author <name>', 'Author name')
456
+ .option('--store <target>', 'Store level: local (default), repo, workspace, user')
457
+ .action((subcommand, args, options) => {
458
+ runTool(subcommand, args, {
459
+ tag: options.tag,
460
+ type: options.type,
461
+ author: options.author,
462
+ store: options.store,
463
+ });
464
+ });
465
+ program
466
+ .command('explore')
467
+ .description('Explore project capabilities and available tools')
468
+ .option('--query <q>', 'Search for specific capability or tool')
469
+ .action((options) => {
470
+ runExplore({ query: options.query });
471
+ });
472
+ program
473
+ .command('switch [project]')
474
+ .description('Set the active project for subsequent commands (session-scoped by default)')
475
+ .option('--list', 'List available projects in the workspace')
476
+ .option('--clear', 'Clear the active project (revert to cwd)')
477
+ .option('--global', 'Set/clear the SHARED workspace default for ALL agents (writes active-project.json). Without it, switch is session-scoped and isolated.')
478
+ .option('--json', 'Output as JSON')
479
+ .action((project, options) => {
480
+ const globalOpts = options.parent?.parent ? program.opts() : {};
481
+ runSwitch(project, {
482
+ list: options.list,
483
+ clear: options.clear,
484
+ global: options.global,
485
+ json: options.json,
486
+ cwd: globalOpts.cwd,
487
+ });
488
+ });
489
+ program
490
+ .command('who')
491
+ .description('Show active agent sessions on this workspace')
492
+ .option('--json', 'Output as JSON')
493
+ .option('--all', 'Include stale sessions')
494
+ .option('--gc', 'Remove stale sessions')
495
+ .option('--local-only', 'Read claims from local store only (skip parent stores in chain)')
496
+ .action(async (options) => {
497
+ const globalOpts = program.opts();
498
+ const { runWho } = await import('../commands/who.js');
499
+ runWho({ json: options.json, all: options.all, gc: options.gc, cwd: globalOpts.cwd, localOnly: options.localOnly });
500
+ });
501
+ }
502
+ //# sourceMappingURL=register-memory-context.js.map