@principles/pd-cli 1.128.1 → 1.129.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 (38) hide show
  1. package/dist/commands/mvp-smoke.js +1 -1
  2. package/dist/commands/mvp-smoke.js.map +1 -1
  3. package/dist/commands/rulecode.js +1 -1
  4. package/dist/commands/rulecode.js.map +1 -1
  5. package/dist/commands/runtime-internalization-run-rulehost.d.ts.map +1 -1
  6. package/dist/commands/runtime-internalization-run-rulehost.js +61 -7
  7. package/dist/commands/runtime-internalization-run-rulehost.js.map +1 -1
  8. package/dist/commands/runtime.js +1 -1
  9. package/dist/commands/runtime.js.map +1 -1
  10. package/dist/index.js +67 -34
  11. package/dist/index.js.map +1 -1
  12. package/dist/services/__tests__/rulehost-readiness.test.d.ts +2 -0
  13. package/dist/services/__tests__/rulehost-readiness.test.d.ts.map +1 -0
  14. package/dist/services/__tests__/rulehost-readiness.test.js +314 -0
  15. package/dist/services/__tests__/rulehost-readiness.test.js.map +1 -0
  16. package/dist/services/rulehost-readiness.d.ts +62 -0
  17. package/dist/services/rulehost-readiness.d.ts.map +1 -0
  18. package/dist/services/rulehost-readiness.js +214 -0
  19. package/dist/services/rulehost-readiness.js.map +1 -0
  20. package/package.json +1 -1
  21. package/src/commands/mvp-smoke.ts +1 -1
  22. package/src/commands/rulecode.ts +1 -1
  23. package/src/commands/runtime-internalization-run-rulehost.ts +68 -6
  24. package/src/commands/runtime.ts +1 -1
  25. package/src/index.ts +73 -36
  26. package/src/services/__tests__/rulehost-readiness.test.ts +366 -0
  27. package/src/services/rulehost-readiness.ts +326 -0
  28. package/tests/commands/cli-command-tree.test.ts +2 -2
  29. package/tests/commands/cli-help-snapshot.test.ts +135 -0
  30. package/tests/commands/cli-skill-contract.test.ts +121 -0
  31. package/tests/commands/run-rulehost-handler.test.ts +277 -0
  32. package/tests/commands/runtime-internalization.test.ts +2 -2
  33. package/tests/services/rulehost-pipeline-e2e.test.ts +71 -61
  34. package/dist/commands/central-sync.d.ts +0 -10
  35. package/dist/commands/central-sync.d.ts.map +0 -1
  36. package/dist/commands/central-sync.js +0 -32
  37. package/dist/commands/central-sync.js.map +0 -1
  38. package/src/commands/central-sync.ts +0 -44
