@zhuk/spego 0.8.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 (43) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +6 -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/workspace/config.d.ts +2 -2
  43. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
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
+
3
19
  ## [0.8.0] - 2026-05-22
4
20
 
5
21
  ### Added
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`)
@@ -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":"AAAA;;;;;GAKG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,SAAS,oBAAoB,CAAC,EAAiC;IAC7D,OAAO,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,QAAQ,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC;AACpE,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAsB;IAC/C,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,aAAa,EAAE,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,oBAAoB,CAAC;SACjC,cAAc,CAAC,eAAe,EAAE,0CAA0C,CAAC;SAC3E,cAAc,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;SACnD,MAAM,CAAC,eAAe,EAAE,wBAAwB,CAAC;SACjD,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;SAC/C,MAAM,CAAC,oBAAoB,EAAE,kDAAkD,CAAC;SAChF,MAAM,CAAC,eAAe,EAAE,yBAAyB,EAAE,IAAI,CAAC;SACxD,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,IAAI,GAAG,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;gBACjC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI;gBACJ,IAAI;aACL,CAAC,CAAC;YACH,MAAM,OAAO,GAAG;gBACd,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE;gBACzB,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI;gBAC7B,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI;gBAC7B,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ;gBACrC,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC;aAC9D,CAAC;YACF,MAAM,KAAK,GAAG,GAAW,EAAE,CACzB;gBACE,YAAY,CAAC,GAAG,EAAE,WAAW,MAAM,CAAC,WAAW,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,SAAS,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;gBACtH,YAAY,MAAM,CAAC,IAAI,EAAE;aAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,qCAAqC,CAAC;SAClD,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC;SAClC,MAAM,CAAC,eAAe,EAAE,6BAA6B,CAAC;SACtD,MAAM,CAAC,eAAe,EAAE,6BAA6B,CAAC;SACtD,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC;SAC9D,MAAM,CAAC,gBAAgB,EAAE,0BAA0B,CAAC;SACpD,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,IAAI,MAAsB,CAAC;YAC3B,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM;oBACJ,IAAI,CAAC,QAAQ,KAAK,SAAS;wBACzB,CAAC,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC3D,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAClC,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7D,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACrB,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5D,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,UAAU,CAAC,mBAAmB,EAAE,4CAA4C,CAAC,CAAC;YAC1F,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;gBAClF,KAAK,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;aACvC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,cAAc,CAAC,WAAW,EAAE,aAAa,CAAC;SAC1C,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC;SACtC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC;SAC5C,MAAM,CAAC,oBAAoB,EAAE,uCAAuC,CAAC;SACrE,MAAM,CAAC,eAAe,EAAE,gCAAgC,CAAC;SACzD,MAAM,CAAC,yBAAyB,EAAE,oDAAoD,CAAC;SACvF,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,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,KAAK,GAA4B,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACvD,IAAI,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS;gBACrC,KAAK,CAAC,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACnD,OAAO;gBACL,OAAO,EAAE;oBACP,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE;oBACzB,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ;oBACrC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,WAAW,EAAE,MAAM,CAAC,WAAW;oBAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;iBAClB;gBACD,KAAK,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;aACvC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yBAAyB,CAAC;SACtC,cAAc,CAAC,WAAW,EAAE,aAAa,CAAC;SAC1C,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,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChD,OAAO;gBACL,OAAO,EAAE;oBACP,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE;oBACzB,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS;oBACvC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ;iBACtC;gBACD,KAAK,EAAE,GAAG,EAAE,CACV;oBACE,YAAY,CAAC,IAAI,EAAE,WAAW,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;oBACtD,UAAU,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;iBACzC,CAAC,IAAI,CAAC,IAAI,CAAC;aACf,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,gBAAgB,CAAC;SAC7B,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC;SACzC,MAAM,CAAC,mBAAmB,EAAE,gCAAgC,EAAE,KAAK,CAAC;SACpE,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,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;YACpF,MAAM,KAAK,GAAG,GAAW,EAAE;gBACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,eAAe,CAAC;gBAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;oBAC5B,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE;oBACrB,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;oBAClB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;oBAClC,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,EAAE;iBACL,CAAC,CAAC;gBACH,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC/E,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,KAAK,EAAE,CAAC;YACxD,CAAC,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -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":"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"}
@@ -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;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Skill regeneration: `spego skills` (and the hidden `regenerate` alias).
3
+ */
4
+ import path from 'node:path';
5
+ import { resolveWorkspacePaths } from '../../workspace/paths.js';
6
+ import { readConfig } from '../../workspace/config.js';
7
+ import { generateAll } from '../../generator/index.js';
8
+ import { renderHeader } from '../render.js';
9
+ import { deprecate } from '../output.js';
10
+ import { runCommand } from '../runtime.js';
11
+ async function runSkills(cwd, json) {
12
+ const projectRoot = path.resolve(cwd ?? process.cwd());
13
+ const wsPaths = resolveWorkspacePaths(projectRoot);
14
+ const config = await readConfig(wsPaths.configPath);
15
+ const reports = await generateAll(projectRoot, config.agents, { emitWarnings: !json });
16
+ const human = () => {
17
+ const lines = [renderHeader('🛠️', 'Skill regeneration'), ''];
18
+ for (const r of reports) {
19
+ lines.push(`[${r.target}]`);
20
+ for (const f of r.files) {
21
+ lines.push(` ${f.action} ${f.path}`);
22
+ }
23
+ }
24
+ return lines.join('\n');
25
+ };
26
+ return { payload: reports, human };
27
+ }
28
+ export function registerSkills(program) {
29
+ program
30
+ .command('skills')
31
+ .description('Regenerate agent skill and command files')
32
+ .option('--cwd <dir>', 'project root')
33
+ .action(async (opts) => {
34
+ await runCommand({ program }, async (json) => runSkills(opts.cwd, json));
35
+ });
36
+ program
37
+ .command('regenerate', { hidden: true })
38
+ .description('Regenerate agent skill and command files')
39
+ .option('--cwd <dir>', 'project root')
40
+ .action(async (opts) => {
41
+ await runCommand({ program }, async (json) => {
42
+ deprecate(json, "'spego regenerate' is now 'spego skills'");
43
+ return runSkills(opts.cwd, json);
44
+ });
45
+ });
46
+ }
47
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/cli/commands/skills.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,KAAK,UAAU,SAAS,CAAC,GAAuB,EAAE,IAAa;IAI7D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,GAAW,EAAE;QACzB,MAAM,KAAK,GAAa,CAAC,YAAY,CAAC,KAAK,EAAE,oBAAoB,CAAC,EAAE,EAAE,CAAC,CAAC;QACxE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC;SACrC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACvC,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC;SACrC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC3C,SAAS,CAAC,IAAI,EAAE,0CAA0C,CAAC,CAAC;YAC5D,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Bundle export: `spego view`.
3
+ *
4
+ * Honors the deprecated `--format` flag during the deprecation window in
5
+ * addition to the global `--json` flag.
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerView(program: Command): void;