@principles/pd-cli 1.107.0 → 1.108.1

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/dist/commands/__tests__/mvp-smoke.test.d.ts +15 -0
  2. package/dist/commands/__tests__/mvp-smoke.test.d.ts.map +1 -0
  3. package/dist/commands/__tests__/mvp-smoke.test.js +245 -0
  4. package/dist/commands/__tests__/mvp-smoke.test.js.map +1 -0
  5. package/dist/commands/__tests__/runtime-probe-config.test.d.ts +20 -0
  6. package/dist/commands/__tests__/runtime-probe-config.test.d.ts.map +1 -0
  7. package/dist/commands/__tests__/runtime-probe-config.test.js +388 -0
  8. package/dist/commands/__tests__/runtime-probe-config.test.js.map +1 -0
  9. package/dist/commands/command-helpers.d.ts +19 -0
  10. package/dist/commands/command-helpers.d.ts.map +1 -0
  11. package/dist/commands/command-helpers.js +22 -0
  12. package/dist/commands/command-helpers.js.map +1 -0
  13. package/dist/commands/mvp-smoke.d.ts +30 -0
  14. package/dist/commands/mvp-smoke.d.ts.map +1 -0
  15. package/dist/commands/mvp-smoke.js +139 -0
  16. package/dist/commands/mvp-smoke.js.map +1 -0
  17. package/dist/commands/runtime.d.ts +6 -0
  18. package/dist/commands/runtime.d.ts.map +1 -1
  19. package/dist/commands/runtime.js +139 -13
  20. package/dist/commands/runtime.js.map +1 -1
  21. package/dist/commands/task.d.ts +11 -0
  22. package/dist/commands/task.d.ts.map +1 -1
  23. package/dist/commands/task.js +63 -2
  24. package/dist/commands/task.js.map +1 -1
  25. package/dist/index.js +7 -29
  26. package/dist/index.js.map +1 -1
  27. package/dist/services/mainline-snapshot-assembler.d.ts.map +1 -1
  28. package/dist/services/mainline-snapshot-assembler.js +22 -4
  29. package/dist/services/mainline-snapshot-assembler.js.map +1 -1
  30. package/dist/services/resolve-runtime-from-pd-config.d.ts +11 -0
  31. package/dist/services/resolve-runtime-from-pd-config.d.ts.map +1 -1
  32. package/dist/services/resolve-runtime-from-pd-config.js +31 -1
  33. package/dist/services/resolve-runtime-from-pd-config.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/commands/__tests__/mvp-smoke.test.ts +284 -0
  36. package/src/commands/__tests__/runtime-probe-config.test.ts +431 -0
  37. package/src/commands/command-helpers.ts +24 -0
  38. package/src/commands/mvp-smoke.ts +160 -0
  39. package/src/commands/runtime.ts +133 -13
  40. package/src/commands/task.ts +68 -3
  41. package/src/index.ts +9 -29
  42. package/src/services/mainline-snapshot-assembler.ts +23 -3
  43. package/src/services/resolve-runtime-from-pd-config.ts +41 -0
