brainclaw 0.29.2 → 1.5.3
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 +193 -170
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +673 -24
- package/dist/commands/accept.js +3 -0
- package/dist/commands/add-step.js +11 -26
- package/dist/commands/agent-board.js +70 -3
- package/dist/commands/audit.js +19 -0
- package/dist/commands/check-policy.js +54 -0
- package/dist/commands/check-security-mcp.js +145 -0
- package/dist/commands/check-security.js +106 -0
- package/dist/commands/claim-resource.js +1 -0
- package/dist/commands/codev.js +672 -0
- package/dist/commands/compact.js +74 -0
- package/dist/commands/complete-step.js +16 -26
- package/dist/commands/constraint.js +8 -20
- package/dist/commands/decision.js +9 -20
- package/dist/commands/delete-plan.js +10 -12
- package/dist/commands/delete-step.js +16 -0
- package/dist/commands/dispatch.js +163 -0
- package/dist/commands/doctor.js +1122 -49
- package/dist/commands/enable-agent.js +1 -0
- package/dist/commands/export.js +280 -22
- package/dist/commands/handoff.js +33 -0
- package/dist/commands/harvest.js +189 -0
- package/dist/commands/hooks.js +82 -25
- package/dist/commands/inbox.js +169 -0
- package/dist/commands/init.js +38 -31
- package/dist/commands/install-hooks.js +71 -44
- package/dist/commands/link.js +89 -0
- package/dist/commands/list-claims.js +48 -3
- package/dist/commands/list-plans.js +129 -25
- package/dist/commands/loops-handlers.js +409 -0
- package/dist/commands/mcp-read-handlers.js +1628 -0
- package/dist/commands/mcp-schemas.generated.js +74 -0
- package/dist/commands/mcp.js +4221 -1501
- package/dist/commands/plan-resource.js +64 -0
- package/dist/commands/plan.js +12 -26
- package/dist/commands/prune.js +37 -2
- package/dist/commands/reflect.js +20 -7
- package/dist/commands/release-claim.js +11 -6
- package/dist/commands/release-notes.js +170 -0
- package/dist/commands/repair.js +210 -0
- package/dist/commands/run-profile.js +57 -0
- package/dist/commands/sequence.js +113 -0
- package/dist/commands/session-end.js +423 -14
- package/dist/commands/session-start.js +214 -41
- package/dist/commands/setup-security.js +103 -0
- package/dist/commands/setup.js +42 -4
- package/dist/commands/stale.js +109 -0
- package/dist/commands/switch.js +100 -2
- package/dist/commands/trap.js +14 -31
- package/dist/commands/update-handoff.js +63 -4
- package/dist/commands/update-plan.js +21 -28
- package/dist/commands/update-step.js +37 -0
- package/dist/commands/upgrade.js +313 -6
- package/dist/commands/usage.js +102 -0
- package/dist/commands/version.js +20 -0
- package/dist/commands/who.js +33 -5
- package/dist/commands/worktree.js +105 -0
- package/dist/core/actions.js +315 -0
- package/dist/core/agent-capability.js +610 -17
- package/dist/core/agent-context.js +7 -1
- package/dist/core/agent-files.js +1169 -85
- package/dist/core/agent-integrations.js +160 -5
- package/dist/core/agent-inventory.js +2 -0
- package/dist/core/agent-profiles.js +93 -0
- package/dist/core/agent-registry.js +162 -30
- package/dist/core/agentrun-reconciler.js +345 -0
- package/dist/core/agentruns.js +424 -0
- package/dist/core/ai-agent-detection.js +31 -10
- package/dist/core/archival.js +77 -0
- package/dist/core/assignment-sweeper.js +82 -0
- package/dist/core/assignments.js +367 -0
- package/dist/core/audit.js +30 -0
- package/dist/core/brainclaw-version.js +94 -2
- package/dist/core/candidates.js +93 -2
- package/dist/core/claims.js +419 -0
- package/dist/core/codev-metrics.js +77 -0
- package/dist/core/codev-personas.js +31 -0
- package/dist/core/codev-plan-gen.js +35 -0
- package/dist/core/codev-prompts.js +74 -0
- package/dist/core/codev-responses.js +62 -0
- package/dist/core/codev-rounds.js +218 -0
- package/dist/core/config.js +4 -0
- package/dist/core/context.js +381 -34
- package/dist/core/coordination.js +201 -6
- package/dist/core/cross-project.js +230 -16
- package/dist/core/default-profiles/doctor.yaml +11 -0
- package/dist/core/default-profiles/janitor.yaml +11 -0
- package/dist/core/default-profiles/onboarder.yaml +11 -0
- package/dist/core/default-profiles/reviewer.yaml +13 -0
- package/dist/core/dispatcher.js +1189 -0
- package/dist/core/duplicates.js +2 -2
- package/dist/core/entity-operations.js +450 -0
- package/dist/core/entity-registry.js +344 -0
- package/dist/core/events.js +106 -2
- package/dist/core/execution-adapters.js +154 -0
- package/dist/core/execution-context.js +63 -0
- package/dist/core/execution-profile.js +270 -0
- package/dist/core/execution.js +255 -0
- package/dist/core/facade-schema.js +81 -0
- package/dist/core/federation-cloud.js +99 -0
- package/dist/core/federation-message.js +52 -0
- package/dist/core/federation-transport.js +65 -0
- package/dist/core/gc-semantic.js +482 -0
- package/dist/core/governance.js +247 -0
- package/dist/core/guards.js +19 -0
- package/dist/core/ideation.js +72 -0
- package/dist/core/identity.js +110 -25
- package/dist/core/ids.js +6 -0
- package/dist/core/input-validation.js +2 -2
- package/dist/core/instruction-templates.js +344 -136
- package/dist/core/io.js +90 -11
- package/dist/core/lock.js +6 -2
- package/dist/core/loops/brief-assembly.js +213 -0
- package/dist/core/loops/facade-schema.js +148 -0
- package/dist/core/loops/index.js +7 -0
- package/dist/core/loops/iteration-engine.js +139 -0
- package/dist/core/loops/lock.js +385 -0
- package/dist/core/loops/store.js +201 -0
- package/dist/core/loops/types.js +403 -0
- package/dist/core/loops/verbs.js +534 -0
- package/dist/core/markdown.js +15 -3
- package/dist/core/memory-compactor.js +432 -0
- package/dist/core/memory-git.js +152 -8
- package/dist/core/messaging.js +278 -0
- package/dist/core/migration.js +32 -1
- package/dist/core/mutation-pipeline.js +4 -2
- package/dist/core/operations/memory-mutation.js +129 -0
- package/dist/core/operations/memory-write.js +78 -0
- package/dist/core/operations/plan.js +190 -0
- package/dist/core/policy.js +169 -0
- package/dist/core/reputation.js +9 -3
- package/dist/core/schema.js +491 -6
- package/dist/core/search.js +21 -2
- package/dist/core/security-cache.js +71 -0
- package/dist/core/security-guard.js +152 -0
- package/dist/core/security-scoring.js +86 -0
- package/dist/core/sequence.js +130 -0
- package/dist/core/socket-client.js +113 -0
- package/dist/core/staleness.js +246 -0
- package/dist/core/state.js +98 -22
- package/dist/core/store-resolution.js +43 -11
- package/dist/core/toml-writer.js +76 -0
- package/dist/core/upgrades/backup.js +232 -0
- package/dist/core/upgrades/health-check.js +169 -0
- package/dist/core/upgrades/patches/candidate-archive.js +145 -0
- package/dist/core/upgrades/patches/handoff-review-strip.js +128 -0
- package/dist/core/upgrades/patches/provenance-rollout.js +136 -0
- package/dist/core/upgrades/schema-version.js +97 -0
- package/dist/core/worktree.js +606 -0
- package/dist/facts.js +114 -0
- package/dist/facts.json +111 -0
- package/docs/architecture/project-refs.md +5 -1
- package/docs/cli.md +690 -43
- package/docs/concepts/ideation-loop.md +317 -0
- package/docs/concepts/loop-engine.md +456 -0
- package/docs/concepts/mcp-governance.md +268 -0
- package/docs/concepts/memory-staleness.md +122 -0
- package/docs/concepts/multi-agent-workflows.md +166 -0
- package/docs/concepts/plans-and-claims.md +31 -6
- package/docs/concepts/project-md-convention.md +35 -0
- package/docs/concepts/troubleshooting.md +220 -0
- package/docs/concepts/upgrade-cli.md +202 -0
- package/docs/concepts/upgrade-dogfood-procedure.md +114 -0
- package/docs/context-format-changelog.md +2 -2
- package/docs/context-format.md +2 -2
- package/docs/index.md +68 -0
- package/docs/integrations/agents.md +15 -16
- package/docs/integrations/cline.md +88 -0
- package/docs/integrations/codex.md +75 -23
- package/docs/integrations/continue.md +60 -0
- package/docs/integrations/copilot.md +67 -9
- package/docs/integrations/kilocode.md +72 -0
- package/docs/integrations/mcp.md +304 -21
- package/docs/integrations/mistral-vibe.md +122 -0
- package/docs/integrations/opencode.md +84 -0
- package/docs/integrations/overview.md +23 -8
- package/docs/integrations/roo.md +74 -0
- package/docs/integrations/windsurf.md +83 -0
- package/docs/mcp-schema-changelog.md +191 -1
- package/docs/playbooks/integration/index.md +121 -0
- package/docs/playbooks/productivity/index.md +102 -0
- package/docs/playbooks/team/index.md +122 -0
- package/docs/product/agent-first-model.md +184 -0
- package/docs/product/entity-model-audit.md +462 -0
- package/docs/quickstart-existing-project.md +135 -0
- package/docs/quickstart.md +124 -37
- package/docs/release-maintenance.md +79 -0
- package/docs/review.md +2 -0
- package/docs/server-operations.md +118 -0
- package/package.json +20 -12
- package/dist/commands/claude-desktop-extension.js +0 -18
- package/dist/commands/diff.js +0 -99
- package/dist/core/claude-desktop-extension.js +0 -224
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { runInit } from './commands/init.js';
|
|
5
5
|
import { runSetup } from './commands/setup.js';
|
|
6
6
|
import { runUpgrade } from './commands/upgrade.js';
|
|
7
|
+
import { patchAllMcpConfigs } from './core/agent-files.js';
|
|
7
8
|
import { runReconcile } from './commands/reconcile.js';
|
|
8
9
|
import { getMemoryLog, rollbackMemory, hasMemoryRepo } from './core/memory-git.js';
|
|
9
10
|
import { buildMachineProfile, saveMachineProfile, loadMachineProfile, renderMachineProfileSummary } from './core/machine-profile.js';
|
|
@@ -18,7 +19,10 @@ import { runListPlans } from './commands/list-plans.js';
|
|
|
18
19
|
import { runUpdatePlan } from './commands/update-plan.js';
|
|
19
20
|
import { runDeletePlan } from './commands/delete-plan.js';
|
|
20
21
|
import { runPlanResource } from './commands/plan-resource.js';
|
|
22
|
+
import { runSequenceResource } from './commands/sequence.js';
|
|
21
23
|
import { runAddStep } from './commands/add-step.js';
|
|
24
|
+
import { runDeleteStep } from './commands/delete-step.js';
|
|
25
|
+
import { runUpdateStep } from './commands/update-step.js';
|
|
22
26
|
import { runEstimationReport } from './commands/estimation-report.js';
|
|
23
27
|
import { runCompleteStep } from './commands/complete-step.js';
|
|
24
28
|
import { runUpdateHandoff } from './commands/update-handoff.js';
|
|
@@ -27,6 +31,8 @@ import { runListAgents } from './commands/list-agents.js';
|
|
|
27
31
|
import { runSurfaceTaskResource } from './commands/surface-task-resource.js';
|
|
28
32
|
import { runListInstructions } from './commands/list-instructions.js';
|
|
29
33
|
import { runDoctor } from './commands/doctor.js';
|
|
34
|
+
import { runRepair } from './commands/repair.js';
|
|
35
|
+
import { runStale } from './commands/stale.js';
|
|
30
36
|
import { runRebuild } from './commands/rebuild.js';
|
|
31
37
|
import { runReflect } from './commands/reflect.js';
|
|
32
38
|
import { runReflectRuntimeNote } from './commands/reflect-runtime-note.js';
|
|
@@ -37,6 +43,7 @@ import { runUseCandidate } from './commands/use-candidate.js';
|
|
|
37
43
|
import { runAccept } from './commands/accept.js';
|
|
38
44
|
import { runReject } from './commands/reject.js';
|
|
39
45
|
import { runPruneCandidates } from './commands/prune-candidates.js';
|
|
46
|
+
import { cleanupStaleCandidates } from './core/candidates.js';
|
|
40
47
|
import { runListClaims } from './commands/list-claims.js';
|
|
41
48
|
import { runReleaseClaim } from './commands/release-claim.js';
|
|
42
49
|
import { runClaimResource } from './commands/claim-resource.js';
|
|
@@ -52,9 +59,13 @@ import { runEnv } from './commands/env.js';
|
|
|
52
59
|
import { runAdapterOpenclawImport } from './commands/adapter-openclaw-import.js';
|
|
53
60
|
import { runInstallHooks } from './commands/install-hooks.js';
|
|
54
61
|
import { runCheckConstraints } from './commands/check-constraints.js';
|
|
62
|
+
import { runCheckPolicy } from './commands/check-policy.js';
|
|
63
|
+
import { runCheckSecurity } from './commands/check-security.js';
|
|
64
|
+
import { runSetupSecurity } from './commands/setup-security.js';
|
|
55
65
|
import { runRegisterAgent } from './commands/register-agent.js';
|
|
56
66
|
import { runEnableAgent } from './commands/enable-agent.js';
|
|
57
67
|
import { runVersion } from './commands/version.js';
|
|
68
|
+
import { runReleaseNotes } from './commands/release-notes.js';
|
|
58
69
|
import { runDiff } from './commands/changes.js';
|
|
59
70
|
import { runPrune } from './commands/prune.js';
|
|
60
71
|
import { runMcp } from './commands/mcp.js';
|
|
@@ -62,10 +73,13 @@ import { runSetTrust } from './commands/set-trust.js';
|
|
|
62
73
|
import { runSessionStart } from './commands/session-start.js';
|
|
63
74
|
import { runSessionEnd } from './commands/session-end.js';
|
|
64
75
|
import { runWhoami } from './commands/whoami.js';
|
|
76
|
+
import { runUsage } from './commands/usage.js';
|
|
65
77
|
import { runSearch } from './commands/search.js';
|
|
66
|
-
import { runExport } from './commands/export.js';
|
|
78
|
+
import { runExport, runRefresh } from './commands/export.js';
|
|
67
79
|
import { runHooks } from './commands/hooks.js';
|
|
68
80
|
import { runWatch } from './commands/watch.js';
|
|
81
|
+
import { runDispatchAnalysis, runDispatch, runDispatchReview } from './commands/dispatch.js';
|
|
82
|
+
import { runInboxList, runInboxAck, runInboxArchive, runInboxSend, runInboxThread } from './commands/inbox.js';
|
|
69
83
|
import { runMetrics } from './commands/metrics.js';
|
|
70
84
|
import { runRollback } from './commands/rollback.js';
|
|
71
85
|
import { runPull } from './commands/pull.js';
|
|
@@ -74,20 +88,30 @@ import { runAuditCommand } from './commands/audit.js';
|
|
|
74
88
|
import { runHistory } from './commands/history.js';
|
|
75
89
|
import { runContextDiff } from './commands/context-diff.js';
|
|
76
90
|
import { runCapability } from './commands/capability.js';
|
|
91
|
+
import { runLink } from './commands/link.js';
|
|
77
92
|
import { runTool } from './commands/tool.js';
|
|
78
93
|
import { runExplore } from './commands/explore.js';
|
|
79
94
|
import { getInstalledBrainclawVersion } from './core/brainclaw-version.js';
|
|
80
|
-
import { cleanOrphanFiles, memoryDir } from './core/io.js';
|
|
95
|
+
import { cleanOrphanFiles, memoryDir, memoryExists } from './core/io.js';
|
|
81
96
|
import { initLogLevel, logger } from './core/logger.js';
|
|
82
97
|
import { resolveEffectiveCwd } from './core/store-resolution.js';
|
|
98
|
+
import { resolveProjectCwd } from './core/cross-project.js';
|
|
83
99
|
import { runSwitch } from './commands/switch.js';
|
|
100
|
+
import { runWorktreeCreate, runWorktreeList, runWorktreeRemove, runWorktreePrune, runWorktreeClean, runWorktreeMerge } from './commands/worktree.js';
|
|
84
101
|
import { runCheckEvents } from './commands/check-events.js';
|
|
85
102
|
import { runDiscover } from './commands/discover.js';
|
|
86
103
|
import { runMigrate } from './commands/migrate.js';
|
|
104
|
+
import { runRunProfile } from './commands/run-profile.js';
|
|
105
|
+
import { runCompact } from './commands/compact.js';
|
|
106
|
+
import { runHarvestCandidates } from './commands/harvest.js';
|
|
107
|
+
import { requireRegisteredAgentIdentity } from './core/agent-registry.js';
|
|
87
108
|
const program = new Command();
|
|
88
109
|
function collect(value, previous) {
|
|
89
110
|
return [...previous, value];
|
|
90
111
|
}
|
|
112
|
+
function isCodevEnabled() {
|
|
113
|
+
return process.env.BRAINCLAW_ENABLE_CODEV === '1';
|
|
114
|
+
}
|
|
91
115
|
program
|
|
92
116
|
.name('brainclaw')
|
|
93
117
|
.description('Shared project memory for humans and coding agents.')
|
|
@@ -95,15 +119,33 @@ program
|
|
|
95
119
|
.option('--verbose', 'Show info-level log messages on stderr')
|
|
96
120
|
.option('--debug', 'Show debug-level log messages on stderr')
|
|
97
121
|
.option('--cwd <path>', 'Override working directory for this invocation')
|
|
122
|
+
.option('--project <name>', 'Run the command against a linked project (cross_project_links or workspace store-chain child). Resolves via resolveProjectCwd; mutually exclusive with --cwd.')
|
|
98
123
|
.hook('preAction', (_thisCommand, actionCommand) => {
|
|
99
124
|
const root = actionCommand.optsWithGlobals();
|
|
100
125
|
initLogLevel({ verbose: root.verbose, debug: root.debug });
|
|
101
126
|
// Skip effective cwd resolution for commands that create the store
|
|
102
127
|
const cmdName = actionCommand.name();
|
|
103
128
|
const skipResolution = cmdName === 'init' || cmdName === 'setup';
|
|
129
|
+
// pln#359 phase 1c — `--project <name>` resolves a linked project to an
|
|
130
|
+
// absolute path via resolveProjectCwd, then feeds the same chdir flow
|
|
131
|
+
// as --cwd. Mutually exclusive with --cwd to avoid ambiguity.
|
|
132
|
+
let explicitCwd = root.cwd;
|
|
133
|
+
if (root.project) {
|
|
134
|
+
if (root.cwd) {
|
|
135
|
+
console.error('Error: --project and --cwd are mutually exclusive. Use one.');
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
explicitCwd = resolveProjectCwd(root.project, process.cwd());
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
console.error(`Error: ${err.message}`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
104
146
|
if (!skipResolution) {
|
|
105
|
-
// Resolve effective cwd (
|
|
106
|
-
const effectiveCwd = resolveEffectiveCwd({ explicitCwd
|
|
147
|
+
// Resolve effective cwd (explicit > BRAINCLAW_PROJECT > active-project > process.cwd)
|
|
148
|
+
const effectiveCwd = resolveEffectiveCwd({ explicitCwd });
|
|
107
149
|
if (effectiveCwd !== process.cwd()) {
|
|
108
150
|
// Change process.cwd() so all commands resolve the correct store
|
|
109
151
|
// without needing individual --cwd plumbing
|
|
@@ -115,9 +157,9 @@ program
|
|
|
115
157
|
logger.info(`Cleaned ${removed} orphan lock/tmp file(s) in ${memoryDir()}`);
|
|
116
158
|
}
|
|
117
159
|
}
|
|
118
|
-
else if (
|
|
119
|
-
// For init/setup, still respect explicit --cwd but nothing else
|
|
120
|
-
process.chdir(path.resolve(
|
|
160
|
+
else if (explicitCwd) {
|
|
161
|
+
// For init/setup, still respect explicit --cwd / --project but nothing else
|
|
162
|
+
process.chdir(path.resolve(explicitCwd));
|
|
121
163
|
}
|
|
122
164
|
});
|
|
123
165
|
// --- init ---
|
|
@@ -131,6 +173,7 @@ program
|
|
|
131
173
|
.option('--project-mode <mode>', 'Project mode: single-project, multi-project, auto')
|
|
132
174
|
.option('--project-strategy <strategy>', 'Project strategy for multi-project mode: manual, folder')
|
|
133
175
|
.option('--no-analyze-repo', 'Skip repository analysis when suggesting a project mode')
|
|
176
|
+
.option('--no-ai-scan', 'Skip AI surface scan during init')
|
|
134
177
|
.option('--scan', 'Scan subdirectories for service boundaries and suggest init targets')
|
|
135
178
|
.action(async (options) => {
|
|
136
179
|
await runInit(options);
|
|
@@ -165,15 +208,34 @@ program
|
|
|
165
208
|
// --- memory-rollback ---
|
|
166
209
|
program
|
|
167
210
|
.command('memory-rollback <ref>')
|
|
168
|
-
.description('
|
|
169
|
-
.
|
|
211
|
+
.description('Restore live project memory from a previous git snapshot without deleting audit or archive artifacts')
|
|
212
|
+
.option('--actor <name>', 'Registered human identity required to authorize the rollback')
|
|
213
|
+
.action((ref, options) => {
|
|
214
|
+
const cwd = process.cwd();
|
|
170
215
|
if (!hasMemoryRepo()) {
|
|
171
216
|
console.error('Error: no memory git repo. Run `brainclaw init --force` to enable.');
|
|
172
217
|
process.exit(1);
|
|
173
218
|
}
|
|
174
|
-
|
|
219
|
+
let actor;
|
|
220
|
+
try {
|
|
221
|
+
actor = requireRegisteredAgentIdentity({
|
|
222
|
+
agentName: options.actor,
|
|
223
|
+
allowCurrent: true,
|
|
224
|
+
allowEnv: true,
|
|
225
|
+
cwd,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
if (actor.kind !== 'human') {
|
|
233
|
+
console.error(`Error: memory-rollback is reserved to registered human identities. Resolved actor '${actor.agent_name}' is kind='${actor.kind}'.`);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
const success = rollbackMemory(ref, cwd);
|
|
175
237
|
if (success) {
|
|
176
|
-
console.log(`✔
|
|
238
|
+
console.log(`✔ Live project memory restored to ${ref} (audit, archives, backups preserved)`);
|
|
177
239
|
}
|
|
178
240
|
else {
|
|
179
241
|
console.error(`Error: failed to rollback to '${ref}'. Check memory-log for valid refs.`);
|
|
@@ -186,12 +248,45 @@ program
|
|
|
186
248
|
.description('Upgrade project memory structure and refresh managed workspace agent files without losing data')
|
|
187
249
|
.option('--json', 'Output as JSON')
|
|
188
250
|
.option('--dry-run', 'Show what would be done without making changes')
|
|
251
|
+
.option('--self-update', 'Check for a newer brainclaw package version and install it before upgrading memory')
|
|
252
|
+
.option('--to <version>', 'One-shot target schema version (e.g. --to=1.0). Real runs require a backup.')
|
|
253
|
+
.option('--backup', 'Create a timestamped backup of .brainclaw/ before any write (always on for --to runs)')
|
|
254
|
+
.option('--no-backup', 'Disable the automatic backup for housekeeping-only upgrade runs')
|
|
255
|
+
.option('--rollback', 'Restore the most recent backup, park the current live store, exit')
|
|
256
|
+
.option('--yes', 'Skip interactive confirmations (reserved for later prompt additions)')
|
|
189
257
|
.action((options) => {
|
|
190
258
|
runUpgrade({
|
|
191
259
|
json: options.json,
|
|
192
260
|
dryRun: options.dryRun,
|
|
261
|
+
selfUpdate: options.selfUpdate,
|
|
262
|
+
to: options.to,
|
|
263
|
+
backup: options.backup,
|
|
264
|
+
rollback: options.rollback,
|
|
265
|
+
yes: options.yes,
|
|
193
266
|
});
|
|
194
267
|
});
|
|
268
|
+
// --- patch-configs ---
|
|
269
|
+
program
|
|
270
|
+
.command('patch-configs')
|
|
271
|
+
.description('Patch all MCP config files to use the current brainclaw binary path')
|
|
272
|
+
.option('--json', 'Output as JSON')
|
|
273
|
+
.action((options) => {
|
|
274
|
+
const cwd = process.env.BRAINCLAW_CWD ?? process.cwd();
|
|
275
|
+
const results = patchAllMcpConfigs(cwd);
|
|
276
|
+
if (options.json) {
|
|
277
|
+
console.log(JSON.stringify(results, null, 2));
|
|
278
|
+
}
|
|
279
|
+
else if (results.length === 0) {
|
|
280
|
+
console.log('✔ All MCP configs are already up to date.');
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
for (const r of results) {
|
|
284
|
+
const tag = r.created ? 'created' : 'updated';
|
|
285
|
+
console.log(`✔ ${r.filePath} (${tag}) — ${r.label}`);
|
|
286
|
+
}
|
|
287
|
+
console.log(`\n${results.length} MCP config(s) patched.`);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
195
290
|
// --- machine-profile ---
|
|
196
291
|
program
|
|
197
292
|
.command('machine-profile')
|
|
@@ -346,6 +441,11 @@ program
|
|
|
346
441
|
.option('--plan <id>', 'Optional linked plan item ID')
|
|
347
442
|
.option('--author <author>', 'Author name')
|
|
348
443
|
.option('--capture-diff', 'Capture current git diff into the handoff snapshot')
|
|
444
|
+
.option('--files <files...>', 'Files touched in this handoff')
|
|
445
|
+
.option('--pre-condition <conditions...>', 'Pre-conditions for the receiving agent')
|
|
446
|
+
.option('--post-condition <conditions...>', 'Post-conditions the receiving agent must satisfy')
|
|
447
|
+
.option('--test <tests...>', 'Tests the receiving agent should verify')
|
|
448
|
+
.option('--linked-plan <plans...>', 'Linked plan IDs')
|
|
349
449
|
.action((text, options) => {
|
|
350
450
|
runHandoff(text, options);
|
|
351
451
|
});
|
|
@@ -376,8 +476,10 @@ program
|
|
|
376
476
|
.option('--estimate <minutes>', 'Estimated effort in minutes (positive integer, e.g. --estimate 30)')
|
|
377
477
|
.option('--actual-effort <effort>', 'Actual effort spent (e.g. "20min", "1h30m")')
|
|
378
478
|
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
479
|
+
.option('--recursive', 'Include plans from descendant brainclaw projects (for list)')
|
|
480
|
+
.option('--local-only', 'Read from local store only for list (skip parent stores in chain)')
|
|
379
481
|
.action((subcommand, args, options) => {
|
|
380
|
-
runPlanResource(subcommand, args, { ...options, actualEffort: options.actualEffort });
|
|
482
|
+
runPlanResource(subcommand, args, { ...options, actualEffort: options.actualEffort, localOnly: options.localOnly });
|
|
381
483
|
});
|
|
382
484
|
// --- list-plans ---
|
|
383
485
|
program
|
|
@@ -389,8 +491,24 @@ program
|
|
|
389
491
|
.option('--assignee <assignee>', 'Filter by assignee')
|
|
390
492
|
.option('--project <project>', 'Filter by project namespace')
|
|
391
493
|
.option('--all', 'Include done and dropped plan items')
|
|
494
|
+
.option('--recursive', 'Include plans from descendant brainclaw projects')
|
|
495
|
+
.option('--local-only', 'Read from local store only (skip parent stores in chain)')
|
|
392
496
|
.action((options) => {
|
|
393
|
-
runListPlans(options);
|
|
497
|
+
runListPlans({ ...options, localOnly: options.localOnly });
|
|
498
|
+
});
|
|
499
|
+
program
|
|
500
|
+
.command('sequence <subcommand> [args...]')
|
|
501
|
+
.description('Manage coordination sequences (create, list, show, update)')
|
|
502
|
+
.option('--json', 'Output as JSON')
|
|
503
|
+
.option('--description <text>', 'Optional sequence description')
|
|
504
|
+
.option('--status <status>', 'Sequence status: draft, active, archived')
|
|
505
|
+
.option('--owner <owner>', 'Optional sequence owner')
|
|
506
|
+
.option('--items <json>', 'Sequence items JSON array')
|
|
507
|
+
.option('--name <name>', 'Optional sequence name for update')
|
|
508
|
+
.option('--tag <tags...>', 'Tags for this sequence')
|
|
509
|
+
.option('--author <author>', 'Author name')
|
|
510
|
+
.action((subcommand, args, options) => {
|
|
511
|
+
runSequenceResource(subcommand, args, options);
|
|
394
512
|
});
|
|
395
513
|
// --- add-step ---
|
|
396
514
|
program
|
|
@@ -407,6 +525,23 @@ program
|
|
|
407
525
|
.action((planId, stepId) => {
|
|
408
526
|
runCompleteStep(planId, stepId);
|
|
409
527
|
});
|
|
528
|
+
// --- update-step ---
|
|
529
|
+
program
|
|
530
|
+
.command('update-step <planId> <stepId>')
|
|
531
|
+
.description('Update a plan step (status, text, assignee)')
|
|
532
|
+
.option('--status <status>', 'New status: todo, in_progress, testing, done, blocked')
|
|
533
|
+
.option('--text <text>', 'Replace step description')
|
|
534
|
+
.option('--assign <assignee>', 'Assign the step (empty string to unassign)')
|
|
535
|
+
.action((planId, stepId, options) => {
|
|
536
|
+
runUpdateStep(planId, stepId, options);
|
|
537
|
+
});
|
|
538
|
+
// --- delete-step ---
|
|
539
|
+
program
|
|
540
|
+
.command('delete-step <planId> <stepId>')
|
|
541
|
+
.description('Remove a step from a plan')
|
|
542
|
+
.action((planId, stepId) => {
|
|
543
|
+
runDeleteStep(planId, stepId);
|
|
544
|
+
});
|
|
410
545
|
// --- estimation-report ---
|
|
411
546
|
program
|
|
412
547
|
.command('estimation-report')
|
|
@@ -460,11 +595,25 @@ program
|
|
|
460
595
|
// --- update-handoff ---
|
|
461
596
|
program
|
|
462
597
|
.command('update-handoff <id>')
|
|
463
|
-
.description('Update the status of a handoff')
|
|
598
|
+
.description('Update the status, recipient, or review state of a handoff')
|
|
464
599
|
.option('--status <status>', 'Status: open, accepted, closed')
|
|
465
600
|
.option('--to <agent>', 'Change the receiving agent')
|
|
601
|
+
.option('--narrative <text>', 'Update the narrative attached to the handoff')
|
|
602
|
+
.option('--reviewer <agent>', 'Set or override the assigned reviewer')
|
|
603
|
+
.option('--review-verdict <verdict>', 'Set review verdict: approve or request_changes')
|
|
604
|
+
.option('--reviewed-by <agent>', 'Set the reviewer identity that produced the verdict')
|
|
605
|
+
.option('--review-summary <text>', 'Attach a short review summary')
|
|
606
|
+
.option('--blocking-issue <text>', 'Add a blocking review issue (repeatable)', collect, [])
|
|
607
|
+
.option('--suggestion <text>', 'Add a non-blocking review suggestion (repeatable)', collect, [])
|
|
466
608
|
.action((id, options) => {
|
|
467
|
-
runUpdateHandoff(id,
|
|
609
|
+
runUpdateHandoff(id, {
|
|
610
|
+
...options,
|
|
611
|
+
review_verdict: options.reviewVerdict,
|
|
612
|
+
reviewed_by: options.reviewedBy,
|
|
613
|
+
review_summary: options.reviewSummary,
|
|
614
|
+
blocking_issues: options.blockingIssue,
|
|
615
|
+
suggestions: options.suggestion,
|
|
616
|
+
});
|
|
468
617
|
});
|
|
469
618
|
// --- doctor ---
|
|
470
619
|
program
|
|
@@ -473,8 +622,34 @@ program
|
|
|
473
622
|
.option('--json', 'Output as JSON dashboard')
|
|
474
623
|
.option('--migration-check', 'Report versioned documents that need schema migration')
|
|
475
624
|
.option('--fix-agent-ignore', 'Add missing .gitignore entries for generated local Brainclaw agent files')
|
|
625
|
+
.option('--fix', 'Fix auto-resolvable issues (e.g. drifting MCP configs)')
|
|
626
|
+
.option('--repair', 'Rebuild dist/ when the MCP runtime is missing or stale')
|
|
627
|
+
.option('--after-migration', 'Run the v1.0 post-migration health check only (exits non-zero on any failure)')
|
|
628
|
+
.option('--dispatch', 'Run dispatch-health diagnostic only: reconcile open agent_runs and report stuck/unverified/silent failures (pln#496 step stp_8c072d75)')
|
|
476
629
|
.action((options) => {
|
|
477
|
-
runDoctor(options);
|
|
630
|
+
runDoctor({ ...options, afterMigration: options.afterMigration, dispatch: options.dispatch });
|
|
631
|
+
});
|
|
632
|
+
// --- repair (Phase 4 Sprint 2 Lane C / pln#397) ---
|
|
633
|
+
program
|
|
634
|
+
.command('repair')
|
|
635
|
+
.description('Apply safe, non-destructive fixes for the repair candidates surfaced by doctor')
|
|
636
|
+
.option('--dry-run', 'Print the plan without executing anything')
|
|
637
|
+
.option('--include-unsafe', 'Also apply candidates flagged unsafe (preserves data but requires confirmation)')
|
|
638
|
+
.option('--json', 'Output as JSON')
|
|
639
|
+
.action((options) => {
|
|
640
|
+
runRepair({
|
|
641
|
+
dryRun: options.dryRun,
|
|
642
|
+
includeUnsafe: options.includeUnsafe,
|
|
643
|
+
json: options.json,
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
// --- stale (Phase 4 Sprint 1 Lane A / pln#390) ---
|
|
647
|
+
program
|
|
648
|
+
.command('stale [subcommand] [id]')
|
|
649
|
+
.description('List or resolve stale memory items (plans, traps, handoffs, candidates, runtime notes). Subcommands: list (default), resolve <id>.')
|
|
650
|
+
.option('--json', 'Output as JSON')
|
|
651
|
+
.action((subcommand, id, options) => {
|
|
652
|
+
runStale(subcommand, id, { json: options.json });
|
|
478
653
|
});
|
|
479
654
|
// --- version ---
|
|
480
655
|
program
|
|
@@ -482,11 +657,23 @@ program
|
|
|
482
657
|
.description('Show the installed brainclaw version and the project version policy')
|
|
483
658
|
.option('--check', 'Check the configured installable update source')
|
|
484
659
|
.option('--publish-local', 'Create/update the local installable .releases channel via npm pack')
|
|
485
|
-
.option('--release-notes <text>', 'Attach release notes to the generated local-pack manifest')
|
|
660
|
+
.option('--release-notes <text>', 'Attach plain-text release notes to the generated local-pack manifest')
|
|
661
|
+
.option('--agent-release-notes <json>', 'Attach structured agent-first release notes (JSON) to the generated local-pack manifest')
|
|
662
|
+
.option('--auto-release-notes', 'Auto-generate agent-first release notes from git log (use with --publish-local)')
|
|
486
663
|
.option('--json', 'Output as JSON')
|
|
487
664
|
.action((options) => {
|
|
488
665
|
runVersion(options);
|
|
489
666
|
});
|
|
667
|
+
// --- release-notes ---
|
|
668
|
+
program
|
|
669
|
+
.command('release-notes')
|
|
670
|
+
.description('Show or generate agent-first release notes')
|
|
671
|
+
.option('--generate', 'Generate release notes from git log instead of showing configured ones')
|
|
672
|
+
.option('--since <ref>', 'Git ref to generate from (default: last version tag)')
|
|
673
|
+
.option('--json', 'Output as JSON')
|
|
674
|
+
.action((options) => {
|
|
675
|
+
runReleaseNotes(options);
|
|
676
|
+
});
|
|
490
677
|
// --- uninstall ---
|
|
491
678
|
import { runUninstall } from './commands/uninstall.js';
|
|
492
679
|
program
|
|
@@ -662,6 +849,7 @@ program
|
|
|
662
849
|
.command('enable-agent <name>')
|
|
663
850
|
.description('Activate a supported coding agent on an already initialized project')
|
|
664
851
|
.option('--kind <kind>', 'Identity kind: agent, human, unknown', 'agent')
|
|
852
|
+
.option('--context-profile <profile>', 'Default context profile: dev, dense, compact, copilot, quick, openclaw, ops, research')
|
|
665
853
|
.option('--capability <value>', 'Declare a capability on the agent profile (repeatable)', collect, [])
|
|
666
854
|
.option('--replace-capabilities', 'Replace existing capabilities instead of merging')
|
|
667
855
|
.option('--generate-fingerprint', 'Generate or rotate a local public identity fingerprint for this agent')
|
|
@@ -749,6 +937,17 @@ program
|
|
|
749
937
|
.action((id, options) => {
|
|
750
938
|
runReject(id, options.reason, options.by);
|
|
751
939
|
});
|
|
940
|
+
// --- harvest-candidates ---
|
|
941
|
+
program
|
|
942
|
+
.command('harvest-candidates')
|
|
943
|
+
.description('Harvest candidates from worktree inboxes into the main project store (codex sandbox bridge)')
|
|
944
|
+
.option('--dry-run', 'Preview what would be imported without writing anything')
|
|
945
|
+
.option('--worktree <path>', 'Explicit worktree path to scan (repeatable)', collect, [])
|
|
946
|
+
.option('--json', 'Output as JSON')
|
|
947
|
+
.action((options) => {
|
|
948
|
+
const globalOpts = program.opts();
|
|
949
|
+
runHarvestCandidates({ ...options, cwd: globalOpts.cwd });
|
|
950
|
+
});
|
|
752
951
|
// --- prune-candidates ---
|
|
753
952
|
program
|
|
754
953
|
.command('prune-candidates')
|
|
@@ -758,6 +957,35 @@ program
|
|
|
758
957
|
.action((options) => {
|
|
759
958
|
runPruneCandidates(options);
|
|
760
959
|
});
|
|
960
|
+
// --- cleanup-candidates ---
|
|
961
|
+
program
|
|
962
|
+
.command('cleanup-candidates')
|
|
963
|
+
.description('Remove stale auto-generated pending candidates')
|
|
964
|
+
.option('--max-age <days>', 'Max age in days before cleanup', parseInt)
|
|
965
|
+
.option('--dry-run', 'Preview without deleting')
|
|
966
|
+
.action((options) => {
|
|
967
|
+
if (!memoryExists()) {
|
|
968
|
+
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
969
|
+
process.exit(1);
|
|
970
|
+
}
|
|
971
|
+
const maxAgeDays = options.maxAge ?? 30;
|
|
972
|
+
const result = cleanupStaleCandidates({
|
|
973
|
+
maxAgeDays,
|
|
974
|
+
dryRun: options.dryRun,
|
|
975
|
+
});
|
|
976
|
+
if (result.matched === 0) {
|
|
977
|
+
console.log(`No stale auto-generated candidates older than ${maxAgeDays} days found.`);
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
if (options.dryRun) {
|
|
981
|
+
console.log(`Would remove ${result.matched} stale auto-generated candidate(s):`);
|
|
982
|
+
for (const candidate of result.candidates) {
|
|
983
|
+
console.log(` [${candidate.id}] ${candidate.text}`);
|
|
984
|
+
}
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
console.log(`✔ Removed ${result.deleted} stale auto-generated candidate(s) older than ${maxAgeDays} days.`);
|
|
988
|
+
});
|
|
761
989
|
// --- claim ---
|
|
762
990
|
program
|
|
763
991
|
.command('claim <subcommand> [args...]')
|
|
@@ -771,8 +999,9 @@ program
|
|
|
771
999
|
.option('--json', 'Output as JSON for list')
|
|
772
1000
|
.option('--plan-status <status>', 'Optional linked plan status when releasing: todo, in_progress, blocked, done, dropped')
|
|
773
1001
|
.option('--store <target>', 'Target store level: local (default), repo, workspace')
|
|
1002
|
+
.option('--local-only', 'Read from local store only for list (skip parent stores in chain)')
|
|
774
1003
|
.action((subcommand, args, options) => {
|
|
775
|
-
runClaimResource(subcommand, args, { ...options, planStatus: options.planStatus });
|
|
1004
|
+
runClaimResource(subcommand, args, { ...options, planStatus: options.planStatus, localOnly: options.localOnly });
|
|
776
1005
|
});
|
|
777
1006
|
// --- list-claims ---
|
|
778
1007
|
program
|
|
@@ -783,8 +1012,9 @@ program
|
|
|
783
1012
|
.option('--project <project>', 'Filter by project namespace')
|
|
784
1013
|
.option('--plan <id>', 'Filter by linked plan item')
|
|
785
1014
|
.option('--agent <agent>', 'Filter by agent name')
|
|
1015
|
+
.option('--local-only', 'Read from local store only (skip parent stores in chain)')
|
|
786
1016
|
.action((options) => {
|
|
787
|
-
runListClaims(options);
|
|
1017
|
+
runListClaims({ ...options, localOnly: options.localOnly });
|
|
788
1018
|
});
|
|
789
1019
|
// --- release-claim ---
|
|
790
1020
|
program
|
|
@@ -818,6 +1048,7 @@ program
|
|
|
818
1048
|
.option('--capabilities', 'List all registered agents with their declared capabilities')
|
|
819
1049
|
.option('--suggest <query>', 'Suggest agents whose capabilities match a query string')
|
|
820
1050
|
.option('--include-session-meta', 'Include session_start/session_end runtime notes (hidden by default)')
|
|
1051
|
+
.option('--all-agents', 'Show unfiltered board (supervisor mode — all claims, all agents)')
|
|
821
1052
|
.action((options) => {
|
|
822
1053
|
runAgentBoard(options);
|
|
823
1054
|
});
|
|
@@ -836,6 +1067,24 @@ program
|
|
|
836
1067
|
.action((text, options) => {
|
|
837
1068
|
runRuntimeNote(text, { ...options, autoReflect: options.autoReflect });
|
|
838
1069
|
});
|
|
1070
|
+
// --- note create ---
|
|
1071
|
+
const noteCommand = program
|
|
1072
|
+
.command('note')
|
|
1073
|
+
.description('Manage runtime notes');
|
|
1074
|
+
noteCommand
|
|
1075
|
+
.command('create <text>')
|
|
1076
|
+
.description('Alias for runtime-note')
|
|
1077
|
+
.option('--agent <agent>', 'Agent name; defaults to the configured current agent')
|
|
1078
|
+
.option('--project <project>', 'Optional project namespace')
|
|
1079
|
+
.option('--plan <id>', 'Optional linked plan item ID')
|
|
1080
|
+
.option('--visibility <visibility>', 'Visibility: shared, machine, private', 'shared')
|
|
1081
|
+
.option('--host <host>', 'Optional host identifier override for machine/private runtime notes')
|
|
1082
|
+
.option('--tag <tags...>', 'Tags')
|
|
1083
|
+
.option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d (note auto-expires after this duration)')
|
|
1084
|
+
.option('--auto-reflect', 'Attempt to turn this runtime note into durable memory immediately')
|
|
1085
|
+
.action((text, options) => {
|
|
1086
|
+
runRuntimeNote(text, { ...options, autoReflect: options.autoReflect });
|
|
1087
|
+
});
|
|
839
1088
|
// --- runtime-status ---
|
|
840
1089
|
program
|
|
841
1090
|
.command('runtime-status')
|
|
@@ -872,6 +1121,46 @@ program
|
|
|
872
1121
|
.action((options) => {
|
|
873
1122
|
runCheckConstraints({ staged: options.staged, files: options.files, json: options.json });
|
|
874
1123
|
});
|
|
1124
|
+
// --- check-policy ---
|
|
1125
|
+
program
|
|
1126
|
+
.command('check-policy')
|
|
1127
|
+
.description('Pre-execution policy check: verify claims, constraints, traps and instructions for a scope')
|
|
1128
|
+
.requiredOption('--scope <path>', 'File or directory scope to check')
|
|
1129
|
+
.option('--agent <name>', 'Agent name to check claims for')
|
|
1130
|
+
.option('--agent-id <id>', 'Agent id to check claims for')
|
|
1131
|
+
.option('--action <action>', 'Intended action: edit, create, delete')
|
|
1132
|
+
.option('--json', 'Output as JSON')
|
|
1133
|
+
.action((options) => {
|
|
1134
|
+
runCheckPolicy({
|
|
1135
|
+
scope: options.scope,
|
|
1136
|
+
agent: options.agent,
|
|
1137
|
+
agentId: options.agentId,
|
|
1138
|
+
action: options.action,
|
|
1139
|
+
json: options.json,
|
|
1140
|
+
});
|
|
1141
|
+
});
|
|
1142
|
+
// --- check-security ---
|
|
1143
|
+
program
|
|
1144
|
+
.command('check-security')
|
|
1145
|
+
.description('Check supply chain security scores for packages via Socket.dev')
|
|
1146
|
+
.requiredOption('--packages <names>', 'Comma-separated package names (e.g. "axios,express" or "axios@1.14.1")')
|
|
1147
|
+
.option('--ecosystem <type>', 'Package ecosystem: npm or pypi', 'npm')
|
|
1148
|
+
.option('--json', 'Output as JSON')
|
|
1149
|
+
.action(async (options) => {
|
|
1150
|
+
await runCheckSecurity({
|
|
1151
|
+
packages: options.packages,
|
|
1152
|
+
ecosystem: options.ecosystem,
|
|
1153
|
+
json: options.json,
|
|
1154
|
+
});
|
|
1155
|
+
});
|
|
1156
|
+
// --- setup-security ---
|
|
1157
|
+
program
|
|
1158
|
+
.command('setup-security')
|
|
1159
|
+
.description('Enable supply chain security gate: generate wrapper scripts and configure preinstall checks')
|
|
1160
|
+
.option('--mode <mode>', 'Security mode: advisory (default) or enforced', 'advisory')
|
|
1161
|
+
.action((options) => {
|
|
1162
|
+
runSetupSecurity({ mode: options.mode });
|
|
1163
|
+
});
|
|
875
1164
|
// --- install-hooks ---
|
|
876
1165
|
program
|
|
877
1166
|
.command('install-hooks')
|
|
@@ -894,9 +1183,26 @@ program
|
|
|
894
1183
|
.command('prune')
|
|
895
1184
|
.description('Prune expired constraints and stale memory')
|
|
896
1185
|
.option('--expired', 'Also prune expired runtime notes and traps')
|
|
1186
|
+
.option('--archive', 'Archive done plans and closed handoffs (>30 days) to cold storage JSONL')
|
|
1187
|
+
.option('--semantic', 'Detect near-duplicate clusters and stale items via semantic analysis')
|
|
1188
|
+
.option('--dry-run', 'Preview compaction without applying (use with --semantic)')
|
|
897
1189
|
.action((options) => {
|
|
898
1190
|
runPrune(options);
|
|
899
1191
|
});
|
|
1192
|
+
// --- compact ---
|
|
1193
|
+
program
|
|
1194
|
+
.command('compact')
|
|
1195
|
+
.description('LLM-driven semantic memory compaction — archive old items and get a summary template')
|
|
1196
|
+
.option('--assess', 'Show pressure assessment and compaction template without archiving')
|
|
1197
|
+
.option('--dry-run', 'Preview eligible items without archiving')
|
|
1198
|
+
.option('--max-items <n>', 'Maximum items to compact (default: 20)', parseInt)
|
|
1199
|
+
.option('--min-age <days>', 'Minimum age in days for eligibility (default: 7)', parseInt)
|
|
1200
|
+
.option('--no-dedup-handoffs', 'Skip deduplication of auto-generated session-end handoffs')
|
|
1201
|
+
.option('--no-purge-claims', 'Skip archival of released claims')
|
|
1202
|
+
.option('--no-purge-session-notes', 'Skip archival of session-lifecycle runtime_notes')
|
|
1203
|
+
.action((options) => {
|
|
1204
|
+
runCompact(options);
|
|
1205
|
+
});
|
|
900
1206
|
// --- mcp ---
|
|
901
1207
|
program
|
|
902
1208
|
.command('mcp')
|
|
@@ -921,6 +1227,8 @@ program
|
|
|
921
1227
|
.option('--agent <agent>', 'Agent name (defaults to current configured agent)')
|
|
922
1228
|
.option('--context <path>', 'Context target path for initial hash capture')
|
|
923
1229
|
.option('--model <id>', 'Model identifier (e.g. claude-sonnet-4-6)')
|
|
1230
|
+
.option('--maintenance-mode <mode>', 'Maintenance mode: full (default) or fast')
|
|
1231
|
+
.option('--include-context', 'Output full project context after starting session (replaces separate context call)')
|
|
924
1232
|
.option('--json', 'Output as JSON')
|
|
925
1233
|
.action((options) => {
|
|
926
1234
|
runSessionStart(options);
|
|
@@ -934,10 +1242,21 @@ program
|
|
|
934
1242
|
.option('--summary <text>', 'Session summary text')
|
|
935
1243
|
.option('--auto-reflect', 'Auto-reflect session notes as pending candidates')
|
|
936
1244
|
.option('--auto-release', 'Auto-release any active claims at session end')
|
|
937
|
-
.option('--reflect-handoff', '
|
|
1245
|
+
.option('--reflect-handoff', 'Materialize an open handoff from git commits since session start')
|
|
1246
|
+
.option('--dispatch-review', 'When used with --reflect-handoff, auto-dispatch a code review if the handoff is reviewable')
|
|
1247
|
+
.option('--reviewer <name>', 'Explicit reviewer to route the reflected handoff review to')
|
|
1248
|
+
.option('--reflect', 'Include structured reflection questions for the agent to answer')
|
|
938
1249
|
.option('--json', 'Output as JSON')
|
|
939
1250
|
.action((options) => {
|
|
940
|
-
runSessionEnd({
|
|
1251
|
+
runSessionEnd({
|
|
1252
|
+
...options,
|
|
1253
|
+
autoReflect: options.autoReflect,
|
|
1254
|
+
autoRelease: options.autoRelease,
|
|
1255
|
+
reflectHandoff: options.reflectHandoff,
|
|
1256
|
+
dispatchReview: options.dispatchReview,
|
|
1257
|
+
reviewer: options.reviewer,
|
|
1258
|
+
reflect: options.reflect,
|
|
1259
|
+
});
|
|
941
1260
|
});
|
|
942
1261
|
// --- whoami ---
|
|
943
1262
|
program
|
|
@@ -947,6 +1266,17 @@ program
|
|
|
947
1266
|
.action((options) => {
|
|
948
1267
|
runWhoami(options);
|
|
949
1268
|
});
|
|
1269
|
+
// --- usage ---
|
|
1270
|
+
program
|
|
1271
|
+
.command('usage')
|
|
1272
|
+
.description('Show brainclaw context volume stats (tokens injected per agent/tool)')
|
|
1273
|
+
.option('--agent <name>', 'Filter by agent name')
|
|
1274
|
+
.option('--tool <name>', 'Filter by tool name')
|
|
1275
|
+
.option('--days <n>', 'Limit to last N days', parseInt)
|
|
1276
|
+
.option('--json', 'Output as JSON')
|
|
1277
|
+
.action((options) => {
|
|
1278
|
+
runUsage(options);
|
|
1279
|
+
});
|
|
950
1280
|
// --- search ---
|
|
951
1281
|
program
|
|
952
1282
|
.command('search <query>')
|
|
@@ -968,6 +1298,7 @@ program
|
|
|
968
1298
|
.option('--detect', 'Auto-detect agent environment and write to its native file')
|
|
969
1299
|
.option('--all', 'Write all known agent instruction files at once (claude-md, agents-md, copilot-instructions, cursor-rules, etc.)')
|
|
970
1300
|
.option('--write', 'Write to canonical file path instead of stdout (when --format is given); local files are gitignored by default')
|
|
1301
|
+
.option('--include-live', 'Also write the native live companion file when the target agent supports one')
|
|
971
1302
|
.option('--shared', 'Keep the main exported instruction file versionable instead of auto-ignoring it (companions remain local)')
|
|
972
1303
|
.option('--output <file>', 'Write to a specific file path instead of stdout')
|
|
973
1304
|
.option('--project <project>', 'Project namespace filter')
|
|
@@ -975,6 +1306,12 @@ program
|
|
|
975
1306
|
.action((options) => {
|
|
976
1307
|
runExport(options);
|
|
977
1308
|
});
|
|
1309
|
+
program
|
|
1310
|
+
.command('refresh')
|
|
1311
|
+
.description('Refresh live companion files with current state (plans, claims, traps, sequences). Gitignored, safe to run frequently.')
|
|
1312
|
+
.action(() => {
|
|
1313
|
+
runRefresh();
|
|
1314
|
+
});
|
|
978
1315
|
program
|
|
979
1316
|
.command('reconcile')
|
|
980
1317
|
.description('Refresh machine and workspace bootstrap state after updates or onboarding on complex installs')
|
|
@@ -1012,6 +1349,110 @@ program
|
|
|
1012
1349
|
.action((options) => {
|
|
1013
1350
|
runWatch({ ...options, autoClaim: options.autoClaim });
|
|
1014
1351
|
});
|
|
1352
|
+
// --- dispatch ---
|
|
1353
|
+
const dispatchCmd = program
|
|
1354
|
+
.command('dispatch')
|
|
1355
|
+
.description('Local agent dispatcher — analyze lanes and assign work');
|
|
1356
|
+
dispatchCmd
|
|
1357
|
+
.command('analysis')
|
|
1358
|
+
.description('Analyze the active sequence: show ready, active, blocked, and done lanes')
|
|
1359
|
+
.option('--json', 'Output as JSON')
|
|
1360
|
+
.action((options) => {
|
|
1361
|
+
runDispatchAnalysis({ json: options.json });
|
|
1362
|
+
});
|
|
1363
|
+
dispatchCmd
|
|
1364
|
+
.command('run')
|
|
1365
|
+
.description('Run a dispatch cycle: assign ready lanes to available agents')
|
|
1366
|
+
.option('--agents <names>', 'Comma-separated list of agents to dispatch to')
|
|
1367
|
+
.option('--lanes <names>', 'Comma-separated list of lanes to dispatch')
|
|
1368
|
+
.option('--max <n>', 'Maximum assignments', parseInt)
|
|
1369
|
+
.option('--dry', 'Preview assignments without sending messages')
|
|
1370
|
+
.option('--spawn', 'Autonomously launch CLI agents with invoke templates')
|
|
1371
|
+
.option('--agent <name>', 'Dispatcher agent name')
|
|
1372
|
+
.option('--json', 'Output as JSON')
|
|
1373
|
+
.action((options) => {
|
|
1374
|
+
runDispatch({
|
|
1375
|
+
agents: options.agents,
|
|
1376
|
+
lanes: options.lanes,
|
|
1377
|
+
max: options.max,
|
|
1378
|
+
dry: options.dry,
|
|
1379
|
+
spawn: options.spawn,
|
|
1380
|
+
agent: options.agent,
|
|
1381
|
+
json: options.json,
|
|
1382
|
+
});
|
|
1383
|
+
});
|
|
1384
|
+
dispatchCmd
|
|
1385
|
+
.command('review')
|
|
1386
|
+
.description('Dispatch code reviews for completed handoffs')
|
|
1387
|
+
.option('--handoff <id>', 'Specific handoff ID to review')
|
|
1388
|
+
.option('--reviewer <name>', 'Specific reviewer agent')
|
|
1389
|
+
.option('--spawn', 'Launch the reviewer CLI agent')
|
|
1390
|
+
.option('--dry', 'Preview without sending')
|
|
1391
|
+
.option('--agent <name>', 'Dispatcher agent name')
|
|
1392
|
+
.option('--json', 'Output as JSON')
|
|
1393
|
+
.action((options) => {
|
|
1394
|
+
runDispatchReview({
|
|
1395
|
+
handoff: options.handoff,
|
|
1396
|
+
reviewer: options.reviewer,
|
|
1397
|
+
spawn: options.spawn,
|
|
1398
|
+
dry: options.dry,
|
|
1399
|
+
agent: options.agent,
|
|
1400
|
+
json: options.json,
|
|
1401
|
+
});
|
|
1402
|
+
});
|
|
1403
|
+
// --- inbox ---
|
|
1404
|
+
const inboxCmd = program
|
|
1405
|
+
.command('inbox')
|
|
1406
|
+
.description('Inter-agent messaging inbox');
|
|
1407
|
+
inboxCmd
|
|
1408
|
+
.command('list')
|
|
1409
|
+
.description('List inbox messages (default: pending only)')
|
|
1410
|
+
.option('--agent <name>', 'Agent name')
|
|
1411
|
+
.option('--status <status>', 'Filter by status: pending, read, acknowledged, archived')
|
|
1412
|
+
.option('--type <type>', 'Filter by type: assign, review, rfc, info, reply')
|
|
1413
|
+
.option('--thread <id>', 'Filter by thread ID')
|
|
1414
|
+
.option('--all', 'Show all messages, not just pending')
|
|
1415
|
+
.option('--json', 'Output as JSON')
|
|
1416
|
+
.option('--local-only', 'Read from local store only (skip parent stores in chain)')
|
|
1417
|
+
.action((options) => {
|
|
1418
|
+
runInboxList({ ...options, localOnly: options.localOnly });
|
|
1419
|
+
});
|
|
1420
|
+
inboxCmd
|
|
1421
|
+
.command('ack <id>')
|
|
1422
|
+
.description('Acknowledge a message')
|
|
1423
|
+
.option('--agent <name>', 'Agent name')
|
|
1424
|
+
.option('--json', 'Output as JSON')
|
|
1425
|
+
.action((id, options) => {
|
|
1426
|
+
runInboxAck(id, options);
|
|
1427
|
+
});
|
|
1428
|
+
inboxCmd
|
|
1429
|
+
.command('archive <id>')
|
|
1430
|
+
.description('Archive a message')
|
|
1431
|
+
.option('--agent <name>', 'Agent name')
|
|
1432
|
+
.option('--json', 'Output as JSON')
|
|
1433
|
+
.action((id, options) => {
|
|
1434
|
+
runInboxArchive(id, options);
|
|
1435
|
+
});
|
|
1436
|
+
inboxCmd
|
|
1437
|
+
.command('send <to> <text>')
|
|
1438
|
+
.description('Send a message to another agent')
|
|
1439
|
+
.option('--type <type>', 'Message type: assign, review, rfc, info, reply (default: info)')
|
|
1440
|
+
.option('--ref <id>', 'Reference to a plan, sequence, or other entity')
|
|
1441
|
+
.option('--scope <path>', 'File scope')
|
|
1442
|
+
.option('--thread <id>', 'Thread ID for conversations')
|
|
1443
|
+
.option('--ack', 'Require acknowledgment')
|
|
1444
|
+
.option('--agent <name>', 'Sender agent name')
|
|
1445
|
+
.option('--json', 'Output as JSON')
|
|
1446
|
+
.action((to, text, options) => {
|
|
1447
|
+
runInboxSend(to, text, options);
|
|
1448
|
+
});
|
|
1449
|
+
inboxCmd
|
|
1450
|
+
.command('thread <id>')
|
|
1451
|
+
.description('Show all messages in a thread')
|
|
1452
|
+
.option('--json', 'Output as JSON')
|
|
1453
|
+
.action((id, options) => {
|
|
1454
|
+
runInboxThread(id, options);
|
|
1455
|
+
});
|
|
1015
1456
|
// --- check-events ---
|
|
1016
1457
|
program
|
|
1017
1458
|
.command('check-events')
|
|
@@ -1063,14 +1504,16 @@ program
|
|
|
1063
1504
|
// --- audit ---
|
|
1064
1505
|
program
|
|
1065
1506
|
.command('audit')
|
|
1066
|
-
.description('View the append-only audit log
|
|
1507
|
+
.description('View the append-only audit log, or generate a governance posture report with --governance')
|
|
1067
1508
|
.option('--since <date>', 'Show entries since this ISO date')
|
|
1068
1509
|
.option('--actor <agent>', 'Filter by actor name or agent ID')
|
|
1069
1510
|
.option('--action <action>', 'Filter by action type (create, accept, reject, etc.)')
|
|
1070
1511
|
.option('--limit <n>', 'Show last N entries', parseInt)
|
|
1071
1512
|
.option('--json', 'Output as JSON')
|
|
1513
|
+
.option('--governance', 'Generate a governance posture report (aggregated view of claims, constraints, traps, instructions)')
|
|
1514
|
+
.option('--scope <path>', 'Filter governance report by scope (used with --governance)')
|
|
1072
1515
|
.action((options) => {
|
|
1073
|
-
runAuditCommand({ since: options.since, actor: options.actor, action: options.action, limit: options.limit, json: options.json });
|
|
1516
|
+
runAuditCommand({ since: options.since, actor: options.actor, action: options.action, limit: options.limit, json: options.json, governance: options.governance, scope: options.scope });
|
|
1074
1517
|
});
|
|
1075
1518
|
// --- history ---
|
|
1076
1519
|
program
|
|
@@ -1102,6 +1545,25 @@ program
|
|
|
1102
1545
|
store: options.store,
|
|
1103
1546
|
});
|
|
1104
1547
|
});
|
|
1548
|
+
program
|
|
1549
|
+
.command('link <subcommand> [args...]')
|
|
1550
|
+
.description('Manage cross-project federation links (add, list, remove)')
|
|
1551
|
+
.option('--name <slug>', 'Override the auto-derived link name')
|
|
1552
|
+
.option('--role <role>', 'Link role: publisher (push signals out) or subscriber (default)')
|
|
1553
|
+
.option('--channels <list>', 'Comma-separated allow-list of channels: candidate,handoff,runtime_note', (val) => val.split(',').map((s) => s.trim()).filter(Boolean))
|
|
1554
|
+
.option('--force', 'Replace an existing link of the same name/path')
|
|
1555
|
+
.option('--json', 'Output as JSON')
|
|
1556
|
+
.option('--store <target>', 'Store level: local (default), repo, workspace, user')
|
|
1557
|
+
.action((subcommand, args, options) => {
|
|
1558
|
+
runLink(subcommand, args, {
|
|
1559
|
+
name: options.name,
|
|
1560
|
+
role: options.role,
|
|
1561
|
+
channels: options.channels,
|
|
1562
|
+
force: options.force,
|
|
1563
|
+
json: options.json,
|
|
1564
|
+
store: options.store,
|
|
1565
|
+
});
|
|
1566
|
+
});
|
|
1105
1567
|
program
|
|
1106
1568
|
.command('tool <subcommand> [args...]')
|
|
1107
1569
|
.description('Manage project tools (list, add, describe, search)')
|
|
@@ -1163,10 +1625,197 @@ program
|
|
|
1163
1625
|
.option('--json', 'Output as JSON')
|
|
1164
1626
|
.option('--all', 'Include stale sessions')
|
|
1165
1627
|
.option('--gc', 'Remove stale sessions')
|
|
1628
|
+
.option('--local-only', 'Read claims from local store only (skip parent stores in chain)')
|
|
1166
1629
|
.action(async (options) => {
|
|
1167
1630
|
const globalOpts = program.opts();
|
|
1168
1631
|
const { runWho } = await import('./commands/who.js');
|
|
1169
|
-
runWho({ json: options.json, all: options.all, gc: options.gc, cwd: globalOpts.cwd });
|
|
1632
|
+
runWho({ json: options.json, all: options.all, gc: options.gc, cwd: globalOpts.cwd, localOnly: options.localOnly });
|
|
1633
|
+
});
|
|
1634
|
+
const worktreeCmd = program
|
|
1635
|
+
.command('worktree')
|
|
1636
|
+
.description('Manage git worktrees for parallel agent isolation');
|
|
1637
|
+
worktreeCmd
|
|
1638
|
+
.command('create <branch>')
|
|
1639
|
+
.description('Create a linked git worktree for a given branch')
|
|
1640
|
+
.option('--session-id <id>', 'Associate this worktree with a brainclaw session')
|
|
1641
|
+
.option('--agent <name>', 'Associate this worktree with an agent name')
|
|
1642
|
+
.action((branch, options) => {
|
|
1643
|
+
const globalOpts = program.opts();
|
|
1644
|
+
runWorktreeCreate({ branch, sessionId: options.sessionId, agent: options.agent, cwd: globalOpts.cwd });
|
|
1645
|
+
});
|
|
1646
|
+
worktreeCmd
|
|
1647
|
+
.command('list')
|
|
1648
|
+
.description('List all git worktrees for this project')
|
|
1649
|
+
.action(() => {
|
|
1650
|
+
const globalOpts = program.opts();
|
|
1651
|
+
runWorktreeList({ cwd: globalOpts.cwd });
|
|
1652
|
+
});
|
|
1653
|
+
worktreeCmd
|
|
1654
|
+
.command('remove <path>')
|
|
1655
|
+
.description('Remove a linked git worktree')
|
|
1656
|
+
.option('--force', 'Force removal even with uncommitted changes')
|
|
1657
|
+
.action((worktreePath, options) => {
|
|
1658
|
+
const globalOpts = program.opts();
|
|
1659
|
+
runWorktreeRemove({ path: worktreePath, force: options.force, cwd: globalOpts.cwd });
|
|
1660
|
+
});
|
|
1661
|
+
worktreeCmd
|
|
1662
|
+
.command('prune')
|
|
1663
|
+
.description('Prune stale worktree administrative files')
|
|
1664
|
+
.action(() => {
|
|
1665
|
+
const globalOpts = program.opts();
|
|
1666
|
+
runWorktreePrune({ cwd: globalOpts.cwd });
|
|
1667
|
+
});
|
|
1668
|
+
worktreeCmd
|
|
1669
|
+
.command('clean')
|
|
1670
|
+
.description('Remove worktrees whose branch is fully merged and orphan worktree directories')
|
|
1671
|
+
.option('--force', 'Force removal even with uncommitted changes')
|
|
1672
|
+
.option('--dry-run', 'Show what would be removed without actually removing')
|
|
1673
|
+
.action((options) => {
|
|
1674
|
+
const globalOpts = program.opts();
|
|
1675
|
+
runWorktreeClean({ force: options.force, dryRun: options.dryRun, cwd: globalOpts.cwd });
|
|
1676
|
+
});
|
|
1677
|
+
worktreeCmd
|
|
1678
|
+
.command('merge <branch>')
|
|
1679
|
+
.description('Merge a worktree branch with auto-restoration of parasitic deletions')
|
|
1680
|
+
.option('-m, --message <message>', 'Merge commit message')
|
|
1681
|
+
.option('--dry-run', 'Show what would be merged without committing')
|
|
1682
|
+
.action((branch, options) => {
|
|
1683
|
+
const globalOpts = program.opts();
|
|
1684
|
+
runWorktreeMerge({ branch, message: options.message, dryRun: options.dryRun, cwd: globalOpts.cwd });
|
|
1685
|
+
});
|
|
1686
|
+
// --- federation cloud ---
|
|
1687
|
+
const federationCmd = program
|
|
1688
|
+
.command('federation')
|
|
1689
|
+
.description('Cloud federation — sync signals with app.brainclaw.dev');
|
|
1690
|
+
federationCmd
|
|
1691
|
+
.command('push <message>')
|
|
1692
|
+
.description('Push a test signal to the cloud')
|
|
1693
|
+
.option('--type <type>', 'Signal type', 'runtime_note')
|
|
1694
|
+
.option('--to-project <project>', 'Target project name')
|
|
1695
|
+
.option('--to-agent <agent>', 'Target agent name')
|
|
1696
|
+
.action(async (message, options) => {
|
|
1697
|
+
const { pushSignalToCloud, isCloudConfigured } = await import('./core/federation-cloud.js');
|
|
1698
|
+
const { createFederationMessage } = await import('./core/federation-message.js');
|
|
1699
|
+
const { loadConfig } = await import('./core/config.js');
|
|
1700
|
+
const { resolveCurrentAgentName } = await import('./core/agent-registry.js');
|
|
1701
|
+
if (!isCloudConfigured()) {
|
|
1702
|
+
console.error('Error: cloud not configured. Set BRAINCLAW_CLOUD_API_KEY env var.');
|
|
1703
|
+
process.exit(1);
|
|
1704
|
+
}
|
|
1705
|
+
const config = loadConfig();
|
|
1706
|
+
const agent = resolveCurrentAgentName() ?? 'unknown';
|
|
1707
|
+
const msg = createFederationMessage({
|
|
1708
|
+
version: 1,
|
|
1709
|
+
from: { project_name: config.project_name, project_path: process.cwd(), agent_name: agent },
|
|
1710
|
+
to: { project_name: options.toProject ?? 'broadcast', project_path: '' },
|
|
1711
|
+
type: options.type,
|
|
1712
|
+
payload: { text: message },
|
|
1713
|
+
});
|
|
1714
|
+
const ok = await pushSignalToCloud(msg);
|
|
1715
|
+
if (ok) {
|
|
1716
|
+
console.log(`✔ Signal pushed to cloud: [${msg.id}] ${message}`);
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
console.error('Error: failed to push signal to cloud.');
|
|
1720
|
+
process.exit(1);
|
|
1721
|
+
}
|
|
1722
|
+
});
|
|
1723
|
+
federationCmd
|
|
1724
|
+
.command('pull')
|
|
1725
|
+
.description('Pull signals from the cloud inbox')
|
|
1726
|
+
.option('--agent <name>', 'Agent name to pull for')
|
|
1727
|
+
.option('--since <date>', 'Only pull signals after this ISO date')
|
|
1728
|
+
.option('--limit <n>', 'Max signals to pull', '20')
|
|
1729
|
+
.action(async (options) => {
|
|
1730
|
+
const { pullSignalsFromCloud, isCloudConfigured } = await import('./core/federation-cloud.js');
|
|
1731
|
+
const { resolveCurrentAgentName } = await import('./core/agent-registry.js');
|
|
1732
|
+
if (!isCloudConfigured()) {
|
|
1733
|
+
console.error('Error: cloud not configured. Set BRAINCLAW_CLOUD_API_KEY env var.');
|
|
1734
|
+
process.exit(1);
|
|
1735
|
+
}
|
|
1736
|
+
const agent = options.agent ?? resolveCurrentAgentName() ?? 'unknown';
|
|
1737
|
+
const signals = await pullSignalsFromCloud(agent, {
|
|
1738
|
+
since: options.since,
|
|
1739
|
+
limit: parseInt(options.limit, 10),
|
|
1740
|
+
});
|
|
1741
|
+
if (signals.length === 0) {
|
|
1742
|
+
console.log('No signals in cloud inbox.');
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
console.log(`${signals.length} signal(s) from cloud:\n`);
|
|
1746
|
+
for (const s of signals) {
|
|
1747
|
+
const payload = typeof s.payload === 'object' && s.payload !== null ? s.payload.text ?? JSON.stringify(s.payload) : String(s.payload);
|
|
1748
|
+
console.log(` [${s.id}] ${s.type} from ${s.from.project_name}/${s.from.agent_name}`);
|
|
1749
|
+
console.log(` ${String(payload).slice(0, 120)}`);
|
|
1750
|
+
console.log(` ${s.created_at}\n`);
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
federationCmd
|
|
1754
|
+
.command('status')
|
|
1755
|
+
.description('Check cloud federation configuration')
|
|
1756
|
+
.action(async () => {
|
|
1757
|
+
const { isCloudConfigured } = await import('./core/federation-cloud.js');
|
|
1758
|
+
const url = process.env.BRAINCLAW_CLOUD_URL ?? 'https://app.brainclaw.dev';
|
|
1759
|
+
console.log(`Cloud URL: ${url}`);
|
|
1760
|
+
console.log(`API Key: ${process.env.BRAINCLAW_CLOUD_API_KEY ? '***configured***' : 'NOT SET'}`);
|
|
1761
|
+
console.log(`Configured: ${isCloudConfigured() ? 'yes' : 'no'}`);
|
|
1762
|
+
if (isCloudConfigured()) {
|
|
1763
|
+
try {
|
|
1764
|
+
const res = await fetch(`${url}/api/v1/health`);
|
|
1765
|
+
const data = await res.json();
|
|
1766
|
+
console.log(`Cloud status: ${data.status} (v${data.version})`);
|
|
1767
|
+
}
|
|
1768
|
+
catch (e) {
|
|
1769
|
+
console.error(`Cloud unreachable: ${e.message}`);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
// --- codev (legacy experimental) ---
|
|
1774
|
+
if (isCodevEnabled()) {
|
|
1775
|
+
program
|
|
1776
|
+
.command('codev [topic]')
|
|
1777
|
+
.description('Experimental legacy ideation session using persona-based consultation')
|
|
1778
|
+
.option('--personas <tier>', 'Persona tier: tier1 (default), tier2, or list', 'tier1')
|
|
1779
|
+
.option('--checkpoint', 'Pause after clarification for human input')
|
|
1780
|
+
.option('--spawn', 'Spawn each consultant as an agent CLI instance')
|
|
1781
|
+
.option('--fresh', 'Clear cached responses before starting a new run')
|
|
1782
|
+
.option('--agents <list>', 'Comma-separated agent names for spawn (e.g. claude-code,codex,antigravity). Default: auto-detect')
|
|
1783
|
+
.option('--rounds <N>', 'Number of discussion rounds in spawn mode (default 3, min 2)', '3')
|
|
1784
|
+
.option('--target-duration <seconds>', 'Target duration per round indicated to agents (default 120)', '120')
|
|
1785
|
+
.option('--quorum <N>', 'Advance to next round after N agent responses (default: all)')
|
|
1786
|
+
.option('--model-map <map>', 'Per-persona model overrides, e.g. simplificateur:sonnet,stratege:opus')
|
|
1787
|
+
.option('--metrics', 'Display response timing metrics at end of session')
|
|
1788
|
+
.option('--json', 'Output as JSON')
|
|
1789
|
+
.action(async (topic, options) => {
|
|
1790
|
+
const globalOpts = program.opts();
|
|
1791
|
+
const { runCodev } = await import('./commands/codev.js');
|
|
1792
|
+
runCodev(topic, {
|
|
1793
|
+
...options,
|
|
1794
|
+
rounds: parseInt(options.rounds, 10),
|
|
1795
|
+
targetDuration: parseInt(options.targetDuration, 10),
|
|
1796
|
+
quorum: options.quorum != null ? parseInt(options.quorum, 10) : undefined,
|
|
1797
|
+
cwd: globalOpts.cwd,
|
|
1798
|
+
});
|
|
1799
|
+
});
|
|
1800
|
+
program
|
|
1801
|
+
.command('codev-metrics <thread>')
|
|
1802
|
+
.description('Show per-agent avg/p95 response metrics for an experimental CoDev thread')
|
|
1803
|
+
.option('--json', 'Output as JSON')
|
|
1804
|
+
.action(async (thread, options) => {
|
|
1805
|
+
const globalOpts = program.opts();
|
|
1806
|
+
const { runCodevMetrics } = await import('./commands/codev.js');
|
|
1807
|
+
runCodevMetrics(thread, { ...options, cwd: globalOpts.cwd });
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
// --- run (agent profiles) ---
|
|
1811
|
+
program
|
|
1812
|
+
.command('run [profile-name]')
|
|
1813
|
+
.description('Run an agent profile (list profiles if no name given)')
|
|
1814
|
+
.option('--dry', 'Print the resolved command without executing')
|
|
1815
|
+
.option('--agent <agent>', 'Override the invoke template with a known agent')
|
|
1816
|
+
.action((profileName, options) => {
|
|
1817
|
+
const globalOpts = program.opts();
|
|
1818
|
+
runRunProfile(profileName, { ...options, cwd: globalOpts.cwd });
|
|
1170
1819
|
});
|
|
1171
1820
|
program.parseAsync(process.argv).catch((err) => {
|
|
1172
1821
|
console.error(err);
|