@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,452 @@
1
+ /**
2
+ * pd diagnose run/status commands — Diagnostician execution and status inspection.
3
+ *
4
+ * Usage:
5
+ * pd diagnose status --task-id <taskId> --workspace <path>
6
+ * pd diagnose run --task-id <taskId> --workspace <path>
7
+ */
8
+ import {
9
+ RuntimeStateManager,
10
+ SqliteHistoryQuery,
11
+ SqliteContextAssembler,
12
+ SqliteDiagnosticianCommitter,
13
+ SqliteTrajectoryLocator,
14
+ SqliteSourceTraceLocator,
15
+ StoreEventEmitter,
16
+ storeEmitter,
17
+ DiagnosticianRunner,
18
+ DefaultDiagnosticianValidator,
19
+ TestDoubleRuntimeAdapter,
20
+ OpenClawCliRuntimeAdapter,
21
+ PiAiRuntimeAdapter,
22
+ PDRuntimeError,
23
+ resolveRuntimeConfig,
24
+ isRuntimeConfigError,
25
+ CandidateIntakeService,
26
+ run as diagnoseRun,
27
+ status as diagnoseStatus,
28
+ } from '@principles/core/runtime-v2';
29
+ import type { PDRuntimeAdapter, RuntimeConfig } from '@principles/core/runtime-v2';
30
+ import { PrincipleTreeLedgerAdapter } from '../principle-tree-ledger-adapter.js';
31
+ import { resolveWorkspaceDir } from '../resolve-workspace.js';
32
+ import * as path from 'path';
33
+
34
+ interface DiagnoseStatusOptions {
35
+ taskId: string;
36
+ workspace?: string;
37
+ json?: boolean;
38
+ }
39
+
40
+ interface DiagnoseRunOptions {
41
+ taskId: string;
42
+ workspace?: string;
43
+ json?: boolean;
44
+ runtime?: string;
45
+ openclawLocal?: boolean;
46
+ openclawGateway?: boolean;
47
+ agent?: string;
48
+ provider?: string;
49
+ model?: string;
50
+ apiKeyEnv?: string;
51
+ baseUrl?: string;
52
+ maxRetries?: number;
53
+ timeoutMs?: number;
54
+ intake?: boolean;
55
+ }
56
+
57
+ /**
58
+ * pd diagnose status --task-id <taskId> [--workspace <path>] [--json]
59
+ *
60
+ * Inspects the current status of a diagnostician task.
61
+ */
62
+ export async function handleDiagnoseStatus(opts: DiagnoseStatusOptions): Promise<void> {
63
+ const workspaceDir = resolveWorkspaceDir(opts.workspace);
64
+ const stateManager = new RuntimeStateManager({ workspaceDir });
65
+
66
+ try {
67
+ await stateManager.initialize();
68
+ const result = await diagnoseStatus({
69
+ taskId: opts.taskId,
70
+ stateManager,
71
+ });
72
+
73
+ if (!result) {
74
+ console.error(`Task not found: ${opts.taskId}`);
75
+ process.exit(1);
76
+ return;
77
+ }
78
+
79
+ if (opts.json) {
80
+ console.log(JSON.stringify(result, null, 2));
81
+ return;
82
+ }
83
+
84
+ console.log(`\nDiagnostician Task: ${result.taskId}\n`);
85
+ console.log(` Status: ${result.status}`);
86
+ console.log(` Attempts: ${result.attemptCount} / ${result.maxAttempts}`);
87
+ if (result.commitId) {
88
+ console.log(` Result Ref: commit://${result.commitId}`);
89
+ console.log(` Commit ID: ${result.commitId}`);
90
+ console.log(` Artifact ID: ${result.artifactId ?? 'N/A'}`);
91
+ console.log(` Candidates: ${result.candidateCount ?? 0}`);
92
+ }
93
+ if (result.lastError) {
94
+ console.log(` Last Error: ${result.lastError}`);
95
+ }
96
+ console.log('');
97
+ } finally {
98
+ await stateManager.close();
99
+ }
100
+ }
101
+
102
+ /**
103
+ * pd diagnose run --task-id <taskId> [--workspace <path>] [--json]
104
+ *
105
+ * Executes the diagnostician runner for a task.
106
+ */
107
+ export async function handleDiagnoseRun(opts: DiagnoseRunOptions): Promise<void> {
108
+ const workspaceDir = resolveWorkspaceDir(opts.workspace);
109
+
110
+ // Validate mutually exclusive flags (HG-03)
111
+ if (opts.openclawLocal && opts.openclawGateway) {
112
+ console.error('error: --openclaw-local and --openclaw-gateway are mutually exclusive');
113
+ process.exit(1);
114
+ }
115
+
116
+ const runtimeKind = opts.runtime ?? 'test-double';
117
+
118
+ const stateManager = new RuntimeStateManager({ workspaceDir });
119
+
120
+ try {
121
+ await stateManager.initialize();
122
+
123
+ // Build context assembler from internal stores
124
+ const sqliteConn = stateManager.connection;
125
+ const {taskStore} = stateManager;
126
+ const {runStore} = stateManager;
127
+ const historyQuery = new SqliteHistoryQuery(sqliteConn);
128
+ const trajectoryLocator = new SqliteTrajectoryLocator(sqliteConn);
129
+ const sourceTraceLocator = new SqliteSourceTraceLocator(taskStore, trajectoryLocator);
130
+ const contextAssembler = new SqliteContextAssembler(taskStore, historyQuery, runStore, { sourceTraceLocator });
131
+
132
+ // Select runtime adapter based on --runtime flag (CLI-02)
133
+ // eslint-disable-next-line @typescript-eslint/init-declarations
134
+ let runtimeAdapter: PDRuntimeAdapter;
135
+ if (runtimeKind === 'openclaw-cli') {
136
+ const stateDir = `${workspaceDir}/.state`;
137
+ const configResult = resolveRuntimeConfig(stateDir, { openclawLocal: opts.openclawLocal, openclawGateway: opts.openclawGateway, requestedRuntimeKind: 'openclaw-cli' });
138
+ if (isRuntimeConfigError(configResult)) {
139
+ if (opts.json) {
140
+ console.log(JSON.stringify({ ok: false, reason: configResult.reason, message: configResult.message, nextAction: configResult.nextAction }));
141
+ } else {
142
+ console.error(`error: ${configResult.message}`);
143
+ console.error(`nextAction: ${configResult.nextAction}`);
144
+ }
145
+ process.exit(1);
146
+ return;
147
+ }
148
+ const { openclawMode } = configResult;
149
+ if (!openclawMode) {
150
+ if (opts.json) {
151
+ console.log(JSON.stringify({ ok: false, reason: 'missing_openclaw_mode', message: 'runtimeKind is openclaw-cli but no mode resolved', nextAction: 'Provide --openclaw-local or --openclaw-gateway, or set openclawMode in workflows.yaml' }));
152
+ } else {
153
+ console.error('error: runtimeKind is openclaw-cli but no mode resolved');
154
+ console.error('nextAction: Provide --openclaw-local or --openclaw-gateway, or set openclawMode in workflows.yaml');
155
+ }
156
+ process.exit(1);
157
+ return;
158
+ }
159
+
160
+ runtimeAdapter = new OpenClawCliRuntimeAdapter({
161
+ runtimeMode: openclawMode,
162
+ workspaceDir,
163
+ agentId: opts.agent ?? 'main',
164
+ });
165
+
166
+ // TELE-01: runtime_adapter_selected — user explicitly chose openclaw-cli runtime
167
+ storeEmitter.emitTelemetry({
168
+ eventType: 'runtime_adapter_selected',
169
+ traceId: opts.taskId,
170
+ timestamp: new Date().toISOString(),
171
+ sessionId: 'pd-cli-diagnose',
172
+ agentId: 'openclaw-cli-adapter',
173
+ payload: {
174
+ runtimeKind: 'openclaw-cli',
175
+ runtimeMode: openclawMode,
176
+ },
177
+ });
178
+ } else if (runtimeKind === 'test-double') {
179
+ runtimeAdapter = new TestDoubleRuntimeAdapter({
180
+ onPollRun: (_runId: string) => ({
181
+ runId: _runId,
182
+ status: 'succeeded',
183
+ startedAt: new Date().toISOString(),
184
+ endedAt: new Date().toISOString(),
185
+ }),
186
+ onFetchOutput: (_runId: string) => ({
187
+ runId: _runId,
188
+ payload: {
189
+ valid: true,
190
+ diagnosisId: `diag-cli-${Date.now()}`,
191
+ taskId: opts.taskId,
192
+ summary: 'CLI test diagnosis — validate tool arguments before execution',
193
+ rootCause: 'Test root cause — missing argument validation',
194
+ violatedPrinciples: [],
195
+ evidence: [],
196
+ recommendations: [
197
+ { kind: 'principle', description: 'Always validate tool arguments before execution to prevent silent failures' },
198
+ { kind: 'rule', description: 'Use schema validation for external inputs' },
199
+ ],
200
+ confidence: 0.9,
201
+ },
202
+ }),
203
+ });
204
+ } else if (runtimeKind === 'pi-ai') {
205
+ const stateDir = `${workspaceDir}/.state`;
206
+ let policyConfig: RuntimeConfig | null = null;
207
+ try {
208
+ const configResult = resolveRuntimeConfig(stateDir);
209
+ if (!isRuntimeConfigError(configResult)) {
210
+ policyConfig = configResult;
211
+ } else {
212
+ console.warn(`[pd diagnose] workflows.yaml policy load failed: ${configResult.message}. Using CLI flags if provided.`);
213
+ }
214
+ } catch (err: unknown) {
215
+ const detail = err instanceof Error ? err.message : String(err);
216
+ console.warn(`[pd diagnose] workflows.yaml policy load failed: ${detail}. Using CLI flags if provided.`);
217
+ }
218
+
219
+ const provider = opts.provider ?? policyConfig?.provider;
220
+ const model = opts.model ?? policyConfig?.model;
221
+ const apiKeyEnv = opts.apiKeyEnv ?? policyConfig?.apiKeyEnv;
222
+ const baseUrl = opts.baseUrl ?? policyConfig?.baseUrl;
223
+ const maxRetries = opts.maxRetries ?? policyConfig?.maxRetries;
224
+ const effectiveTimeoutMs = opts.timeoutMs ?? policyConfig?.timeoutMs;
225
+
226
+ // D-11: validate config — missing fields + fix suggestion
227
+ const missing: string[] = [];
228
+ if (!provider) missing.push('provider');
229
+ if (!model) missing.push('model');
230
+ if (!apiKeyEnv) missing.push('apiKeyEnv');
231
+ if (missing.length > 0) {
232
+ console.error(
233
+ `error: missing required pi-ai config: ${missing.join(', ')}.\n` +
234
+ `Pass via --flag or add to workflows.yaml pd-runtime-v2-diagnosis funnel policy.\n` +
235
+ `Example:\n` +
236
+ ` pd diagnose run --runtime pi-ai --provider openrouter --model anthropic/claude-sonnet-4 --apiKeyEnv OPENROUTER_API_KEY\n` +
237
+ ` Or add to workflows.yaml:\n` +
238
+ ` policy:\n` +
239
+ ` runtimeKind: pi-ai\n` +
240
+ ` provider: openrouter\n` +
241
+ ` model: anthropic/claude-sonnet-4\n` +
242
+ ` apiKeyEnv: OPENROUTER_API_KEY`,
243
+ );
244
+ process.exit(1);
245
+ }
246
+
247
+ // After validation: all fields are confirmed non-null
248
+ const validProvider: string = provider as string;
249
+ const validModel: string = model as string;
250
+ const validApiKeyEnv: string = apiKeyEnv as string;
251
+
252
+ // D-09: validate env var exists
253
+ if (!process.env[validApiKeyEnv]) {
254
+ console.error(`error: environment variable '${validApiKeyEnv}' is not set`);
255
+ process.exit(1);
256
+ }
257
+
258
+ runtimeAdapter = new PiAiRuntimeAdapter({
259
+ provider: validProvider,
260
+ model: validModel,
261
+ apiKeyEnv: validApiKeyEnv,
262
+ baseUrl,
263
+ maxRetries,
264
+ timeoutMs: effectiveTimeoutMs,
265
+ workspace: workspaceDir,
266
+ });
267
+
268
+ // TELE: runtime_adapter_selected telemetry
269
+ storeEmitter.emitTelemetry({
270
+ eventType: 'runtime_adapter_selected',
271
+ traceId: opts.taskId,
272
+ timestamp: new Date().toISOString(),
273
+ sessionId: 'pd-cli-diagnose',
274
+ agentId: 'pi-ai-adapter',
275
+ payload: { runtimeKind: 'pi-ai', provider: validProvider, model: validModel, baseUrlPresent: !!baseUrl },
276
+ });
277
+ } else {
278
+ console.error(`error: unknown runtime kind '${runtimeKind}' (supported: openclaw-cli, test-double, pi-ai)`);
279
+ process.exit(1);
280
+ }
281
+
282
+ const eventEmitter = new StoreEventEmitter();
283
+ const committer = new SqliteDiagnosticianCommitter(sqliteConn);
284
+ const runner = new DiagnosticianRunner(
285
+ {
286
+ stateManager,
287
+ contextAssembler,
288
+ runtimeAdapter,
289
+ eventEmitter,
290
+ validator: new DefaultDiagnosticianValidator(),
291
+ committer,
292
+ },
293
+ {
294
+ owner: 'pd-cli-diagnose',
295
+ runtimeKind,
296
+ pollIntervalMs: 100,
297
+ timeoutMs: 300_000, // 5 min — same as probe timeout for real LLM calls
298
+ agentId: opts.agent,
299
+ },
300
+ );
301
+
302
+ if (!opts.json) {
303
+ console.log(`\nRunning diagnostician for task: ${opts.taskId}`);
304
+ console.log(`Workspace: ${workspaceDir}\n`);
305
+ }
306
+
307
+ const result = await diagnoseRun({
308
+ taskId: opts.taskId,
309
+ stateManager,
310
+ runner,
311
+ });
312
+
313
+ if (result.status !== 'succeeded') {
314
+ if (opts.json) {
315
+ console.log(JSON.stringify(result, null, 2));
316
+ } else {
317
+ console.log(`\nResult:`);
318
+ console.log(` Status: ${result.status}`);
319
+ console.log(` Task ID: ${result.taskId}`);
320
+ if (result.errorCategory) {
321
+ console.log(` Error Category: ${result.errorCategory}`);
322
+ }
323
+ if (result.failureReason) {
324
+ console.log(` Failure Reason: ${result.failureReason}`);
325
+ }
326
+ console.log(` Attempt Count: ${result.attemptCount}`);
327
+ console.log('');
328
+ }
329
+ process.exit(1);
330
+ return;
331
+ }
332
+
333
+ const candidates = await stateManager.getCandidatesByTaskId(opts.taskId);
334
+ const intakeResults: { candidateId: string; ledgerEntryId?: string; status: string; error?: string; nextAction?: string }[] = [];
335
+ let intakeFailed = false;
336
+
337
+ if (opts.intake === false) {
338
+ for (const candidate of candidates) {
339
+ intakeResults.push({
340
+ candidateId: candidate.candidateId,
341
+ status: 'skipped',
342
+ });
343
+ }
344
+ } else {
345
+ const ledgerAdapter = new PrincipleTreeLedgerAdapter({ stateDir: path.join(workspaceDir, '.state') });
346
+ const intakeService = new CandidateIntakeService({ stateManager, ledgerAdapter });
347
+
348
+ for (const candidate of candidates) {
349
+ try {
350
+ const entry = await intakeService.intake(candidate.candidateId);
351
+ if (candidate.status !== 'consumed') {
352
+ await stateManager.updateCandidateStatus(candidate.candidateId, { status: 'consumed' });
353
+ }
354
+ intakeResults.push({
355
+ candidateId: candidate.candidateId,
356
+ ledgerEntryId: entry.id,
357
+ status: 'consumed',
358
+ });
359
+ } catch (intakeErr: unknown) {
360
+ intakeFailed = true;
361
+ const intakeErrorMessage = intakeErr instanceof Error ? intakeErr.message : String(intakeErr);
362
+ intakeResults.push({
363
+ candidateId: candidate.candidateId,
364
+ status: 'intake_failed',
365
+ error: intakeErrorMessage,
366
+ nextAction: `pd candidate intake --candidate-id ${candidate.candidateId} --workspace "${workspaceDir}"`,
367
+ });
368
+ }
369
+ }
370
+ }
371
+
372
+ if (opts.json) {
373
+ const jsonOutput = {
374
+ ...result,
375
+ intake: {
376
+ enabled: opts.intake !== false,
377
+ candidates: intakeResults,
378
+ },
379
+ };
380
+ console.log(JSON.stringify(jsonOutput, null, 2));
381
+ if (intakeFailed) {
382
+ process.exit(1);
383
+ }
384
+ return;
385
+ }
386
+
387
+ console.log(`\nResult:`);
388
+ console.log(` Status: ${result.status}`);
389
+ console.log(` Task ID: ${result.taskId}`);
390
+ if (result.contextHash) {
391
+ console.log(` Context Hash: ${result.contextHash.substring(0, 16)}...`);
392
+ }
393
+ if (result.output) {
394
+ console.log(` Diagnosis ID: ${result.output.diagnosisId}`);
395
+ console.log(` Summary: ${result.output.summary}`);
396
+ if (result.output.recommendations) {
397
+ const principleCount = result.output.recommendations.filter((r: { kind: string }) => r.kind === 'principle').length;
398
+ if (principleCount > 0) {
399
+ console.log(` Principles: ${principleCount} candidate(s) generated`);
400
+ }
401
+ }
402
+ }
403
+ console.log(` Attempt Count: ${result.attemptCount}`);
404
+
405
+ if (intakeResults.length > 0) {
406
+ console.log(`\n Candidate Intake:`);
407
+ for (const ir of intakeResults) {
408
+ if (ir.status === 'consumed') {
409
+ console.log(` ${ir.candidateId}: consumed (ledger: ${ir.ledgerEntryId})`);
410
+ } else if (ir.status === 'skipped') {
411
+ console.log(` ${ir.candidateId}: skipped (--no-intake)`);
412
+ } else if (ir.status === 'intake_failed') {
413
+ console.log(` ${ir.candidateId}: INTAKE FAILED — ${ir.error}`);
414
+ console.log(` Next action: pd candidate intake --candidate-id ${ir.candidateId} --workspace "${workspaceDir}"`);
415
+ }
416
+ }
417
+ }
418
+
419
+ if (opts.intake === false && candidates.length > 0) {
420
+ console.log(`\n Note: --no-intake was set. Candidates remain at 'pending'.`);
421
+ console.log(` To intake manually:`);
422
+ for (const c of candidates) {
423
+ console.log(` pd candidate intake --candidate-id ${c.candidateId} --workspace "${workspaceDir}"`);
424
+ }
425
+ }
426
+
427
+ console.log('');
428
+
429
+ if (intakeFailed) {
430
+ process.exit(1);
431
+ }
432
+ } catch (error: unknown) {
433
+ const message = error instanceof Error ? error.message : String(error);
434
+ let errorCategory = 'execution_failed';
435
+ if (error instanceof PDRuntimeError) {
436
+ errorCategory = error.category;
437
+ }
438
+ if (opts.json) {
439
+ console.log(JSON.stringify({
440
+ status: 'failed',
441
+ errorCategory,
442
+ message,
443
+ runtimeKind,
444
+ }, null, 2));
445
+ } else {
446
+ console.error(`error: ${message} (${errorCategory})`);
447
+ }
448
+ process.exit(1);
449
+ } finally {
450
+ await stateManager.close();
451
+ }
452
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * pd evolution tasks list command implementation.
3
+ *
4
+ * Usage: pd evolution tasks list [--status pending|in_progress|completed|all]
5
+ * [--limit <number>] [--date-from <date>] [--date-to <date>]
6
+ */
7
+
8
+ import { listEvolutionTasks } from '@principles/core/evolution-store';
9
+ import { resolveWorkspaceDir } from '../resolve-workspace.js';
10
+
11
+ interface EvolutionTasksListOptions {
12
+ status?: string;
13
+ limit?: number;
14
+ dateFrom?: string;
15
+ dateTo?: string;
16
+ }
17
+
18
+ export async function handleEvolutionTasksList(opts: EvolutionTasksListOptions): Promise<void> {
19
+ const workspaceDir = resolveWorkspaceDir();
20
+
21
+ try {
22
+ const tasks = listEvolutionTasks(workspaceDir, {
23
+ status: opts.status === 'all' ? undefined : opts.status,
24
+ limit: opts.limit,
25
+ dateFrom: opts.dateFrom,
26
+ dateTo: opts.dateTo,
27
+ });
28
+ if (tasks.length === 0) {
29
+ console.log('No evolution tasks found.');
30
+ return;
31
+ }
32
+ for (const task of tasks) {
33
+ const enqueuedAt = task.enqueuedAt ?? 'null';
34
+ console.log(
35
+ `[${task.status}] ${task.taskId} (${task.taskKind}) score=${task.score} source=${task.source} enqueued=${enqueuedAt}`
36
+ );
37
+ }
38
+ console.log(`${tasks.length} task(s)`);
39
+ return;
40
+ } catch {
41
+ console.log('No evolution tasks found.');
42
+ return;
43
+ }
44
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * pd evolution tasks show command implementation.
3
+ *
4
+ * Usage: pd evolution tasks show <id>
5
+ *
6
+ * Displays full details for a single evolution task.
7
+ * Accepts both numeric id and string taskId.
8
+ */
9
+
10
+ import { getEvolutionTask } from '@principles/core/evolution-store';
11
+ import { resolveWorkspaceDir } from '../resolve-workspace.js';
12
+
13
+ interface EvolutionTasksShowOptions {
14
+ id: string;
15
+ }
16
+
17
+ export async function handleEvolutionTasksShow(opts: EvolutionTasksShowOptions): Promise<void> {
18
+ const workspaceDir = resolveWorkspaceDir();
19
+
20
+ // eslint-disable-next-line @typescript-eslint/init-declarations
21
+ let foundTask;
22
+ try {
23
+ const numericId = isNaN(Number(opts.id)) ? undefined : Number(opts.id);
24
+ foundTask = getEvolutionTask(workspaceDir, numericId ?? opts.id);
25
+ } catch {
26
+ console.log('No evolution tasks found.');
27
+ return;
28
+ }
29
+
30
+ if (!foundTask) {
31
+ console.error(`Task not found: ${opts.id}`);
32
+ process.exit(1);
33
+ }
34
+
35
+ const fields = [
36
+ ['id', String(foundTask.id)],
37
+ ['taskId', foundTask.taskId],
38
+ ['traceId', foundTask.traceId],
39
+ ['source', foundTask.source],
40
+ ['reason', foundTask.reason ?? 'null'],
41
+ ['score', String(foundTask.score)],
42
+ ['status', foundTask.status],
43
+ ['enqueuedAt', foundTask.enqueuedAt ?? 'null'],
44
+ ['startedAt', foundTask.startedAt ?? 'null'],
45
+ ['completedAt', foundTask.completedAt ?? 'null'],
46
+ ['resolution', foundTask.resolution ?? 'null'],
47
+ ['taskKind', foundTask.taskKind ?? 'null'],
48
+ ['priority', foundTask.priority ?? 'null'],
49
+ ['retryCount', foundTask.retryCount != null ? String(foundTask.retryCount) : 'null'],
50
+ ['maxRetries', foundTask.maxRetries != null ? String(foundTask.maxRetries) : 'null'],
51
+ ['lastError', foundTask.lastError ?? 'null'],
52
+ ['resultRef', foundTask.resultRef ?? 'null'],
53
+ ['createdAt', foundTask.createdAt],
54
+ ['updatedAt', foundTask.updatedAt],
55
+ ];
56
+
57
+ for (const [key, value] of fields) {
58
+ console.log(`${key}: ${value}`);
59
+ }
60
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * pd runtime flow show command — Display workflow funnel definitions from workflows.yaml.
3
+ *
4
+ * Usage:
5
+ * pd runtime flow show [--workspace <path>] [--json]
6
+ */
7
+ import * as path from 'path';
8
+ import { WorkflowFunnelLoader } from '@principles/core';
9
+
10
+ interface FlowShowOptions {
11
+ workspace?: string;
12
+ json?: boolean;
13
+ }
14
+
15
+ export async function handleFlowShow(opts: FlowShowOptions): Promise<void> {
16
+ const workspaceDir = opts.workspace ?? process.cwd();
17
+ const stateDir = path.join(workspaceDir, '.state');
18
+
19
+ const loader = new WorkflowFunnelLoader(stateDir);
20
+
21
+ if (opts.json) {
22
+ const all = loader.getAllFunnelsWithPolicy();
23
+ console.log(JSON.stringify({ status: 'ok', funnels: [...all.values()] }, null, 2));
24
+ return;
25
+ }
26
+
27
+ const all = loader.getAllFunnelsWithPolicy();
28
+ const funnels = [...all.values()];
29
+
30
+ if (funnels.length === 0) {
31
+ console.log('Workflows: (no funnels defined)\n');
32
+ return;
33
+ }
34
+
35
+ console.log(`Workflows (${funnels.length} funnel${funnels.length !== 1 ? 's' : ''}):\n`);
36
+
37
+ for (const funnel of funnels) {
38
+ console.log(` ${funnel.workflowId}`);
39
+ if (funnel.policy) {
40
+ const p = funnel.policy;
41
+ if (p.timeoutMs) console.log(` timeoutMs: ${p.timeoutMs}`);
42
+ if (p.stageOrder) console.log(` stageOrder: ${p.stageOrder}`);
43
+ if (p.legacyDisabled !== undefined) console.log(` legacyDisabled: ${p.legacyDisabled}`);
44
+ if (p.observability?.enabled !== undefined) console.log(` observability: ${p.observability.enabled}`);
45
+ if (p.observability?.logLevel) console.log(` logLevel: ${p.observability.logLevel}`);
46
+ if (p.observability?.emitEvents?.length) {
47
+ console.log(` emitEvents: ${p.observability.emitEvents.join(', ')}`);
48
+ }
49
+ }
50
+ console.log(` stages (${funnel.stages.length}):`);
51
+ for (const stage of funnel.stages) {
52
+ const parts = [` - ${stage.name}`];
53
+ if (stage.timeoutMs) parts.push(` timeoutMs=${stage.timeoutMs}`);
54
+ if (stage.successCriteria) parts.push(` successCriteria="${stage.successCriteria}"`);
55
+ if (stage.legacyDisabled) parts.push(` legacyDisabled`);
56
+ console.log(parts.join(''));
57
+ }
58
+ console.log('');
59
+ }
60
+ }