@@ -144,7 +144,7 @@ export async function handleMvpSmoke(opts: MvpSmokeOptions): Promise<void> {
144
144
  */
145
145
  export function registerMvpCommands(program: Command): Command {
146
146
  const mvpCmd = program
147
- .command('mvp')
147
+ .command('mvp', { hidden: true })
148
148
  .description('MVP readiness commands');
149
149
 
150
150
  withWorkspaceAndJson(
@@ -381,7 +381,7 @@ export async function handleRulecodeReplay(opts: ReplayOptions): Promise<void> {
381
381
  */
382
382
  export function registerRulecodeCommand(parentCmd: Command): Command {
383
383
  const rulecodeCmd = parentCmd
384
- .command('rulecode')
384
+ .command('rulecode', { hidden: true })
385
385
  .description('RuleCode dialect spec, static validation, and sandbox replay (read-only)');
386
386
 
387
387
  // spec — no code input needed
@@ -38,6 +38,8 @@ import {
38
38
  } from '@principles/core/runtime-v2';
39
39
  import type { EffectivePdConfig, InternalAgentName, PDRuntimeAdapter } from '@principles/core/runtime-v2';
40
40
  import { resolveRuntimeFromPdConfig } from '../services/resolve-runtime-from-pd-config.js';
41
+ import { resolveRuleHostReadiness } from '../services/rulehost-readiness.js';
42
+ import type { RuleHostReadinessResult } from '../services/rulehost-readiness.js';
41
43
 
42
44
  export interface RunRuleHostOptions {
43
45
  workspace?: string;
@@ -109,6 +111,7 @@ function resolvePiAiAgentAdapter(
109
111
  function resolveRunRuleHostRuntime(
110
112
  workspaceDir: string,
111
113
  timeoutMs: number | undefined,
114
+ readiness: RuleHostReadinessResult,
112
115
  ): ResolvedRunRuleHostRuntime {
113
116
  const { configLoadResult } = resolveRuntimeFromPdConfig(workspaceDir);
114
117
 
@@ -126,6 +129,14 @@ function resolveRunRuleHostRuntime(
126
129
  philosopher: philosopher.profileId,
127
130
  scribe: scribe.profileId,
128
131
  };
132
+ if (readiness.status === 'text_principle_only') {
133
+ return {
134
+ agentAdapters: { dreamer: dreamer.adapter, philosopher: philosopher.adapter, scribe: scribe.adapter, evaluator: scribe.adapter },
135
+ agentRuntimeProfiles,
136
+ capability: { enabled: false, disabledReason: readiness.reason },
137
+ capabilityStatus: `code_rule_capability: OFF (${readiness.reason})`,
138
+ };
139
+ }
129
140
  const featureFlags = computeFeatureFlagsFromConfig(effective);
130
141
  if (!isFeatureEnabled(featureFlags, 'code_rule_capability')) {
131
142
  return {
@@ -234,16 +245,35 @@ function formatTextOutput(result: RuleHostPipelineResult): string {
234
245
  return lines.join('\n');
235
246
  }
236
247
 
237
- function formatDryRunOutput(opts: RunRuleHostOptions, capabilityStatus: string, workspaceDir: string): string {
248
+ interface DryRunFormatInput {
249
+ readonly opts: RunRuleHostOptions;
250
+ readonly capabilityStatus: string;
251
+ readonly workspaceDir: string;
252
+ readonly readiness: RuleHostReadinessResult;
253
+ }
254
+
255
+ function formatDryRunOutput(input: DryRunFormatInput): string {
256
+ const { opts, capabilityStatus, workspaceDir, readiness } = input;
238
257
  const lines: string[] = [];
239
258
  lines.push('RuleHost Pipeline (PRI-429) — DRY RUN');
240
259
  lines.push(`pain: ${opts.painId}`);
241
260
  lines.push(`workspace: ${workspaceDir}`);
242
261
  lines.push(`channel: ${opts.channel ?? 'code_tool_hook'}`);
262
+ lines.push(`readiness: ${readiness.status.toUpperCase()}`);
263
+ if (readiness.status !== 'ready') {
264
+ lines.push(` reason: ${readiness.reason}`);
265
+ lines.push(` nextAction: ${readiness.nextAction}`);
266
+ }
243
267
  lines.push(capabilityStatus);
244
268
  lines.push('');
245
269
  lines.push('No tasks created, no LLM calls made, no artifacts written.');
246
- lines.push('Next: pass --confirm to actually run the pipeline.');
270
+ if (readiness.status === 'ready') {
271
+ lines.push('Next: pass --confirm to actually run the pipeline.');
272
+ } else if (readiness.status === 'text_principle_only') {
273
+ lines.push('Next: pass --confirm to run in text-principle-only mode, or fix the issues above to enable full pipeline.');
274
+ } else {
275
+ lines.push('Next: fix the readiness issues above before running the pipeline.');
276
+ }
247
277
  return lines.join('\n');
248
278
  }
249
279
 
@@ -303,14 +333,40 @@ export async function handleRunRuleHost(opts: RunRuleHostOptions): Promise<void>
303
333
 
304
334
  const workspaceDir = resolveWorkspace(opts);
305
335
 
336
+ // ── Readiness check (PRI-461) ──
337
+ // Check all preconditions BEFORE constructing adapters. This produces a
338
+ // structured ready/text_principle_only/refused status instead of an opaque
339
+ // agent_runtime_resolution_failed error.
340
+ const readiness = resolveRuleHostReadiness(workspaceDir);
341
+
342
+ // If refused, emit structured error and exit (CLI gate rule 2 + rule 5).
343
+ // Refused means the pipeline cannot run at all — do NOT attempt adapter
344
+ // construction or pipeline execution.
345
+ if (readiness.status === 'refused') {
346
+ if (opts.json) {
347
+ process.stdout.write(JSON.stringify({
348
+ status: 'refused',
349
+ reason: readiness.reason,
350
+ nextAction: readiness.nextAction,
351
+ readiness,
352
+ }) + '\n');
353
+ } else {
354
+ console.error(`RuleHost readiness: REFUSED`);
355
+ console.error(` reason: ${readiness.reason}`);
356
+ console.error(` nextAction: ${readiness.nextAction}`);
357
+ }
358
+ process.exitCode = 1;
359
+ return;
360
+ }
361
+
306
362
  // ── Resolve each executed agent from canonical config ──
307
363
  let resolvedRuntime: ResolvedRunRuleHostRuntime;
308
364
  try {
309
- resolvedRuntime = resolveRunRuleHostRuntime(workspaceDir, opts.timeoutMs);
365
+ resolvedRuntime = resolveRunRuleHostRuntime(workspaceDir, opts.timeoutMs, readiness);
310
366
  } catch (err) {
311
367
  const message = err instanceof Error ? err.message : String(err);
312
368
  if (opts.json) {
313
- process.stdout.write(JSON.stringify({ status: 'failed', reason: 'agent_runtime_resolution_failed', message, nextAction: 'check internalAgents and runtimeProfiles in .pd/config.yaml; run pd config doctor' }) + '\n');
369
+ process.stdout.write(JSON.stringify({ status: 'failed', reason: 'agent_runtime_resolution_failed', message, nextAction: 'check internalAgents and runtimeProfiles in .pd/config.yaml; run pd config doctor', readiness }) + '\n');
314
370
  } else {
315
371
  console.error(`Error: ${message}`);
316
372
  }
@@ -328,13 +384,19 @@ export async function handleRunRuleHost(opts: RunRuleHostOptions): Promise<void>
328
384
  painId: opts.painId,
329
385
  workspace: workspaceDir,
330
386
  channel,
387
+ readiness,
388
+ readinessStatus: readiness.status,
331
389
  capabilityStatus: resolvedRuntime.capabilityStatus,
332
390
  agentRuntimeProfiles: resolvedRuntime.agentRuntimeProfiles,
333
391
  codeRuleCapability: { enabled: resolvedRuntime.capability.enabled, disabledReason: resolvedRuntime.capability.disabledReason },
334
- nextAction: 'pass --confirm to actually run the pipeline',
392
+ nextAction: readiness.status === 'ready'
393
+ ? 'pass --confirm to run the full pipeline'
394
+ : readiness.status === 'text_principle_only'
395
+ ? 'pass --confirm to run in text-principle-only mode (code-rule capability OFF), or fix the issues above to enable full pipeline'
396
+ : 'fix the readiness issues above before running the pipeline',
335
397
  }) + '\n');
336
398
  } else {
337
- process.stdout.write(formatDryRunOutput(opts, resolvedRuntime.capabilityStatus, workspaceDir) + '\n');
399
+ process.stdout.write(formatDryRunOutput({ opts, capabilityStatus: resolvedRuntime.capabilityStatus, workspaceDir, readiness }) + '\n');
338
400
  }
339
401
  return;
340
402
  }
@@ -453,7 +453,7 @@ export async function handleRuntimeProbe(opts: RuntimeProbeOptions): Promise<voi
453
453
  */
454
454
  export function registerRuntimeProbeCommand(runtimeCmd: Command): Command {
455
455
  return runtimeCmd
456
- .command('probe')
456
+ .command('probe', { hidden: true })
457
457
  .description('Probe runtime health and capabilities (HG-01 HARD GATE)')
458
458
  .requiredOption('-r, --runtime <kind>', "Runtime kind: 'openclaw-cli', 'pi-ai', or 'config'")
459
459
  .option('--openclaw-local', 'Use local OpenClaw (mutually exclusive with --openclaw-gateway)')
package/src/index.ts CHANGED
@@ -15,7 +15,6 @@ import { handleSamplesReview } from './commands/samples-review.js';
15
15
  import { handleEvolutionTasksList } from './commands/evolution-tasks-list.js';
16
16
  import { handleEvolutionTasksShow } from './commands/evolution-tasks-show.js';
17
17
  import { handleHealth } from './commands/health.js';
18
- import { handleCentralSync } from './commands/central-sync.js';
19
18
  import { handleTaskShow, registerTaskListCommand } from './commands/task.js';
20
19
  import { handleRunList, handleRunShow } from './commands/run.js';
21
20
  import { handleTrajectoryLocate } from './commands/trajectory.js';
@@ -117,7 +116,7 @@ painCmd
117
116
  });
118
117
 
119
118
  const samplesCmd = program
120
- .command('samples')
119
+ .command('samples', { hidden: true })
121
120
  .description('Correction sample management');
122
121
 
123
122
  samplesCmd
@@ -143,7 +142,7 @@ samplesCmd
143
142
  });
144
143
 
145
144
  const evolutionCmd = program
146
- .command('evolution')
145
+ .command('evolution', { hidden: true })
147
146
  .description('Evolution task management');
148
147
 
149
148
  const tasksCmd = evolutionCmd
@@ -178,17 +177,6 @@ program
178
177
  await handleHealth(opts);
179
178
  });
180
179
 
181
- const centralCmd = program
182
- .command('central')
183
- .description('Central server management');
184
-
185
- centralCmd
186
- .command('sync')
187
- .description('Trigger a sync cycle and report results')
188
- .action(async () => {
189
- await handleCentralSync();
190
- });
191
-
192
180
  // ── Runtime v2 task/run commands ──────────────────────────────────────────────鈹€鈹€鈹€鈹€鈹€鈹€
193
181
 
194
182
  const rtTaskCmd = program
@@ -207,7 +195,7 @@ rtTaskCmd
207
195
  });
