principles-disciple 1.8.1 → 1.8.3

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 (508) hide show
  1. package/ADVANCED_CONFIG_ZH.md +97 -0
  2. package/AGENT_INSTALL.md +173 -0
  3. package/AGENT_INSTALL_EN.md +173 -0
  4. package/INSTALL.md +256 -0
  5. package/SKILL.md +63 -0
  6. package/docs/COMMAND_REFERENCE.md +76 -0
  7. package/docs/COMMAND_REFERENCE_EN.md +79 -0
  8. package/esbuild.config.js +75 -0
  9. package/openclaw.plugin.json +4 -4
  10. package/package.json +11 -13
  11. package/scripts/build-web.mjs +46 -0
  12. package/scripts/install-dependencies.cjs +47 -0
  13. package/scripts/sync-plugin.mjs +802 -0
  14. package/scripts/verify-build.mjs +109 -0
  15. package/src/agents/nocturnal-dreamer.md +152 -0
  16. package/src/agents/nocturnal-philosopher.md +138 -0
  17. package/src/agents/nocturnal-reflector.md +126 -0
  18. package/src/agents/nocturnal-scribe.md +164 -0
  19. package/src/commands/capabilities.ts +85 -0
  20. package/{dist/commands/context.js → src/commands/context.ts} +78 -38
  21. package/src/commands/evolution-status.ts +146 -0
  22. package/src/commands/export.ts +111 -0
  23. package/src/commands/focus.ts +533 -0
  24. package/src/commands/nocturnal-review.ts +311 -0
  25. package/src/commands/nocturnal-rollout.ts +763 -0
  26. package/src/commands/nocturnal-train.ts +1002 -0
  27. package/{dist/commands/pain.js → src/commands/pain.ts} +68 -49
  28. package/src/commands/principle-rollback.ts +27 -0
  29. package/{dist/commands/rollback.js → src/commands/rollback.ts} +44 -12
  30. package/src/commands/samples.ts +60 -0
  31. package/src/commands/strategy.ts +38 -0
  32. package/{dist/commands/thinking-os.js → src/commands/thinking-os.ts} +59 -36
  33. package/src/commands/workflow-debug.ts +128 -0
  34. package/{dist/config/defaults/runtime.js → src/config/defaults/runtime.ts} +12 -5
  35. package/src/config/errors.ts +163 -0
  36. package/{dist/config/index.d.ts → src/config/index.ts} +2 -1
  37. package/src/constants/diagnostician.ts +66 -0
  38. package/src/constants/tools.ts +62 -0
  39. package/src/core/adaptive-thresholds.ts +476 -0
  40. package/{dist/core/config-service.js → src/core/config-service.ts} +7 -4
  41. package/{dist/core/config.js → src/core/config.ts} +158 -46
  42. package/src/core/control-ui-db.ts +435 -0
  43. package/{dist/core/detection-funnel.js → src/core/detection-funnel.ts} +36 -21
  44. package/{dist/core/detection-service.js → src/core/detection-service.ts} +7 -4
  45. package/{dist/core/dictionary-service.js → src/core/dictionary-service.ts} +7 -4
  46. package/{dist/core/dictionary.js → src/core/dictionary.ts} +57 -34
  47. package/src/core/empathy-keyword-matcher.ts +327 -0
  48. package/src/core/empathy-types.ts +218 -0
  49. package/src/core/event-log.ts +544 -0
  50. package/src/core/evolution-engine.ts +612 -0
  51. package/src/core/evolution-logger.ts +353 -0
  52. package/src/core/evolution-migration.ts +77 -0
  53. package/src/core/evolution-reducer.ts +731 -0
  54. package/src/core/evolution-types.ts +456 -0
  55. package/src/core/external-training-contract.ts +527 -0
  56. package/src/core/focus-history.ts +1458 -0
  57. package/src/core/hygiene/tracker.ts +117 -0
  58. package/{dist/core/init.js → src/core/init.ts} +39 -26
  59. package/src/core/local-worker-routing.ts +617 -0
  60. package/{dist/core/migration.js → src/core/migration.ts} +18 -11
  61. package/src/core/model-deployment-registry.ts +722 -0
  62. package/src/core/model-training-registry.ts +813 -0
  63. package/src/core/nocturnal-arbiter.ts +706 -0
  64. package/src/core/nocturnal-candidate-scoring.ts +392 -0
  65. package/src/core/nocturnal-compliance.ts +1075 -0
  66. package/src/core/nocturnal-dataset.ts +668 -0
  67. package/src/core/nocturnal-executability.ts +428 -0
  68. package/src/core/nocturnal-export.ts +390 -0
  69. package/{dist/core/nocturnal-paths.js → src/core/nocturnal-paths.ts} +49 -23
  70. package/src/core/nocturnal-trajectory-extractor.ts +484 -0
  71. package/src/core/nocturnal-trinity.ts +1384 -0
  72. package/src/core/pain.ts +122 -0
  73. package/{dist/core/path-resolver.js → src/core/path-resolver.ts} +157 -36
  74. package/{dist/core/paths.js → src/core/paths.ts} +13 -4
  75. package/src/core/principle-training-state.ts +450 -0
  76. package/src/core/profile.ts +226 -0
  77. package/src/core/promotion-gate.ts +822 -0
  78. package/{dist/core/risk-calculator.js → src/core/risk-calculator.ts} +42 -16
  79. package/{dist/core/session-tracker.js → src/core/session-tracker.ts} +175 -62
  80. package/src/core/shadow-observation-registry.ts +534 -0
  81. package/{dist/core/system-logger.js → src/core/system-logger.ts} +9 -5
  82. package/src/core/thinking-models.ts +217 -0
  83. package/src/core/training-program.ts +630 -0
  84. package/src/core/trajectory-types.ts +243 -0
  85. package/src/core/trajectory.ts +1673 -0
  86. package/{dist/core/workspace-context.js → src/core/workspace-context.ts} +57 -32
  87. package/src/hooks/bash-risk.ts +171 -0
  88. package/src/hooks/edit-verification.ts +295 -0
  89. package/src/hooks/gate-block-helper.ts +160 -0
  90. package/src/hooks/gate.ts +210 -0
  91. package/src/hooks/gfi-gate.ts +177 -0
  92. package/src/hooks/lifecycle.ts +326 -0
  93. package/{dist/hooks/llm.js → src/hooks/llm.ts} +160 -80
  94. package/src/hooks/message-sanitize.ts +45 -0
  95. package/src/hooks/pain.ts +384 -0
  96. package/src/hooks/progressive-trust-gate.ts +174 -0
  97. package/src/hooks/prompt.ts +920 -0
  98. package/src/hooks/subagent.ts +207 -0
  99. package/src/hooks/thinking-checkpoint.ts +73 -0
  100. package/src/hooks/trajectory-collector.ts +290 -0
  101. package/src/http/principles-console-route.ts +716 -0
  102. package/src/i18n/commands.ts +117 -0
  103. package/src/index.ts +694 -0
  104. package/src/service/central-database.ts +831 -0
  105. package/src/service/control-ui-query-service.ts +888 -0
  106. package/src/service/evolution-query-service.ts +405 -0
  107. package/src/service/evolution-worker.ts +1646 -0
  108. package/src/service/health-query-service.ts +836 -0
  109. package/{dist/service/nocturnal-runtime.js → src/service/nocturnal-runtime.ts} +235 -79
  110. package/src/service/nocturnal-service.ts +1015 -0
  111. package/src/service/nocturnal-target-selector.ts +532 -0
  112. package/src/service/phase3-input-filter.ts +237 -0
  113. package/src/service/runtime-summary-service.ts +757 -0
  114. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +513 -0
  115. package/{dist/service/subagent-workflow/empathy-observer-workflow-manager.js → src/service/subagent-workflow/empathy-observer-workflow-manager.ts} +240 -117
  116. package/src/service/subagent-workflow/index.ts +51 -0
  117. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +856 -0
  118. package/src/service/subagent-workflow/runtime-direct-driver.ts +166 -0
  119. package/{dist/service/subagent-workflow/types.d.ts → src/service/subagent-workflow/types.ts} +137 -18
  120. package/src/service/subagent-workflow/workflow-store.ts +328 -0
  121. package/src/service/trajectory-service.ts +15 -0
  122. package/{dist/tools/critique-prompt.js → src/tools/critique-prompt.ts} +25 -8
  123. package/src/tools/deep-reflect.ts +349 -0
  124. package/{dist/tools/model-index.js → src/tools/model-index.ts} +33 -17
  125. package/src/types/event-types.ts +453 -0
  126. package/src/types/hygiene-types.ts +31 -0
  127. package/src/types/principle-tree-schema.ts +244 -0
  128. package/src/types/runtime-summary.ts +49 -0
  129. package/src/types.ts +74 -0
  130. package/src/utils/file-lock.ts +391 -0
  131. package/{dist/utils/glob-match.js → src/utils/glob-match.ts} +21 -20
  132. package/{dist/utils/hashing.js → src/utils/hashing.ts} +6 -4
  133. package/src/utils/io.ts +110 -0
  134. package/{dist/utils/nlp.js → src/utils/nlp.ts} +19 -12
  135. package/{dist/utils/plugin-logger.js → src/utils/plugin-logger.ts} +33 -8
  136. package/src/utils/subagent-probe.ts +94 -0
  137. package/templates/langs/en/skills/ai-sprint-orchestration/EXAMPLES.md +63 -0
  138. package/templates/langs/en/skills/ai-sprint-orchestration/REFERENCE.md +136 -0
  139. package/templates/langs/en/skills/ai-sprint-orchestration/SKILL.md +67 -0
  140. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +214 -0
  141. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +107 -0
  142. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +107 -0
  143. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +105 -0
  144. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +108 -0
  145. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +58 -0
  146. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +190 -0
  147. package/templates/langs/en/skills/ai-sprint-orchestration/runtime/.gitignore +2 -0
  148. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +310 -0
  149. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +683 -0
  150. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +604 -0
  151. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +32 -0
  152. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +707 -0
  153. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +3419 -0
  154. package/templates/langs/zh/skills/ai-sprint-orchestration/EXAMPLES.md +63 -0
  155. package/templates/langs/zh/skills/ai-sprint-orchestration/REFERENCE.md +136 -0
  156. package/templates/langs/zh/skills/ai-sprint-orchestration/SKILL.md +67 -0
  157. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +214 -0
  158. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +107 -0
  159. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +107 -0
  160. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +105 -0
  161. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +108 -0
  162. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +58 -0
  163. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +190 -0
  164. package/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +2 -0
  165. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +310 -0
  166. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +683 -0
  167. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +604 -0
  168. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +32 -0
  169. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +707 -0
  170. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +3419 -0
  171. package/templates/langs/zh/skills/ai-sprint-orchestration/test/archive.test.mjs +230 -0
  172. package/templates/langs/zh/skills/ai-sprint-orchestration/test/contract-enforcement.test.mjs +672 -0
  173. package/templates/langs/zh/skills/ai-sprint-orchestration/test/decision.test.mjs +1321 -0
  174. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +1419 -0
  175. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +70 -1
  176. package/templates/pain_settings.json +2 -1
  177. package/tests/README.md +120 -0
  178. package/tests/build-artifacts.test.ts +111 -0
  179. package/tests/commands/evolution-status.test.ts +222 -0
  180. package/tests/commands/evolver.test.ts +22 -0
  181. package/tests/commands/export.test.ts +78 -0
  182. package/tests/commands/nocturnal-review.test.ts +448 -0
  183. package/tests/commands/nocturnal-train.test.ts +97 -0
  184. package/tests/commands/pain.test.ts +108 -0
  185. package/tests/commands/samples.test.ts +65 -0
  186. package/tests/commands/strategy.test.ts +34 -0
  187. package/tests/commands/thinking-os.test.ts +88 -0
  188. package/tests/core/adaptive-thresholds.test.ts +261 -0
  189. package/tests/core/config-service.test.ts +89 -0
  190. package/tests/core/config.test.ts +90 -0
  191. package/tests/core/control-ui-db.test.ts +75 -0
  192. package/tests/core/core-template-guidance.test.ts +21 -0
  193. package/tests/core/detection-funnel.test.ts +63 -0
  194. package/tests/core/detection-service.test.ts +50 -0
  195. package/tests/core/dictionary-service.test.ts +116 -0
  196. package/tests/core/dictionary.test.ts +168 -0
  197. package/tests/core/empathy-keyword-matcher.test.ts +209 -0
  198. package/tests/core/event-log.test.ts +181 -0
  199. package/tests/core/evolution-e2e.test.ts +58 -0
  200. package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
  201. package/tests/core/evolution-engine.test.ts +562 -0
  202. package/tests/core/evolution-logger.test.ts +148 -0
  203. package/tests/core/evolution-migration.test.ts +50 -0
  204. package/tests/core/evolution-paths.test.ts +21 -0
  205. package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
  206. package/tests/core/evolution-reducer.test.ts +180 -0
  207. package/tests/core/evolution-types-loop.test.ts +48 -0
  208. package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
  209. package/tests/core/external-training-contract.test.ts +463 -0
  210. package/tests/core/focus-history.test.ts +682 -0
  211. package/tests/core/init-flatten.test.ts +69 -0
  212. package/tests/core/init-refactor.test.ts +87 -0
  213. package/tests/core/init-v1.3.test.ts +46 -0
  214. package/tests/core/init.test.ts +190 -0
  215. package/tests/core/local-worker-routing.test.ts +757 -0
  216. package/tests/core/migration.test.ts +84 -0
  217. package/tests/core/model-deployment-registry.test.ts +845 -0
  218. package/tests/core/model-training-registry.test.ts +889 -0
  219. package/tests/core/nocturnal-arbiter.test.ts +494 -0
  220. package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
  221. package/tests/core/nocturnal-compliance.test.ts +646 -0
  222. package/tests/core/nocturnal-dataset.test.ts +892 -0
  223. package/tests/core/nocturnal-executability.test.ts +357 -0
  224. package/tests/core/nocturnal-export.test.ts +462 -0
  225. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
  226. package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
  227. package/tests/core/nocturnal-trinity.test.ts +953 -0
  228. package/tests/core/pain.test.ts +33 -0
  229. package/tests/core/path-resolver.test.ts +57 -0
  230. package/tests/core/paths-refactor.test.ts +42 -0
  231. package/tests/core/phase7-rollout-integration.test.ts +477 -0
  232. package/tests/core/principle-training-state.test.ts +712 -0
  233. package/tests/core/profile.test.ts +56 -0
  234. package/tests/core/promotion-gate.test.ts +556 -0
  235. package/tests/core/risk-calculator.test.ts +168 -0
  236. package/tests/core/session-tracker.test.ts +191 -0
  237. package/tests/core/training-program.test.ts +472 -0
  238. package/tests/core/trajectory.test.ts +265 -0
  239. package/tests/core/workspace-context-factory.test.ts +18 -0
  240. package/tests/core/workspace-context.test.ts +134 -0
  241. package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
  242. package/tests/fixtures/production-compatibility.test.ts +147 -0
  243. package/tests/fixtures/production-mock-generator.ts +282 -0
  244. package/tests/hooks/bash-risk-integration.test.ts +137 -0
  245. package/tests/hooks/bash-risk.test.ts +81 -0
  246. package/tests/hooks/edit-verification.test.ts +678 -0
  247. package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
  248. package/tests/hooks/gate-edit-verification.test.ts +435 -0
  249. package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
  250. package/tests/hooks/gate.test.ts +271 -0
  251. package/tests/hooks/gfi-gate-unit.test.ts +422 -0
  252. package/tests/hooks/gfi-gate.test.ts +669 -0
  253. package/tests/hooks/lifecycle.test.ts +248 -0
  254. package/tests/hooks/llm.test.ts +308 -0
  255. package/tests/hooks/message-sanitize.test.ts +36 -0
  256. package/tests/hooks/pain.test.ts +141 -0
  257. package/tests/hooks/progressive-trust-gate.test.ts +277 -0
  258. package/tests/hooks/prompt.test.ts +1411 -0
  259. package/tests/hooks/subagent.test.ts +467 -0
  260. package/tests/hooks/thinking-gate.test.ts +313 -0
  261. package/tests/http/principles-console-route.test.ts +140 -0
  262. package/tests/hygiene-tracker.test.ts +77 -0
  263. package/tests/index.integration.test.ts +179 -0
  264. package/tests/index.shadow-routing.integration.test.ts +140 -0
  265. package/tests/index.test.ts +9 -0
  266. package/tests/integration/empathy-workflow-integration.test.ts +627 -0
  267. package/tests/service/control-ui-query-service.test.ts +121 -0
  268. package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
  269. package/tests/service/evolution-worker.test.ts +585 -0
  270. package/tests/service/nocturnal-runtime.test.ts +470 -0
  271. package/tests/service/nocturnal-service.test.ts +577 -0
  272. package/tests/service/nocturnal-target-selector.test.ts +615 -0
  273. package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
  274. package/tests/service/phase3-input-filter.test.ts +289 -0
  275. package/tests/service/runtime-summary-service.test.ts +919 -0
  276. package/tests/task-compliance.test.ts +166 -0
  277. package/tests/test-utils.ts +48 -0
  278. package/tests/tools/critique-prompt.test.ts +260 -0
  279. package/tests/tools/deep-reflect.test.ts +232 -0
  280. package/tests/tools/model-index.test.ts +246 -0
  281. package/tests/ui/app.test.tsx +114 -0
  282. package/tests/utils/file-lock.test.ts +407 -0
  283. package/tests/utils/hashing.test.ts +32 -0
  284. package/tests/utils/io.test.ts +39 -0
  285. package/tests/utils/nlp.test.ts +53 -0
  286. package/tests/utils/plugin-logger.test.ts +156 -0
  287. package/tsconfig.json +16 -0
  288. package/tsconfig.tsbuildinfo +1 -0
  289. package/ui/src/App.tsx +45 -0
  290. package/ui/src/api.ts +216 -0
  291. package/ui/src/charts.tsx +586 -0
  292. package/ui/src/components/ErrorState.tsx +6 -0
  293. package/ui/src/components/Loading.tsx +13 -0
  294. package/ui/src/components/ProtectedRoute.tsx +12 -0
  295. package/ui/src/components/Shell.tsx +91 -0
  296. package/ui/src/components/WorkspaceConfig.tsx +146 -0
  297. package/ui/src/components/index.ts +5 -0
  298. package/ui/src/context/auth.tsx +80 -0
  299. package/ui/src/context/theme.tsx +66 -0
  300. package/ui/src/hooks/useAutoRefresh.ts +39 -0
  301. package/ui/src/i18n/ui.ts +363 -0
  302. package/ui/src/main.tsx +16 -0
  303. package/ui/src/pages/EvolutionPage.tsx +352 -0
  304. package/ui/src/pages/FeedbackPage.tsx +140 -0
  305. package/ui/src/pages/GateMonitorPage.tsx +136 -0
  306. package/ui/src/pages/LoginPage.tsx +88 -0
  307. package/ui/src/pages/OverviewPage.tsx +238 -0
  308. package/ui/src/pages/SamplesPage.tsx +174 -0
  309. package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
  310. package/ui/src/styles.css +1661 -0
  311. package/ui/src/types.ts +368 -0
  312. package/ui/src/utils/format.ts +15 -0
  313. package/vitest.config.ts +23 -0
  314. package/dist/commands/capabilities.d.ts +0 -3
  315. package/dist/commands/capabilities.js +0 -73
  316. package/dist/commands/context.d.ts +0 -5
  317. package/dist/commands/evolution-status.d.ts +0 -4
  318. package/dist/commands/evolution-status.js +0 -117
  319. package/dist/commands/evolver.d.ts +0 -9
  320. package/dist/commands/evolver.js +0 -26
  321. package/dist/commands/export.d.ts +0 -2
  322. package/dist/commands/export.js +0 -98
  323. package/dist/commands/focus.d.ts +0 -14
  324. package/dist/commands/focus.js +0 -457
  325. package/dist/commands/nocturnal-review.d.ts +0 -24
  326. package/dist/commands/nocturnal-review.js +0 -265
  327. package/dist/commands/nocturnal-rollout.d.ts +0 -27
  328. package/dist/commands/nocturnal-rollout.js +0 -671
  329. package/dist/commands/nocturnal-train.d.ts +0 -25
  330. package/dist/commands/nocturnal-train.js +0 -919
  331. package/dist/commands/pain.d.ts +0 -5
  332. package/dist/commands/principle-rollback.d.ts +0 -4
  333. package/dist/commands/principle-rollback.js +0 -22
  334. package/dist/commands/rollback.d.ts +0 -19
  335. package/dist/commands/samples.d.ts +0 -2
  336. package/dist/commands/samples.js +0 -55
  337. package/dist/commands/strategy.d.ts +0 -3
  338. package/dist/commands/strategy.js +0 -29
  339. package/dist/commands/thinking-os.d.ts +0 -2
  340. package/dist/config/defaults/runtime.d.ts +0 -40
  341. package/dist/config/errors.d.ts +0 -84
  342. package/dist/config/errors.js +0 -94
  343. package/dist/config/index.js +0 -7
  344. package/dist/constants/diagnostician.d.ts +0 -12
  345. package/dist/constants/diagnostician.js +0 -56
  346. package/dist/constants/tools.d.ts +0 -17
  347. package/dist/constants/tools.js +0 -54
  348. package/dist/core/adaptive-thresholds.d.ts +0 -186
  349. package/dist/core/adaptive-thresholds.js +0 -300
  350. package/dist/core/config-service.d.ts +0 -15
  351. package/dist/core/config.d.ts +0 -129
  352. package/dist/core/control-ui-db.d.ts +0 -95
  353. package/dist/core/control-ui-db.js +0 -292
  354. package/dist/core/detection-funnel.d.ts +0 -33
  355. package/dist/core/detection-service.d.ts +0 -15
  356. package/dist/core/dictionary-service.d.ts +0 -15
  357. package/dist/core/dictionary.d.ts +0 -38
  358. package/dist/core/event-log.d.ts +0 -82
  359. package/dist/core/event-log.js +0 -463
  360. package/dist/core/evolution-engine.d.ts +0 -118
  361. package/dist/core/evolution-engine.js +0 -464
  362. package/dist/core/evolution-logger.d.ts +0 -137
  363. package/dist/core/evolution-logger.js +0 -256
  364. package/dist/core/evolution-migration.d.ts +0 -5
  365. package/dist/core/evolution-migration.js +0 -65
  366. package/dist/core/evolution-reducer.d.ts +0 -98
  367. package/dist/core/evolution-reducer.js +0 -465
  368. package/dist/core/evolution-types.d.ts +0 -287
  369. package/dist/core/evolution-types.js +0 -78
  370. package/dist/core/external-training-contract.d.ts +0 -276
  371. package/dist/core/external-training-contract.js +0 -269
  372. package/dist/core/focus-history.d.ts +0 -210
  373. package/dist/core/focus-history.js +0 -1185
  374. package/dist/core/hygiene/tracker.d.ts +0 -22
  375. package/dist/core/hygiene/tracker.js +0 -106
  376. package/dist/core/init.d.ts +0 -12
  377. package/dist/core/local-worker-routing.d.ts +0 -175
  378. package/dist/core/local-worker-routing.js +0 -525
  379. package/dist/core/migration.d.ts +0 -6
  380. package/dist/core/model-deployment-registry.d.ts +0 -218
  381. package/dist/core/model-deployment-registry.js +0 -503
  382. package/dist/core/model-training-registry.d.ts +0 -295
  383. package/dist/core/model-training-registry.js +0 -475
  384. package/dist/core/nocturnal-arbiter.d.ts +0 -159
  385. package/dist/core/nocturnal-arbiter.js +0 -534
  386. package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
  387. package/dist/core/nocturnal-candidate-scoring.js +0 -266
  388. package/dist/core/nocturnal-compliance.d.ts +0 -175
  389. package/dist/core/nocturnal-compliance.js +0 -824
  390. package/dist/core/nocturnal-dataset.d.ts +0 -224
  391. package/dist/core/nocturnal-dataset.js +0 -443
  392. package/dist/core/nocturnal-executability.d.ts +0 -85
  393. package/dist/core/nocturnal-executability.js +0 -331
  394. package/dist/core/nocturnal-export.d.ts +0 -124
  395. package/dist/core/nocturnal-export.js +0 -275
  396. package/dist/core/nocturnal-paths.d.ts +0 -124
  397. package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
  398. package/dist/core/nocturnal-trajectory-extractor.js +0 -307
  399. package/dist/core/nocturnal-trinity.d.ts +0 -311
  400. package/dist/core/nocturnal-trinity.js +0 -880
  401. package/dist/core/pain.d.ts +0 -4
  402. package/dist/core/pain.js +0 -70
  403. package/dist/core/path-resolver.d.ts +0 -46
  404. package/dist/core/paths.d.ts +0 -65
  405. package/dist/core/principle-training-state.d.ts +0 -121
  406. package/dist/core/principle-training-state.js +0 -321
  407. package/dist/core/profile.d.ts +0 -62
  408. package/dist/core/profile.js +0 -210
  409. package/dist/core/promotion-gate.d.ts +0 -238
  410. package/dist/core/promotion-gate.js +0 -529
  411. package/dist/core/risk-calculator.d.ts +0 -22
  412. package/dist/core/session-tracker.d.ts +0 -101
  413. package/dist/core/shadow-observation-registry.d.ts +0 -217
  414. package/dist/core/shadow-observation-registry.js +0 -308
  415. package/dist/core/system-logger.d.ts +0 -8
  416. package/dist/core/thinking-models.d.ts +0 -38
  417. package/dist/core/thinking-models.js +0 -170
  418. package/dist/core/training-program.d.ts +0 -233
  419. package/dist/core/training-program.js +0 -433
  420. package/dist/core/trajectory.d.ts +0 -411
  421. package/dist/core/trajectory.js +0 -1307
  422. package/dist/core/workspace-context.d.ts +0 -71
  423. package/dist/hooks/bash-risk.d.ts +0 -57
  424. package/dist/hooks/bash-risk.js +0 -137
  425. package/dist/hooks/edit-verification.d.ts +0 -62
  426. package/dist/hooks/edit-verification.js +0 -256
  427. package/dist/hooks/gate-block-helper.d.ts +0 -44
  428. package/dist/hooks/gate-block-helper.js +0 -119
  429. package/dist/hooks/gate.d.ts +0 -24
  430. package/dist/hooks/gate.js +0 -173
  431. package/dist/hooks/gfi-gate.d.ts +0 -40
  432. package/dist/hooks/gfi-gate.js +0 -113
  433. package/dist/hooks/lifecycle.d.ts +0 -5
  434. package/dist/hooks/lifecycle.js +0 -284
  435. package/dist/hooks/llm.d.ts +0 -13
  436. package/dist/hooks/message-sanitize.d.ts +0 -3
  437. package/dist/hooks/message-sanitize.js +0 -37
  438. package/dist/hooks/pain.d.ts +0 -5
  439. package/dist/hooks/pain.js +0 -301
  440. package/dist/hooks/progressive-trust-gate.d.ts +0 -52
  441. package/dist/hooks/progressive-trust-gate.js +0 -134
  442. package/dist/hooks/prompt.d.ts +0 -49
  443. package/dist/hooks/prompt.js +0 -905
  444. package/dist/hooks/subagent.d.ts +0 -10
  445. package/dist/hooks/subagent.js +0 -387
  446. package/dist/hooks/thinking-checkpoint.d.ts +0 -37
  447. package/dist/hooks/thinking-checkpoint.js +0 -51
  448. package/dist/hooks/trajectory-collector.d.ts +0 -32
  449. package/dist/hooks/trajectory-collector.js +0 -256
  450. package/dist/http/principles-console-route.d.ts +0 -9
  451. package/dist/http/principles-console-route.js +0 -681
  452. package/dist/i18n/commands.d.ts +0 -26
  453. package/dist/i18n/commands.js +0 -116
  454. package/dist/index.d.ts +0 -7
  455. package/dist/index.js +0 -581
  456. package/dist/service/central-database.d.ts +0 -104
  457. package/dist/service/central-database.js +0 -649
  458. package/dist/service/control-ui-query-service.d.ts +0 -221
  459. package/dist/service/control-ui-query-service.js +0 -543
  460. package/dist/service/empathy-observer-manager.d.ts +0 -88
  461. package/dist/service/empathy-observer-manager.js +0 -414
  462. package/dist/service/evolution-query-service.d.ts +0 -155
  463. package/dist/service/evolution-query-service.js +0 -258
  464. package/dist/service/evolution-worker.d.ts +0 -101
  465. package/dist/service/evolution-worker.js +0 -975
  466. package/dist/service/health-query-service.d.ts +0 -170
  467. package/dist/service/health-query-service.js +0 -662
  468. package/dist/service/nocturnal-runtime.d.ts +0 -183
  469. package/dist/service/nocturnal-service.d.ts +0 -163
  470. package/dist/service/nocturnal-service.js +0 -787
  471. package/dist/service/nocturnal-target-selector.d.ts +0 -145
  472. package/dist/service/nocturnal-target-selector.js +0 -315
  473. package/dist/service/phase3-input-filter.d.ts +0 -73
  474. package/dist/service/phase3-input-filter.js +0 -172
  475. package/dist/service/runtime-summary-service.d.ts +0 -122
  476. package/dist/service/runtime-summary-service.js +0 -485
  477. package/dist/service/subagent-workflow/empathy-observer-workflow-manager.d.ts +0 -48
  478. package/dist/service/subagent-workflow/index.d.ts +0 -4
  479. package/dist/service/subagent-workflow/index.js +0 -3
  480. package/dist/service/subagent-workflow/runtime-direct-driver.d.ts +0 -77
  481. package/dist/service/subagent-workflow/runtime-direct-driver.js +0 -75
  482. package/dist/service/subagent-workflow/types.js +0 -11
  483. package/dist/service/subagent-workflow/workflow-store.d.ts +0 -26
  484. package/dist/service/subagent-workflow/workflow-store.js +0 -165
  485. package/dist/service/trajectory-service.d.ts +0 -2
  486. package/dist/service/trajectory-service.js +0 -15
  487. package/dist/tools/critique-prompt.d.ts +0 -14
  488. package/dist/tools/deep-reflect.d.ts +0 -39
  489. package/dist/tools/deep-reflect.js +0 -350
  490. package/dist/tools/model-index.d.ts +0 -9
  491. package/dist/types/event-types.d.ts +0 -306
  492. package/dist/types/event-types.js +0 -106
  493. package/dist/types/hygiene-types.d.ts +0 -20
  494. package/dist/types/hygiene-types.js +0 -12
  495. package/dist/types/runtime-summary.d.ts +0 -47
  496. package/dist/types/runtime-summary.js +0 -1
  497. package/dist/types.d.ts +0 -50
  498. package/dist/types.js +0 -22
  499. package/dist/utils/file-lock.d.ts +0 -71
  500. package/dist/utils/file-lock.js +0 -309
  501. package/dist/utils/glob-match.d.ts +0 -28
  502. package/dist/utils/hashing.d.ts +0 -9
  503. package/dist/utils/io.d.ts +0 -6
  504. package/dist/utils/io.js +0 -106
  505. package/dist/utils/nlp.d.ts +0 -9
  506. package/dist/utils/plugin-logger.d.ts +0 -39
  507. package/dist/utils/subagent-probe.d.ts +0 -34
  508. package/dist/utils/subagent-probe.js +0 -81
