create-principles-disciple 1.82.0 → 1.83.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 (494) hide show
  1. package/console/dist/server/config/pd-config-store.d.ts +135 -0
  2. package/console/dist/server/config/pd-config-store.js +660 -0
  3. package/console/dist/server/index.js +40 -389
  4. package/console/dist/server/models/ActivationsConsoleModel.d.ts +33 -0
  5. package/console/dist/server/models/ActivationsConsoleModel.js +112 -0
  6. package/console/dist/server/models/ApprovalsConsoleModel.d.ts +5 -0
  7. package/console/dist/server/models/ApprovalsConsoleModel.js +14 -0
  8. package/console/dist/server/models/ApprovalsGroupedConsoleModel.d.ts +25 -0
  9. package/console/dist/server/models/ApprovalsGroupedConsoleModel.js +126 -0
  10. package/console/dist/server/models/ConsoleLifecycleDatasource.d.ts +13 -0
  11. package/console/dist/server/models/ConsoleLifecycleDatasource.js +73 -0
  12. package/console/dist/server/models/EvidenceChainConsoleModel.d.ts +58 -0
  13. package/console/dist/server/models/EvidenceChainConsoleModel.js +493 -0
  14. package/console/dist/server/models/GovernanceConsoleModel.d.ts +74 -0
  15. package/console/dist/server/models/GovernanceConsoleModel.js +246 -0
  16. package/console/dist/server/models/HealthCheckModel.d.ts +0 -4
  17. package/console/dist/server/models/HealthCheckModel.js +49 -80
  18. package/console/dist/server/models/LifecycleConsoleModel.d.ts +19 -0
  19. package/console/dist/server/models/LifecycleConsoleModel.js +55 -0
  20. package/console/dist/server/models/PrincipleClassifier.d.ts +41 -0
  21. package/console/dist/server/models/PrincipleClassifier.js +100 -0
  22. package/console/dist/server/models/PrinciplesConsoleModel.d.ts +12 -1
  23. package/console/dist/server/models/PrinciplesConsoleModel.js +53 -6
  24. package/console/dist/server/models/WorkspaceService.d.ts +2 -1
  25. package/console/dist/server/models/WorkspaceService.js +51 -23
  26. package/console/dist/server/routes/activations.d.ts +3 -0
  27. package/console/dist/server/routes/activations.js +111 -0
  28. package/console/dist/server/routes/approvals-grouped.d.ts +3 -0
  29. package/console/dist/server/routes/approvals-grouped.js +32 -0
  30. package/console/dist/server/routes/approvals.js +28 -4
  31. package/console/dist/server/routes/config.d.ts +27 -0
  32. package/console/dist/server/routes/config.js +213 -0
  33. package/console/dist/server/routes/evidence-chain.d.ts +9 -0
  34. package/console/dist/server/routes/evidence-chain.js +32 -0
  35. package/console/dist/server/routes/governance.d.ts +3 -0
  36. package/console/dist/server/routes/governance.js +32 -0
  37. package/console/dist/server/routes/{evolution.d.ts → lifecycle.d.ts} +2 -2
  38. package/console/dist/server/routes/lifecycle.js +48 -0
  39. package/console/dist/server/routes/principles.js +74 -1
  40. package/console/dist/server/routes/workspaces.js +8 -1
  41. package/console/dist/server/utils/response.d.ts +1 -1
  42. package/console/dist/server/utils/response.js +6 -2
  43. package/console/dist/types.d.ts +1 -0
  44. package/console/dist/ui/App.js +116 -40
  45. package/console/dist/ui/api.d.ts +88 -501
  46. package/console/dist/ui/api.js +139 -162
  47. package/console/dist/ui/components/approval-card.js +1 -1
  48. package/console/dist/ui/components/approval-detail-dialog.js +1 -1
  49. package/console/dist/ui/components/auth/login-form.d.ts +3 -0
  50. package/console/dist/ui/components/auth/login-form.js +36 -0
  51. package/console/dist/ui/components/auth/splash-screen.d.ts +8 -0
  52. package/console/dist/ui/components/auth/splash-screen.js +22 -0
  53. package/console/dist/ui/components/layout/app-sidebar.d.ts +1 -0
  54. package/console/dist/ui/components/layout/app-sidebar.js +56 -0
  55. package/console/dist/ui/components/layout/page-shell.d.ts +11 -0
  56. package/console/dist/ui/components/layout/page-shell.js +10 -0
  57. package/console/dist/ui/components/layout/section-title.d.ts +10 -0
  58. package/console/dist/ui/components/layout/section-title.js +9 -0
  59. package/console/dist/ui/components/theme-provider.d.ts +1 -1
  60. package/console/dist/ui/components/theme-provider.js +13 -8
  61. package/console/dist/ui/components/theme-toggle.js +2 -21
  62. package/console/dist/ui/components/ui/badge.d.ts +1 -1
  63. package/console/dist/ui/components/ui/badge.js +7 -5
  64. package/console/dist/ui/components/ui/button.d.ts +2 -2
  65. package/console/dist/ui/components/ui/button.js +12 -11
  66. package/console/dist/ui/components/ui/card.js +6 -6
  67. package/console/dist/ui/components/ui/sheet.d.ts +1 -1
  68. package/console/dist/ui/i18n/en.json +401 -343
  69. package/console/dist/ui/i18n/index.js +2 -2
  70. package/console/dist/ui/i18n/zh-CN.json +406 -348
  71. package/console/dist/ui/main.d.ts +1 -1
  72. package/console/dist/ui/main.js +1 -0
  73. package/console/dist/ui/pages/activation/ActivationPage.d.ts +1 -0
  74. package/console/dist/ui/pages/activation/ActivationPage.js +150 -0
  75. package/console/dist/ui/pages/activation/ActivationValidators.d.ts +20 -0
  76. package/console/dist/ui/pages/activation/ActivationValidators.js +156 -0
  77. package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +1 -0
  78. package/console/dist/ui/pages/control-center/ControlCenterPage.js +447 -0
  79. package/console/dist/ui/pages/debt/DebtPage.d.ts +1 -0
  80. package/console/dist/ui/pages/debt/DebtPage.js +5 -0
  81. package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +1 -0
  82. package/console/dist/ui/pages/design-system/DesignSystemPage.js +30 -0
  83. package/console/dist/ui/pages/focus/FocusPage.d.ts +1 -0
  84. package/console/dist/ui/pages/focus/FocusPage.js +265 -0
  85. package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +59 -0
  86. package/console/dist/ui/pages/pain/PainEvidenceValidators.js +125 -0
  87. package/console/dist/ui/pages/pain/PainPage.js +136 -0
  88. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +264 -0
  89. package/console/dist/ui/pages/principles/PrinciplesPage.js +244 -0
  90. package/console/dist/ui/pages/report-problem/ReportProblemPage.js +245 -0
  91. package/console/dist/ui/pages/settings/SettingsPage.d.ts +4 -0
  92. package/console/dist/ui/pages/settings/SettingsPage.js +202 -0
  93. package/console/dist/ui/pages/settings/UpdatePage.d.ts +5 -0
  94. package/console/dist/ui/pages/settings/UpdatePage.js +168 -0
  95. package/console/dist/ui/utils/control-center-helpers.d.ts +58 -0
  96. package/console/dist/ui/utils/control-center-helpers.js +152 -0
  97. package/console/dist/ui/utils/validators.d.ts +350 -0
  98. package/console/dist/ui/utils/validators.js +995 -0
  99. package/console/dist/web/assets/app.css +672 -902
  100. package/console/dist/web/assets/app.js +6404 -15347
  101. package/console/dist/web/assets/jetbrains-mono-cyrillic-400-normal-C5JECUCT.woff2 +0 -0
  102. package/console/dist/web/assets/jetbrains-mono-cyrillic-400-normal-FGCZYWMY.woff +0 -0
  103. package/console/dist/web/assets/jetbrains-mono-cyrillic-ext-400-normal-C7IFWGF6.woff2 +0 -0
  104. package/console/dist/web/assets/jetbrains-mono-cyrillic-ext-400-normal-PWXUA557.woff +0 -0
  105. package/console/dist/web/assets/jetbrains-mono-greek-400-normal-JJNQZMPZ.woff +0 -0
  106. package/console/dist/web/assets/jetbrains-mono-greek-400-normal-O7JTTR3P.woff2 +0 -0
  107. package/console/dist/web/assets/jetbrains-mono-latin-400-normal-3OOWLGQ2.woff2 +0 -0
  108. package/console/dist/web/assets/jetbrains-mono-latin-400-normal-WDD34GPP.woff +0 -0
  109. package/console/dist/web/assets/jetbrains-mono-latin-ext-400-normal-55RNMRQS.woff +0 -0
  110. package/console/dist/web/assets/jetbrains-mono-latin-ext-400-normal-JVR3IR4Z.woff2 +0 -0
  111. package/console/dist/web/assets/jetbrains-mono-vietnamese-400-normal-7ULXAK72.woff +0 -0
  112. package/console/dist/web/assets/jetbrains-mono-vietnamese-400-normal-KU7YLUPA.woff2 +0 -0
  113. package/console/package.json +2 -1
  114. package/core/dist/runtime-v2/__tests__/admission-gate.test.js +49 -0
  115. package/core/dist/runtime-v2/__tests__/admission-gate.test.js.map +1 -1
  116. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +16 -1
  117. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  118. package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.d.ts +21 -0
  119. package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.d.ts.map +1 -0
  120. package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.js +354 -0
  121. package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.js.map +1 -0
  122. package/core/dist/runtime-v2/__tests__/language-directive.test.d.ts +12 -0
  123. package/core/dist/runtime-v2/__tests__/language-directive.test.d.ts.map +1 -0
  124. package/core/dist/runtime-v2/__tests__/language-directive.test.js +162 -0
  125. package/core/dist/runtime-v2/__tests__/language-directive.test.js.map +1 -0
  126. package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js +23 -1
  127. package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js.map +1 -1
  128. package/core/dist/runtime-v2/__tests__/pain-to-principle-service.test.js +48 -3
  129. package/core/dist/runtime-v2/__tests__/pain-to-principle-service.test.js.map +1 -1
  130. package/core/dist/runtime-v2/__tests__/proven-channel-baseline.test.js +13 -1
  131. package/core/dist/runtime-v2/__tests__/proven-channel-baseline.test.js.map +1 -1
  132. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.d.ts +12 -0
  133. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.d.ts.map +1 -0
  134. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js +194 -0
  135. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js.map +1 -0
  136. package/core/dist/runtime-v2/__tests__/runtime-config-boundary.test.js +5 -3
  137. package/core/dist/runtime-v2/__tests__/runtime-config-boundary.test.js.map +1 -1
  138. package/core/dist/runtime-v2/activation/__tests__/activation-dispatcher.test.js +1 -0
  139. package/core/dist/runtime-v2/activation/__tests__/activation-dispatcher.test.js.map +1 -1
  140. package/core/dist/runtime-v2/activation/__tests__/approval-queue.test.js +54 -0
  141. package/core/dist/runtime-v2/activation/__tests__/approval-queue.test.js.map +1 -1
  142. package/core/dist/runtime-v2/activation/__tests__/memory-activation-state-store.test.js +15 -2
  143. package/core/dist/runtime-v2/activation/__tests__/memory-activation-state-store.test.js.map +1 -1
  144. package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.js +10 -0
  145. package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.js.map +1 -1
  146. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js +17 -2
  147. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js.map +1 -1
  148. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store.test.js +36 -0
  149. package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store.test.js.map +1 -1
  150. package/core/dist/runtime-v2/activation/activation-dispatcher.d.ts.map +1 -1
  151. package/core/dist/runtime-v2/activation/activation-dispatcher.js +1 -1
  152. package/core/dist/runtime-v2/activation/activation-dispatcher.js.map +1 -1
  153. package/core/dist/runtime-v2/activation/activation-types.d.ts +10 -0
  154. package/core/dist/runtime-v2/activation/activation-types.d.ts.map +1 -1
  155. package/core/dist/runtime-v2/activation/activation-types.js.map +1 -1
  156. package/core/dist/runtime-v2/activation/approval-queue.d.ts +6 -0
  157. package/core/dist/runtime-v2/activation/approval-queue.d.ts.map +1 -1
  158. package/core/dist/runtime-v2/activation/approval-queue.js +3 -0
  159. package/core/dist/runtime-v2/activation/approval-queue.js.map +1 -1
  160. package/core/dist/runtime-v2/activation/memory-activation-state-store.d.ts +2 -0
  161. package/core/dist/runtime-v2/activation/memory-activation-state-store.d.ts.map +1 -1
  162. package/core/dist/runtime-v2/activation/memory-activation-state-store.js +17 -1
  163. package/core/dist/runtime-v2/activation/memory-activation-state-store.js.map +1 -1
  164. package/core/dist/runtime-v2/activation/memory-approval-store.d.ts +6 -0
  165. package/core/dist/runtime-v2/activation/memory-approval-store.d.ts.map +1 -1
  166. package/core/dist/runtime-v2/activation/memory-approval-store.js +16 -0
  167. package/core/dist/runtime-v2/activation/memory-approval-store.js.map +1 -1
  168. package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js +1 -1
  169. package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js.map +1 -1
  170. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts +2 -0
  171. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts.map +1 -1
  172. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js +34 -6
  173. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js.map +1 -1
  174. package/core/dist/runtime-v2/activation/sqlite-approval-store.d.ts +6 -0
  175. package/core/dist/runtime-v2/activation/sqlite-approval-store.d.ts.map +1 -1
  176. package/core/dist/runtime-v2/activation/sqlite-approval-store.js +10 -0
  177. package/core/dist/runtime-v2/activation/sqlite-approval-store.js.map +1 -1
  178. package/core/dist/runtime-v2/adapter/__tests__/json-extractor.test.js +51 -1
  179. package/core/dist/runtime-v2/adapter/__tests__/json-extractor.test.js.map +1 -1
  180. package/core/dist/runtime-v2/adapter/__tests__/openclaw-cli-runtime-adapter.test.js +145 -0
  181. package/core/dist/runtime-v2/adapter/__tests__/openclaw-cli-runtime-adapter.test.js.map +1 -1
  182. package/core/dist/runtime-v2/adapter/json-extractor.d.ts +13 -0
  183. package/core/dist/runtime-v2/adapter/json-extractor.d.ts.map +1 -1
  184. package/core/dist/runtime-v2/adapter/json-extractor.js +103 -0
  185. package/core/dist/runtime-v2/adapter/json-extractor.js.map +1 -1
  186. package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.d.ts +4 -2
  187. package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.d.ts.map +1 -1
  188. package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js +57 -5
  189. package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js.map +1 -1
  190. package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.d.ts +18 -0
  191. package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.d.ts.map +1 -0
  192. package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.js +633 -0
  193. package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.js.map +1 -0
  194. package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js +92 -0
  195. package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js.map +1 -1
  196. package/core/dist/runtime-v2/config/index.d.ts +3 -1
  197. package/core/dist/runtime-v2/config/index.d.ts.map +1 -1
  198. package/core/dist/runtime-v2/config/index.js +1 -0
  199. package/core/dist/runtime-v2/config/index.js.map +1 -1
  200. package/core/dist/runtime-v2/config/pd-config-agent-binding.d.ts +93 -0
  201. package/core/dist/runtime-v2/config/pd-config-agent-binding.d.ts.map +1 -0
  202. package/core/dist/runtime-v2/config/pd-config-agent-binding.js +184 -0
  203. package/core/dist/runtime-v2/config/pd-config-agent-binding.js.map +1 -0
  204. package/core/dist/runtime-v2/config/pd-config-defaults.d.ts.map +1 -1
  205. package/core/dist/runtime-v2/config/pd-config-defaults.js +2 -0
  206. package/core/dist/runtime-v2/config/pd-config-defaults.js.map +1 -1
  207. package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -1
  208. package/core/dist/runtime-v2/config/pd-config-effective.js +3 -0
  209. package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -1
  210. package/core/dist/runtime-v2/config/pd-config-types.d.ts +8 -0
  211. package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -1
  212. package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -1
  213. package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts +13 -0
  214. package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts.map +1 -0
  215. package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js +97 -0
  216. package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js.map +1 -0
  217. package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts +3 -2
  218. package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts.map +1 -1
  219. package/core/dist/runtime-v2/diagnostician-prompt-builder.js +6 -4
  220. package/core/dist/runtime-v2/diagnostician-prompt-builder.js.map +1 -1
  221. package/core/dist/runtime-v2/evidence-sanitizer.d.ts +57 -0
  222. package/core/dist/runtime-v2/evidence-sanitizer.d.ts.map +1 -0
  223. package/core/dist/runtime-v2/evidence-sanitizer.js +213 -0
  224. package/core/dist/runtime-v2/evidence-sanitizer.js.map +1 -0
  225. package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.d.ts +7 -0
  226. package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.d.ts.map +1 -0
  227. package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.js +170 -0
  228. package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.js.map +1 -0
  229. package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.d.ts +18 -0
  230. package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.d.ts.map +1 -0
  231. package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.js +277 -0
  232. package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.js.map +1 -0
  233. package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.d.ts +13 -0
  234. package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.d.ts.map +1 -0
  235. package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.js +264 -0
  236. package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.js.map +1 -0
  237. package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.d.ts +16 -0
  238. package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.d.ts.map +1 -0
  239. package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.js +316 -0
  240. package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.js.map +1 -0
  241. package/core/dist/runtime-v2/evidence-triage/admission-events.d.ts +126 -0
  242. package/core/dist/runtime-v2/evidence-triage/admission-events.d.ts.map +1 -0
  243. package/core/dist/runtime-v2/evidence-triage/admission-events.js +159 -0
  244. package/core/dist/runtime-v2/evidence-triage/admission-events.js.map +1 -0
  245. package/core/dist/runtime-v2/evidence-triage/index.d.ts +16 -0
  246. package/core/dist/runtime-v2/evidence-triage/index.d.ts.map +1 -0
  247. package/core/dist/runtime-v2/evidence-triage/index.js +13 -0
  248. package/core/dist/runtime-v2/evidence-triage/index.js.map +1 -0
  249. package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts +48 -0
  250. package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts.map +1 -0
  251. package/core/dist/runtime-v2/evidence-triage/source-descriptors.js +131 -0
  252. package/core/dist/runtime-v2/evidence-triage/source-descriptors.js.map +1 -0
  253. package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts +32 -0
  254. package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts.map +1 -0
  255. package/core/dist/runtime-v2/evidence-triage/triage-policy.js +95 -0
  256. package/core/dist/runtime-v2/evidence-triage/triage-policy.js.map +1 -0
  257. package/core/dist/runtime-v2/evidence-triage/trigger-controller.d.ts +116 -0
  258. package/core/dist/runtime-v2/evidence-triage/trigger-controller.d.ts.map +1 -0
  259. package/core/dist/runtime-v2/evidence-triage/trigger-controller.js +218 -0
  260. package/core/dist/runtime-v2/evidence-triage/trigger-controller.js.map +1 -0
  261. package/core/dist/runtime-v2/evidence-triage/types.d.ts +65 -0
  262. package/core/dist/runtime-v2/evidence-triage/types.d.ts.map +1 -0
  263. package/core/dist/runtime-v2/evidence-triage/types.js +38 -0
  264. package/core/dist/runtime-v2/evidence-triage/types.js.map +1 -0
  265. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +10 -0
  266. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  267. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
  268. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +1 -0
  269. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  270. package/core/dist/runtime-v2/index.d.ts +8 -1
  271. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  272. package/core/dist/runtime-v2/index.js +7 -1
  273. package/core/dist/runtime-v2/index.js.map +1 -1
  274. package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.d.ts +12 -0
  275. package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.d.ts.map +1 -0
  276. package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.js +83 -0
  277. package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.js.map +1 -0
  278. package/core/dist/runtime-v2/internalization/scribe-prompt-builder.d.ts +10 -0
  279. package/core/dist/runtime-v2/internalization/scribe-prompt-builder.d.ts.map +1 -1
  280. package/core/dist/runtime-v2/internalization/scribe-prompt-builder.js +13 -1
  281. package/core/dist/runtime-v2/internalization/scribe-prompt-builder.js.map +1 -1
  282. package/core/dist/runtime-v2/internalization/scribe-runner.d.ts +3 -0
  283. package/core/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
  284. package/core/dist/runtime-v2/internalization/scribe-runner.js +2 -0
  285. package/core/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
  286. package/core/dist/runtime-v2/internalization-chain-integrity-read-model.js +1 -1
  287. package/core/dist/runtime-v2/internalization-chain-integrity-read-model.js.map +1 -1
  288. package/core/dist/runtime-v2/language-directive.d.ts +80 -0
  289. package/core/dist/runtime-v2/language-directive.d.ts.map +1 -0
  290. package/core/dist/runtime-v2/language-directive.js +108 -0
  291. package/core/dist/runtime-v2/language-directive.js.map +1 -0
  292. package/core/dist/runtime-v2/pain-signal-observability.d.ts.map +1 -1
  293. package/core/dist/runtime-v2/pain-signal-observability.js +24 -11
  294. package/core/dist/runtime-v2/pain-signal-observability.js.map +1 -1
  295. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts +16 -0
  296. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
  297. package/core/dist/runtime-v2/pain-signal-runtime-factory.js +97 -6
  298. package/core/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
  299. package/core/dist/runtime-v2/pain-to-principle-service.d.ts +7 -0
  300. package/core/dist/runtime-v2/pain-to-principle-service.d.ts.map +1 -1
  301. package/core/dist/runtime-v2/pain-to-principle-service.js +2 -0
  302. package/core/dist/runtime-v2/pain-to-principle-service.js.map +1 -1
  303. package/core/dist/runtime-v2/proven-channel-baseline.d.ts.map +1 -1
  304. package/core/dist/runtime-v2/proven-channel-baseline.js +14 -0
  305. package/core/dist/runtime-v2/proven-channel-baseline.js.map +1 -1
  306. package/core/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js +40 -0
  307. package/core/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js.map +1 -1
  308. package/core/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -1
  309. package/core/dist/runtime-v2/runner/base-peer-runner.js +1 -0
  310. package/core/dist/runtime-v2/runner/base-peer-runner.js.map +1 -1
  311. package/core/dist/runtime-v2/runner/diagnostician-runner-options.d.ts +10 -0
  312. package/core/dist/runtime-v2/runner/diagnostician-runner-options.d.ts.map +1 -1
  313. package/core/dist/runtime-v2/runner/diagnostician-runner-options.js +1 -0
  314. package/core/dist/runtime-v2/runner/diagnostician-runner-options.js.map +1 -1
  315. package/core/dist/runtime-v2/runner/diagnostician-runner.d.ts.map +1 -1
  316. package/core/dist/runtime-v2/runner/diagnostician-runner.js +28 -4
  317. package/core/dist/runtime-v2/runner/diagnostician-runner.js.map +1 -1
  318. package/core/dist/runtime-v2/runner/peer-runner-types.d.ts +9 -0
  319. package/core/dist/runtime-v2/runner/peer-runner-types.d.ts.map +1 -1
  320. package/core/dist/runtime-v2/store/runtime-state-manager.d.ts.map +1 -1
  321. package/core/dist/runtime-v2/store/runtime-state-manager.integration.test.js +34 -1
  322. package/core/dist/runtime-v2/store/runtime-state-manager.integration.test.js.map +1 -1
  323. package/core/dist/runtime-v2/store/runtime-state-manager.js +1 -0
  324. package/core/dist/runtime-v2/store/runtime-state-manager.js.map +1 -1
  325. package/core/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
  326. package/core/dist/runtime-v2/store/sqlite-connection.js +9 -1
  327. package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
  328. package/core/dist/runtime-v2/store/task/sqlite-task-store.js +1 -1
  329. package/core/dist/runtime-v2/store/task/sqlite-task-store.js.map +1 -1
  330. package/core/dist/runtime-v2/task-status.d.ts +4 -4
  331. package/core/dist/runtime-v2/task-status.d.ts.map +1 -1
  332. package/core/dist/runtime-v2/task-status.js +2 -2
  333. package/core/dist/runtime-v2/task-status.js.map +1 -1
  334. package/core/package.json +1 -1
  335. package/package.json +2 -2
  336. package/pd-cli/dist/commands/console.d.ts +2 -0
  337. package/pd-cli/dist/commands/console.d.ts.map +1 -1
  338. package/pd-cli/dist/commands/console.js +6 -1
  339. package/pd-cli/dist/commands/console.js.map +1 -1
  340. package/pd-cli/dist/commands/diagnose.d.ts.map +1 -1
  341. package/pd-cli/dist/commands/diagnose.js +18 -1
  342. package/pd-cli/dist/commands/diagnose.js.map +1 -1
  343. package/pd-cli/dist/commands/pain-evidence.d.ts +41 -0
  344. package/pd-cli/dist/commands/pain-evidence.d.ts.map +1 -0
  345. package/pd-cli/dist/commands/pain-evidence.js +177 -0
  346. package/pd-cli/dist/commands/pain-evidence.js.map +1 -0
  347. package/pd-cli/dist/commands/pain-record.d.ts.map +1 -1
  348. package/pd-cli/dist/commands/pain-record.js +24 -9
  349. package/pd-cli/dist/commands/pain-record.js.map +1 -1
  350. package/pd-cli/dist/commands/pain-retry.d.ts +19 -0
  351. package/pd-cli/dist/commands/pain-retry.d.ts.map +1 -0
  352. package/pd-cli/dist/commands/pain-retry.js +485 -0
  353. package/pd-cli/dist/commands/pain-retry.js.map +1 -0
  354. package/pd-cli/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
  355. package/pd-cli/dist/commands/runtime-internalization-run-once.js +59 -9
  356. package/pd-cli/dist/commands/runtime-internalization-run-once.js.map +1 -1
  357. package/pd-cli/dist/commands/runtime-uat.d.ts +1 -0
  358. package/pd-cli/dist/commands/runtime-uat.d.ts.map +1 -1
  359. package/pd-cli/dist/commands/runtime-uat.guard.test.d.ts +2 -0
  360. package/pd-cli/dist/commands/runtime-uat.guard.test.d.ts.map +1 -0
  361. package/pd-cli/dist/commands/runtime-uat.guard.test.js +155 -0
  362. package/pd-cli/dist/commands/runtime-uat.guard.test.js.map +1 -0
  363. package/pd-cli/dist/commands/runtime-uat.js +29 -3
  364. package/pd-cli/dist/commands/runtime-uat.js.map +1 -1
  365. package/pd-cli/dist/config-reader.d.ts +25 -0
  366. package/pd-cli/dist/config-reader.d.ts.map +1 -0
  367. package/pd-cli/dist/config-reader.js +109 -0
  368. package/pd-cli/dist/config-reader.js.map +1 -0
  369. package/pd-cli/dist/index.js +40 -5
  370. package/pd-cli/dist/index.js.map +1 -1
  371. package/pd-cli/dist/services/console-launcher.d.ts.map +1 -1
  372. package/pd-cli/dist/services/console-launcher.js +29 -15
  373. package/pd-cli/dist/services/console-launcher.js.map +1 -1
  374. package/pd-cli/dist/services/demo-story-a-runner.d.ts.map +1 -1
  375. package/pd-cli/dist/services/demo-story-a-runner.js +1 -0
  376. package/pd-cli/dist/services/demo-story-a-runner.js.map +1 -1
  377. package/pd-cli/dist/utils/production-workspace-guard.d.ts +77 -0
  378. package/pd-cli/dist/utils/production-workspace-guard.d.ts.map +1 -0
  379. package/pd-cli/dist/utils/production-workspace-guard.js +170 -0
  380. package/pd-cli/dist/utils/production-workspace-guard.js.map +1 -0
  381. package/pd-cli/dist/utils/production-workspace-guard.test.d.ts +2 -0
  382. package/pd-cli/dist/utils/production-workspace-guard.test.d.ts.map +1 -0
  383. package/pd-cli/dist/utils/production-workspace-guard.test.js +95 -0
  384. package/pd-cli/dist/utils/production-workspace-guard.test.js.map +1 -0
  385. package/pd-cli/package.json +1 -1
  386. package/plugin/dist/commands/pain.js +27 -2
  387. package/plugin/dist/core/pain-diagnostic-gate.d.ts +6 -0
  388. package/plugin/dist/core/pain-diagnostic-gate.js +9 -0
  389. package/plugin/dist/hooks/after-tool-call-helpers.d.ts +90 -0
  390. package/plugin/dist/hooks/after-tool-call-helpers.js +486 -0
  391. package/plugin/dist/hooks/after-tool-call-types.d.ts +92 -0
  392. package/plugin/dist/hooks/after-tool-call-types.js +13 -0
  393. package/plugin/dist/hooks/gate-block-helper.js +73 -29
  394. package/plugin/dist/hooks/llm.js +49 -29
  395. package/plugin/dist/hooks/message-sanitize.d.ts +21 -0
  396. package/plugin/dist/hooks/message-sanitize.js +30 -0
  397. package/plugin/dist/hooks/pain.d.ts +26 -3
  398. package/plugin/dist/hooks/pain.js +165 -425
  399. package/plugin/dist/hooks/prompt.js +3 -2
  400. package/plugin/dist/hooks/trajectory-evidence.d.ts +11 -0
  401. package/plugin/dist/hooks/trajectory-evidence.js +65 -0
  402. package/plugin/dist/hooks/triage-adapter.d.ts +82 -0
  403. package/plugin/dist/hooks/triage-adapter.js +121 -0
  404. package/console/dist/server/models/EventLogReadModel.d.ts +0 -33
  405. package/console/dist/server/models/EventLogReadModel.js +0 -218
  406. package/console/dist/server/models/EvolutionConsoleModel.d.ts +0 -79
  407. package/console/dist/server/models/EvolutionConsoleModel.js +0 -179
  408. package/console/dist/server/models/FeedbackConsoleModel.d.ts +0 -38
  409. package/console/dist/server/models/FeedbackConsoleModel.js +0 -129
  410. package/console/dist/server/models/GateConsoleModel.d.ts +0 -50
  411. package/console/dist/server/models/GateConsoleModel.js +0 -151
  412. package/console/dist/server/models/OverviewConsoleModel.d.ts +0 -22
  413. package/console/dist/server/models/OverviewConsoleModel.js +0 -202
  414. package/console/dist/server/models/PipelineStatsModel.d.ts +0 -35
  415. package/console/dist/server/models/PipelineStatsModel.js +0 -129
  416. package/console/dist/server/models/SampleConsoleModel.d.ts +0 -21
  417. package/console/dist/server/models/SampleConsoleModel.js +0 -188
  418. package/console/dist/server/models/ThinkingModelsConsoleModel.d.ts +0 -22
  419. package/console/dist/server/models/ThinkingModelsConsoleModel.js +0 -75
  420. package/console/dist/server/routes/agents.d.ts +0 -3
  421. package/console/dist/server/routes/agents.js +0 -442
  422. package/console/dist/server/routes/central.d.ts +0 -5
  423. package/console/dist/server/routes/central.js +0 -31
  424. package/console/dist/server/routes/events.d.ts +0 -10
  425. package/console/dist/server/routes/events.js +0 -99
  426. package/console/dist/server/routes/evolution.js +0 -73
  427. package/console/dist/server/routes/feedback.d.ts +0 -3
  428. package/console/dist/server/routes/feedback.js +0 -65
  429. package/console/dist/server/routes/gates.d.ts +0 -3
  430. package/console/dist/server/routes/gates.js +0 -52
  431. package/console/dist/server/routes/overview.d.ts +0 -3
  432. package/console/dist/server/routes/overview.js +0 -49
  433. package/console/dist/server/routes/pipeline.d.ts +0 -3
  434. package/console/dist/server/routes/pipeline.js +0 -33
  435. package/console/dist/server/routes/samples.d.ts +0 -3
  436. package/console/dist/server/routes/samples.js +0 -101
  437. package/console/dist/server/routes/thinking-models.d.ts +0 -3
  438. package/console/dist/server/routes/thinking-models.js +0 -54
  439. package/console/dist/ui/components/app-sidebar.d.ts +0 -7
  440. package/console/dist/ui/components/app-sidebar.js +0 -75
  441. package/console/dist/ui/components/compare-view.d.ts +0 -7
  442. package/console/dist/ui/components/compare-view.js +0 -32
  443. package/console/dist/ui/components/data-freshness-indicator.d.ts +0 -10
  444. package/console/dist/ui/components/data-freshness-indicator.js +0 -63
  445. package/console/dist/ui/components/health-diagnostic-card.d.ts +0 -15
  446. package/console/dist/ui/components/health-diagnostic-card.js +0 -42
  447. package/console/dist/ui/components/page-header.d.ts +0 -10
  448. package/console/dist/ui/components/page-header.js +0 -37
  449. package/console/dist/ui/hooks/useAutoRefresh.d.ts +0 -13
  450. package/console/dist/ui/hooks/useAutoRefresh.js +0 -64
  451. package/console/dist/ui/hooks/useBookmarks.d.ts +0 -6
  452. package/console/dist/ui/hooks/useBookmarks.js +0 -43
  453. package/console/dist/ui/hooks/useDebounce.d.ts +0 -2
  454. package/console/dist/ui/hooks/useDebounce.js +0 -32
  455. package/console/dist/ui/hooks/useKeyboardNavigation.d.ts +0 -14
  456. package/console/dist/ui/hooks/useKeyboardNavigation.js +0 -75
  457. package/console/dist/ui/pages/AgentsPage.d.ts +0 -1
  458. package/console/dist/ui/pages/AgentsPage.js +0 -167
  459. package/console/dist/ui/pages/ApprovalsPage.d.ts +0 -1
  460. package/console/dist/ui/pages/ApprovalsPage.js +0 -123
  461. package/console/dist/ui/pages/CentralPage.d.ts +0 -1
  462. package/console/dist/ui/pages/CentralPage.js +0 -57
  463. package/console/dist/ui/pages/DataFlowPage.d.ts +0 -1
  464. package/console/dist/ui/pages/DataFlowPage.js +0 -158
  465. package/console/dist/ui/pages/EventLogPage.d.ts +0 -1
  466. package/console/dist/ui/pages/EventLogPage.js +0 -176
  467. package/console/dist/ui/pages/EvolutionPage.d.ts +0 -1
  468. package/console/dist/ui/pages/EvolutionPage.js +0 -118
  469. package/console/dist/ui/pages/FeedbackPage.d.ts +0 -1
  470. package/console/dist/ui/pages/FeedbackPage.js +0 -46
  471. package/console/dist/ui/pages/GatesPage.d.ts +0 -1
  472. package/console/dist/ui/pages/GatesPage.js +0 -31
  473. package/console/dist/ui/pages/LoginPage.d.ts +0 -5
  474. package/console/dist/ui/pages/LoginPage.js +0 -39
  475. package/console/dist/ui/pages/OverviewPage.d.ts +0 -1
  476. package/console/dist/ui/pages/OverviewPage.js +0 -50
  477. package/console/dist/ui/pages/PainPage.js +0 -50
  478. package/console/dist/ui/pages/PrincipleDetailPage.js +0 -145
  479. package/console/dist/ui/pages/PrinciplesPage.js +0 -322
  480. package/console/dist/ui/pages/ReportProblemPage.js +0 -186
  481. package/console/dist/ui/pages/SamplesPage.d.ts +0 -1
  482. package/console/dist/ui/pages/SamplesPage.js +0 -105
  483. package/console/dist/ui/pages/SettingsPage.d.ts +0 -1
  484. package/console/dist/ui/pages/SettingsPage.js +0 -86
  485. package/console/dist/ui/pages/TasksPage.d.ts +0 -1
  486. package/console/dist/ui/pages/TasksPage.js +0 -373
  487. package/console/dist/ui/pages/ThinkingModelsPage.d.ts +0 -1
  488. package/console/dist/ui/pages/ThinkingModelsPage.js +0 -32
  489. package/console/dist/ui/pages/UpdatePage.d.ts +0 -1
  490. package/console/dist/ui/pages/UpdatePage.js +0 -142
  491. /package/console/dist/ui/pages/{PainPage.d.ts → pain/PainPage.d.ts} +0 -0
  492. /package/console/dist/ui/pages/{PrincipleDetailPage.d.ts → principles/PrincipleDetailPage.d.ts} +0 -0
  493. /package/console/dist/ui/pages/{PrinciplesPage.d.ts → principles/PrinciplesPage.d.ts} +0 -0
  494. /package/console/dist/ui/pages/{ReportProblemPage.d.ts → report-problem/ReportProblemPage.d.ts} +0 -0