208
196
 
209
197
  const rtRunCmd = program
210
- .command('run')
198
+ .command('run', { hidden: true })
211
199
  .description('Runtime v2 run inspection');
212
200
 
213
201
  rtRunCmd
@@ -227,7 +215,7 @@ rtRunCmd
227
215
  // ── Runtime v2 trajectory/history/context commands ────────────────────────────鈹€鈹€
228
216
 
229
217
  const trajectoryCmd = program
230
- .command('trajectory')
218
+ .command('trajectory', { hidden: true })
231
219
  .description('Runtime v2 trajectory location');
232
220
 
233
221
  trajectoryCmd
@@ -244,7 +232,7 @@ trajectoryCmd
244
232
  });
245
233
 
246
234
  const historyCmd = program
247
- .command('history')
235
+ .command('history', { hidden: true })
248
236
  .description('Runtime v2 history query');
249
237
 
250
238
  historyCmd
@@ -261,7 +249,7 @@ historyCmd
261
249
  });
262
250
 
263
251
  const contextCmd = program
264
- .command('context')
252
+ .command('context', { hidden: true })
265
253
  .description('Runtime v2 context assembly');
266
254
 
267
255
  contextCmd
@@ -276,7 +264,7 @@ contextCmd
276
264
  // ── Legacy import command ──────────────────────────────────────────────────────鈹€鈹€鈹€鈹€鈹€鈹€鈹€