@@ -1,44 +1,64 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
- import { trackLlmOutput, recordThinkingCheckpoint, resetFriction } from '../core/session-tracker.js';
3
+ import { PluginHookLlmOutputEvent, PluginHookAgentContext } from '../openclaw-sdk.js';
4
+ import { trackFriction, trackLlmOutput, recordThinkingCheckpoint, resetFriction } from '../core/session-tracker.js';
4
5
  import { writePainFlag } from '../core/pain.js';
5
6
  import { ControlUiDatabase } from '../core/control-ui-db.js';
6
7
  import { DetectionService } from '../core/detection-service.js';
7
8
  import { detectThinkingModelMatches, deriveThinkingScenarios } from '../core/thinking-models.js';
8
9
  import { WorkspaceContext } from '../core/workspace-context.js';
9
10
  import { sanitizeAssistantText } from './message-sanitize.js';
10
- const empathyDedupState = new Map();
11
- const empathyRateState = new Map();
12
- function clamp(value, min, max) {
11
+
12
+ export interface EmpathySignal {
13
+ detected: boolean;
14
+ severity: 'mild' | 'moderate' | 'severe';
15
+ confidence: number;
16
+ reason?: string;
17
+ mode?: 'structured' | 'legacy_tag';
18
+ }
19
+
20
+ type EmpathyRateState = {
21
+ turnScore: number;
22
+ hourScore: number;
23
+ hourWindowStart: number;
24
+ lastRunId?: string;
25
+ };
26
+
27
+ const empathyDedupState = new Map<string, number>();
28
+ const empathyRateState = new Map<string, EmpathyRateState>();
29
+
30
+ function clamp(value: number, min: number, max: number): number {
13
31
  return Math.max(min, Math.min(max, value));
14
32
  }
15
- function normalizeSeverity(input) {
33
+
34
+ function normalizeSeverity(input?: string): 'mild' | 'moderate' | 'severe' {
16
35
  const normalized = (input || '').toLowerCase();
17
- if (normalized === 'severe' || normalized === 'high')
18
- return 'severe';
19
- if (normalized === 'moderate' || normalized === 'medium')
20
- return 'moderate';
36
+ if (normalized === 'severe' || normalized === 'high') return 'severe';
37
+ if (normalized === 'moderate' || normalized === 'medium') return 'moderate';
21
38
  return 'mild';
22
39
  }
23
- function parseConfidence(raw) {
40
+
41
+ function parseConfidence(raw?: string): number {
24
42
  const parsed = Number(raw);
25
- if (!Number.isFinite(parsed))
26
- return 1;
43
+ if (!Number.isFinite(parsed)) return 1;
27
44
  return clamp(parsed, 0, 1);
28
45
  }
29
- function parseTrustedLegacyTag(text) {
46
+
47
+ function parseTrustedLegacyTag(text: string): RegExpMatchArray | null {
30
48
  return text.match(/^\s*\[EMOTIONAL_DAMAGE_DETECTED(?::(mild|moderate|severe))?\]\s*$/i);
31
49
  }
50
+
32
51
  /**
33
52
  * 检测标签是否是被用户诱导/引用输出的(回显),而非 LLM 主动输出的情绪信号
34
53
  */
35
- function isEchoedTag(text, tagMatch) {
54
+ function isEchoedTag(text: string, tagMatch: RegExpMatchArray): boolean {
36
55
  const tagIndex = tagMatch.index ?? 0;
37
56
  const before = text.substring(Math.max(0, tagIndex - 100), tagIndex).toLowerCase();
57
+
38
58
  // 1. 检查是否在引号内(用户引用)
39
59
  const quotesBefore = (before.match(/["'\u300c\u300d\u201c\u201d`]/g) || []).length;
40
- if (quotesBefore % 2 === 1)
41
- return true;
60
+ if (quotesBefore % 2 === 1) return true;
61
+
42
62
  // 2. Strong patterns: 用户指令关键词(任意位置匹配)
43
63
  const strongPatterns = [
44
64
  /用户(说|让|要求|让我输出)/,
@@ -48,9 +68,9 @@ function isEchoedTag(text, tagMatch) {
48
68
  /你让我输出/,
49
69
  ];
50
70
  for (const pattern of strongPatterns) {
51
- if (pattern.test(before))
52
- return true;
71
+ if (pattern.test(before)) return true;
53
72
  }
73
+
54
74
  // 3. Weak patterns: 仅在标签 15 字符内触发
55
75
  const weakPatterns = [
56
76
  { pattern: /echo/, window: 15 },
@@ -59,19 +79,21 @@ function isEchoedTag(text, tagMatch) {
59
79
  ];
60
80
  for (const { pattern, window } of weakPatterns) {
61
81
  const nearTag = text.substring(Math.max(0, tagIndex - window), tagIndex).toLowerCase();
62
- if (pattern.test(nearTag))
63
- return true;
82
+ if (pattern.test(nearTag)) return true;
64
83
  }
84
+
65
85
  // 4. 检查是否在代码块内
66
86
  const codeBlocksBefore = (before.match(/```/g) || []).length;
67
- if (codeBlocksBefore % 2 === 1)
68
- return true;
87
+ if (codeBlocksBefore % 2 === 1) return true;
88
+
69
89
  return false;
70
90
  }
71
- export function extractEmpathySignal(text) {
91
+
92
+ export function extractEmpathySignal(text: string): EmpathySignal {
72
93
  if (!text || typeof text !== 'string') {
73
94
  return { detected: false, severity: 'mild', confidence: 1 };
74
95
  }
96
+
75
97
  const xmlMatch = text.match(/<empathy\s+([^>]*)\/?>(?:<\/empathy>)?/i);
76
98
  if (xmlMatch?.[1]) {
77
99
  const attrs = xmlMatch[1];
@@ -83,11 +105,14 @@ export function extractEmpathySignal(text) {
83
105
  return { detected: true, severity, confidence, reason, mode: 'structured' };
84
106
  }
85
107
  }
108
+
86
109
  const jsonMatch = text.match(/"empathy"\s*:\s*\{[\s\S]*?\}/i);
87
110
  if (jsonMatch) {
88
111
  const jsonText = `{${jsonMatch[0]}}`;
89
112
  try {
90
- const parsed = JSON.parse(jsonText);
113
+ const parsed = JSON.parse(jsonText) as {
114
+ empathy?: { damageDetected?: boolean; severity?: string; confidence?: number; reason?: string };
115
+ };
91
116
  if (parsed.empathy?.damageDetected === true) {
92
117
  return {
93
118
  detected: true,
@@ -97,11 +122,11 @@ export function extractEmpathySignal(text) {
97
122
  mode: 'structured'
98
123
  };
99
124
  }
100
- }
101
- catch {
125
+ } catch {
102
126
  // ignore malformed snippet
103
127
  }
104
128
  }
129
+
105
130
  const tagMatch = parseTrustedLegacyTag(text);
106
131
  if (tagMatch) {
107
132
  if (isEchoedTag(text, tagMatch)) {
@@ -114,22 +139,25 @@ export function extractEmpathySignal(text) {
114
139
  mode: 'legacy_tag'
115
140
  };
116
141
  }
142
+
117
143
  return { detected: false, severity: 'mild', confidence: 1 };
118
144
  }
119
- function mapSeverityToPenalty(severity, config) {
145
+
146
+ function mapSeverityToPenalty(severity: 'mild' | 'moderate' | 'severe', config: ReturnType<typeof WorkspaceContext.fromHookContext>['config']): number {
120
147
  const mild = Number(config.get('empathy_engine.penalties.mild') ?? 10);
121
148
  const moderate = Number(config.get('empathy_engine.penalties.moderate') ?? 25);
122
149
  const severe = Number(config.get('empathy_engine.penalties.severe') ?? 40);
123
- if (severity === 'severe')
124
- return severe;
125
- if (severity === 'moderate')
126
- return moderate;
150
+
151
+ if (severity === 'severe') return severe;
152
+ if (severity === 'moderate') return moderate;
127
153
  return mild;
128
154
  }
129
- function dedupeKey(sessionId, runId, signal) {
155
+
156
+ function dedupeKey(sessionId: string, runId: string, signal: EmpathySignal): string {
130
157
  return `${sessionId}:${runId}:${signal.severity}:${(signal.reason || '').slice(0, 80)}`;
131
158
  }
132
- function shouldDedupe(sessionId, runId, signal, windowMs) {
159
+
160
+ function shouldDedupe(sessionId: string, runId: string, signal: EmpathySignal, windowMs: number): boolean {
133
161
  const key = dedupeKey(sessionId, runId, signal);
134
162
  const now = Date.now();
135
163
  const last = empathyDedupState.get(key);
@@ -139,69 +167,88 @@ function shouldDedupe(sessionId, runId, signal, windowMs) {
139
167
  empathyDedupState.set(key, now);
140
168
  return false;
141
169
  }
142
- function resolveCalibrationFactor(event, config) {
143
- const table = config.get('empathy_engine.model_calibration');
144
- if (!table || typeof table !== 'object')
145
- return 1;
170
+
171
+ function resolveCalibrationFactor(
172
+ event: PluginHookLlmOutputEvent,
173
+ config: ReturnType<typeof WorkspaceContext.fromHookContext>['config']
174
+ ): number {
175
+ const table = config.get('empathy_engine.model_calibration') as Record<string, number> | undefined;
176
+ if (!table || typeof table !== 'object') return 1;
177
+
146
178
  const modelKey = `${event.provider}/${event.model}`;
147
179
  const factor = Number(table[modelKey] ?? 1);
148
- if (!Number.isFinite(factor))
149
- return 1;
180
+ if (!Number.isFinite(factor)) return 1;
150
181
  return clamp(factor, 0.1, 3);
151
182
  }
152
- function applyRateLimit(sessionId, runId, score, config) {
183
+
184
+ function applyRateLimit(
185
+ sessionId: string,
186
+ runId: string,
187
+ score: number,
188
+ config: ReturnType<typeof WorkspaceContext.fromHookContext>['config']
189
+ ): number {
153
190
  const maxPerTurn = Number(config.get('empathy_engine.rate_limit.max_per_turn') ?? 40);
154
191
  const maxPerHour = Number(config.get('empathy_engine.rate_limit.max_per_hour') ?? 120);
155
192
  const now = Date.now();
193
+
156
194
  const prev = empathyRateState.get(sessionId) ?? {
157
195
  turnScore: 0,
158
196
  hourScore: 0,
159
197
  hourWindowStart: now,
160
198
  lastRunId: runId,
161
199
  };
200
+
162
201
  if (prev.lastRunId !== runId) {
163
202
  prev.turnScore = 0;
164
203
  prev.lastRunId = runId;
165
204
  }
205
+
166
206
  if (now - prev.hourWindowStart >= 60 * 60 * 1000) {
167
207
  prev.hourScore = 0;
168
208
  prev.hourWindowStart = now;
169
209
  }
210
+
170
211
  const byTurn = Math.max(0, maxPerTurn - prev.turnScore);
171
212
  const byHour = Math.max(0, maxPerHour - prev.hourScore);
172
213
  const allowed = Math.max(0, Math.min(score, byTurn, byHour));
214
+
173
215
  prev.turnScore += allowed;
174
216
  prev.hourScore += allowed;
175
217
  empathyRateState.set(sessionId, prev);
218
+
176
219
  return allowed;
177
220
  }
178
- export function isEmpathyAuditPayload(text) {
179
- if (!text || typeof text !== 'string')
180
- return false;
221
+
222
+
223
+ export function isEmpathyAuditPayload(text: string): boolean {
224
+ if (!text || typeof text !== 'string') return false;
181
225
  const trimmed = text.trim();
182
- if (/^\{[\s\S]*"damageDetected"[\s\S]*\}$/.test(trimmed))
183
- return true;
184
- if (/^<empathy\s+([^>]*)\/?>/i.test(trimmed))
185
- return true;
186
- if (/^\s*\[EMOTIONAL_DAMAGE_DETECTED(?::(mild|moderate|severe))?\]\s*$/i.test(trimmed))
187
- return true;
226
+ if (/^\{[\s\S]*"damageDetected"[\s\S]*\}$/.test(trimmed)) return true;
227
+ if (/^<empathy\s+([^>]*)\/?>/i.test(trimmed)) return true;
228
+ if (/^\s*\[EMOTIONAL_DAMAGE_DETECTED(?::(mild|moderate|severe))?\]\s*$/i.test(trimmed)) return true;
188
229
  return false;
189
230
  }
190
- export function handleLlmOutput(event, ctx) {
191
- if (!ctx.workspaceDir || !ctx.sessionId)
192
- return;
231
+
232
+ export function handleLlmOutput(
233
+ event: PluginHookLlmOutputEvent,
234
+ ctx: PluginHookAgentContext & { workspaceDir?: string }
235
+ ): void {
236
+ if (!ctx.workspaceDir || !ctx.sessionId) return;
237
+
193
238
  const wctx = WorkspaceContext.fromHookContext(ctx);
194
239
  const config = wctx.config;
195
240
  const eventLog = wctx.eventLog;
241
+
196
242
  // Track this turn in the core session memory
197
243
  const state = trackLlmOutput(ctx.sessionId, event.usage, config, ctx.workspaceDir, ctx.sessionKey, ctx.trigger);
244
+
198
245
  // We need actual assistant text to analyze
199
- if (!event.assistantTexts || event.assistantTexts.length === 0)
200
- return;
246
+ if (!event.assistantTexts || event.assistantTexts.length === 0) return;
247
+
201
248
  const text = event.assistantTexts.join('\n');
202
249
  const signal = extractEmpathySignal(text);
203
250
  const createdAt = new Date().toISOString();
204
- let assistantTurnId = null;
251
+ let assistantTurnId: number | null = null;
205
252
  try {
206
253
  assistantTurnId = wctx.trajectory?.recordAssistantTurn?.({
207
254
  sessionId: ctx.sessionId,
@@ -214,14 +261,15 @@ export function handleLlmOutput(event, ctx) {
214
261
  empathySignalJson: signal,
215
262
  createdAt,
216
263
  });
217
- }
218
- catch (error) {
264
+ } catch (error) {
219
265
  ctx.logger?.warn?.(`[PD:LLM] Failed to persist assistant turn to trajectory: ${String(error)}`);
220
266
  }
267
+
221
268
  // ── Track B: Semantic Pain Detection (V1.3.0 Funnel) ──
222
269
  const detectionText = isEmpathyAuditPayload(text) ? '' : text;
223
270
  const detectionService = DetectionService.get(wctx.stateDir);
224
271
  const detection = detectionService.detect(detectionText);
272
+
225
273
  if (detection.detected) {
226
274
  eventLog.recordRuleMatch(ctx.sessionId, {
227
275
  ruleId: detection.ruleId || detection.source,
@@ -230,6 +278,7 @@ export function handleLlmOutput(event, ctx) {
230
278
  textPreview: detectionText.substring(0, 100)
231
279
  });
232
280
  }
281
+
233
282
  let painScore = detection.detected ? (detection.severity || 0) : 0;
234
283
  let source = detection.detected
235
284
  ? (detection.ruleId ? `llm_${detection.ruleId.toLowerCase()}` : `llm_${detection.source}`)
@@ -237,12 +286,18 @@ export function handleLlmOutput(event, ctx) {
237
286
  let matchedReason = detection.detected
238
287
  ? `Agent triggered pain detection (Source: ${detection.source}${detection.ruleId ? `, Rule: ${detection.ruleId}` : ''})`
239
288
  : '';
289
+
240
290
  // ═══ Natural Language Rollback Detection ═══
241
291
  const rollbackMatch = text.match(/^\s*\[EMPATHY_ROLLBACK_REQUEST\]\s*$/m);
242
292
  if (rollbackMatch) {
243
293
  const eventId = eventLog.getLastEmpathyEventId(ctx.sessionId);
244
294
  if (eventId) {
245
- const rolledBackScore = eventLog.rollbackEmpathyEvent(eventId, ctx.sessionId, 'Natural language rollback request detected', 'natural_language');
295
+ const rolledBackScore = eventLog.rollbackEmpathyEvent(
296
+ eventId,
297
+ ctx.sessionId,
298
+ 'Natural language rollback request detected',
299
+ 'natural_language'
300
+ );
246
301
  if (rolledBackScore > 0) {
247
302
  // Reset GFI after successful rollback
248
303
  resetFriction(ctx.sessionId, ctx.workspaceDir, {
@@ -252,28 +307,37 @@ export function handleLlmOutput(event, ctx) {
252
307
  }
253
308
  }
254
309
  }
310
+
255
311
  // 3. Paralysis Check (from session state tracker)
256
312
  const stuckThreshold = config.get('thresholds.stuck_loops_trigger') || 3;
257
313
  const inputThreshold = config.get('thresholds.cognitive_paralysis_input') || 4000;
258
314
  const paralysisScore = config.get('scores.paralysis') || 40;
315
+
259
316
  if (state.stuckLoops >= stuckThreshold && state.totalInputTokens > inputThreshold && painScore < paralysisScore) {
260
317
  painScore = paralysisScore;
261
318
  source = 'llm_paralysis';
262
319
  matchedReason = `Agent is stuck in low-output loops (${state.stuckLoops} consecutive turns with tiny output but huge context), indicating cognitive paralysis.`;
263
320
  }
321
+
264
322
  // If a pain threshold is crossed, write the autonomous pain flag
265
323
  const painTriggerThreshold = config.get('thresholds.pain_trigger') || 30;
266
324
  if (painScore >= painTriggerThreshold) {
267
325
  // Inject the actual text snippet that triggered this for the diagnostician to read later
268
326
  const snippet = text.length > 200 ? text.substring(0, 100) + '...' + text.substring(text.length - 100) : text;
269
- writePainFlag(ctx.workspaceDir, {
270
- source,
271
- score: String(painScore),
272
- time: new Date().toISOString(),
273
- reason: matchedReason,
274
- is_risky: 'false',
275
- trigger_text_preview: snippet
276
- });
327
+
328
+ try {
329
+ writePainFlag(ctx.workspaceDir, {
330
+ source,
331
+ score: String(painScore),
332
+ time: new Date().toISOString(),
333
+ reason: matchedReason,
334
+ is_risky: 'false',
335
+ trigger_text_preview: snippet
336
+ });
337
+ } catch (e) {
338
+ ctx.logger?.warn?.(`[PD:LLM] Failed to write pain flag: ${String(e)}`);
339
+ }
340
+
277
341
  eventLog.recordPainSignal(ctx.sessionId, {
278
342
  score: painScore,
279
343
  source: source,
@@ -281,6 +345,7 @@ export function handleLlmOutput(event, ctx) {
281
345
  isRisky: false
282
346
  });
283
347
  }
348
+
284
349
  // ═══ Thinking OS: Mental Model Usage Tracking ═══
285
350
  trackThinkingModelUsage({
286
351
  text,
@@ -292,41 +357,56 @@ export function handleLlmOutput(event, ctx) {
292
357
  logger: ctx.logger,
293
358
  });
294
359
  }
295
- function trackThinkingModelUsage(args) {
360
+
361
+ function trackThinkingModelUsage(args: {
362
+ text: string;
363
+ wctx: WorkspaceContext;
364
+ sessionId?: string;
365
+ runId: string;
366
+ assistantTurnId: number | null;
367
+ createdAt: string;
368
+ logger?: PluginHookAgentContext['logger'];
369
+ }): void {
296
370
  const { text, wctx, sessionId, runId, assistantTurnId, createdAt, logger } = args;
297
371
  const logPath = wctx.resolve('THINKING_OS_USAGE');
298
372
  const logDir = path.dirname(logPath);
299
- if (!fs.existsSync(logDir))
300
- fs.mkdirSync(logDir, { recursive: true });
301
- let usageLog = {};
373
+ if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
374
+
375
+ let usageLog: Record<string, number> = {};
376
+
302
377
  if (fs.existsSync(logPath)) {
303
378
  try {
304
379
  usageLog = JSON.parse(fs.readFileSync(logPath, 'utf8'));
305
- }
306
- catch (e) {
307
- console.error(`[PD:LLM] Failed to parse thinking OS usage log: ${String(e)}`);
380
+ } catch (e) {
381
+ logger?.error?.(`[PD:LLM] Failed to parse thinking OS usage log: ${String(e)}`);
308
382
  }
309
383
  }
384
+
310
385
  const matches = detectThinkingModelMatches(text);
311
386
  for (const match of matches) {
312
387
  usageLog[match.modelId] = (usageLog[match.modelId] || 0) + 1;
313
388
  }
389
+
314
390
  usageLog['_total_turns'] = (usageLog['_total_turns'] || 0) + 1;
391
+
315
392
  try {
316
393
  fs.writeFileSync(logPath, JSON.stringify(usageLog, null, 2), 'utf8');
394
+ } catch (e) {
395
+ logger?.error?.(`[PD:LLM] Failed to write thinking OS usage log: ${String(e)}`);
317
396
  }
318
- catch (e) {
319
- console.error(`[PD:LLM] Failed to write thinking OS usage log: ${String(e)}`);
320
- }
397
+
321
398
  if (matches.length === 0) {
322
399
  return;
323
400
  }
401
+
324
402
  if (sessionId) {
325
403
  recordThinkingCheckpoint(sessionId, wctx.workspaceDir);
326
404
  }
405
+
327
406
  if (!sessionId || !assistantTurnId) {
328
407
  return;
329
408
  }
409
+
330
410
  const uiDb = new ControlUiDatabase({ workspaceDir: wctx.workspaceDir });
331
411
  try {
332
412
  const recentContext = uiDb.getRecentThinkingContext(sessionId, createdAt);
@@ -344,6 +424,7 @@ function trackThinkingModelUsage(args) {
344
424
  eventType: event.eventType,
345
425
  }));
346
426
  const triggerExcerpt = text.length > 280 ? `${text.slice(0, 277)}...` : text;
427
+
347
428
  for (const match of matches) {
348
429
  const scenarios = deriveThinkingScenarios(match.modelId, {
349
430
  recentToolCalls: toolContext,
@@ -357,6 +438,7 @@ function trackThinkingModelUsage(args) {
357
438
  })),
358
439
  recentPrincipleEvents: principleContext,
359
440
  });
441
+
360
442
  uiDb.recordThinkingModelEvent({
361
443
  sessionId,
362
444
  runId,
@@ -371,11 +453,9 @@ function trackThinkingModelUsage(args) {
371
453
  createdAt,
372
454
  });
373
455
  }
374
- }
375
- catch (error) {
456
+ } catch (error) {
376
457
  logger?.warn?.(`[PD:LLM] Failed to persist thinking model events: ${String(error)}`);
377
- }
378
- finally {
458
+ } finally {
379
459
  uiDb.dispose();
380
460
  }
381
461
  }
@@ -0,0 +1,45 @@
1
+ import type { PluginHookBeforeMessageWriteEvent, PluginHookBeforeMessageWriteResult } from '../openclaw-sdk.js';
2
+
3
+ const INTERNAL_TAG_PATTERNS = [
4
+ /\[EMOTIONAL_DAMAGE_DETECTED(?::(?:mild|moderate|severe))?\]/gi,
5
+ /\[EMPATHY_ROLLBACK_REQUEST\]/gi,
6
+ /<empathy\s+[^>]*\/?>(?:<\/empathy>)?/gi,
7
+ ];
8
+
9
+ export function sanitizeAssistantText(text: string): string {
10
+ let result = text;
11
+ for (const pattern of INTERNAL_TAG_PATTERNS) {
12
+ result = result.replace(pattern, '');
13
+ }
14
+ return result
15
+ .replace(/[ \t]+\n/g, '\n')
16
+ .replace(/\n{3,}/g, '\n\n')
17
+ .trim();
18
+ }
19
+
20
+ export function handleBeforeMessageWrite(
21
+ event: PluginHookBeforeMessageWriteEvent,
22
+ ): PluginHookBeforeMessageWriteResult | void {
23
+ const msg = event.message as { role?: string; content?: unknown } | undefined;
24
+ if (!msg || msg.role !== 'assistant') return;
25
+
26
+ if (typeof msg.content === 'string') {
27
+ const sanitized = sanitizeAssistantText(msg.content);
28
+ if (sanitized !== msg.content) {
29
+ return { message: { ...msg, content: sanitized } as any };
30
+ }
31
+ return;
32
+ }
33
+
34
+ if (Array.isArray(msg.content)) {
35
+ const next = msg.content.map((part: any) => {
36
+ if (part && typeof part === 'object' && part.type === 'text' && typeof part.text === 'string') {
37
+ return { ...part, text: sanitizeAssistantText(part.text) };
38
+ }
39
+ return part;
40
+ });
41
+ return { message: { ...msg, content: next } as any };
42
+ }
43
+
44
+ return;
45
+ }