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
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Production Compatibility Tests
3
+ *
4
+ * These tests validate that new code works correctly with production data patterns.
5
+ * Run with: npm test -- tests/fixtures/production-compatibility.test.ts
6
+ *
7
+ * NOTE: These tests require access to ~/.openclaw directory (production data)
8
+ */
9
+
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import { describe, expect, it, beforeAll } from 'vitest';
13
+ import {
14
+ loadProductionPainFlag,
15
+ loadProductionEvolutionQueue,
16
+ loadProductionPainCandidates,
17
+ generateTestFixtureFromProduction,
18
+ validateProductionCompatibility,
19
+ createMockQueueItem,
20
+ createMockPainFlag,
21
+ PRODUCTION_FIXTURES,
22
+ } from './production-mock-generator.js';
23
+
24
+ // Skip tests if production data not available
25
+ const hasProductionData = fs.existsSync(PRODUCTION_FIXTURES.STATE_DIR);
26
+
27
+ describe.skipIf(!hasProductionData)('Production Data Compatibility', () => {
28
+ describe('Data Loading', () => {
29
+ it('should load production pain_flag', () => {
30
+ const painFlag = loadProductionPainFlag();
31
+ // May be null if no active pain
32
+ if (painFlag) {
33
+ expect(painFlag).toHaveProperty('score');
34
+ expect(painFlag).toHaveProperty('source');
35
+ expect(painFlag).toHaveProperty('reason');
36
+ }
37
+ });
38
+
39
+ it('should load production evolution_queue', () => {
40
+ const queue = loadProductionEvolutionQueue();
41
+ expect(Array.isArray(queue)).toBe(true);
42
+
43
+ if (queue.length > 0) {
44
+ const item = queue[0];
45
+ expect(item).toHaveProperty('id');
46
+ expect(item).toHaveProperty('score');
47
+ expect(item).toHaveProperty('status');
48
+ expect(['pending', 'in_progress', 'completed', 'resolved']).toContain(item.status);
49
+ }
50
+ });
51
+
52
+ it('should load production pain_candidates', () => {
53
+ const candidates = loadProductionPainCandidates();
54
+ expect(typeof candidates).toBe('object');
55
+ });
56
+ });
57
+
58
+ describe('New Field Compatibility', () => {
59
+ it('should detect missing session_id in pain_flag (expected: fails until production updated)', () => {
60
+ const result = validateProductionCompatibility();
61
+
62
+ // This test documents the current state - not a failure
63
+ console.log('Compatibility issues:', result.issues);
64
+ console.log('Production data:', result.productionData);
65
+
66
+ // New fields are expected to be missing in production
67
+ if (!result.compatible) {
68
+ console.log('⚠️ Production data does not have new fields (session_id, agent_id)');
69
+ console.log(' This is expected after code changes. Production will be updated on next pain event.');
70
+ }
71
+ });
72
+
73
+ it('should handle queue items without session_id gracefully', () => {
74
+ const queue = loadProductionEvolutionQueue();
75
+
76
+ for (const item of queue.slice(0, 5)) {
77
+ // Code should handle missing session_id/agent_id
78
+ expect(() => {
79
+ const normalized = {
80
+ ...item,
81
+ session_id: item.session_id || undefined,
82
+ agent_id: item.agent_id || undefined,
83
+ };
84
+ return normalized;
85
+ }).not.toThrow();
86
+ }
87
+ });
88
+ });
89
+
90
+ describe('Pattern Extraction', () => {
91
+ it('should extract patterns from production data', () => {
92
+ const fixture = generateTestFixtureFromProduction();
93
+
94
+ expect(fixture.patterns).toBeDefined();
95
+ expect(fixture.patterns.painSources.length).toBeGreaterThanOrEqual(0);
96
+
97
+ console.log('Pain sources:', fixture.patterns.painSources);
98
+ console.log('Score distribution:', fixture.patterns.scoreDistribution);
99
+ console.log('Status distribution:', fixture.patterns.statusDistribution);
100
+ });
101
+ });
102
+
103
+ describe('Mock Generation', () => {
104
+ it('should create realistic mock queue items', () => {
105
+ const item = createMockQueueItem({
106
+ session_id: 'test-session-123',
107
+ agent_id: 'main',
108
+ });
109
+
110
+ expect(item.session_id).toBe('test-session-123');
111
+ expect(item.agent_id).toBe('main');
112
+ expect(item.id).toBeDefined();
113
+ expect(item.timestamp).toBeDefined();
114
+ });
115
+
116
+ it('should create realistic mock pain flags', () => {
117
+ const flag = createMockPainFlag({
118
+ session_id: 'test-session-456',
119
+ agent_id: 'builder',
120
+ });
121
+
122
+ expect(flag.session_id).toBe('test-session-456');
123
+ expect(flag.agent_id).toBe('builder');
124
+ expect(flag.time).toBeDefined();
125
+ });
126
+ });
127
+ });
128
+
129
+ describe('Edge Cases from Production', () => {
130
+ it('should handle empty evolution queue', () => {
131
+ const item = createMockQueueItem(); // Uses fallback template
132
+ expect(item).toBeDefined();
133
+ expect(item.id).toBeDefined();
134
+ });
135
+
136
+ it('should handle very long reason strings', () => {
137
+ const longReason = 'A'.repeat(10000);
138
+ const item = createMockQueueItem({ reason: longReason });
139
+ expect(item.reason).toBe(longReason);
140
+ });
141
+
142
+ it('should handle special characters in reason', () => {
143
+ const specialReason = 'Error: "quotes" and \n newlines \t tabs';
144
+ const item = createMockQueueItem({ reason: specialReason });
145
+ expect(item.reason).toBe(specialReason);
146
+ });
147
+ });
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Production Mock Data Generator
3
+ *
4
+ * Extracts patterns from production data to create realistic test fixtures.
5
+ * This ensures tests match real-world scenarios and catches edge cases.
6
+ */
7
+
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+
11
+ // Production data paths
12
+ const OPENCLAW_HOME = process.env.HOME + '/.openclaw';
13
+ const WORKSPACE_MAIN = OPENCLAW_HOME + '/workspace-main';
14
+ const STATE_DIR = WORKSPACE_MAIN + '/.state';
15
+
16
+ // Types extracted from production
17
+ export interface ProductionPainFlag {
18
+ is_risky: string;
19
+ reason: string;
20
+ score: string;
21
+ source: string;
22
+ time: string;
23
+ status?: string;
24
+ task_id?: string;
25
+ session_id?: string; // New field
26
+ agent_id?: string; // New field
27
+ trace_id?: string; // From recent changes
28
+ }
29
+
30
+ export interface ProductionEvolutionQueueItem {
31
+ id: string;
32
+ score: number;
33
+ source: string;
34
+ reason: string;
35
+ trigger_text_preview: string;
36
+ timestamp: string;
37
+ enqueued_at: string;
38
+ status: 'pending' | 'in_progress' | 'completed' | 'resolved';
39
+ task?: string;
40
+ started_at?: string;
41
+ completed_at?: string;
42
+ resolved_at?: string;
43
+ assigned_session_key?: string;
44
+ resolution?: string;
45
+ session_id?: string; // New field
46
+ agent_id?: string; // New field
47
+ }
48
+
49
+ export interface ProductionPainCandidate {
50
+ count: number;
51
+ status?: string;
52
+ firstSeen: string;
53
+ lastSeen?: string;
54
+ samples: string[];
55
+ }
56
+
57
+ /**
58
+ * Load real pain_flag from production
59
+ */
60
+ export function loadProductionPainFlag(): ProductionPainFlag | null {
61
+ const painFlagPath = path.join(STATE_DIR, '.pain_flag');
62
+ if (!fs.existsSync(painFlagPath)) return null;
63
+
64
+ const content = fs.readFileSync(painFlagPath, 'utf8');
65
+ const result: ProductionPainFlag = {} as ProductionPainFlag;
66
+
67
+ for (const line of content.split('\n')) {
68
+ const match = line.match(/^(\w+):\s*(.+)$/);
69
+ if (match) {
70
+ (result as any)[match[1]] = match[2];
71
+ }
72
+ }
73
+
74
+ return result;
75
+ }
76
+
77
+ /**
78
+ * Load real evolution queue from production
79
+ */
80
+ export function loadProductionEvolutionQueue(): ProductionEvolutionQueueItem[] {
81
+ const queuePath = path.join(STATE_DIR, 'evolution_queue.json');
82
+ if (!fs.existsSync(queuePath)) return [];
83
+
84
+ try {
85
+ return JSON.parse(fs.readFileSync(queuePath, 'utf8'));
86
+ } catch {
87
+ return [];
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Load real pain candidates from production
93
+ */
94
+ export function loadProductionPainCandidates(): Record<string, ProductionPainCandidate> {
95
+ const candidatesPath = path.join(STATE_DIR, 'pain_candidates.json');
96
+ if (!fs.existsSync(candidatesPath)) return {};
97
+
98
+ try {
99
+ const data = JSON.parse(fs.readFileSync(candidatesPath, 'utf8'));
100
+ return data.candidates || {};
101
+ } catch {
102
+ return {};
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Sample a JSONL session file for message patterns
108
+ */
109
+ export function sampleSessionMessages(
110
+ sessionId: string,
111
+ agentId: string = 'main',
112
+ limit: number = 10
113
+ ): Array<{ role: string; content: string; timestamp: number }> {
114
+ const sessionPath = path.join(OPENCLAW_HOME, 'agents', agentId, 'sessions', `${sessionId}.jsonl`);
115
+ if (!fs.existsSync(sessionPath)) return [];
116
+
117
+ const messages: Array<{ role: string; content: string; timestamp: number }> = [];
118
+
119
+ try {
120
+ const lines = fs.readFileSync(sessionPath, 'utf8').split('\n').filter(Boolean);
121
+ for (const line of lines.slice(0, limit * 3)) { // Read more lines to get enough messages
122
+ try {
123
+ const entry = JSON.parse(line);
124
+ if (entry.type === 'message' && entry.message) {
125
+ const msg = entry.message;
126
+ let content = '';
127
+ if (typeof msg.content === 'string') {
128
+ content = msg.content;
129
+ } else if (Array.isArray(msg.content)) {
130
+ content = msg.content
131
+ .filter((c: any) => c.type === 'text')
132
+ .map((c: any) => c.text)
133
+ .join('\n');
134
+ }
135
+
136
+ // Truncate to reasonable size
137
+ if (content.length > 500) {
138
+ content = content.slice(0, 500) + '...';
139
+ }
140
+
141
+ messages.push({
142
+ role: msg.role,
143
+ content,
144
+ timestamp: entry.timestamp || Date.now(),
145
+ });
146
+
147
+ if (messages.length >= limit) break;
148
+ }
149
+ } catch {
150
+ // Skip malformed lines
151
+ }
152
+ }
153
+ } catch {
154
+ return [];
155
+ }
156
+
157
+ return messages;
158
+ }
159
+
160
+ /**
161
+ * Generate realistic test fixtures from production patterns
162
+ */
163
+ export function generateTestFixtureFromProduction() {
164
+ const painFlag = loadProductionPainFlag();
165
+ const queue = loadProductionEvolutionQueue();
166
+ const candidates = loadProductionPainCandidates();
167
+
168
+ // Extract patterns
169
+ const patterns = {
170
+ // Pain sources seen in production
171
+ painSources: [...new Set(queue.map(q => q.source))],
172
+
173
+ // Common error patterns
174
+ errorPatterns: queue.map(q => ({
175
+ type: q.source,
176
+ reasonPreview: q.reason.slice(0, 100),
177
+ })),
178
+
179
+ // Score distribution
180
+ scoreDistribution: queue.reduce((acc, q) => {
181
+ acc[q.score] = (acc[q.score] || 0) + 1;
182
+ return acc;
183
+ }, {} as Record<number, number>),
184
+
185
+ // Status distribution
186
+ statusDistribution: queue.reduce((acc, q) => {
187
+ acc[q.status] = (acc[q.status] || 0) + 1;
188
+ return acc;
189
+ }, {} as Record<string, number>),
190
+ };
191
+
192
+ return {
193
+ painFlag,
194
+ queue,
195
+ candidates,
196
+ patterns,
197
+ };
198
+ }
199
+
200
+ /**
201
+ * Create a mock evolution queue item based on production patterns
202
+ */
203
+ export function createMockQueueItem(overrides: Partial<ProductionEvolutionQueueItem> = {}): ProductionEvolutionQueueItem {
204
+ const queue = loadProductionEvolutionQueue();
205
+ const template = queue[0] || {
206
+ id: 'test-001',
207
+ score: 50,
208
+ source: 'tool_failure',
209
+ reason: 'Tool write failed on test.md. Error: Test error.',
210
+ trigger_text_preview: '',
211
+ timestamp: new Date().toISOString(),
212
+ enqueued_at: new Date().toISOString(),
213
+ status: 'pending',
214
+ };
215
+
216
+ return {
217
+ ...template,
218
+ ...overrides,
219
+ id: overrides.id || `test-${Date.now().toString(36)}`,
220
+ timestamp: overrides.timestamp || new Date().toISOString(),
221
+ enqueued_at: overrides.enqueued_at || new Date().toISOString(),
222
+ };
223
+ }
224
+
225
+ /**
226
+ * Create a mock pain flag based on production patterns
227
+ */
228
+ export function createMockPainFlag(overrides: Partial<ProductionPainFlag> = {}): ProductionPainFlag {
229
+ const realFlag = loadProductionPainFlag();
230
+ const template = realFlag || {
231
+ is_risky: 'false',
232
+ reason: 'Test pain signal',
233
+ score: '50',
234
+ source: 'tool_failure',
235
+ time: new Date().toISOString(),
236
+ };
237
+
238
+ return {
239
+ ...template,
240
+ ...overrides,
241
+ time: overrides.time || new Date().toISOString(),
242
+ };
243
+ }
244
+
245
+ /**
246
+ * Validate that new code handles production data correctly
247
+ */
248
+ export function validateProductionCompatibility() {
249
+ const issues: string[] = [];
250
+
251
+ // Check if pain_flag has session_id/agent_id (new fields)
252
+ const painFlag = loadProductionPainFlag();
253
+ if (painFlag && !painFlag.session_id) {
254
+ issues.push('pain_flag missing session_id (new field not yet in production)');
255
+ }
256
+ if (painFlag && !painFlag.agent_id) {
257
+ issues.push('pain_flag missing agent_id (new field not yet in production)');
258
+ }
259
+
260
+ // Check if queue items have session_id/agent_id
261
+ const queue = loadProductionEvolutionQueue();
262
+ const missingSessionId = queue.filter(q => !q.session_id);
263
+ if (missingSessionId.length > 0) {
264
+ issues.push(`evolution_queue: ${missingSessionId.length}/${queue.length} items missing session_id`);
265
+ }
266
+
267
+ return {
268
+ compatible: issues.length === 0,
269
+ issues,
270
+ productionData: {
271
+ painFlag,
272
+ queueCount: queue.length,
273
+ },
274
+ };
275
+ }
276
+
277
+ // Export for use in tests
278
+ export const PRODUCTION_FIXTURES = {
279
+ OPENCLAW_HOME,
280
+ WORKSPACE_MAIN,
281
+ STATE_DIR,
282
+ };
@@ -0,0 +1,137 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { analyzeBashCommand } from '../../src/hooks/bash-risk.js';
3
+
4
+ /**
5
+ * Integration tests for bash-risk module
6
+ * Tests zero-width character detection and command chain analysis
7
+ */
8
+ describe('Bash Risk Analysis - Integration', () => {
9
+ describe('Zero-width character detection', () => {
10
+ it('should block commands with zero-width space (U+200B)', () => {
11
+ // Zero-width space injected between characters
12
+ const maliciousCmd = 'rm\u200B -rf /';
13
+ const result = analyzeBashCommand(maliciousCmd, [], [], { warn: vi.fn() });
14
+ expect(result).toBe('dangerous');
15
+ });
16
+
17
+ it('should block commands with zero-width non-joiner (U+200C)', () => {
18
+ const maliciousCmd = 'rm\u200C -rf /';
19
+ const result = analyzeBashCommand(maliciousCmd, [], [], { warn: vi.fn() });
20
+ expect(result).toBe('dangerous');
21
+ });
22
+
23
+ it('should block commands with zero-width joiner (U+200D)', () => {
24
+ const maliciousCmd = 'rm\u200D -rf /';
25
+ const result = analyzeBashCommand(maliciousCmd, [], [], { warn: vi.fn() });
26
+ expect(result).toBe('dangerous');
27
+ });
28
+
29
+ it('should block commands with word joiner (U+2060)', () => {
30
+ const maliciousCmd = 'rm\u2060 -rf /';
31
+ const result = analyzeBashCommand(maliciousCmd, [], [], { warn: vi.fn() });
32
+ expect(result).toBe('dangerous');
33
+ });
34
+
35
+ it('should block commands with zero-width invisible separator (U+FEFF)', () => {
36
+ const maliciousCmd = 'rm\uFEFF -rf /';
37
+ const result = analyzeBashCommand(maliciousCmd, [], [], { warn: vi.fn() });
38
+ expect(result).toBe('dangerous');
39
+ });
40
+
41
+ it('should block commands with multiple zero-width characters', () => {
42
+ const maliciousCmd = 'rm\u200B\u200C\u200D -rf /';
43
+ const result = analyzeBashCommand(maliciousCmd, [], [], { warn: vi.fn() });
44
+ expect(result).toBe('dangerous');
45
+ });
46
+
47
+ it('should allow normal commands without zero-width characters', () => {
48
+ const normalCmd = 'rm -rf /tmp/test';
49
+ const result = analyzeBashCommand(normalCmd, ['^rm\\s'], [], { warn: vi.fn() });
50
+ expect(result).toBe('safe');
51
+ });
52
+
53
+ it('should detect zero-width characters hidden in normal-looking commands', () => {
54
+ // Command looks like 'git status' but contains hidden chars
55
+ const hiddenCmd = 'git\u200B status';
56
+ const result = analyzeBashCommand(hiddenCmd, [], [], { warn: vi.fn() });
57
+ expect(result).toBe('dangerous');
58
+ });
59
+ });
60
+
61
+ describe('Cyrillic homograph attack detection', () => {
62
+ it('should de-obfuscate Cyrillic characters and match dangerous patterns', () => {
63
+ // Cyrillic 'р' (U+0440) looks like Latin 'p' - 'g\u0440ush' → 'gpush' then 'push'
64
+ // After toLowerCase + deobfuscation: 'gpush' won't match dangerous, but 'push' alone might
65
+ // Actually: '\u0440' maps to 'p' so 'g\u0440ush' → 'gp' + 'ush' = 'gpush'
66
+ // Let's use Cyrillic 'е' which maps to 'e': '\u0435' → 'e'
67
+ const cyrillicCmd = 'r\u0435m -rf /tmp';
68
+ const result = analyzeBashCommand(cyrillicCmd, [], ['^rem'], { warn: vi.fn() });
69
+ expect(result).toBe('dangerous');
70
+ });
71
+
72
+ it('should handle Cyrillic а being converted to Latin a', () => {
73
+ // Cyrillic 'а' (U+0430) maps to Latin 'a' - 's\u0430do' → 'sado'
74
+ // After de-obfuscation: 'sado' - doesn't match dangerous patterns
75
+ const mixedCmd = 's\u0430do apt update';
76
+ const result = analyzeBashCommand(mixedCmd, [], ['^sudo'], { warn: vi.fn() });
77
+ expect(result).toBe('normal');
78
+ });
79
+ });
80
+
81
+ describe('Command chain tokenization', () => {
82
+ it('should detect dangerous commands in chains using &&', () => {
83
+ const chainCmd = 'echo "hello" && rm -rf /tmp/test';
84
+ const result = analyzeBashCommand(chainCmd, [], ['rm\\s+-rf'], { warn: vi.fn() });
85
+ expect(result).toBe('dangerous');
86
+ });
87
+
88
+ it('should detect dangerous commands in chains using ||', () => {
89
+ const chainCmd = 'ls || rm -rf /tmp/test';
90
+ const result = analyzeBashCommand(chainCmd, [], ['rm\\s+-rf'], { warn: vi.fn() });
91
+ expect(result).toBe('dangerous');
92
+ });
93
+
94
+ it('should detect dangerous commands in chains using ;', () => {
95
+ const chainCmd = 'ls ; rm -rf /tmp/test';
96
+ const result = analyzeBashCommand(chainCmd, [], ['rm\\s+-rf'], { warn: vi.fn() });
97
+ expect(result).toBe('dangerous');
98
+ });
99
+
100
+ it('should return safe if no segment matches dangerous patterns', () => {
101
+ const safeChain = 'echo "hello" && echo "world"';
102
+ const result = analyzeBashCommand(safeChain, [], ['rm\\s+-rf'], { warn: vi.fn() });
103
+ expect(result).toBe('normal');
104
+ });
105
+ });
106
+
107
+ describe('Fail-closed behavior', () => {
108
+ it('should return dangerous for invalid regex in dangerousPatterns', () => {
109
+ const cmd = 'ls';
110
+ const result = analyzeBashCommand(cmd, [], ['[invalid'], { warn: vi.fn() });
111
+ expect(result).toBe('dangerous'); // Fail-closed
112
+ });
113
+
114
+ it('should ignore invalid regex in safePatterns', () => {
115
+ const cmd = 'echo hello';
116
+ const warnFn = vi.fn();
117
+ const result = analyzeBashCommand(cmd, ['[invalid'], [], { warn: warnFn });
118
+ // Should not crash, should return normal (not all segments safe)
119
+ expect(result).toBe('normal');
120
+ expect(warnFn).toHaveBeenCalled();
121
+ });
122
+ });
123
+
124
+ describe('Safe pattern override', () => {
125
+ it('should return safe when all segments match safe patterns', () => {
126
+ const safeCmd = 'git status';
127
+ const result = analyzeBashCommand(safeCmd, ['^git\\s+status', '^ls'], []);
128
+ expect(result).toBe('safe');
129
+ });
130
+
131
+ it('should return normal when not all segments are safe', () => {
132
+ const mixedCmd = 'git status && rm -rf /tmp';
133
+ const result = analyzeBashCommand(mixedCmd, ['^git\\s+status'], ['rm\\s+-rf']);
134
+ expect(result).toBe('dangerous');
135
+ });
136
+ });
137
+ });
@@ -0,0 +1,81 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { analyzeBashCommand } from '../../src/hooks/bash-risk.js';
3
+
4
+ describe('analyzeBashCommand', () => {
5
+ it('should return safe for commands matching safe patterns', () => {
6
+ const result = analyzeBashCommand('npm install lodash', ['^npm\\s+install'], []);
7
+ expect(result).toBe('safe');
8
+ });
9
+
10
+ it('should return dangerous for commands matching dangerous patterns', () => {
11
+ const result = analyzeBashCommand('rm -rf /', [], ['rm\\s+.*-rf']);
12
+ expect(result).toBe('dangerous');
13
+ });
14
+
15
+ it('should return normal for commands not in safe/dangerous lists', () => {
16
+ const result = analyzeBashCommand('npm install lodash', [], []);
17
+ expect(result).toBe('normal');
18
+ });
19
+
20
+ it('should de-obfuscate Cyrillic lookalikes', () => {
21
+ // Using Cyrillic 'rеset' (with Cyrillic 'е' U+0435) instead of 'reset'
22
+ // This should de-obfuscate to 'git reset --hard' and match the dangerous pattern
23
+ const result = analyzeBashCommand('git rеset --hard', [], ['git\\s+(push\\s+.*--force|reset\\s+--hard|clean\\s+-fd)']);
24
+ expect(result).toBe('dangerous');
25
+ });
26
+
27
+ it('should tokenize command chains', () => {
28
+ const result = analyzeBashCommand('npm install && npm test', ['^npm\\s+install'], ['npm\\s+publish']);
29
+ expect(result).toBe('normal');
30
+ });
31
+
32
+ it('should fail-closed on invalid dangerous regex', () => {
33
+ const mockLogger = { warn: vi.fn() };
34
+ const result = analyzeBashCommand('echo test', ['^echo'], ['invalid('], mockLogger);
35
+ expect(result).toBe('dangerous'); // Fail-closed behavior
36
+ expect(mockLogger.warn).toHaveBeenCalledWith(
37
+ expect.stringContaining('Invalid dangerous bash regex')
38
+ );
39
+ });
40
+
41
+ it('should ignore safe pattern on invalid safe regex', () => {
42
+ const mockLogger = { warn: vi.fn() };
43
+ const result = analyzeBashCommand('echo test', ['invalid('], [], mockLogger);
44
+ expect(result).toBe('normal'); // Not safe because safe pattern is invalid and ignored
45
+ expect(mockLogger.warn).toHaveBeenCalledWith(
46
+ expect.stringContaining('Invalid safe bash regex')
47
+ );
48
+ });
49
+
50
+ it('should strip $() from commands before pattern matching', () => {
51
+ const result = analyzeBashCommand('$(npm install)', ['^npm\\s+install'], []);
52
+ expect(result).toBe('safe');
53
+ });
54
+
55
+ it('should strip backticks from commands before pattern matching', () => {
56
+ const result = analyzeBashCommand('`npm install`', ['^npm\\s+install'], []);
57
+ expect(result).toBe('safe');
58
+ });
59
+
60
+ it('should handle command chains with semicolon separator', () => {
61
+ const result = analyzeBashCommand('npm install ; npm test', ['^npm\\s+install'], ['rm\\s+']);
62
+ expect(result).toBe('normal'); // Second command not safe
63
+ });
64
+
65
+ it('should handle command chains with OR separator', () => {
66
+ const result = analyzeBashCommand('npm install || npm test', ['^npm\\s+install'], ['rm\\s+']);
67
+ expect(result).toBe('normal');
68
+ });
69
+
70
+ it('should convert uppercase Cyrillic to lowercase Latin', () => {
71
+ // Using uppercase Cyrillic 'Е' (U+0415) which should convert to 'e'
72
+ // 'git REsET --hard' should become 'git reset --hard' and match the dangerous pattern
73
+ const result = analyzeBashCommand('git rEsET --hard', [], ['git\\s+(push\\s+.*--force|reset\\s+--hard|clean\\s+-fd)']);
74
+ expect(result).toBe('dangerous');
75
+ });
76
+
77
+ it('should handle additional confusable Unicode characters', () => {
78
+ const result = analyzeBashCommand('del node_modules', [], ['rm\\s+']);
79
+ expect(result).toBe('normal'); // 'del' is not in dangerous patterns
80
+ });
81
+ });