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
@@ -1,104 +1,56 @@
1
- import { createHash } from 'crypto';
2
- import { shouldIgnorePainProtocolText } from './dictionary.js';
3
1
  /**
4
- * A simple LRU Cache implementation using Map.
2
+ * Detection Funnel — PRI-446 thin adapter
3
+ *
4
+ * The pure three-layer funnel logic (LRU cache, async queue, layer dispatch)
5
+ * now lives in principles-core
6
+ * (runtime-v2/detection/detection-funnel-policy.ts). This file is a thin shell
7
+ * that wires DetectionFunnelCore with the two environment-coupled dependencies
8
+ * the plugin owns:
9
+ * - crypto.createHash (the L2 cache key hasher)
10
+ * - PainDictionary.match (the L1 exact matcher)
11
+ * - shouldIgnorePainProtocolText (the protocol-token gate)
12
+ *
13
+ * It re-exports DetectionFunnel (same class name + constructor signature) and
14
+ * DetectionResult so DetectionService, llm.ts, and evolution-worker keep working
15
+ * unchanged.
16
+ *
17
+ * ERR checklist:
18
+ * - ERR-011: this is a thin adapter delegating to core pure logic.
5
19
  */
6
- class SimpleLRU {
7
- cache;
8
- maxSize;
9
- constructor(maxSize = 100) {
10
- this.cache = new Map();
11
- this.maxSize = maxSize;
12
- }
13
- get(key) {
14
- const item = this.cache.get(key);
15
- if (item !== undefined) {
16
- // Refresh: delete and re-insert
17
- this.cache.delete(key);
18
- this.cache.set(key, item);
19
- }
20
- return item;
21
- }
22
- set(key, value) {
23
- if (this.cache.has(key)) {
24
- this.cache.delete(key);
25
- }
26
- else if (this.cache.size >= this.maxSize) {
27
- // Remove the oldest (first) item
28
- const firstKey = this.cache.keys().next().value;
29
- if (firstKey !== undefined) {
30
- this.cache.delete(firstKey);
31
- }
32
- }
33
- this.cache.set(key, value);
34
- }
35
- }
20
+ import { createHash } from 'crypto';
21
+ import { shouldIgnorePainProtocolText } from './dictionary.js';
22
+ import { DetectionFunnelCore, } from '@principles/core/runtime-v2';
36
23
  /**
37
24
  * Orchestrates the three-layer detection funnel for pain signals.
25
+ *
26
+ * Delegates to the core DetectionFunnelCore, injecting the crypto hasher,
27
+ * the dictionary matcher, and the protocol-token gate.
38
28
  */
39
29
  export class DetectionFunnel {
40
- cache = new SimpleLRU(100);
41
- asyncQueue = [];
42
- dictionary;
30
+ core;
43
31
  constructor(dictionary) {
44
- this.dictionary = dictionary;
32
+ this.core = new DetectionFunnelCore({
33
+ match: (text) => dictionary.match(text),
34
+ hash: (text) => createHash('sha256').update(text).digest('hex'),
35
+ shouldIgnoreProtocol: shouldIgnorePainProtocolText,
36
+ });
45
37
  }
46
38
  /**
47
39
  * Detects pain in the given text using L1 (Exact), L2 (Cache), and L3 (Async).
48
40
  */
49
41
  detect(text) {
50
- if (shouldIgnorePainProtocolText(text)) {
51
- return { detected: false, source: 'l1_exact' };
52
- }
53
- // --- Layer 1: Exact Match (Sync) ---
54
- const exactMatch = this.dictionary.match(text);
55
- if (exactMatch) {
56
- return {
57
- detected: true,
58
- severity: exactMatch.severity,
59
- ruleId: exactMatch.ruleId,
60
- source: 'l1_exact'
61
- };
62
- }
63
- // --- Layer 2: LRU Cache (Sync) ---
64
- const hash = DetectionFunnel.computeHash(text);
65
- const cached = this.cache.get(hash);
66
- if (cached) {
67
- return {
68
- detected: cached.detected,
69
- severity: cached.severity,
70
- source: 'l2_cache'
71
- };
72
- }
73
- // --- Layer 3: Async Semantic Queue ---
74
- this.enqueueAsync(text);
75
- return {
76
- detected: false,
77
- source: 'l3_async_queued'
78
- };
79
- }
80
- static computeHash(text) {
81
- return createHash('sha256').update(text).digest('hex');
82
- }
83
- enqueueAsync(text) {
84
- if (this.asyncQueue.length < 1000) {
85
- this.asyncQueue.push(text);
86
- }
87
- // Worker will pick this up and perform semantic search via createMemorySearchTool
42
+ return this.core.detect(text);
88
43
  }
89
44
  /**
90
45
  * Internal method for the worker to update the cache after a semantic hit.
91
46
  */
92
47
  updateCache(text, result) {
93
- const hash = DetectionFunnel.computeHash(text);
94
- this.cache.set(hash, result);
48
+ this.core.updateCache(text, result);
95
49
  }
96
50
  /**
97
51
  * Retrieves and clears the current asynchronous queue.
98
52
  */
99
53
  flushQueue() {
100
- const queue = [...this.asyncQueue];
101
- this.asyncQueue = [];
102
- return queue;
54
+ return this.core.flushQueue();
103
55
  }
104
56
  }
