@zhuk/spego 0.7.0 → 0.9.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 (48) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +57 -2
  3. package/dist/cli/body-input.d.ts +12 -0
  4. package/dist/cli/body-input.js +27 -0
  5. package/dist/cli/body-input.js.map +1 -0
  6. package/dist/cli/commands/artifact.d.ts +8 -0
  7. package/dist/cli/commands/artifact.js +171 -0
  8. package/dist/cli/commands/artifact.js.map +1 -0
  9. package/dist/cli/commands/delivery.d.ts +7 -0
  10. package/dist/cli/commands/delivery.js +99 -0
  11. package/dist/cli/commands/delivery.js.map +1 -0
  12. package/dist/cli/commands/index-rebuild.d.ts +5 -0
  13. package/dist/cli/commands/index-rebuild.js +31 -0
  14. package/dist/cli/commands/index-rebuild.js.map +1 -0
  15. package/dist/cli/commands/meta.d.ts +6 -0
  16. package/dist/cli/commands/meta.js +60 -0
  17. package/dist/cli/commands/meta.js.map +1 -0
  18. package/dist/cli/commands/skills.d.ts +5 -0
  19. package/dist/cli/commands/skills.js +47 -0
  20. package/dist/cli/commands/skills.js.map +1 -0
  21. package/dist/cli/commands/view.d.ts +8 -0
  22. package/dist/cli/commands/view.js +59 -0
  23. package/dist/cli/commands/view.js.map +1 -0
  24. package/dist/cli/commands/workspace.d.ts +5 -0
  25. package/dist/cli/commands/workspace.js +61 -0
  26. package/dist/cli/commands/workspace.js.map +1 -0
  27. package/dist/cli/errors.d.ts +20 -0
  28. package/dist/cli/errors.js +55 -0
  29. package/dist/cli/errors.js.map +1 -0
  30. package/dist/cli/output.d.ts +12 -0
  31. package/dist/cli/output.js +28 -0
  32. package/dist/cli/output.js.map +1 -0
  33. package/dist/cli/render.d.ts +7 -0
  34. package/dist/cli/render.js +22 -0
  35. package/dist/cli/render.js.map +1 -1
  36. package/dist/cli/runtime.d.ts +26 -0
  37. package/dist/cli/runtime.js +48 -0
  38. package/dist/cli/runtime.js.map +1 -0
  39. package/dist/cli.d.ts +8 -0
  40. package/dist/cli.js +64 -582
  41. package/dist/cli.js.map +1 -1
  42. package/dist/generator/index.d.ts +4 -1
  43. package/dist/generator/index.js +5 -2
  44. package/dist/generator/index.js.map +1 -1
  45. package/dist/workflows/registry.js +107 -1
  46. package/dist/workflows/registry.js.map +1 -1
  47. package/dist/workspace/config.d.ts +2 -2
  48. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.0] - 2026-05-29
4
+
5
+ ### Changed
6
+ - Refactored the CLI into shared runtime helpers and per-command registrars, reducing duplicated JSON/output/error/engine lifecycle code while preserving public command names and flags.
7
+ - `spego update --json` now returns the artifact `frontmatter`, `body`, and `path` in addition to the existing `id` and `revision` fields, matching `spego read --json` for agent parsing.
8
+ - Human output is more consistent across commands: `create`, `delete`, and `index rebuild` now use the same section-header style as the rest of the CLI.
9
+ - JSON validation errors now always include `details: {}` and exit with code 2, matching other structured CLI failures.
10
+
11
+ ### Added
12
+ - Shared body input handling for `spego create` and `spego update`, including stdin support through `--body-file -`.
13
+ - End-to-end CLI coverage for `epics`, `tasks`, read selectors, revision reads, optimistic concurrency, view filters, body-file/stdin input, uninitialized status JSON, registry parity, and validation error envelopes.
14
+ - OpenSpec change `2026-05-29-clean-cli-command-surface` documenting and validating the CLI cleanup.
15
+
16
+ ### Fixed
17
+ - `npm run lint` now includes `test/cli-help-exit.test.ts` and the new CLI test files in ESLint project-service configuration.
18
+
19
+ ## [0.8.0] - 2026-05-22
20
+
21
+ ### Added
22
+ - Combined OpenSpec + spego workflow skills: `change-brainstorm`, `change-review`, `change-verify-report`, and `change-retro`.
23
+ - README guidance for before/during/after OpenSpec change lanes with spego persistence checkpoints.
24
+
3
25
  ## [0.7.0] - 2026-05-14
