@zhuk/spego 0.13.0 → 0.14.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 (44) hide show
  1. package/CHANGELOG.md +23 -2
  2. package/README.md +10 -11
  3. package/dist/cli/commands/board.d.ts +2 -0
  4. package/dist/cli/commands/{mirror.js → board.js} +10 -122
  5. package/dist/cli/commands/board.js.map +1 -0
  6. package/dist/cli/commands/delivery.d.ts +3 -2
  7. package/dist/cli/commands/delivery.js +40 -34
  8. package/dist/cli/commands/delivery.js.map +1 -1
  9. package/dist/cli/commands/sprints.d.ts +6 -0
  10. package/dist/cli/commands/sprints.js +35 -0
  11. package/dist/cli/commands/sprints.js.map +1 -0
  12. package/dist/cli/commands/view.d.ts +0 -3
  13. package/dist/cli/commands/view.js +1 -12
  14. package/dist/cli/commands/view.js.map +1 -1
  15. package/dist/cli/commands/workspace.js +50 -2
  16. package/dist/cli/commands/workspace.js.map +1 -1
  17. package/dist/cli/runtime.d.ts +0 -1
  18. package/dist/cli/runtime.js +1 -1
  19. package/dist/cli/runtime.js.map +1 -1
  20. package/dist/cli.js +4 -2
  21. package/dist/cli.js.map +1 -1
  22. package/dist/command-meta/registry.d.ts +1 -0
  23. package/dist/command-meta/registry.js +18 -8
  24. package/dist/command-meta/registry.js.map +1 -1
  25. package/dist/delivery/load.d.ts +13 -0
  26. package/dist/delivery/load.js +124 -0
  27. package/dist/delivery/load.js.map +1 -0
  28. package/dist/delivery/mirror.d.ts +11 -0
  29. package/dist/delivery/mirror.js +14 -0
  30. package/dist/delivery/mirror.js.map +1 -1
  31. package/dist/delivery/openspec-adapter.d.ts +3 -1
  32. package/dist/delivery/openspec-adapter.js +34 -37
  33. package/dist/delivery/openspec-adapter.js.map +1 -1
  34. package/dist/delivery/openspec-discover.d.ts +0 -1
  35. package/dist/delivery/openspec-discover.js +13 -33
  36. package/dist/delivery/openspec-discover.js.map +1 -1
  37. package/dist/generator/claude.d.ts +1 -1
  38. package/dist/generator/claude.js +11 -4
  39. package/dist/generator/claude.js.map +1 -1
  40. package/dist/workflows/registry.js +5 -5
  41. package/dist/workflows/registry.js.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/cli/commands/mirror.d.ts +0 -2
  44. package/dist/cli/commands/mirror.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## [0.14.0] - 2026-07-22
6
+
7
+ ### Added
8
+ - `spego sprints` lists sprint plans in board order (start date, undated last).
9
+ - `spego status` reports advisory delivery drift (ungroomed changes, orphan epics, closable sprints) with a pointer to the groom workflow.
10
+
11
+ ### Changed
12
+ - **Breaking:** renamed `spego mirror` to `spego board` (`/spego:board`); the delivery board name matches what the command renders. The Mirror stays the internal derivation concept.
13
+ - **Breaking:** `spego epics` and `spego tasks` take positional arguments: `spego epics [name]`, `spego tasks <change> [task]`. The `--change` and `--task` flags are gone; mutation verbs in the name position still fail with `DELIVERY_READ_ONLY`.
14
+
15
+ ### Removed
16
+ - **Breaking:** removed the deprecated `spego view --format` flag; use the global `--json` flag.
17
+
18
+ ## [0.13.1] - 2026-07-21
19
+
20
+ ### Changed
21
+ - `spego mirror` / `spego epics` resolve epic status from `tasks.md` on disk instead of spawning `openspec status` per change (~114x faster on multi-change workspaces) and discover changes once per render with parallelized filesystem reads.
22
+
23
+ ### Removed
24
+ - Removed the per-change `openspec status` subprocess call and the "OpenSpec CLI status unavailable" fallback warning; mirror and epics no longer require the `openspec` binary on PATH.
25
+
3
26
  ## [0.13.0] - 2026-07-21
