@principles/pd-cli 1.73.2 → 1.75.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/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
- * pd CLI Principles Disciple command-line interface.
3
+ * pd CLI 鈥?Principles Disciple command-line interface.
4
4
  *
5
5
  * Usage:
6
6
  * pd pain record --reason <text> [--score N] [--source manual]
@@ -46,6 +46,7 @@ import { handleRuntimeActivationDispatch } from './commands/runtime-activation.j
46
46
  import { handleProvenChannelBaseline } from './commands/proven-channel-baseline.js';
47
47
  import { handleDemoStoryA } from './commands/demo-story-a.js';
48
48
  import { handleRuntimeFeaturesStatus } from './commands/runtime-features.js';
49
+ import { handleConfigDoctor } from './commands/config-doctor.js';
49
50
 
50
51
  import { createRequire } from 'module';
51
52
  const require = createRequire(import.meta.url);
@@ -56,7 +57,8 @@ const program = new Command();
56
57
  program
57
58
  .name('pd')
58
59
  .description('PD CLI — Pain recording, sample management, and evolution tasks')
59
- .version(pkg.version);
60
+ .version(pkg.version)
61
+ .enablePositionalOptions();
60
62
 
61
63
  const painCmd = program
62
64
  .command('pain')
@@ -147,7 +149,7 @@ centralCmd
147
149
  await handleCentralSync();
148
150
  });
149
151
 
150
- // ── Runtime v2 task/run commands ──────────────────────────────────────────────
152
+ // 鈹€鈹€ Runtime v2 task/run commands 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
151
153
 
152
154
  const rtTaskCmd = program
153
155
  .command('task')
@@ -190,7 +192,7 @@ rtRunCmd
190
192
  await handleRunShow({ id: runId });
191
193
  });
192
194
 
193
- // ── Runtime v2 trajectory/history/context commands ───────────────────────────
195
+ // 鈹€鈹€ Runtime v2 trajectory/history/context commands 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
194
196
 
195
197
  const trajectoryCmd = program
196
198
  .command('trajectory')
@@ -239,7 +241,7 @@ contextCmd
239
241
  await handleContextBuild(taskId, opts);
240
242
  });
241
243
 
242
- // ── Legacy import command ───────────────────────────────────────────────────────
244
+ // 鈹€鈹€ Legacy import command 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
243
245
 
244
246
  const legacyCmd = program
245
247
  .command('legacy')
@@ -258,7 +260,7 @@ importCmd
258
260
  await handleLegacyImportOpenClaw(opts);
259
261
  });
260
262
 
261
- // ── Diagnostician run/status commands ─────────────────────────────────────
263
+ // 鈹€鈹€ Diagnostician run/status commands 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
262
264
 
263
265
  const diagnoseCmd = program
264
266
  .command('diagnose')
@@ -283,19 +285,19 @@ diagnoseCmd
283
285
  .option('--openclaw-local', 'Use local OpenClaw (mutually exclusive with --openclaw-gateway)')
284
286
  .option('--openclaw-gateway', 'Use gateway OpenClaw (mutually exclusive with --openclaw-local)')
285
287
  .option('-a, --agent <agentId>', 'Agent ID to invoke')
286
- .option('--provider <name>', 'LLM provider (e.g., openrouter) for pi-ai, falls back to policy')
287
- .option('--model <id>', 'Model ID (e.g., anthropic/claude-sonnet-4) for pi-ai, falls back to policy')
288
- .option('--apiKeyEnv <name>', 'Env var name for API key for pi-ai, falls back to policy')
289
- .option('--baseUrl <url>', 'Custom base URL for pi-ai, falls back to policy')
290
- .option('--maxRetries <n>', 'Max retry attempts for LLM failures for pi-ai, falls back to policy', parseInt)
291
- .option('--timeoutMs <ms>', 'Timeout in milliseconds for pi-ai, falls back to policy', parseInt)
288
+ .option('--provider <name>', 'LLM provider (e.g., openrouter) 鈥?for pi-ai, falls back to policy')
289
+ .option('--model <id>', 'Model ID (e.g., anthropic/claude-sonnet-4) 鈥?for pi-ai, falls back to policy')
290
+ .option('--apiKeyEnv <name>', 'Env var name for API key 鈥?for pi-ai, falls back to policy')
291
+ .option('--baseUrl <url>', 'Custom base URL 鈥?for pi-ai, falls back to policy')
292
+ .option('--maxRetries <n>', 'Max retry attempts for LLM failures 鈥?for pi-ai, falls back to policy', parseInt)
293
+ .option('--timeoutMs <ms>', 'Timeout in milliseconds 鈥?for pi-ai, falls back to policy', parseInt)
292
294
  .option('--no-intake', 'Skip candidate intake after successful diagnosis')
