@principles/pd-cli 1.73.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 (298) hide show
  1. package/README.md +90 -0
  2. package/dist/commands/artifact.d.ts +14 -0
  3. package/dist/commands/artifact.d.ts.map +1 -0
  4. package/dist/commands/artifact.js +67 -0
  5. package/dist/commands/artifact.js.map +1 -0
  6. package/dist/commands/candidate.d.ts +83 -0
  7. package/dist/commands/candidate.d.ts.map +1 -0
  8. package/dist/commands/candidate.js +891 -0
  9. package/dist/commands/candidate.js.map +1 -0
  10. package/dist/commands/central-sync.d.ts +10 -0
  11. package/dist/commands/central-sync.d.ts.map +1 -0
  12. package/dist/commands/central-sync.js +32 -0
  13. package/dist/commands/central-sync.js.map +1 -0
  14. package/dist/commands/console.d.ts +9 -0
  15. package/dist/commands/console.d.ts.map +1 -0
  16. package/dist/commands/console.js +114 -0
  17. package/dist/commands/console.js.map +1 -0
  18. package/dist/commands/context.d.ts +7 -0
  19. package/dist/commands/context.d.ts.map +1 -0
  20. package/dist/commands/context.js +55 -0
  21. package/dist/commands/context.js.map +1 -0
  22. package/dist/commands/demo-story-a.d.ts +12 -0
  23. package/dist/commands/demo-story-a.d.ts.map +1 -0
  24. package/dist/commands/demo-story-a.js +175 -0
  25. package/dist/commands/demo-story-a.js.map +1 -0
  26. package/dist/commands/diagnose.d.ts +35 -0
  27. package/dist/commands/diagnose.d.ts.map +1 -0
  28. package/dist/commands/diagnose.js +390 -0
  29. package/dist/commands/diagnose.js.map +1 -0
  30. package/dist/commands/evolution-tasks-list.d.ts +15 -0
  31. package/dist/commands/evolution-tasks-list.d.ts.map +1 -0
  32. package/dist/commands/evolution-tasks-list.js +34 -0
  33. package/dist/commands/evolution-tasks-list.js.map +1 -0
  34. package/dist/commands/evolution-tasks-show.d.ts +14 -0
  35. package/dist/commands/evolution-tasks-show.d.ts.map +1 -0
  36. package/dist/commands/evolution-tasks-show.js +52 -0
  37. package/dist/commands/evolution-tasks-show.js.map +1 -0
  38. package/dist/commands/flow.d.ts +7 -0
  39. package/dist/commands/flow.d.ts.map +1 -0
  40. package/dist/commands/flow.js +57 -0
  41. package/dist/commands/flow.js.map +1 -0
  42. package/dist/commands/health.d.ts +16 -0
  43. package/dist/commands/health.d.ts.map +1 -0
  44. package/dist/commands/health.js +150 -0
  45. package/dist/commands/health.js.map +1 -0
  46. package/dist/commands/history.d.ts +11 -0
  47. package/dist/commands/history.d.ts.map +1 -0
  48. package/dist/commands/history.js +50 -0
  49. package/dist/commands/history.js.map +1 -0
  50. package/dist/commands/legacy-cleanup.d.ts +27 -0
  51. package/dist/commands/legacy-cleanup.d.ts.map +1 -0
  52. package/dist/commands/legacy-cleanup.js +171 -0
  53. package/dist/commands/legacy-cleanup.js.map +1 -0
  54. package/dist/commands/legacy-import.d.ts +7 -0
  55. package/dist/commands/legacy-import.d.ts.map +1 -0
  56. package/dist/commands/legacy-import.js +86 -0
  57. package/dist/commands/legacy-import.js.map +1 -0
  58. package/dist/commands/pain-record.d.ts +10 -0
  59. package/dist/commands/pain-record.d.ts.map +1 -0
  60. package/dist/commands/pain-record.js +162 -0
  61. package/dist/commands/pain-record.js.map +1 -0
  62. package/dist/commands/proven-channel-baseline.d.ts +12 -0
  63. package/dist/commands/proven-channel-baseline.d.ts.map +1 -0
  64. package/dist/commands/proven-channel-baseline.js +97 -0
  65. package/dist/commands/proven-channel-baseline.js.map +1 -0
  66. package/dist/commands/remediation-output.d.ts +40 -0
  67. package/dist/commands/remediation-output.d.ts.map +1 -0
  68. package/dist/commands/remediation-output.js +23 -0
  69. package/dist/commands/remediation-output.js.map +1 -0
  70. package/dist/commands/run.d.ts +10 -0
  71. package/dist/commands/run.d.ts.map +1 -0
  72. package/dist/commands/run.js +68 -0
  73. package/dist/commands/run.js.map +1 -0
  74. package/dist/commands/runtime-activation.d.ts +11 -0
  75. package/dist/commands/runtime-activation.d.ts.map +1 -0
  76. package/dist/commands/runtime-activation.js +150 -0
  77. package/dist/commands/runtime-activation.js.map +1 -0
  78. package/dist/commands/runtime-canary.d.ts +30 -0
  79. package/dist/commands/runtime-canary.d.ts.map +1 -0
  80. package/dist/commands/runtime-canary.js +343 -0
  81. package/dist/commands/runtime-canary.js.map +1 -0
  82. package/dist/commands/runtime-diagnostics-export.d.ts +20 -0
  83. package/dist/commands/runtime-diagnostics-export.d.ts.map +1 -0
  84. package/dist/commands/runtime-diagnostics-export.js +177 -0
  85. package/dist/commands/runtime-diagnostics-export.js.map +1 -0
  86. package/dist/commands/runtime-features.d.ts +26 -0
  87. package/dist/commands/runtime-features.d.ts.map +1 -0
  88. package/dist/commands/runtime-features.js +70 -0
  89. package/dist/commands/runtime-features.js.map +1 -0
  90. package/dist/commands/runtime-gfi-snapshot.d.ts +7 -0
  91. package/dist/commands/runtime-gfi-snapshot.d.ts.map +1 -0
  92. package/dist/commands/runtime-gfi-snapshot.js +101 -0
  93. package/dist/commands/runtime-gfi-snapshot.js.map +1 -0
  94. package/dist/commands/runtime-health-snapshot.d.ts +7 -0
  95. package/dist/commands/runtime-health-snapshot.d.ts.map +1 -0
  96. package/dist/commands/runtime-health-snapshot.js +93 -0
  97. package/dist/commands/runtime-health-snapshot.js.map +1 -0
  98. package/dist/commands/runtime-idle-trigger.d.ts +12 -0
  99. package/dist/commands/runtime-idle-trigger.d.ts.map +1 -0
  100. package/dist/commands/runtime-idle-trigger.js +102 -0
  101. package/dist/commands/runtime-idle-trigger.js.map +1 -0
  102. package/dist/commands/runtime-internalization-enqueue-successors.d.ts +9 -0
  103. package/dist/commands/runtime-internalization-enqueue-successors.d.ts.map +1 -0
  104. package/dist/commands/runtime-internalization-enqueue-successors.js +393 -0
  105. package/dist/commands/runtime-internalization-enqueue-successors.js.map +1 -0
  106. package/dist/commands/runtime-internalization-integrity-repair.d.ts +9 -0
  107. package/dist/commands/runtime-internalization-integrity-repair.d.ts.map +1 -0
  108. package/dist/commands/runtime-internalization-integrity-repair.js +54 -0
  109. package/dist/commands/runtime-internalization-integrity-repair.js.map +1 -0
  110. package/dist/commands/runtime-internalization-integrity.d.ts +7 -0
  111. package/dist/commands/runtime-internalization-integrity.d.ts.map +1 -0
  112. package/dist/commands/runtime-internalization-integrity.js +53 -0
  113. package/dist/commands/runtime-internalization-integrity.js.map +1 -0
  114. package/dist/commands/runtime-internalization-queue.d.ts +7 -0
  115. package/dist/commands/runtime-internalization-queue.d.ts.map +1 -0
  116. package/dist/commands/runtime-internalization-queue.js +85 -0
  117. package/dist/commands/runtime-internalization-queue.js.map +1 -0
  118. package/dist/commands/runtime-internalization-run-once.d.ts +12 -0
  119. package/dist/commands/runtime-internalization-run-once.d.ts.map +1 -0
  120. package/dist/commands/runtime-internalization-run-once.js +546 -0
  121. package/dist/commands/runtime-internalization-run-once.js.map +1 -0
  122. package/dist/commands/runtime-internalization-wake-once.d.ts +8 -0
  123. package/dist/commands/runtime-internalization-wake-once.d.ts.map +1 -0
  124. package/dist/commands/runtime-internalization-wake-once.js +72 -0
  125. package/dist/commands/runtime-internalization-wake-once.js.map +1 -0
  126. package/dist/commands/runtime-pain-flood-simulation.d.ts +10 -0
  127. package/dist/commands/runtime-pain-flood-simulation.d.ts.map +1 -0
  128. package/dist/commands/runtime-pain-flood-simulation.js +104 -0
  129. package/dist/commands/runtime-pain-flood-simulation.js.map +1 -0
  130. package/dist/commands/runtime-pruning.d.ts +45 -0
  131. package/dist/commands/runtime-pruning.d.ts.map +1 -0
  132. package/dist/commands/runtime-pruning.js +355 -0
  133. package/dist/commands/runtime-pruning.js.map +1 -0
  134. package/dist/commands/runtime-recovery.d.ts +9 -0
  135. package/dist/commands/runtime-recovery.d.ts.map +1 -0
  136. package/dist/commands/runtime-recovery.js +94 -0
  137. package/dist/commands/runtime-recovery.js.map +1 -0
  138. package/dist/commands/runtime-synthetic-baseline.d.ts +7 -0
  139. package/dist/commands/runtime-synthetic-baseline.d.ts.map +1 -0
  140. package/dist/commands/runtime-synthetic-baseline.js +59 -0
  141. package/dist/commands/runtime-synthetic-baseline.js.map +1 -0
  142. package/dist/commands/runtime-uat.d.ts +52 -0
  143. package/dist/commands/runtime-uat.d.ts.map +1 -0
  144. package/dist/commands/runtime-uat.js +274 -0
  145. package/dist/commands/runtime-uat.js.map +1 -0
  146. package/dist/commands/runtime.d.ts +20 -0
  147. package/dist/commands/runtime.d.ts.map +1 -0
  148. package/dist/commands/runtime.js +256 -0
  149. package/dist/commands/runtime.js.map +1 -0
  150. package/dist/commands/samples-list.d.ts +11 -0
  151. package/dist/commands/samples-list.d.ts.map +1 -0
  152. package/dist/commands/samples-list.js +37 -0
  153. package/dist/commands/samples-list.js.map +1 -0
  154. package/dist/commands/samples-review.d.ts +14 -0
  155. package/dist/commands/samples-review.d.ts.map +1 -0
  156. package/dist/commands/samples-review.js +22 -0
  157. package/dist/commands/samples-review.js.map +1 -0
  158. package/dist/commands/task.d.ts +14 -0
  159. package/dist/commands/task.d.ts.map +1 -0
  160. package/dist/commands/task.js +92 -0
  161. package/dist/commands/task.js.map +1 -0
  162. package/dist/commands/trace.d.ts +19 -0
  163. package/dist/commands/trace.d.ts.map +1 -0
  164. package/dist/commands/trace.js +154 -0
  165. package/dist/commands/trace.js.map +1 -0
  166. package/dist/commands/trajectory.d.ts +11 -0
  167. package/dist/commands/trajectory.d.ts.map +1 -0
  168. package/dist/commands/trajectory.js +47 -0
  169. package/dist/commands/trajectory.js.map +1 -0
  170. package/dist/index.d.ts +9 -0
  171. package/dist/index.d.ts.map +1 -0
  172. package/dist/index.js +736 -0
  173. package/dist/index.js.map +1 -0
  174. package/dist/legacy/legacy-import.d.ts +15 -0
  175. package/dist/legacy/legacy-import.d.ts.map +1 -0
  176. package/dist/legacy/legacy-import.js +141 -0
  177. package/dist/legacy/legacy-import.js.map +1 -0
  178. package/dist/legacy/session-history-import.d.ts +26 -0
  179. package/dist/legacy/session-history-import.d.ts.map +1 -0
  180. package/dist/legacy/session-history-import.js +151 -0
  181. package/dist/legacy/session-history-import.js.map +1 -0
  182. package/dist/principle-tree-ledger-adapter.d.ts +12 -0
  183. package/dist/principle-tree-ledger-adapter.d.ts.map +1 -0
  184. package/dist/principle-tree-ledger-adapter.js +12 -0
  185. package/dist/principle-tree-ledger-adapter.js.map +1 -0
  186. package/dist/resolve-workspace.d.ts +12 -0
  187. package/dist/resolve-workspace.d.ts.map +1 -0
  188. package/dist/resolve-workspace.js +20 -0
  189. package/dist/resolve-workspace.js.map +1 -0
  190. package/dist/services/demo-story-a-runner.d.ts +8 -0
  191. package/dist/services/demo-story-a-runner.d.ts.map +1 -0
  192. package/dist/services/demo-story-a-runner.js +369 -0
  193. package/dist/services/demo-story-a-runner.js.map +1 -0
  194. package/dist/services/feature-flag-loader.d.ts +6 -0
  195. package/dist/services/feature-flag-loader.d.ts.map +1 -0
  196. package/dist/services/feature-flag-loader.js +54 -0
  197. package/dist/services/feature-flag-loader.js.map +1 -0
  198. package/dist/services/pain-flood-simulation-runner.d.ts +10 -0
  199. package/dist/services/pain-flood-simulation-runner.d.ts.map +1 -0
  200. package/dist/services/pain-flood-simulation-runner.js +289 -0
  201. package/dist/services/pain-flood-simulation-runner.js.map +1 -0
  202. package/dist/services/proven-channel-baseline-runner.d.ts +12 -0
  203. package/dist/services/proven-channel-baseline-runner.d.ts.map +1 -0
  204. package/dist/services/proven-channel-baseline-runner.js +114 -0
  205. package/dist/services/proven-channel-baseline-runner.js.map +1 -0
  206. package/dist/services/synthetic-baseline-runner.d.ts +8 -0
  207. package/dist/services/synthetic-baseline-runner.d.ts.map +1 -0
  208. package/dist/services/synthetic-baseline-runner.js +251 -0
  209. package/dist/services/synthetic-baseline-runner.js.map +1 -0
  210. package/package.json +35 -0
  211. package/src/commands/artifact.ts +82 -0
  212. package/src/commands/candidate.ts +1117 -0
  213. package/src/commands/central-sync.ts +44 -0
  214. package/src/commands/console.ts +121 -0
  215. package/src/commands/context.ts +72 -0
  216. package/src/commands/demo-story-a.ts +195 -0
  217. package/src/commands/diagnose.ts +452 -0
  218. package/src/commands/evolution-tasks-list.ts +44 -0
  219. package/src/commands/evolution-tasks-show.ts +60 -0
  220. package/src/commands/flow.ts +60 -0
  221. package/src/commands/health.ts +189 -0
  222. package/src/commands/history.ts +63 -0
  223. package/src/commands/legacy-cleanup.ts +206 -0
  224. package/src/commands/legacy-import.ts +104 -0
  225. package/src/commands/pain-record.ts +167 -0
  226. package/src/commands/proven-channel-baseline.ts +113 -0
  227. package/src/commands/remediation-output.ts +66 -0
  228. package/src/commands/run.ts +89 -0
  229. package/src/commands/runtime-activation.ts +176 -0
  230. package/src/commands/runtime-canary.ts +371 -0
  231. package/src/commands/runtime-diagnostics-export.ts +229 -0
  232. package/src/commands/runtime-features.ts +103 -0
  233. package/src/commands/runtime-gfi-snapshot.ts +135 -0
  234. package/src/commands/runtime-health-snapshot.ts +106 -0
  235. package/src/commands/runtime-internalization-enqueue-successors.ts +479 -0
  236. package/src/commands/runtime-internalization-integrity-repair.ts +69 -0
  237. package/src/commands/runtime-internalization-integrity.ts +63 -0
  238. package/src/commands/runtime-internalization-queue.ts +106 -0
  239. package/src/commands/runtime-internalization-run-once.ts +658 -0
  240. package/src/commands/runtime-internalization-wake-once.ts +87 -0
  241. package/src/commands/runtime-pain-flood-simulation.ts +121 -0
  242. package/src/commands/runtime-pruning.ts +438 -0
  243. package/src/commands/runtime-recovery.ts +107 -0
  244. package/src/commands/runtime-synthetic-baseline.ts +70 -0
  245. package/src/commands/runtime-uat.ts +339 -0
  246. package/src/commands/runtime.ts +281 -0
  247. package/src/commands/samples-list.ts +43 -0
  248. package/src/commands/samples-review.ts +32 -0
  249. package/src/commands/task.ts +130 -0
  250. package/src/commands/trace.ts +174 -0
  251. package/src/commands/trajectory.ts +64 -0
  252. package/src/index.ts +829 -0
  253. package/src/legacy/legacy-import.ts +179 -0
  254. package/src/legacy/session-history-import.ts +231 -0
  255. package/src/principle-tree-ledger-adapter.ts +13 -0
  256. package/src/resolve-workspace.ts +20 -0
  257. package/src/services/demo-story-a-runner.ts +472 -0
  258. package/src/services/feature-flag-loader.ts +73 -0
  259. package/src/services/pain-flood-simulation-runner.ts +354 -0
  260. package/src/services/proven-channel-baseline-runner.ts +150 -0
  261. package/src/services/synthetic-baseline-runner.ts +291 -0
  262. package/tests/commands/candidate-audit-repair.test.ts +338 -0
  263. package/tests/commands/candidate-intake.test.ts +589 -0
  264. package/tests/commands/candidate-internalization-backfill.test.ts +480 -0
  265. package/tests/commands/candidate-internalize.test.ts +272 -0
  266. package/tests/commands/candidate-route.test.ts +328 -0
  267. package/tests/commands/candidate-show.test.ts +95 -0
  268. package/tests/commands/cli-command-tree.test.ts +64 -0
  269. package/tests/commands/context.test.ts +114 -0
  270. package/tests/commands/demo-story-a.test.ts +255 -0
  271. package/tests/commands/diagnose.test.ts +792 -0
  272. package/tests/commands/health.test.ts +330 -0
  273. package/tests/commands/pain-record.test.ts +316 -0
  274. package/tests/commands/plugin-config-resolution-cutover.test.ts +220 -0
  275. package/tests/commands/proven-channel-baseline.test.ts +441 -0
  276. package/tests/commands/runtime-activation.test.ts +168 -0
  277. package/tests/commands/runtime-canary.test.ts +369 -0
  278. package/tests/commands/runtime-diagnostics-export.test.ts +170 -0
  279. package/tests/commands/runtime-features.test.ts +114 -0
  280. package/tests/commands/runtime-health-snapshot.test.ts +357 -0
  281. package/tests/commands/runtime-internalization-enqueue-successors.test.ts +803 -0
  282. package/tests/commands/runtime-internalization-integrity-repair.test.ts +169 -0
  283. package/tests/commands/runtime-internalization-integrity.test.ts +102 -0
  284. package/tests/commands/runtime-internalization-queue.test.ts +252 -0
  285. package/tests/commands/runtime-internalization-run-once.test.ts +1318 -0
  286. package/tests/commands/runtime-internalization-wake-once.test.ts +170 -0
  287. package/tests/commands/runtime-internalization.test.ts +52 -0
  288. package/tests/commands/runtime-pain-flood-simulation.test.ts +418 -0
  289. package/tests/commands/runtime-pruning.test.ts +693 -0
  290. package/tests/commands/runtime-recovery.test.ts +96 -0
  291. package/tests/commands/runtime-synthetic-baseline.test.ts +249 -0
  292. package/tests/commands/runtime-uat.test.ts +397 -0
  293. package/tests/commands/runtime.test.ts +262 -0
  294. package/tests/commands/trace.test.ts +314 -0
  295. package/tests/e2e/candidate-intake-e2e.test.ts +316 -0
  296. package/tests/services/feature-flag-loader.test.ts +207 -0
  297. package/tests/services/proven-channel-baseline-runner.test.ts +30 -0
  298. package/tsconfig.json +26 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * pd pain record command — Runtime v2 pain signal entry point.