4
27
 
5
28
  ### Added
@@ -8,8 +31,6 @@
8
31
  - `spego mirror` command deriving the delivery mirror (sprint board, blockers, gaps, drift warnings, next-change suggestion) from OpenSpec changes and `epic`/`sprint-plan` artifacts, with `--graph`, `--gaps`, and deterministic `--json` output.
9
32
  - `spego-groom` workflow skill for syncing delivery-mirror epics with active OpenSpec changes, analyzing deps/requires/gaps, and maintaining sprint plans.
10
33
 
11
- ## [Unreleased]
12
-
13
34
  ## [0.12.0] - 2026-07-12
14
35
 
15
36
  ### Security
package/README.md CHANGED
@@ -24,9 +24,10 @@ spego init --agents claude,opencode --demo false
24
24
  | `spego commands` | List command metadata |
25
25
  | `spego workflows` | List workflow skills metadata |
26
26
  | `spego skills` | Regenerate agent skill files |
27
- | `spego epics` | List delivery epics |
28
- | `spego tasks --change <name>` | List tasks for a change |
29
- | `spego mirror` | Show delivery mirror board |
27
+ | `spego epics [name]` | List delivery epics, or get one by change name |
28
+ | `spego tasks <change> [task]` | List tasks for a change, or get one task |
29
+ | `spego sprints` | List sprint plans in board order |
30
+ | `spego board` | Show the delivery board (sprints, blockers, gaps) |
30
31
  | `spego index rebuild` | Rebuild SQLite index from files |
31
32
 
32
33
  All commands accept `--cwd <dir>` to set the project root.
@@ -40,8 +41,6 @@ Every spego command speaks two output modes:
40
41
 