4
26
 
5
27
  ### Changed
package/README.md CHANGED
@@ -35,13 +35,17 @@ All commands accept `--cwd <dir>` to set the project root.
35
35
 
36
36
  Every spego command speaks two output modes:
37
37
 
38
- - **Human (default)** — pretty, scannable output for terminals. Section headers use a single emoji prefix (`📦 📄 🛠️ 🧭 📚 ✅`), summaries render as bordered boxes (`╭─ … ─╮`), lists render as aligned tables, and `view` separates artifacts with `────` dividers. Errors print as `⚠️ [CODE] message` to stderr.
39
- - **JSON (opt-in)** — pass the global `--json` flag to get deterministic, decoration-free JSON on stdout. Errors come back as `{ "error": { "code", "message", "details" } }` on stderr.
38
+ - **Human (default)** — pretty, scannable output for terminals. Section headers use a single emoji prefix (`📦 📄 🛠️ 🧭 📚 ✅ ✨ 🗑`), summaries render as bordered boxes (`╭─ … ─╮`), lists render as aligned tables, and `view` separates artifacts with `────` dividers. Errors print as `⚠️ [CODE] message` to stderr.
39
+ - **JSON (opt-in)** — pass the global `--json` flag to get deterministic, decoration-free JSON on stdout. Errors come back as `{ "error": { "code", "message", "details" } }` on stderr; `details` is always an object.
40
40
 
41
41
  Agents calling spego MUST pass `--json` so they get parseable output. Humans normally do not.
42
42
 
43
43
  The legacy `spego view --format markdown|json` flag is **deprecated** and will be removed in the next minor release. Use the global `--json` flag instead. The old flag still works during the deprecation window and prints a single `deprecated:` warning line to stderr.
44
44
 
45
+ `spego read --json` and `spego update --json` both return artifact records with `frontmatter`, `body`, and `path`; `update` also keeps the compatibility fields `id` and `revision`.
46
+
47
+ `spego create` and `spego update` accept body content through `--body`, `--body-file <path>`, or stdin via `--body-file -`.
48
+
45
49
  ## Architecture
46
50
 
47
51
  - Markdown files are the source of truth (`.spego/artifacts/<type>/<slug>.md`)
@@ -72,6 +76,21 @@ deliveryAdapter:
72
76
  options: {}
