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.
Files changed (195) hide show
  1. package/README.md +193 -170
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli.js +673 -24
  4. package/dist/commands/accept.js +3 -0
  5. package/dist/commands/add-step.js +11 -26
  6. package/dist/commands/agent-board.js +70 -3
  7. package/dist/commands/audit.js +19 -0
  8. package/dist/commands/check-policy.js +54 -0
  9. package/dist/commands/check-security-mcp.js +145 -0
  10. package/dist/commands/check-security.js +106 -0
  11. package/dist/commands/claim-resource.js +1 -0
  12. package/dist/commands/codev.js +672 -0
  13. package/dist/commands/compact.js +74 -0
  14. package/dist/commands/complete-step.js +16 -26
  15. package/dist/commands/constraint.js +8 -20
  16. package/dist/commands/decision.js +9 -20
  17. package/dist/commands/delete-plan.js +10 -12
  18. package/dist/commands/delete-step.js +16 -0
  19. package/dist/commands/dispatch.js +163 -0
  20. package/dist/commands/doctor.js +1122 -49
  21. package/dist/commands/enable-agent.js +1 -0
  22. package/dist/commands/export.js +280 -22
  23. package/dist/commands/handoff.js +33 -0
  24. package/dist/commands/harvest.js +189 -0
  25. package/dist/commands/hooks.js +82 -25
  26. package/dist/commands/inbox.js +169 -0
  27. package/dist/commands/init.js +38 -31
  28. package/dist/commands/install-hooks.js +71 -44
  29. package/dist/commands/link.js +89 -0
  30. package/dist/commands/list-claims.js +48 -3
  31. package/dist/commands/list-plans.js +129 -25
  32. package/dist/commands/loops-handlers.js +409 -0
  33. package/dist/commands/mcp-read-handlers.js +1628 -0
  34. package/dist/commands/mcp-schemas.generated.js +74 -0
  35. package/dist/commands/mcp.js +4221 -1501
  36. package/dist/commands/plan-resource.js +64 -0
  37. package/dist/commands/plan.js +12 -26
  38. package/dist/commands/prune.js +37 -2
  39. package/dist/commands/reflect.js +20 -7
  40. package/dist/commands/release-claim.js +11 -6
  41. package/dist/commands/release-notes.js +170 -0
  42. package/dist/commands/repair.js +210 -0
  43. package/dist/commands/run-profile.js +57 -0
  44. package/dist/commands/sequence.js +113 -0
  45. package/dist/commands/session-end.js +423 -14
  46. package/dist/commands/session-start.js +214 -41
  47. package/dist/commands/setup-security.js +103 -0
  48. package/dist/commands/setup.js +42 -4
  49. package/dist/commands/stale.js +109 -0
  50. package/dist/commands/switch.js +100 -2
  51. package/dist/commands/trap.js +14 -31
  52. package/dist/commands/update-handoff.js +63 -4
  53. package/dist/commands/update-plan.js +21 -28
  54. package/dist/commands/update-step.js +37 -0
  55. package/dist/commands/upgrade.js +313 -6
  56. package/dist/commands/usage.js +102 -0
  57. package/dist/commands/version.js +20 -0
  58. package/dist/commands/who.js +33 -5
  59. package/dist/commands/worktree.js +105 -0
  60. package/dist/core/actions.js +315 -0
  61. package/dist/core/agent-capability.js +610 -17
  62. package/dist/core/agent-context.js +7 -1
  63. package/dist/core/agent-files.js +1169 -85
  64. package/dist/core/agent-integrations.js +160 -5
  65. package/dist/core/agent-inventory.js +2 -0
  66. package/dist/core/agent-profiles.js +93 -0
  67. package/dist/core/agent-registry.js +162 -30
  68. package/dist/core/agentrun-reconciler.js +345 -0
  69. package/dist/core/agentruns.js +424 -0
  70. package/dist/core/ai-agent-detection.js +31 -10
  71. package/dist/core/archival.js +77 -0
  72. package/dist/core/assignment-sweeper.js +82 -0
  73. package/dist/core/assignments.js +367 -0
  74. package/dist/core/audit.js +30 -0
  75. package/dist/core/brainclaw-version.js +94 -2
  76. package/dist/core/candidates.js +93 -2
  77. package/dist/core/claims.js +419 -0
  78. package/dist/core/codev-metrics.js +77 -0
  79. package/dist/core/codev-personas.js +31 -0
  80. package/dist/core/codev-plan-gen.js +35 -0
  81. package/dist/core/codev-prompts.js +74 -0
  82. package/dist/core/codev-responses.js +62 -0
  83. package/dist/core/codev-rounds.js +218 -0
  84. package/dist/core/config.js +4 -0
  85. package/dist/core/context.js +381 -34
  86. package/dist/core/coordination.js +201 -6
  87. package/dist/core/cross-project.js +230 -16
  88. package/dist/core/default-profiles/doctor.yaml +11 -0
  89. package/dist/core/default-profiles/janitor.yaml +11 -0
  90. package/dist/core/default-profiles/onboarder.yaml +11 -0
  91. package/dist/core/default-profiles/reviewer.yaml +13 -0
  92. package/dist/core/dispatcher.js +1189 -0
  93. package/dist/core/duplicates.js +2 -2
  94. package/dist/core/entity-operations.js +450 -0
  95. package/dist/core/entity-registry.js +344 -0
  96. package/dist/core/events.js +106 -2
  97. package/dist/core/execution-adapters.js +154 -0
  98. package/dist/core/execution-context.js +63 -0
  99. package/dist/core/execution-profile.js +270 -0
  100. package/dist/core/execution.js +255 -0
  101. package/dist/core/facade-schema.js +81 -0
  102. package/dist/core/federation-cloud.js +99 -0
  103. package/dist/core/federation-message.js +52 -0
  104. package/dist/core/federation-transport.js +65 -0
  105. package/dist/core/gc-semantic.js +482 -0
  106. package/dist/core/governance.js +247 -0
  107. package/dist/core/guards.js +19 -0
  108. package/dist/core/ideation.js +72 -0
  109. package/dist/core/identity.js +110 -25
  110. package/dist/core/ids.js +6 -0
  111. package/dist/core/input-validation.js +2 -2
  112. package/dist/core/instruction-templates.js +344 -136
  113. package/dist/core/io.js +90 -11
  114. package/dist/core/lock.js +6 -2
  115. package/dist/core/loops/brief-assembly.js +213 -0
  116. package/dist/core/loops/facade-schema.js +148 -0
  117. package/dist/core/loops/index.js +7 -0
  118. package/dist/core/loops/iteration-engine.js +139 -0
  119. package/dist/core/loops/lock.js +385 -0
  120. package/dist/core/loops/store.js +201 -0
  121. package/dist/core/loops/types.js +403 -0
  122. package/dist/core/loops/verbs.js +534 -0
  123. package/dist/core/markdown.js +15 -3
  124. package/dist/core/memory-compactor.js +432 -0
  125. package/dist/core/memory-git.js +152 -8
  126. package/dist/core/messaging.js +278 -0
  127. package/dist/core/migration.js +32 -1
  128. package/dist/core/mutation-pipeline.js +4 -2
  129. package/dist/core/operations/memory-mutation.js +129 -0
  130. package/dist/core/operations/memory-write.js +78 -0
  131. package/dist/core/operations/plan.js +190 -0
  132. package/dist/core/policy.js +169 -0
  133. package/dist/core/reputation.js +9 -3
  134. package/dist/core/schema.js +491 -6
  135. package/dist/core/search.js +21 -2
  136. package/dist/core/security-cache.js +71 -0
  137. package/dist/core/security-guard.js +152 -0
  138. package/dist/core/security-scoring.js +86 -0
  139. package/dist/core/sequence.js +130 -0
  140. package/dist/core/socket-client.js +113 -0
  141. package/dist/core/staleness.js +246 -0
  142. package/dist/core/state.js +98 -22
  143. package/dist/core/store-resolution.js +43 -11
  144. package/dist/core/toml-writer.js +76 -0
  145. package/dist/core/upgrades/backup.js +232 -0
  146. package/dist/core/upgrades/health-check.js +169 -0
  147. package/dist/core/upgrades/patches/candidate-archive.js +145 -0
  148. package/dist/core/upgrades/patches/handoff-review-strip.js +128 -0
  149. package/dist/core/upgrades/patches/provenance-rollout.js +136 -0
  150. package/dist/core/upgrades/schema-version.js +97 -0
  151. package/dist/core/worktree.js +606 -0
  152. package/dist/facts.js +114 -0
  153. package/dist/facts.json +111 -0
  154. package/docs/architecture/project-refs.md +5 -1
  155. package/docs/cli.md +690 -43
  156. package/docs/concepts/ideation-loop.md +317 -0
  157. package/docs/concepts/loop-engine.md +456 -0
  158. package/docs/concepts/mcp-governance.md +268 -0
  159. package/docs/concepts/memory-staleness.md +122 -0
  160. package/docs/concepts/multi-agent-workflows.md +166 -0
  161. package/docs/concepts/plans-and-claims.md +31 -6
  162. package/docs/concepts/project-md-convention.md +35 -0
  163. package/docs/concepts/troubleshooting.md +220 -0
  164. package/docs/concepts/upgrade-cli.md +202 -0
  165. package/docs/concepts/upgrade-dogfood-procedure.md +114 -0
  166. package/docs/context-format-changelog.md +2 -2
  167. package/docs/context-format.md +2 -2
  168. package/docs/index.md +68 -0
  169. package/docs/integrations/agents.md +15 -16
  170. package/docs/integrations/cline.md +88 -0
  171. package/docs/integrations/codex.md +75 -23
  172. package/docs/integrations/continue.md +60 -0
  173. package/docs/integrations/copilot.md +67 -9
  174. package/docs/integrations/kilocode.md +72 -0
  175. package/docs/integrations/mcp.md +304 -21
  176. package/docs/integrations/mistral-vibe.md +122 -0
  177. package/docs/integrations/opencode.md +84 -0
  178. package/docs/integrations/overview.md +23 -8
  179. package/docs/integrations/roo.md +74 -0
  180. package/docs/integrations/windsurf.md +83 -0
  181. package/docs/mcp-schema-changelog.md +191 -1
  182. package/docs/playbooks/integration/index.md +121 -0
  183. package/docs/playbooks/productivity/index.md +102 -0
  184. package/docs/playbooks/team/index.md +122 -0
  185. package/docs/product/agent-first-model.md +184 -0
  186. package/docs/product/entity-model-audit.md +462 -0
  187. package/docs/quickstart-existing-project.md +135 -0
  188. package/docs/quickstart.md +124 -37
  189. package/docs/release-maintenance.md +79 -0
  190. package/docs/review.md +2 -0
  191. package/docs/server-operations.md +118 -0
  192. package/package.json +20 -12
  193. package/dist/commands/claude-desktop-extension.js +0 -18
  194. package/dist/commands/diff.js +0 -99
  195. package/dist/core/claude-desktop-extension.js +0 -224