277
265
 
278
266
  const legacyCmd = program
279
- .command('legacy')
267
+ .command('legacy', { hidden: true })
280
268
  .description('Legacy data management (import and cleanup)');
281
269
 
282
270
  const importCmd = legacyCmd.command('import');
@@ -337,7 +325,7 @@ const runtimeCmd = program
337
325
  .description('Runtime inspection and health checks');
338
326
 
339
327
  runtimeCmd
340
- .command('canary')
328
+ .command('canary', { hidden: true })
341
329
  .description('One-shot control plane health canary')
342
330
  .option('-w, --workspace <path>', 'Workspace directory')
343
331
  .option('--json', 'Output raw JSON')
@@ -346,7 +334,7 @@ runtimeCmd
346
334
  });
347
335
 
348
336
  const synthCmd = runtimeCmd
349
- .command('synthetic')
337
+ .command('synthetic', { hidden: true })
350
338
  .description('Synthetic workload baseline commands');
351
339
 
352
340
  synthCmd
@@ -402,6 +390,55 @@ runtimeCmd
402
390
  });
403
391
  });
404
392
 
393
+ // ── PRI-455: Promoted owner commands (trace + activation) ────────────────────
394
+ // These are promoted from runtime subcommands to top-level for discoverability.
395
+ // The old paths (pd runtime trace show, pd runtime activation list) remain as
396
+ // hidden aliases — they still work but are not shown in --help.
397
+
398
+ const traceTopCmd = program
399
+ .command('trace')
400
+ .description('Trace full pain-to-ledger chain (Story A\' Step 6: Observe)');
401
+
402
+ traceTopCmd
403
+ .command('show')
404
+ .description('Show full trace for a pain ID')
405
+ .requiredOption('--pain-id <id>', 'Pain ID to trace')
406
+ .option('-w, --workspace <path>', 'Workspace directory')
407
+ .option('--json', 'Output raw JSON')
408
+ .action(async (opts) => {
409
+ await handleTraceShow({ painId: opts.painId, workspace: opts.workspace, json: opts.json });
410
+ });
411
+
412
+ const activationTopCmd = program
413
+ .command('activation')
414
+ .description('Activation management — list active activations, deactivate (Story A\' Steps 5-6)');
415
+
416
+ activationTopCmd
417
+ .command('list')
418
+ .description('List all activations for a workspace')
419
+ .option('-w, --workspace <path>', 'Workspace directory')
420
+ .option('-c, --channel <channel>', 'Filter by channel (prompt|code_tool_hook)')
421
+ .option('--include-deactivated', 'Include deactivated records in output')
422
+ .option('--json', 'Output raw JSON')
423
+ .action(async (opts) => {
424
+ await handleRuntimeActivationList({
425
+ workspace: opts.workspace,
426
+ channel: opts.channel,
427
+ includeDeactivated: opts.includeDeactivated,
428
+ json: opts.json,
429
+ });
430
+ });
431
+
432
+ activationTopCmd
433
+ .command('deactivate')
434
+ .description('Deactivate an activation by activation ID')
435
+ .requiredOption('--activation-id <id>', 'Activation ID to deactivate')
436
+ .option('-w, --workspace <path>', 'Workspace directory')
437
+ .option('--json', 'Output raw JSON')
438
+ .action(async (opts) => {
439
+ await handleRuntimeActivationDeactivate({ activationId: opts.activationId, workspace: opts.workspace, json: opts.json });
440
+ });
441
+
405
442
  const configCmd = program