73
77
  ```
74
78
 
79
+ ## OpenSpec Delivery View
80
+
81
+ The default delivery adapter is OpenSpec. `spego epics` exposes active OpenSpec changes as delivery epics, and `spego tasks --change <name>` exposes checklist items from the change's `tasks.md`.
82
+
83
+ The adapter is read-only. It observes OpenSpec state but does not create, continue, apply, verify, sync, or archive OpenSpec changes.
84
+
85
+ | Source | spego view |
86
+ |--------|------------|
87
+ | `openspec/changes/<name>/proposal.md` | Epic title |
88
+ | `openspec/changes/<name>/tasks.md` | Task summaries |
89
+ | `openspec status --change <name> --json` | Preferred status source |
90
+ | Filesystem parsing | Fallback when the OpenSpec CLI is unavailable |
91
+
92
+ Archived changes under `openspec/changes/archive/` are excluded. A change with no `tasks.md` is reported as `planning-incomplete`.
93
+
75
94
  ## Generated Files
76
95
 
77
96
  For Claude agent targets, `spego init` generates:
@@ -136,6 +155,42 @@ Use when you have a focused problem and want maximum idea throughput without per
136
155
  | One voice, fast iteration | `brainstorm-deep` |
137
156
  | Multiple viewpoints, stress-test ideas | `brainstorm-party` |
138
157
 
158
+ ### Combined OpenSpec + spego workflows
159
+
160
+ OpenSpec prompts and spego workflow skills are separate surfaces:
161
+
162
+ - OPSX/OpenSpec prompts live under `.claude/commands/opsx/` and `.claude/skills/openspec-*/`.
163
+ - spego-generated commands and workflow skills live under `.claude/commands/spego/` and `.claude/skills/spego-*/`.
164
+
165
+ OpenSpec owns change execution and lifecycle state: proposal, design, specs, tasks, apply, verify, sync, and archive. spego owns durable product-thinking artifacts: `brainstorm`, `qa`, `risk`, and `retro`. The OpenSpec delivery adapter exposed through `spego epics` and `spego tasks` is read-only.
166
+
167
+ Use combined workflows when an OpenSpec change needs durable thinking around it:
168
+
169
+ | Lane | OpenSpec action | spego action |
170
+ |------|-----------------|--------------|
171
+ | Before implementation | Create or continue a change with OPSX/OpenSpec, then read `proposal.md`, `design.md`, specs, and `tasks.md` | `spego-change-brainstorm` creates a `brainstorm` artifact |
172
+ | During implementation | Keep task state and artifact mutations in OPSX/OpenSpec | `spego-change-review` creates `qa` or `risk` findings |
173
+ | Before archive | Run OPSX/OpenSpec verification | `spego-change-verify-report` creates a `qa` verification report |
174
+ | After completion | Archive or complete the OpenSpec change | `spego-change-retro` creates a `retro` artifact |
175
+
176
+ Example read-only context commands:
177
+
178
+ ```sh
179
+ spego epics --json
180
+ spego tasks --change <change-name> --json
181
+ ```
182
+
183
+ Example spego persistence checkpoints:
184
+
185
+ ```sh
186
+ spego --json create --type brainstorm --title "<change-name> brainstorm" --body "<brainstorm output>"
187
+ spego --json create --type qa --title "<change-name> review" --body "<quality findings>"
188
+ spego --json create --type risk --title "<change-name> risks" --body "<risk findings>"
189
+ spego --json create --type retro --title "<change-name> retro" --body "<retrospective>"
190
+ ```
191
+
192
+ If a combined workflow discovers that OpenSpec artifacts need to change, use the matching OPSX/OpenSpec command. Do not mutate OpenSpec lifecycle state through spego.
193
+
139
194
  ### elicit
140
195
 
141
196
  Iterative refinement of an existing artifact using named methods (clarify, sharpen, generalize, specialize, stress-test, contextualize, simplify, formalize). A single Refiner persona proposes changes, confirms with the user, and applies via `spego update --expected-revision`. Maximum 5 cycles per session. Outputs a `qa` summary and in-place updates of the source artifact.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Unified body-input resolution for `spego create` and `spego update`.
3
+ *
4
+ * Accepts either an inline `--body` string, a `--body-file <path>` reference,
5
+ * or stdin when `--body-file -`. Returns `undefined` when no body source was
6
+ * supplied so callers can leave the artifact body unchanged.
7
+ */
8
+ export interface BodyInputOptions {
9
+ body?: string;
10
+ bodyFile?: string;
11
+ }
12
+ export declare function resolveBody(opts: BodyInputOptions): Promise<string | undefined>;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Unified body-input resolution for `spego create` and `spego update`.
3
+ *
4
+ * Accepts either an inline `--body` string, a `--body-file <path>` reference,
5
+ * or stdin when `--body-file -`. Returns `undefined` when no body source was
6
+ * supplied so callers can leave the artifact body unchanged.
7
+ */
8
+ import fs from 'node:fs/promises';
9
+ async function readStdin() {
10
+ return new Promise((resolve, reject) => {
11
+ let buf = '';
12
+ process.stdin.setEncoding('utf8');
13
+ process.stdin.on('data', (chunk) => {
14
+ buf += chunk;
15
+ });
16
+ process.stdin.on('end', () => resolve(buf));
17
+ process.stdin.on('error', reject);
18
+ });
19
+ }
20
+ export async function resolveBody(opts) {
21
+ if (opts.bodyFile === '-')
22
+ return readStdin();
23
+ if (opts.bodyFile)
24
+ return fs.readFile(opts.bodyFile, 'utf8');
25
+ return opts.body;
26
+ }
27
+ //# sourceMappingURL=body-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-input.js","sourceRoot":"","sources":["../../src/cli/body-input.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAOlC,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,GAAG,IAAI,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAsB;IACtD,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG;QAAE,OAAO,SAAS,EAAE,CAAC;IAC9C,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Artifact CRUD commands: `create`, `read`, `update`, `delete`, `list`.
3
+ *
4
+ * All five share the artifact-engine runtime helper so neither engine
5
+ * lifecycle nor `--json` resolution is duplicated per command.
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerArtifact(program: Command): void;
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Artifact CRUD commands: `create`, `read`, `update`, `delete`, `list`.
3
+ *
4
+ * All five share the artifact-engine runtime helper so neither engine
5
+ * lifecycle nor `--json` resolution is duplicated per command.
6
+ */
7
+ import path from 'node:path';
8
+ import { renderArtifactFile } from '../../artifacts/storage.js';
9
+ import { SpegoError } from '../../errors.js';
10
+ import { renderDivider, renderHeader, renderTable } from '../render.js';
11
+ import { runEngineCommand } from '../runtime.js';
12
+ import { resolveBody } from '../body-input.js';
13
+ function renderArtifactHeader(fm) {
14
+ return `📄 ${fm.type}/${fm.slug} rev ${fm.revision} (${fm.id})`;
15
+ }
16
+ function renderRecordHuman(record) {
17
+ return `${renderArtifactHeader(record.frontmatter)}\n${renderDivider()}\n${record.body}`;
18
+ }
19
+ export function registerArtifact(program) {
20
+ program
21
+ .command('create')
22
+ .description('Create an artifact')
23
+ .requiredOption('--type <type>', 'artifact type, e.g. prd|api|architecture')
24
+ .requiredOption('--title <title>', 'artifact title')
25
+ .option('--slug <slug>', 'optional explicit slug')
26
+ .option('--body <text>', 'inline markdown body')
27
+ .option('--body-file <path>', 'read markdown body from a file (use - for stdin)')
28
+ .option('--meta <json>', 'JSON object of metadata', '{}')
29
+ .option('--cwd <dir>', 'project root')
30
+ .action(async (opts) => {
31
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
32
+ const body = (await resolveBody(opts)) ?? '';
33
+ const meta = JSON.parse(opts.meta);
34
+ const record = await engine.create({
35
+ type: opts.type,
36
+ title: opts.title,
37
+ slug: opts.slug,
38
+ body,
39
+ meta,
40
+ });
41
+ const payload = {
42
+ id: record.frontmatter.id,
43
+ type: record.frontmatter.type,
44
+ slug: record.frontmatter.slug,
45
+ revision: record.frontmatter.revision,
46
+ path: record.path,
47
+ markdown: renderArtifactFile(record.frontmatter, record.body),
48
+ };
49
+ const human = () => [
50
+ renderHeader('✨', `Created ${record.frontmatter.type}/${record.frontmatter.slug} rev ${record.frontmatter.revision}`),
51
+ ` path: ${record.path}`,
52
+ ].join('\n');
53
+ return { payload, human };
54
+ });
55
+ });
56
+ program
57
+ .command('read')
58
+ .description('Read an artifact by id or type+slug')
59
+ .option('--id <id>', 'artifact id')
60
+ .option('--type <type>', 'artifact type (with --slug)')
61
+ .option('--slug <slug>', 'artifact slug (with --type)')
62
+ .option('--path <path>', 'read artifact by absolute file path')
63
+ .option('--revision <n>', 'specific revision number')
64
+ .option('--cwd <dir>', 'project root')
65
+ .action(async (opts) => {
66
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
67
+ let record;
68
+ if (opts.id) {
69
+ record =
70
+ opts.revision !== undefined
71
+ ? await engine.readRevision(opts.id, Number(opts.revision))
72
+ : await engine.readById(opts.id);
73
+ }
74
+ else if (opts.type && opts.slug) {
75
+ record = await engine.readByTypeSlug(opts.type, opts.slug);
76
+ }
77
+ else if (opts.path) {
78
+ record = await engine.readByPath(path.resolve(opts.path));
79
+ }
80
+ else {
81
+ throw new SpegoError('VALIDATION_FAILED', 'Provide --id, --type and --slug, or --path');
82
+ }
83
+ return {
84
+ payload: { frontmatter: record.frontmatter, body: record.body, path: record.path },
85
+ human: () => renderRecordHuman(record),
86
+ };
87
+ });
88
+ });
89
+ program
90
+ .command('update')
91
+ .description('Update an artifact (requires id)')
92
+ .requiredOption('--id <id>', 'artifact id')
93
+ .option('--title <title>', 'new title')
94
+ .option('--body <text>', 'new markdown body')
95
+ .option('--body-file <path>', 'read body from file (use - for stdin)')
96
+ .option('--meta <json>', 'replace metadata (JSON object)')
97
+ .option('--expected-revision <n>', 'expected current revision (optimistic concurrency)')
98
+ .option('--cwd <dir>', 'project root')
99
+ .action(async (opts) => {
100
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
101
+ const body = await resolveBody(opts);
102
+ const patch = {};
103
+ if (opts.title !== undefined)
104
+ patch.title = opts.title;
105
+ if (body !== undefined)
106
+ patch.body = body;
107
+ if (opts.meta !== undefined)
108
+ patch.meta = JSON.parse(opts.meta);
109
+ if (opts.expectedRevision !== undefined)
110
+ patch.expectedRevision = Number(opts.expectedRevision);
111
+ const record = await engine.update(opts.id, patch);
112
+ return {
113
+ payload: {
114
+ id: record.frontmatter.id,
115
+ revision: record.frontmatter.revision,
116
+ path: record.path,
117
+ frontmatter: record.frontmatter,
118
+ body: record.body,
119
+ },
120
+ human: () => renderRecordHuman(record),
121
+ };
122
+ });
123
+ });
124
+ program
125
+ .command('delete')
126
+ .description('Soft-delete an artifact')
127
+ .requiredOption('--id <id>', 'artifact id')
128
+ .option('--cwd <dir>', 'project root')
129
+ .action(async (opts) => {
130
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
131
+ const record = await engine.softDelete(opts.id);
132
+ return {
133
+ payload: {
134
+ id: record.frontmatter.id,
135
+ deletedAt: record.frontmatter.deletedAt,
136
+ revision: record.frontmatter.revision,
137
+ },
138
+ human: () => [
139
+ renderHeader('🗑', `Deleted ${record.frontmatter.id}`),
140
+ ` at: ${record.frontmatter.deletedAt}`,
141
+ ].join('\n'),
142
+ };
143
+ });
144
+ });
145
+ program
146
+ .command('list')
147
+ .description('List artifacts')
148
+ .option('--type <type>', 'filter by type')
149
+ .option('--include-deleted', 'include soft-deleted artifacts', false)
150
+ .option('--cwd <dir>', 'project root')
151
+ .action(async (opts) => {
152
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
153
+ const items = engine.list({ type: opts.type, includeDeleted: opts.includeDeleted });
154
+ const human = () => {
155
+ if (items.length === 0)
156
+ return 'No artifacts.';
157
+ const rows = items.map((a) => [
158
+ `${a.type}/${a.slug}`,
159
+ String(a.revision),
160
+ a.deletedAt ? 'deleted' : 'active',
161
+ a.title,
162
+ a.id,
163
+ ]);
164
+ const table = renderTable(['type/slug', 'rev', 'status', 'title', 'id'], rows);
165
+ return `${renderHeader('📦', 'Artifacts')}\n${table}`;
166
+ };
167
+ return { payload: items, human };
168
+ });
169
+ });
170
+ }
171
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../../src/cli/commands/artifact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Delivery commands: read-only `epics` and `tasks` views over the configured
3
+ * delivery adapter (default: OpenSpec). Mutating actions are rejected with
4
+ * `DELIVERY_READ_ONLY` so users get a structured pointer to the right tool.
5
+ */
6
+ import type { Command } from 'commander';
7
+ export declare function registerDelivery(program: Command): void;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Delivery commands: read-only `epics` and `tasks` views over the configured
3
+ * delivery adapter (default: OpenSpec). Mutating actions are rejected with
4
+ * `DELIVERY_READ_ONLY` so users get a structured pointer to the right tool.
5
+ */
6
+ import path from 'node:path';
7
+ import { resolveWorkspacePaths } from '../../workspace/paths.js';
8
+ import { readConfig } from '../../workspace/config.js';
9
+ import { resolveAdapter } from '../../delivery/index.js';
10
+ import { SpegoError } from '../../errors.js';
11
+ import { renderHeader, renderTable } from '../render.js';
12
+ import { runCommand } from '../runtime.js';
13
+ const READ_ONLY_ACTIONS = new Set(['list', 'get']);
14
+ function assertReadOnlyAction(action, surface) {
15
+ if (!action || READ_ONLY_ACTIONS.has(action))
16
+ return;
17
+ throw new SpegoError('DELIVERY_READ_ONLY', `Cannot '${action}' delivery ${surface} through spego. Use the OpenSpec CLI for delivery mutations.`, { attemptedAction: action, suggestedTool: 'openspec' });
18
+ }
19
+ function renderEpicRow(epic) {
20
+ const progress = epic.taskCount != null ? `${epic.tasksDone ?? 0}/${epic.taskCount}` : '—';
21
+ return [epic.externalId, epic.status, progress, epic.title];
22
+ }
23
+ function renderTaskRow(task) {
24
+ return [task.status === 'done' ? '[x]' : '[ ]', task.title];
25
+ }
26
+ export function registerDelivery(program) {
27
+ program
28
+ .command('epics')
29
+ .description('List epics or get a single epic')
30
+ .argument('[action]', 'list (default) or get')
31
+ .option('--change <name>', 'get a single epic by name')
32
+ .option('--cwd <dir>', 'project root')
33
+ .action(async (action, opts) => {
34
+ await runCommand({ program }, async () => {
35
+ assertReadOnlyAction(action, 'epics');
36
+ const projectRoot = path.resolve(opts.cwd ?? process.cwd());
37
+ const wsPaths = resolveWorkspacePaths(projectRoot);
38
+ const config = await readConfig(wsPaths.configPath);
39
+ const adapter = resolveAdapter(projectRoot, config);
40
+ if (opts.change) {
41
+ const epic = await adapter.getEpic(opts.change);
42
+ return {
43
+ payload: epic,
44
+ human: () => {
45
+ const table = renderTable(['id', 'status', 'progress', 'title'], [renderEpicRow(epic)]);
46
+ return `${renderHeader('📚', `Epic (${adapter.name})`)}\n${table}`;
47
+ },
48
+ };
49
+ }
50
+ const epics = await adapter.listEpics();
51
+ return {
52
+ payload: epics,
53
+ human: () => {
54
+ if (epics.length === 0)
55
+ return 'No epics.';
56
+ const table = renderTable(['id', 'status', 'progress', 'title'], epics.map(renderEpicRow));
57
+ return `${renderHeader('📚', `Epics (${adapter.name})`)}\n${table}`;
58
+ },
59
+ };
60
+ });
61
+ });
62
+ program
63
+ .command('tasks')
64
+ .description('List tasks for a change or get a single task')
65
+ .argument('[action]', 'list (default) or get')
66
+ .requiredOption('--change <name>', 'the epic/change name')
67
+ .option('--task <id>', 'get a single task by id')
68
+ .option('--cwd <dir>', 'project root')
69
+ .action(async (action, opts) => {
70
+ await runCommand({ program }, async () => {
71
+ assertReadOnlyAction(action, 'tasks');
72
+ const projectRoot = path.resolve(opts.cwd ?? process.cwd());
73
+ const wsPaths = resolveWorkspacePaths(projectRoot);
74
+ const config = await readConfig(wsPaths.configPath);
75
+ const adapter = resolveAdapter(projectRoot, config);
76
+ if (opts.task) {
77
+ const task = await adapter.getTask(opts.change, opts.task);
78
+ return {
79
+ payload: task,
80
+ human: () => {
81
+ const table = renderTable(['done', 'title'], [renderTaskRow(task)]);
82
+ return `${renderHeader('✅', `Task: ${opts.change} (${adapter.name})`)}\n${table}`;
83
+ },
84
+ };
85
+ }
86
+ const tasks = await adapter.listTasks(opts.change);
87
+ return {
88
+ payload: tasks,
89
+ human: () => {
90
+ if (tasks.length === 0)
91
+ return `No tasks for ${opts.change}.`;
92
+ const table = renderTable(['done', 'title'], tasks.map(renderTaskRow));
93
+ return `${renderHeader('✅', `Tasks: ${opts.change} (${adapter.name})`)}\n${table}`;
94
+ },
95
+ };
96
+ });
97
+ });
98
+ }
99
+ //# sourceMappingURL=delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/cli/commands/delivery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Index maintenance: `spego index rebuild`.
3
+ */
4
+ import type { Command } from 'commander';
5
+ export declare function registerIndex(program: Command): void;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Index maintenance: `spego index rebuild`.
3
+ */
4
+ import { renderBox, renderHeader, renderTable } from '../render.js';
5
+ import { runEngineCommand } from '../runtime.js';
6
+ export function registerIndex(program) {
7
+ const indexCmd = program.command('index').description('Index maintenance');
8
+ indexCmd
9
+ .command('rebuild')
10
+ .description('Rebuild the SQLite index from markdown files')
11
+ .option('--cwd <dir>', 'project root')
12
+ .action(async (opts) => {
13
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
14
+ const report = await engine.rebuildIndex();
15
+ const human = () => {
16
+ const summary = renderBox('Index rebuild', [
17
+ ['scanned', String(report.scannedFiles)],
18
+ ['indexed', String(report.indexedArtifacts)],
19
+ ['invalid', String(report.invalidFiles.length)],
20
+ ]);
21
+ const header = renderHeader('📦', 'Index rebuild');
22
+ if (report.invalidFiles.length === 0)
23
+ return `${header}\n${summary}`;
24
+ const table = renderTable(['path', 'error'], report.invalidFiles.map((i) => [i.path, i.error]), { maxWidth: 80 });
25
+ return `${header}\n${summary}\n\nInvalid files:\n${table}`;
26
+ };
27
+ return { payload: report, human };
28
+ });
29
+ });
30
+ }
31
+ //# sourceMappingURL=index-rebuild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-rebuild.js","sourceRoot":"","sources":["../../../src/cli/commands/index-rebuild.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;IAE3E,QAAQ;SACL,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC;SACrC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAClE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,GAAW,EAAE;gBACzB,MAAM,OAAO,GAAG,SAAS,CAAC,eAAe,EAAE;oBACzC,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;oBACxC,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;oBAC5C,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;iBAChD,CAAC,CAAC;gBACH,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;gBACnD,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,GAAG,MAAM,KAAK,OAAO,EAAE,CAAC;gBACrE,MAAM,KAAK,GAAG,WAAW,CACvB,CAAC,MAAM,EAAE,OAAO,CAAC,EACjB,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EACjD,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjB,CAAC;gBACF,OAAO,GAAG,MAAM,KAAK,OAAO,uBAAuB,KAAK,EAAE,CAAC;YAC7D,CAAC,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Metadata commands: `commands` and `workflows`.
3
+ * Both are read-only listings backed by static registries.
4
+ */
5
+ import type { Command } from 'commander';
6
+ export declare function registerMeta(program: Command): void;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Metadata commands: `commands` and `workflows`.
3
+ * Both are read-only listings backed by static registries.
4
+ */
5
+ import { COMMAND_REGISTRY } from '../../commands/registry.js';
6
+ import { WORKFLOW_REGISTRY } from '../../workflows/registry.js';
7
+ import { renderHeader, renderTable } from '../render.js';
8
+ import { runCommand } from '../runtime.js';
9
+ function renderCommandsHuman() {
10
+ const order = ['workspace', 'artifact', 'view', 'planning'];
11
+ const titles = {
12
+ workspace: 'Workspace',
13
+ artifact: 'Artifacts',
14
+ view: 'View',
15
+ planning: 'Planning',
16
+ };
17
+ const sections = order
18
+ .map((cat) => {
19
+ const items = COMMAND_REGISTRY.filter((c) => c.category === cat);
20
+ if (items.length === 0)
21
+ return '';
22
+ const table = renderTable(['name', 'description'], items.map((c) => [c.name, c.description]));
23
+ return `${titles[cat]}\n${table}`;
24
+ })
25
+ .filter((s) => s.length > 0);
26
+ return [renderHeader('🛠️', 'Commands'), '', sections.join('\n\n')].join('\n');
27
+ }
28
+ function renderWorkflowsHuman() {
29
+ const rows = WORKFLOW_REGISTRY.map((w) => [w.name, String(w.phases.length), w.description]);
30
+ const table = renderTable(['name', 'phases', 'description'], rows, { maxWidth: 80 });
31
+ return [renderHeader('🧭', 'Workflows'), '', table].join('\n');
32
+ }
33
+ export function registerMeta(program) {
34
+ program
35
+ .command('commands')
36
+ .description('List available spego commands with metadata')
37
+ .action(async () => {
38
+ await runCommand({ program }, async () => ({
39
+ payload: COMMAND_REGISTRY,
40
+ human: renderCommandsHuman,
41
+ }));
42
+ });
43
+ program
44
+ .command('workflows')
45
+ .description('List available workflow skills')
46
+ .action(async () => {
47
+ await runCommand({ program }, async () => {
48
+ const entries = WORKFLOW_REGISTRY.map((w) => ({
49
+ name: w.name,
50
+ description: w.description,
51
+ personas: w.personas,
52
+ phases: w.phases,
53
+ inputs: w.inputs,
54
+ outputs: w.outputs,
55
+ }));
56
+ return { payload: entries, human: renderWorkflowsHuman };
57
+ });
58
+ });
59
+ }
60
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/cli/commands/meta.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,SAAS,mBAAmB;IAC1B,MAAM,KAAK,GAAmC,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC5F,MAAM,MAAM,GAA4C;QACtD,SAAS,EAAE,WAAW;QACtB,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,UAAU;KACrB,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK;SACnB,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC;QACjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC9F,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC;IACpC,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,oBAAoB;IAC3B,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5F,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IACrF,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACzC,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,mBAAmB;SAC3B,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC5C,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC,CAAC;YACJ,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Skill regeneration: `spego skills` (and the hidden `regenerate` alias).
3
+ */
4
+ import type { Command } from 'commander';
5
+ export declare function registerSkills(program: Command): void;