@@ -1,80 +1,49 @@
1
+ /**
2
+ * Pain Hook — PRI-326 decomposed
3
+ *
4
+ * After-tool-call hook that captures tool failures and emits pain signals.
5
+ *
6
+ * Pipeline stages (delegated to after-tool-call-helpers):
7
+ * 1. classifyToolCallOutcome — determine failure/success + source
8
+ * 2. buildToolCallObservation — normalize event into observation
9
+ * 3. handleFrictionTracking — GFI, event log, trajectory recording
10
+ * 4. handleProbationFeedback — probation attribution + cleanup
11
+ * 5. evaluatePainAdmission — triage + gate evaluation
12
+ * 6. emitPainIfAdmitted — pain signal emission
13
+ *
14
+ * The manual pain path (toolName === 'pain') remains inline because it
15
+ * has a different control flow (early return, no triage, no gate on cooldown).
16
+ */
1
17
  import * as fs from 'fs';
2
- import { isRisky, normalizePath } from '../utils/io.js';
3
18
  import { normalizeProfile } from '../core/profile.js';
4
- import { computePainScore, trackPrincipleValue } from '../core/pain.js';
5
- import { getSession, trackFriction, resetFriction, getInjectedProbationIds, clearInjectedProbationIds } from '../core/session-tracker.js';
6
- import { denoiseError, computeHash } from '../utils/hashing.js';
19
+ import { getSession, trackFriction } from '../core/session-tracker.js';
20
+ import { computeHash } from '../utils/hashing.js';
7
21
  import { SystemLogger } from '../core/system-logger.js';