41
42
  Agents calling spego MUST pass `--json` so they get parseable output. Humans normally do not.
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
-
45
44
  `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
45
 
47
46
  `spego create` and `spego update` accept body content through `--body`, `--body-file <path>`, or stdin via `--body-file -`.
@@ -89,19 +88,19 @@ The adapter is read-only. It observes OpenSpec state but does not create, contin
89
88
  | Source | spego view |
90
89
  |--------|------------|
91
90
  | `openspec/changes/<name>/proposal.md` | Epic title |
92
- | `openspec/changes/<name>/tasks.md` | Task summaries |
93
- | `openspec status --change <name> --json` | Preferred status source |
94
- | Filesystem parsing | Fallback when the OpenSpec CLI is unavailable |
91
+ | `openspec/changes/<name>/tasks.md` | Task status and counts |
92
+
93
+ The `openspec` binary is not required on PATH — board and epics resolve status entirely from `tasks.md` on disk.
95
94
 
96
95
  Archived changes under `openspec/changes/archive/` are excluded. A change with no `tasks.md` is reported as `planning-incomplete`.
97
96
 
98
97
  ## Delivery Mirror
99
98
 
100
- `spego mirror` derives the delivery mirror on demand — it never writes artifacts or OpenSpec state. It combines active and archived OpenSpec changes with `epic` and `sprint-plan` artifacts into a sprint board: sprints in date order (undated last), changes in each sprint-plan's list order, per-change status, blockers, gaps, and missing artifacts (`requires` minus resolvable `links`). A change is blocked when a dependency is incomplete and not scheduled in the same or an earlier sprint.
99
+ `spego board` derives the delivery mirror on demand — it never writes artifacts or OpenSpec state. It combines active and archived OpenSpec changes with `epic` and `sprint-plan` artifacts into a sprint board: sprints in date order (undated last), changes in each sprint-plan's list order, per-change status, blockers, gaps, and missing artifacts (`requires` minus resolvable `links`). A change is blocked when a dependency is incomplete and not scheduled in the same or an earlier sprint.
101
100
 
102
101
  The default output is the human board. `--graph` shows dependency edges; `--gaps` focuses on gap flags and missing artifacts. The global `--json` flag emits a deterministic `{ sprints, ungrouped, warnings, next }` document in all modes; `next` names the first pending, unblocked change or is `null` with a hint to groom.
103
102
 
104
- Every rendering attaches drift warnings: `dangling-dep`, `dep-cycle`, `ungroomed-change`, `orphan-epic`, `archived-in-sprint`, and `closable-sprint`. Repair belongs to the groom workflow; mirror only reports.
103
+ Every rendering attaches drift warnings: `dangling-dep`, `dep-cycle`, `ungroomed-change`, `orphan-epic`, `archived-in-sprint`, and `closable-sprint`. Repair belongs to the groom workflow; the board only reports.
105
104
 
106
105
  ## OpenCode Workflows
107
106
 
@@ -229,7 +228,7 @@ If a combined workflow discovers that OpenSpec artifacts need to change, use the
229
228
 
230
229
  Delivery-mirror workflow that reconciles active OpenSpec changes with `epic` and `sprint-plan` artifacts. One Groomer persona runs five phases:
231
230
 
232
- 1. `orient` — read `spego mirror --json` and `spego epics --json`, then classify drift warnings.
231
+ 1. `orient` — read `spego board --json` and `spego epics --json`, then classify drift warnings.
233
232
  2. `sync` — create missing epics for ungroomed active changes and propose orphan-epic disposition.
234
233
  3. `analyze` — update deps, requires, supporting links, and gap notes on epics.
235
234
  4. `plan` — propose releasable, testable sprint groupings and create or update `sprint-plan` artifacts after confirmation.
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerBoard(program: Command): void;
@@ -1,22 +1,17 @@
1
- import path from 'node:path';
2
- import { resolveAdapter } from '../../delivery/index.js';
3
- import { discoverChanges } from '../../delivery/openspec-discover.js';
4
- import { deriveMirror, filterMirrorGaps, } from '../../delivery/mirror.js';
5
- import { SpegoError } from '../../errors.js';
6
- import { readConfig } from '../../workspace/config.js';
7
- import { resolveWorkspacePaths } from '../../workspace/paths.js';
1
+ import { loadBoardState } from '../../delivery/load.js';
2
+ import { filterMirrorGaps, } from '../../delivery/mirror.js';
8
3
  import { renderHeader, renderTable } from '../render.js';
9
4
  import { runEngineCommand } from '../runtime.js';
10
- export function registerMirror(program) {
5
+ export function registerBoard(program) {
11
6
  program
12
- .command('mirror')
13
- .description('Show delivery mirror board')
7
+ .command('board')
8
+ .description('Show the delivery board (sprints, blockers, gaps)')
14
9
  .option('--graph', 'show dependency graph', false)
15
10
  .option('--gaps', 'show gaps, missing artifacts, and blockers', false)
16
11
  .option('--cwd <dir>', 'project root')
17
12
  .action(async (opts) => {
18
13
  await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
19
- const state = await loadMirrorState(engine, opts.cwd);
14
+ const state = await loadBoardState(engine, opts.cwd);
20
15
  const payload = opts.gaps ? filterMirrorGaps(state.board) : state.board;
21
16
  return {
22
17
  payload,
@@ -31,115 +26,8 @@ export function registerMirror(program) {
31
26
  });
32
27
  });
33
28
  }
34
- async function loadMirrorState(engine, cwd) {
35
- const projectRoot = path.resolve(cwd ?? process.cwd());
36
- const wsPaths = resolveWorkspacePaths(projectRoot);
37
- const config = await readConfig(wsPaths.configPath);
38
- const adapter = resolveAdapter(projectRoot, config);
39
- try {
40
- const input = await collectMirrorInput(engine, projectRoot, adapter);
41
- return { input, board: deriveMirror(input) };
42
- }
43
- catch (err) {
44
- if (err instanceof SpegoError && err.code === 'DELIVERY_ADAPTER_ERROR') {
45
- const warning = {
46
- code: 'adapter-unavailable',
47
- message: 'OpenSpec workspace unavailable; mirror board is empty.',
48
- details: err.details,
49
- };
50
- const input = {
51
- changes: [],
52
- epics: [],
53
- sprints: [],
54
- linkedArtifacts: [],
55
- warnings: [warning],
56
- };
57
- return { input, board: deriveMirror(input) };
58
- }
59
- throw err;
60
- }
61
- }
62
- async function collectMirrorInput(engine, projectRoot, adapter) {
63
- const adapterEpics = await adapter.listEpics();
64
- const discovered = await discoverChanges(projectRoot);
65
- const adapterBySlug = new Map(adapterEpics.map((epic) => [epic.externalId, epic]));
66
- const seen = new Set();
67
- const changes = discovered
68
- .map((item) => {
69
- seen.add(item.name);
70
- const adapterEpic = adapterBySlug.get(item.name);
71
- return sourceChange(item.name, item.archived, adapterEpic);
72
- })
73
- .sort((a, b) => a.slug.localeCompare(b.slug));
74
- for (const epic of adapterEpics) {
75
- if (seen.has(epic.externalId))
76
- continue;
77
- changes.push(sourceChange(epic.externalId, false, epic));
78
- }
79
- changes.sort((a, b) => a.slug.localeCompare(b.slug));
80
- const epics = engine.list({ type: 'epic' }).map(indexedArtifact);
81
- const sprints = engine.list({ type: 'sprint-plan' }).map(indexedArtifact);
82
- const linkedArtifacts = await resolveLinkedArtifacts(engine, epics);
83
- return { changes, epics, sprints, linkedArtifacts, warnings: [] };
84
- }
85
- function sourceChange(slug, archived, epic) {
86
- const status = archived ? 'completed' : (epic?.status ?? 'unknown');
87
- return {
88
- slug,
89
- title: epic?.title ?? slug,
90
- status,
91
- archived,
92
- warnings: epic?.warnings,
93
- };
94
- }
95
- function indexedArtifact(artifact) {
96
- return {
97
- id: artifact.id,
98
- type: artifact.type,
99
- slug: artifact.slug,
100
- title: artifact.title,
101
- meta: artifact.meta,
102
- };
103
- }
104
- async function resolveLinkedArtifacts(engine, epics) {
105
- const ids = new Set();
106
- for (const epic of epics) {
107
- const links = epic.meta.links;
108
- if (!Array.isArray(links))
109
- continue;
110
- for (const link of links) {
111
- if (typeof link === 'string')
112
- ids.add(link);
113
- }
114
- }
115
- const artifacts = [];
116
- for (const id of [...ids].sort()) {
117
- try {
118
- const record = await engine.readById(id);
119
- artifacts.push({
120
- id: record.frontmatter.id,
121
- type: record.frontmatter.type,
122
- slug: record.frontmatter.slug,
123
- title: record.frontmatter.title,
124
- meta: record.frontmatter.meta,
125
- });
126
- }
127
- catch (err) {
128
- if (err instanceof SpegoError && err.code === 'ARTIFACT_NOT_FOUND')
129
- continue;
130
- throw err;
131
- }
132
- }
133
- artifacts.sort((a, b) => {
134
- const bySlug = a.slug.localeCompare(b.slug);
135
- if (bySlug !== 0)
136
- return bySlug;
137
- return a.id.localeCompare(b.id);
138
- });
139
- return artifacts;
140
- }
141
29
  function renderBoard(board) {
142
- const lines = [renderHeader('🪞', 'Mirror board'), ''];
30
+ const lines = [renderHeader('🪞', 'Delivery board'), ''];
143
31
  if (board.sprints.length === 0 && board.ungrouped.length === 0) {
144
32
  lines.push('No groomed delivery board.');
145
33
  }
@@ -171,7 +59,7 @@ function renderGraph(board, input) {
171
59
  rows.push([change.slug, visible.has(dep) ? dep : `${dep} (missing)`, change.blockers.join(', ') || '—', change.status]);
172
60
  }
173
61
  }
174
- const lines = [renderHeader('🕸️', 'Mirror dependency graph'), ''];
62
+ const lines = [renderHeader('🕸️', 'Dependency graph'), ''];
175
63
  if (rows.length === 0)
176
64
  lines.push('No dependency edges.');
177
65
  else
@@ -191,7 +79,7 @@ function renderGaps(board) {
191
79
  for (const change of board.ungrouped) {
192
80
  rows.push([change.slug, '—', change.blockers.join(', ') || '—', formatGaps(change), change.missing.join(', ') || '—']);
193
81
  }
194
- const lines = [renderHeader('🧩', 'Mirror gaps'), ''];
82
+ const lines = [renderHeader('🧩', 'Delivery gaps'), ''];
195
83
  if (rows.length === 0)
196
84
  lines.push('No gaps, missing artifacts, or blockers.');
197
85
  else
@@ -250,4 +138,4 @@ function allChanges(board) {
250
138
  changes.push(...board.ungrouped);
251
139
  return changes;
252
140
  }
253
- //# sourceMappingURL=mirror.js.map
141
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../../src/cli/commands/board.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  /**
2
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.
3
+ * delivery adapter (default: OpenSpec). Mutation verbs in the name position
4
+ * are rejected with `DELIVERY_READ_ONLY` so agents get a structured pointer
5
+ * to the right tool.
5
6
  */
6
7
  import type { Command } from 'commander';
7
8
  export declare function registerDelivery(program: Command): void;
@@ -1,7 +1,8 @@
1
1
  /**
2
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.
3
+ * delivery adapter (default: OpenSpec). Mutation verbs in the name position
4
+ * are rejected with `DELIVERY_READ_ONLY` so agents get a structured pointer
5
+ * to the right tool.
5
6
  */
6
7
  import path from 'node:path';
7
8
  import { resolveWorkspacePaths } from '../../workspace/paths.js';
@@ -10,11 +11,24 @@ import { resolveAdapter } from '../../delivery/index.js';
10
11
  import { SpegoError } from '../../errors.js';
11
12
  import { renderHeader, renderTable } from '../render.js';
12
13
  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))
14
+ const MUTATING_ACTIONS = new Set([
15
+ 'create', 'update', 'delete', 'add', 'remove', 'edit', 'set', 'complete', 'close', 'archive',
16
+ ]);
17
+ function assertReadOnly(name, surface, usage) {
18
+ if (!name)
16
19
  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' });
20
+ if (MUTATING_ACTIONS.has(name)) {
21
+ throw new SpegoError('DELIVERY_READ_ONLY', `Cannot '${name}' delivery ${surface} through spego. Use the OpenSpec CLI for delivery mutations.`, { attemptedAction: name, suggestedTool: 'openspec' });
22
+ }
23
+ if (name === 'get') {
24
+ throw new SpegoError('VALIDATION_FAILED', `'get' is no longer an action; usage: ${usage}`, { usage });
25
+ }
26
+ }
27
+ async function loadAdapter(cwd) {
28
+ const projectRoot = path.resolve(cwd ?? process.cwd());
29
+ const wsPaths = resolveWorkspacePaths(projectRoot);
30
+ const config = await readConfig(wsPaths.configPath);
31
+ return resolveAdapter(projectRoot, config);
18
32
  }
19
33
  function renderEpicRow(epic) {
20
34
  const progress = epic.taskCount != null ? `${epic.tasksDone ?? 0}/${epic.taskCount}` : '—';
@@ -26,19 +40,15 @@ function renderTaskRow(task) {
26
40
  export function registerDelivery(program) {
27
41
  program
28
42
  .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')
43
+ .description('List epics or get a single epic by change name')
44
+ .argument('[name]', 'change name to get a single epic')
32
45
  .option('--cwd <dir>', 'project root')
33
- .action(async (action, opts) => {
46
+ .action(async (name, opts) => {
34
47
  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);
48
+ assertReadOnly(name, 'epics', 'spego epics <name>');
49
+ const adapter = await loadAdapter(opts.cwd);
50
+ if (name && name !== 'list') {
51
+ const epic = await adapter.getEpic(name);
42
52
  return {
43
53
  payload: epic,
44
54
  human: () => {
@@ -62,35 +72,31 @@ export function registerDelivery(program) {
62
72
  program
63
73
  .command('tasks')
64
74
  .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')
75
+ .argument('<change>', 'change or epic name')
76
+ .argument('[task]', 'task id to get a single task')
68
77
  .option('--cwd <dir>', 'project root')
69
- .action(async (action, opts) => {
78
+ .action(async (change, task, opts) => {
70
79
  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);
80
+ assertReadOnly(change, 'tasks', 'spego tasks <change> [task]');
81
+ const adapter = await loadAdapter(opts.cwd);
82
+ if (task) {
83
+ const found = await adapter.getTask(change, task);
78
84
  return {
79
- payload: task,
85
+ payload: found,
80
86
  human: () => {
81
- const table = renderTable(['done', 'title'], [renderTaskRow(task)]);
82
- return `${renderHeader('✅', `Task: ${opts.change} (${adapter.name})`)}\n${table}`;
87
+ const table = renderTable(['done', 'title'], [renderTaskRow(found)]);
88
+ return `${renderHeader('✅', `Task: ${change} (${adapter.name})`)}\n${table}`;
83
89
  },
84
90
  };
85
91
  }
86
- const tasks = await adapter.listTasks(opts.change);
92
+ const tasks = await adapter.listTasks(change);
87
93
  return {
88
94
  payload: tasks,
89
95
  human: () => {
90
96
  if (tasks.length === 0)
91
- return `No tasks for ${opts.change}.`;
97
+ return `No tasks for ${change}.`;
92
98
  const table = renderTable(['done', 'title'], tasks.map(renderTaskRow));
93
- return `${renderHeader('✅', `Tasks: ${opts.change} (${adapter.name})`)}\n${table}`;
99
+ return `${renderHeader('✅', `Tasks: ${change} (${adapter.name})`)}\n${table}`;
94
100
  },
95
101
  };
96
102
  });
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/cli/commands/delivery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/cli/commands/delivery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sprint listing: `spego sprints` — a read-only view over `sprint-plan`
3
+ * artifacts in board order. Membership stays owned by the groom workflow.
4
+ */
5
+ import type { Command } from 'commander';
6
+ export declare function registerSprints(program: Command): void;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Sprint listing: `spego sprints` — a read-only view over `sprint-plan`
3
+ * artifacts in board order. Membership stays owned by the groom workflow.
4
+ */
5
+ import { toMirrorArtifact } from '../../delivery/load.js';
6
+ import { summarizeSprints } from '../../delivery/mirror.js';
7
+ import { renderHeader, renderTable } from '../render.js';
8
+ import { runEngineCommand } from '../runtime.js';
9
+ function sprintRow(sprint) {
10
+ const window = sprint.startDate || sprint.endDate
11
+ ? `${sprint.startDate ?? '…'} → ${sprint.endDate ?? '…'}`
12
+ : '—';
13
+ return [sprint.slug, sprint.status, window, String(sprint.changes.length), sprint.title];
14
+ }
15
+ export function registerSprints(program) {
16
+ program
17
+ .command('sprints')
18
+ .description('List sprint plans in board order')
19
+ .option('--cwd <dir>', 'project root')
20
+ .action(async (opts) => {
21
+ await runEngineCommand({ program, cwd: opts.cwd }, async (engine) => {
22
+ const sprints = summarizeSprints(engine.list({ type: 'sprint-plan' }).map(toMirrorArtifact));
23
+ return {
24
+ payload: sprints,
25
+ human: () => {
26
+ if (sprints.length === 0)
27
+ return 'No sprint plans.';
28
+ const table = renderTable(['sprint', 'status', 'window', 'changes', 'title'], sprints.map(sprintRow), { maxWidth: 48 });
29
+ return `${renderHeader('🏃', 'Sprints')}\n${table}`;
30
+ },
31
+ };
32
+ });
33
+ });
34
+ }
35
+ //# sourceMappingURL=sprints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprints.js","sourceRoot":"","sources":["../../../src/cli/commands/sprints.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAsB,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,SAAS,SAAS,CAAC,MAAqB;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO;QAC/C,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE;QACzD,CAAC,CAAC,GAAG,CAAC;IACR,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,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,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAC7F,OAAO;gBACL,OAAO,EAAE,OAAO;gBAChB,KAAK,EAAE,GAAG,EAAE;oBACV,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO,kBAAkB,CAAC;oBACpD,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;oBACxH,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,KAAK,EAAE,CAAC;gBACtD,CAAC;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,8 +1,5 @@
1
1
  /**
2
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
3
  */
7
4
  import type { Command } from 'commander';
8
5
  export declare function registerView(program: Command): void;
@@ -1,15 +1,11 @@
1
1
  /**
2
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
3
  */
7
4
  import { z } from 'zod';
8
5
  import { SpegoError } from '../../errors.js';
9
6
  import { viewArtifacts } from '../../export/view.js';
10
7
  import { intersperseBundleDividers, renderHeader } from '../render.js';
11
- import { deprecate } from '../output.js';
12
- import { getJsonMode, runEngineCommand } from '../runtime.js';
8
+ import { runEngineCommand } from '../runtime.js';
13
9
  export function registerView(program) {
14
10
  program
15
11
  .command('view')
@@ -18,19 +14,12 @@ export function registerView(program) {
18
14
  .option('--id <id>', 'limit to a single artifact')
19
15
  .option('--revision <n>', 'specific revision (requires --id)')
20
16
  .option('--include-deleted', 'include soft-deleted artifacts', false)
21
- .option('--format <fmt>', '[deprecated] markdown | json — use the global --json flag instead')
22
17
  .option('--cwd <dir>', 'project root')
23
18
  .action(async (opts) => {
24
- const globalJson = getJsonMode(program);
25
- if (opts.format !== undefined) {
26
- deprecate(globalJson, '--format is deprecated; use the global --json flag');
27
- }
28
- const wantJson = globalJson || opts.format === 'json';
29
19
  let revision;
30
20
  await runEngineCommand({
31
21
  program,
32
22
  cwd: opts.cwd,
33
- jsonOverride: wantJson,
34
23
  validate: () => {
35
24
  if (opts.revision === undefined)
36
25
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"view.js","sourceRoot":"","sources":["../../../src/cli/commands/view.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC5C,OAAO;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC;SACzC,MAAM,CAAC,WAAW,EAAE,4BAA4B,CAAC;SACjD,MAAM,CAAC,gBAAgB,EAAE,mCAAmC,CAAC;SAC7D,MAAM,CAAC,mBAAmB,EAAE,gCAAgC,EAAE,KAAK,CAAC;SACpE,MAAM,CAAC,gBAAgB,EAAE,mEAAmE,CAAC;SAC7F,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC;SACrC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,SAAS,CAAC,UAAU,EAAE,oDAAoD,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,QAAQ,GAAG,UAAU,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC;QAEtD,IAAI,QAA4B,CAAC;QACjC,MAAM,gBAAgB,CACrB;YACC,OAAO;YACP,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,YAAY,EAAE,QAAQ;YACtB,QAAQ,EAAE,GAAG,EAAE;gBACd,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;oBAAE,OAAO;gBACxC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC3E,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;oBACvB,OAAO;gBACR,CAAC;gBACD,MAAM,IAAI,UAAU,CAAC,mBAAmB,EAAE,iDAAiD,EAAE;oBAC5F,MAAM,EAAE,YAAY;iBACpB,CAAC,CAAC;YACJ,CAAC;SACD,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;YAChB,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE;gBACxC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,QAAQ;gBACR,cAAc,EAAE,IAAI,CAAC,cAAc;aACnC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9D,OAAO;gBACN,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC,KAAK,IAAI,EAAE;aAChE,CAAC;QACH,CAAC,CACD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../../../src/cli/commands/view.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC5C,OAAO;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC;SACzC,MAAM,CAAC,WAAW,EAAE,4BAA4B,CAAC;SACjD,MAAM,CAAC,gBAAgB,EAAE,mCAAmC,CAAC;SAC7D,MAAM,CAAC,mBAAmB,EAAE,gCAAgC,EAAE,KAAK,CAAC;SACpE,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC;SACrC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,IAAI,QAA4B,CAAC;QACjC,MAAM,gBAAgB,CACrB;YACC,OAAO;YACP,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,GAAG,EAAE;gBACd,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;oBAAE,OAAO;gBACxC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC3E,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;oBACvB,OAAO;gBACR,CAAC;gBACD,MAAM,IAAI,UAAU,CAAC,mBAAmB,EAAE,iDAAiD,EAAE;oBAC5F,MAAM,EAAE,YAAY;iBACpB,CAAC,CAAC;YACJ,CAAC;SACD,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;YAChB,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE;gBACxC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,QAAQ;gBACR,cAAc,EAAE,IAAI,CAAC,cAAc;aACnC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9D,OAAO;gBACN,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC,KAAK,IAAI,EAAE;aAChE,CAAC;QACH,CAAC,CACD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,9 +1,53 @@
1
1
  /**
2
2
  * Workspace lifecycle commands: `init` and `status`.
3
3
  */
4
+ import { ArtifactEngine } from '../../artifacts/engine.js';
5
+ import { loadBoardState } from '../../delivery/load.js';
4
6
  import { initWorkspace, workspaceStatus } from '../../workspace/init.js';
5
7
  import { renderBox, renderHeader } from '../render.js';
6
8
  import { runCommand } from '../runtime.js';
9
+ const DRIFT_CODES = new Set([
10
+ 'dangling-dep', 'dep-cycle', 'ungroomed-change', 'orphan-epic', 'archived-in-sprint', 'closable-sprint',
11
+ ]);
12
+ /**
13
+ * Drift is advisory: any failure to derive the board (no OpenSpec workspace,
14
+ * broken adapter) silently yields no summary so `status` never breaks.
15
+ */
16
+ async function collectDrift(cwd) {
17
+ let engine;
18
+ try {
19
+ engine = await ArtifactEngine.open({ projectRoot: cwd });
20
+ }
21
+ catch {
22
+ return undefined;
23
+ }
24
+ try {
25
+ const { board } = await loadBoardState(engine, cwd);
26
+ if (board.warnings.some((warning) => warning.code === 'adapter-unavailable'))
27
+ return undefined;
28
+ const codes = {};
29
+ let warnings = 0;
30
+ for (const warning of board.warnings) {
31
+ if (!DRIFT_CODES.has(warning.code))
32
+ continue;
33
+ warnings += 1;
34
+ codes[warning.code] = (codes[warning.code] ?? 0) + 1;
35
+ }
36
+ return { warnings, codes };
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ finally {
42
+ engine.close();
43
+ }
44
+ }
45
+ function driftLine(drift) {
46
+ const parts = Object.entries(drift.codes)
47
+ .sort(([a], [b]) => a.localeCompare(b))
48
+ .map(([code, count]) => (count > 1 ? `${code} ×${count}` : code));
49
+ return `Delivery drift: ${parts.join(', ')} — run the spego-groom workflow.`;
50
+ }
7
51
  export function registerWorkspace(program) {
8
52
  program
9
53
  .command('init')
@@ -43,6 +87,7 @@ export function registerWorkspace(program) {
43
87
  .action(async (opts) => {
44
88
  await runCommand({ program }, async () => {
45
89
  const status = await workspaceStatus(opts.cwd);
90
+ const drift = status.initialized ? await collectDrift(opts.cwd) : undefined;
46
91
  const human = () => {
47
92
  if (!status.initialized)
48
93
  return `No spego workspace; run: spego init`;
@@ -52,9 +97,12 @@ export function registerWorkspace(program) {
52
97
  ['artifacts', status.artifactsRoot ?? ''],
53
98
  ['index', status.indexPath ?? ''],
54
99
  ]);
55
- return `${renderHeader('📦', 'Workspace ready')}\n${box}`;
100
+ const lines = [`${renderHeader('📦', 'Workspace ready')}\n${box}`];
101
+ if (drift && drift.warnings > 0)
102
+ lines.push(driftLine(drift));
103
+ return lines.join('\n');
56
104
  };
57
- return { payload: status, human };
105
+ return { payload: drift === undefined ? status : { ...status, drift }, human };
58
106
  });
59
107
  });
60
108
  }