@principles/core 1.123.0 → 1.125.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 (231) hide show
  1. package/dist/runtime-v2/__tests__/architecture-regression.test.js +42 -74
  2. package/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  3. package/dist/runtime-v2/__tests__/attack-e2e-pipeline-smoke.test.js +115 -21
  4. package/dist/runtime-v2/__tests__/attack-e2e-pipeline-smoke.test.js.map +1 -1
  5. package/dist/runtime-v2/__tests__/golden-path-diagnostician-e2e.test.js.map +1 -1
  6. package/dist/runtime-v2/__tests__/pain-signal-bridge-retried.test.js +7 -6
  7. package/dist/runtime-v2/__tests__/pain-signal-bridge-retried.test.js.map +1 -1
  8. package/dist/runtime-v2/__tests__/pain-signal-bridge-short-circuit.test.js.map +1 -1
  9. package/dist/runtime-v2/__tests__/pain-signal-bridge-workspace-dir.test.js.map +1 -1
  10. package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts.map +1 -1
  11. package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +4 -0
  12. package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
  13. package/dist/runtime-v2/cli/diagnose.d.ts +2 -2
  14. package/dist/runtime-v2/cli/diagnose.d.ts.map +1 -1
  15. package/dist/runtime-v2/config/__tests__/pd-config-contract.test.js +3 -3
  16. package/dist/runtime-v2/config/__tests__/pd-config-contract.test.js.map +1 -1
  17. package/dist/runtime-v2/config/pd-config-defaults.js +3 -3
  18. package/dist/runtime-v2/config/pd-config-defaults.js.map +1 -1
  19. package/dist/runtime-v2/config/pd-config-types.d.ts +2 -0
  20. package/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -1
  21. package/dist/runtime-v2/config/pd-config-types.js.map +1 -1
  22. package/dist/runtime-v2/diagnostician/__tests__/diag-distiller-output.test.d.ts +2 -0
  23. package/dist/runtime-v2/diagnostician/__tests__/diag-distiller-output.test.d.ts.map +1 -0
  24. package/dist/runtime-v2/diagnostician/__tests__/diag-distiller-output.test.js +45 -0
  25. package/dist/runtime-v2/diagnostician/__tests__/diag-distiller-output.test.js.map +1 -0
  26. package/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.d.ts +2 -0
  27. package/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.d.ts.map +1 -0
  28. package/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.js +57 -0
  29. package/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.js.map +1 -0
  30. package/dist/runtime-v2/diagnostician/__tests__/distiller-prompt-builder.test.d.ts +2 -0
  31. package/dist/runtime-v2/diagnostician/__tests__/distiller-prompt-builder.test.d.ts.map +1 -0
  32. package/dist/runtime-v2/diagnostician/__tests__/distiller-prompt-builder.test.js +39 -0
  33. package/dist/runtime-v2/diagnostician/__tests__/distiller-prompt-builder.test.js.map +1 -0
  34. package/dist/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.d.ts +2 -0
  35. package/dist/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.d.ts.map +1 -0
  36. package/dist/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.js +34 -0
  37. package/dist/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.js.map +1 -0
  38. package/dist/runtime-v2/diagnostician/__tests__/router-prompt-builder.test.d.ts +2 -0
  39. package/dist/runtime-v2/diagnostician/__tests__/router-prompt-builder.test.d.ts.map +1 -0
  40. package/dist/runtime-v2/diagnostician/__tests__/router-prompt-builder.test.js +57 -0
  41. package/dist/runtime-v2/diagnostician/__tests__/router-prompt-builder.test.js.map +1 -0
  42. package/dist/runtime-v2/diagnostician/diag-distiller-output.d.ts +80 -0
  43. package/dist/runtime-v2/diagnostician/diag-distiller-output.d.ts.map +1 -0
  44. package/dist/runtime-v2/diagnostician/diag-distiller-output.js +103 -0
  45. package/dist/runtime-v2/diagnostician/diag-distiller-output.js.map +1 -0
  46. package/dist/runtime-v2/diagnostician/diag-rootcause-output.d.ts +115 -0
  47. package/dist/runtime-v2/diagnostician/diag-rootcause-output.d.ts.map +1 -0
  48. package/dist/runtime-v2/diagnostician/diag-rootcause-output.js +166 -0
  49. package/dist/runtime-v2/diagnostician/diag-rootcause-output.js.map +1 -0
  50. package/dist/runtime-v2/diagnostician/distiller-prompt-builder.d.ts +134 -0
  51. package/dist/runtime-v2/diagnostician/distiller-prompt-builder.d.ts.map +1 -0
  52. package/dist/runtime-v2/diagnostician/distiller-prompt-builder.js +156 -0
  53. package/dist/runtime-v2/diagnostician/distiller-prompt-builder.js.map +1 -0
  54. package/dist/runtime-v2/diagnostician/rootcause-prompt-builder.d.ts +96 -0
  55. package/dist/runtime-v2/diagnostician/rootcause-prompt-builder.d.ts.map +1 -0
  56. package/dist/runtime-v2/diagnostician/rootcause-prompt-builder.js +216 -0
  57. package/dist/runtime-v2/diagnostician/rootcause-prompt-builder.js.map +1 -0
  58. package/dist/runtime-v2/diagnostician/router-prompt-builder.d.ts +127 -0
  59. package/dist/runtime-v2/diagnostician/router-prompt-builder.d.ts.map +1 -0
  60. package/dist/runtime-v2/diagnostician/router-prompt-builder.js +131 -0
  61. package/dist/runtime-v2/diagnostician/router-prompt-builder.js.map +1 -0
  62. package/dist/runtime-v2/diagnostician-prompt-builder.d.ts +1 -64
  63. package/dist/runtime-v2/diagnostician-prompt-builder.d.ts.map +1 -1
  64. package/dist/runtime-v2/diagnostician-prompt-builder.js +0 -186
  65. package/dist/runtime-v2/diagnostician-prompt-builder.js.map +1 -1
  66. package/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +13 -7
  67. package/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  68. package/dist/runtime-v2/feature-flags/feature-flag-contract.js +3 -3
  69. package/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  70. package/dist/runtime-v2/index.d.ts +14 -10
  71. package/dist/runtime-v2/index.d.ts.map +1 -1
  72. package/dist/runtime-v2/index.js +9 -6
  73. package/dist/runtime-v2/index.js.map +1 -1
  74. package/dist/runtime-v2/internalization/__tests__/__fixtures__/split-pipeline-mock-outputs.d.ts +25 -0
  75. package/dist/runtime-v2/internalization/__tests__/__fixtures__/split-pipeline-mock-outputs.d.ts.map +1 -0
  76. package/dist/runtime-v2/internalization/__tests__/__fixtures__/split-pipeline-mock-outputs.js +123 -0
  77. package/dist/runtime-v2/internalization/__tests__/__fixtures__/split-pipeline-mock-outputs.js.map +1 -0
  78. package/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.d.ts +2 -0
  79. package/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.d.ts.map +1 -0
  80. package/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js +734 -0
  81. package/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js.map +1 -0
  82. package/dist/runtime-v2/internalization/__tests__/diag-distiller-runner.test.d.ts +2 -0
  83. package/dist/runtime-v2/internalization/__tests__/diag-distiller-runner.test.d.ts.map +1 -0
  84. package/dist/runtime-v2/internalization/__tests__/diag-distiller-runner.test.js +437 -0
  85. package/dist/runtime-v2/internalization/__tests__/diag-distiller-runner.test.js.map +1 -0
  86. package/dist/runtime-v2/internalization/__tests__/diag-rootcause-runner.test.d.ts +2 -0
  87. package/dist/runtime-v2/internalization/__tests__/diag-rootcause-runner.test.d.ts.map +1 -0
  88. package/dist/runtime-v2/internalization/__tests__/diag-rootcause-runner.test.js +336 -0
  89. package/dist/runtime-v2/internalization/__tests__/diag-rootcause-runner.test.js.map +1 -0
  90. package/dist/runtime-v2/internalization/__tests__/diag-router-runner.test.d.ts +2 -0
  91. package/dist/runtime-v2/internalization/__tests__/diag-router-runner.test.d.ts.map +1 -0
  92. package/dist/runtime-v2/internalization/__tests__/diag-router-runner.test.js +437 -0
  93. package/dist/runtime-v2/internalization/__tests__/diag-router-runner.test.js.map +1 -0
  94. package/dist/runtime-v2/internalization/__tests__/runnerkind-seam.test.js +3 -3
  95. package/dist/runtime-v2/internalization/__tests__/runnerkind-seam.test.js.map +1 -1
  96. package/dist/runtime-v2/internalization/diag-distiller-runner.d.ts +83 -0
  97. package/dist/runtime-v2/internalization/diag-distiller-runner.d.ts.map +1 -0
  98. package/dist/runtime-v2/internalization/diag-distiller-runner.js +274 -0
  99. package/dist/runtime-v2/internalization/diag-distiller-runner.js.map +1 -0
  100. package/dist/runtime-v2/internalization/diag-rootcause-runner.d.ts +73 -0
  101. package/dist/runtime-v2/internalization/diag-rootcause-runner.d.ts.map +1 -0
  102. package/dist/runtime-v2/internalization/diag-rootcause-runner.js +229 -0
  103. package/dist/runtime-v2/internalization/diag-rootcause-runner.js.map +1 -0
  104. package/dist/runtime-v2/internalization/diag-router-runner.d.ts +85 -0
  105. package/dist/runtime-v2/internalization/diag-router-runner.d.ts.map +1 -0
  106. package/dist/runtime-v2/internalization/diag-router-runner.js +353 -0
  107. package/dist/runtime-v2/internalization/diag-router-runner.js.map +1 -0
  108. package/dist/runtime-v2/internalization/evaluator-runner.d.ts +1 -1
  109. package/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  110. package/dist/runtime-v2/internalization/evaluator-runner.js +1 -1
  111. package/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  112. package/dist/runtime-v2/internalization/split-diagnostician-runner.d.ts +66 -0
  113. package/dist/runtime-v2/internalization/split-diagnostician-runner.d.ts.map +1 -0
  114. package/dist/runtime-v2/internalization/split-diagnostician-runner.js +241 -0
  115. package/dist/runtime-v2/internalization/split-diagnostician-runner.js.map +1 -0
  116. package/dist/runtime-v2/observer/__tests__/empathy-observer.real-e2e.test.js +28 -21
  117. package/dist/runtime-v2/observer/__tests__/empathy-observer.real-e2e.test.js.map +1 -1
  118. package/dist/runtime-v2/pain-signal-bridge.d.ts +22 -3
  119. package/dist/runtime-v2/pain-signal-bridge.d.ts.map +1 -1
  120. package/dist/runtime-v2/pain-signal-bridge.js +16 -7
  121. package/dist/runtime-v2/pain-signal-bridge.js.map +1 -1
  122. package/dist/runtime-v2/pain-signal-runtime-factory.d.ts +13 -1
  123. package/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
  124. package/dist/runtime-v2/pain-signal-runtime-factory.js +64 -34
  125. package/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
  126. package/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js +2 -2
  127. package/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js.map +1 -1
  128. package/dist/runtime-v2/runner/__tests__/diagnose.test.js.map +1 -1
  129. package/dist/runtime-v2/runner/base-peer-runner.d.ts +3 -3
  130. package/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -1
  131. package/dist/runtime-v2/runner/base-peer-runner.js +6 -6
  132. package/dist/runtime-v2/runner/base-peer-runner.js.map +1 -1
  133. package/dist/runtime-v2/runner/peer-runner-types.d.ts +3 -3
  134. package/dist/runtime-v2/runner/peer-runner-types.d.ts.map +1 -1
  135. package/dist/runtime-v2/store/candidate/sqlite-candidate-store.js +2 -2
  136. package/dist/runtime-v2/store/candidate/sqlite-candidate-store.js.map +1 -1
  137. package/dist/runtime-v2/types/principle-enums.d.ts +2 -2
  138. package/dist/runtime-v2/types/principle-enums.d.ts.map +1 -1
  139. package/dist/runtime-v2/types/principle-enums.js +1 -0
  140. package/dist/runtime-v2/types/principle-enums.js.map +1 -1
  141. package/dist/runtime-v2/types/principle-schema.d.ts +1 -1
  142. package/dist/runtime-v2/types/principle-tree-store.d.ts +1 -1
  143. package/dist/telemetry-event.d.ts +2 -2
  144. package/dist/telemetry-event.d.ts.map +1 -1
  145. package/dist/telemetry-event.js +1 -0
  146. package/dist/telemetry-event.js.map +1 -1
  147. package/package.json +1 -1
  148. package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.d.ts +0 -2
  149. package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.d.ts.map +0 -1
  150. package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.js +0 -122
  151. package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.js.map +0 -1
  152. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.d.ts +0 -2
  153. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.d.ts.map +0 -1
  154. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.js +0 -169
  155. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.js.map +0 -1
  156. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.d.ts +0 -2
  157. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.d.ts.map +0 -1
  158. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.js +0 -462
  159. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.js.map +0 -1
  160. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts +0 -13
  161. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts.map +0 -1
  162. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js +0 -97
  163. package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js.map +0 -1
  164. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.d.ts +0 -2
  165. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.d.ts.map +0 -1
  166. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.js +0 -378
  167. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.js.map +0 -1
  168. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.d.ts +0 -2
  169. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.d.ts.map +0 -1
  170. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js +0 -682
  171. package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js.map +0 -1
  172. package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.d.ts +0 -2
  173. package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.d.ts.map +0 -1
  174. package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.js +0 -286
  175. package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.js.map +0 -1
  176. package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.d.ts +0 -2
  177. package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.d.ts.map +0 -1
  178. package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.js +0 -320
  179. package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.js.map +0 -1
  180. package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.d.ts +0 -2
  181. package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.d.ts.map +0 -1
  182. package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.js +0 -261
  183. package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.js.map +0 -1
  184. package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.d.ts +0 -2
  185. package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.d.ts.map +0 -1
  186. package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.js +0 -405
  187. package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.js.map +0 -1
  188. package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.d.ts +0 -2
  189. package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.d.ts.map +0 -1
  190. package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.js +0 -347
  191. package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.js.map +0 -1
  192. package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.d.ts +0 -2
  193. package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.d.ts.map +0 -1
  194. package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.js +0 -186
  195. package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.js.map +0 -1
  196. package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.d.ts +0 -2
  197. package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.d.ts.map +0 -1
  198. package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.js +0 -355
  199. package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.js.map +0 -1
  200. package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.d.ts +0 -2
  201. package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.d.ts.map +0 -1
  202. package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.js +0 -486
  203. package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.js.map +0 -1
  204. package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.d.ts +0 -2
  205. package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.d.ts.map +0 -1
  206. package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.js +0 -171
  207. package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.js.map +0 -1
  208. package/dist/runtime-v2/runner/__tests__/m9-e2e.test.d.ts +0 -2
  209. package/dist/runtime-v2/runner/__tests__/m9-e2e.test.d.ts.map +0 -1
  210. package/dist/runtime-v2/runner/__tests__/m9-e2e.test.js +0 -175
  211. package/dist/runtime-v2/runner/__tests__/m9-e2e.test.js.map +0 -1
  212. package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.d.ts +0 -2
  213. package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.d.ts.map +0 -1
  214. package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.js +0 -276
  215. package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.js.map +0 -1
  216. package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.d.ts +0 -2
  217. package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.d.ts.map +0 -1
  218. package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.js +0 -272
  219. package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.js.map +0 -1
  220. package/dist/runtime-v2/runner/__tests__/start-run-input.test.d.ts +0 -2
  221. package/dist/runtime-v2/runner/__tests__/start-run-input.test.d.ts.map +0 -1
  222. package/dist/runtime-v2/runner/__tests__/start-run-input.test.js +0 -67
  223. package/dist/runtime-v2/runner/__tests__/start-run-input.test.js.map +0 -1
  224. package/dist/runtime-v2/runner/diagnostician-runner-options.d.ts +0 -57
  225. package/dist/runtime-v2/runner/diagnostician-runner-options.d.ts.map +0 -1
  226. package/dist/runtime-v2/runner/diagnostician-runner-options.js +0 -21
  227. package/dist/runtime-v2/runner/diagnostician-runner-options.js.map +0 -1
  228. package/dist/runtime-v2/runner/diagnostician-runner.d.ts +0 -89
  229. package/dist/runtime-v2/runner/diagnostician-runner.d.ts.map +0 -1
  230. package/dist/runtime-v2/runner/diagnostician-runner.js +0 -470
  231. package/dist/runtime-v2/runner/diagnostician-runner.js.map +0 -1
