create-principles-disciple 1.94.0 → 1.95.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 (339) hide show
  1. package/console/dist/server/config/WorkspaceConfigStore.js +2 -1
  2. package/console/dist/server/config/pd-config-store.d.ts +33 -0
  3. package/console/dist/server/config/pd-config-store.js +159 -0
  4. package/console/dist/server/index.js +18 -4
  5. package/console/dist/server/models/EvidenceChainConsoleModel.d.ts +0 -2
  6. package/console/dist/server/models/EvidenceChainConsoleModel.js +36 -2
  7. package/console/dist/server/models/HealthCheckModel.js +5 -3
  8. package/console/dist/server/models/IntentDecisionModel.d.ts +66 -0
  9. package/console/dist/server/models/IntentDecisionModel.js +207 -0
  10. package/console/dist/server/models/IntentPageModel.d.ts +18 -0
  11. package/console/dist/server/models/IntentPageModel.js +90 -0
  12. package/console/dist/server/models/PrinciplesConsoleModel.d.ts +2 -0
  13. package/console/dist/server/models/PrinciplesConsoleModel.js +37 -1
  14. package/console/dist/server/models/WorkspaceService.d.ts +0 -28
  15. package/console/dist/server/models/WorkspaceService.js +0 -115
  16. package/console/dist/server/routes/config.js +55 -1
  17. package/console/dist/server/routes/intent-decisions.d.ts +33 -0
  18. package/console/dist/server/routes/intent-decisions.js +499 -0
  19. package/console/dist/server/routes/intent.d.ts +3 -0
  20. package/console/dist/server/routes/intent.js +35 -0
  21. package/console/dist/server/routes/principles.js +67 -1
  22. package/console/dist/server/routes/update.d.ts +0 -1
  23. package/console/dist/server/routes/update.js +14 -11
  24. package/console/dist/ui/App.js +2 -7
  25. package/console/dist/ui/api.d.ts +44 -18
  26. package/console/dist/ui/api.js +44 -5
  27. package/console/dist/ui/components/layout/app-sidebar.js +2 -1
  28. package/console/dist/ui/components/ui/badge.d.ts +1 -1
  29. package/console/dist/ui/components/ui/button.d.ts +1 -1
  30. package/console/dist/ui/components/ui/shiny-text.d.ts +28 -0
  31. package/console/dist/ui/components/ui/shiny-text.js +46 -0
  32. package/console/dist/ui/i18n/en.json +167 -3
  33. package/console/dist/ui/i18n/zh-CN.json +167 -3
  34. package/console/dist/ui/pages/activation/ActivationPage.js +2 -1
  35. package/console/dist/ui/pages/control-center/ControlCenterPage.js +28 -2
  36. package/console/dist/ui/pages/control-center/EmpathyObserverCostHint.d.ts +28 -0
  37. package/console/dist/ui/pages/control-center/EmpathyObserverCostHint.js +38 -0
  38. package/console/dist/ui/pages/debt/DebtPage.js +219 -2
  39. package/console/dist/ui/pages/focus/FocusPage.js +2 -1
  40. package/console/dist/ui/pages/intent/IntentPage.d.ts +1 -0
  41. package/console/dist/ui/pages/intent/IntentPage.js +147 -0
  42. package/console/dist/ui/pages/pain/PainPage.js +234 -4
  43. package/console/dist/ui/pages/pain/pain-card-helpers.d.ts +75 -0
  44. package/console/dist/ui/pages/pain/pain-card-helpers.js +78 -0
  45. package/console/dist/ui/pages/principles/PrinciplesPage.js +2 -1
  46. package/console/dist/ui/utils/validators.d.ts +163 -0
  47. package/console/dist/ui/utils/validators.js +433 -0
  48. package/console/dist/web/assets/app.css +138 -0
  49. package/console/dist/web/assets/app.js +3124 -1288
  50. package/console/package.json +3 -0
  51. package/core/dist/principle-tree-ledger.d.ts +55 -4
  52. package/core/dist/principle-tree-ledger.d.ts.map +1 -1
  53. package/core/dist/principle-tree-ledger.js +472 -13
  54. package/core/dist/principle-tree-ledger.js.map +1 -1
  55. package/core/dist/prompt-builder/__tests__/prompt-builder-core.test.js +58 -0
  56. package/core/dist/prompt-builder/__tests__/prompt-builder-core.test.js.map +1 -1
  57. package/core/dist/prompt-builder/empathy-keyword-matching.d.ts.map +1 -1
  58. package/core/dist/prompt-builder/empathy-keyword-matching.js +9 -6
  59. package/core/dist/prompt-builder/empathy-keyword-matching.js.map +1 -1
  60. package/core/dist/prompt-builder/size-guard.d.ts +1 -0
  61. package/core/dist/prompt-builder/size-guard.d.ts.map +1 -1
  62. package/core/dist/prompt-builder/size-guard.js +21 -0
  63. package/core/dist/prompt-builder/size-guard.js.map +1 -1
  64. package/core/dist/prompt-builder/types.d.ts +2 -0
  65. package/core/dist/prompt-builder/types.d.ts.map +1 -1
  66. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +118 -32
  67. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  68. package/core/dist/runtime-v2/__tests__/evidence-chain-intent-tension.test.d.ts +2 -0
  69. package/core/dist/runtime-v2/__tests__/evidence-chain-intent-tension.test.d.ts.map +1 -0
  70. package/core/dist/runtime-v2/__tests__/evidence-chain-intent-tension.test.js +284 -0
  71. package/core/dist/runtime-v2/__tests__/evidence-chain-intent-tension.test.js.map +1 -0
  72. package/core/dist/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.js +105 -0
  73. package/core/dist/runtime-v2/__tests__/pain-signal-bridge-result-shaping.test.js.map +1 -1
  74. package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js +7 -5
  75. package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js.map +1 -1
  76. package/core/dist/runtime-v2/__tests__/pi-artifact-store.test.js +11 -0
  77. package/core/dist/runtime-v2/__tests__/pi-artifact-store.test.js.map +1 -1
  78. package/core/dist/runtime-v2/__tests__/proven-channel-baseline.test.js +15 -2
  79. package/core/dist/runtime-v2/__tests__/proven-channel-baseline.test.js.map +1 -1
  80. package/core/dist/runtime-v2/__tests__/schema-float-precision.test.d.ts +2 -0
  81. package/core/dist/runtime-v2/__tests__/schema-float-precision.test.d.ts.map +1 -0
  82. package/core/dist/runtime-v2/__tests__/schema-float-precision.test.js +290 -0
  83. package/core/dist/runtime-v2/__tests__/schema-float-precision.test.js.map +1 -0
  84. package/core/dist/runtime-v2/__tests__/schema-orphan-detection.test.d.ts +2 -0
  85. package/core/dist/runtime-v2/__tests__/schema-orphan-detection.test.d.ts.map +1 -0
  86. package/core/dist/runtime-v2/__tests__/schema-orphan-detection.test.js +158 -0
  87. package/core/dist/runtime-v2/__tests__/schema-orphan-detection.test.js.map +1 -0
  88. package/core/dist/runtime-v2/activation/__tests__/approval-store-extended.test.js +15 -1
  89. package/core/dist/runtime-v2/activation/__tests__/approval-store-extended.test.js.map +1 -1
  90. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store-fk.test.d.ts +2 -0
  91. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store-fk.test.d.ts.map +1 -0
  92. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store-fk.test.js +62 -0
  93. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store-fk.test.js.map +1 -0
  94. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js +12 -2
  95. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js.map +1 -1
  96. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store-fk.test.d.ts +2 -0
  97. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store-fk.test.d.ts.map +1 -0
  98. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store-fk.test.js +56 -0
  99. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store-fk.test.js.map +1 -0
  100. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store.test.js +8 -0
  101. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store.test.js.map +1 -1
  102. package/core/dist/runtime-v2/activation/__tests__/story-a-acceptance.test.js +20 -0
  103. package/core/dist/runtime-v2/activation/__tests__/story-a-acceptance.test.js.map +1 -1
  104. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts.map +1 -1
  105. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js +6 -0
  106. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js.map +1 -1
  107. package/core/dist/runtime-v2/activation/sqlite-approval-store.d.ts.map +1 -1
  108. package/core/dist/runtime-v2/activation/sqlite-approval-store.js +86 -32
  109. package/core/dist/runtime-v2/activation/sqlite-approval-store.js.map +1 -1
  110. package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js +65 -1
  111. package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js.map +1 -1
  112. package/core/dist/runtime-v2/activation/writers/rule-host-writer.d.ts.map +1 -1
  113. package/core/dist/runtime-v2/activation/writers/rule-host-writer.js +33 -11
  114. package/core/dist/runtime-v2/activation/writers/rule-host-writer.js.map +1 -1
  115. package/core/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.js +134 -15
  116. package/core/dist/runtime-v2/diagnostician/__tests__/diag-rootcause-output.test.js.map +1 -1
  117. package/core/dist/runtime-v2/diagnostician/__tests__/intent-tension-schema.test.d.ts +18 -0
  118. package/core/dist/runtime-v2/diagnostician/__tests__/intent-tension-schema.test.d.ts.map +1 -0
  119. package/core/dist/runtime-v2/diagnostician/__tests__/intent-tension-schema.test.js +251 -0
  120. package/core/dist/runtime-v2/diagnostician/__tests__/intent-tension-schema.test.js.map +1 -0
  121. package/core/dist/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.js +73 -0
  122. package/core/dist/runtime-v2/diagnostician/__tests__/rootcause-prompt-builder.test.js.map +1 -1
  123. package/core/dist/runtime-v2/diagnostician/diag-rootcause-output.d.ts +98 -0
  124. package/core/dist/runtime-v2/diagnostician/diag-rootcause-output.d.ts.map +1 -1
  125. package/core/dist/runtime-v2/diagnostician/diag-rootcause-output.js +131 -0
  126. package/core/dist/runtime-v2/diagnostician/diag-rootcause-output.js.map +1 -1
  127. package/core/dist/runtime-v2/diagnostician/rootcause-prompt-builder.d.ts +8 -0
  128. package/core/dist/runtime-v2/diagnostician/rootcause-prompt-builder.d.ts.map +1 -1
  129. package/core/dist/runtime-v2/diagnostician/rootcause-prompt-builder.js +66 -3
  130. package/core/dist/runtime-v2/diagnostician/rootcause-prompt-builder.js.map +1 -1
  131. package/core/dist/runtime-v2/diagnostician-output.d.ts +23 -0
  132. package/core/dist/runtime-v2/diagnostician-output.d.ts.map +1 -1
  133. package/core/dist/runtime-v2/diagnostician-output.js +16 -0
  134. package/core/dist/runtime-v2/diagnostician-output.js.map +1 -1
  135. package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts +32 -0
  136. package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts.map +1 -1
  137. package/core/dist/runtime-v2/diagnostician-prompt-builder.js.map +1 -1
  138. package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts +1 -1
  139. package/core/dist/runtime-v2/evidence-triage/source-descriptors.js +1 -1
  140. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +23 -0
  141. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  142. package/core/dist/runtime-v2/feature-flags/__tests__/intent-engineering-flag.test.d.ts +2 -0
  143. package/core/dist/runtime-v2/feature-flags/__tests__/intent-engineering-flag.test.d.ts.map +1 -0
  144. package/core/dist/runtime-v2/feature-flags/__tests__/intent-engineering-flag.test.js +30 -0
  145. package/core/dist/runtime-v2/feature-flags/__tests__/intent-engineering-flag.test.js.map +1 -0
  146. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
  147. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +2 -0
  148. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  149. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.d.ts.map +1 -1
  150. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js +0 -9
  151. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js.map +1 -1
  152. package/core/dist/runtime-v2/index.d.ts +9 -4
  153. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  154. package/core/dist/runtime-v2/index.js +12 -3
  155. package/core/dist/runtime-v2/index.js.map +1 -1
  156. package/core/dist/runtime-v2/intent/__tests__/intent-decision-record.test.d.ts +2 -0
  157. package/core/dist/runtime-v2/intent/__tests__/intent-decision-record.test.d.ts.map +1 -0
  158. package/core/dist/runtime-v2/intent/__tests__/intent-decision-record.test.js +185 -0
  159. package/core/dist/runtime-v2/intent/__tests__/intent-decision-record.test.js.map +1 -0
  160. package/core/dist/runtime-v2/intent/__tests__/intent-doc.test.d.ts +2 -0
  161. package/core/dist/runtime-v2/intent/__tests__/intent-doc.test.d.ts.map +1 -0
  162. package/core/dist/runtime-v2/intent/__tests__/intent-doc.test.js +91 -0
  163. package/core/dist/runtime-v2/intent/__tests__/intent-doc.test.js.map +1 -0
  164. package/core/dist/runtime-v2/intent/__tests__/intent-friction-block.test.d.ts +2 -0
  165. package/core/dist/runtime-v2/intent/__tests__/intent-friction-block.test.d.ts.map +1 -0
  166. package/core/dist/runtime-v2/intent/__tests__/intent-friction-block.test.js +168 -0
  167. package/core/dist/runtime-v2/intent/__tests__/intent-friction-block.test.js.map +1 -0
  168. package/core/dist/runtime-v2/intent/__tests__/intent-patch-proposal.test.d.ts +2 -0
  169. package/core/dist/runtime-v2/intent/__tests__/intent-patch-proposal.test.d.ts.map +1 -0
  170. package/core/dist/runtime-v2/intent/__tests__/intent-patch-proposal.test.js +121 -0
  171. package/core/dist/runtime-v2/intent/__tests__/intent-patch-proposal.test.js.map +1 -0
  172. package/core/dist/runtime-v2/intent/index.d.ts +6 -0
  173. package/core/dist/runtime-v2/intent/index.d.ts.map +1 -0
  174. package/core/dist/runtime-v2/intent/index.js +6 -0
  175. package/core/dist/runtime-v2/intent/index.js.map +1 -0
  176. package/core/dist/runtime-v2/intent/intent-decision-record.d.ts +125 -0
  177. package/core/dist/runtime-v2/intent/intent-decision-record.d.ts.map +1 -0
  178. package/core/dist/runtime-v2/intent/intent-decision-record.js +21 -0
  179. package/core/dist/runtime-v2/intent/intent-decision-record.js.map +1 -0
  180. package/core/dist/runtime-v2/intent/intent-doc-reader-port.d.ts +95 -0
  181. package/core/dist/runtime-v2/intent/intent-doc-reader-port.d.ts.map +1 -0
  182. package/core/dist/runtime-v2/intent/intent-doc-reader-port.js +43 -0
  183. package/core/dist/runtime-v2/intent/intent-doc-reader-port.js.map +1 -0
  184. package/core/dist/runtime-v2/intent/intent-doc.d.ts +19 -0
  185. package/core/dist/runtime-v2/intent/intent-doc.d.ts.map +1 -0
  186. package/core/dist/runtime-v2/intent/intent-doc.js +70 -0
  187. package/core/dist/runtime-v2/intent/intent-doc.js.map +1 -0
  188. package/core/dist/runtime-v2/intent/intent-friction-block.d.ts +63 -0
  189. package/core/dist/runtime-v2/intent/intent-friction-block.d.ts.map +1 -0
  190. package/core/dist/runtime-v2/intent/intent-friction-block.js +129 -0
  191. package/core/dist/runtime-v2/intent/intent-friction-block.js.map +1 -0
  192. package/core/dist/runtime-v2/intent/intent-patch-proposal.d.ts +42 -0
  193. package/core/dist/runtime-v2/intent/intent-patch-proposal.d.ts.map +1 -0
  194. package/core/dist/runtime-v2/intent/intent-patch-proposal.js +81 -0
  195. package/core/dist/runtime-v2/intent/intent-patch-proposal.js.map +1 -0
  196. package/core/dist/runtime-v2/internalization/__tests__/__fixtures__/intent-tension-cases.d.ts +54 -0
  197. package/core/dist/runtime-v2/internalization/__tests__/__fixtures__/intent-tension-cases.d.ts.map +1 -0
  198. package/core/dist/runtime-v2/internalization/__tests__/__fixtures__/intent-tension-cases.js +219 -0
  199. package/core/dist/runtime-v2/internalization/__tests__/__fixtures__/intent-tension-cases.js.map +1 -0
  200. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-intent-tension.test.d.ts +2 -0
  201. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-intent-tension.test.d.ts.map +1 -0
  202. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-intent-tension.test.js +360 -0
  203. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-intent-tension.test.js.map +1 -0
  204. package/core/dist/runtime-v2/internalization/__tests__/diag-router-intent-tension.test.d.ts +2 -0
  205. package/core/dist/runtime-v2/internalization/__tests__/diag-router-intent-tension.test.d.ts.map +1 -0
  206. package/core/dist/runtime-v2/internalization/__tests__/diag-router-intent-tension.test.js +333 -0
  207. package/core/dist/runtime-v2/internalization/__tests__/diag-router-intent-tension.test.js.map +1 -0
  208. package/core/dist/runtime-v2/internalization/__tests__/intent-tension-cases.test.d.ts +2 -0
  209. package/core/dist/runtime-v2/internalization/__tests__/intent-tension-cases.test.d.ts.map +1 -0
  210. package/core/dist/runtime-v2/internalization/__tests__/intent-tension-cases.test.js +113 -0
  211. package/core/dist/runtime-v2/internalization/__tests__/intent-tension-cases.test.js.map +1 -0
  212. package/core/dist/runtime-v2/internalization/diag-rootcause-runner.d.ts +13 -0
  213. package/core/dist/runtime-v2/internalization/diag-rootcause-runner.d.ts.map +1 -1
  214. package/core/dist/runtime-v2/internalization/diag-rootcause-runner.js +42 -0
  215. package/core/dist/runtime-v2/internalization/diag-rootcause-runner.js.map +1 -1
  216. package/core/dist/runtime-v2/internalization/diag-router-runner.d.ts.map +1 -1
  217. package/core/dist/runtime-v2/internalization/diag-router-runner.js +27 -0
  218. package/core/dist/runtime-v2/internalization/diag-router-runner.js.map +1 -1
  219. package/core/dist/runtime-v2/pain-signal-observability.d.ts.map +1 -1
  220. package/core/dist/runtime-v2/pain-signal-observability.js +257 -56
  221. package/core/dist/runtime-v2/pain-signal-observability.js.map +1 -1
  222. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts +12 -0
  223. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
  224. package/core/dist/runtime-v2/pain-signal-runtime-factory.js +1 -1
  225. package/core/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
  226. package/core/dist/runtime-v2/pain-to-principle-service.d.ts +6 -0
  227. package/core/dist/runtime-v2/pain-to-principle-service.d.ts.map +1 -1
  228. package/core/dist/runtime-v2/pain-to-principle-service.js +2 -0
  229. package/core/dist/runtime-v2/pain-to-principle-service.js.map +1 -1
  230. package/core/dist/runtime-v2/principle-tree/ledger-codec.js.map +1 -1
  231. package/core/dist/runtime-v2/proven-channel-baseline.js +1 -1
  232. package/core/dist/runtime-v2/proven-channel-baseline.js.map +1 -1
  233. package/core/dist/runtime-v2/store/artifact/__tests__/sqlite-pi-artifact-store-fk.test.d.ts +2 -0
  234. package/core/dist/runtime-v2/store/artifact/__tests__/sqlite-pi-artifact-store-fk.test.d.ts.map +1 -0
  235. package/core/dist/runtime-v2/store/artifact/__tests__/sqlite-pi-artifact-store-fk.test.js +55 -0
  236. package/core/dist/runtime-v2/store/artifact/__tests__/sqlite-pi-artifact-store-fk.test.js.map +1 -0
  237. package/core/dist/runtime-v2/store/artifact/sqlite-pi-artifact-store.d.ts.map +1 -1
  238. package/core/dist/runtime-v2/store/artifact/sqlite-pi-artifact-store.js +6 -0
  239. package/core/dist/runtime-v2/store/artifact/sqlite-pi-artifact-store.js.map +1 -1
  240. package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.d.ts +2 -0
  241. package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.d.ts.map +1 -0
  242. package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.js +272 -0
  243. package/core/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.js.map +1 -0
  244. package/core/dist/runtime-v2/store/intent/index.d.ts +6 -0
  245. package/core/dist/runtime-v2/store/intent/index.d.ts.map +1 -0
  246. package/core/dist/runtime-v2/store/intent/index.js +5 -0
  247. package/core/dist/runtime-v2/store/intent/index.js.map +1 -0
  248. package/core/dist/runtime-v2/store/intent/sqlite-intent-decision-store.d.ts +51 -0
  249. package/core/dist/runtime-v2/store/intent/sqlite-intent-decision-store.d.ts.map +1 -0
  250. package/core/dist/runtime-v2/store/intent/sqlite-intent-decision-store.js +306 -0
  251. package/core/dist/runtime-v2/store/intent/sqlite-intent-decision-store.js.map +1 -0
  252. package/core/dist/runtime-v2/store/sqlite-connection-pragma.test.js +14 -3
  253. package/core/dist/runtime-v2/store/sqlite-connection-pragma.test.js.map +1 -1
  254. package/core/dist/runtime-v2/store/sqlite-connection-schema-version.test.d.ts +2 -0
  255. package/core/dist/runtime-v2/store/sqlite-connection-schema-version.test.d.ts.map +1 -0
  256. package/core/dist/runtime-v2/store/sqlite-connection-schema-version.test.js +72 -0
  257. package/core/dist/runtime-v2/store/sqlite-connection-schema-version.test.js.map +1 -0
  258. package/core/dist/runtime-v2/store/sqlite-connection.d.ts +27 -0
  259. package/core/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
  260. package/core/dist/runtime-v2/store/sqlite-connection.js +124 -12
  261. package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
  262. package/core/dist/runtime-v2/types/event-payload.d.ts +1 -20
  263. package/core/dist/runtime-v2/types/event-payload.d.ts.map +1 -1
  264. package/core/dist/runtime-v2/types/event-payload.js +0 -12
  265. package/core/dist/runtime-v2/types/event-payload.js.map +1 -1
  266. package/core/dist/runtime-v2/types/event-types.d.ts +5 -34
  267. package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
  268. package/core/dist/runtime-v2/types/event-types.js +0 -19
  269. package/core/dist/runtime-v2/types/event-types.js.map +1 -1
  270. package/core/dist/runtime-v2/types/evidence-chain-contract.d.ts +63 -0
  271. package/core/dist/runtime-v2/types/evidence-chain-contract.d.ts.map +1 -1
  272. package/core/dist/runtime-v2/types/evidence-chain-contract.js +234 -9
  273. package/core/dist/runtime-v2/types/evidence-chain-contract.js.map +1 -1
  274. package/core/dist/runtime-v2/types/index.d.ts +5 -5
  275. package/core/dist/runtime-v2/types/index.d.ts.map +1 -1
  276. package/core/dist/runtime-v2/types/index.js +5 -3
  277. package/core/dist/runtime-v2/types/index.js.map +1 -1
  278. package/core/dist/runtime-v2/types/ledger-store.d.ts +30 -30
  279. package/core/dist/runtime-v2/types/ledger-store.d.ts.map +1 -1
  280. package/core/dist/runtime-v2/types/ledger-store.js +10 -5
  281. package/core/dist/runtime-v2/types/ledger-store.js.map +1 -1
  282. package/core/dist/workflow-funnel-loader.d.ts +2 -2
  283. package/core/dist/workflow-funnel-loader.d.ts.map +1 -1
  284. package/dist/installer.d.ts.map +1 -1
  285. package/dist/installer.js +16 -0
  286. package/dist/installer.js.map +1 -1
  287. package/package.json +1 -1
  288. package/pd-cli/dist/commands/__tests__/intent-flag-wiring.test.d.ts +9 -0
  289. package/pd-cli/dist/commands/__tests__/intent-flag-wiring.test.d.ts.map +1 -0
  290. package/pd-cli/dist/commands/__tests__/intent-flag-wiring.test.js +166 -0
  291. package/pd-cli/dist/commands/__tests__/intent-flag-wiring.test.js.map +1 -0
  292. package/pd-cli/dist/commands/intent.d.ts +59 -0
  293. package/pd-cli/dist/commands/intent.d.ts.map +1 -0
  294. package/pd-cli/dist/commands/intent.js +350 -0
  295. package/pd-cli/dist/commands/intent.js.map +1 -0
  296. package/pd-cli/dist/commands/runtime-init.d.ts +43 -0
  297. package/pd-cli/dist/commands/runtime-init.d.ts.map +1 -0
  298. package/pd-cli/dist/commands/runtime-init.js +264 -0
  299. package/pd-cli/dist/commands/runtime-init.js.map +1 -0
  300. package/pd-cli/dist/index.js +25 -0
  301. package/pd-cli/dist/index.js.map +1 -1
  302. package/pd-cli/dist/services/demo-story-a-runner.d.ts.map +1 -1
  303. package/pd-cli/dist/services/demo-story-a-runner.js +6 -0
  304. package/pd-cli/dist/services/demo-story-a-runner.js.map +1 -1
  305. package/pd-cli/package.json +1 -0
  306. package/plugin/dist/commands/pain.js +2 -0
  307. package/plugin/dist/core/control-ui-db.d.ts +11 -0
  308. package/plugin/dist/core/control-ui-db.js +40 -16
  309. package/plugin/dist/core/event-log.js +0 -5
  310. package/plugin/dist/core/intent-doc-reader-adapter.d.ts +28 -0
  311. package/plugin/dist/core/intent-doc-reader-adapter.js +56 -0
  312. package/plugin/dist/core/intent-doc-reader.d.ts +80 -0
  313. package/plugin/dist/core/intent-doc-reader.js +189 -0
  314. package/plugin/dist/core/principle-tree-ledger.d.ts +27 -79
  315. package/plugin/dist/core/principle-tree-ledger.js +39 -524
  316. package/plugin/dist/core/reflection/reflection-context.d.ts +2 -2
  317. package/plugin/dist/core/trajectory.d.ts +16 -0
  318. package/plugin/dist/core/trajectory.js +332 -254
  319. package/plugin/dist/core/workspace-context.d.ts +2 -3
  320. package/plugin/dist/hooks/pain.js +5 -0
  321. package/plugin/dist/hooks/prompt-helpers.d.ts +19 -1
  322. package/plugin/dist/hooks/prompt-helpers.js +39 -2
  323. package/plugin/dist/hooks/prompt-types.d.ts +8 -0
  324. package/plugin/dist/hooks/prompt.js +80 -21
  325. package/plugin/dist/index.d.ts +3 -1
  326. package/plugin/dist/index.js +9 -5
  327. package/plugin/dist/service/runtime-summary-service.js +1 -1
  328. package/plugin/dist/service/subagent-workflow/workflow-store.d.ts +14 -0
  329. package/plugin/dist/service/subagent-workflow/workflow-store.js +91 -2
  330. package/plugin/dist/types/event-types.d.ts +1 -1
  331. package/plugin/package.json +6 -3
  332. package/plugin/scripts/acceptance-test.mjs +3 -3
  333. package/plugin/dist/core/principle-tree-ledger-adapter.d.ts +0 -32
  334. package/plugin/dist/core/principle-tree-ledger-adapter.js +0 -125
  335. package/plugin/dist/service/central-database.d.ts +0 -138
  336. package/plugin/dist/service/central-database.js +0 -731
  337. package/plugin/dist/service/central-sync-service.d.ts +0 -8
  338. package/plugin/dist/service/central-sync-service.js +0 -71
  339. package/plugin/scripts/validate-live-path.ts +0 -462