293
295
  .option('--json', 'Output raw JSON')
294
296
  .action(async (opts) => {
295
297
  await handleDiagnoseRun(opts);
296
298
  });
297
299
 
298
- // ── Runtime probe command (HG-01 HARD GATE) ─────────────────────────────────
300
+ // 鈹€鈹€ Runtime probe command (HG-01 HARD GATE) 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
299
301
 
300
302
  const runtimeCmd = program
301
303
  .command('runtime')
@@ -316,7 +318,7 @@ const synthCmd = runtimeCmd
316
318
 
317
319
  synthCmd
318
320
  .command('baseline')
319
- .description('Run synthetic PD workload baseline (PRI-206) deterministic, no LLM required')
321
+ .description('Run synthetic PD workload baseline (PRI-206) 鈥?deterministic, no LLM required')
320
322
  .option('-w, --workspace <path>', 'Workspace directory (default: temp workspace)')
321
323
  .option('--json', 'Output raw JSON')
322
324
  .action(async (opts) => {
@@ -325,7 +327,7 @@ synthCmd
325
327
 
326
328
  synthCmd
327
329
  .command('flood')
328
- .description('Run pain flood simulation (PRI-208) deterministic dedup/stress test, no LLM required')
330
+ .description('Run pain flood simulation (PRI-208) 鈥?deterministic dedup/stress test, no LLM required')
329
331
  .option('-w, --workspace <path>', 'Workspace directory (default: temp workspace)')
330
332
  .option('--json', 'Output raw JSON')
331
333
  .option('--identical-count <n>', 'Number of identical pain signals (default: 10)', parseInt)
@@ -343,7 +345,7 @@ synthCmd
343
345
 
344
346
  synthCmd
345
347
  .command('proven-channel')
346
- .description('Run MVP activation continuity baseline (PRI-240) deterministic, no LLM required')
348
+ .description('Run MVP activation continuity baseline (PRI-240) 鈥?deterministic, no LLM required')
347
349
  .option('-w, --workspace <path>', 'Workspace directory (default: temp workspace)')
348
350
  .option('--json', 'Output raw JSON')
349
351
  .option('--channels <channels>', 'Comma-separated channel list (prompt,code_tool_hook,defer_archive)')
@@ -367,13 +369,26 @@ runtimeCmd
367
369
  });
368
370
  });
369
371
 
372
+ const configCmd = program
373
+ .command('config')
374
+ .description('PD configuration discovery and diagnosis');
375
+
376
+ configCmd
377
+ .command('doctor')
378
+ .description('Show PD + OpenClaw config locations, feature flags, and provider connectivity (PRI-299)')
379
+ .option('-w, --workspace <path>', 'Workspace directory')
380
+ .option('--json', 'Output raw JSON')
381
+ .action(async (opts) => {
382
+ await handleConfigDoctor({ workspace: opts.workspace, json: opts.json });
383
+ });
384
+
370
385
  const demoCmd = program
371
386
  .command('demo')
372
387
  .description('Demo scenarios for MVP validation');
373
388
 
374
389
  demoCmd
375
390
  .command('story-a')
376
- .description('Run Story A\' proven-channel demo (PRI-246) full evidence→proposal→approval→activation→observation chain')
391
+ .description('Run Story A\' proven-channel demo (PRI-246) 鈥?full evidence鈫抪roposal鈫抋pproval鈫抋ctivation鈫抩bservation chain')
377
392
  .option('-w, --workspace <path>', 'Workspace directory (default: temp workspace)')