@@ -1,4 +1,4 @@
1
- import type { EventLogEntry, DailyStats, EmpathyEventStats, ToolCallEventData, PainSignalEventData, RuleMatchEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, EmpathyRollbackEventData, DiagnosisTaskEventData, HeartbeatDiagnosisEventData, DiagnosticianReportEventData, PrincipleCandidateEventData, RuleEnforcedEventData, RuleHostEvaluatedEventData, RuleHostBlockedEventData, RuleHostRequireApprovalEventData, RuleHostAutoCorrectProposedEventData, RuleHostAutoCorrectAppliedEventData, RuntimeV2PromptActivationsInjectedEventData, RuleHostUnhealthyEventData } from '../types/event-types.js';
1
+ import type { EventLogEntry, DailyStats, EmpathyEventStats, ToolCallEventData, PainSignalEventData, RulePromotionEventData, HookExecutionEventData, GateBlockEventData, GateBypassEventData, PlanApprovalEventData, EvolutionTaskEventData, EmpathyRollbackEventData, DiagnosisTaskEventData, HeartbeatDiagnosisEventData, DiagnosticianReportEventData, PrincipleCandidateEventData, RuleEnforcedEventData, RuleHostEvaluatedEventData, RuleHostBlockedEventData, RuleHostRequireApprovalEventData, RuleHostAutoCorrectProposedEventData, RuleHostAutoCorrectAppliedEventData, RuntimeV2PromptActivationsInjectedEventData, RuleHostUnhealthyEventData } from '../types/event-types.js';
2
2
  import type { PluginLogger } from '../openclaw-sdk.js';