@@ -87,7 +87,8 @@ export class WorkspaceConfigStore {
87
87
  }
88
88
  return parsed;
89
89
  }
90
- catch {
90
+ catch (e) {
91
+ console.warn('WorkspaceConfigStore: failed to parse workspaces.json, returning empty list:', e);
91
92
  return [];
92
93
  }
93
94
  }
@@ -138,4 +138,37 @@ export declare function getPrinciplesOutputLanguage(workspaceDir: string): Outpu
138
138
  * Safe partial write: preserves unknown sections, validates before write.
139
139
  */
140
140
  export declare function updatePrinciplesOutputLanguage(workspaceDir: string, payload: unknown): OutputLanguageResult;
141
+ export interface FeatureFlagUpdateResultOk {
142
+ ok: true;
143
+ feature: string;
144
+ enabled: boolean;
145
+ }
146
+ export interface FeatureFlagUpdateResultErr {
147
+ ok: false;
148
+ statusCode: number;
149
+ error: string;
150
+ message: string;
151
+ nextAction?: string;
152
+ }
153
+ export type FeatureFlagUpdateResult = FeatureFlagUpdateResultOk | FeatureFlagUpdateResultErr;
154
+ /**
155
+ * Update a feature flag's `enabled` field in .pd/config.yaml.
156
+ *
157
+ * Safe partial write: preserves unknown sections, validates before write.
158
+ * Follows the load → validate → merge → atomic write pattern of
159
+ * updateAgentBinding / updatePrinciplesOutputLanguage.
160
+ *
161
+ * Constraints (spec §13.4):
162
+ * - featureName must be in the registered flag set (DEFAULT_FEATURE_FLAGS)
163
+ * - Does NOT create a new `features:` section if absent (rejects)
164
+ * - Atomic write + validates merged yaml can be re-parsed by loadPdConfig
165
+ *
166
+ * ERR entries (spec §13.9):
167
+ * - ERR-001/ERR-005: enabled strictly typeof === 'boolean'; featureName
168
+ * strictly checked against whitelist
169
+ * - ERR-009: unknown featureName → ok:false with reason
170
+ * - ERR-013: Object.hasOwn for features section existence check
171
+ * - ERR-015/018/019: load-validate-merge-write-reload, no stale cache
172
+ */
173
+ export declare function updateFeatureFlag(workspaceDir: string, featureName: string, enabled: boolean): FeatureFlagUpdateResult;
141
174
  export declare function checkReadiness(workspaceDir: string, agentName: string, getEnvVar?: (name: string) => string | undefined): ReadinessResult | ReadinessError;
