create-principles-disciple 1.92.0 → 1.94.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 (335) hide show
  1. package/console/dist/server/config/AuthConfig.js +6 -0
  2. package/console/dist/server/config/pd-config-store.d.ts +7 -1
  3. package/console/dist/server/config/pd-config-store.js +11 -1
  4. package/console/dist/server/index.js +41 -22
  5. package/console/dist/server/models/ApprovalsConsoleModel.js +4 -12
  6. package/console/dist/server/models/ApprovalsGroupedConsoleModel.js +6 -3
  7. package/console/dist/server/models/ConsoleLifecycleDatasource.js +1 -1
  8. package/console/dist/server/routes/activations.js +4 -0
  9. package/console/dist/server/routes/approvals.js +24 -4
  10. package/console/dist/server/routes/feedback-reports.js +7 -5
  11. package/console/dist/server/routes/lifecycle.js +6 -1
  12. package/console/dist/server/routes/principles.js +10 -2
  13. package/console/dist/server/routes/workspaces.js +4 -0
  14. package/console/dist/ui/components/ui/charts.js +4 -1
  15. package/console/dist/ui/components/ui/markdown.js +9 -5
  16. package/console/dist/ui/utils/enum-labels.js +4 -1
  17. package/console/dist/web/assets/app.js +5 -2
  18. package/core/dist/index.d.ts +2 -3
  19. package/core/dist/index.d.ts.map +1 -1
  20. package/core/dist/index.js +1 -3
  21. package/core/dist/index.js.map +1 -1
  22. package/core/dist/pain-signal.d.ts +11 -71
  23. package/core/dist/pain-signal.d.ts.map +1 -1
  24. package/core/dist/pain-signal.js +10 -120
  25. package/core/dist/pain-signal.js.map +1 -1
  26. package/core/dist/principle-tree-ledger.d.ts +4 -87
  27. package/core/dist/principle-tree-ledger.d.ts.map +1 -1
  28. package/core/dist/principle-tree-ledger.js +51 -148
  29. package/core/dist/principle-tree-ledger.js.map +1 -1
  30. package/core/dist/prompt-builder/__tests__/model-config.test.d.ts +2 -0
  31. package/core/dist/prompt-builder/__tests__/model-config.test.d.ts.map +1 -0
  32. package/core/dist/prompt-builder/__tests__/model-config.test.js +158 -0
  33. package/core/dist/prompt-builder/__tests__/model-config.test.js.map +1 -0
  34. package/core/dist/prompt-builder/__tests__/xml-escape.test.d.ts +2 -0
  35. package/core/dist/prompt-builder/__tests__/xml-escape.test.d.ts.map +1 -0
  36. package/core/dist/prompt-builder/__tests__/xml-escape.test.js +42 -0
  37. package/core/dist/prompt-builder/__tests__/xml-escape.test.js.map +1 -0
  38. package/core/dist/prompt-builder/index.d.ts +3 -0
  39. package/core/dist/prompt-builder/index.d.ts.map +1 -1
  40. package/core/dist/prompt-builder/index.js +2 -0
  41. package/core/dist/prompt-builder/index.js.map +1 -1
  42. package/core/dist/prompt-builder/model-config.d.ts +42 -0
  43. package/core/dist/prompt-builder/model-config.d.ts.map +1 -0
  44. package/core/dist/prompt-builder/model-config.js +84 -0
  45. package/core/dist/prompt-builder/model-config.js.map +1 -0
  46. package/core/dist/prompt-builder/xml-escape.d.ts +12 -0
  47. package/core/dist/prompt-builder/xml-escape.d.ts.map +1 -0
  48. package/core/dist/prompt-builder/xml-escape.js +19 -0
  49. package/core/dist/prompt-builder/xml-escape.js.map +1 -0
  50. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +265 -20
  51. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  52. package/core/dist/runtime-v2/__tests__/barrel-io-cleanup.test.d.ts +12 -0
  53. package/core/dist/runtime-v2/__tests__/barrel-io-cleanup.test.d.ts.map +1 -0
  54. package/core/dist/runtime-v2/__tests__/barrel-io-cleanup.test.js +46 -0
  55. package/core/dist/runtime-v2/__tests__/barrel-io-cleanup.test.js.map +1 -0
  56. package/core/dist/runtime-v2/__tests__/io-deletion.test.d.ts +12 -0
  57. package/core/dist/runtime-v2/__tests__/io-deletion.test.d.ts.map +1 -0
  58. package/core/dist/runtime-v2/__tests__/io-deletion.test.js +92 -0
  59. package/core/dist/runtime-v2/__tests__/io-deletion.test.js.map +1 -0
  60. package/core/dist/runtime-v2/__tests__/ledger-codec.test.d.ts +2 -0
  61. package/core/dist/runtime-v2/__tests__/ledger-codec.test.d.ts.map +1 -0
  62. package/core/dist/runtime-v2/__tests__/ledger-codec.test.js +429 -0
  63. package/core/dist/runtime-v2/__tests__/ledger-codec.test.js.map +1 -0
  64. package/core/dist/runtime-v2/__tests__/ledger-store.test.d.ts +2 -0
  65. package/core/dist/runtime-v2/__tests__/ledger-store.test.d.ts.map +1 -0
  66. package/core/dist/runtime-v2/__tests__/ledger-store.test.js +65 -0
  67. package/core/dist/runtime-v2/__tests__/ledger-store.test.js.map +1 -0
  68. package/core/dist/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.d.ts +2 -0
  69. package/core/dist/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.d.ts.map +1 -0
  70. package/core/dist/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.js +395 -0
  71. package/core/dist/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.js.map +1 -0
  72. package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js +146 -0
  73. package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js.map +1 -1
  74. package/core/dist/runtime-v2/__tests__/pain-signal-unification.test.d.ts +2 -0
  75. package/core/dist/runtime-v2/__tests__/pain-signal-unification.test.d.ts.map +1 -0
  76. package/core/dist/runtime-v2/__tests__/pain-signal-unification.test.js +150 -0
  77. package/core/dist/runtime-v2/__tests__/pain-signal-unification.test.js.map +1 -0
  78. package/core/dist/runtime-v2/adapter/__tests__/test-double-runtime-adapter.test.js +199 -0
  79. package/core/dist/runtime-v2/adapter/__tests__/test-double-runtime-adapter.test.js.map +1 -1
  80. package/core/dist/runtime-v2/bridge-result-shaper.d.ts +53 -0
  81. package/core/dist/runtime-v2/bridge-result-shaper.d.ts.map +1 -0
  82. package/core/dist/runtime-v2/bridge-result-shaper.js +117 -0
  83. package/core/dist/runtime-v2/bridge-result-shaper.js.map +1 -0
  84. package/core/dist/runtime-v2/detection/__tests__/detection-funnel-policy.test.d.ts +13 -0
  85. package/core/dist/runtime-v2/detection/__tests__/detection-funnel-policy.test.d.ts.map +1 -0
  86. package/core/dist/runtime-v2/detection/__tests__/detection-funnel-policy.test.js +111 -0
  87. package/core/dist/runtime-v2/detection/__tests__/detection-funnel-policy.test.js.map +1 -0
  88. package/core/dist/runtime-v2/detection/detection-funnel-policy.d.ts +103 -0
  89. package/core/dist/runtime-v2/detection/detection-funnel-policy.d.ts.map +1 -0
  90. package/core/dist/runtime-v2/detection/detection-funnel-policy.js +135 -0
  91. package/core/dist/runtime-v2/detection/detection-funnel-policy.js.map +1 -0
  92. package/core/dist/runtime-v2/detection/index.d.ts +10 -0
  93. package/core/dist/runtime-v2/detection/index.d.ts.map +1 -0
  94. package/core/dist/runtime-v2/detection/index.js +9 -0
  95. package/core/dist/runtime-v2/detection/index.js.map +1 -0
  96. package/core/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.js +156 -0
  97. package/core/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.js.map +1 -1
  98. package/core/dist/runtime-v2/evidence-triage/__tests__/observation-resolver.test.d.ts +12 -0
  99. package/core/dist/runtime-v2/evidence-triage/__tests__/observation-resolver.test.d.ts.map +1 -0
  100. package/core/dist/runtime-v2/evidence-triage/__tests__/observation-resolver.test.js +181 -0
  101. package/core/dist/runtime-v2/evidence-triage/__tests__/observation-resolver.test.js.map +1 -0
  102. package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.js +104 -1
  103. package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.js.map +1 -1
  104. package/core/dist/runtime-v2/evidence-triage/index.d.ts +3 -0
  105. package/core/dist/runtime-v2/evidence-triage/index.d.ts.map +1 -1
  106. package/core/dist/runtime-v2/evidence-triage/index.js +3 -0
  107. package/core/dist/runtime-v2/evidence-triage/index.js.map +1 -1
  108. package/core/dist/runtime-v2/evidence-triage/observation-resolver.d.ts +128 -0
  109. package/core/dist/runtime-v2/evidence-triage/observation-resolver.d.ts.map +1 -0
  110. package/core/dist/runtime-v2/evidence-triage/observation-resolver.js +203 -0
  111. package/core/dist/runtime-v2/evidence-triage/observation-resolver.js.map +1 -0
  112. package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts +4 -0
  113. package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts.map +1 -1
  114. package/core/dist/runtime-v2/evidence-triage/triage-policy.js +66 -9
  115. package/core/dist/runtime-v2/evidence-triage/triage-policy.js.map +1 -1
  116. package/core/dist/runtime-v2/evidence-triage/types.d.ts +14 -0
  117. package/core/dist/runtime-v2/evidence-triage/types.d.ts.map +1 -1
  118. package/core/dist/runtime-v2/evidence-triage/types.js.map +1 -1
  119. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +33 -4
  120. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  121. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
  122. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +9 -2
  123. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  124. package/core/dist/runtime-v2/feedback/__tests__/redact-sensitive.test.d.ts +15 -0
  125. package/core/dist/runtime-v2/feedback/__tests__/redact-sensitive.test.d.ts.map +1 -0
  126. package/core/dist/runtime-v2/feedback/__tests__/redact-sensitive.test.js +450 -0
  127. package/core/dist/runtime-v2/feedback/__tests__/redact-sensitive.test.js.map +1 -0
  128. package/core/dist/runtime-v2/feedback/__tests__/render-github-url.test.d.ts +13 -0
  129. package/core/dist/runtime-v2/feedback/__tests__/render-github-url.test.d.ts.map +1 -0
  130. package/core/dist/runtime-v2/feedback/__tests__/render-github-url.test.js +243 -0
  131. package/core/dist/runtime-v2/feedback/__tests__/render-github-url.test.js.map +1 -0
  132. package/core/dist/runtime-v2/feedback/__tests__/safe-stringify.test.d.ts +12 -0
  133. package/core/dist/runtime-v2/feedback/__tests__/safe-stringify.test.d.ts.map +1 -0
  134. package/core/dist/runtime-v2/feedback/__tests__/safe-stringify.test.js +172 -0
  135. package/core/dist/runtime-v2/feedback/__tests__/safe-stringify.test.js.map +1 -0
  136. package/core/dist/runtime-v2/index.d.ts +9 -6
  137. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  138. package/core/dist/runtime-v2/index.js +8 -4
  139. package/core/dist/runtime-v2/index.js.map +1 -1
  140. package/core/dist/runtime-v2/internalization/__tests__/c2-live-runner-chain.test.d.ts +2 -0
  141. package/core/dist/runtime-v2/internalization/__tests__/c2-live-runner-chain.test.d.ts.map +1 -0
  142. package/core/dist/runtime-v2/internalization/__tests__/c2-live-runner-chain.test.js +306 -0
  143. package/core/dist/runtime-v2/internalization/__tests__/c2-live-runner-chain.test.js.map +1 -0
  144. package/core/dist/runtime-v2/internalization/index.d.ts +0 -16
  145. package/core/dist/runtime-v2/internalization/index.d.ts.map +1 -1
  146. package/core/dist/runtime-v2/internalization/index.js +0 -8
  147. package/core/dist/runtime-v2/internalization/index.js.map +1 -1
  148. package/core/dist/runtime-v2/pain-gate/__tests__/pain-diagnostic-gate-policy.test.d.ts +15 -0
  149. package/core/dist/runtime-v2/pain-gate/__tests__/pain-diagnostic-gate-policy.test.d.ts.map +1 -0
  150. package/core/dist/runtime-v2/pain-gate/__tests__/pain-diagnostic-gate-policy.test.js +179 -0
  151. package/core/dist/runtime-v2/pain-gate/__tests__/pain-diagnostic-gate-policy.test.js.map +1 -0
  152. package/core/dist/runtime-v2/pain-gate/index.d.ts +10 -0
  153. package/core/dist/runtime-v2/pain-gate/index.d.ts.map +1 -0
  154. package/core/dist/runtime-v2/pain-gate/index.js +9 -0
  155. package/core/dist/runtime-v2/pain-gate/index.js.map +1 -0
  156. package/core/dist/runtime-v2/pain-gate/pain-diagnostic-gate-policy.d.ts +121 -0
  157. package/core/dist/runtime-v2/pain-gate/pain-diagnostic-gate-policy.d.ts.map +1 -0
  158. package/core/dist/runtime-v2/pain-gate/pain-diagnostic-gate-policy.js +157 -0
  159. package/core/dist/runtime-v2/pain-gate/pain-diagnostic-gate-policy.js.map +1 -0
  160. package/core/dist/runtime-v2/pain-signal-bridge.d.ts.map +1 -1
  161. package/core/dist/runtime-v2/pain-signal-bridge.js +14 -88
  162. package/core/dist/runtime-v2/pain-signal-bridge.js.map +1 -1
  163. package/core/dist/runtime-v2/pain-signal-observability.d.ts.map +1 -1
  164. package/core/dist/runtime-v2/pain-signal-observability.js +15 -5
  165. package/core/dist/runtime-v2/pain-signal-observability.js.map +1 -1
  166. package/core/dist/runtime-v2/principle-tree/ledger-codec.d.ts +30 -0
  167. package/core/dist/runtime-v2/principle-tree/ledger-codec.d.ts.map +1 -0
  168. package/core/dist/runtime-v2/principle-tree/ledger-codec.js +154 -0
  169. package/core/dist/runtime-v2/principle-tree/ledger-codec.js.map +1 -0
  170. package/core/dist/runtime-v2/types/event-types.d.ts +0 -27
  171. package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
  172. package/core/dist/runtime-v2/types/event-types.js +2 -17
  173. package/core/dist/runtime-v2/types/event-types.js.map +1 -1
  174. package/core/dist/runtime-v2/types/index.d.ts +4 -2
  175. package/core/dist/runtime-v2/types/index.d.ts.map +1 -1
  176. package/core/dist/runtime-v2/types/index.js +4 -1
  177. package/core/dist/runtime-v2/types/index.js.map +1 -1
  178. package/core/dist/runtime-v2/types/ledger-store.d.ts +101 -0
  179. package/core/dist/runtime-v2/types/ledger-store.d.ts.map +1 -0
  180. package/core/dist/runtime-v2/types/ledger-store.js +15 -0
  181. package/core/dist/runtime-v2/types/ledger-store.js.map +1 -0
  182. package/core/dist/runtime-v2/types/pain-signal.d.ts +7 -5
  183. package/core/dist/runtime-v2/types/pain-signal.d.ts.map +1 -1
  184. package/core/dist/runtime-v2/types/pain-signal.js +25 -5
  185. package/core/dist/runtime-v2/types/pain-signal.js.map +1 -1
  186. package/core/package.json +3 -3
  187. package/dist/installer.d.ts.map +1 -1
  188. package/dist/installer.js +9 -3
  189. package/dist/installer.js.map +1 -1
  190. package/dist/mvp-config.d.ts +0 -10
  191. package/dist/mvp-config.d.ts.map +1 -1
  192. package/dist/mvp-config.js +0 -64
  193. package/dist/mvp-config.js.map +1 -1
  194. package/dist/utils/env.d.ts.map +1 -1
  195. package/dist/utils/env.js +10 -4
  196. package/dist/utils/env.js.map +1 -1
  197. package/package.json +1 -1
  198. package/pd-cli/dist/commands/__tests__/legacy-cleanup.test.js +11 -3
  199. package/pd-cli/dist/commands/__tests__/legacy-cleanup.test.js.map +1 -1
  200. package/pd-cli/dist/commands/candidate.d.ts.map +1 -1
  201. package/pd-cli/dist/commands/candidate.js +2 -1
  202. package/pd-cli/dist/commands/candidate.js.map +1 -1
  203. package/pd-cli/dist/commands/health.d.ts.map +1 -1
  204. package/pd-cli/dist/commands/health.js +2 -1
  205. package/pd-cli/dist/commands/health.js.map +1 -1
  206. package/pd-cli/dist/commands/mvp-smoke.js +1 -1
  207. package/pd-cli/dist/commands/mvp-smoke.js.map +1 -1
  208. package/pd-cli/dist/commands/rulecode.js +1 -1
  209. package/pd-cli/dist/commands/rulecode.js.map +1 -1
  210. package/pd-cli/dist/commands/runtime-canary.d.ts.map +1 -1
  211. package/pd-cli/dist/commands/runtime-canary.js +10 -11
  212. package/pd-cli/dist/commands/runtime-canary.js.map +1 -1
  213. package/pd-cli/dist/commands/runtime-internalization-integrity.d.ts.map +1 -1
  214. package/pd-cli/dist/commands/runtime-internalization-integrity.js +3 -1
  215. package/pd-cli/dist/commands/runtime-internalization-integrity.js.map +1 -1
  216. package/pd-cli/dist/commands/runtime-internalization-queue.d.ts.map +1 -1
  217. package/pd-cli/dist/commands/runtime-internalization-queue.js +13 -16
  218. package/pd-cli/dist/commands/runtime-internalization-queue.js.map +1 -1
  219. package/pd-cli/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
  220. package/pd-cli/dist/commands/runtime-internalization-run-once.js +3 -0
  221. package/pd-cli/dist/commands/runtime-internalization-run-once.js.map +1 -1
  222. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.d.ts.map +1 -1
  223. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.js +61 -7
  224. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.js.map +1 -1
  225. package/pd-cli/dist/commands/runtime-uat.d.ts.map +1 -1
  226. package/pd-cli/dist/commands/runtime-uat.js +4 -1
  227. package/pd-cli/dist/commands/runtime-uat.js.map +1 -1
  228. package/pd-cli/dist/commands/runtime.js +1 -1
  229. package/pd-cli/dist/commands/runtime.js.map +1 -1
  230. package/pd-cli/dist/index.js +67 -34
  231. package/pd-cli/dist/index.js.map +1 -1
  232. package/pd-cli/dist/legacy/session-history-import.js +7 -5
  233. package/pd-cli/dist/legacy/session-history-import.js.map +1 -1
  234. package/pd-cli/dist/services/__tests__/rulehost-readiness.test.d.ts +2 -0
  235. package/pd-cli/dist/services/__tests__/rulehost-readiness.test.d.ts.map +1 -0
  236. package/pd-cli/dist/services/__tests__/rulehost-readiness.test.js +314 -0
  237. package/pd-cli/dist/services/__tests__/rulehost-readiness.test.js.map +1 -0
  238. package/pd-cli/dist/services/__tests__/runtime-adapter-resolver.test.js +33 -14
  239. package/pd-cli/dist/services/__tests__/runtime-adapter-resolver.test.js.map +1 -1
  240. package/pd-cli/dist/services/pain-flood-simulation-runner.d.ts.map +1 -1
  241. package/pd-cli/dist/services/pain-flood-simulation-runner.js +6 -2
  242. package/pd-cli/dist/services/pain-flood-simulation-runner.js.map +1 -1
  243. package/pd-cli/dist/services/rulehost-readiness.d.ts +62 -0
  244. package/pd-cli/dist/services/rulehost-readiness.d.ts.map +1 -0
  245. package/pd-cli/dist/services/rulehost-readiness.js +214 -0
  246. package/pd-cli/dist/services/rulehost-readiness.js.map +1 -0
  247. package/pd-cli/dist/services/runtime-adapter-resolver.d.ts +1 -1
  248. package/pd-cli/dist/services/runtime-adapter-resolver.d.ts.map +1 -1
  249. package/pd-cli/dist/services/runtime-adapter-resolver.js +9 -7
  250. package/pd-cli/dist/services/runtime-adapter-resolver.js.map +1 -1
  251. package/plugin/dist/commands/capabilities.js +3 -2
  252. package/plugin/dist/commands/disable-impl.js +1 -1
  253. package/plugin/dist/commands/evolution-status.js +0 -2
  254. package/plugin/dist/commands/focus.js +10 -2
  255. package/plugin/dist/commands/rollback-impl.js +1 -1
  256. package/plugin/dist/commands/thinking-os.js +5 -1
  257. package/plugin/dist/core/correction-cue-learner.js +2 -0
  258. package/plugin/dist/core/detection-funnel.d.ts +25 -11
  259. package/plugin/dist/core/detection-funnel.js +32 -80
  260. package/plugin/dist/core/event-log.d.ts +1 -3
  261. package/plugin/dist/core/event-log.js +27 -31
  262. package/plugin/dist/core/evolution-reducer.d.ts +0 -8
  263. package/plugin/dist/core/evolution-reducer.js +9 -19
  264. package/plugin/dist/core/focus-history.js +1 -1
  265. package/plugin/dist/core/hygiene/tracker.js +3 -3
  266. package/plugin/dist/core/pain-diagnostic-gate.d.ts +37 -28
  267. package/plugin/dist/core/pain-diagnostic-gate.js +53 -89
  268. package/plugin/dist/core/pain.d.ts +0 -63
  269. package/plugin/dist/core/pain.js +0 -167
  270. package/plugin/dist/core/paths.d.ts +0 -1
  271. package/plugin/dist/core/paths.js +2 -1
  272. package/plugin/dist/core/principle-compiler/compiler.js +2 -0
  273. package/plugin/dist/core/replay-engine.js +1 -1
  274. package/plugin/dist/core/rule-host.js +3 -1
  275. package/plugin/dist/core/schema/migrations/001-init-trajectory.js +3 -6
  276. package/plugin/dist/core/schema/schema-definitions.js +4 -9
  277. package/plugin/dist/core/thinking-os-parser.js +13 -4
  278. package/plugin/dist/core/trajectory.d.ts +0 -16
  279. package/plugin/dist/core/trajectory.js +9 -60
  280. package/plugin/dist/hooks/after-tool-call-helpers.d.ts +4 -1
  281. package/plugin/dist/hooks/after-tool-call-helpers.js +13 -17
  282. package/plugin/dist/hooks/gate-block-helper.js +57 -17
  283. package/plugin/dist/hooks/lifecycle.js +3 -6
  284. package/plugin/dist/hooks/llm.js +66 -26
  285. package/plugin/dist/hooks/pain.d.ts +3 -1
  286. package/plugin/dist/hooks/pain.js +119 -49
  287. package/plugin/dist/hooks/prompt-helpers.d.ts +87 -0
  288. package/plugin/dist/hooks/prompt-helpers.js +251 -0
  289. package/plugin/dist/hooks/prompt-types.d.ts +66 -0
  290. package/plugin/dist/hooks/prompt-types.js +12 -0
  291. package/plugin/dist/hooks/prompt.d.ts +7 -38
  292. package/plugin/dist/hooks/prompt.js +361 -325
  293. package/plugin/dist/hooks/raw-observation-adapter.d.ts +9 -50
  294. package/plugin/dist/hooks/raw-observation-adapter.js +9 -164
  295. package/plugin/dist/hooks/raw-observation-types.d.ts +6 -57
  296. package/plugin/dist/hooks/raw-observation-types.js +5 -9
  297. package/plugin/dist/hooks/trajectory-collector.d.ts +20 -4
  298. package/plugin/dist/hooks/trajectory-collector.js +95 -156
  299. package/plugin/dist/hooks/triage-adapter.js +6 -26
  300. package/plugin/dist/hooks/trigger-cooldown-tracker.d.ts +12 -0
  301. package/plugin/dist/hooks/trigger-cooldown-tracker.js +25 -0
  302. package/plugin/dist/index.js +7 -2
  303. package/plugin/dist/openclaw-sdk.d.ts +4 -1
  304. package/plugin/dist/service/evolution-worker.js +8 -62
  305. package/plugin/dist/service/internalization-auto-consumer-service.js +2 -1
  306. package/plugin/dist/service/runtime-summary-service.d.ts +0 -2
  307. package/plugin/dist/service/runtime-summary-service.js +8 -5
  308. package/plugin/dist/service/workflow-watchdog.js +2 -1
  309. package/plugin/dist/types/event-types.d.ts +1 -1
  310. package/plugin/dist/utils/retry.js +7 -2
  311. package/plugin/dist/utils/session-key.js +4 -1
  312. package/plugin/scripts/sync-plugin.mjs +33 -22
  313. package/plugin/scripts/validate-live-path.ts +0 -18
  314. package/plugin/templates/langs/en/skills/pd-cli-operator/SKILL.md +20 -11
  315. package/plugin/templates/langs/en/skills/pd-runtime-v2/SKILL.md +10 -0
  316. package/plugin/templates/langs/zh/skills/pd-cli-operator/SKILL.md +20 -11
  317. package/plugin/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +10 -0
  318. package/console/dist/server/config/feature-flags.d.ts +0 -25
  319. package/console/dist/server/config/feature-flags.js +0 -101
  320. package/core/dist/io.d.ts +0 -35
  321. package/core/dist/io.d.ts.map +0 -1
  322. package/core/dist/io.js +0 -95
  323. package/core/dist/io.js.map +0 -1
  324. package/pd-cli/dist/commands/central-sync.d.ts +0 -10
  325. package/pd-cli/dist/commands/central-sync.d.ts.map +0 -1
  326. package/pd-cli/dist/commands/central-sync.js +0 -32
  327. package/pd-cli/dist/commands/central-sync.js.map +0 -1
  328. package/pd-cli/dist/services/feature-flag-loader.d.ts +0 -6
  329. package/pd-cli/dist/services/feature-flag-loader.d.ts.map +0 -1
  330. package/pd-cli/dist/services/feature-flag-loader.js +0 -53
  331. package/pd-cli/dist/services/feature-flag-loader.js.map +0 -1
  332. package/plugin/dist/core/observability.d.ts +0 -40
  333. package/plugin/dist/core/observability.js +0 -164
  334. package/plugin/dist/hooks/subagent.d.ts +0 -9
  335. package/plugin/dist/hooks/subagent.js +0 -122
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ledger-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-store.test.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/__tests__/ledger-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * PRI-443: Ledger store types module — pure type definitions, zero I/O.
3
+ *
4
+ * Tests verify:
5
+ * 1. All types are importable from the new pure module
6
+ * 2. The module has zero fs/path imports
7
+ * 3. TREE_NAMESPACE constant is available
8
+ */
9
+ import { describe, it, expect } from 'vitest';
10
+ import { readFileSync } from 'node:fs';
11
+ import { resolve } from 'node:path';
12
+ import { TREE_NAMESPACE } from '../types/ledger-store.js';
13
+ describe('PRI-443: ledger-store.ts pure types module', () => {
14
+ it('TREE_NAMESPACE constant is exported and equals _tree', () => {
15
+ expect(TREE_NAMESPACE).toBe('_tree');
16
+ });
17
+ it('LedgerPrinciple extends Principle with optional fields', () => {
18
+ const principle = {
19
+ id: 'pri-001',
20
+ version: 1,
21
+ text: 'Test principle',
22
+ triggerPattern: 'test',
23
+ action: 'test',
24
+ status: 'active',
25
+ priority: 'P0',
26
+ scope: 'general',
27
+ evaluability: 'manual_only',
28
+ valueScore: 0.5,
29
+ adherenceRate: 0.8,
30
+ painPreventedCount: 0,
31
+ derivedFromPainIds: [],
32
+ ruleIds: [],
33
+ conflictsWithPrincipleIds: [],
34
+ createdAt: '2026-01-01T00:00:00Z',
35
+ updatedAt: '2026-01-01T00:00:00Z',
36
+ suggestedRules: ['rule-1'],
37
+ lastTriggeredAt: '2026-01-02T00:00:00Z',
38
+ };
39
+ expect(principle.id).toBe('pri-001');
40
+ expect(principle.suggestedRules).toEqual(['rule-1']);
41
+ expect(principle.lastTriggeredAt).toBe('2026-01-02T00:00:00Z');
42
+ });
43
+ it('HybridLedgerStore has trainingStore and tree', () => {
44
+ const store = {
45
+ trainingStore: {},
46
+ tree: {
47
+ principles: {},
48
+ rules: {},
49
+ implementations: {},
50
+ metrics: {},
51
+ lastUpdated: '2026-01-01T00:00:00Z',
52
+ },
53
+ };
54
+ expect(store.trainingStore).toEqual({});
55
+ expect(store.tree.principles).toEqual({});
56
+ });
57
+ it('ledger-store.ts has zero fs/path imports (pure module)', () => {
58
+ const src = readFileSync(resolve(__dirname, '..', 'types', 'ledger-store.ts'), 'utf-8');
59
+ expect(src).not.toMatch(/from\s+['"]fs['"]/);
60
+ expect(src).not.toMatch(/from\s+['"]path['"]/);
61
+ expect(src).not.toMatch(/from\s+['"]node:fs/);
62
+ expect(src).not.toMatch(/from\s+['"]node:path/);
63
+ });
64
+ });
65
+ //# sourceMappingURL=ledger-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-store.test.js","sourceRoot":"","sources":["../../../src/runtime-v2/__tests__/ledger-store.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IAC1D,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,SAAS,GAAoB;YACjC,EAAE,EAAE,SAAS;YACb,OAAO,EAAE,CAAC;YACV,IAAI,EAAE,gBAAgB;YACtB,cAAc,EAAE,MAAM;YACtB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,SAAS;YAChB,YAAY,EAAE,aAAa;YAC3B,UAAU,EAAE,GAAG;YACf,aAAa,EAAE,GAAG;YAClB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,EAAE;YACtB,OAAO,EAAE,EAAE;YACX,yBAAyB,EAAE,EAAE;YAC7B,SAAS,EAAE,sBAAsB;YACjC,SAAS,EAAE,sBAAsB;YACjC,cAAc,EAAE,CAAC,QAAQ,CAAC;YAC1B,eAAe,EAAE,sBAAsB;SACxC,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAsB;YAC/B,aAAa,EAAE,EAAE;YACjB,IAAI,EAAE;gBACJ,UAAU,EAAE,EAAE;gBACd,KAAK,EAAE,EAAE;gBACT,eAAe,EAAE,EAAE;gBACnB,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,sBAAsB;aACpC;SACF,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,GAAG,GAAG,YAAY,CACtB,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,CAAC,EACpD,OAAO,CACR,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pain-signal-bridge-result-shaping.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pain-signal-bridge-result-shaping.test.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,395 @@
1
+ /**
2
+ * PRI-456: Characterization test for PainSignalBridge result-shaping.
3
+ *
4
+ * Pins the full PainSignalBridgeResult status matrix for both:
5
+ * - onDiagnosisComplete() (fresh diagnosis path)
6
+ * - buildExistingResult() (idempotent existing-task path)
7
+ *
8
+ * This test MUST remain green before and after the refactor that extracts
9
+ * a pure shapeBridgeResult() function. If any assertion changes, it is a
10
+ * behavior change — STOP.
11
+ *
12
+ * ERR gate:
13
+ * - ERR-007 / EP-02: single source for status decision (test proves both paths)
14
+ * - ERR-002 / EP-03: every degraded/failed branch keeps its structured message
15
+ * - ERR-004 / ERR-008 / EP-07: lineage fields come from the same source rows
16
+ */
17
+ import { describe, it, expect } from 'vitest';
18
+ import { PainSignalBridge } from '../pain-signal-bridge.js';
19
+ const PAIN_ID = 'pain-char-001';
20
+ const TASK_ID = 'diagnosis_pain-char-001';
21
+ const RUN_ID = 'run-char-1';
22
+ // ── Factory helpers ──────────────────────────────────────────────────────────
23
+ function makeCandidate(id, kind, overrides = {}) {
24
+ return {
25
+ candidateId: id,
26
+ taskId: TASK_ID,
27
+ artifactId: `artifact-${id}`,
28
+ sourceRunId: `run-${id}`,
29
+ title: `Candidate ${id}`,
30
+ description: `Description for ${id}`,
31
+ confidence: 0.85,
32
+ sourceRecommendationJson: '{}',
33
+ recommendationKind: kind,
34
+ status: 'pending',
35
+ createdAt: '2026-06-24T00:00:00.000Z',
36
+ ...overrides,
37
+ };
38
+ }
39
+ function makeLedgerEntry(candidateId) {
40
+ return {
41
+ id: `ledger-${candidateId}`,
42
+ status: 'probation',
43
+ createdAt: '2026-06-24T00:00:00.000Z',
44
+ text: `Principle text for ${candidateId}`,
45
+ sourceRef: `candidate://${candidateId}`,
46
+ title: `Principle ${candidateId}`,
47
+ evaluability: 'weak_heuristic',
48
+ };
49
+ }
50
+ function makeHighConfidenceOutput() {
51
+ return {
52
+ valid: true,
53
+ diagnosisId: 'diag-high',
54
+ summary: 'Valid diagnosis with sufficient evidence',
55
+ rootCause: 'Identified root cause from session trace',
56
+ violatedPrinciples: [],
57
+ evidence: [{ sourceRef: 'session-trace-1', note: 'Owner confirmed behavior' }],
58
+ recommendations: [{ kind: 'principle', description: 'Valid principle from evidence' }],
59
+ confidence: 0.85,
60
+ };
61
+ }
62
+ function makeLowConfidenceOutput() {
63
+ return {
64
+ valid: true,
65
+ diagnosisId: 'diag-low',
66
+ summary: 'Low confidence diagnosis',
67
+ rootCause: 'Insufficient evidence',
68
+ violatedPrinciples: [],
69
+ evidence: [],
70
+ recommendations: [{ kind: 'principle', description: 'Low confidence principle' }],
71
+ confidence: 0.3,
72
+ };
73
+ }
74
+ function makeMockDeps(overrides) {
75
+ const telemetryEvents = [];
76
+ const createTaskCalls = [];
77
+ const updateCandidateStatusCalls = [];
78
+ const createTaskMock = async (input) => {
79
+ createTaskCalls.push(input);
80
+ if (overrides.createTaskFn)
81
+ return overrides.createTaskFn(input);
82
+ return { taskId: 'mock-task' };
83
+ };
84
+ const getTaskMock = overrides.getTaskFn ?? (async () => null);
85
+ const updateCandidateStatusMock = async (candidateId, patch) => {
86
+ updateCandidateStatusCalls.push({ candidateId, patch });
87
+ };
88
+ const stateManager = {
89
+ getTask: getTaskMock,
90
+ createTask: createTaskMock,
91
+ updateTask: async () => undefined,
92
+ getCandidatesByTaskId: async () => overrides.candidates ?? [],
93
+ getRunsByTask: async () => [{ runId: RUN_ID, taskId: TASK_ID, status: 'succeeded' }],
94
+ updateCandidateStatus: updateCandidateStatusMock,
95
+ };
96
+ const intakeService = {
97
+ intake: async (candidateId) => ({ id: `ledger-${candidateId}` }),
98
+ };
99
+ const ledgerEntries = overrides.ledgerEntries ?? new Map();
100
+ const ledgerAdapter = {
101
+ existsForCandidate: (candidateId) => ledgerEntries.get(candidateId) ?? null,
102
+ };
103
+ const runner = {
104
+ run: async () => ({
105
+ status: 'succeeded',
106
+ taskId: TASK_ID,
107
+ attemptCount: 1,
108
+ output: overrides.output ?? makeHighConfidenceOutput(),
109
+ }),
110
+ };
111
+ return {
112
+ stateManager,
113
+ intakeService,
114
+ ledgerAdapter,
115
+ runner,
116
+ telemetryEvents,
117
+ createTaskCalls,
118
+ updateCandidateStatusCalls,
119
+ };
120
+ }
121
+ function createBridge(deps, autoIntakeEnabled = true) {
122
+ return new PainSignalBridge({
123
+ stateManager: deps.stateManager,
124
+ runner: deps.runner,
125
+ intakeService: deps.intakeService,
126
+ ledgerAdapter: deps.ledgerAdapter,
127
+ autoIntakeEnabled,
128
+ eventEmitter: {
129
+ emitTelemetry: (event) => {
130
+ deps.telemetryEvents.push(event);
131
+ },
132
+ },
133
+ });
134
+ }
135
+ const PROVENANCE = 'openclaw_context_bound';
136
+ // ── onDiagnosisComplete() characterization ───────────────────────────────────
137
+ describe('PRI-456: onDiagnosisComplete result-shaping characterization', () => {
138
+ it('succeeded: 1 admitted candidate with ledger entry and successful dreamer seed', async () => {
139
+ const candidates = [makeCandidate('c1', 'principle')];
140
+ const deps = makeMockDeps({ candidates, output: makeHighConfidenceOutput() });
141
+ const bridge = createBridge(deps);
142
+ const result = await bridge.onDiagnosisComplete({
143
+ taskId: TASK_ID,
144
+ diagnosticianOutput: makeHighConfidenceOutput(),
145
+ painId: PAIN_ID,
146
+ provenance: PROVENANCE,
147
+ inputEvidenceCount: 1,
148
+ });
149
+ expect(result.status).toBe('succeeded');
150
+ expect(result.painId).toBe(PAIN_ID);
151
+ expect(result.taskId).toBe(TASK_ID);
152
+ expect(result.runId).toBe(RUN_ID);
153
+ expect(result.artifactId).toBe('artifact-c1');
154
+ expect(result.candidateIds).toEqual(['c1']);
155
+ expect(result.ledgerEntryIds).toEqual(['ledger-c1']);
156
+ expect(result.admissionResults).toBeDefined();
157
+ expect(result.admissionResults).toHaveLength(1);
158
+ expect(result.admissionResults?.[0]?.admission.decision).toBe('admitted');
159
+ expect(result.message).toBeUndefined();
160
+ });
161
+ it('succeeded: autoIntakeEnabled=false — no ledger entries needed', async () => {
162
+ const candidates = [makeCandidate('c1', 'principle')];
163
+ const deps = makeMockDeps({ candidates, output: makeHighConfidenceOutput() });
164
+ const bridge = createBridge(deps, false);
165
+ const result = await bridge.onDiagnosisComplete({
166
+ taskId: TASK_ID,
167
+ diagnosticianOutput: makeHighConfidenceOutput(),
168
+ painId: PAIN_ID,
169
+ provenance: PROVENANCE,
170
+ inputEvidenceCount: 1,
171
+ });
172
+ expect(result.status).toBe('succeeded');
173
+ expect(result.candidateIds).toEqual(['c1']);
174
+ expect(result.ledgerEntryIds).toEqual([]);
175
+ expect(result.admissionResults).toBeDefined();
176
+ expect(result.admissionResults?.[0]?.admission.decision).toBe('admitted');
177
+ expect(result.message).toBeUndefined();
178
+ });
179
+ it('failed: no candidates — "Diagnostician succeeded but produced no principle candidates"', async () => {
180
+ const deps = makeMockDeps({ candidates: [], output: makeHighConfidenceOutput() });
181
+ const bridge = createBridge(deps);
182
+ const result = await bridge.onDiagnosisComplete({
183
+ taskId: TASK_ID,
184
+ diagnosticianOutput: makeHighConfidenceOutput(),
185
+ painId: PAIN_ID,
186
+ provenance: PROVENANCE,
187
+ inputEvidenceCount: 1,
188
+ });
189
+ expect(result.status).toBe('failed');
190
+ expect(result.painId).toBe(PAIN_ID);
191
+ expect(result.taskId).toBe(TASK_ID);
192
+ expect(result.runId).toBe(RUN_ID);
193
+ expect(result.artifactId).toBeUndefined();
194
+ expect(result.candidateIds).toEqual([]);
195
+ expect(result.ledgerEntryIds).toEqual([]);
196
+ expect(result.admissionResults).toEqual([]);
197
+ expect(result.message).toBe('Diagnostician succeeded but produced no principle candidates');
198
+ });
199
+ it('degraded: all_candidates_gated — 1 candidate, low confidence, not admitted', async () => {
200
+ const candidates = [makeCandidate('c-gated', 'principle')];
201
+ const deps = makeMockDeps({ candidates, output: makeLowConfidenceOutput() });
202
+ const bridge = createBridge(deps);
203
+ const result = await bridge.onDiagnosisComplete({
204
+ taskId: TASK_ID,
205
+ diagnosticianOutput: makeLowConfidenceOutput(),
206
+ painId: PAIN_ID,
207
+ provenance: PROVENANCE,
208
+ inputEvidenceCount: 1,
209
+ });
210
+ expect(result.status).toBe('degraded');
211
+ expect(result.candidateIds).toEqual(['c-gated']);
212
+ expect(result.ledgerEntryIds).toEqual([]);
213
+ expect(result.admissionResults).toBeDefined();
214
+ expect(result.admissionResults?.[0]?.admission.decision).toBe('needs_evidence');
215
+ expect(result.message).toContain('all_candidates_gated');
216
+ expect(result.message).toContain('c-gated=needs_evidence');
217
+ });
218
+ it('degraded: partial_admission — 2 candidates, 1 admitted, 1 deferred', async () => {
219
+ // To get partial admission, one candidate must be admitted (principle, high confidence)
220
+ // and one must be non-admitted (defer kind → always deferred regardless of confidence).
221
+ const candidatesPartial = [
222
+ makeCandidate('c-ok', 'principle'),
223
+ makeCandidate('c-defer', 'defer'),
224
+ ];
225
+ const deps = makeMockDeps({ candidates: candidatesPartial, output: makeHighConfidenceOutput() });
226
+ const bridge = createBridge(deps);
227
+ const result = await bridge.onDiagnosisComplete({
228
+ taskId: TASK_ID,
229
+ diagnosticianOutput: makeHighConfidenceOutput(),
230
+ painId: PAIN_ID,
231
+ provenance: PROVENANCE,
232
+ inputEvidenceCount: 1,
233
+ });
234
+ expect(result.status).toBe('degraded');
235
+ expect(result.candidateIds).toEqual(['c-ok', 'c-defer']);
236
+ expect(result.ledgerEntryIds).toEqual(['ledger-c-ok']);
237
+ expect(result.admissionResults).toBeDefined();
238
+ expect(result.admissionResults).toHaveLength(2);
239
+ const admitted = result.admissionResults?.find((a) => a.candidateId === 'c-ok');
240
+ expect(admitted?.admission.decision).toBe('admitted');
241
+ const deferred = result.admissionResults?.find((a) => a.candidateId === 'c-defer');
242
+ expect(deferred?.admission.decision).toBe('deferred');
243
+ expect(result.message).toContain('partial_admission');
244
+ expect(result.message).toContain('1_admitted_1_gated');
245
+ });
246
+ it('degraded: dreamer_seed_failed — admitted candidate, ledger created, dreamer seed throws', async () => {
247
+ const candidates = [makeCandidate('c-fail', 'principle')];
248
+ const deps = makeMockDeps({
249
+ candidates,
250
+ output: makeHighConfidenceOutput(),
251
+ createTaskFn: async (input) => {
252
+ if (input.taskKind === 'dreamer')
253
+ throw new Error('DB write failed');
254
+ return { taskId: input.taskId ?? 'mock-task' };
255
+ },
256
+ });
257
+ const bridge = createBridge(deps);
258
+ const result = await bridge.onDiagnosisComplete({
259
+ taskId: TASK_ID,
260
+ diagnosticianOutput: makeHighConfidenceOutput(),
261
+ painId: PAIN_ID,
262
+ provenance: PROVENANCE,
263
+ inputEvidenceCount: 1,
264
+ });
265
+ expect(result.status).toBe('degraded');
266
+ expect(result.candidateIds).toEqual(['c-fail']);
267
+ expect(result.ledgerEntryIds).toEqual(['ledger-c-fail']);
268
+ expect(result.message).toContain('dreamer_seed_failed:c-fail');
269
+ // The candidate should still be consumed despite seed failure
270
+ const consumedCall = deps.updateCandidateStatusCalls.find((c) => c.candidateId === 'c-fail');
271
+ expect(consumedCall).toBeDefined();
272
+ expect(consumedCall?.patch).toEqual({ status: 'consumed' });
273
+ });
274
+ it('degraded: all_candidates_gated with seed failure note appended', async () => {
275
+ // When all candidates are gated AND a seed failure occurs (shouldn't normally happen
276
+ // since seed only runs for admitted candidates, but test the message format)
277
+ const candidates = [makeCandidate('c-gated', 'principle')];
278
+ const deps = makeMockDeps({
279
+ candidates,
280
+ output: makeLowConfidenceOutput(),
281
+ });
282
+ const bridge = createBridge(deps);
283
+ const result = await bridge.onDiagnosisComplete({
284
+ taskId: TASK_ID,
285
+ diagnosticianOutput: makeLowConfidenceOutput(),
286
+ painId: PAIN_ID,
287
+ provenance: PROVENANCE,
288
+ inputEvidenceCount: 1,
289
+ });
290
+ // All gated → degraded, no seed failure (no admitted candidates to seed)
291
+ expect(result.status).toBe('degraded');
292
+ expect(result.message).toContain('all_candidates_gated');
293
+ expect(result.message).not.toContain('dreamer_seed_failed');
294
+ });
295
+ it('diagnosticianOutput=undefined: all candidates get needs_evidence → all_candidates_gated', async () => {
296
+ const candidates = [makeCandidate('c-undef', 'principle')];
297
+ const deps = makeMockDeps({ candidates });
298
+ const bridge = createBridge(deps);
299
+ const result = await bridge.onDiagnosisComplete({
300
+ taskId: TASK_ID,
301
+ diagnosticianOutput: undefined,
302
+ painId: PAIN_ID,
303
+ provenance: PROVENANCE,
304
+ inputEvidenceCount: 1,
305
+ });
306
+ expect(result.status).toBe('degraded');
307
+ expect(result.admissionResults).toBeDefined();
308
+ expect(result.admissionResults?.[0]?.admission.decision).toBe('needs_evidence');
309
+ expect(result.admissionResults?.[0]?.admission.reason).toBe('diagnostician_output_unavailable');
310
+ expect(result.message).toContain('all_candidates_gated');
311
+ });
312
+ });
313
+ // ── buildExistingResult() characterization ───────────────────────────────────
314
+ describe('PRI-456: buildExistingResult result-shaping characterization', () => {
315
+ it('succeeded: existing task with candidates and ledger entries', async () => {
316
+ const candidates = [makeCandidate('c1', 'principle')];
317
+ const ledgerEntries = new Map([['c1', makeLedgerEntry('c1')]]);
318
+ const deps = makeMockDeps({ candidates, ledgerEntries });
319
+ const bridge = createBridge(deps);
320
+ const result = await bridge.buildExistingResult({
321
+ painId: PAIN_ID,
322
+ taskId: TASK_ID,
323
+ });
324
+ expect(result.status).toBe('succeeded');
325
+ expect(result.painId).toBe(PAIN_ID);
326
+ expect(result.taskId).toBe(TASK_ID);
327
+ expect(result.runId).toBe(RUN_ID);
328
+ expect(result.artifactId).toBe('artifact-c1');
329
+ expect(result.candidateIds).toEqual(['c1']);
330
+ expect(result.ledgerEntryIds).toEqual(['ledger-c1']);
331
+ expect(result.message).toBe('Task already succeeded');
332
+ });
333
+ it('succeeded: autoIntakeEnabled=false — no ledger entries needed', async () => {
334
+ const candidates = [makeCandidate('c1', 'principle')];
335
+ const deps = makeMockDeps({ candidates, ledgerEntries: new Map() });
336
+ const bridge = createBridge(deps, false);
337
+ const result = await bridge.buildExistingResult({
338
+ painId: PAIN_ID,
339
+ taskId: TASK_ID,
340
+ });
341
+ expect(result.status).toBe('succeeded');
342
+ expect(result.candidateIds).toEqual(['c1']);
343
+ expect(result.ledgerEntryIds).toEqual([]);
344
+ expect(result.message).toBe('Task already succeeded');
345
+ });
346
+ it('failed: no candidates — "Task has no principle candidates — treating as failed"', async () => {
347
+ const deps = makeMockDeps({ candidates: [], ledgerEntries: new Map() });
348
+ const bridge = createBridge(deps);
349
+ const result = await bridge.buildExistingResult({
350
+ painId: PAIN_ID,
351
+ taskId: TASK_ID,
352
+ });
353
+ expect(result.status).toBe('failed');
354
+ expect(result.painId).toBe(PAIN_ID);
355
+ expect(result.taskId).toBe(TASK_ID);
356
+ expect(result.runId).toBe(RUN_ID);
357
+ expect(result.artifactId).toBeUndefined();
358
+ expect(result.candidateIds).toEqual([]);
359
+ expect(result.ledgerEntryIds).toEqual([]);
360
+ expect(result.message).toBe('Task has no principle candidates — treating as failed');
361
+ });
362
+ it('failed: no ledger entries with autoIntakeEnabled=true', async () => {
363
+ const candidates = [makeCandidate('c1', 'principle')];
364
+ const deps = makeMockDeps({ candidates, ledgerEntries: new Map() });
365
+ const bridge = createBridge(deps);
366
+ const result = await bridge.buildExistingResult({
367
+ painId: PAIN_ID,
368
+ taskId: TASK_ID,
369
+ });
370
+ expect(result.status).toBe('failed');
371
+ expect(result.runId).toBe(RUN_ID);
372
+ expect(result.artifactId).toBe('artifact-c1');
373
+ expect(result.candidateIds).toEqual(['c1']);
374
+ expect(result.ledgerEntryIds).toEqual([]);
375
+ expect(result.message).toBe('Candidate intake did not produce a ledger entry — treating as failed');
376
+ });
377
+ it('multiple candidates with mixed ledger existence — only existing ledgers counted', async () => {
378
+ const candidates = [
379
+ makeCandidate('c1', 'principle'),
380
+ makeCandidate('c2', 'principle'),
381
+ ];
382
+ const ledgerEntries = new Map([['c1', makeLedgerEntry('c1')]]);
383
+ const deps = makeMockDeps({ candidates, ledgerEntries });
384
+ const bridge = createBridge(deps);
385
+ const result = await bridge.buildExistingResult({
386
+ painId: PAIN_ID,
387
+ taskId: TASK_ID,
388
+ });
389
+ expect(result.status).toBe('succeeded');
390
+ expect(result.candidateIds).toEqual(['c1', 'c2']);
391
+ expect(result.ledgerEntryIds).toEqual(['ledger-c1']);
392
+ expect(result.message).toBe('Task already succeeded');
393
+ });
394
+ });
395
+ //# sourceMappingURL=pain-signal-bridge-result-shaping.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pain-signal-bridge-result-shaping.test.js","sourceRoot":"","sources":["../../../src/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.ts"],"names":[],"mappings":"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"}
@@ -222,5 +222,151 @@ describe('recordPainSignalObservability', () => {
222
222
  db.close();
223
223
  }
224
224
  });
225
+ // PRI-406 regression tests — empty string config guards
226
+ it('handles empty workspaceDir gracefully (returns warnings)', () => {
227
+ const { stateDir } = makeWorkspace();
228
+ const result = recordPainSignalObservability({
229
+ workspaceDir: '',
230
+ stateDir,
231
+ data: {
232
+ painId: 'empty_workspace_test',
233
+ painType: 'tool_failure',
234
+ source: 'manual',
235
+ reason: 'empty workspace test',
236
+ score: 60,
237
+ sessionId: 'cli',
238
+ },
239
+ });
240
+ // Should still succeed but may have warnings about path resolution
241
+ expect(result.warnings.length).toBeGreaterThanOrEqual(0);
242
+ // trajectoryPainEventId should still be valid
243
+ expect(result.trajectoryPainEventId).toBeGreaterThan(0);
244
+ });
245
+ it('handles empty stateDir gracefully (returns warnings)', () => {
246
+ const { workspaceDir } = makeWorkspace();
247
+ const result = recordPainSignalObservability({
248
+ workspaceDir,
249
+ stateDir: '',
250
+ data: {
251
+ painId: 'empty_state_test',
252
+ painType: 'tool_failure',
253
+ source: 'manual',
254
+ reason: 'empty state test',
255
+ score: 60,
256
+ sessionId: 'cli',
257
+ },
258
+ });
259
+ // Should still succeed but may have warnings about path resolution
260
+ expect(result.warnings.length).toBeGreaterThanOrEqual(0);
261
+ // trajectoryPainEventId should still be valid (default path used)
262
+ expect(result.trajectoryPainEventId).toBeGreaterThan(0);
263
+ });
264
+ it('handles empty canonicalPainId gracefully (stored as empty string)', () => {
265
+ const { workspaceDir, stateDir } = makeWorkspace();
266
+ const result = recordPainSignalObservability({
267
+ workspaceDir,
268
+ stateDir,
269
+ data: {
270
+ painId: 'empty_canonical_test',
271
+ painType: 'tool_failure',
272
+ source: 'manual',
273
+ reason: 'empty canonical test',
274
+ score: 60,
275
+ sessionId: 'cli',
276
+ },
277
+ canonicalPainId: '',
278
+ runtimeTaskId: 'task_empty',
279
+ });
280
+ expect(result.warnings).toEqual([]);
281
+ expect(result.trajectoryPainEventId).toBeGreaterThan(0);
282
+ // Verify canonical_pain_id is stored as empty string (not null)
283
+ const db = new Database(join(stateDir, 'trajectory.db'), { readonly: true });
284
+ try {
285
+ const row = db.prepare('SELECT canonical_pain_id FROM pain_events WHERE id = ?').get(result.trajectoryPainEventId);
286
+ // Empty string is stored as empty string, not null
287
+ expect(row.canonical_pain_id).toBe('');
288
+ }
289
+ finally {
290
+ db.close();
291
+ }
292
+ });
293
+ it('handles whitespace-only canonicalPainId gracefully (stored as whitespace)', () => {
294
+ const { workspaceDir, stateDir } = makeWorkspace();
295
+ const result = recordPainSignalObservability({
296
+ workspaceDir,
297
+ stateDir,
298
+ data: {
299
+ painId: 'whitespace_canonical_test',
300
+ painType: 'tool_failure',
301
+ source: 'manual',
302
+ reason: 'whitespace canonical test',
303
+ score: 60,
304
+ sessionId: 'cli',
305
+ },
306
+ canonicalPainId: ' ',
307
+ runtimeTaskId: 'task_whitespace',
308
+ });
309
+ expect(result.warnings).toEqual([]);
310
+ expect(result.trajectoryPainEventId).toBeGreaterThan(0);
311
+ // Verify canonical_pain_id is stored as whitespace string (not null)
312
+ const db = new Database(join(stateDir, 'trajectory.db'), { readonly: true });
313
+ try {
314
+ const row = db.prepare('SELECT canonical_pain_id FROM pain_events WHERE id = ?').get(result.trajectoryPainEventId);
315
+ // Whitespace string is stored as whitespace, not null
316
+ expect(row.canonical_pain_id).toBe(' ');
317
+ }
318
+ finally {
319
+ db.close();
320
+ }
321
+ });
322
+ it('preserves original score and reason on UNIQUE constraint violation', () => {
323
+ const { workspaceDir, stateDir } = makeWorkspace();
324
+ const canonicalPainId = 'preserve_original_test';
325
+ // First insert
326
+ recordPainSignalObservability({
327
+ workspaceDir,
328
+ stateDir,
329
+ data: {
330
+ painId: canonicalPainId,
331
+ taskId: 'diagnosis_preserve_001',
332
+ painType: 'user_frustration',
333
+ source: 'manual',
334
+ reason: 'original reason',
335
+ score: 80,
336
+ sessionId: 'cli',
337
+ agentId: 'pd-cli',
338
+ },
339
+ canonicalPainId,
340
+ runtimeTaskId: 'task_001',
341
+ });
342
+ // Second insert with different score/reason
343
+ const result2 = recordPainSignalObservability({
344
+ workspaceDir,
345
+ stateDir,
346
+ data: {
347
+ painId: canonicalPainId,
348
+ taskId: 'diagnosis_preserve_002',
349
+ painType: 'user_frustration',
350
+ source: 'manual',
351
+ reason: 'new reason',
352
+ score: 95,
353
+ sessionId: 'cli',
354
+ agentId: 'pd-cli',
355
+ },
356
+ canonicalPainId,
357
+ runtimeTaskId: 'task_002',
358
+ });
359
+ expect(result2.warnings).toEqual([]);
360
+ // Verify original score and reason are preserved (not updated)
361
+ const db = new Database(join(stateDir, 'trajectory.db'), { readonly: true });
362
+ try {
363
+ const row = db.prepare('SELECT score, reason FROM pain_events WHERE canonical_pain_id = ?').get(canonicalPainId);
364
+ expect(row.score).toBe(80);
365
+ expect(row.reason).toBe('original reason');
366
+ }
367
+ finally {
368
+ db.close();
369
+ }
370
+ });
225
371
  });
226
372
  //# sourceMappingURL=pain-signal-observability.test.js.map