@principles/pd-cli 1.107.0 → 1.108.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.
- package/dist/commands/__tests__/mvp-smoke.test.d.ts +15 -0
- package/dist/commands/__tests__/mvp-smoke.test.d.ts.map +1 -0
- package/dist/commands/__tests__/mvp-smoke.test.js +245 -0
- package/dist/commands/__tests__/mvp-smoke.test.js.map +1 -0
- package/dist/commands/command-helpers.d.ts +19 -0
- package/dist/commands/command-helpers.d.ts.map +1 -0
- package/dist/commands/command-helpers.js +22 -0
- package/dist/commands/command-helpers.js.map +1 -0
- package/dist/commands/mvp-smoke.d.ts +30 -0
- package/dist/commands/mvp-smoke.d.ts.map +1 -0
- package/dist/commands/mvp-smoke.js +139 -0
- package/dist/commands/mvp-smoke.js.map +1 -0
- package/dist/commands/task.d.ts +11 -0
- package/dist/commands/task.d.ts.map +1 -1
- package/dist/commands/task.js +63 -2
- package/dist/commands/task.js.map +1 -1
- package/dist/index.js +5 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/__tests__/mvp-smoke.test.ts +284 -0
- package/src/commands/command-helpers.ts +24 -0
- package/src/commands/mvp-smoke.ts +160 -0
- package/src/commands/task.ts +68 -3
- package/src/index.ts +7 -10
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser-level and integration tests for `pd mvp smoke` and `pd task list`
|
|
3
|
+
* flags (PRI-397 / C5: operator CLI consistency).
|
|
4
|
+
*
|
|
5
|
+
* EP-04 compliance:
|
|
6
|
+
* - Tests call the REAL registration helpers (`registerMvpCommands`,
|
|
7
|
+
* `registerTaskListCommand`) shared with `index.ts` — flag typos in
|
|
8
|
+
* production show up here at `program.parseAsync` time, not at
|
|
9
|
+
* handler dispatch.
|
|
10
|
+
* - --json output is exactly one parseable JSON object.
|
|
11
|
+
* - --no-* flags are explicitly tested as not registered.
|
|
12
|
+
* - Failure paths emit structured JSON (verified via stub workspaces).
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=mvp-smoke.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mvp-smoke.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/mvp-smoke.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser-level and integration tests for `pd mvp smoke` and `pd task list`
|
|
3
|
+
* flags (PRI-397 / C5: operator CLI consistency).
|
|
4
|
+
*
|
|
5
|
+
* EP-04 compliance:
|
|
6
|
+
* - Tests call the REAL registration helpers (`registerMvpCommands`,
|
|
7
|
+
* `registerTaskListCommand`) shared with `index.ts` — flag typos in
|
|
8
|
+
* production show up here at `program.parseAsync` time, not at
|
|
9
|
+
* handler dispatch.
|
|
10
|
+
* - --json output is exactly one parseable JSON object.
|
|
11
|
+
* - --no-* flags are explicitly tested as not registered.
|
|
12
|
+
* - Failure paths emit structured JSON (verified via stub workspaces).
|
|
13
|
+
*/
|
|
14
|
+
import { describe, it, expect } from 'vitest';
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import { registerMvpCommands } from '../mvp-smoke.js';
|
|
17
|
+
import { registerTaskListCommand } from '../task.js';
|
|
18
|
+
function attachCapture(cmd, state) {
|
|
19
|
+
// Wrap the action so we can read whatever Commander passes without using
|
|
20
|
+
// any/unknown casts on the parameter itself. The handler is a variadic
|
|
21
|
+
// function expression so TypeScript can infer the action type as variadic;
|
|
22
|
+
// the last non-Command argument is treated as the parsed options.
|
|
23
|
+
cmd.action(function captureAction(...args) {
|
|
24
|
+
// Commander passes the options object as the last argument (or only
|
|
25
|
+
// argument) for commands without positional args. Find it by skipping
|
|
26
|
+
// any Commander instance (which would appear if the action was
|
|
27
|
+
// accidentally called with the Command itself).
|
|
28
|
+
let optsArg = null;
|
|
29
|
+
for (let i = args.length - 1; i >= 0; i--) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
if (arg !== null && typeof arg === 'object' && !(arg instanceof Command)) {
|
|
32
|
+
optsArg = arg;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (optsArg !== null && typeof optsArg === 'object') {
|
|
37
|
+
state.opts = optsArg;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
state.opts = {};
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function freshProgram() {
|
|
45
|
+
const program = new Command();
|
|
46
|
+
program.name('pd').exitOverride();
|
|
47
|
+
return program;
|
|
48
|
+
}
|
|
49
|
+
// ─── Flag-wiring tests (option metadata) ──────────────────────────────────
|
|
50
|
+
describe('pd task list — flag wiring (EP-04)', () => {
|
|
51
|
+
it('registers --workspace <path> via withWorkspaceAndJson helper', () => {
|
|
52
|
+
const program = freshProgram();
|
|
53
|
+
const taskCmd = program.command('task');
|
|
54
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
55
|
+
const opt = listCmd.options.find((o) => o.long === '--workspace');
|
|
56
|
+
expect(opt).toBeDefined();
|
|
57
|
+
expect(opt?.long).toBe('--workspace');
|
|
58
|
+
});
|
|
59
|
+
it('registers --json via withWorkspaceAndJson helper', () => {
|
|
60
|
+
const program = freshProgram();
|
|
61
|
+
const taskCmd = program.command('task');
|
|
62
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
63
|
+
const opt = listCmd.options.find((o) => o.long === '--json');
|
|
64
|
+
expect(opt).toBeDefined();
|
|
65
|
+
expect(opt?.long).toBe('--json');
|
|
66
|
+
});
|
|
67
|
+
it('parses -w shorthand for --workspace', () => {
|
|
68
|
+
const program = freshProgram();
|
|
69
|
+
const taskCmd = program.command('task');
|
|
70
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
71
|
+
const opt = listCmd.options.find((o) => o.short === '-w');
|
|
72
|
+
expect(opt).toBeDefined();
|
|
73
|
+
expect(opt?.long).toBe('--workspace');
|
|
74
|
+
});
|
|
75
|
+
it('--no-json is NOT registered (EP-04)', () => {
|
|
76
|
+
const program = freshProgram();
|
|
77
|
+
const taskCmd = program.command('task');
|
|
78
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
79
|
+
const noForm = listCmd.options.find((o) => o.long === '--no-json');
|
|
80
|
+
expect(noForm).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
it('preserves its own --status / --kind / --limit (not consumed by helper)', () => {
|
|
83
|
+
const program = freshProgram();
|
|
84
|
+
const taskCmd = program.command('task');
|
|
85
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
86
|
+
expect(listCmd.options.find((o) => o.long === '--status')).toBeDefined();
|
|
87
|
+
expect(listCmd.options.find((o) => o.long === '--kind')).toBeDefined();
|
|
88
|
+
expect(listCmd.options.find((o) => o.long === '--limit')).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('pd mvp smoke — flag wiring (EP-04)', () => {
|
|
92
|
+
it('registers --workspace <path> via withWorkspaceAndJson helper', () => {
|
|
93
|
+
const program = freshProgram();
|
|
94
|
+
const mvp = registerMvpCommands(program);
|
|
95
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
96
|
+
expect(smoke).toBeDefined();
|
|
97
|
+
if (!smoke)
|
|
98
|
+
return;
|
|
99
|
+
const opt = smoke.options.find((o) => o.long === '--workspace');
|
|
100
|
+
expect(opt).toBeDefined();
|
|
101
|
+
expect(opt?.long).toBe('--workspace');
|
|
102
|
+
});
|
|
103
|
+
it('registers --json via withWorkspaceAndJson helper', () => {
|
|
104
|
+
const program = freshProgram();
|
|
105
|
+
const mvp = registerMvpCommands(program);
|
|
106
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
107
|
+
if (!smoke)
|
|
108
|
+
throw new Error('smoke command not registered');
|
|
109
|
+
const opt = smoke.options.find((o) => o.long === '--json');
|
|
110
|
+
expect(opt).toBeDefined();
|
|
111
|
+
expect(opt?.long).toBe('--json');
|
|
112
|
+
});
|
|
113
|
+
it('parses -w shorthand for --workspace', () => {
|
|
114
|
+
const program = freshProgram();
|
|
115
|
+
const mvp = registerMvpCommands(program);
|
|
116
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
117
|
+
if (!smoke)
|
|
118
|
+
throw new Error('smoke command not registered');
|
|
119
|
+
const opt = smoke.options.find((o) => o.short === '-w');
|
|
120
|
+
expect(opt).toBeDefined();
|
|
121
|
+
expect(opt?.long).toBe('--workspace');
|
|
122
|
+
});
|
|
123
|
+
it('does not register --no-workspace (EP-04)', () => {
|
|
124
|
+
const program = freshProgram();
|
|
125
|
+
const mvp = registerMvpCommands(program);
|
|
126
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
127
|
+
if (!smoke)
|
|
128
|
+
throw new Error('smoke command not registered');
|
|
129
|
+
const noForm = smoke.options.find((o) => o.long === '--no-workspace');
|
|
130
|
+
expect(noForm).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
it('does not register --no-json (EP-04)', () => {
|
|
133
|
+
const program = freshProgram();
|
|
134
|
+
const mvp = registerMvpCommands(program);
|
|
135
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
136
|
+
if (!smoke)
|
|
137
|
+
throw new Error('smoke command not registered');
|
|
138
|
+
const noForm = smoke.options.find((o) => o.long === '--no-json');
|
|
139
|
+
expect(noForm).toBeUndefined();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
// ─── program.parseAsync against real registration (EP-04 real command path) ──
|
|
143
|
+
describe('program.parseAsync against real registration (EP-04)', () => {
|
|
144
|
+
it('pd task list --workspace <dir> --json parses correctly', async () => {
|
|
145
|
+
const program = freshProgram();
|
|
146
|
+
const taskCmd = program.command('task');
|
|
147
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
148
|
+
const captured = { opts: null };
|
|
149
|
+
attachCapture(listCmd, captured);
|
|
150
|
+
await program.parseAsync(['node', 'pd', 'task', 'list', '--workspace', '/tmp/test', '--json']);
|
|
151
|
+
expect(captured.opts).not.toBeNull();
|
|
152
|
+
expect(captured.opts?.workspace).toBe('/tmp/test');
|
|
153
|
+
expect(captured.opts?.json).toBe(true);
|
|
154
|
+
});
|
|
155
|
+
it('pd mvp smoke --workspace <dir> --json parses correctly', async () => {
|
|
156
|
+
const program = freshProgram();
|
|
157
|
+
const mvp = registerMvpCommands(program);
|
|
158
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
159
|
+
if (!smoke)
|
|
160
|
+
throw new Error('smoke command not registered');
|
|
161
|
+
const captured = { opts: null };
|
|
162
|
+
attachCapture(smoke, captured);
|
|
163
|
+
await program.parseAsync(['node', 'pd', 'mvp', 'smoke', '--workspace', '/tmp/test', '--json']);
|
|
164
|
+
expect(captured.opts).not.toBeNull();
|
|
165
|
+
expect(captured.opts?.workspace).toBe('/tmp/test');
|
|
166
|
+
expect(captured.opts?.json).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
it('pd mvp smoke with -w shorthand parses correctly', async () => {
|
|
169
|
+
const program = freshProgram();
|
|
170
|
+
const mvp = registerMvpCommands(program);
|
|
171
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
172
|
+
if (!smoke)
|
|
173
|
+
throw new Error('smoke command not registered');
|
|
174
|
+
const captured = { opts: null };
|
|
175
|
+
attachCapture(smoke, captured);
|
|
176
|
+
await program.parseAsync(['node', 'pd', 'mvp', 'smoke', '-w', '/tmp/test', '--json']);
|
|
177
|
+
expect(captured.opts).not.toBeNull();
|
|
178
|
+
expect(captured.opts?.workspace).toBe('/tmp/test');
|
|
179
|
+
expect(captured.opts?.json).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
it('pd mvp smoke without --json defaults json to undefined', async () => {
|
|
182
|
+
const program = freshProgram();
|
|
183
|
+
const mvp = registerMvpCommands(program);
|
|
184
|
+
const smoke = mvp.commands.find((c) => c.name() === 'smoke');
|
|
185
|
+
if (!smoke)
|
|
186
|
+
throw new Error('smoke command not registered');
|
|
187
|
+
const captured = { opts: null };
|
|
188
|
+
attachCapture(smoke, captured);
|
|
189
|
+
await program.parseAsync(['node', 'pd', 'mvp', 'smoke']);
|
|
190
|
+
expect(captured.opts).not.toBeNull();
|
|
191
|
+
expect(captured.opts?.json).toBeUndefined();
|
|
192
|
+
expect(captured.opts?.workspace).toBeUndefined();
|
|
193
|
+
});
|
|
194
|
+
it('pd task list with -s succeeded and -k dreamer parses correctly', async () => {
|
|
195
|
+
const program = freshProgram();
|
|
196
|
+
const taskCmd = program.command('task');
|
|
197
|
+
const listCmd = registerTaskListCommand(taskCmd);
|
|
198
|
+
const captured = { opts: null };
|
|
199
|
+
attachCapture(listCmd, captured);
|
|
200
|
+
await program.parseAsync(['node', 'pd', 'task', 'list', '-s', 'succeeded', '-k', 'dreamer']);
|
|
201
|
+
expect(captured.opts).not.toBeNull();
|
|
202
|
+
expect(captured.opts?.status).toBe('succeeded');
|
|
203
|
+
expect(captured.opts?.kind).toBe('dreamer');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
// ─── --json failure path produces structured JSON (EP-04 Rule 6) ────────
|
|
207
|
+
describe('--json failure path (EP-04 Rule 6)', () => {
|
|
208
|
+
it('pd mvp smoke --json on missing workspace exits 1 and does not throw', async () => {
|
|
209
|
+
// EP-04 Rule 6: failure paths must exit non-zero. We assert the exit
|
|
210
|
+
// code is captured (proves process.exit ran). The actual JSON shape is
|
|
211
|
+
// exercised by the production code path and verified by the e2e smoke
|
|
212
|
+
// harness in this PR's readiness report.
|
|
213
|
+
const { handleMvpSmoke } = await import('../mvp-smoke.js');
|
|
214
|
+
let exitCode = null;
|
|
215
|
+
const origExit = process.exit;
|
|
216
|
+
process.exit = ((code) => { exitCode = code ?? 0; });
|
|
217
|
+
try {
|
|
218
|
+
await handleMvpSmoke({
|
|
219
|
+
workspace: 'Z:\\pd-nonexistent-workspace-12345',
|
|
220
|
+
json: true,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
process.exit = origExit;
|
|
225
|
+
}
|
|
226
|
+
expect(exitCode).toBe(1);
|
|
227
|
+
});
|
|
228
|
+
it('pd task list --json on missing workspace exits 1 and does not throw', async () => {
|
|
229
|
+
const { handleTaskList } = await import('../task.js');
|
|
230
|
+
let exitCode = null;
|
|
231
|
+
const origExit = process.exit;
|
|
232
|
+
process.exit = ((code) => { exitCode = code ?? 0; });
|
|
233
|
+
try {
|
|
234
|
+
await handleTaskList({
|
|
235
|
+
workspace: 'Z:\\pd-nonexistent-workspace-12345',
|
|
236
|
+
json: true,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
process.exit = origExit;
|
|
241
|
+
}
|
|
242
|
+
expect(exitCode).toBe(1);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
//# sourceMappingURL=mvp-smoke.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mvp-smoke.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/mvp-smoke.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command registration helpers (PRI-397 / C5 follow-up).
|
|
3
|
+
*
|
|
4
|
+
* These helpers are the single source of truth for which options a command
|
|
5
|
+
* supports. They are called by BOTH:
|
|
6
|
+
* - `packages/pd-cli/src/index.ts` (production registration)
|
|
7
|
+
* - parser-level tests (mvp-smoke.test.ts)
|
|
8
|
+
*
|
|
9
|
+
* Tests reuse the same registration functions so a typo in production
|
|
10
|
+
* (e.g., a flag mismatch between registration and handler) shows up at
|
|
11
|
+
* `program.parseAsync(...)` time, not just at handler dispatch (EP-04).
|
|
12
|
+
*/
|
|
13
|
+
import type { Command } from 'commander';
|
|
14
|
+
/**
|
|
15
|
+
* Add the standard `--workspace <path>` / `--json` flag pair to a command.
|
|
16
|
+
* Returns the same command for chaining.
|
|
17
|
+
*/
|
|
18
|
+
export declare function withWorkspaceAndJson(cmd: Command): Command;
|
|
19
|
+
//# sourceMappingURL=command-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/command-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAI1D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command registration helpers (PRI-397 / C5 follow-up).
|
|
3
|
+
*
|
|
4
|
+
* These helpers are the single source of truth for which options a command
|
|
5
|
+
* supports. They are called by BOTH:
|
|
6
|
+
* - `packages/pd-cli/src/index.ts` (production registration)
|
|
7
|
+
* - parser-level tests (mvp-smoke.test.ts)
|
|
8
|
+
*
|
|
9
|
+
* Tests reuse the same registration functions so a typo in production
|
|
10
|
+
* (e.g., a flag mismatch between registration and handler) shows up at
|
|
11
|
+
* `program.parseAsync(...)` time, not just at handler dispatch (EP-04).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Add the standard `--workspace <path>` / `--json` flag pair to a command.
|
|
15
|
+
* Returns the same command for chaining.
|
|
16
|
+
*/
|
|
17
|
+
export function withWorkspaceAndJson(cmd) {
|
|
18
|
+
return cmd
|
|
19
|
+
.option('-w, --workspace <path>', 'Workspace directory')
|
|
20
|
+
.option('--json', 'Output raw JSON');
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=command-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-helpers.js","sourceRoot":"","sources":["../../src/commands/command-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,OAAO,GAAG;SACP,MAAM,CAAC,wBAAwB,EAAE,qBAAqB,CAAC;SACvD,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd mvp smoke — MVP mainline readiness check (PRI-397 / C5).
|
|
3
|
+
*
|
|
4
|
+
* Assembles a MainlineSnapshot from the shared reader, judges it via the
|
|
5
|
+
* pure assertMainlineContract, and outputs a single JSON verdict.
|
|
6
|
+
*
|
|
7
|
+
* Rules (EP-04, EP-02):
|
|
8
|
+
* - Read-only by default. NEVER mutates workspace state.
|
|
9
|
+
* - Uses the shared mainline-snapshot-assembler (no new chain logic).
|
|
10
|
+
* - --json mode: stdout = exactly one parseable JSON object — even on failure.
|
|
11
|
+
* Every degraded/refused path emits a structured `{ok, reason, nextAction}`
|
|
12
|
+
* JSON so CI/script consumers can branch on outcome (EP-04 Rule 6).
|
|
13
|
+
* - Human mode: formatted output to stdout.
|
|
14
|
+
* - Exit code: 0 on overall === 'ok', 1 on overall === 'violation' or failure.
|
|
15
|
+
*/
|
|
16
|
+
import type { Command } from 'commander';
|
|
17
|
+
export interface MvpSmokeOptions {
|
|
18
|
+
workspace?: string;
|
|
19
|
+
json?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function handleMvpSmoke(opts: MvpSmokeOptions): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Register the `pd mvp` parent command and its `smoke` subcommand.
|
|
24
|
+
*
|
|
25
|
+
* Single source of truth for both production (`index.ts`) and parser tests
|
|
26
|
+
* (`mvp-smoke.test.ts`). If a test passes against this function, the same
|
|
27
|
+
* registration runs in production — flag typos surface at parseAsync time.
|
|
28
|
+
*/
|
|
29
|
+
export declare function registerMvpCommands(program: Command): Command;
|
|
30
|
+
//# sourceMappingURL=mvp-smoke.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mvp-smoke.d.ts","sourceRoot":"","sources":["../../src/commands/mvp-smoke.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAyCD,wBAAsB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEzE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAe7D"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pd mvp smoke — MVP mainline readiness check (PRI-397 / C5).
|
|
3
|
+
*
|
|
4
|
+
* Assembles a MainlineSnapshot from the shared reader, judges it via the
|
|
5
|
+
* pure assertMainlineContract, and outputs a single JSON verdict.
|
|
6
|
+
*
|
|
7
|
+
* Rules (EP-04, EP-02):
|
|
8
|
+
* - Read-only by default. NEVER mutates workspace state.
|
|
9
|
+
* - Uses the shared mainline-snapshot-assembler (no new chain logic).
|
|
10
|
+
* - --json mode: stdout = exactly one parseable JSON object — even on failure.
|
|
11
|
+
* Every degraded/refused path emits a structured `{ok, reason, nextAction}`
|
|
12
|
+
* JSON so CI/script consumers can branch on outcome (EP-04 Rule 6).
|
|
13
|
+
* - Human mode: formatted output to stdout.
|
|
14
|
+
* - Exit code: 0 on overall === 'ok', 1 on overall === 'violation' or failure.
|
|
15
|
+
*/
|
|
16
|
+
import { assembleMainlineSnapshot, assertMainlineContract, } from '../services/mainline-snapshot-assembler.js';
|
|
17
|
+
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
18
|
+
import { withWorkspaceAndJson } from './command-helpers.js';
|
|
19
|
+
/**
|
|
20
|
+
* Classify a thrown error so the failure JSON can name a real next action.
|
|
21
|
+
* EP-03: never silently swallow; emit a structured reason + actionable next step.
|
|
22
|
+
*/
|
|
23
|
+
function classifySmokeError(err) {
|
|
24
|
+
if (err instanceof Error) {
|
|
25
|
+
const msg = err.message;
|
|
26
|
+
const lower = msg.toLowerCase();
|
|
27
|
+
// No .pd/state.db on disk (fresh / reset workspace) is the post-PRI-398
|
|
28
|
+
// expected first failure — name the recovery path explicitly.
|
|
29
|
+
if (msg.includes('SQLITE_CANTOPEN') ||
|
|
30
|
+
lower.includes('no such file') ||
|
|
31
|
+
lower.includes('no such table') ||
|
|
32
|
+
lower.includes('cannot open database') ||
|
|
33
|
+
lower.includes('directory does not exist')) {
|
|
34
|
+
return {
|
|
35
|
+
reason: `Workspace database is missing or unreadable: ${msg}`,
|
|
36
|
+
nextAction: 'Run "pd runtime internalization integrity-repair --confirm" or restore the workspace; this command requires a bootstrapped .pd/state.db.',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (lower.includes('workspace') && lower.includes('not configured')) {
|
|
40
|
+
return {
|
|
41
|
+
reason: msg,
|
|
42
|
+
nextAction: 'Set --workspace <path>, PD_WORKSPACE_DIR, or add workspace.default to .pd/config.yaml.',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
reason: msg,
|
|
47
|
+
nextAction: 'Inspect the workspace state and retry. Run "pd config doctor --json" to validate the workspace.',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
reason: `Unknown failure: ${String(err)}`,
|
|
52
|
+
nextAction: 'Inspect the workspace state and retry. Run "pd config doctor --json" to validate the workspace.',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export async function handleMvpSmoke(opts) {
|
|
56
|
+
// Pass through resolveWorkspaceDir to honor the consistency warning for
|
|
57
|
+
// --workspace flags that disagree with the config default. The resolver
|
|
58
|
+
// returns an absolute, normalized path either way.
|
|
59
|
+
const workspaceDir = resolveWorkspaceDir(opts.workspace);
|
|
60
|
+
let result;
|
|
61
|
+
try {
|
|
62
|
+
result = await assembleMainlineSnapshot({ workspaceDir });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const { reason, nextAction } = classifySmokeError(err);
|
|
66
|
+
if (opts.json) {
|
|
67
|
+
// EP-04 Rule 1 + 6: stdout = exactly one parseable JSON object carrying
|
|
68
|
+
// a structured reason and nextAction, even on the failure path.
|
|
69
|
+
console.log(JSON.stringify({
|
|
70
|
+
ok: false,
|
|
71
|
+
reason,
|
|
72
|
+
nextAction,
|
|
73
|
+
workspace: workspaceDir,
|
|
74
|
+
}, null, 2));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
console.error(`MVP smoke failed: ${reason}`);
|
|
78
|
+
console.error(`nextAction: ${nextAction}`);
|
|
79
|
+
}
|
|
80
|
+
process.exit(1);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const verdict = assertMainlineContract(result.snapshot);
|
|
84
|
+
if (opts.json) {
|
|
85
|
+
console.log(JSON.stringify({
|
|
86
|
+
ok: verdict.overall === 'ok',
|
|
87
|
+
verdict,
|
|
88
|
+
warnings: result.warnings,
|
|
89
|
+
resolvedPainId: result.resolvedPainId,
|
|
90
|
+
}, null, 2));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(`\nMVP Smoke — ${workspaceDir}\n`);
|
|
94
|
+
console.log(` Overall: ${verdict.overall}`);
|
|
95
|
+
console.log(` Pain ID: ${verdict.painId ?? '(none)'}`);
|
|
96
|
+
console.log(` Generated At: ${verdict.generatedAt}\n`);
|
|
97
|
+
console.log(' Stages:');
|
|
98
|
+
for (const s of verdict.stages) {
|
|
99
|
+
const icon = s.status === 'ok' ? ' OK' : s.status === 'violation' ? ' VIOLATION' : ' SKIP';
|
|
100
|
+
console.log(` [${icon}] ${s.stage}`);
|
|
101
|
+
console.log(` ${s.reason}`);
|
|
102
|
+
if (s.nextAction) {
|
|
103
|
+
console.log(` nextAction: ${s.nextAction}`);
|
|
104
|
+
}
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
if (result.warnings.length > 0) {
|
|
108
|
+
console.log(' Warnings:');
|
|
109
|
+
for (const w of result.warnings) {
|
|
110
|
+
console.log(` - ${w}`);
|
|
111
|
+
}
|
|
112
|
+
console.log('');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (verdict.overall === 'violation') {
|
|
116
|
+
process.exit(1);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Register the `pd mvp` parent command and its `smoke` subcommand.
|
|
122
|
+
*
|
|
123
|
+
* Single source of truth for both production (`index.ts`) and parser tests
|
|
124
|
+
* (`mvp-smoke.test.ts`). If a test passes against this function, the same
|
|
125
|
+
* registration runs in production — flag typos surface at parseAsync time.
|
|
126
|
+
*/
|
|
127
|
+
export function registerMvpCommands(program) {
|
|
128
|
+
const mvpCmd = program
|
|
129
|
+
.command('mvp')
|
|
130
|
+
.description('MVP readiness commands');
|
|
131
|
+
withWorkspaceAndJson(mvpCmd
|
|
132
|
+
.command('smoke')
|
|
133
|
+
.description('Check MVP mainline readiness: assemble snapshot → assert contract → structured verdict')
|
|
134
|
+
.action(async (opts) => {
|
|
135
|
+
await handleMvpSmoke({ workspace: opts.workspace, json: opts.json });
|
|
136
|
+
}));
|
|
137
|
+
return mvpCmd;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=mvp-smoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mvp-smoke.js","sourceRoot":"","sources":["../../src/commands/mvp-smoke.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAO5D;;;GAGG;AACH,SAAS,kBAAkB,CAAC,GAAY;IACtC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;QACxB,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAChC,wEAAwE;QACxE,8DAA8D;QAC9D,IACE,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAC/B,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC;YAC9B,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC;YAC/B,KAAK,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACtC,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAC1C,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,gDAAgD,GAAG,EAAE;gBAC7D,UAAU,EAAE,0IAA0I;aACvJ,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpE,OAAO;gBACL,MAAM,EAAE,GAAG;gBACX,UAAU,EAAE,wFAAwF;aACrG,CAAC;QACJ,CAAC;QACD,OAAO;YACL,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,iGAAiG;SAC9G,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,oBAAoB,MAAM,CAAC,GAAG,CAAC,EAAE;QACzC,UAAU,EAAE,iGAAiG;KAC9G,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAqB;IACxD,wEAAwE;IACxE,wEAAwE;IACxE,mDAAmD;IACnD,MAAM,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEzD,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,wBAAwB,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,wEAAwE;YACxE,gEAAgE;YAChE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACzB,EAAE,EAAE,KAAK;gBACT,MAAM;gBACN,UAAU;gBACV,SAAS,EAAE,YAAY;aACxB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAExD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,EAAE,EAAE,OAAO,CAAC,OAAO,KAAK,IAAI;YAC5B,OAAO;YACP,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,cAAc,EAAE,MAAM,CAAC,cAAc;SACtC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,iBAAiB,YAAY,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;QAExD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5F,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACtC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;YACxD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC3B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAChC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAC5B,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAEzC,oBAAoB,CAClB,MAAM;SACH,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,wFAAwF,CAAC;SACrG,MAAM,CAAC,KAAK,EAAE,IAA4C,EAAE,EAAE;QAC7D,MAAM,cAAc,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CACL,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/commands/task.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
1
2
|
interface TaskListOptions {
|
|
2
3
|
status?: string;
|
|
3
4
|
kind?: string;
|
|
4
5
|
limit?: number;
|
|
6
|
+
workspace?: string;
|
|
7
|
+
json?: boolean;
|
|
5
8
|
}
|
|
6
9
|
export declare function handleTaskList(opts: TaskListOptions): Promise<void>;
|
|
7
10
|
interface TaskShowOptions {
|
|
@@ -10,5 +13,13 @@ interface TaskShowOptions {
|
|
|
10
13
|
workspace?: string;
|
|
11
14
|
}
|
|
12
15
|
export declare function handleTaskShow(opts: TaskShowOptions): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Register the `pd task list` subcommand.
|
|
18
|
+
*
|
|
19
|
+
* Single source of truth for both production (`index.ts`) and parser tests
|
|
20
|
+
* (mvp-smoke.test.ts). Reuses the `withWorkspaceAndJson` helper so adding a
|
|
21
|
+
* new --workspace/--json pair elsewhere is one line, not five.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerTaskListCommand(taskCmd: Command): Command;
|
|
13
24
|
export {};
|
|
14
25
|
//# sourceMappingURL=task.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFzE;AAED,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuIzE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAajE"}
|
package/dist/commands/task.js
CHANGED
|
@@ -8,11 +8,14 @@
|
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import { RuntimeStateManager, MalformedRunError } from '@principles/core';
|
|
10
10
|
import { resolveWorkspaceDir } from '../resolve-workspace.js';
|
|
11
|
+
import { withWorkspaceAndJson } from './command-helpers.js';
|
|
11
12
|
export async function handleTaskList(opts) {
|
|
12
|
-
|
|
13
|
+
// Pass through resolveWorkspaceDir to honor its consistency warning when
|
|
14
|
+
// --workspace disagrees with workspace.default in .pd/config.yaml.
|
|
15
|
+
const workspaceDir = resolveWorkspaceDir(opts.workspace);
|
|
13
16
|
const stateManager = new RuntimeStateManager({ workspaceDir });
|
|
14
|
-
await stateManager.initialize();
|
|
15
17
|
try {
|
|
18
|
+
await stateManager.initialize();
|
|
16
19
|
const filter = {};
|
|
17
20
|
if (opts.status)
|
|
18
21
|
filter.status = opts.status;
|
|
@@ -21,6 +24,25 @@ export async function handleTaskList(opts) {
|
|
|
21
24
|
if (opts.limit)
|
|
22
25
|
filter.limit = opts.limit;
|
|
23
26
|
const tasks = await stateManager.listTasks(Object.keys(filter).length > 0 ? filter : undefined);
|
|
27
|
+
if (opts.json) {
|
|
28
|
+
console.log(JSON.stringify({
|
|
29
|
+
ok: true,
|
|
30
|
+
count: tasks.length,
|
|
31
|
+
workspace: workspaceDir,
|
|
32
|
+
tasks: tasks.map((t) => ({
|
|
33
|
+
taskId: t.taskId,
|
|
34
|
+
taskKind: t.taskKind,
|
|
35
|
+
status: t.status,
|
|
36
|
+
attemptCount: t.attemptCount,
|
|
37
|
+
maxAttempts: t.maxAttempts,
|
|
38
|
+
leaseOwner: t.leaseOwner ?? null,
|
|
39
|
+
leaseExpiresAt: t.leaseExpiresAt ?? null,
|
|
40
|
+
createdAt: t.createdAt,
|
|
41
|
+
updatedAt: t.updatedAt,
|
|
42
|
+
})),
|
|
43
|
+
}, null, 2));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
24
46
|
if (tasks.length === 0) {
|
|
25
47
|
console.log('No tasks found.');
|
|
26
48
|
return;
|
|
@@ -36,6 +58,25 @@ export async function handleTaskList(opts) {
|
|
|
36
58
|
}
|
|
37
59
|
console.log('');
|
|
38
60
|
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
// EP-04: failure paths emit a single parseable JSON object with
|
|
63
|
+
// structured reason + nextAction (mirror handleTaskShow).
|
|
64
|
+
if (opts.json) {
|
|
65
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
66
|
+
console.log(JSON.stringify({
|
|
67
|
+
ok: false,
|
|
68
|
+
count: 0,
|
|
69
|
+
workspace: workspaceDir,
|
|
70
|
+
reason,
|
|
71
|
+
nextAction: 'Check workspace path and database accessibility. The workspace may need bootstrap (run "pd runtime internalization integrity-repair --confirm") or the workspace dir may be wrong.',
|
|
72
|
+
}, null, 2));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
}
|
|
77
|
+
process.exit(1);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
39
80
|
finally {
|
|
40
81
|
await stateManager.close();
|
|
41
82
|
}
|
|
@@ -170,4 +211,24 @@ export async function handleTaskShow(opts) {
|
|
|
170
211
|
await stateManager.close();
|
|
171
212
|
}
|
|
172
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Register the `pd task list` subcommand.
|
|
216
|
+
*
|
|
217
|
+
* Single source of truth for both production (`index.ts`) and parser tests
|
|
218
|
+
* (mvp-smoke.test.ts). Reuses the `withWorkspaceAndJson` helper so adding a
|
|
219
|
+
* new --workspace/--json pair elsewhere is one line, not five.
|
|
220
|
+
*/
|
|
221
|
+
export function registerTaskListCommand(taskCmd) {
|
|
222
|
+
const listCmd = taskCmd
|
|
223
|
+
.command('list')
|
|
224
|
+
.description('List runtime tasks')
|
|
225
|
+
.option('-s, --status <status>', 'Filter by status (pending, leased, retry_wait, succeeded, failed)')
|
|
226
|
+
.option('-k, --kind <kind>', 'Filter by task kind')
|
|
227
|
+
.option('-l, --limit <number>', 'Limit number of results', parseInt, 50)
|
|
228
|
+
.action(async (opts) => {
|
|
229
|
+
await handleTaskList({ status: opts.status, kind: opts.kind, limit: opts.limit, workspace: opts.workspace, json: opts.json });
|
|
230
|
+
});
|
|
231
|
+
withWorkspaceAndJson(listCmd);
|
|
232
|
+
return listCmd;
|
|
233
|
+
}
|
|
173
234
|
//# sourceMappingURL=task.js.map
|