8
22
  import { WorkspaceContext } from '../core/workspace-context.js';
9
23
  import { getEvolutionLogger, createTraceId } from '../core/evolution-logger.js';
10
- import { recordEvolutionSuccess, recordEvolutionFailure } from '../core/evolution-engine.js';
11
24
  import { resolveWorkspaceDirForRuntimeV2 } from '../utils/workspace-resolver.js';
12
- import { PainToPrincipleService, PrincipleTreeLedgerAdapter, MAX_EVIDENCE_ENTRIES, MAX_EVIDENCE_NOTE_CHARS } from '@principles/core/runtime-v2';
25
+ import { PainToPrincipleService, PrincipleTreeLedgerAdapter } from '@principles/core/runtime-v2';
13
26
  import { evaluatePainDiagnosticGate } from '../core/pain-diagnostic-gate.js';
14
- import { sanitizeAssistantText } from './message-sanitize.js';
15
- const WRITE_TOOLS = ['write', 'edit', 'apply_patch', 'write_file', 'edit_file', 'replace'];
27
+ import { loadPdConfigForPlugin } from '../core/pd-config-loader.js';
28
+ import { classifyToolCallOutcome, buildToolCallObservation, handleFrictionTrackingForFailure, handleFrictionTrackingForSuccess, recordHygieneTracking, handleProbationFeedback, evaluatePainAdmissionForToolCall, emitPainIfAdmitted, } from './after-tool-call-helpers.js';
29
+ import { buildTrajectoryEvidence } from './trajectory-evidence.js';
30
+ export { buildTrajectoryEvidence };
31
+ // ── Service Factory ─────────────────────────────────────────────────────────
16
32
  function createPainToPrincipleService(wctx) {
17
33
  const ledgerAdapter = new PrincipleTreeLedgerAdapter({ stateDir: wctx.stateDir });
34
+ const configResult = loadPdConfigForPlugin(wctx.workspaceDir);
18
35
  return new PainToPrincipleService({
19
36
  workspaceDir: wctx.workspaceDir,
20
37
  stateDir: wctx.stateDir,
21
38
  ledgerAdapter,
22
39
  owner: 'openclaw-plugin',
23
40
  autoIntakeEnabled: true,
41
+ effectiveConfig: configResult.effective,
42
+ getEnvVar: (name) => process.env[name],
24
43
  });
25
44
  }