@@ -0,0 +1,388 @@
1
+ /**
2
+ * PRI-402: pd runtime probe reads .pd/config.yaml for pi-ai config.
3
+ *
4
+ * Tests cover:
5
+ * - probe reads config from .pd/config.yaml when --workspace is provided
6
+ * - JSON output includes configSource, runtimeProfileId, runtimeProfileLabel
7
+ * - explicit --provider overrides config.yaml
8
+ * - fail-loud JSON when config.yaml is missing or incomplete
9
+ * - program.parseAsync against real Commander registration (EP-04)
10
+ *
11
+ * ERR refs:
12
+ * - EP-04 (CLI gate): --json stdout single object, process.exit(1) + return
13
+ * - EP-03 (fail loud): structured JSON with reason + nextAction on failure
14
+ * - EP-07 (source alignment): probe and doctor read same config source
15
+ * - ERR-004 (source alignment): profileId/label must match doctor output
16
+ * - ERR-021 (handler-only tests): add program.parseAsync tests
17
+ * - ERR-029 (fail-loud JSON): config missing → structured JSON, not bare error
18
+ */
19
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
20
+ import { Command } from 'commander';
21
+ import * as fs from 'fs';
22
+ import * as path from 'path';
23
+ import * as os from 'os';
24
+ // ─── Mocks ─────────────────────────────────────────────────────────────────
25
+ // Mock only probeRuntime so we don't need a real LLM provider.
26
+ // All other core functions (validatePdConfig, computeEffectivePdConfig,
27
+ // resolveAgentRuntimeBinding, etc.) use their real implementations.
28
+ const mockProbeRuntime = vi.fn();
29
+ vi.mock('@principles/core/runtime-v2', async (importOriginal) => {
30
+ const actual = await importOriginal();
31
+ return {
32
+ ...actual,
33
+ probeRuntime: mockProbeRuntime,
34
+ };
35
+ });
36
+ const { handleRuntimeProbe } = await import('../runtime.js');
37
+ // ─── Test Setup ─────────────────────────────────────────────────────────────
38
+ const capturedStdout = [];
39
+ const capturedStderr = [];
40
+ let capturedExitCode = null;
41
+ const originalExit = process.exit;
42
+ const originalLog = console.log;
43
+ const originalError = console.error;
44
+ const originalWarn = console.warn;
45
+ const originalEnv = { ...process.env };
46
+ beforeEach(() => {
47
+ capturedExitCode = null;
48
+ capturedStdout.length = 0;
49
+ capturedStderr.length = 0;
50
+ process.exit = vi.fn(((code) => {
51
+ capturedExitCode = code ?? 0;
52
+ }));
53
+ console.log = vi.fn((...args) => { capturedStdout.push(args.join(' ')); });
54
+ console.error = vi.fn((...args) => { capturedStderr.push(args.join(' ')); });
55
+ console.warn = vi.fn(() => { });
56
+ mockProbeRuntime.mockReset();
57
+ process.env = { ...originalEnv, LMSTUDIO_API_KEY: 'test-key-for-pri-402' };
58
+ });
59
+ afterEach(() => {
60
+ process.exit = originalExit;
61
+ console.log = originalLog;
62
+ console.error = originalError;
63
+ console.warn = originalWarn;
64
+ process.env = originalEnv;
65
+ });
66
+ // ─── Helper: create temp workspace with .pd/config.yaml ────────────────────
67
+ function createTempWorkspace(configYaml) {
68
+ const tmpDir = path.join(os.tmpdir(), `pd-probe-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
69
+ const pdDir = path.join(tmpDir, '.pd');
70
+ fs.mkdirSync(pdDir, { recursive: true });
71
+ // Replace __WORKSPACE_DIR__ placeholder with actual path
72
+ const resolvedYaml = configYaml.replace(/__WORKSPACE_DIR__/g, tmpDir.replace(/\\/g, '/'));
73
+ fs.writeFileSync(path.join(pdDir, 'config.yaml'), resolvedYaml, 'utf-8');
74
+ return tmpDir;
75
+ }
76
+ function cleanupWorkspace(dir) {
77
+ try {
78
+ fs.rmSync(dir, { recursive: true, force: true });
79
+ }
80
+ catch {
81
+ // best effort
82
+ }
83
+ }
84
+ const PI_AI_CONFIG_YAML = `
85
+ version: 1
86
+ features:
87
+ prompt: { category: core, enabled: true }
88
+ code_tool_hook: { category: core, enabled: true }
89
+ defer_archive: { category: core, enabled: true }
90
+ workspace:
91
+ default: __WORKSPACE_DIR__
92
+ internalAgents:
93
+ defaultRuntime: pi-ai.lmstudio
94
+ agents:
95
+ diagnostician:
96
+ enabled: true
97
+ runtimeProfile: pi-ai.lmstudio
98
+ dreamer:
99
+ enabled: true
100
+ philosopher:
101
+ enabled: true
102
+ scribe:
103
+ enabled: true
104
+ artificer:
105
+ enabled: true
106
+ runtimeProfiles:
107
+ pi-ai.lmstudio:
108
+ type: pi-ai
109
+ provider: lmstudio
110
+ model: qwen3.6-27b-mtp
111
+ apiKeyEnv: LMSTUDIO_API_KEY
112
+ baseUrl: http://localhost:1234/v1
113
+ `;
114
+ // ─── Tests: probe reads config from .pd/config.yaml ────────────────────────
115
+ describe('PRI-402: probe reads .pd/config.yaml for pi-ai config', () => {
116
+ it('reads provider/model from config.yaml when --workspace provided without --provider', async () => {
117
+ const workspace = createTempWorkspace(PI_AI_CONFIG_YAML);
118
+ try {
119
+ mockProbeRuntime.mockResolvedValue({
120
+ runtimeKind: 'pi-ai',
121
+ provider: 'lmstudio',
122
+ model: 'qwen3.6-27b-mtp',
123
+ health: { healthy: true, degraded: false, warnings: [], lastCheckedAt: '2026-01-01T00:00:00Z' },
124
+ capabilities: { streaming: true },
125
+ });
126
+ await handleRuntimeProbe({
127
+ runtime: 'pi-ai',
128
+ workspace,
129
+ json: true,
130
+ });
131
+ // probeRuntime should be called with config.yaml values
132
+ expect(mockProbeRuntime).toHaveBeenCalled();
133
+ const callArgs = mockProbeRuntime.mock.calls[0]?.[0];
134
+ expect(callArgs?.provider).toBe('lmstudio');
135
+ expect(callArgs?.model).toBe('qwen3.6-27b-mtp');
136
+ expect(callArgs?.apiKeyEnv).toBe('LMSTUDIO_API_KEY');
137
+ // JSON output should contain configSource, runtimeProfileId, runtimeProfileLabel
138
+ const output = JSON.parse(capturedStdout.join(''));
139
+ expect(output.configSource).toBe('.pd/config.yaml');
140
+ expect(output.runtimeProfileId).toBe('pi-ai.lmstudio');
141
+ expect(output.runtimeProfileLabel).toBe('pi-ai: lmstudio/qwen3.6-27b-mtp');
142
+ expect(output.ok).toBe(true);
143
+ }
144
+ finally {
145
+ cleanupWorkspace(workspace);
146
+ }
147
+ });
148
+ it('explicit --provider overrides config.yaml value', async () => {
149
+ const workspace = createTempWorkspace(PI_AI_CONFIG_YAML);
150
+ try {
151
+ mockProbeRuntime.mockResolvedValue({
152
+ runtimeKind: 'pi-ai',
153
+ provider: 'openrouter',
154
+ model: 'qwen3.6-27b-mtp',
155
+ health: { healthy: true, degraded: false, warnings: [], lastCheckedAt: '2026-01-01T00:00:00Z' },
156
+ capabilities: { streaming: true },
157
+ });
158
+ await handleRuntimeProbe({
159
+ runtime: 'pi-ai',
160
+ workspace,
161
+ provider: 'openrouter',
162
+ model: 'anthropic/claude-sonnet-4',
163
+ apiKeyEnv: 'OPENROUTER_API_KEY',
164
+ json: true,
165
+ });
166
+ const callArgs = mockProbeRuntime.mock.calls[0]?.[0];
167
+ // CLI flags override config.yaml
168
+ expect(callArgs?.provider).toBe('openrouter');
169
+ expect(callArgs?.model).toBe('anthropic/claude-sonnet-4');
170
+ expect(callArgs?.apiKeyEnv).toBe('OPENROUTER_API_KEY');
171
+ // Profile info still comes from config.yaml (EP-07: source alignment)
172
+ const output = JSON.parse(capturedStdout.join(''));
173
+ expect(output.configSource).toBe('.pd/config.yaml');
174
+ expect(output.runtimeProfileId).toBe('pi-ai.lmstudio');
175
+ }
176
+ finally {
177
+ cleanupWorkspace(workspace);
178
+ }
179
+ });
180
+ it('fail-loud JSON when config.yaml is missing and no --provider', async () => {
181
+ const workspace = path.join(os.tmpdir(), `pd-probe-test-missing-${Date.now()}`);
182
+ fs.mkdirSync(workspace, { recursive: true });
183
+ // No .pd/config.yaml created
184
+ try {
185
+ await handleRuntimeProbe({
186
+ runtime: 'pi-ai',
187
+ workspace,
188
+ json: true,
189
+ });
190
+ expect(capturedExitCode).toBe(1);
191
+ const output = JSON.parse(capturedStdout.join(''));
192
+ expect(output.ok).toBe(false);
193
+ expect(output.status).toBe('failed');
194
+ expect(typeof output.reason).toBe('string');
195
+ expect(typeof output.nextAction).toBe('string');
196
+ // Single parseable JSON object (EP-04 Rule 1)
197
+ expect(Array.isArray(output)).toBe(false);
198
+ }
199
+ finally {
200
+ cleanupWorkspace(workspace);
201
+ }
202
+ });
203
+ it('fail-loud JSON when provider missing from config.yaml', async () => {
204
+ const workspace = createTempWorkspace(`
205
+ version: 1
206
+ features:
207
+ prompt: { category: core, enabled: true }
208
+ code_tool_hook: { category: core, enabled: true }
209
+ defer_archive: { category: core, enabled: true }
210
+ workspace:
211
+ default: __WORKSPACE_DIR__
212
+ internalAgents:
213
+ defaultRuntime: pi-ai.broken
214
+ agents:
215
+ diagnostician:
216
+ enabled: true
217
+ runtimeProfile: pi-ai.broken
218
+ runtimeProfiles:
219
+ pi-ai.broken:
220
+ type: pi-ai
221
+ # Missing provider, model, apiKeyEnv
222
+ `);
223
+ try {
224
+ await handleRuntimeProbe({
225
+ runtime: 'pi-ai',
226
+ workspace,
227
+ json: true,
228
+ });
229
+ expect(capturedExitCode).toBe(1);
230
+ const output = JSON.parse(capturedStdout.join(''));
231
+ expect(output.ok).toBe(false);
232
+ expect(output.status).toBe('failed');
233
+ expect(typeof output.reason).toBe('string');
234
+ expect(typeof output.nextAction).toBe('string');
235
+ }
236
+ finally {
237
+ cleanupWorkspace(workspace);
238
+ }
239
+ });
240
+ it('fail-loud JSON when apiKeyEnv env var is not set', async () => {
241
+ const workspace = createTempWorkspace(PI_AI_CONFIG_YAML);
242
+ try {
243
+ // Remove the API key env var
244
+ delete process.env.LMSTUDIO_API_KEY;
245
+ await handleRuntimeProbe({
246
+ runtime: 'pi-ai',
247
+ workspace,
248
+ json: true,
249
+ });
250
+ expect(capturedExitCode).toBe(1);
251
+ const output = JSON.parse(capturedStdout.join(''));
252
+ expect(output.ok).toBe(false);
253
+ // When apiKeyEnv is not set, resolveRuntimeConfigFromPdConfig returns
254
+ // a config error (not_ready), so the error comes from the config resolution path
255
+ expect(typeof output.reason).toBe('string');
256
+ expect(typeof output.nextAction).toBe('string');
257
+ }
258
+ finally {
259
+ cleanupWorkspace(workspace);
260
+ }
261
+ });
262
+ it('human-readable output includes Profile and Config lines', async () => {
263
+ const workspace = createTempWorkspace(PI_AI_CONFIG_YAML);
264
+ try {
265
+ mockProbeRuntime.mockResolvedValue({
266
+ runtimeKind: 'pi-ai',
267
+ provider: 'lmstudio',
268
+ model: 'qwen3.6-27b-mtp',
269
+ health: { healthy: true, degraded: false, warnings: [], lastCheckedAt: '2026-01-01T00:00:00Z' },
270
+ capabilities: { streaming: true },
271
+ });
272
+ await handleRuntimeProbe({
273
+ runtime: 'pi-ai',
274
+ workspace,
275
+ json: false,
276
+ });
277
+ const output = capturedStdout.join('\n');
278
+ expect(output).toContain('Profile:');
279
+ expect(output).toContain('pi-ai: lmstudio/qwen3.6-27b-mtp');
280
+ expect(output).toContain('Config:');
281
+ expect(output).toContain('.pd/config.yaml');
282
+ }
283
+ finally {
284
+ cleanupWorkspace(workspace);
285
+ }
286
+ });
287
+ });
288
+ // ─── Tests: program.parseAsync against real Commander registration (EP-04) ──
289
+ // Import the real command registration function to test actual production wiring
290
+ const { registerRuntimeProbeCommand } = await import('../runtime.js');
291
+ function attachCapture(cmd, state) {
292
+ // Override the action handler to capture opts without calling the real handler
293
+ cmd.action((...args) => {
294
+ // Find the opts object (last non-Command, non-null object arg)
295
+ let optsArg = null;
296
+ for (let i = args.length - 1; i >= 0; i--) {
297
+ const arg = args[i];
298
+ if (arg !== null && typeof arg === 'object' && !(arg instanceof Command)) {
299
+ optsArg = arg;
300
+ break;
301
+ }
302
+ }
303
+ state.opts = optsArg ?? {};
304
+ // Do NOT call original action (would call handleRuntimeProbe which needs real runtime)
305
+ });
306
+ }
307
+ function freshProgram() {
308
+ const program = new Command();
309
+ program.name('pd').exitOverride();
310
+ return program;
311
+ }
312
+ describe('PRI-402: probe command flag wiring (EP-04 real registration)', () => {
313
+ it('registers --runtime as required option via real registration', () => {
314
+ const program = freshProgram();
315
+ const runtimeCmd = program.command('runtime');
316
+ const probeCmd = registerRuntimeProbeCommand(runtimeCmd);
317
+ const runtimeOpt = probeCmd.options.find((o) => o.long === '--runtime');
318
+ expect(runtimeOpt).toBeDefined();
319
+ expect(runtimeOpt?.required).toBe(true);
320
+ });
321
+ it('registers --workspace with -w shorthand via real registration', () => {
322
+ const program = freshProgram();
323
+ const runtimeCmd = program.command('runtime');
324
+ const probeCmd = registerRuntimeProbeCommand(runtimeCmd);
325
+ const wsOpt = probeCmd.options.find((o) => o.short === '-w');
326
+ expect(wsOpt).toBeDefined();
327
+ expect(wsOpt?.long).toBe('--workspace');
328
+ });
329
+ it('parses --runtime pi-ai --workspace <dir> --json correctly via real registration', async () => {
330
+ const program = freshProgram();
331
+ const runtimeCmd = program.command('runtime');
332
+ const probeCmd = registerRuntimeProbeCommand(runtimeCmd);
333
+ const captured = { opts: null };
334
+ attachCapture(probeCmd, captured);
335
+ await program.parseAsync(['node', 'pd', 'runtime', 'probe', '--runtime', 'pi-ai', '--workspace', '/tmp/test', '--json']);
336
+ expect(captured.opts).not.toBeNull();
337
+ if (!captured.opts)
338
+ throw new Error('captured.opts is null');
339
+ expect(captured.opts.runtime).toBe('pi-ai');
340
+ expect(captured.opts.workspace).toBe('/tmp/test');
341
+ expect(captured.opts.json).toBe(true);
342
+ });
343
+ it('parses --runtime config --workspace <dir> correctly via real registration', async () => {
344
+ const program = freshProgram();
345
+ const runtimeCmd = program.command('runtime');
346
+ const probeCmd = registerRuntimeProbeCommand(runtimeCmd);
347
+ const captured = { opts: null };
348
+ attachCapture(probeCmd, captured);
349
+ await program.parseAsync(['node', 'pd', 'runtime', 'probe', '--runtime', 'config', '--workspace', '/tmp/test']);
350
+ expect(captured.opts).not.toBeNull();
351
+ if (!captured.opts)
352
+ throw new Error('captured.opts is null');
353
+ expect(captured.opts.runtime).toBe('config');
354
+ expect(captured.opts.workspace).toBe('/tmp/test');
355
+ });
356
+ });
357
+ // ─── Tests: resolve-runtime-from-pd-config profile extraction ───────────────
358
+ describe('PRI-402: resolveRuntimeWithOverrides returns profile info', () => {
359
+ it('returns runtimeProfileId and runtimeProfileLabel from config.yaml', async () => {
360
+ const workspace = createTempWorkspace(PI_AI_CONFIG_YAML);
361
+ try {
362
+ const { resolveRuntimeWithOverrides } = await import('../../services/resolve-runtime-from-pd-config.js');
363
+ const result = resolveRuntimeWithOverrides(workspace, {});
364
+ expect(result.configSource).toBe('.pd/config.yaml');
365
+ expect(result.runtimeProfileId).toBe('pi-ai.lmstudio');
366
+ expect(result.runtimeProfileLabel).toBe('pi-ai: lmstudio/qwen3.6-27b-mtp');
367
+ }
368
+ finally {
369
+ cleanupWorkspace(workspace);
370
+ }
371
+ });
372
+ it('returns default profile when config.yaml is missing', async () => {
373
+ const workspace = path.join(os.tmpdir(), `pd-probe-test-noprofile-${Date.now()}`);
374
+ fs.mkdirSync(workspace, { recursive: true });
375
+ try {
376
+ const { resolveRuntimeWithOverrides } = await import('../../services/resolve-runtime-from-pd-config.js');
377
+ const result = resolveRuntimeWithOverrides(workspace, {});
378
+ // Missing config → defaults, which use openclaw.default as defaultRuntime
379
+ expect(result.configSource).toBe('.pd/config.yaml');
380
+ expect(result.runtimeProfileId).toBe('openclaw.default');
381
+ expect(typeof result.runtimeProfileLabel).toBe('string');
382
+ }
383
+ finally {
384
+ cleanupWorkspace(workspace);
385
+ }
386
+ });
387
+ });
388
+ //# sourceMappingURL=runtime-probe-config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-probe-config.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/runtime-probe-config.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":"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"}
@@ -1,3 +1,4 @@
1
+ import type { Command } from 'commander';
1
2
  interface RuntimeProbeOptions {
2
3
  runtime: string;
3
4
  openclawLocal?: boolean;
@@ -16,5 +17,10 @@ interface RuntimeProbeOptions {
16
17
  * pd runtime probe — dispatches to openclaw-cli, pi-ai, or config branch.
17
18
  */
18
19
  export declare function handleRuntimeProbe(opts: RuntimeProbeOptions): Promise<void>;
20
+ /**
21
+ * Register the `pd runtime probe` command on a Commander instance.
22
+ * Used by index.ts and tests to ensure real command wiring is verified (EP-04).
23
+ */
24
+ export declare function registerRuntimeProbeCommand(runtimeCmd: Command): Command;
19
25
  export {};
20
26
  //# sourceMappingURL=runtime.d.ts.map