406
443
  .command('config')
407
444
  .description('PD configuration discovery and diagnosis');
@@ -416,7 +453,7 @@ configCmd
416
453
  });
417
454
 
418
455
  const demoCmd = program
419
- .command('demo')
456
+ .command('demo', { hidden: true })
420
457
  .description('Demo scenarios for MVP validation');
421
458
 
422
459
  demoCmd
@@ -436,7 +473,7 @@ demoCmd
436
473
  registerRuntimeProbeCommand(runtimeCmd);
437
474
 
438
475
  const flowCmd = runtimeCmd
439
- .command('flow')
476
+ .command('flow', { hidden: true })
440
477
  .description('Workflow funnel inspection');
441
478
 
442
479
  flowCmd
@@ -449,8 +486,8 @@ flowCmd
449
486
  });
450
487
 
451
488
  const traceCmd = runtimeCmd
452
- .command('trace')
453
- .description('Trace full pain-to-ledger chain');
489
+ .command('trace', { hidden: true })
490
+ .description('Trace full pain-to-ledger chain (hidden alias — use pd trace show)');
454
491
 
455
492
  traceCmd
456
493
  .command('show')
@@ -463,7 +500,7 @@ traceCmd
463
500
  });
464
501
 
465
502
  runtimeCmd
466
- .command('uat')
503
+ .command('uat', { hidden: true })
467
504
  .description('Runtime V2 chain UAT baseline runner')