26
- export function buildTrajectoryEvidence(wctx, sessionId) {
27
- const evidence = [];
28
- if (!wctx.trajectory || sessionId === 'unknown') {
29
- evidence.push({
30
- sourceRef: 'owner_message:unavailable',
31
- note: `trajectory_unavailable: ${!wctx.trajectory ? 'no_trajectory_db' : 'unknown_session'}`,
32
- });
33
- return evidence.slice(0, MAX_EVIDENCE_ENTRIES);
34
- }
35
- try {
36
- const userTurns = wctx.trajectory.listUserTurnsForSession(sessionId) ?? [];
37
- const lastCorrectionTurn = [...userTurns].reverse().find(t => t.correctionDetected);
38
- if (lastCorrectionTurn) {
39
- const sanitizedOwnerMessage = sanitizeAssistantText((lastCorrectionTurn.rawExcerpt ?? '').slice(0, MAX_EVIDENCE_NOTE_CHARS));
40
- evidence.push({
41
- sourceRef: `owner_message:${lastCorrectionTurn.createdAt}`,
42
- note: sanitizedOwnerMessage,
43
- });
44
- }
45
- }
46
- catch (e) {
47
- evidence.push({
48
- sourceRef: 'owner_message:unavailable',
49
- note: `trajectory_user_turns_unavailable: ${String(e).slice(0, 100)}`,
50
- });
51
- }
52
- try {
53
- const assistantTurns = wctx.trajectory.listAssistantTurns(sessionId) ?? [];
54
- const recentAssistant = assistantTurns.slice(-3);
55
- for (const turn of recentAssistant) {
56
- if (evidence.length >= MAX_EVIDENCE_ENTRIES)
57
- break;
58
- const sanitizedNote = sanitizeAssistantText((turn.sanitizedText ?? '').slice(0, MAX_EVIDENCE_NOTE_CHARS));
59
- evidence.push({
60
- sourceRef: `agent_turn:${turn.createdAt}`,
61
- note: sanitizedNote,
62
- });
63
- }
64
- }
65
- catch (e) {
66
- if (evidence.length < MAX_EVIDENCE_ENTRIES) {
67
- evidence.push({
68
- sourceRef: 'agent_turn:unavailable',
69
- note: `trajectory_assistant_turns_unavailable: ${String(e).slice(0, 100)}`,
70
- });
71
- }
72
- }
73
- return evidence.slice(0, MAX_EVIDENCE_ENTRIES);
74
- }
75
- function shouldAttributePrincipleToTool(principle, toolName) {
76
- return principle.contextTags.includes(toolName) || principle.trigger.includes(toolName);
77
- }
45
+ // buildTrajectoryEvidence is in ./trajectory-evidence.ts (re-exported above)
46
+ // ── Pain Event Emission ─────────────────────────────────────────────────────
78
47
  export async function emitPainDetectedEvent(wctx, event) {
79
48
  try {
80
49
  wctx.evolutionReducer.emitSync(event);
@@ -87,6 +56,18 @@ export async function emitPainDetectedEvent(wctx, event) {
87
56
  const painData = event.data;
88
57
  try {
89
58
  const service = createPainToPrincipleService(wctx);
59
+ const isManual = painData.source === 'manual' || painData.source === 'pain' || painData.source === 'skill:pain';
60
+ // PEAT-B2: Record trigger decision for observability
61
+ if (isManual) {
62
+ SystemLogger.log(wctx.workspaceDir, 'TRIGGER_DECISION', JSON.stringify({
63
+ outcome: 'manual_owner_admitted',
64
+ sourceKind: 'owner_reported',
65
+ reason: 'Owner explicit manual pain. Bypasses triage and cooldown.',
66
+ nextAction: 'create_diagnostic_task',
67
+ painId: painData.painId,
68
+ score: painData.score,
69
+ }));
70
+ }
90
71
  const result = await service.recordPain({
91
72
  painId: painData.painId,
92
73
  painType: painData.painType,
@@ -127,36 +108,39 @@ export async function emitPainDetectedEvent(wctx, event) {
127
108
  function createPainId(sessionId) {
128
109
  return `pain_${Date.now()}_${computeHash(sessionId).slice(0, 8)}`;
129
110
  }
130
- export function classifyToolFailureSource(toolName, error) {
131
- if (!toolName || toolName.trim() === '')
132
- return 'dispatch_error';
133
- const msg = String(error ?? '');
134
- // Dropped "error:" prefix to catch "failed: unknown tool read_file" style messages.
135
- // Catches: "tool not found", "tool <name> not found", "unknown tool".
136
- // Word-boundary anchors prevent "report_tool_not_found" from matching.
137
- if (/\btool\s+(?:\S+\s+)?not\s+found\b/i.test(msg))
138
- return 'dispatch_error';
139
- if (/\bunknown\s+tool\b/i.test(msg))
140
- return 'dispatch_error';
141
- return 'tool_failure';
142
- }
111
+ // ── Source Classification (re-exported from helpers) ────────────────────────
112
+ export { classifyToolFailureSource } from './after-tool-call-helpers.js';
113
+ // ── Main Hook ───────────────────────────────────────────────────────────────
114
+ /**
115
+ * Handle after_tool_call hook decomposed into pipeline stages.
116
+ *
117
+ * Pipeline: classify record → triage → gate → emit
118
+ *
119
+ * Manual pain (toolName === 'pain') is handled inline with early return.
120
+ */
143
121
  export function handleAfterToolCall(event, ctx, api) {
122
+ // ── Workspace Resolution ──
144
123
  let effectiveWorkspaceDir;
145
124
  try {
146
125
  effectiveWorkspaceDir = resolveWorkspaceDirForRuntimeV2(ctx, api, 'after_tool_call');
147
126
  }
148
- catch {
127
+ catch (error) {
128
+ SystemLogger.log(ctx.workspaceDir ?? 'unknown', 'WORKSPACE_RESOLUTION_FAILED', JSON.stringify({
129
+ hook: 'after_tool_call',
130
+ sessionId: ctx.sessionId ?? 'unknown',
131
+ toolName: event.toolName,
132
+ reason: 'workspace_resolution_failed',
133
+ nextAction: 'check_plugin_config_workspace_resolution',
134
+ error: String(error).slice(0, 200),
135
+ }));
149
136
  return;
150
137
  }
151
138
  const wctx = WorkspaceContext.fromHookContextExplicit({ ...ctx, workspaceDir: effectiveWorkspaceDir });
152
139
  const { config } = wctx;
153
- const { eventLog } = wctx;
154
140
  const sessionId = ctx.sessionId || 'unknown';
155
141
  const sessionState = ctx.sessionId ? getSession(ctx.sessionId) : undefined;
156
142
  const gfiBefore = sessionState?.currentGfi ?? 0;
157
- let latestFailureState;
158
- const params = event.params;
159
- // Load profile once (with 1MB size guard) — used by both failure and legacy risky-write paths
143
+ // ── Profile Loading (once per call) ──
160
144
  const profilePath = wctx.resolve('PROFILE');
161
145
  let profile = normalizeProfile({});
162
146
  if (fs.existsSync(profilePath)) {
@@ -173,381 +157,137 @@ export function handleAfterToolCall(event, ctx, api) {
173
157
  SystemLogger.log(effectiveWorkspaceDir, 'PROFILE_PARSE_WARN', `Failed to parse PROFILE.json: ${String(e)}`);
174
158
  }
175
159
  }
176
- // ── Track A: Empirical Friction (GFI) ──
177
- // 0. Special Case: Manual Pain Intervention
160
+ // ── Manual Pain Early Return ──
178
161
  if (event.toolName === 'pain' || event.toolName === 'skill:pain') {
179
- const reason = params.input || params.arguments || 'Manual intervention';
180
- const traceId = createTraceId();
181
- trackFriction(sessionId, 100, 'manual_pain', effectiveWorkspaceDir, { source: 'manual_pain' });
182
- SystemLogger.log(effectiveWorkspaceDir, 'MANUAL_PAIN', `User manually triggered pain: ${reason}`);
183
- eventLog.recordPainSignal(sessionId, {
184
- score: 100,
185
- source: 'manual',
186
- reason: `User intervention: ${reason}`,
187
- isRisky: true
188
- });
189
- wctx.trajectory?.recordPainEvent?.({
190
- sessionId,
191
- source: 'manual',
192
- score: 100,
193
- reason: `User intervention: ${reason}`,
194
- origin: 'user_manual',
195
- text: reason, // Store the intervention reason as text
196
- });
197
- // Log to EvolutionLogger
198
- const evoLogger = getEvolutionLogger(effectiveWorkspaceDir, wctx.trajectory);
199
- evoLogger.logPainDetected({
200
- traceId,
201
- source: 'manual',
202
- reason: `User intervention: ${reason}`,
203
- score: 100,
204
- toolName: event.toolName,
205
- sessionId,
206
- });
207
- // Apply PainDiagnosticGate with cooldown to prevent duplicate diagnoses
208
- const session = getSession(sessionId);
209
- const gate = evaluatePainDiagnosticGate({
210
- source: 'manual',
211
- score: 100,
212
- currentGfi: session?.currentGfi ?? 0,
213
- sessionId,
214
- });
215
- if (!gate.shouldDiagnose) {
216
- SystemLogger.log(effectiveWorkspaceDir, 'MANUAL_PAIN_SKIPPED', `Manual pain within cooldown: ${gate.detail}`);
217
- let payload;
218
- try {
219
- payload = JSON.stringify({
220
- reason: gate.reason,
221
- detail: gate.detail,
222
- source: 'manual',
223
- sessionId,
224
- gfi: 0,
225
- score: 100,
226
- });
227
- }
228
- catch (e) {
229
- SystemLogger.log(effectiveWorkspaceDir, 'PAYLOAD_SERIALIZE_FAILED', String(e));
230
- payload = JSON.stringify({ reason: gate.reason, detail: '(log serialization failed)' });
231
- }
232
- SystemLogger.log(effectiveWorkspaceDir, 'PAIN_GATE_REJECTED', payload);
233
- return;
234
- }
235
- emitPainDetectedEvent(wctx, {
236
- ts: new Date().toISOString(),
237
- type: 'pain_detected',
238
- data: {
239
- painId: createPainId(sessionId),
240
- painType: 'user_frustration',
241
- source: event.toolName,
242
- reason: `User intervention: ${reason}`,
243
- score: 100,
244
- sessionId,
245
- traceId,
246
- agentId: ctx.agentId,
247
- provenance: (sessionId && sessionId !== 'unknown') ? 'openclaw_context_bound' : 'owner_reported_no_host_trace',
248
- evidence: buildTrajectoryEvidence(wctx, sessionId),
249
- },
250
- });
162
+ handleManualPain(event, ctx, wctx, effectiveWorkspaceDir, sessionId);
251
163
  return;
252
164
  }
253
- // 1. Determine if this was a failure
254
- // Support nested details structure where OpenClaw exec tool stores exitCode in result.details.exitCode
255
- // Prefer the first *numeric* exit code: if result.exitCode is non-numeric, fall back to details.exitCode
256
- const resultObj = (event.result && typeof event.result === 'object') ? event.result : null;
257
- const details = resultObj?.details && typeof resultObj.details === 'object' ? resultObj.details : null;
258
- const topExitCode = resultObj?.exitCode;
259
- const detailExitCode = details?.exitCode;
260
- const exitCode = typeof topExitCode === 'number' ? topExitCode
261
- : typeof detailExitCode === 'number' ? detailExitCode
262
- : 0;
263
- const isFailure = !!event.error || exitCode !== 0;
264
- if (isFailure) {
265
- const failureSource = classifyToolFailureSource(event.toolName, event.error);
266
- const errorText = String(event.error ?? (typeof event.result === 'string' ? event.result : JSON.stringify(event.result)));
267
- const denoised = denoiseError(errorText);
268
- const hash = computeHash(denoised);
269
- const deltaF = config.get('scores.tool_failure_friction') || 30;
270
- const updatedState = trackFriction(sessionId, deltaF, hash, effectiveWorkspaceDir, { source: failureSource });
271
- latestFailureState = updatedState;
272
- // ── Trust Engine: Record failure ──
273
- const errorType = extractErrorType(event.error || errorText);
274
- const filePath = params.file_path || params.path || params.file;
275
- const relPath = typeof filePath === 'string' ? normalizePath(filePath, effectiveWorkspaceDir) : 'unknown';
276
- // Use profile loaded at function scope (1MB guard already applied)
277
- const isRisk = isRisky(relPath, profile.risk_paths);
278
- recordEvolutionFailure(effectiveWorkspaceDir, event.toolName, {
279
- filePath: relPath,
280
- reason: isRisk ? 'risky' : 'tool',
281
- sessionId,
282
- });
283
- // Record tool call failure event
284
- eventLog.recordToolCall(sessionId, {
285
- toolName: event.toolName,
286
- filePath: typeof filePath === 'string' ? filePath : undefined,
287
- error: event.error ? String(event.error).substring(0, 200) : undefined,
288
- errorType,
289
- gfi: updatedState.currentGfi,
290
- consecutiveErrors: updatedState.consecutiveErrors,
291
- exitCode: exitCode,
292
- gfiBefore,
293
- gfiAfter: updatedState.currentGfi,
294
- });
295
- wctx.trajectory?.recordToolCall?.({
296
- sessionId,
297
- toolName: event.toolName,
298
- outcome: 'failure',
299
- durationMs: event.durationMs,
300
- exitCode: exitCode,
301
- errorType,
302
- errorMessage: event.error ? String(event.error) : undefined,
303
- gfiBefore,
304
- gfiAfter: updatedState.currentGfi,
305
- paramsJson: event.params,
306
- });
307
- const injectedProbationIds = getInjectedProbationIds(sessionId, effectiveWorkspaceDir);
308
- for (const id of injectedProbationIds) {
309
- const principle = wctx.evolutionReducer.getPrincipleById(id);
310
- const shouldAttribute = !!principle && shouldAttributePrincipleToTool(principle, event.toolName);
311
- if (shouldAttribute) {
312
- wctx.evolutionReducer.recordProbationFeedback(id, false);
313
- }
314
- }
315
- clearInjectedProbationIds(sessionId, effectiveWorkspaceDir);
165
+ // ── Stage 1: Classify ──
166
+ const outcome = classifyToolCallOutcome(event);
167
+ // ── Stage 2: Build Observation ──
168
+ const observation = buildToolCallObservation(event, outcome, effectiveWorkspaceDir, profile);
169
+ let latestFailureState;
170
+ if (outcome.isFailure) {
171
+ // ── Stage 3a: Friction + Recording (Failure) ──
172
+ latestFailureState = handleFrictionTrackingForFailure(sessionId, event, outcome, observation, gfiBefore, effectiveWorkspaceDir, config, wctx);
173
+ // ── Stage 4: Probation Feedback (Failure) ──
174
+ handleProbationFeedback(sessionId, event.toolName, effectiveWorkspaceDir, wctx, false);
316
175
  }
317
176
  else {
318
- // ── SUCCESS BRANCH ──
319
- // PRI-80: Relieve both dispatch_error and tool_failure on success.
320
- // This prevents "read file success" from wiping dispatch error signals.
321
- const session = getSession(sessionId);
322
- const toolFailureGfi = session?.gfiBySource?.tool_failure || 0;
323
- const dispatchErrorGfi = session?.gfiBySource?.dispatch_error || 0;
324
- let resetState = session || resetFriction(sessionId, effectiveWorkspaceDir);
325
- if (toolFailureGfi > 0 || dispatchErrorGfi > 0) {
326
- // Relieve both sources proportionally (50% relief each)
327
- if (toolFailureGfi > 0) {
328
- const reliefAmount = toolFailureGfi * 0.5;
329
- resetState = resetFriction(sessionId, effectiveWorkspaceDir, {
330
- source: 'tool_failure',
331
- amount: reliefAmount,
332
- });
333
- }
334
- if (dispatchErrorGfi > 0) {
335
- const reliefAmount = dispatchErrorGfi * 0.5;
336
- resetState = resetFriction(sessionId, effectiveWorkspaceDir, {
337
- source: 'dispatch_error',
338
- amount: reliefAmount,
339
- });
340
- }
341
- }
342
- recordEvolutionSuccess(effectiveWorkspaceDir, event.toolName, {
343
- sessionId,
344
- reason: 'tool_success',
345
- });
346
- const injectedProbationIds = getInjectedProbationIds(sessionId, effectiveWorkspaceDir);
347
- for (const id of injectedProbationIds) {
348
- const principle = wctx.evolutionReducer.getPrincipleById(id);
349
- const shouldAttribute = !!principle && shouldAttributePrincipleToTool(principle, event.toolName);
350
- if (shouldAttribute) {
351
- wctx.evolutionReducer.recordProbationFeedback(id, true);
352
- }
353
- }
354
- clearInjectedProbationIds(sessionId, effectiveWorkspaceDir);
355
- wctx.trajectory?.recordToolCall?.({
356
- sessionId,
357
- toolName: event.toolName,
358
- outcome: 'success',
359
- durationMs: event.durationMs,
360
- exitCode,
361
- gfiBefore,
362
- gfiAfter: resetState.currentGfi,
363
- paramsJson: event.params,
364
- });
365
- const filePath = params.file_path || params.path || params.file;
366
- eventLog.recordToolCall(sessionId, {
367
- toolName: event.toolName,
368
- filePath: typeof filePath === 'string' ? filePath : undefined,
369
- gfi: resetState.currentGfi,
370
- gfiBefore,
371
- gfiAfter: resetState.currentGfi,
372
- });
373
- // ── Hygiene Tracking: Record persistence actions ──
374
- const normalized = typeof filePath === 'string' ? filePath.replace(/\\/g, '/') : '';
375
- const isMemory = /(?:^|\/)memory\//.test(normalized) || normalized.endsWith('/MEMORY.md') || normalized === 'MEMORY.md';
376
- const isPlan = normalized === 'PLAN.md' || normalized.endsWith('/PLAN.md');
377
- if (isMemory || isPlan) {
378
- const content = params.content || params.new_string || '';
379
- wctx.hygiene.recordPersistence({
380
- ts: new Date().toISOString(),
381
- tool: event.toolName,
382
- path: typeof filePath === 'string' ? filePath : 'unknown',
383
- type: isMemory ? 'memory' : 'plan',
384
- contentLength: content.length,
385
- });
386
- }
387
- // Special case for memory_store tool (Success only)
388
- if (event.toolName === 'memory_store') {
389
- const text = params.text || '';
390
- wctx.hygiene.recordPersistence({
391
- ts: new Date().toISOString(),
392
- tool: event.toolName,
393
- path: 'DATABASE',
394
- type: 'memory',
395
- contentLength: text.length,
396
- });
397
- }
177
+ // ── Stage 3b: Friction + Recording (Success) ──
178
+ handleFrictionTrackingForSuccess(sessionId, event, outcome, observation, gfiBefore, effectiveWorkspaceDir, wctx);
179
+ // ── Stage 4: Probation Feedback (Success) ──
180
+ handleProbationFeedback(sessionId, event.toolName, effectiveWorkspaceDir, wctx, true);
181
+ // ── Stage 5b: Hygiene Tracking (Success only) ──
182
+ recordHygieneTracking(event, observation, wctx);
398
183
  }
399
- // ── Legacy/Risky Write Pain Logic (Unified WRITE_TOOLS) ──
400
- if (!WRITE_TOOLS.includes(event.toolName) || !isFailure) {
184
+ // ── Stage 6: Pain Admission ──
185
+ const admission = evaluatePainAdmissionForToolCall(event, observation, outcome, latestFailureState, sessionState, sessionId, effectiveWorkspaceDir, config);
186
+ if (admission.stage === 'not_applicable') {
401
187
  return;
402
188
  }
403
- const failureSource = classifyToolFailureSource(event.toolName, event.error);
404
- const filePath = params.file_path || params.path || params.file;
405
- const relPath = typeof filePath === 'string' ? normalizePath(filePath, effectiveWorkspaceDir) : 'unknown';
406
- const isRisk = isRisky(relPath, profile.risk_paths);
407
- const painScore = computePainScore(1, false, false, isRisk ? 20 : 0, effectiveWorkspaceDir);
189
+ // ── Stage 7: Emit Pain (only if admitted) ──
190
+ emitPainIfAdmitted(wctx, event, observation, outcome, admission, sessionId, ctx.agentId, effectiveWorkspaceDir, emitPainDetectedEvent);
191
+ }
192
+ // ── Manual Pain Handler ─────────────────────────────────────────────────────
193
+ /**
194
+ * Handle manual pain intervention (toolName === 'pain' or 'skill:pain').
195
+ *
196
+ * This path is separate because:
197
+ * - It always records pain at score 100
198
+ * - It uses a different GFI track (manual_pain)
199
+ * - It has its own cooldown via PainDiagnosticGate
200
+ * - It does NOT go through evidence triage
201
+ */
202
+ function handleManualPain(event, ctx, wctx, workspaceDir, sessionId) {
203
+ const rawParams = event.params;
204
+ const params = (rawParams && typeof rawParams === 'object' && !Array.isArray(rawParams))
205
+ ? rawParams
206
+ : {};
207
+ const reason = params.input || params.arguments || 'Manual intervention';
408
208
  const traceId = createTraceId();
409
- const diagnosticGate = evaluatePainDiagnosticGate({
410
- source: failureSource,
411
- score: painScore,
412
- currentGfi: (latestFailureState ?? getSession(sessionId) ?? sessionState)?.currentGfi ?? 0,
413
- consecutiveErrors: (latestFailureState ?? getSession(sessionId) ?? sessionState)?.consecutiveErrors ?? 0,
414
- isRisky: isRisk,
415
- errorHash: latestFailureState?.lastErrorHash,
416
- sessionId,
417
- thresholds: {
418
- painTrigger: config.get('thresholds.pain_trigger') || 40,
419
- highSeverity: config.get('severity_thresholds.high') || 70,
420
- repeatedFailure: config.get('thresholds.stuck_loops_trigger') || 4,
421
- },
209
+ // Track friction at max score
210
+ trackFriction(sessionId, 100, 'manual_pain', workspaceDir, { source: 'manual_pain' });
211
+ SystemLogger.log(workspaceDir, 'MANUAL_PAIN', `User manually triggered pain: ${reason}`);
212
+ wctx.eventLog.recordPainSignal(sessionId, {
213
+ score: 100,
214
+ source: 'manual',
215
+ reason: `User intervention: ${reason}`,
216
+ isRisky: true
422
217
  });
423
- if (!diagnosticGate.shouldDiagnose) {
424
- SystemLogger.log(effectiveWorkspaceDir, 'PAIN_DIAGNOSE_SKIPPED', `Tool failure recorded as friction only: ${diagnosticGate.detail}; tool=${event.toolName}; path=${relPath}`);
425
- // Structured gate rejection event for traceability
426
- let rejectPayload;
427
- try {
428
- rejectPayload = JSON.stringify({
429
- reason: diagnosticGate.reason,
430
- detail: diagnosticGate.detail,
431
- source: failureSource,
432
- sessionId: sessionId,
433
- gfi: (latestFailureState ?? getSession(sessionId) ?? sessionState)?.currentGfi ?? 0,
434
- score: painScore,
435
- });
436
- }
437
- catch (e) {
438
- SystemLogger.log(effectiveWorkspaceDir, 'PAYLOAD_SERIALIZE_FAILED', String(e));
439
- rejectPayload = JSON.stringify({ reason: diagnosticGate.reason, detail: '(log serialization failed)' });
440
- }
441
- SystemLogger.log(effectiveWorkspaceDir, 'PAIN_GATE_REJECTED', rejectPayload);
442
- return;
443
- }
444
- // Record to trajectory before Runtime V2 diagnosis so the compiler can later
445
- // resolve derivedFromPainIds to the originating failed action.
446
- wctx.trajectory?.recordPainEvent({
218
+ wctx.trajectory?.recordPainEvent?.({
447
219
  sessionId,
448
- source: failureSource,
449
- score: painScore,
450
- reason: `Tool ${event.toolName} failed on ${relPath}`,
451
- severity: painScore >= 70 ? 'severe' : painScore >= 40 ? 'moderate' : 'mild',
452
- origin: 'system_infer',
453
- text: params.text ?? params.content ?? undefined,
454
- });
455
- // Pain signal emitted via emitPainDetectedEvent below — no .pain_flag file written (M8: single-path chain)
456
- // Observe: track which principles would have prevented this pain (Phase 1, observation-only)
457
- try {
458
- trackPrincipleValue(effectiveWorkspaceDir, {
459
- reason: `Tool ${event.toolName} failed on ${relPath}. Error: ${event.error ?? 'Non-zero exit code'}`,
460
- source: failureSource,
461
- score: String(painScore),
462
- }, () => wctx.evolutionReducer.getActivePrinciples().map((p) => ({
463
- id: p.id,
464
- trigger: p.trigger,
465
- valueMetrics: p.valueMetrics,
466
- })), (id, metrics) => {
467
- const principle = wctx.evolutionReducer.getPrincipleById(id);
468
- if (principle) {
469
- principle.valueMetrics = metrics;
470
- // Persist to training state (best-effort, non-critical)
471
- try {
472
- wctx.principleTreeLedger.updatePrincipleValueMetrics(id, {
473
- principleId: id,
474
- painPreventedCount: metrics.painPreventedCount,
475
- lastPainPreventedAt: metrics.lastPainPreventedAt,
476
- calculatedAt: metrics.calculatedAt,
477
- avgPainSeverityPrevented: 0,
478
- totalOpportunities: 0,
479
- adheredCount: 0,
480
- violatedCount: 0,
481
- implementationCost: 0,
482
- benefitScore: 0,
483
- });
484
- }
485
- catch (e) {
486
- // Non-critical — metrics tracked in memory
487
- SystemLogger.log(effectiveWorkspaceDir, 'METRICS_UPDATE_SKIP', String(e));
488
- }
489
- }
490
- });
491
- }
492
- catch (e) {
493
- // Observation only — never disrupt the pain pipeline
494
- SystemLogger.log(effectiveWorkspaceDir, ' PRINCIPLE_TRACK_SKIP', String(e));
495
- }
496
- eventLog.recordPainSignal(sessionId, {
497
- score: painScore,
498
- source: failureSource,
499
- reason: `Tool ${event.toolName} failed on ${relPath}`,
500
- isRisky: isRisk,
220
+ source: 'manual',
221
+ score: 100,
222
+ reason: `User intervention: ${reason}`,
223
+ origin: 'user_manual',
224
+ text: reason,
501
225
  });
502
226
  // Log to EvolutionLogger
503
- const evoLogger = getEvolutionLogger(effectiveWorkspaceDir, wctx.trajectory);
227
+ const evoLogger = getEvolutionLogger(workspaceDir, wctx.trajectory);
504
228
  evoLogger.logPainDetected({
505
229
  traceId,
506
- source: failureSource,
507
- reason: `Tool ${event.toolName} failed on ${relPath}`,
508
- score: painScore,
230
+ source: 'manual',
231
+ reason: `User intervention: ${reason}`,
232
+ score: 100,
509
233
  toolName: event.toolName,
510
- filePath: relPath,
511
234
  sessionId,
512
235
  });
236
+ // Apply PainDiagnosticGate with cooldown
237
+ const session = getSession(sessionId);
238
+ const gate = evaluatePainDiagnosticGate({
239
+ source: 'manual',
240
+ score: 100,
241
+ currentGfi: session?.currentGfi ?? 0,
242
+ sessionId,
243
+ });
244
+ if (!gate.shouldDiagnose) {
245
+ SystemLogger.log(workspaceDir, 'MANUAL_PAIN_SKIPPED', `Manual pain within cooldown: ${gate.detail}`);
246
+ let payload;
247
+ try {
248
+ payload = JSON.stringify({
249
+ reason: gate.reason,
250
+ detail: gate.detail,
251
+ source: 'manual',
252
+ sessionId,
253
+ gfi: 0,
254
+ score: 100,
255
+ });
256
+ }
257
+ catch (e) {
258
+ SystemLogger.log(workspaceDir, 'PAYLOAD_SERIALIZE_FAILED', String(e));
259
+ payload = JSON.stringify({ reason: gate.reason, detail: '(log serialization failed)' });
260
+ }
261
+ SystemLogger.log(workspaceDir, 'PAIN_GATE_REJECTED', payload);
262
+ // PEAT-B2: Record trigger decision even when cooldown blocks manual pain
263
+ const painTriageFlag = loadPdConfigForPlugin(workspaceDir);
264
+ if (painTriageFlag.effective) {
265
+ SystemLogger.log(workspaceDir, 'TRIGGER_DECISION', JSON.stringify({
266
+ outcome: 'cooldown_skipped',
267
+ sourceKind: 'owner_reported',
268
+ reason: `Manual pain within cooldown: ${gate.detail}`,
269
+ nextAction: 'wait_for_cooldown_or_manual_retrigger',
270
+ isOwnerManual: true,
271
+ sessionId,
272
+ score: 100,
273
+ }));
274
+ }
275
+ return;
276
+ }
513
277
  emitPainDetectedEvent(wctx, {
514
278
  ts: new Date().toISOString(),
515
279
  type: 'pain_detected',
516
280
  data: {
517
281
  painId: createPainId(sessionId),
518
- painType: failureSource,
282
+ painType: 'user_frustration',
519
283
  source: event.toolName,
520
- reason: `Tool ${event.toolName} failed on ${relPath}; diagnosticGate=${diagnosticGate.reason}`,
521
- score: painScore,
284
+ reason: `User intervention: ${reason}`,
285
+ score: 100,
522
286
  sessionId,
523
287
  traceId,
524
288
  agentId: ctx.agentId,
525
- provenance: 'automatic_hook',
289
+ provenance: (sessionId && sessionId !== 'unknown') ? 'openclaw_context_bound' : 'owner_reported_no_host_trace',
526
290
  evidence: buildTrajectoryEvidence(wctx, sessionId),
527
291
  },
528
292
  });
529
293
  }
530
- function extractErrorType(error) {
531
- if (!error)
532
- return 'Unknown';
533
- const msg = String(error);
534
- if (msg.includes('EACCES') || msg.includes('permission denied'))
535
- return 'EACCES';
536
- if (msg.includes('ENOENT') || msg.includes('no such file'))
537
- return 'ENOENT';
538
- if (msg.includes('EISDIR'))
539
- return 'EISDIR';
540
- if (msg.includes('ENOSPC'))
541
- return 'ENOSPC';
542
- if (msg.includes('SyntaxError'))
543
- return 'SyntaxError';
544
- if (msg.includes('TypeError'))
545
- return 'TypeError';
546
- if (msg.includes('ReferenceError'))
547
- return 'ReferenceError';
548
- if (msg.includes('timeout') || msg.includes('ETIMEDOUT'))
549
- return 'Timeout';
550
- if (msg.includes('network') || msg.includes('ECONNREFUSED'))
551
- return 'Network';
552
- return 'Other';
553
- }