3
3
  export declare class EventLog {
4
4
  private readonly logsDir;
@@ -11,7 +11,6 @@ export declare class EventLog {
11
11
  private flushTimer?;
12
12
  private currentEventsFile;
13
13
  private currentDate;
14
- private readonly painScoreSums;
15
14
  constructor(stateDir: string, logger?: PluginLogger);
16
15
  private getEventsFile;
17
16
  private getTodayStr;
@@ -19,7 +18,6 @@ export declare class EventLog {
19
18
  private cleanupOldEventFiles;
20
19
  recordToolCall(sessionId: string | undefined, data: ToolCallEventData): void;
21
20
  recordPainSignal(sessionId: string | undefined, data: PainSignalEventData): void;
22
- recordRuleMatch(sessionId: string | undefined, data: RuleMatchEventData): void;
23
21
  recordRulePromotion(data: RulePromotionEventData): void;
24
22
  recordHookExecution(data: HookExecutionEventData, opts?: {
25
23
  flushImmediately?: boolean;
@@ -15,7 +15,8 @@ export class EventLog {
15
15
  flushTimer;
16
16
  currentEventsFile;
17
17
  currentDate;
18
- painScoreSums = new Map();
18
+ // painScoreSums map removed (PRI-451 Wave 1.5): it only fed the dead
19
+ // stats.pain.avgScore counter, which is also removed.
19
20
  constructor(stateDir, logger) {
20
21
  this.logsDir = path.join(stateDir, 'logs');
21
22
  if (!fs.existsSync(this.logsDir)) {
@@ -30,7 +31,7 @@ export class EventLog {
30
31
  return path.join(this.logsDir, `events_${date}.jsonl`);
31
32
  }
32
33
  getTodayStr() {
33
- return new Date().toISOString().split('T')[0];
34
+ return new Date().toISOString().split('T')[0] ?? '';
34
35
  }
35
36
  ensureEventsFile() {
36
37
  const today = this.getTodayStr();
@@ -68,9 +69,8 @@ export class EventLog {
68
69
  recordPainSignal(sessionId, data) {
69
70
  this.record('pain_signal', 'detected', sessionId, data);
70
71
  }
71
- recordRuleMatch(sessionId, data) {
72
- this.record('rule_match', 'detected', sessionId, data);
73
- }
72
+ // recordRuleMatch removed (PRI-451 Wave 1): dead code. Its only effect was
73
+ // incrementing stats.pain.rulesMatched (also dead, removed in Wave 1.5).
74
74
  recordRulePromotion(data) {
75
75
  this.record('rule_promotion', 'promoted', undefined, data);
76
76
  }
@@ -255,7 +255,7 @@ export class EventLog {
255
255
  }
256
256
  }
257
257
  formatDate(date) {
258
- return date.toISOString().split('T')[0];
258
+ return date.toISOString().split('T')[0] ?? '';
259
259
  }
260
260
  loadStats() {
261
261
  if (fs.existsSync(this.statsFile)) {
@@ -293,16 +293,8 @@ export class EventLog {
293
293
  }
294
294
  else if (entry.type === 'pain_signal') {
295
295
  const data = entry.data;
296
- stats.pain.signalsDetected++;
297
- stats.pain.maxScore = Math.max(stats.pain.maxScore, data.score);
298
- if (data.source) {
299
- stats.pain.signalsBySource[data.source] = (stats.pain.signalsBySource[data.source] || 0) + 1;
300
- }
301
- const currentSum = this.painScoreSums.get(entry.date) ?? 0;
302
- this.painScoreSums.set(entry.date, currentSum + (data.score || 0));
303
- stats.pain.avgScore = stats.pain.signalsDetected > 0
304
- ? Math.round((currentSum + (data.score || 0)) / stats.pain.signalsDetected)
305
- : 0;
296
+ // stats.pain.* counters removed (PRI-451 Wave 1.5): no live reader.
297
+ // The user_empathy aggregation below (stats.empathy.*) is LIVE and stays.
306
298
  if (data.source === 'user_empathy') {
307
299
  if (data.deduped) {
308
300
  stats.empathy.dedupedCount++;
@@ -343,11 +335,14 @@ export class EventLog {
343
335
  if (!stats.hooks.byType[data.hook]) {
344
336
  stats.hooks.byType[data.hook] = { total: 0, success: 0, failure: 0 };
345
337
  }
346
- stats.hooks.byType[data.hook].total++;
347
- if (entry.category === 'success')
348
- stats.hooks.byType[data.hook].success++;
349
- else
350
- stats.hooks.byType[data.hook].failure++;
338
+ const hookStats = stats.hooks.byType[data.hook];
339
+ if (hookStats) {
340
+ hookStats.total++;
341
+ if (entry.category === 'success')
342
+ hookStats.success++;
343
+ else
344
+ hookStats.failure++;
345
+ }
351
346
  }
352
347
  }
353
348
  else if (entry.type === 'empathy_rollback') {
@@ -355,14 +350,11 @@ export class EventLog {
355
350
  stats.empathy.rollbackCount++;
356
351
  stats.empathy.rolledBackScore += data.originalScore || 0;
357
352
  }
358
- else if (entry.type === 'rule_match') {
359
- const data = entry.data;
360
- if (data.ruleId) {
361
- stats.pain.rulesMatched[data.ruleId] = (stats.pain.rulesMatched[data.ruleId] || 0) + 1;
362
- }
363
- }
353
+ // rule_match handler removed (PRI-451 Wave 1.5): recordRuleMatch is gone
354
+ // (Wave 1.1), so no rule_match events are emitted; stats.pain.rulesMatched
355
+ // was its only consumer and is also removed.
364
356
  else if (entry.type === 'rule_promotion') {
365
- stats.pain.candidatesPromoted++;
357
+ // stats.pain.candidatesPromoted removed (PRI-451 Wave 1.5): dead counter.
366
358
  stats.evolution.rulesPromoted++;
367
359
  }
368
360
  else if (entry.type === 'evolution_task') {
@@ -383,13 +375,13 @@ export class EventLog {
383
375
  const raw = entry.data;
384
376
  if (Object.prototype.hasOwnProperty.call(raw, 'category')) {
385
377
  const cat = raw['category'];
386
- if (cat === 'success' || cat === 'missing_json' || cat === 'incomplete_fields') {
378
+ if (typeof cat === 'string' && (cat === 'success' || cat === 'missing_json' || cat === 'incomplete_fields')) {
387
379
  stats.evolution.diagnosticianReportsWritten++;
388
380
  }
389
- if (cat === 'missing_json') {
381
+ if (typeof cat === 'string' && cat === 'missing_json') {
390
382
  stats.evolution.reportsMissingJson++;
391
383
  }
392
- if (cat === 'incomplete_fields') {
384
+ if (typeof cat === 'string' && cat === 'incomplete_fields') {
393
385
  stats.evolution.reportsIncompleteFields++;
394
386
  }
395
387
  }
@@ -651,6 +643,8 @@ export class EventLog {
651
643
  const allEvents = this.getMergedEvents();
652
644
  for (let i = allEvents.length - 1; i >= 0; i--) {
653
645
  const entry = allEvents[i];
646
+ if (!entry)
647
+ continue;
654
648
  if (entry.sessionId === sessionId && entry.type === 'pain_signal') {
655
649
  const data = entry.data;
656
650
  if (data.source === 'user_empathy' && !data.deduped) {
@@ -664,6 +658,8 @@ export class EventLog {
664
658
  const allEvents = this.getMergedEvents();
665
659
  for (let i = allEvents.length - 1; i >= 0; i--) {
666
660
  const entry = allEvents[i];
661
+ if (!entry)
662
+ continue;
667
663
  if (entry.sessionId === sessionId && entry.type === "pain_signal") {
668
664
  return entry.data;
669
665
  }
@@ -52,20 +52,12 @@ export declare class EvolutionReducerImpl implements EvolutionReducer {
52
52
  private readonly failureStreak;
53
53
  private lastPromotedAt;
54
54
  private isReplaying;
55
- /** Registered pain_detected callbacks (e.g., PainSignalBridge). */
56
- private readonly _painCallbacks;
57
55
  constructor(opts: {
58
56
  workspaceDir: string;
59
57
  stateDir?: string;
60
58
  });
61
59
  emit(event: EvolutionLoopEvent): void;
62
60
  emitSync(event: EvolutionLoopEvent): void;
63
- /**
64
- * Register a callback for 'pain_detected' events.
65
- * The callback is invoked synchronously within emitSync() after applyEvent completes.
66
- * HG-4: Callbacks are fire-and-forget from the emitSync perspective.
67
- */
68
- on(callback: (event: EvolutionLoopEvent) => void): void;
69
61
  getEventLog(): EvolutionLoopEvent[];
70
62
  getCandidatePrinciples(): Principle[];
71
63
  getProbationPrinciples(): Principle[];
@@ -38,8 +38,9 @@ export class EvolutionReducerImpl {
38
38
  failureStreak = new Map();
39
39
  lastPromotedAt = null;
40
40
  isReplaying = false;
41
- /** Registered pain_detected callbacks (e.g., PainSignalBridge). */
42
- _painCallbacks = [];
41
+ // _painCallbacks pub/sub removed (PRI-451 Wave 1): no code ever registered a
42
+ // callback via .on(). The pain_detected → PainSignalBridge bridge happens via
43
+ // emitPainDetectedEvent (hooks/pain.ts), not this pub/sub layer.
43
44
  constructor(opts) {
44
45
  this.workspaceDir = opts.workspaceDir;
45
46
  this.stateDir = opts.stateDir;
@@ -77,14 +78,9 @@ export class EvolutionReducerImpl {
77
78
  }
78
79
  // Performance: sweepExpiredProbation() moved to getProbationPrinciples() for lazy cleanup
79
80
  }
80
- /**
81
- * Register a callback for 'pain_detected' events.
82
- * The callback is invoked synchronously within emitSync() after applyEvent completes.
83
- * HG-4: Callbacks are fire-and-forget from the emitSync perspective.
84
- */
85
- on(callback) {
86
- this._painCallbacks.push(callback);
87
- }
81
+ // on(callback) pub/sub registration removed (PRI-451 Wave 1): dead code —
82
+ // no caller ever registered a callback. pain_detected events still flow via
83
+ // emitPainDetectedEvent → PainSignalBridge, unaffected.
88
84
  getEventLog() {
89
85
  return [...this.memoryEvents];
90
86
  }
@@ -522,15 +518,9 @@ export class EvolutionReducerImpl {
522
518
  if (!this.isReplaying) {
523
519
  this.onPainDetected(event.data, event.ts);
524
520
  }
525
- // PainSignalBridge subscriptions: invoke registered callbacks (fire-and-forget)
526
- for (const cb of this._painCallbacks) {
527
- try {
528
- cb(event);
529
- }
530
- catch {
531
- // Keep the evolution loop resilient — callback errors must not propagate
532
- }
533
- }
521
+ // _painCallbacks dispatch removed (PRI-451 Wave 1): no callback was ever
522
+ // registered via .on() (also removed). The pain_detected → PainSignalBridge
523
+ // bridge flows through emitPainDetectedEvent (hooks/pain.ts), not here.
534
524
  return;
535
525
  case 'candidate_created':
536
526
  this.onCandidateCreated(event.data, event.ts);
@@ -503,7 +503,7 @@ export function recoverFromTemplate(focusPath, extensionRoot) {
503
503
  };
504
504
  }
505
505
  let template = fs.readFileSync(templatePath, 'utf-8');
506
- const [today] = new Date().toISOString().split('T');
506
+ const today = new Date().toISOString().split('T')[0] ?? '';
507
507
  template = template.replace(/{YYYY-MM-DD}/g, today);
508
508
  if (fs.existsSync(focusPath)) {
509
509
  const backupPath = `${focusPath}.corrupted.${Date.now()}.md`;
@@ -24,7 +24,7 @@ export class HygieneTracker {
24
24
  this.currentStats = this.loadStats();
25
25
  }
26
26
  loadStats() {
27
- const [today] = new Date().toISOString().split('T');
27
+ const today = new Date().toISOString().split('T')[0] ?? '';
28
28
  if (fs.existsSync(this.statsFile)) {
29
29
  try {
30
30
  const content = fs.readFileSync(this.statsFile, 'utf-8');
@@ -54,7 +54,7 @@ export class HygieneTracker {
54
54
  saveStats() {
55
55
  let allStats = {};
56
56
  // Check if we need to rotate date (reset currentStats if date changed)
57
- const [today] = new Date().toISOString().split('T');
57
+ const today = new Date().toISOString().split('T')[0] ?? '';
58
58
  if (this.currentStats.date !== today) {
59
59
  this.currentStats = createEmptyHygieneStats(today);
60
60
  }
@@ -101,7 +101,7 @@ export class HygieneTracker {
101
101
  }
102
102
  getStats() {
103
103
  // Check for date change on every get
104
- const [today] = new Date().toISOString().split('T');
104
+ const today = new Date().toISOString().split('T')[0] ?? '';
105
105
  if (this.currentStats.date !== today) {
106
106
  this.currentStats = createEmptyHygieneStats(today);
107
107
  }
@@ -1,30 +1,35 @@
1
- declare const PAIN_DIAGNOSTIC_SOURCES: readonly ["manual", "tool_failure", "dispatch_error", "gate_blocked", "user_empathy", "llm_paralysis", "semantic", "subagent_error"];
2
- export type PainDiagnosticSource = typeof PAIN_DIAGNOSTIC_SOURCES[number];
3
- export type PainDiagnosticGateReason = 'manual' | 'high_gfi' | 'repeated_failure' | 'semantic_pain' | 'llm_paralysis' | 'risky_high_score' | 'subagent_error' | 'gate_blocked' | 'cooldown' | 'below_gate';
4
- export interface PainDiagnosticGateInput {
5
- source: PainDiagnosticSource | string;
6
- score: number;
7
- currentGfi: number;
8
- consecutiveErrors?: number;
9
- isRisky?: boolean;
10
- errorHash?: string;
11
- sessionId?: string;
12
- nowMs?: number;
13
- cooldownMs?: number;
14
- thresholds?: {
15
- painTrigger?: number;
16
- highSeverity?: number;
17
- highGfi?: number;
18
- repeatedFailure?: number;
19
- semanticPain?: number;
20
- };
21
- }
22
- export interface PainDiagnosticGateDecision {
23
- shouldDiagnose: boolean;
24
- reason: PainDiagnosticGateReason;
25
- episodeKey: string;
26
- detail: string;
27
- }
1
+ /**
2
+ * Pain Diagnostic Gate — PRI-446 thin adapter
3
+ *
4
+ * @deprecated PRI-454 — Gate A (PainDiagnosticGate) is superseded by Gate B
5
+ * (TriggerController + EvidenceTriage). This module remains as the rollback
6
+ * path when `painEvidenceAdmission` or `painEvidenceAdmissionDefault` flags
7
+ * are OFF. Do not add new callers. New admission logic must use
8
+ * `evaluateTriggerController` from runtime-v2/evidence-triage.
9
+ *
10
+ * Disposition: Archive (do not delete) per PRI-454 plan step 6.
11
+ * Removal conditions: Both flags confirmed ON in production for 30 days,
12
+ * and all 5 MVP paths verified on Gate B. See
13
+ * docs/plans/2026-06-pain-evidence-admission-track.md.
14
+ *
15
+ * The pure decision logic (threshold tree, cooldown comparison, episode-key
16
+ * construction) now lives in principles-core
17
+ * (runtime-v2/pain-gate/pain-diagnostic-gate-policy.ts). This file is the
18
+ * stateful adapter that owns:
19
+ * - the cooldown Map (lastDiagnosedAtByEpisode)
20
+ * - Date.now() injection
21
+ * - SystemLogger for unknown-source telemetry
22
+ *
23
+ * It preserves the original export names (evaluatePainDiagnosticGate,
24
+ * isCooldownActiveForEpisode, resetPainDiagnosticGateForTest) so all 5 callers
25
+ * (gate-block-helper, llm, pain, prompt x2) and the characterization test keep
26
+ * working unchanged.
27
+ *
28
+ * ERR checklist:
29
+ * - ERR-011: this is a stateful adapter delegating to core pure logic.
30
+ */
31
+ import { type PainDiagnosticSource, type PainDiagnosticGateReason, type PainDiagnosticGateInput, type PainDiagnosticGateDecision } from '@principles/core/runtime-v2';
32
+ export type { PainDiagnosticSource, PainDiagnosticGateReason, PainDiagnosticGateInput, PainDiagnosticGateDecision, };
28
33
  export declare function resetPainDiagnosticGateForTest(): void;
29
34
  /**
30
35
  * Check whether cooldown is currently active for a given episode.
@@ -32,5 +37,9 @@ export declare function resetPainDiagnosticGateForTest(): void;
32
37
  * with the PainDiagnosticGate's cooldown state.
33
38
  */
34
39
  export declare function isCooldownActiveForEpisode(source: string, sessionId: string | undefined, errorHash: string | undefined, cooldownMs?: number): boolean;
40
+ /**
41
+ * Evaluate the pain diagnostic gate. Delegates the pure decision to core and,
42
+ * when the decision is to diagnose, records the current time against the
43
+ * episode so subsequent calls within the cooldown window are suppressed.
44
+ */
35
45
  export declare function evaluatePainDiagnosticGate(input: PainDiagnosticGateInput): PainDiagnosticGateDecision;
36
- export {};
@@ -1,42 +1,37 @@
1
+ /**
2
+ * Pain Diagnostic Gate — PRI-446 thin adapter
3
+ *
4
+ * @deprecated PRI-454 — Gate A (PainDiagnosticGate) is superseded by Gate B
5
+ * (TriggerController + EvidenceTriage). This module remains as the rollback
6
+ * path when `painEvidenceAdmission` or `painEvidenceAdmissionDefault` flags
7
+ * are OFF. Do not add new callers. New admission logic must use
8
+ * `evaluateTriggerController` from runtime-v2/evidence-triage.
9
+ *
10
+ * Disposition: Archive (do not delete) per PRI-454 plan step 6.
11
+ * Removal conditions: Both flags confirmed ON in production for 30 days,
12
+ * and all 5 MVP paths verified on Gate B. See
13
+ * docs/plans/2026-06-pain-evidence-admission-track.md.
14
+ *
15
+ * The pure decision logic (threshold tree, cooldown comparison, episode-key
16
+ * construction) now lives in principles-core
17
+ * (runtime-v2/pain-gate/pain-diagnostic-gate-policy.ts). This file is the
18
+ * stateful adapter that owns:
19
+ * - the cooldown Map (lastDiagnosedAtByEpisode)
20
+ * - Date.now() injection
21
+ * - SystemLogger for unknown-source telemetry
22
+ *
23
+ * It preserves the original export names (evaluatePainDiagnosticGate,
24
+ * isCooldownActiveForEpisode, resetPainDiagnosticGateForTest) so all 5 callers
25
+ * (gate-block-helper, llm, pain, prompt x2) and the characterization test keep
26
+ * working unchanged.
27
+ *
28
+ * ERR checklist:
29
+ * - ERR-011: this is a stateful adapter delegating to core pure logic.
30
+ */
1
31
  import { SystemLogger } from './system-logger.js';
2
- const PAIN_DIAGNOSTIC_SOURCES = [
3
- 'manual',
4
- 'tool_failure',
5
- 'dispatch_error',
6
- 'gate_blocked',
7
- 'user_empathy',
8
- 'llm_paralysis',
9
- 'semantic',
10
- 'subagent_error',
11
- ];
12
- const DEFAULT_COOLDOWN_MS = 15 * 60 * 1000;
32
+ import { evaluatePainDiagnosticGateDecision, normalizedSource, buildEpisodeKey, isCooldownActive as isCooldownActiveCore, } from '@principles/core/runtime-v2';
33
+ // Module-level cooldown state — owned by this adapter (core is stateless).
13
34
  const lastDiagnosedAtByEpisode = new Map();
14
- function normalizedSource(source) {
15
- if (source.startsWith('llm_') && source !== 'llm_paralysis') {
16
- return 'semantic';
17
- }
18
- if (!PAIN_DIAGNOSTIC_SOURCES.includes(source)) {
19
- SystemLogger.log('', 'GATE_UNKNOWN_SOURCE', `Unknown pain source: "${source}"`);
20
- }
21
- return source;
22
- }
23
- function buildEpisodeKey(input) {
24
- const source = normalizedSource(input.source);
25
- const sessionId = input.sessionId || 'unknown';
26
- const hash = input.errorHash || 'no-hash';
27
- return `${sessionId}:${source}:${hash}`;
28
- }
29
- function withinCooldown(input, episodeKey) {
30
- const cooldownMs = input.cooldownMs ?? DEFAULT_COOLDOWN_MS;
31
- if (cooldownMs <= 0)
32
- return false;
33
- const nowMs = input.nowMs ?? Date.now();
34
- const last = lastDiagnosedAtByEpisode.get(episodeKey);
35
- return last !== undefined && nowMs - last < cooldownMs;
36
- }
37
- function markDiagnosed(input, episodeKey) {
38
- lastDiagnosedAtByEpisode.set(episodeKey, input.nowMs ?? Date.now());
39
- }
40
35
  export function resetPainDiagnosticGateForTest() {
41
36
  lastDiagnosedAtByEpisode.clear();
42
37
  }
@@ -46,60 +41,29 @@ export function resetPainDiagnosticGateForTest() {
46
41
  * with the PainDiagnosticGate's cooldown state.
47
42
  */
48
43
  export function isCooldownActiveForEpisode(source, sessionId, errorHash, cooldownMs) {
49
- const episodeKey = buildEpisodeKey({ source, sessionId, errorHash });
50
- return withinCooldown({ source, sessionId, errorHash, cooldownMs }, episodeKey);
44
+ const episodeKey = buildEpisodeKey({ source, sessionId, errorHash, score: 0, currentGfi: 0 });
45
+ const last = lastDiagnosedAtByEpisode.get(episodeKey);
46
+ const nowMs = Date.now();
47
+ return isCooldownActiveCore({ source, sessionId, errorHash, cooldownMs, nowMs, lastDiagnosedAtMs: last });
51
48
  }
49
+ /**
50
+ * Evaluate the pain diagnostic gate. Delegates the pure decision to core and,
51
+ * when the decision is to diagnose, records the current time against the
52
+ * episode so subsequent calls within the cooldown window are suppressed.
53
+ */
52
54
  export function evaluatePainDiagnosticGate(input) {
53
- const source = normalizedSource(input.source);
54
- const episodeKey = buildEpisodeKey(input);
55
- const painTrigger = input.thresholds?.painTrigger ?? 40;
56
- const highSeverity = input.thresholds?.highSeverity ?? 70;
57
- const highGfi = input.thresholds?.highGfi ?? Math.max(highSeverity, painTrigger + 30);
58
- const repeatedFailure = input.thresholds?.repeatedFailure ?? 4;
59
- const semanticPain = input.thresholds?.semanticPain ?? Math.max(painTrigger, 60);
60
- const score = Number.isFinite(input.score) ? input.score : 0;
61
- const currentGfi = Number.isFinite(input.currentGfi) ? input.currentGfi : 0;
62
- const consecutiveErrors = Number.isFinite(input.consecutiveErrors) ? input.consecutiveErrors : 0;
63
- const approve = (reason, detail) => {
64
- if (withinCooldown(input, episodeKey)) {
65
- return {
66
- shouldDiagnose: false,
67
- reason: 'cooldown',
68
- episodeKey,
69
- detail: `recently diagnosed; ${detail}`,
70
- };
71
- }
72
- markDiagnosed(input, episodeKey);
73
- return { shouldDiagnose: true, reason, episodeKey, detail };
74
- };
75
- if (source === 'manual') {
76
- return approve('manual', 'manual pain signal bypasses automatic gate');
77
- }
78
- if (source === 'subagent_error' && score >= painTrigger) {
79
- return approve('subagent_error', `subagent error score ${score} >= ${painTrigger}`);
80
- }
81
- if (source === 'llm_paralysis' && score >= painTrigger) {
82
- return approve('llm_paralysis', `llm paralysis score ${score} >= ${painTrigger}`);
83
- }
84
- if (source === 'gate_blocked' && score >= painTrigger) {
85
- return approve('gate_blocked', `gate blocked score ${score} >= ${painTrigger}`);
86
- }
87
- if ((source === 'user_empathy' || source === 'semantic') && score >= semanticPain) {
88
- return approve('semantic_pain', `semantic pain score ${score} >= ${semanticPain}`);
55
+ // Surface unknown sources via telemetry (core cannot log).
56
+ const { unknown } = normalizedSource(input.source);
57
+ if (unknown) {
58
+ SystemLogger.log('', 'GATE_UNKNOWN_SOURCE', `Unknown pain source: "${input.source}"`);
89
59
  }
90
- if (input.isRisky === true && score >= highSeverity) {
91
- return approve('risky_high_score', `risky operation score ${score} >= ${highSeverity}`);
92
- }
93
- if (consecutiveErrors >= repeatedFailure) {
94
- return approve('repeated_failure', `consecutive errors ${consecutiveErrors} >= ${repeatedFailure}`);
95
- }
96
- if (currentGfi >= highGfi) {
97
- return approve('high_gfi', `GFI ${currentGfi.toFixed(1)} >= ${highGfi}`);
60
+ const episodeKey = buildEpisodeKey(input);
61
+ const last = lastDiagnosedAtByEpisode.get(episodeKey);
62
+ const nowMs = input.nowMs ?? Date.now();
63
+ const decision = evaluatePainDiagnosticGateDecision({ ...input, nowMs }, last);
64
+ // Record the diagnosis time when approved (matches prior markDiagnosed behavior).
65
+ if (decision.shouldDiagnose) {
66
+ lastDiagnosedAtByEpisode.set(episodeKey, nowMs);
98
67
  }
99
- return {
100
- shouldDiagnose: false,
101
- reason: 'below_gate',
102
- episodeKey,
103
- detail: `score=${score}; gfi=${currentGfi.toFixed(1)}; consecutive=${consecutiveErrors}`,
104
- };
68
+ return decision;
105
69
  }