@@ -0,0 +1,210 @@
1
+ /**
2
+ * `brainclaw repair` — safe, non-destructive repair flow built on doctor's
3
+ * structured repair candidates (pln#397 stp_b31fbe23 + stp_7ad66f68).
4
+ *
5
+ * Design:
6
+ * 1. Run the doctor JSON output and capture `repair_candidates[]`.
7
+ * 2. Split into `safe` and `unsafe`.
8
+ * 3. Execute safe candidates by default; unsafe stay deferred unless the
9
+ * caller passes `includeUnsafe`.
10
+ *
11
+ * Preservation guarantees (stp_7ad66f68):
12
+ * - NO action in this module deletes files. Lossy-looking actions
13
+ * (quarantine, archive) always rename into a clearly-labelled parking
14
+ * directory so operators can recover. Enforced by a source-level
15
+ * invariant test in tests/unit/repair-preservation.test.ts.
16
+ * - Before executing any unsafe candidate, a highlighted warning prints
17
+ * exactly what will be moved and where it will land — operators get
18
+ * full visibility before data relocates.
19
+ * - Memory entities (plans, decisions, constraints, traps, claims,
20
+ * handoffs) are never touched by any current action. Only inbox
21
+ * hygiene and filesystem-shape candidates are wired.
22
+ *
23
+ * Exposed via CLI (`brainclaw repair`) and MCP (`bclaw_repair`). Always
24
+ * returns a structured summary so agents can inspect what changed.
25
+ */
26
+ import fs from 'node:fs';
27
+ import path from 'node:path';
28
+ import { memoryExists, memoryDir } from '../core/io.js';
29
+ import { runDoctor } from './doctor.js';
30
+ /**
31
+ * Execute a single repair candidate. Returns the outcome; never throws.
32
+ * Safe actions are pure creation / rename operations — see the switch cases.
33
+ */
34
+ function executeCandidate(candidate, cwd) {
35
+ try {
36
+ switch (candidate.action) {
37
+ case 'mkdir': {
38
+ const target = path.resolve(cwd, candidate.target);
39
+ if (!fs.existsSync(target)) {
40
+ fs.mkdirSync(target, { recursive: true });
41
+ }
42
+ return { action: candidate.action, target: candidate.target, status: 'applied' };
43
+ }
44
+ case 'move_inbox_message': {
45
+ // Orphaned messages stored under the wrong agent directory. Read the
46
+ // message, resolve the correct destination from message.to, and
47
+ // rename. Source file already exists; target dir is auto-created.
48
+ const sourceAbs = path.resolve(cwd, candidate.target);
49
+ if (!fs.existsSync(sourceAbs)) {
50
+ return { action: candidate.action, target: candidate.target, status: 'skipped', reason: 'source file no longer exists' };
51
+ }
52
+ const parsed = JSON.parse(fs.readFileSync(sourceAbs, 'utf-8'));
53
+ const recipient = parsed.document?.to ?? parsed.to;
54
+ if (!recipient) {
55
+ return { action: candidate.action, target: candidate.target, status: 'skipped', reason: 'message has no recipient (to) field' };
56
+ }
57
+ const normalizedAgent = recipient.toLowerCase().replace(/[^a-z0-9_-]/g, '_');
58
+ const inboxRoot = path.join(memoryDir(cwd), 'coordination', 'inbox', normalizedAgent);
59
+ if (!fs.existsSync(inboxRoot)) {
60
+ fs.mkdirSync(inboxRoot, { recursive: true });
61
+ }
62
+ const destAbs = path.join(inboxRoot, path.basename(sourceAbs));
63
+ if (fs.existsSync(destAbs) && path.resolve(destAbs) !== path.resolve(sourceAbs)) {
64
+ return { action: candidate.action, target: candidate.target, status: 'skipped', reason: `destination already exists: ${destAbs}` };
65
+ }
66
+ fs.renameSync(sourceAbs, destAbs);
67
+ return { action: candidate.action, target: candidate.target, status: 'applied' };
68
+ }
69
+ case 'quarantine_inbox_message': {
70
+ // Unsafe: move malformed message to a quarantine directory so a human
71
+ // can inspect it. Never deletes. Requires includeUnsafe.
72
+ const sourceAbs = path.resolve(cwd, candidate.target);
73
+ if (!fs.existsSync(sourceAbs)) {
74
+ return { action: candidate.action, target: candidate.target, status: 'skipped', reason: 'source file no longer exists' };
75
+ }
76
+ const quarantineDir = path.join(memoryDir(cwd), 'coordination', 'inbox', '.quarantine');
77
+ if (!fs.existsSync(quarantineDir)) {
78
+ fs.mkdirSync(quarantineDir, { recursive: true });
79
+ }
80
+ const destAbs = path.join(quarantineDir, `${Date.now()}-${path.basename(sourceAbs)}`);
81
+ fs.renameSync(sourceAbs, destAbs);
82
+ return { action: candidate.action, target: candidate.target, status: 'applied' };
83
+ }
84
+ default:
85
+ return {
86
+ action: candidate.action,
87
+ target: candidate.target,
88
+ status: 'skipped',
89
+ reason: `unknown action: ${candidate.action}`,
90
+ };
91
+ }
92
+ }
93
+ catch (err) {
94
+ return {
95
+ action: candidate.action,
96
+ target: candidate.target,
97
+ status: 'failed',
98
+ reason: err instanceof Error ? err.message : String(err),
99
+ };
100
+ }
101
+ }
102
+ /**
103
+ * Collect repair candidates by running doctor with JSON output captured.
104
+ * We re-run doctor instead of accepting them via an argument so the caller
105
+ * always sees the current state of the store.
106
+ */
107
+ function collectCandidates(cwd) {
108
+ const originalLog = console.log;
109
+ let captured = '';
110
+ console.log = (...args) => { captured += args.map(String).join(' '); };
111
+ try {
112
+ runDoctor({ cwd, json: true });
113
+ }
114
+ finally {
115
+ console.log = originalLog;
116
+ }
117
+ try {
118
+ const parsed = JSON.parse(captured);
119
+ return Array.isArray(parsed.repair_candidates) ? parsed.repair_candidates : [];
120
+ }
121
+ catch {
122
+ return [];
123
+ }
124
+ }
125
+ export function runRepair(options = {}) {
126
+ const cwd = options.cwd ?? process.cwd();
127
+ if (!memoryExists(cwd)) {
128
+ console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
129
+ process.exit(1);
130
+ }
131
+ const candidates = collectCandidates(cwd);
132
+ const safe = candidates.filter((c) => c.safe);
133
+ const unsafe = candidates.filter((c) => !c.safe);
134
+ const applied = [];
135
+ const skipped = [];
136
+ const failed = [];
137
+ const toRun = [...safe, ...(options.includeUnsafe ? unsafe : [])];
138
+ const deferred = options.includeUnsafe ? [] : unsafe;
139
+ // pln#397 stp_7ad66f68: explicit warning banner whenever we're about to
140
+ // touch existing files. Operators see exactly what moves and where
141
+ // before any rename executes. No JSON noise.
142
+ if (!options.json && !options.dryRun && options.includeUnsafe && unsafe.length > 0) {
143
+ console.warn('');
144
+ console.warn('⚠ Preservation notice — the following unsafe actions will RELOCATE files (never delete):');
145
+ for (const candidate of unsafe) {
146
+ console.warn(` • ${candidate.action} → ${candidate.target}`);
147
+ console.warn(` ${candidate.description}`);
148
+ }
149
+ console.warn('Files are moved to labelled parking directories (e.g. inbox/.quarantine/) so you can recover them manually.');
150
+ console.warn('');
151
+ }
152
+ for (const candidate of toRun) {
153
+ if (options.dryRun) {
154
+ skipped.push({
155
+ action: candidate.action,
156
+ target: candidate.target,
157
+ status: 'skipped',
158
+ reason: 'dry-run',
159
+ });
160
+ continue;
161
+ }
162
+ const outcome = executeCandidate(candidate, cwd);
163
+ if (outcome.status === 'applied')
164
+ applied.push(outcome);
165
+ else if (outcome.status === 'failed')
166
+ failed.push(outcome);
167
+ else
168
+ skipped.push(outcome);
169
+ }
170
+ for (const candidate of deferred) {
171
+ skipped.push({
172
+ action: candidate.action,
173
+ target: candidate.target,
174
+ status: 'skipped',
175
+ reason: 'unsafe — pass --include-unsafe to execute (preserves data, but requires confirmation)',
176
+ });
177
+ }
178
+ const result = {
179
+ ok: failed.length === 0,
180
+ dry_run: Boolean(options.dryRun),
181
+ candidates_total: candidates.length,
182
+ candidates_safe: safe.length,
183
+ candidates_unsafe: unsafe.length,
184
+ applied,
185
+ skipped,
186
+ failed,
187
+ };
188
+ if (options.json) {
189
+ console.log(JSON.stringify(result, null, 2));
190
+ return result;
191
+ }
192
+ if (candidates.length === 0) {
193
+ console.log('Nothing to repair — doctor surfaced no candidates.');
194
+ return result;
195
+ }
196
+ if (options.dryRun) {
197
+ console.log(`Dry-run: ${candidates.length} candidate(s) (${safe.length} safe, ${unsafe.length} unsafe)`);
198
+ }
199
+ else {
200
+ console.log(`Repair complete: ${applied.length} applied, ${skipped.length} skipped, ${failed.length} failed`);
201
+ }
202
+ for (const o of applied)
203
+ console.log(` ✔ ${o.action} → ${o.target}`);
204
+ for (const o of skipped)
205
+ console.log(` ○ ${o.action} → ${o.target}${o.reason ? ` (${o.reason})` : ''}`);
206
+ for (const o of failed)
207
+ console.log(` ✗ ${o.action} → ${o.target}${o.reason ? ` (${o.reason})` : ''}`);
208
+ return result;
209
+ }
210
+ //# sourceMappingURL=repair.js.map
@@ -0,0 +1,57 @@
1
+ /**
2
+ * CLI command: brainclaw run <profile-name>
3
+ *
4
+ * Loads an agent profile, resolves the invoke template, and spawns the agent.
5
+ *
6
+ * @module
7
+ */
8
+ import { execSync } from 'node:child_process';
9
+ import { loadProfile, listProfiles } from '../core/agent-profiles.js';
10
+ import { getDefaultInvokeTemplate } from '../core/agent-capability.js';
11
+ import { requireInitialized } from '../core/guards.js';
12
+ export function runRunProfile(profileName, options = {}) {
13
+ const cwd = options.cwd ?? process.cwd();
14
+ requireInitialized(cwd);
15
+ // List mode: no profile name
16
+ if (!profileName) {
17
+ const profiles = listProfiles(cwd);
18
+ if (profiles.length === 0) {
19
+ console.log('No agent profiles found. Add .yaml files to .brainclaw/agents/profiles/');
20
+ return;
21
+ }
22
+ console.log('Available profiles:');
23
+ for (const p of profiles) {
24
+ console.log(` ${p.name} — ${p.description} [${p.trigger}]`);
25
+ }
26
+ return;
27
+ }
28
+ const profile = loadProfile(profileName, cwd);
29
+ // Resolve invoke template: --agent override replaces the profile's invoke
30
+ let invoke = profile.invoke;
31
+ if (options.agent) {
32
+ const template = getDefaultInvokeTemplate(options.agent);
33
+ if (template) {
34
+ invoke = template.command;
35
+ }
36
+ else {
37
+ console.error(`Unknown agent: ${options.agent}. Using profile invoke template.`);
38
+ }
39
+ }
40
+ // Replace {prompt} placeholder with the profile prompt
41
+ const command = invoke.replace(/\{prompt\}/g, profile.prompt.replace(/"/g, '\\"'));
42
+ if (options.dry) {
43
+ console.log(`[dry-run] Profile: ${profile.name}`);
44
+ console.log(`[dry-run] Command: ${command}`);
45
+ return;
46
+ }
47
+ console.log(`Running profile: ${profile.name}`);
48
+ console.log(`Command: ${command}`);
49
+ try {
50
+ execSync(command, { cwd, stdio: 'inherit' });
51
+ }
52
+ catch (err) {
53
+ const code = err.status ?? 1;
54
+ process.exit(code);
55
+ }
56
+ }
57
+ //# sourceMappingURL=run-profile.js.map
@@ -0,0 +1,113 @@
1
+ import { resolveCurrentAgentName } from '../core/agent-registry.js';
2
+ import { requireInitialized } from '../core/guards.js';
3
+ import { validateCliInput } from '../core/input-validation.js';
4
+ import { createSequence, listSequences, loadSequence, updateSequence } from '../core/sequence.js';
5
+ const KNOWN_SUBCOMMANDS = new Set(['create', 'list', 'ls', 'show', 'update']);
6
+ function parseItems(raw) {
7
+ if (!raw)
8
+ return undefined;
9
+ let parsed;
10
+ try {
11
+ parsed = JSON.parse(raw);
12
+ }
13
+ catch (error) {
14
+ throw new Error(`Invalid --items JSON: ${error instanceof Error ? error.message : String(error)}`);
15
+ }
16
+ if (!Array.isArray(parsed)) {
17
+ throw new Error('Invalid --items JSON: expected an array');
18
+ }
19
+ return parsed;
20
+ }
21
+ export function runSequenceResource(subcommand, args, options = {}) {
22
+ const cwd = options.cwd ?? process.cwd();
23
+ requireInitialized(cwd);
24
+ const normalized = subcommand.trim().toLowerCase();
25
+ if (!KNOWN_SUBCOMMANDS.has(normalized)) {
26
+ console.error(`Error: unknown sequence subcommand "${subcommand}".`);
27
+ console.error(' Available: create, list, show, update');
28
+ process.exit(1);
29
+ }
30
+ if (normalized === 'create') {
31
+ const name = args.join(' ').trim();
32
+ if (!name) {
33
+ console.error('Error: sequence create requires <name>');
34
+ process.exit(1);
35
+ }
36
+ validateCliInput(name, options.tag);
37
+ const items = parseItems(options.items);
38
+ const result = createSequence({
39
+ name,
40
+ description: options.description,
41
+ status: options.status,
42
+ owner: options.owner,
43
+ items,
44
+ author: options.author ?? resolveCurrentAgentName(cwd),
45
+ tags: options.tag,
46
+ }, cwd);
47
+ console.log(`✔ Sequence added: [${result.id}] ${name}`);
48
+ return;
49
+ }
50
+ if (normalized === 'list' || normalized === 'ls') {
51
+ const sequences = listSequences(cwd).filter((sequence) => !options.status || sequence.status === options.status);
52
+ if (options.json) {
53
+ console.log(JSON.stringify(sequences, null, 2));
54
+ return;
55
+ }
56
+ if (sequences.length === 0) {
57
+ console.log('No sequences found.');
58
+ return;
59
+ }
60
+ console.log(`${sequences.length} sequence(s):`);
61
+ for (const sequence of sequences) {
62
+ console.log(`[${sequence.id}] ${sequence.name} (${sequence.status}, items=${sequence.items.length})`);
63
+ }
64
+ return;
65
+ }
66
+ if (normalized === 'show') {
67
+ const id = args[0];
68
+ if (!id) {
69
+ console.error('Error: sequence show requires <id>.');
70
+ process.exit(1);
71
+ }
72
+ const sequence = loadSequence(id, cwd);
73
+ if (options.json) {
74
+ console.log(JSON.stringify(sequence, null, 2));
75
+ return;
76
+ }
77
+ console.log(`Sequence: ${sequence.id}`);
78
+ console.log(` Name: ${sequence.name}`);
79
+ console.log(` Status: ${sequence.status}`);
80
+ if (sequence.owner)
81
+ console.log(` Owner: ${sequence.owner}`);
82
+ if (sequence.description)
83
+ console.log(` Description: ${sequence.description}`);
84
+ console.log(` Updated: ${sequence.updated_at}`);
85
+ if (sequence.items.length > 0) {
86
+ console.log(' Items:');
87
+ for (const item of sequence.items) {
88
+ const lane = item.lane ? ` lane=${item.lane}` : '';
89
+ const hardAfter = item.hard_after.length ? ` hard_after=${item.hard_after.join(',')}` : '';
90
+ const softAfter = item.soft_after.length ? ` soft_after=${item.soft_after.join(',')}` : '';
91
+ console.log(` #${item.rank} ${item.planId}${lane}${hardAfter}${softAfter}`);
92
+ }
93
+ }
94
+ return;
95
+ }
96
+ const id = args[0];
97
+ if (!id) {
98
+ console.error('Error: sequence update requires <id>.');
99
+ process.exit(1);
100
+ }
101
+ const items = options.items ? parseItems(options.items) : undefined;
102
+ const sequence = updateSequence({
103
+ id,
104
+ name: options.name,
105
+ description: options.description,
106
+ status: options.status,
107
+ owner: options.owner,
108
+ items,
109
+ tags: options.tag,
110
+ }, cwd);
111
+ console.log(`✔ Sequence updated: [${sequence.id}] ${sequence.name}`);
112
+ }
113
+ //# sourceMappingURL=sequence.js.map