@@ -0,0 +1,39 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { DistillerPromptBuilder, buildDistillerProtocolInstruction } from '../distiller-prompt-builder.js';
3
+ const mockRootCauseOutput = {
4
+ valid: true,
5
+ diagnosisId: 'diag-001',
6
+ taskId: 'task-001',
7
+ summary: 'Test summary',
8
+ causalChain: [{ why: 1, statement: 'First why', evidenceRefs: ['ref1'] }],
9
+ rootCause: 'Design: Poor error handling',
10
+ rootCauseCategory: 'Design',
11
+ evidence: [{ sourceRef: 'src1', note: 'note1' }],
12
+ confidence: 0.8,
13
+ };
14
+ describe('DistillerPromptBuilder', () => {
15
+ it('prompt includes Stage A root cause artifact as input', () => {
16
+ const builder = new DistillerPromptBuilder();
17
+ const result = builder.buildPrompt({
18
+ rootCauseArtifactId: 'artifact-001',
19
+ rootCauseOutput: mockRootCauseOutput,
20
+ });
21
+ expect(result.message).toContain('artifact-001');
22
+ });
23
+ it('prompt includes CORE_PRINCIPLES when coreGrounding=true', () => {
24
+ const instruction = buildDistillerProtocolInstruction({ coreGrounding: true });
25
+ expect(instruction).toContain('T-01');
26
+ expect(instruction).toContain('T-10');
27
+ });
28
+ it('prompt instructs LLM to only reference given axiom IDs, prohibit fabrication', () => {
29
+ const instruction = buildDistillerProtocolInstruction({ coreGrounding: true });
30
+ expect(instruction).toContain('fabricat');
31
+ });
32
+ it('prompt requires output matching DiagDistillerOutputV1Schema', () => {
33
+ const instruction = buildDistillerProtocolInstruction({ coreGrounding: false });
34
+ expect(instruction).toContain('abstractedPrinciple');
35
+ expect(instruction).toContain('groundedOnCorePrincipleIds');
36
+ expect(instruction).toContain('sourceRootCauseArtifactId');
37
+ });
38
+ });
39
+ //# sourceMappingURL=distiller-prompt-builder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distiller-prompt-builder.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/diagnostician/__tests__/distiller-prompt-builder.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AAG3G,MAAM,mBAAmB,GAA0B;IACjD,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,UAAU;IACvB,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE,cAAc;IACvB,WAAW,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;IACzE,SAAS,EAAE,6BAA6B;IACxC,iBAAiB,EAAE,QAAQ;IAC3B,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAChD,UAAU,EAAE,GAAG;CAChB,CAAC;AAEF,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,OAAO,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;YACjC,mBAAmB,EAAE,cAAc;YACnC,eAAe,EAAE,mBAAmB;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QAC5D,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rootcause-prompt-builder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rootcause-prompt-builder.test.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { buildRootCauseProtocolInstruction } from '../rootcause-prompt-builder.js';
3
+ describe('RootCausePromptBuilder', () => {
4
+ it('prompt contains PHASE 1-3 (evidence review, causal chain, root cause classification)', () => {
5
+ const instruction = buildRootCauseProtocolInstruction({ coreGrounding: false });
6
+ expect(instruction).toContain('PHASE 1');
7
+ expect(instruction).toContain('PHASE 2');
8
+ expect(instruction).toContain('PHASE 3');
9
+ });
10
+ it('prompt requires output matching DiagRootCauseOutputV1Schema', () => {
11
+ const instruction = buildRootCauseProtocolInstruction({ coreGrounding: false });
12
+ expect(instruction).toContain('diagnosisId');
13
+ expect(instruction).toContain('causalChain');
14
+ expect(instruction).toContain('rootCause');
15
+ expect(instruction).toContain('rootCauseCategory');
16
+ });
17
+ it('coreGrounding=true injects PHASE 3.5', () => {
18
+ const instruction = buildRootCauseProtocolInstruction({ coreGrounding: true });
19
+ expect(instruction).toContain('PHASE 3.5');
20
+ expect(instruction).toContain('Core Axiom Grounding');
21
+ });
22
+ it('coreGrounding=false does NOT include PHASE 3.5', () => {
23
+ const instruction = buildRootCauseProtocolInstruction({ coreGrounding: false });
24
+ expect(instruction).not.toContain('PHASE 3.5');
25
+ });
26
+ it('PHASE 3.5 appears between PHASE 3 and PHASE 4', () => {
27
+ const instruction = buildRootCauseProtocolInstruction({ coreGrounding: true });
28
+ const phase3Index = instruction.indexOf('PHASE 3');
29
+ const phase35Index = instruction.indexOf('PHASE 3.5');
30
+ // PHASE 3.5 must come after PHASE 3
31
+ expect(phase35Index).toBeGreaterThan(phase3Index);
32
+ });
33
+ });
34
+ //# sourceMappingURL=rootcause-prompt-builder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rootcause-prompt-builder.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AAEnF,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,sFAAsF,EAAE,GAAG,EAAE;QAC9F,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,WAAW,GAAG,iCAAiC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACtD,oCAAoC;QACpC,MAAM,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=router-prompt-builder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-prompt-builder.test.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/diagnostician/__tests__/router-prompt-builder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { RouterPromptBuilder } from '../router-prompt-builder.js';
3
+ const mockRootCauseOutput = {
4
+ valid: true,
5
+ diagnosisId: 'diag-001',
6
+ taskId: 'task-001',
7
+ summary: 'Test summary',
8
+ causalChain: [{ why: 1, statement: 'First why', evidenceRefs: ['ref1'] }],
9
+ rootCause: 'Design: Poor error handling',
10
+ rootCauseCategory: 'Design',
11
+ evidence: [{ sourceRef: 'src1', note: 'note1' }],
12
+ confidence: 0.8,
13
+ };
14
+ const mockDistillerOutput = {
15
+ valid: true,
16
+ taskId: 'task-001',
17
+ sourceRootCauseArtifactId: 'artifact-001',
18
+ abstractedPrinciple: 'Prefer explicit error handling over silent fallbacks',
19
+ rationale: 'Root cause shows silent error swallowing',
20
+ groundedOnCorePrincipleIds: ['T-03'],
21
+ scope: 'general',
22
+ confidence: 0.85,
23
+ };
24
+ describe('RouterPromptBuilder', () => {
25
+ it('prompt includes Stage A + Stage B artifacts as input', () => {
26
+ const builder = new RouterPromptBuilder();
27
+ const result = builder.buildPrompt({
28
+ rootCauseArtifactId: 'artifact-001',
29
+ rootCauseOutput: mockRootCauseOutput,
30
+ distillerArtifactId: 'artifact-002',
31
+ distillerOutput: mockDistillerOutput,
32
+ });
33
+ expect(result.message).toContain('artifact-001');
34
+ expect(result.message).toContain('artifact-002');
35
+ });
36
+ it('prompt requires output matching DiagnosticianOutputV1Schema', () => {
37
+ const builder = new RouterPromptBuilder();
38
+ const instruction = builder.buildRouterInstruction();
39
+ expect(instruction).toContain('violatedPrinciples');
40
+ expect(instruction).toContain('recommendations');
41
+ });
42
+ it('prompt instructs filling violatedPrinciples from A + B', () => {
43
+ const builder = new RouterPromptBuilder();
44
+ const instruction = builder.buildRouterInstruction();
45
+ expect(instruction).toContain('violatedPrinciples');
46
+ });
47
+ it('prompt instructs filling recommendations from taxonomy decision', () => {
48
+ const builder = new RouterPromptBuilder();
49
+ const instruction = builder.buildRouterInstruction();
50
+ expect(instruction).toContain('principle');
51
+ expect(instruction).toContain('rule');
52
+ expect(instruction).toContain('implementation');
53
+ expect(instruction).toContain('prompt');
54
+ expect(instruction).toContain('defer');
55
+ });
56
+ });
57
+ //# sourceMappingURL=router-prompt-builder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-prompt-builder.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/diagnostician/__tests__/router-prompt-builder.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Stage B (Distiller) output schema for the split diagnostician pipeline.
3
+ *
4
+ * The Distiller takes the root-cause artifact from Stage A and produces
5
+ * an abstracted, cross-scenario principle grounded on the T-01..T-10
6
+ * core axiom registry.
7
+ *
8
+ * @see PRI-372 — Split diagnostician into Stage A (Root Cause) + Stage B (Distiller)
9
+ */
10
+ import { type Static } from '@sinclair/typebox';
11
+ export declare const DiagDistillerScopeSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"general">, import("@sinclair/typebox").TLiteral<"domain">, import("@sinclair/typebox").TLiteral<"scenario">]>;
12
+ /** Scope classification for a distilled principle. */
13
+ export type DiagDistillerScope = Static<typeof DiagDistillerScopeSchema>;
14
+ /**
15
+ * TypeBox schema for Stage B (Distiller) output.
16
+ *
17
+ * Lineage consistency: `sourceRootCauseArtifactId` must match the artifact
18
+ * produced by Stage A so that the pipeline can trace every distilled
19
+ * principle back to its root-cause diagnosis.
20
+ *
21
+ * `groundedOnCorePrincipleIds` is validated against the T-01..T-10
22
+ * registry at runtime — fabricated IDs cause validation failure.
23
+ *
24
+ * @see PRI-372
25
+ */
26
+ export declare const DiagDistillerOutputV1Schema: import("@sinclair/typebox").TObject<{
27
+ valid: import("@sinclair/typebox").TBoolean;
28
+ taskId: import("@sinclair/typebox").TString;
29
+ sourceRootCauseArtifactId: import("@sinclair/typebox").TString;
30
+ abstractedPrinciple: import("@sinclair/typebox").TString;
31
+ rationale: import("@sinclair/typebox").TString;
32
+ groundedOnCorePrincipleIds: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
33
+ scope: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"general">, import("@sinclair/typebox").TLiteral<"domain">, import("@sinclair/typebox").TLiteral<"scenario">]>;
34
+ confidence: import("@sinclair/typebox").TNumber;
35
+ ambiguityNotes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
36
+ }>;
37
+ /** Inferred TypeScript type for Stage B (Distiller) output. */
38
+ export type DiagDistillerOutputV1 = Static<typeof DiagDistillerOutputV1Schema>;
39
+ /**
40
+ * Validator interface for DiagDistillerOutputV1.
41
+ *
42
+ * Accepts `unknown` input — implementations must perform runtime checks (ERR-001).
43
+ *
44
+ * @see PRI-372
45
+ */
46
+ export interface DiagDistillerValidator {
47
+ /**
48
+ * Validate untrusted distiller stage output.
49
+ *
50
+ * @param output - Raw output to validate (treated as unknown — ERR-001)
51
+ * @param taskId - Expected taskId for lineage verification (ERR-008)
52
+ * @returns Validation result with valid flag, errors, and optional error category
53
+ */
54
+ validate(output: unknown, taskId: string): Promise<{
55
+ valid: boolean;
56
+ errors: string[];
57
+ errorCategory?: string;
58
+ }>;
59
+ }
60
+ /**
61
+ * Default validator for DiagDistillerOutputV1 using TypeBox Value.Check / Value.Errors.
62
+ *
63
+ * Validates:
64
+ * 1. Structural correctness via TypeBox schema
65
+ * 2. taskId lineage match (ERR-008)
66
+ * 3. Core principle registry membership — every id in
67
+ * groundedOnCorePrincipleIds must pass isCorePrincipleId().
68
+ * Fabricated IDs (e.g. T-99) produce a validation failure with
69
+ * errorCategory 'output_invalid'.
70
+ *
71
+ * @see PRI-372
72
+ */
73
+ export declare class DefaultDiagDistillerValidator implements DiagDistillerValidator {
74
+ validate(output: unknown, taskId: string): Promise<{
75
+ valid: boolean;
76
+ errors: string[];
77
+ errorCategory?: string;
78
+ }>;
79
+ }
80
+ //# sourceMappingURL=diag-distiller-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diag-distiller-output.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/diagnostician/diag-distiller-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAMtD,eAAO,MAAM,wBAAwB,yLAInC,CAAC;AAEH,sDAAsD;AACtD,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAIzE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;EAuBtC,CAAC;AAEH,+DAA+D;AAC/D,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAI/E;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,QAAQ,CACN,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,6BAA8B,YAAW,sBAAsB;IAEpE,QAAQ,CACZ,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAuCzE"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Stage B (Distiller) output schema for the split diagnostician pipeline.
3
+ *
4
+ * The Distiller takes the root-cause artifact from Stage A and produces
5
+ * an abstracted, cross-scenario principle grounded on the T-01..T-10
6
+ * core axiom registry.
7
+ *
8
+ * @see PRI-372 — Split diagnostician into Stage A (Root Cause) + Stage B (Distiller)
9
+ */
10
+ import { Type } from '@sinclair/typebox';
11
+ import { Value } from '@sinclair/typebox/value';
12
+ import { isCorePrincipleId } from '../core-principles/core-principle-registry.js';
13
+ // ── Scope literal ─────────────────────────────────────────────────────────
14
+ export const DiagDistillerScopeSchema = Type.Union([
15
+ Type.Literal('general'),
16
+ Type.Literal('domain'),
17
+ Type.Literal('scenario'),
18
+ ]);
19
+ // ── Distiller Output V1 ──────────────────────────────────────────────────
20
+ /**
21
+ * TypeBox schema for Stage B (Distiller) output.
22
+ *
23
+ * Lineage consistency: `sourceRootCauseArtifactId` must match the artifact
24
+ * produced by Stage A so that the pipeline can trace every distilled
25
+ * principle back to its root-cause diagnosis.
26
+ *
27
+ * `groundedOnCorePrincipleIds` is validated against the T-01..T-10
28
+ * registry at runtime — fabricated IDs cause validation failure.
29
+ *
30
+ * @see PRI-372
31
+ */
32
+ export const DiagDistillerOutputV1Schema = Type.Object({
33
+ valid: Type.Boolean(),
34
+ taskId: Type.String({ minLength: 1 }),
35
+ sourceRootCauseArtifactId: Type.String({
36
+ minLength: 1,
37
+ description: 'Lineage consistency check — must match the artifact ID from Stage A',
38
+ }),
39
+ abstractedPrinciple: Type.String({
40
+ minLength: 1,
41
+ maxLength: 200,
42
+ description: 'Highly abstracted, cross-scenario principle (≤200 chars)',
43
+ }),
44
+ rationale: Type.String({
45
+ minLength: 1,
46
+ description: 'Why this principle addresses the root cause',
47
+ }),
48
+ groundedOnCorePrincipleIds: Type.Array(Type.String({ minLength: 1 }), {
49
+ description: 'Subset of T-01..T-10. Validated against registry — fabricated IDs cause validation failure.',
50
+ }),
51
+ scope: DiagDistillerScopeSchema,
52
+ confidence: Type.Number({ minimum: 0, maximum: 1 }),
53
+ ambiguityNotes: Type.Optional(Type.Array(Type.String())),
54
+ });
55
+ /**
56
+ * Default validator for DiagDistillerOutputV1 using TypeBox Value.Check / Value.Errors.
57
+ *
58
+ * Validates:
59
+ * 1. Structural correctness via TypeBox schema
60
+ * 2. taskId lineage match (ERR-008)
61
+ * 3. Core principle registry membership — every id in
62
+ * groundedOnCorePrincipleIds must pass isCorePrincipleId().
63
+ * Fabricated IDs (e.g. T-99) produce a validation failure with
64
+ * errorCategory 'output_invalid'.
65
+ *
66
+ * @see PRI-372
67
+ */
68
+ export class DefaultDiagDistillerValidator {
69
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
70
+ async validate(output, taskId) {
71
+ const errors = [];
72
+ // ── Step 1: Object guard ────────────────────────────────────────────────
73
+ if (typeof output !== 'object' || output === null) {
74
+ return { valid: false, errors: ['Output is not an object'], errorCategory: 'output_invalid' };
75
+ }
76
+ // Narrow to Record for property access — all fields still treated as untrusted.
77
+ const record = output;
78
+ // ── Step 2: taskId lineage check (ERR-008) ──────────────────────────────
79
+ if (typeof record.taskId !== 'string' || record.taskId !== taskId) {
80
+ errors.push(`taskId mismatch: expected ${taskId}, got ${String(record.taskId)}`);
81
+ }
82
+ // ── Step 3: TypeBox schema validation ───────────────────────────────────
83
+ if (!Value.Check(DiagDistillerOutputV1Schema, output)) {
84
+ const schemaErrors = [...Value.Errors(DiagDistillerOutputV1Schema, output)];
85
+ const messages = schemaErrors.map((e) => `${e.path}: ${e.message}`);
86
+ errors.push(...messages);
87
+ }
88
+ // ── Step 4: Core principle registry validation ──────────────────────────
89
+ // This constraint cannot be expressed in a TypeBox schema alone.
90
+ if (Array.isArray(record.groundedOnCorePrincipleIds)) {
91
+ for (const id of record.groundedOnCorePrincipleIds) {
92
+ if (typeof id === 'string' && !isCorePrincipleId(id)) {
93
+ errors.push(`Fabricated axiom ID ${id} not in core principle registry`);
94
+ }
95
+ }
96
+ }
97
+ if (errors.length > 0) {
98
+ return { valid: false, errors, errorCategory: 'output_invalid' };
99
+ }
100
+ return { valid: true, errors: [] };
101
+ }
102
+ }
103
+ //# sourceMappingURL=diag-distiller-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diag-distiller-output.js","sourceRoot":"","sources":["../../../src/runtime-v2/diagnostician/diag-distiller-output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Root Cause stage (Stage A) output schema for the split diagnostician pipeline.
3
+ *
4
+ * This schema defines the output of the Root Cause stage, which identifies
5
+ * the underlying cause of a pain signal using a 5-Whys causal chain and
6
+ * categorises it into one of four root-cause categories.
7
+ *
8
+ * The taskId field is lineage data re-injected by the runner if stripped
9
+ * by the adapter before LLM validation (ERR-008).
10
+ *
11
+ * @see PRI-372
12
+ */
13
+ import { type Static } from '@sinclair/typebox';
14
+ /**
15
+ * Root-cause category literal union.
16
+ *
17
+ * Every root cause MUST be classified into exactly one of these four
18
+ * categories. The category prefix in `rootCause` must match this value.
19
+ *
20
+ * @see PRI-372
21
+ */
22
+ export declare const RootCauseCategorySchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"People">, import("@sinclair/typebox").TLiteral<"Design">, import("@sinclair/typebox").TLiteral<"Assumption">, import("@sinclair/typebox").TLiteral<"Tooling">]>;
23
+ /** Root-cause category: People | Design | Assumption | Tooling */
24
+ export type RootCauseCategory = Static<typeof RootCauseCategorySchema>;
25
+ /**
26
+ * A single entry in the 5-Whys causal chain.
27
+ *
28
+ * `why` is 1-indexed (1 = shallowest, 5 = deepest).
29
+ */
30
+ export declare const CausalChainEntrySchema: import("@sinclair/typebox").TObject<{
31
+ why: import("@sinclair/typebox").TNumber;
32
+ statement: import("@sinclair/typebox").TString;
33
+ evidenceRefs: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
34
+ }>;
35
+ /** A single entry in the 5-Whys causal chain. */
36
+ export type CausalChainEntry = Static<typeof CausalChainEntrySchema>;
37
+ /**
38
+ * Evidence entry linking a source reference to an explanatory note.
39
+ */
40
+ export declare const DiagRootCauseEvidenceSchema: import("@sinclair/typebox").TObject<{
41
+ sourceRef: import("@sinclair/typebox").TString;
42
+ note: import("@sinclair/typebox").TString;
43
+ }>;
44
+ /** Evidence entry linking a source reference to an explanatory note. */
45
+ export type DiagRootCauseEvidence = Static<typeof DiagRootCauseEvidenceSchema>;
46
+ /**
47
+ * TypeBox schema for the Root Cause stage (Stage A) output.
48
+ *
49
+ * Consumed by the next pipeline stage and stored as a RunRecord output.
50
+ * The host layer (runner) is responsible for re-injecting `taskId` if
51
+ * the adapter strips lineage fields before LLM invocation (ERR-008).
52
+ *
53
+ * @see PRI-372
54
+ */
55
+ export declare const DiagRootCauseOutputV1Schema: import("@sinclair/typebox").TObject<{
56
+ valid: import("@sinclair/typebox").TBoolean;
57
+ diagnosisId: import("@sinclair/typebox").TString;
58
+ taskId: import("@sinclair/typebox").TString;
59
+ summary: import("@sinclair/typebox").TString;
60
+ causalChain: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
61
+ why: import("@sinclair/typebox").TNumber;
62
+ statement: import("@sinclair/typebox").TString;
63
+ evidenceRefs: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
64
+ }>>;
65
+ rootCause: import("@sinclair/typebox").TString;
66
+ rootCauseCategory: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"People">, import("@sinclair/typebox").TLiteral<"Design">, import("@sinclair/typebox").TLiteral<"Assumption">, import("@sinclair/typebox").TLiteral<"Tooling">]>;
67
+ evidence: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
68
+ sourceRef: import("@sinclair/typebox").TString;
69
+ note: import("@sinclair/typebox").TString;
70
+ }>>;
71
+ confidence: import("@sinclair/typebox").TNumber;
72
+ ambiguityNotes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
73
+ }>;
74
+ /** Typed output of the Root Cause stage (Stage A). */
75
+ export type DiagRootCauseOutputV1 = Static<typeof DiagRootCauseOutputV1Schema>;
76
+ /**
77
+ * Validator interface for DiagRootCauseOutputV1.
78
+ *
79
+ * Accepts `unknown` input — implementations must perform runtime checks (ERR-001).
80
+ *
81
+ * @see PRI-372
82
+ */
83
+ export interface DiagRootCauseValidator {
84
+ /**
85
+ * Validate untrusted root-cause stage output.
86
+ *
87
+ * @param output - Raw output to validate (treated as unknown — ERR-001)
88
+ * @param taskId - Expected taskId for lineage verification (ERR-008)
89
+ * @returns Validation result with valid flag, errors, and optional error category
90
+ */
91
+ validate(output: unknown, taskId: string): Promise<{
92
+ valid: boolean;
93
+ errors: string[];
94
+ errorCategory?: string;
95
+ }>;
96
+ }
97
+ /**
98
+ * Default validator for DiagRootCauseOutputV1 using TypeBox Value.Check / Value.Errors.
99
+ *
100
+ * Validates:
101
+ * 1. Structural correctness via TypeBox schema
102
+ * 2. taskId lineage match (ERR-008)
103
+ * 3. rootCauseCategory consistency with rootCause prefix
104
+ * 4. causalChain entry ordering (why field 1-5)
105
+ *
106
+ * @see PRI-372
107
+ */
108
+ export declare class DefaultDiagRootCauseValidator implements DiagRootCauseValidator {
109
+ validate(output: unknown, taskId: string): Promise<{
110
+ valid: boolean;
111
+ errors: string[];
112
+ errorCategory?: string;
113
+ }>;
114
+ }
115
+ //# sourceMappingURL=diag-rootcause-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diag-rootcause-output.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/diagnostician/diag-rootcause-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAKtD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,2OAKlC,CAAC;AAEH,kEAAkE;AAClE,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAEvE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;EAIjC,CAAC;AAEH,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAErE;;GAEG;AACH,eAAO,MAAM,2BAA2B;;;EAGtC,CAAC;AAEH,wEAAwE;AACxE,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAI/E;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;EActC,CAAC;AAEH,sDAAsD;AACtD,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAM/E;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClH;AAED;;;;;;;;;;GAUG;AACH,qBAAa,6BAA8B,YAAW,sBAAsB;IAEpE,QAAQ,CACZ,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CA0FzE"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Root Cause stage (Stage A) output schema for the split diagnostician pipeline.
3
+ *
4
+ * This schema defines the output of the Root Cause stage, which identifies
5
+ * the underlying cause of a pain signal using a 5-Whys causal chain and
6
+ * categorises it into one of four root-cause categories.
7
+ *
8
+ * The taskId field is lineage data re-injected by the runner if stripped
9
+ * by the adapter before LLM validation (ERR-008).
10
+ *
11
+ * @see PRI-372
12
+ */
13
+ import { Type } from '@sinclair/typebox';
14
+ import { Value } from '@sinclair/typebox/value';
15
+ // ── Sub-schemas ──────────────────────────────────────────────────────────────
16
+ /**
17
+ * Root-cause category literal union.
18
+ *
19
+ * Every root cause MUST be classified into exactly one of these four
20
+ * categories. The category prefix in `rootCause` must match this value.
21
+ *
22
+ * @see PRI-372
23
+ */
24
+ export const RootCauseCategorySchema = Type.Union([
25
+ Type.Literal('People'),
26
+ Type.Literal('Design'),
27
+ Type.Literal('Assumption'),
28
+ Type.Literal('Tooling'),
29
+ ]);
30
+ /**
31
+ * A single entry in the 5-Whys causal chain.
32
+ *
33
+ * `why` is 1-indexed (1 = shallowest, 5 = deepest).
34
+ */
35
+ export const CausalChainEntrySchema = Type.Object({
36
+ why: Type.Number({ minimum: 1, maximum: 5 }),
37
+ statement: Type.String({ minLength: 1 }),
38
+ evidenceRefs: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
39
+ });
40
+ /**
41
+ * Evidence entry linking a source reference to an explanatory note.
42
+ */
43
+ export const DiagRootCauseEvidenceSchema = Type.Object({
44
+ sourceRef: Type.String({ minLength: 1 }),
45
+ note: Type.String({ minLength: 1 }),
46
+ });
47
+ // ── Main output schema ───────────────────────────────────────────────────────
48
+ /**
49
+ * TypeBox schema for the Root Cause stage (Stage A) output.
50
+ *
51
+ * Consumed by the next pipeline stage and stored as a RunRecord output.
52
+ * The host layer (runner) is responsible for re-injecting `taskId` if
53
+ * the adapter strips lineage fields before LLM invocation (ERR-008).
54
+ *
55
+ * @see PRI-372
56
+ */
57
+ export const DiagRootCauseOutputV1Schema = Type.Object({
58
+ valid: Type.Boolean(),
59
+ diagnosisId: Type.String({ minLength: 1 }),
60
+ taskId: Type.String({ minLength: 1, description: 'Lineage — re-injected if stripped; ERR-008' }),
61
+ summary: Type.String({ minLength: 1 }),
62
+ causalChain: Type.Array(CausalChainEntrySchema),
63
+ rootCause: Type.String({
64
+ minLength: 1,
65
+ description: 'MUST include category prefix: "People: ..." or "Design: ..." or "Assumption: ..." or "Tooling: ..."',
66
+ }),
67
+ rootCauseCategory: RootCauseCategorySchema,
68
+ evidence: Type.Array(DiagRootCauseEvidenceSchema),
69
+ confidence: Type.Number({ minimum: 0, maximum: 1 }),
70
+ ambiguityNotes: Type.Optional(Type.Array(Type.String())),
71
+ });
72
+ // ── Validator ────────────────────────────────────────────────────────────────
73
+ const VALID_ROOT_CAUSE_CATEGORIES = new Set(['People', 'Design', 'Assumption', 'Tooling']);
74
+ /**
75
+ * Default validator for DiagRootCauseOutputV1 using TypeBox Value.Check / Value.Errors.
76
+ *
77
+ * Validates:
78
+ * 1. Structural correctness via TypeBox schema
79
+ * 2. taskId lineage match (ERR-008)
80
+ * 3. rootCauseCategory consistency with rootCause prefix
81
+ * 4. causalChain entry ordering (why field 1-5)
82
+ *
83
+ * @see PRI-372
84
+ */
85
+ export class DefaultDiagRootCauseValidator {
86
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
87
+ async validate(output, taskId) {
88
+ const errors = [];
89
+ // ── Step 1: Object guard ────────────────────────────────────────────────
90
+ if (typeof output !== 'object' || output === null) {
91
+ return { valid: false, errors: ['Output is not an object'], errorCategory: 'output_invalid' };
92
+ }
93
+ // Narrow to Record for property access — all fields still treated as untrusted.
94
+ const record = output;
95
+ // ── Step 2: taskId lineage check (ERR-008) ──────────────────────────────
96
+ if (typeof record.taskId !== 'string' || record.taskId !== taskId) {
97
+ errors.push(`taskId mismatch: expected ${taskId}, got ${String(record.taskId)}`);
98
+ }
99
+ // ── Step 3: valid flag must be true ─────────────────────────────────────
100
+ if (record.valid !== true) {
101
+ errors.push('output.valid must be true');
102
+ }
103
+ // ── Step 4: rootCauseCategory semantic check ────────────────────────────
104
+ if (typeof record.rootCauseCategory !== 'string' || !VALID_ROOT_CAUSE_CATEGORIES.has(record.rootCauseCategory)) {
105
+ errors.push(`rootCauseCategory must be one of People|Design|Assumption|Tooling, got ${String(record.rootCauseCategory)}`);
106
+ }
107
+ // ── Step 4b: rootCause prefix must match rootCauseCategory ──────────────
108
+ if (typeof record.rootCause === 'string'
109
+ && typeof record.rootCauseCategory === 'string'
110
+ && VALID_ROOT_CAUSE_CATEGORIES.has(record.rootCauseCategory)) {
111
+ const expectedPrefix = `${record.rootCauseCategory}: `;
112
+ if (!record.rootCause.startsWith(expectedPrefix)) {
113
+ errors.push(`rootCause must start with "${expectedPrefix}" (matching rootCauseCategory "${record.rootCauseCategory}"), got: "${record.rootCause.slice(0, 40)}${record.rootCause.length > 40 ? '...' : ''}"`);
114
+ }
115
+ }
116
+ // ── Step 5: causalChain entry-level checks ──────────────────────────────
117
+ if (Array.isArray(record.causalChain)) {
118
+ for (let i = 0; i < record.causalChain.length; i++) {
119
+ const entry = record.causalChain[i];
120
+ if (!entry || typeof entry !== 'object') {
121
+ errors.push(`causalChain[${i}] must be an object`);
122
+ continue;
123
+ }
124
+ if (typeof entry.why !== 'number' || entry.why < 1 || entry.why > 5) {
125
+ errors.push(`causalChain[${i}].why must be a number in [1, 5]`);
126
+ }
127
+ if (typeof entry.statement !== 'string' || entry.statement.trim() === '') {
128
+ errors.push(`causalChain[${i}].statement must be a non-empty string`);
129
+ }
130
+ if (!Array.isArray(entry.evidenceRefs)) {
131
+ errors.push(`causalChain[${i}].evidenceRefs must be an array`);
132
+ }
133
+ else if (entry.evidenceRefs.length === 0) {
134
+ errors.push(`causalChain[${i}].evidenceRefs must have at least 1 item`);
135
+ }
136
+ }
137
+ }
138
+ // ── Step 6: evidence entry-level checks ─────────────────────────────────
139
+ if (Array.isArray(record.evidence)) {
140
+ for (let i = 0; i < record.evidence.length; i++) {
141
+ const ev = record.evidence[i];
142
+ if (!ev || typeof ev !== 'object') {
143
+ errors.push(`evidence[${i}] must be an object`);
144
+ continue;
145
+ }
146
+ if (typeof ev.sourceRef !== 'string' || ev.sourceRef.trim() === '') {
147
+ errors.push(`evidence[${i}].sourceRef must be a non-empty string`);
148
+ }
149
+ if (typeof ev.note !== 'string' || ev.note.trim() === '') {
150
+ errors.push(`evidence[${i}].note must be a non-empty string`);
151
+ }
152
+ }
153
+ }
154
+ // ── Step 7: TypeBox schema validation as fallback ───────────────────────
155
+ if (!Value.Check(DiagRootCauseOutputV1Schema, output)) {
156
+ const schemaErrors = [...Value.Errors(DiagRootCauseOutputV1Schema, output)];
157
+ const messages = schemaErrors.map((e) => `${e.path}: ${e.message}`);
158
+ errors.push(...messages);
159
+ }
160
+ if (errors.length > 0) {
161
+ return { valid: false, errors, errorCategory: 'output_invalid' };
162
+ }
163
+ return { valid: true, errors: [] };
164
+ }
165
+ }
166
+ //# sourceMappingURL=diag-rootcause-output.js.map