468
505
  .option('-w, --workspace <path>', 'Workspace directory')
469
506
  .option('--count <n>', 'Number of iterations (default: 5, max: 50)', parseInt)
@@ -481,7 +518,7 @@ runtimeCmd
481
518
  });
482
519
 
483
520
  const runtimeHealthCmd = runtimeCmd
484
- .command('health')
521
+ .command('health', { hidden: true })
485
522
  .description('Runtime V2 health inspection');
486
523
 
487
524
  runtimeHealthCmd
@@ -503,7 +540,7 @@ runtimeHealthCmd
503
540
  });
504
541
 
505
542
  const internalizationCmd = runtimeCmd
506
- .command('internalization')
543
+ .command('internalization', { hidden: true })
507
544
  .description('Internalization Engine operator visibility');
508
545
 
509
546
  internalizationCmd
@@ -573,8 +610,8 @@ internalizationCmd
573
610
  });
574
611
 
575
612
  const activationCmd = runtimeCmd
576
- .command('activation')
577
- .description('Activation dispatch operations');
613
+ .command('activation', { hidden: true })
614
+ .description('Activation dispatch operations (hidden — use pd activation for list/deactivate)');
578
615
 
579
616
  activationCmd
580
617
  .command('dispatch')
@@ -652,11 +689,11 @@ activationCmd
652
689
  });
653
690
 
654
691
  const diagnosticsCmd = runtimeCmd
655
- .command('diagnostics')
692
+ .command('diagnostics', { hidden: true })
656
693
  .description('Control plane diagnostic bundle operations');
657
694
 
658
695
  const recoveryCmd = runtimeCmd
659
- .command('recovery')
696
+ .command('recovery', { hidden: true })
660
697
  .description('Runtime V2 lease recovery operations');
661
698
 
662
699
  recoveryCmd
@@ -699,7 +736,7 @@ diagnosticsCmd
699
736
  });
700
737
 
701
738
  const pruningCmd = runtimeCmd
702
- .command('pruning')
739
+ .command('pruning', { hidden: true })
703
740
  .description('Non-destructive pruning metrics and health signals');
704
741
 
705
742
  pruningCmd
@@ -882,7 +919,7 @@ candidateInternalizationCmd
882
919
  // ── Artifact inspection commands ──────────────────────────────────────────────
883
920
 
884
921
  const artifactCmd = program
885
- .command('artifact')
922
+ .command('artifact', { hidden: true })
886
923
  .description('Artifact registry inspection');
887
924
 
888
925
  artifactCmd
@@ -936,7 +973,7 @@ registerRulecodeCommand(program);
936
973
 
937
974
  const consoleCmd = program
938
975
  .command('console')
939
- .description('Start the pd-console web UI for principle review (default: legacy launcher)')
976
+ .description('Start the pd-console web UI for principle review (default: fallback launcher)')
940
977
  .passThroughOptions()
941
978
  .option('-w, --workspace <path>', 'Workspace directory')
942
979
  .option('-p, --port <port>', 'Port to listen on', '3100')
@@ -998,7 +1035,7 @@ consoleCmd.action(async (opts) => {
998
1035
  // ─── Quality Scorecard (PRI-361) ──────────────────────────────────
999
1036
 
1000
1037
  const qualityCmd = program
1001
- .command('quality')
1038
+ .command('quality', { hidden: true })
1002
1039
  .description('Quality scoring and evaluation');
1003
1040
 
1004
1041
  qualityCmd