378
393
  .option('--json', 'Output raw JSON')
379
394
  .option('--channels <channels>', 'Comma-separated channel list (prompt,code_tool_hook,defer_archive)')
@@ -392,13 +407,13 @@ runtimeCmd
392
407
  .option('--openclaw-local', 'Use local OpenClaw (mutually exclusive with --openclaw-gateway)')
393
408
  .option('--openclaw-gateway', 'Use gateway OpenClaw (mutually exclusive with --openclaw-local)')
394
409
  .option('-a, --agent <agentId>', 'Agent ID to probe')
395
- .option('--provider <name>', 'LLM provider (e.g., openrouter) for pi-ai, falls back to --workspace workflows.yaml')
396
- .option('--model <id>', 'Model ID (e.g., anthropic/claude-sonnet-4) for pi-ai, falls back to --workspace workflows.yaml')
397
- .option('--apiKeyEnv <name>', 'Env var name for API key (e.g., OPENROUTER_API_KEY) for pi-ai, falls back to --workspace workflows.yaml')
398
- .option('--baseUrl <url>', 'Custom base URL for OpenAI-compatible providers for pi-ai, falls back to --workspace workflows.yaml')
410
+ .option('--provider <name>', 'LLM provider (e.g., openrouter) 鈥?for pi-ai, falls back to --workspace workflows.yaml')
411
+ .option('--model <id>', 'Model ID (e.g., anthropic/claude-sonnet-4) 鈥?for pi-ai, falls back to --workspace workflows.yaml')
412
+ .option('--apiKeyEnv <name>', 'Env var name for API key (e.g., OPENROUTER_API_KEY) 鈥?for pi-ai, falls back to --workspace workflows.yaml')
413
+ .option('--baseUrl <url>', 'Custom base URL for OpenAI-compatible providers 鈥?for pi-ai, falls back to --workspace workflows.yaml')
399
414
  .option('--maxRetries <n>', 'Max retry attempts for LLM failures', parseInt)
400
415
  .option('--timeoutMs <ms>', 'Timeout in milliseconds for probe', parseInt)
401
- .option('-w, --workspace <path>', 'Workspace directory loads pi-ai policy from .state/workflows.yaml')
416
+ .option('-w, --workspace <path>', 'Workspace directory 鈥?loads pi-ai policy from .state/workflows.yaml')
402
417
  .option('--json', 'Output raw JSON')
403
418
  .action(async (opts) => {
404
419
  await handleRuntimeProbe(opts);
@@ -462,17 +477,17 @@ runtimeHealthCmd
462
477
 
463
478
  runtimeHealthCmd
464
479
  .command('gfi')
465
- .description('GFI workspace snapshot active vs stale session breakdown')
480
+ .description('GFI workspace snapshot 鈥?active vs stale session breakdown')
466
481
  .option('-w, --workspace <path>', 'Workspace directory')
467
482
  .option('--json', 'Output raw JSON')
468
483
  .action(async (opts) => {
469
484
  await handleRuntimeGfiSnapshot({ workspace: opts.workspace, json: opts.json });
470
485
  });
471
486
 
472
- // PRI-82: pd runtime gfi snapshot canonical operator command (alias of runtime health gfi)
487
+ // PRI-82: pd runtime gfi snapshot 鈥?canonical operator command (alias of runtime health gfi)
473
488
  runtimeCmd
474
489
  .command('gfi')
475
- .description('GFI workspace snapshot active vs stale session breakdown')
490
+ .description('GFI workspace snapshot 鈥?active vs stale session breakdown')
476
491
  .command('snapshot')
477
492
  .description('GFI workspace snapshot for the operator (alias: pd runtime health gfi)')
478
493
  .option('-w, --workspace <path>', 'Workspace directory')
@@ -608,7 +623,7 @@ const pruningCmd = runtimeCmd
608
623
 
609
624
  pruningCmd
610
625
  .command('report')
611
- .description('Show pruning health report watch/review principle signals')
626
+ .description('Show pruning health report 鈥?watch/review principle signals')
612
627
  .option('-w, --workspace <path>', 'Workspace directory')
613
628
  .option('--json', 'Output raw JSON')
614
629
  .action((opts) => {
@@ -679,7 +694,7 @@ pruningCmd
679
694
  });
680
695
  });