3
+ *
4
+ * Uses PainToPrincipleService as the single write-side orchestration API.
5
+ *
6
+ * Usage:
7
+ * pd pain record --reason <text> [--score N] [--source manual] [--workspace <path>] [--json]
8
+ */
9
+ import {
10
+ PainToPrincipleService,
11
+ PrincipleTreeLedgerAdapter,
12
+ resolveRuntimeConfig,
13
+ isRuntimeConfigError,
14
+ } from '@principles/core/runtime-v2';
15
+ import type { KnownProvider } from '@mariozechner/pi-ai';
16
+ import { resolveWorkspaceDir } from '../resolve-workspace.js';
17
+
18
+ interface RecordOptions {
19
+ reason?: string;
20
+ score?: number;
21
+ source?: string;
22
+ workspace?: string;
23
+ json?: boolean;
24
+ }
25
+
26
+ export async function handlePainRecord(opts: RecordOptions): Promise<void> {
27
+ if (!opts.reason) {
28
+ console.error('Error: --reason <text> is required');
29
+ console.error('Usage: pd pain record --reason <text> [--score N] [--source manual] [--workspace <path>] [--json]');
30
+ process.exit(1);
31
+ }
32
+
33
+ if (opts.score !== undefined && (isNaN(opts.score) || opts.score < 0 || opts.score > 100)) {
34
+ console.error('Error: --score must be a number between 0 and 100');
35
+ process.exit(1);
36
+ }
37
+
38
+ const workspaceDir = resolveWorkspaceDir(opts.workspace);
39
+ const stateDir = `${workspaceDir}/.state`;
40
+ const painId = `manual_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
41
+
42
+ const ledgerAdapter = new PrincipleTreeLedgerAdapter({ stateDir });
43
+ const service = new PainToPrincipleService({
44
+ workspaceDir,
45
+ stateDir,
46
+ ledgerAdapter,
47
+ owner: 'pd-cli',
48
+ autoIntakeEnabled: true,
49
+ });
50
+
51
+ const result = await service.recordPain({
52
+ painId,
53
+ painType: 'user_frustration',
54
+ source: opts.source ?? 'manual',
55
+ reason: opts.reason,
56
+ score: opts.score ?? 80,
57
+ sessionId: 'cli',
58
+ agentId: 'pd-cli',
59
+ provenance: 'owner_reported_no_host_trace',
60
+ recordObservability: true,
61
+ });
62
+
63
+ // Show diagnostic info for config failures
64
+ if (result.failureCategory === 'config_missing') {
65
+ const configResult = resolveRuntimeConfig(stateDir);
66
+ if (isRuntimeConfigError(configResult)) {
67
+ if (opts.json) {
68
+ console.log(JSON.stringify({
69
+ status: 'failed',
70
+ painId: result.painId,
71
+ taskId: result.taskId,
72
+ failureCategory: result.failureCategory,
73
+ message: result.message,
74
+ configError: {
75
+ reason: configResult.reason,
76
+ message: configResult.message,
77
+ nextAction: configResult.nextAction,
78
+ },
79
+ }, null, 2));
80
+ } else {
81
+ console.error(` Config resolution failed: ${configResult.reason}`);
82
+ console.error(` ${configResult.message}`);
83
+ console.error(` nextAction: ${configResult.nextAction}`);
84
+ }
85
+ process.exit(1);
86
+ return;
87
+ }
88
+ const config = configResult;
89
+ const missing: string[] = [];
90
+ if (!config.provider) missing.push('provider');
91
+ if (!config.model) missing.push('model');
92
+ if (!config.apiKeyEnv) missing.push('apiKeyEnv');
93
+ if (config.provider) {
94
+ try {
95
+ const { getProviders } = await import('@mariozechner/pi-ai');
96
+ const knownProviders = getProviders();
97
+ if (!knownProviders.includes(config.provider as KnownProvider) && !config.baseUrl) {
98
+ missing.push('baseUrl');
99
+ }
100
+ } catch {
101
+ // pi-ai may not be available
102
+ }
103
+ }
104
+
105
+ if (missing.length > 0 || config.provider || config.apiKeyEnv) {
106
+ console.error('Error: Pain signal failed\n');
107
+
108
+ if (missing.length > 0) {
109
+ console.error(' Missing configuration:');
110
+ for (const m of missing) {
111
+ console.error(` - ${m}`);
112
+ }
113
+ console.error('');
114
+ }
115
+
116
+ if (config.provider || config.model || config.apiKeyEnv || config.baseUrl) {
117
+ console.error(' Current workflow policy (pd-runtime-v2-diagnosis):');
118
+ console.error(` runtimeKind: ${config.runtimeKind}`);
119
+ if (config.provider) console.error(` provider: ${config.provider}`);
120
+ if (config.model) console.error(` model: ${config.model}`);
121
+ if (config.apiKeyEnv) console.error(` apiKeyEnv: ${config.apiKeyEnv}`);
122
+ if (config.baseUrl) console.error(` baseUrl: ${config.baseUrl}`);
123
+ console.error('');
124
+ }
125
+
126
+ console.error(' To diagnose and configure your runtime, run:');
127
+ console.error(' pd runtime probe --runtime pi-ai --provider <name> --model <id> --apiKeyEnv <name>');
128
+ console.error('');
129
+
130
+ if (result.message) console.error(` Details: ${result.message}`);
131
+ process.exit(1);
132
+ }
133
+ }
134
+
135
+ if (opts.json) {
136
+ console.log(JSON.stringify(result, null, 2));
137
+ if (result.status !== 'succeeded' && result.status !== 'skipped' && result.status !== 'retried') process.exit(1);
138
+ } else {
139
+ if (result.status === 'succeeded') {
140
+ console.log('[OK] Pain signal recorded via PainToPrincipleService');
141
+ console.log(` Pain ID: ${result.painId}`);
142
+ console.log(` Task ID: ${result.taskId}`);
143
+ if (result.runId) console.log(` Run ID: ${result.runId}`);
144
+ if (result.artifactId) console.log(` Artifact ID: ${result.artifactId}`);
145
+ if (result.candidateIds.length > 0) console.log(` Candidate IDs: ${result.candidateIds.join(', ')}`);
146
+ if (result.ledgerEntryIds.length > 0) console.log(` Ledger Entry IDs: ${result.ledgerEntryIds.join(', ')}`);
147
+ console.log(` Reason: ${opts.reason}`);
148
+ console.log(` Score: ${opts.score ?? 80}`);
149
+ console.log(` Source: ${opts.source ?? 'manual'}`);
150
+ console.log(` Workspace: ${workspaceDir}`);
151
+ if (result.latencyMs !== undefined) console.log(` Latency: ${result.latencyMs}ms`);
152
+ console.log(`\nDiagnostician pipeline running. Check progress with:`);
153
+ console.log(` pd task show ${result.taskId} --workspace "${workspaceDir}"`);
154
+ } else if (result.status === 'skipped') {
155
+ console.log(`[SKIP] Task already in progress: ${result.message ?? 'unknown'}`);
156
+ console.log(` Pain ID: ${result.painId}`);
157
+ console.log(` Task ID: ${result.taskId}`);
158
+ } else if (result.status === 'retried') {
159
+ console.log(`[RETRY] Task retried: ${result.message ?? 'unknown'}`);
160
+ console.log(` Pain ID: ${result.painId}`);
161
+ console.log(` Task ID: ${result.taskId}`);
162
+ } else {
163
+ console.error('[FAIL] Pain signal failed:', result.message);
164
+ process.exit(1);
165
+ }
166
+ }
167
+ }
@@ -0,0 +1,113 @@
1
+ import * as path from 'path';
2
+ import * as os from 'os';
3
+ import * as fs from 'fs';
4
+ import { runProvenChannelBaseline } from '../services/proven-channel-baseline-runner.js';
5
+ import { parseChannels, type ProvenChannelBaselineSummary, type MvpChannel } from '@principles/core/runtime-v2';
6
+
7
+ interface ProvenChannelBaselineCliOptions {
8
+ workspace?: string;
9
+ json?: boolean;
10
+ channels?: string;
11
+ }
12
+
13
+ function formatChannelResult(ch: { channel: string; status: string; failureReason?: string; nextAction?: string; evidence: Record<string, unknown> }): string {
14
+ const icon = ch.status === 'passed' ? '✓' : ch.status === 'degraded' ? '⚠' : '✗';
15
+ const lines: string[] = [];
16
+ lines.push(` ${icon} ${ch.channel}: ${ch.status}`);
17
+ if (ch.failureReason) {
18
+ lines.push(` reason: ${ch.failureReason}`);
19
+ }
20
+ if (ch.nextAction) {
21
+ lines.push(` nextAction: ${ch.nextAction}`);
22
+ }
23
+ return lines.join('\n');
24
+ }
25
+
26
+ function formatTextOutput(summary: ProvenChannelBaselineSummary): string {
27
+ const lines: string[] = [];
28
+ const icon = summary.status === 'passed' ? '✓' : summary.status === 'degraded' ? '⚠' : '✗';
29
+
30
+ lines.push('PD Proven Channel Baseline (PRI-240)');
31
+ lines.push(`generatedAt: ${summary.generatedAt}`);
32
+ lines.push(`workspaceMode: ${summary.workspaceMode}`);
33
+ lines.push(`OVERALL: ${icon} ${summary.status.toUpperCase()}`);
34
+ lines.push('');
35
+
36
+ if (summary.inputValidationFailure) {
37
+ const ivf = summary.inputValidationFailure;
38
+ lines.push('Input Validation Failure:');
39
+ lines.push(` reason: ${ivf.reason}`);
40
+ lines.push(` message: ${ivf.message}`);
41
+ lines.push(` nextAction: ${ivf.nextAction}`);
42
+ lines.push('');
43
+ }
44
+
45
+ lines.push('Channel Results:');
46
+ for (const ch of summary.channels) {
47
+ lines.push(formatChannelResult(ch));
48
+ }
49
+
50
+ lines.push('');
51
+ lines.push('Continuity Matrix:');
52
+ for (const entry of summary.continuityMatrix) {
53
+ lines.push(` ${entry.channel}:`);
54
+ lines.push(` entryPoint: ${entry.entryPoint}`);
55
+ lines.push(` expected: ${entry.expectedObservable}`);
56
+ lines.push(` dependsOnPluginDiscovery: ${entry.dependsOnPluginDiscovery}`);
57
+ }
58
+
59
+ if (summary.recommendedNextIssue) {
60
+ lines.push('');
61
+ lines.push(`Recommended next issue: ${summary.recommendedNextIssue}`);
62
+ }
63
+
64
+ return lines.join('\n');
65
+ }
66
+
67
+ export function cleanupTempWorkspace(workspaceDir: string, rmSyncImpl: (dir: string, opts: { recursive: boolean; force: boolean }) => void = fs.rmSync.bind(fs)): void {
68
+ try {
69
+ rmSyncImpl(workspaceDir, { recursive: true, force: true });
70
+ } catch (cleanupErr) {
71
+ const cleanupMsg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
72
+ console.error(`[pd-cli] cleanup warning: failed to remove temp workspace ${workspaceDir}: ${cleanupMsg}`);
73
+ }
74
+ }
75
+
76
+ export async function handleProvenChannelBaseline(opts: ProvenChannelBaselineCliOptions): Promise<void> {
77
+ const workspaceDir = opts.workspace
78
+ ? path.resolve(opts.workspace)
79
+ : fs.mkdtempSync(path.join(os.tmpdir(), 'pd-proven-channel-'));
80
+ const workspaceMode: 'temp' | 'explicit_workspace' = opts.workspace ? 'explicit_workspace' : 'temp';
81
+
82
+ const parsed = opts.channels ? parseChannels(opts.channels) : null;
83
+ const userSpecifiedChannels = opts.channels !== undefined;
84
+ const channels: MvpChannel[] | undefined = parsed && parsed.channels.length > 0 ? parsed.channels : undefined;
85
+ const unknownChannels: string[] = parsed ? parsed.unknowns : [];
86
+ const emptyChannelInput = userSpecifiedChannels && channels === undefined && unknownChannels.length === 0;
87
+
88
+ try {
89
+ const summary = await runProvenChannelBaseline({
90
+ workspaceDir,
91
+ workspaceMode,
92
+ channels,
93
+ unknownChannels,
94
+ emptyChannelInput,
95
+ });
96
+
97
+ if (opts.json) {
98
+ console.log(JSON.stringify(summary, null, 2));
99
+ } else {
100
+ console.log(formatTextOutput(summary));
101
+ }
102
+
103
+ if (summary.status !== 'passed') {
104
+ console.error('');
105
+ console.error(`FAIL: status=${summary.status}`);
106
+ process.exitCode = 1;
107
+ }
108
+ } finally {
109
+ if (workspaceMode === 'temp') {
110
+ cleanupTempWorkspace(workspaceDir);
111
+ }
112
+ }
113
+ }
@@ -0,0 +1,66 @@
1
+ export type RemediationMode = 'dry_run' | 'confirm';
2
+ export type RemediationStatus = 'would_change' | 'changed' | 'no_op' | 'refused' | 'error';
3
+
4
+ export interface RemediationAction {
5
+ action: string;
6
+ targetId: string;
7
+ previousState?: string;
8
+ nextState?: string;
9
+ reason: string;
10
+ taskId?: string;
11
+ type?: string;
12
+ severity?: 'error' | 'warning';
13
+ previousStatus?: string;
14
+ newStatus?: string;
15
+ recommendedAction?: string;
16
+ successorTaskId?: string;
17
+ }
18
+
19
+ export interface RemediationResult {
20
+ mode: RemediationMode;
21
+ status: RemediationStatus;
22
+ safeToConfirm: boolean;
23
+ repairedCount: number;
24
+ skippedCount: number;
25
+ actions: RemediationAction[];
26
+ warnings: string[];
27
+ generatedAt?: string;
28
+ dryRun?: boolean;
29
+ }
30
+
31
+ export function createRemediationResult(input: {
32
+ mode: RemediationMode;
33
+ repairedCount?: number;
34
+ skippedCount?: number;
35
+ actions?: RemediationAction[];
36
+ warnings?: string[];
37
+ status?: RemediationStatus;
38
+ safeToConfirm?: boolean;
39
+ generatedAt?: string;
40
+ includeLegacyDryRun?: boolean;
41
+ }): RemediationResult {
42
+ const actions = input.actions ?? [];
43
+ const warnings = input.warnings ?? [];
44
+ const repairedCount = input.repairedCount ?? 0;
45
+ const status = input.status ?? (input.mode === 'dry_run'
46
+ ? (actions.length > 0 ? 'would_change' : 'no_op')
47
+ : (repairedCount > 0 ? 'changed' : 'no_op'));
48
+
49
+ return {
50
+ mode: input.mode,
51
+ status,
52
+ safeToConfirm: input.safeToConfirm ?? (
53
+ input.mode === 'dry_run' && status === 'would_change' && warnings.length === 0
54
+ ),
55
+ repairedCount,
56
+ skippedCount: input.skippedCount ?? 0,
57
+ actions,
58
+ warnings,
59
+ ...(input.generatedAt ? { generatedAt: input.generatedAt } : {}),
60
+ ...(input.includeLegacyDryRun ? { dryRun: input.mode === 'dry_run' } : {}),
61
+ };
62
+ }
63
+
64
+ export function remediationAction(input: RemediationAction): RemediationAction {
65
+ return input;
66
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * pd run list/show commands — Runtime v2 run inspection.
3
+ *
4
+ * Usage:
5
+ * pd run list <taskId>
6
+ * pd run show <runId>
7
+ */
8
+ import { RuntimeStateManager } from '@principles/core';
9
+ import { resolveWorkspaceDir } from '../resolve-workspace.js';
10
+
11
+ interface RunListOptions {
12
+ taskId: string;
13
+ }
14
+
15
+ export async function handleRunList(opts: RunListOptions): Promise<void> {
16
+ const workspaceDir = resolveWorkspaceDir();
17
+ const stateManager = new RuntimeStateManager({ workspaceDir });
18
+ await stateManager.initialize();
19
+
20
+ try {
21
+ const runs = await stateManager.getRunsByTask(opts.taskId);
22
+
23
+ if (runs.length === 0) {
24
+ console.log(`No runs found for task: ${opts.taskId}`);
25
+ return;
26
+ }
27
+
28
+ console.log(`\nRuns for ${opts.taskId} (${runs.length}):\n`);
29
+ console.log(' %-22s %-12s %-20s %-6s %s', 'RUN_ID', 'STATUS', 'STARTED', 'ATT', 'ENDED');
30
+ console.log(' ' + '-'.repeat(80));
31
+
32
+ for (const run of runs) {
33
+ console.log(
34
+ ' %-22s %-12s %-20s %-6s %s',
35
+ run.runId.substring(0, 22),
36
+ run.executionStatus,
37
+ new Date(run.startedAt).toLocaleString(),
38
+ run.attemptNumber,
39
+ run.endedAt ? new Date(run.endedAt).toLocaleString() : '-',
40
+ );
41
+ }
42
+ console.log('');
43
+ } finally {
44
+ await stateManager.close();
45
+ }
46
+ }
47
+
48
+ interface RunShowOptions {
49
+ id: string;
50
+ }
51
+
52
+ export async function handleRunShow(opts: RunShowOptions): Promise<void> {
53
+ const workspaceDir = resolveWorkspaceDir();
54
+ const stateManager = new RuntimeStateManager({ workspaceDir });
55
+ await stateManager.initialize();
56
+
57
+ try {
58
+ const run = await stateManager.getRun(opts.id);
59
+
60
+ if (!run) {
61
+ console.error(`Run not found: ${opts.id}`);
62
+ process.exit(1);
63
+ }
64
+
65
+ console.log(`\nRun: ${run.runId}\n`);
66
+ console.log(` Task ID: ${run.taskId}`);
67
+ console.log(` Runtime Kind: ${run.runtimeKind}`);
68
+ console.log(` Status: ${run.executionStatus}`);
69
+ console.log(` Attempt: ${run.attemptNumber}`);
70
+ console.log(` Started: ${new Date(run.startedAt).toLocaleString()}`);
71
+ if (run.endedAt) {
72
+ console.log(` Ended: ${new Date(run.endedAt).toLocaleString()}`);
73
+ const duration = new Date(run.endedAt).getTime() - new Date(run.startedAt).getTime();
74
+ console.log(` Duration: ${(duration / 1000).toFixed(1)}s`);
75
+ }
76
+ if (run.reason) {
77
+ console.log(` Reason: ${run.reason}`);
78
+ }
79
+ if (run.errorCategory) {
80
+ console.log(` Error Category:${run.errorCategory}`);
81
+ }
82
+ if (run.outputRef) {
83
+ console.log(` Output Ref: ${run.outputRef}`);
84
+ }
85
+ console.log('');
86
+ } finally {
87
+ await stateManager.close();
88
+ }
89
+ }
@@ -0,0 +1,176 @@
1
+ import * as path from 'path';
2
+ import {
3
+ RuntimeStateManager,
4
+ ActivationDispatcher,
5
+ PromptWriter,
6
+ DeferArchiveWriter,
7
+ SqliteActivationStateStore,
8
+ SqliteApprovalQueueStore,
9
+ } from '@principles/core/runtime-v2';
10
+ import type { ActivationDecision, PIArtifactSnapshot, RolloutActivationDecision } from '@principles/core/runtime-v2';
11
+ import type { PIArtifactRecord } from '@principles/core/runtime-v2';
12
+ import { resolveWorkspaceDir } from '../resolve-workspace.js';
13
+
14
+ interface ActivationDispatchOptions {
15
+ workspace?: string;
16
+ artifactId?: string;
17
+ channel?: string;
18
+ dryRun?: boolean;
19
+ confirm?: boolean;
20
+ json?: boolean;
21
+ }
22
+
23
+ function mapRolloutDecision(reviewDecision: string | undefined): RolloutActivationDecision {
24
+ if (!reviewDecision) return 'require_approval';
25
+ if (reviewDecision === 'approve_rollout') return 'auto_activate';
26
+ if (reviewDecision === 'needs_revision') return 'require_approval';
27
+ if (reviewDecision === 'reject') return 'reject';
28
+ return 'require_approval';
29
+ }
30
+
31
+ function extractRolloutDecisionFromArtifact(artifact: PIArtifactRecord): RolloutActivationDecision {
32
+ try {
33
+ const parsed = JSON.parse(artifact.contentJson) as Record<string, unknown>;
34
+ if (parsed && typeof parsed === 'object') {
35
+ const review = parsed.review as Record<string, unknown> | undefined;
36
+ if (review && typeof review.decision === 'string') {
37
+ return mapRolloutDecision(review.decision);
38
+ }
39
+ if (typeof parsed.rolloutDecision === 'string') {
40
+ return mapRolloutDecision(parsed.rolloutDecision);
41
+ }
42
+ }
43
+ } catch {
44
+ return 'require_approval';
45
+ }
46
+ return 'require_approval';
47
+ }
48
+
49
+ function toSnapshot(record: PIArtifactRecord): PIArtifactSnapshot {
50
+ return {
51
+ artifactId: record.artifactId,
52
+ artifactKind: record.artifactKind,
53
+ sourceTaskId: record.sourceTaskId,
54
+ sourcePrincipleId: record.sourcePrincipleId,
55
+ sourceRuleId: record.sourceRuleId,
56
+ lineageArtifactIds: record.lineageArtifactIds,
57
+ validationStatus: record.validationStatus,
58
+ contentJson: record.contentJson,
59
+ createdAt: record.createdAt,
60
+ updatedAt: record.updatedAt,
61
+ };
62
+ }
63
+
64
+ function formatTextOutput(result: ActivationDecision): string {
65
+ const lines: string[] = [];
66
+ switch (result.decision) {
67
+ case 'would_activate':
68
+ lines.push(`Activation: would_activate`);
69
+ lines.push(` activationId: ${result.activationId}`);
70
+ lines.push(` action: ${result.action}`);
71
+ lines.push(` targetRef: ${result.targetRef}`);
72
+ break;
73
+ case 'activated':
74
+ lines.push(`Activation: activated`);
75
+ lines.push(` activationId: ${result.activationId}`);
76
+ lines.push(` action: ${result.action}`);
77
+ lines.push(` targetRef: ${result.targetRef}`);
78
+ break;
79
+ case 'already_activated':
80
+ lines.push(`Activation: already_activated`);
81
+ lines.push(` activationId: ${result.activationId}`);
82
+ lines.push(` action: ${result.action}`);
83
+ lines.push(` targetRef: ${result.targetRef}`);
84
+ break;
85
+ case 'refused':
86
+ lines.push(`Activation: refused`);
87
+ lines.push(` reason: ${result.reason}`);
88
+ if (result.riskLevel) lines.push(` riskLevel: ${result.riskLevel}`);
89
+ if (result.channel) lines.push(` channel: ${result.channel}`);
90
+ break;
91
+ case 'invalid_artifact':
92
+ lines.push(`Activation: invalid_artifact`);
93
+ lines.push(` reason: ${result.reason}`);
94
+ break;
95
+ }
96
+ return lines.join('\n');
97
+ }
98
+
99
+ function isNegativeDecision(decision: ActivationDecision['decision']): boolean {
100
+ return decision === 'refused' || decision === 'invalid_artifact';
101
+ }
102
+
103
+ export async function handleRuntimeActivationDispatch(opts: ActivationDispatchOptions): Promise<void> {
104
+ if (opts.dryRun && opts.confirm) {
105
+ console.error('Error: --dry-run and --confirm are mutually exclusive');
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+
110
+ if (!opts.artifactId) {
111
+ console.error('Error: --artifact-id is required');
112
+ process.exitCode = 1;
113
+ return;
114
+ }
115
+
116
+ const confirm = opts.confirm === true;
117
+ const channel = (opts.channel ?? 'prompt') as 'prompt' | 'defer_archive' | 'skill' | 'code_tool_hook' | 'model_training';
118
+
119
+ const workspaceDir = opts.workspace ? path.resolve(opts.workspace) : resolveWorkspaceDir();
120
+ const stateManager = new RuntimeStateManager({ workspaceDir });
121
+
122
+ try {
123
+ await stateManager.initialize();
124
+ const artifactRecord = await stateManager.piArtifactStore.getArtifactById(opts.artifactId);
125
+ if (!artifactRecord) {
126
+ const result: ActivationDecision = { decision: 'invalid_artifact', reason: 'artifact_not_found' };
127
+ if (opts.json) {
128
+ console.log(JSON.stringify(result, null, 2));
129
+ } else {
130
+ console.log(formatTextOutput(result));
131
+ }
132
+ process.exitCode = 1;
133
+ return;
134
+ }
135
+
136
+ const artifactSnapshot = toSnapshot(artifactRecord);
137
+ const rolloutDecision = extractRolloutDecisionFromArtifact(artifactRecord);
138
+
139
+ const artifactReadModel = {
140
+ getArtifactById: async (id: string): Promise<PIArtifactSnapshot | null> => {
141
+ if (id === opts.artifactId) return artifactSnapshot;
142
+ const rec = await stateManager.piArtifactStore.getArtifactById(id);
143
+ return rec ? toSnapshot(rec) : null;
144
+ },
145
+ };
146
+
147
+ const activationStateStore = new SqliteActivationStateStore(stateManager.connection);
148
+ const approvalQueueStore = new SqliteApprovalQueueStore(stateManager.connection);
149
+ const dispatcher = new ActivationDispatcher(
150
+ artifactReadModel,
151
+ activationStateStore,
152
+ { writers: [new PromptWriter(), new DeferArchiveWriter()], approvalQueueStore },
153
+ );
154
+
155
+ const result = await dispatcher.dispatch({
156
+ artifactId: opts.artifactId,
157
+ channel,
158
+ rolloutDecision,
159
+ actor: { kind: 'system', source: 'rollout_reviewer' },
160
+ now: new Date().toISOString(),
161
+ confirm,
162
+ });
163
+
164
+ if (opts.json) {
165
+ console.log(JSON.stringify(result, null, 2));
166
+ } else {
167
+ console.log(formatTextOutput(result));
168
+ }
169
+
170
+ if (isNegativeDecision(result.decision)) {
171
+ process.exitCode = 1;
172
+ }
173
+ } finally {
174
+ await stateManager.close();
175
+ }
176
+ }