@@ -606,6 +606,165 @@ export function updatePrinciplesOutputLanguage(workspaceDir, payload) {
606
606
  }
607
607
  return { ok: true, outputLanguage: outputLangRaw, source: 'user_config' };
608
608
  }
609
+ // ── Update Feature Flag (spec 2026-06-27 §13.4) ────────────────────────────
610
+ /**
611
+ * Whitelist of registered feature flag names. A PATCH request may only
612
+ * toggle flags that already exist in the registry. Built from the default
613
+ * effective config's computed flags — this is the authoritative source of
614
+ * registered flag IDs (avoids ambiguity between the array and Record
615
+ * forms of DEFAULT_FEATURE_FLAGS in the core barrel).
616
+ */
617
+ const _DEFAULT_FLAGS_RESULT = computeFeatureFlagsFromConfig(computeEffectivePdConfig(null));
618
+ const REGISTERED_FEATURE_FLAG_NAMES = new Set(Object.keys(_DEFAULT_FLAGS_RESULT.flags));
619
+ /** Map of flag ID → category, for preserving category when writing. */
620
+ const DEFAULT_FLAG_CATEGORY = new Map(Object.entries(_DEFAULT_FLAGS_RESULT.flags).map(([id, flag]) => [id, flag.category]));
621
+ /**
622
+ * Update a feature flag's `enabled` field in .pd/config.yaml.
623
+ *
624
+ * Safe partial write: preserves unknown sections, validates before write.
625
+ * Follows the load → validate → merge → atomic write pattern of
626
+ * updateAgentBinding / updatePrinciplesOutputLanguage.
627
+ *
628
+ * Constraints (spec §13.4):
629
+ * - featureName must be in the registered flag set (DEFAULT_FEATURE_FLAGS)
630
+ * - Does NOT create a new `features:` section if absent (rejects)
631
+ * - Atomic write + validates merged yaml can be re-parsed by loadPdConfig
632
+ *
633
+ * ERR entries (spec §13.9):
634
+ * - ERR-001/ERR-005: enabled strictly typeof === 'boolean'; featureName
635
+ * strictly checked against whitelist
636
+ * - ERR-009: unknown featureName → ok:false with reason
637
+ * - ERR-013: Object.hasOwn for features section existence check
638
+ * - ERR-015/018/019: load-validate-merge-write-reload, no stale cache
639
+ */
640
+ export function updateFeatureFlag(workspaceDir, featureName, enabled) {
641
+ // 1. Validate featureName against the registered whitelist
642
+ if (!REGISTERED_FEATURE_FLAG_NAMES.has(featureName)) {
643
+ return {
644
+ ok: false,
645
+ statusCode: 400,
646
+ error: 'unknown_feature',
647
+ message: `Unknown feature flag '${featureName}'. Registered flags: ${Array.from(REGISTERED_FEATURE_FLAG_NAMES).join(', ')}`,
648
+ nextAction: `Use one of: ${Array.from(REGISTERED_FEATURE_FLAG_NAMES).join(', ')}`,
649
+ };
650
+ }
651
+ // 2. Validate enabled is boolean (typeof check, no `as` — ERR-001)
652
+ if (typeof enabled !== 'boolean') {
653
+ return {
654
+ ok: false,
655
+ statusCode: 400,
656
+ error: 'bad_request',
657
+ message: `enabled must be a boolean. Got: ${typeof enabled}`,
658
+ nextAction: 'Send { enabled: true } or { enabled: false }',
659
+ };
660
+ }
661
+ // 3. Read raw config to preserve unknown sections + check features section
662
+ // Check features section BEFORE loadPdConfig malformed check: a config
663
+ // without a features section is rejected with 422 regardless of whether
664
+ // the rest is valid or malformed (spec §13.4: 不允许新增).
665
+ const configPath = getPdConfigPath(workspaceDir);
666
+ let rawConfig;
667
+ if (fs.existsSync(configPath)) {
668
+ let rawContent;
669
+ try {
670
+ rawContent = fs.readFileSync(configPath, 'utf8');
671
+ }
672
+ catch (err) {
673
+ const message = err instanceof Error ? err.message : String(err);
674
+ return { ok: false, statusCode: 500, error: 'read_error', message: `Failed to read config for update: ${message}` };
675
+ }
676
+ let rawParsed;
677
+ try {
678
+ rawParsed = yaml.load(rawContent, { schema: yaml.JSON_SCHEMA });
679
+ }
680
+ catch (err) {
681
+ // YAML syntax error = malformed config (409, not 500). Consistent with
682
+ // updateAgentBinding which treats loadPdConfig failures as conflict.
683
+ const message = err instanceof Error ? err.message : String(err);
684
+ return { ok: false, statusCode: 409, error: 'conflict', message: `Cannot update feature flag: existing .pd/config.yaml is malformed. YAML parse error: ${message}` };
685
+ }
686
+ if (isRecord(rawParsed)) {
687
+ rawConfig = { ...rawParsed };
688
+ }
689
+ else {
690
+ rawConfig = {};
691
+ }
692
+ }
693
+ else {
694
+ rawConfig = {};
695
+ }
696
+ // 4. Refuse to CREATE a features section if absent (spec §13.4: 不允许新增)
697
+ // Use Object.hasOwn for untrusted key check (ERR-013)
698
+ if (!Object.hasOwn(rawConfig, 'features') || !isRecord(rawConfig.features)) {
699
+ return {
700
+ ok: false,
701
+ statusCode: 422,
702
+ error: 'no_features_section',
703
+ message: `Cannot update feature flag: .pd/config.yaml has no 'features:' section. This API does not create new feature sections.`,
704
+ nextAction: 'Manually add a features: section to .pd/config.yaml first, or set the flag via yaml directly.',
705
+ };
706
+ }
707
+ // 5. Load existing config — if malformed, refuse to write
708
+ const loadResult = loadPdConfig(workspaceDir);
709
+ if (!loadResult.ok) {
710
+ return {
711
+ ok: false,
712
+ statusCode: 409,
713
+ error: 'conflict',
714
+ message: `Cannot update feature flag: existing .pd/config.yaml is malformed. Fix config errors first. Errors: ${loadResult.errors.map(e => e.reason).join('; ')}`,
715
+ };
716
+ }
717
+ // 6. Merge: update features[featureName].enabled, preserving other flags
718
+ const existingFeatures = { ...rawConfig.features };
719
+ const existingEntry = Object.hasOwn(existingFeatures, featureName)
720
+ ? existingFeatures[featureName]
721
+ : undefined;
722
+ // Preserve existing category if present; otherwise use the registered default
723
+ const category = (isRecord(existingEntry) && Object.hasOwn(existingEntry, 'category') && typeof existingEntry.category === 'string')
724
+ ? existingEntry.category
725
+ : (DEFAULT_FLAG_CATEGORY.get(featureName) ?? 'quiet');
726
+ existingFeatures[featureName] = { category, enabled };
727
+ rawConfig.features = existingFeatures;
728
+ // 7. Validate the updated config before writing
729
+ const validation = validatePdConfig(rawConfig);
730
+ if (!validation.ok) {
731
+ return {
732
+ ok: false,
733
+ statusCode: 400,
734
+ error: 'validation_error',
735
+ message: `Updated config would be invalid: ${validation.errors.map(e => e.reason).join('; ')}`,
736
+ nextAction: 'Fix config validation errors before retrying',
737
+ };
738
+ }
739
+ // 8. Atomic write
740
+ try {
741
+ writeConfigAtomic(configPath, rawConfig);
742
+ }
743
+ catch (err) {
744
+ const message = err instanceof Error ? err.message : String(err);
745
+ return { ok: false, statusCode: 500, error: 'write_error', message: `Failed to write config: ${message}`, nextAction: 'Check disk space and file permissions for .pd/config.yaml' };
746
+ }
747
+ // 9. Re-read to confirm actual persisted state (ERR-002: fail loud on re-read failure)
748
+ const confirmResult = loadPdConfig(workspaceDir);
749
+ if (!confirmResult.ok) {
750
+ return {
751
+ ok: false,
752
+ statusCode: 500,
753
+ error: 'confirm_read_failed',
754
+ message: `Write succeeded but re-read failed: config is now malformed`,
755
+ nextAction: 'Inspect .pd/config.yaml manually for corruption',
756
+ };
757
+ }
758
+ // Use computeFlagsFromLoadResult (not computeFeatureFlagsFromConfig) because
759
+ // confirmResult is a ConfigLoadResult, not an EffectivePdConfig.
760
+ const confirmFlags = computeFlagsFromLoadResult(confirmResult);
761
+ const confirmedEnabled = confirmFlags.flags[featureName]?.enabled === true;
762
+ return {
763
+ ok: true,
764
+ feature: featureName,
765
+ enabled: confirmedEnabled,
766
+ };
767
+ }
609
768
  // ── Check Readiness ──────────────────────────────────────────────────────────