681
696
 
682
- // ── Candidate inspection commands ───────────────────────────────────────────
697
+ // 鈹€鈹€ Candidate inspection commands 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
683
698
 
684
699
  const candidateCmd = program
685
700
  .command('candidate')
@@ -783,7 +798,7 @@ candidateInternalizationCmd
783
798
  await handleCandidateInternalizationBackfill({ workspace: opts.workspace, dryRun: opts.dryRun, confirm: opts.confirm, includePending: opts.includePending, json: opts.json });
784
799
  });
785
800
 
786
- // ── Artifact inspection commands ────────────────────────────────────────────
801
+ // 鈹€鈹€ Artifact inspection commands 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
787
802
 
788
803
  const artifactCmd = program
789
804
  .command('artifact')
@@ -813,9 +828,18 @@ const _legacyCleanupCmd = legacyCmd
813
828
  await handleLegacyCleanup(opts.workspace, apply);
814
829
  });
815
830
 
816
- program
831
+ const consoleCmd = program
817
832
  .command('console')
818
- .description('Start the pd-console web UI for principle review')
833
+ .description('Start the pd-console web UI for principle review (default: legacy launcher)')
834
+ .passThroughOptions()
835
+ .option('-w, --workspace <path>', 'Workspace directory')
836
+ .option('-p, --port <port>', 'Port to listen on', '3100')
837
+ .option('--no-auth', 'Disable authentication (local dev only)', false)
838
+ .option('--json', 'Output JSON status', false);
839
+
840
+ consoleCmd
841
+ .command('start')
842
+ .description('Legacy launcher — start the pd-console on the requested port (no reuse, no browser open)')
819
843
  .option('-w, --workspace <path>', 'Workspace directory')
820
844
  .option('-p, --port <port>', 'Port to listen on', '3100')
821
845
  .option('--no-auth', 'Disable authentication (local dev only)', false)
@@ -825,9 +849,42 @@ program
825
849
  await handleConsole({
826
850
  workspace: opts.workspace,
827
851
  port: opts.port,
828
- noAuth: opts.noAuth,
852
+ noAuth: opts.auth === false,
829
853
  json: opts.json,
830
854
  });
831
855
  });
832
856
 
857
+ // PRI-300: seed-friendly Console launcher with reuse + auto-port + browser open
858
+ consoleCmd
859
+ .command('open')
860
+ .description('Open the pd-console in your browser (PRI-300) — auto-port, reuses running console, loopback-only')
861
+ .option('-w, --workspace <path>', 'Workspace directory')
862
+ .option('-p, --port <port>', 'Preferred port (default 3100; auto-falls back to next free port)')
863
+ .option('--host <host>', 'Loopback host (default 127.0.0.1; non-loopback refused)')
864
+ .option('--no-auth', 'Disable authentication (local dev only)', false)
865
+ .option('--no-browser', 'Do not open the system browser on success', false)
866
+ .option('--json', 'Output JSON status (suppresses browser open)', false)
867
+ .action(async (opts) => {
868
+ const { handleConsoleOpen } = await import('./commands/console.js');
869
+ await handleConsoleOpen({
870
+ workspace: opts.workspace,
871
+ port: opts.port,
872
+ host: opts.host,
873
+ noAuth: opts.auth === false,
874
+ noBrowser: opts.browser === false,
875
+ json: opts.json,
876
+ });
877
+ });
878
+
879
+ // Default `pd console` → legacy launcher (backward compat)
880
+ consoleCmd.action(async (opts) => {
881
+ const { handleConsole } = await import('./commands/console.js');
882
+ await handleConsole({
883
+ workspace: opts.workspace,
884
+ port: opts.port,
885
+ noAuth: opts.auth === false,
886
+ json: opts.json,
887
+ });
888
+ });
889
+
833
890
  program.parse();