610
769
  export function checkReadiness(workspaceDir, agentName, getEnvVar = (name) => process.env[name]) {
611
770
  // 1. Validate agent name
@@ -15,6 +15,8 @@ import { handleActivationsRoute, disposeActivationsModels } from './routes/activ
15
15
  import { handleApprovalsGroupedRoute, disposeApprovalsGroupedModels } from './routes/approvals-grouped.js';
16
16
  import { handleGovernanceRoute, disposeGovernanceModels } from './routes/governance.js';
17
17
  import { handleEvidenceChainRoute, disposeEvidenceChainModels } from './routes/evidence-chain.js';
18
+ import { handleIntentRoute, disposeIntentModels } from './routes/intent.js';
19
+ import { handleIntentDecisionsRoute, disposeIntentDecisionModels } from './routes/intent-decisions.js';
18
20
  import { createWorkspacesRoutes } from './routes/workspaces.js';
19
21
  import { handleUpdateRoute } from './routes/update.js';
20
22
  import { handleUpdateHistoryRoute } from './routes/update-history.js';
@@ -215,7 +217,7 @@ async function initServices(workspaceDir, authConfig) {
215
217
  feedbackFlags,
216
218
  };
217
219
  }
218
- async function closeServices(services) {
220
+ async function closeServices() {
219
221
  disposeFeedbackReportModels();
220
222
  disposeApprovalsModels();
221
223
  disposeApprovalsGroupedModels();
@@ -225,7 +227,8 @@ async function closeServices(services) {
225
227
  disposeActivationsModels();
226
228
  disposeGovernanceModels();
227
229
  disposeEvidenceChainModels();
228
- services.workspaceService.dispose();
230
+ disposeIntentModels();
231
+ disposeIntentDecisionModels();
229
232
  }
230
233
  // ── Route handler ───────────────────────────────────────────────────────────
231
234
  function handleRequest(services) {
@@ -294,7 +297,7 @@ function handleRequest(services) {
294
297
  asyncHandler(() => handleUpdateHistoryRoute(req, res, services.workspaceDir, ''))(req, res);
295
298
  return;
296
299
  }
297
- // Update routes: GET /api/update/check, POST /api/update/apply, GET /api/update/status, POST /api/update/rollback
300
+ // Update routes: GET /api/update/check, POST /api/update/apply, POST /api/update/rollback
298
301
  if (urlPath === '/api/update' || urlPath.startsWith('/api/update/')) {
299
302
  const subPath = urlPath.slice('/api/update'.length);
300
303
  const isApply = subPath === '/apply';
@@ -325,6 +328,17 @@ function handleRequest(services) {
325
328
  asyncHandler(() => handleGovernanceRoute(req, res, services.workspaceDir))(req, res);
326
329
  return;
327
330
  }
331
+ // PRI-466: GET /api/v1/intent
332
+ if (urlPath === '/api/v1/intent') {
333
+ asyncHandler(() => handleIntentRoute(req, res, services.workspaceDir))(req, res);
334
+ return;
335
+ }
336
+ // PRI-470: IntentDecisionRecord (POST/GET /api/v1/intent-decisions, /:id, /summary)
337
+ if (urlPath === '/api/v1/intent-decisions' || urlPath.startsWith('/api/v1/intent-decisions/')) {
338
+ const subPath = urlPath.slice('/api/v1/intent-decisions'.length);
339
+ asyncHandler(() => handleIntentDecisionsRoute(req, res, services.workspaceDir, subPath))(req, res);
340
+ return;
341
+ }
328
342
  // PRI-331: GET /api/v1/evidence-chain
329
343
  if (urlPath === '/api/v1/evidence-chain') {
330
344
  asyncHandler(() => handleEvidenceChainRoute(req, res, services.workspaceDir))(req, res);
@@ -359,7 +373,7 @@ export async function main() {
359
373
  const shutdown = async (signal) => {
360
374
  console.log(`[pd-console] Received ${signal}, shutting down...`);
361
375
  await new Promise((resolve) => { server.close(() => resolve()); });
362
- await closeServices(services);
376
+ await closeServices();
363
377
  process.exit(0);
364
378
  };
365
379
  process.on('SIGTERM', () => { void shutdown('SIGTERM'); });
@@ -22,10 +22,8 @@
22
22
  * - ERR-014/016/017: Evidence previews bounded via sanitizeString
23
23
  * - ERR-013: Use Object.hasOwn() for untrusted object keys
24
24
  */
25
- import { crossReferenceByTimestamp, resolveSummary } from '@principles/core/runtime-v2';
26
25
  import type { EvidenceChainState, EvidenceChainRecord, EvidenceChainResponse } from '@principles/core/runtime-v2';
27
26
  export type { EvidenceChainState, EvidenceChainRecord, EvidenceChainResponse, };
28
- export { crossReferenceByTimestamp, resolveSummary, };
29
27
  export declare class EvidenceChainConsoleModel {
30
28
  private readonly workspaceDir;
31
29
  constructor(workspaceDir: string);
@@ -22,11 +22,10 @@
22
22
  * - ERR-014/016/017: Evidence previews bounded via sanitizeString
23
23
  * - ERR-013: Use Object.hasOwn() for untrusted object keys
24
24
  */
25
- import { SqliteConnection, sanitizeString, assembleEvidenceChain, crossReferenceByTimestamp, resolveSummary, } from '@principles/core/runtime-v2';
25
+ import { SqliteConnection, sanitizeString, assembleEvidenceChain, } from '@principles/core/runtime-v2';
26
26
  import * as fs from 'node:fs';
27
27
  import * as path from 'node:path';
28
28
  import Database from 'better-sqlite3';
29
- export { crossReferenceByTimestamp, resolveSummary, };
30
29
  // ── Helpers ────────────────────────────────────────────────────────────────────
31
30
  function isRecord(value) {
32
31
  return typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -180,6 +179,7 @@ export class EvidenceChainConsoleModel {
180
179
  let tasks = [];
181
180
  let dreamerTasks = [];
182
181
  let candidates = [];
182
+ let diagnosticArtifacts = [];
183
183
  let stateDbAvailable = false;
184
184
  if (fs.existsSync(stateDbPath)) {
185
185
  const conn = new SqliteConnection({ workspaceDir: this.workspaceDir, readonly: true });
@@ -230,6 +230,27 @@ export class EvidenceChainConsoleModel {
230
230
  throw colErr;
231
231
  }
232
232
  }
233
+ // PRI-469: Read diagnostician artifacts from the artifacts table.
234
+ // In production, DiagnosticianCommitter writes Stage C output (rootCause +
235
+ // intentTension) to artifacts.content_json with artifact_kind =
236
+ // 'diagnostician_output'. This is the canonical source for intentTension.
237
+ // The tasks.diagnostic_json column is kept as a fallback for test fixtures.
238
+ // Graceful degradation: if the artifacts table is missing (older workspace),
239
+ // we simply skip it — assembleEvidenceChain falls back to diagnostic_json.
240
+ try {
241
+ diagnosticArtifacts = db.prepare("SELECT task_id, content_json FROM artifacts WHERE artifact_kind = 'diagnostician_output' ORDER BY created_at DESC").all();
242
+ }
243
+ catch (artifactsErr) {
244
+ if (isMissingTableError(artifactsErr)) {
245
+ // Artifacts table not present in older workspaces — not an error,
246
+ // just no intentTension data available from artifacts.
247
+ }
248
+ else {
249
+ // ERR-002: degrade with reason for unexpected errors.
250
+ degradedReasons.push('Failed to read diagnostician artifacts table');
251
+ degradedNextActions.push('Check state database artifacts table integrity.');
252
+ }
253
+ }
233
254
  stateDbAvailable = true;
234
255
  }
235
256
  catch (err) {
@@ -272,6 +293,7 @@ export class EvidenceChainConsoleModel {
272
293
  stateDbAvailable,
273
294
  degradedReasons,
274
295
  degradedNextActions,
296
+ diagnosticArtifacts,
275
297
  });
276
298
  // ── 5. Sanitize strings in place ─────────────────────────────────
277
299
  for (const record of response.records) {
@@ -288,6 +310,18 @@ export class EvidenceChainConsoleModel {
288
310
  if (record.candidateSummary) {
289
311
  record.candidateSummary = sanitizeString(record.candidateSummary, this.workspaceDir);
290
312
  }
313
+ // PRI-469: Sanitize intentTension free-text fields.
314
+ // Enum fields (source, evidenceStrength, suggestedOwnerAction) and
315
+ // relatedIntentFields are controlled vocabularies validated by the core,
316
+ // so they don't need sanitization. The explanation, evidence items,
317
+ // and intentDocHash may contain user/system-generated text.
318
+ if (record.intentTension) {
319
+ record.intentTension.explanation = sanitizeString(record.intentTension.explanation, this.workspaceDir);
320
+ record.intentTension.evidence = record.intentTension.evidence.map((item) => sanitizeString(item, this.workspaceDir));
321
+ if (record.intentTension.intentDocHash) {
322
+ record.intentTension.intentDocHash = sanitizeString(record.intentTension.intentDocHash, this.workspaceDir);
323
+ }
324
+ }
291
325
  }
292
326
  return response;
293
327
  }
@@ -240,8 +240,9 @@ export class HealthCheckModel {
240
240
  lastPrincipleAdded = latestSignal?.updatedAt ?? null;
241
241
  }
242
242
  }
243
- catch {
244
- // Pruning not available — leave as null
243
+ catch (e) {
244
+ // Pruning not available — leave as null, but log for observability (ERR-002)
245
+ console.warn('HealthCheckModel.getPipelineTimestamps: pruning read failed, lastPrincipleAdded left null:', e);
245
246
  }
246
247
  return {
247
248
  lastPainSignal,
@@ -250,7 +251,8 @@ export class HealthCheckModel {
250
251
  lastPrincipleAdded,
251
252
  };
252
253
  }
253
- catch {
254
+ catch (e) {
255
+ console.warn('HealthCheckModel.getPipelineTimestamps: failed to read pipeline timestamps, returning all null:', e);
254
256
  return {
255
257
  lastPainSignal: null,
256
258
  lastTaskCreated: null,
@@ -0,0 +1,66 @@
1
+ /**
2
+ * IntentDecisionModel — Console model for IntentDecisionRecord (PRI-470).
3
+ *
4
+ * Holds the workspaceDir (like ApprovalsConsoleModel) and opens a per-request
5
+ * SqliteConnection inside each method: open → delegate to SqliteIntentDecisionStore
6
+ * → close. This keeps each operation isolated and safe across workspaces.
7
+ *
8
+ * Graceful degradation (SPEC §21.7 / ERR-002):
9
+ * - Missing state.db → reads return null/empty/zero summary; writes return a
10
+ * structured `not_initialized` result so the route can map to a clear HTTP
11
+ * error instead of silently creating a half-initialized workspace.
12
+ * - Missing intent_decisions table → reads degrade to empty; writes re-throw
13
+ * (the table is created by SqliteConnection.initSchema, so its absence
14
+ * signals a corrupted or pre-PD workspace that should not be written to).
15
+ *
16
+ * ERR checklist:
17
+ * - EP-01 / ERR-001, ERR-005: store rows validated via core type guards
18
+ * - EP-03 / ERR-002: every degraded path carries reason + nextAction
19
+ * - EP-09: model is a thin I/O adapter over the pure store contract
20
+ */
21
+ import type { IntentDecisionInput, IntentDecisionRecord, IntentDecisionSummary, FollowUpPatch } from '@principles/core/runtime-v2';
22
+ export type IntentDecisionRecordResultModel = {
23
+ ok: true;
24
+ record: IntentDecisionRecord;
25
+ created: boolean;
26
+ } | {
27
+ ok: false;
28
+ reason: string;
29
+ nextAction: string;
30
+ };
31
+ /**
32
+ * Result of a follow-up dispatch (PRI-471, SPEC §22.1.4).
33
+ *
34
+ * - ok:true + record — the existing record was updated with the follow-up
35
+ * field (e.g. `patchProposalId`, `resultingCandidateId`).
36
+ * - ok:false + reason 'decision_not_found' — no IntentDecisionRecord with
37
+ * the given id exists; the route maps this to 404.
38
+ * - ok:false + reason 'state_db_not_found' / 'intent_decisions_table_missing'
39
+ * — same degradation as the record() path.
40
+ */
41
+ export type FollowUpDispatchResultModel = {
42
+ ok: true;
43
+ record: IntentDecisionRecord;
44
+ } | {
45
+ ok: false;
46
+ reason: 'decision_not_found' | 'state_db_not_found' | 'intent_decisions_table_missing';
47
+ nextAction: string;
48
+ };
49
+ export declare class IntentDecisionModel {
50
+ private readonly workspaceDir;
51
+ constructor(workspaceDir: string);
52
+ record(input: IntentDecisionInput): Promise<IntentDecisionRecordResultModel>;
53
+ getById(id: string): Promise<IntentDecisionRecord | null>;
54
+ listByPainId(painId: string): Promise<IntentDecisionRecord[]>;
55
+ listByTaskId(taskId: string): Promise<IntentDecisionRecord[]>;
56
+ getSummary(): Promise<IntentDecisionSummary>;
57
+ /**
58
+ * Update follow-up action fields on an existing IntentDecisionRecord
59
+ * (PRI-471, SPEC §22.1.4).
60
+ *
61
+ * Called by the follow-up route after the Owner decision has been
62
+ * persisted. Only fields present in `patch` are written; the rest stay
63
+ * unchanged. Returns the updated record or a structured failure.
64
+ */
65
+ updateFollowUp(id: string, patch: FollowUpPatch): Promise<FollowUpDispatchResultModel>;
66
+ }
@@ -0,0 +1,207 @@
1
+ /**
2
+ * IntentDecisionModel — Console model for IntentDecisionRecord (PRI-470).
3
+ *
4
+ * Holds the workspaceDir (like ApprovalsConsoleModel) and opens a per-request
5
+ * SqliteConnection inside each method: open → delegate to SqliteIntentDecisionStore
6
+ * → close. This keeps each operation isolated and safe across workspaces.
7
+ *
8
+ * Graceful degradation (SPEC §21.7 / ERR-002):
9
+ * - Missing state.db → reads return null/empty/zero summary; writes return a
10
+ * structured `not_initialized` result so the route can map to a clear HTTP
11
+ * error instead of silently creating a half-initialized workspace.
12
+ * - Missing intent_decisions table → reads degrade to empty; writes re-throw
13
+ * (the table is created by SqliteConnection.initSchema, so its absence
14
+ * signals a corrupted or pre-PD workspace that should not be written to).
15
+ *
16
+ * ERR checklist:
17
+ * - EP-01 / ERR-001, ERR-005: store rows validated via core type guards
18
+ * - EP-03 / ERR-002: every degraded path carries reason + nextAction
19
+ * - EP-09: model is a thin I/O adapter over the pure store contract
20
+ */
21
+ import * as fs from 'node:fs';
22
+ import * as path from 'node:path';
23
+ import { SqliteConnection, SqliteIntentDecisionStore, } from '@principles/core/runtime-v2';
24
+ function stateDbExists(workspaceDir) {
25
+ return fs.existsSync(path.join(workspaceDir, '.pd', 'state.db'));
26
+ }
27
+ function isMissingTableError(err) {
28
+ if (!(err instanceof Error))
29
+ return false;
30
+ return err.message.includes('no such table');
31
+ }
32
+ function emptySummary() {
33
+ return {
34
+ counts: {
35
+ confirm_drift: 0,
36
+ revise_intent: 0,
37
+ observe: 0,
38
+ dismiss: 0,
39
+ promote_to_principle: 0,
40
+ promote_to_rulehost: 0,
41
+ },
42
+ lastDecisionAt: null,
43
+ };
44
+ }
45
+ export class IntentDecisionModel {
46
+ workspaceDir;
47
+ constructor(workspaceDir) {
48
+ this.workspaceDir = workspaceDir;
49
+ }
50
+ async record(input) {
51
+ if (!stateDbExists(this.workspaceDir)) {
52
+ return {
53
+ ok: false,
54
+ reason: 'state_db_not_found',
55
+ nextAction: 'Initialize the workspace with PD (run a diagnosis or pd config) before recording intent decisions.',
56
+ };
57
+ }
58
+ const connection = new SqliteConnection({ workspaceDir: this.workspaceDir });
59
+ try {
60
+ const store = new SqliteIntentDecisionStore(connection);
61
+ const result = await store.record(input);
62
+ return { ok: true, record: result.record, created: result.created };
63
+ }
64
+ catch (err) {
65
+ if (isMissingTableError(err)) {
66
+ return {
67
+ ok: false,
68
+ reason: 'intent_decisions_table_missing',
69
+ nextAction: 'Run pd config doctor or re-initialize the workspace so the intent_decisions table is created.',
70
+ };
71
+ }
72
+ throw err;
73
+ }
74
+ finally {
75
+ try {
76
+ connection.close();
77
+ }
78
+ catch { /* best-effort */ }
79
+ }
80
+ }
81
+ async getById(id) {
82
+ if (!stateDbExists(this.workspaceDir))
83
+ return null;
84
+ const connection = new SqliteConnection({ workspaceDir: this.workspaceDir, readonly: true });
85
+ try {
86
+ const store = new SqliteIntentDecisionStore(connection);
87
+ return await store.getById(id);
88
+ }
89
+ catch (err) {
90
+ if (isMissingTableError(err))
91
+ return null;
92
+ throw err;
93
+ }
94
+ finally {
95
+ try {
96
+ connection.close();
97
+ }
98
+ catch { /* best-effort */ }
99
+ }
100
+ }
101
+ async listByPainId(painId) {
102
+ if (!stateDbExists(this.workspaceDir))
103
+ return [];
104
+ const connection = new SqliteConnection({ workspaceDir: this.workspaceDir, readonly: true });
105
+ try {
106
+ const store = new SqliteIntentDecisionStore(connection);
107
+ return await store.listByPainId(painId);
108
+ }
109
+ catch (err) {
110
+ if (isMissingTableError(err))
111
+ return [];
112
+ throw err;
113
+ }
114
+ finally {
115
+ try {
116
+ connection.close();
117
+ }
118
+ catch { /* best-effort */ }
119
+ }
120
+ }
121
+ async listByTaskId(taskId) {
122
+ if (!stateDbExists(this.workspaceDir))
123
+ return [];
124
+ const connection = new SqliteConnection({ workspaceDir: this.workspaceDir, readonly: true });
125
+ try {
126
+ const store = new SqliteIntentDecisionStore(connection);
127
+ return await store.listByTaskId(taskId);
128
+ }
129
+ catch (err) {
130
+ if (isMissingTableError(err))
131
+ return [];
132
+ throw err;
133
+ }
134
+ finally {
135
+ try {
136
+ connection.close();
137
+ }
138
+ catch { /* best-effort */ }
139
+ }
140
+ }
141
+ async getSummary() {
142
+ if (!stateDbExists(this.workspaceDir))
143
+ return emptySummary();
144
+ const connection = new SqliteConnection({ workspaceDir: this.workspaceDir, readonly: true });
145
+ try {
146
+ const store = new SqliteIntentDecisionStore(connection);
147
+ return await store.getSummary();
148
+ }
149
+ catch (err) {
150
+ if (isMissingTableError(err))
151
+ return emptySummary();
152
+ throw err;
153
+ }
154
+ finally {
155
+ try {
156
+ connection.close();
157
+ }
158
+ catch { /* best-effort */ }
159
+ }
160
+ }
161
+ /**
162
+ * Update follow-up action fields on an existing IntentDecisionRecord
163
+ * (PRI-471, SPEC §22.1.4).
164
+ *
165
+ * Called by the follow-up route after the Owner decision has been
166
+ * persisted. Only fields present in `patch` are written; the rest stay
167
+ * unchanged. Returns the updated record or a structured failure.
168
+ */
169
+ async updateFollowUp(id, patch) {
170
+ if (!stateDbExists(this.workspaceDir)) {
171
+ return {
172
+ ok: false,
173
+ reason: 'state_db_not_found',
174
+ nextAction: 'Initialize the workspace with PD (run a diagnosis or pd config) before dispatching follow-up actions.',
175
+ };
176
+ }
177
+ const connection = new SqliteConnection({ workspaceDir: this.workspaceDir });
178
+ try {
179
+ const store = new SqliteIntentDecisionStore(connection);
180
+ const record = await store.updateFollowUp(id, patch);
181
+ if (record === null) {
182
+ return {
183
+ ok: false,
184
+ reason: 'decision_not_found',
185
+ nextAction: 'Intent decision ' + id + ' does not exist. Refresh the page and try again.',
186
+ };
187
+ }
188
+ return { ok: true, record };
189
+ }
190
+ catch (err) {
191
+ if (isMissingTableError(err)) {
192
+ return {
193
+ ok: false,
194
+ reason: 'intent_decisions_table_missing',
195
+ nextAction: 'Run pd config doctor or re-initialize the workspace so the intent_decisions table is created.',
196
+ };
197
+ }
198
+ throw err;
199
+ }
200
+ finally {
201
+ try {
202
+ connection.close();
203
+ }
204
+ catch { /* best-effort */ }
205
+ }
206
+ }
207
+ }