principles-disciple 1.8.1 → 1.8.2

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 (470) 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/zh/skills/pd-diagnostician/SKILL.md +70 -1
  138. package/templates/pain_settings.json +2 -1
  139. package/tests/README.md +120 -0
  140. package/tests/build-artifacts.test.ts +111 -0
  141. package/tests/commands/evolution-status.test.ts +222 -0
  142. package/tests/commands/evolver.test.ts +22 -0
  143. package/tests/commands/export.test.ts +78 -0
  144. package/tests/commands/nocturnal-review.test.ts +448 -0
  145. package/tests/commands/nocturnal-train.test.ts +97 -0
  146. package/tests/commands/pain.test.ts +108 -0
  147. package/tests/commands/samples.test.ts +65 -0
  148. package/tests/commands/strategy.test.ts +34 -0
  149. package/tests/commands/thinking-os.test.ts +88 -0
  150. package/tests/core/adaptive-thresholds.test.ts +261 -0
  151. package/tests/core/config-service.test.ts +89 -0
  152. package/tests/core/config.test.ts +90 -0
  153. package/tests/core/control-ui-db.test.ts +75 -0
  154. package/tests/core/core-template-guidance.test.ts +21 -0
  155. package/tests/core/detection-funnel.test.ts +63 -0
  156. package/tests/core/detection-service.test.ts +50 -0
  157. package/tests/core/dictionary-service.test.ts +116 -0
  158. package/tests/core/dictionary.test.ts +168 -0
  159. package/tests/core/empathy-keyword-matcher.test.ts +209 -0
  160. package/tests/core/event-log.test.ts +181 -0
  161. package/tests/core/evolution-e2e.test.ts +58 -0
  162. package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
  163. package/tests/core/evolution-engine.test.ts +562 -0
  164. package/tests/core/evolution-logger.test.ts +148 -0
  165. package/tests/core/evolution-migration.test.ts +50 -0
  166. package/tests/core/evolution-paths.test.ts +21 -0
  167. package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
  168. package/tests/core/evolution-reducer.test.ts +180 -0
  169. package/tests/core/evolution-types-loop.test.ts +48 -0
  170. package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
  171. package/tests/core/external-training-contract.test.ts +463 -0
  172. package/tests/core/focus-history.test.ts +682 -0
  173. package/tests/core/init-flatten.test.ts +69 -0
  174. package/tests/core/init-refactor.test.ts +87 -0
  175. package/tests/core/init-v1.3.test.ts +46 -0
  176. package/tests/core/init.test.ts +190 -0
  177. package/tests/core/local-worker-routing.test.ts +757 -0
  178. package/tests/core/migration.test.ts +84 -0
  179. package/tests/core/model-deployment-registry.test.ts +845 -0
  180. package/tests/core/model-training-registry.test.ts +889 -0
  181. package/tests/core/nocturnal-arbiter.test.ts +494 -0
  182. package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
  183. package/tests/core/nocturnal-compliance.test.ts +646 -0
  184. package/tests/core/nocturnal-dataset.test.ts +892 -0
  185. package/tests/core/nocturnal-executability.test.ts +357 -0
  186. package/tests/core/nocturnal-export.test.ts +462 -0
  187. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
  188. package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
  189. package/tests/core/nocturnal-trinity.test.ts +953 -0
  190. package/tests/core/pain.test.ts +33 -0
  191. package/tests/core/path-resolver.test.ts +57 -0
  192. package/tests/core/paths-refactor.test.ts +42 -0
  193. package/tests/core/phase7-rollout-integration.test.ts +477 -0
  194. package/tests/core/principle-training-state.test.ts +712 -0
  195. package/tests/core/profile.test.ts +56 -0
  196. package/tests/core/promotion-gate.test.ts +556 -0
  197. package/tests/core/risk-calculator.test.ts +168 -0
  198. package/tests/core/session-tracker.test.ts +191 -0
  199. package/tests/core/training-program.test.ts +472 -0
  200. package/tests/core/trajectory.test.ts +265 -0
  201. package/tests/core/workspace-context-factory.test.ts +18 -0
  202. package/tests/core/workspace-context.test.ts +134 -0
  203. package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
  204. package/tests/fixtures/production-compatibility.test.ts +147 -0
  205. package/tests/fixtures/production-mock-generator.ts +282 -0
  206. package/tests/hooks/bash-risk-integration.test.ts +137 -0
  207. package/tests/hooks/bash-risk.test.ts +81 -0
  208. package/tests/hooks/edit-verification.test.ts +678 -0
  209. package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
  210. package/tests/hooks/gate-edit-verification.test.ts +435 -0
  211. package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
  212. package/tests/hooks/gate.test.ts +271 -0
  213. package/tests/hooks/gfi-gate-unit.test.ts +422 -0
  214. package/tests/hooks/gfi-gate.test.ts +669 -0
  215. package/tests/hooks/lifecycle.test.ts +248 -0
  216. package/tests/hooks/llm.test.ts +308 -0
  217. package/tests/hooks/message-sanitize.test.ts +36 -0
  218. package/tests/hooks/pain.test.ts +141 -0
  219. package/tests/hooks/progressive-trust-gate.test.ts +277 -0
  220. package/tests/hooks/prompt.test.ts +1411 -0
  221. package/tests/hooks/subagent.test.ts +467 -0
  222. package/tests/hooks/thinking-gate.test.ts +313 -0
  223. package/tests/http/principles-console-route.test.ts +140 -0
  224. package/tests/hygiene-tracker.test.ts +77 -0
  225. package/tests/index.integration.test.ts +179 -0
  226. package/tests/index.shadow-routing.integration.test.ts +140 -0
  227. package/tests/index.test.ts +9 -0
  228. package/tests/integration/empathy-workflow-integration.test.ts +627 -0
  229. package/tests/service/control-ui-query-service.test.ts +121 -0
  230. package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
  231. package/tests/service/evolution-worker.test.ts +585 -0
  232. package/tests/service/nocturnal-runtime.test.ts +470 -0
  233. package/tests/service/nocturnal-service.test.ts +577 -0
  234. package/tests/service/nocturnal-target-selector.test.ts +615 -0
  235. package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
  236. package/tests/service/phase3-input-filter.test.ts +289 -0
  237. package/tests/service/runtime-summary-service.test.ts +919 -0
  238. package/tests/task-compliance.test.ts +166 -0
  239. package/tests/test-utils.ts +48 -0
  240. package/tests/tools/critique-prompt.test.ts +260 -0
  241. package/tests/tools/deep-reflect.test.ts +232 -0
  242. package/tests/tools/model-index.test.ts +246 -0
  243. package/tests/ui/app.test.tsx +114 -0
  244. package/tests/utils/file-lock.test.ts +407 -0
  245. package/tests/utils/hashing.test.ts +32 -0
  246. package/tests/utils/io.test.ts +39 -0
  247. package/tests/utils/nlp.test.ts +53 -0
  248. package/tests/utils/plugin-logger.test.ts +156 -0
  249. package/tsconfig.json +16 -0
  250. package/tsconfig.tsbuildinfo +1 -0
  251. package/ui/src/App.tsx +45 -0
  252. package/ui/src/api.ts +216 -0
  253. package/ui/src/charts.tsx +586 -0
  254. package/ui/src/components/ErrorState.tsx +6 -0
  255. package/ui/src/components/Loading.tsx +13 -0
  256. package/ui/src/components/ProtectedRoute.tsx +12 -0
  257. package/ui/src/components/Shell.tsx +91 -0
  258. package/ui/src/components/WorkspaceConfig.tsx +146 -0
  259. package/ui/src/components/index.ts +5 -0
  260. package/ui/src/context/auth.tsx +80 -0
  261. package/ui/src/context/theme.tsx +66 -0
  262. package/ui/src/hooks/useAutoRefresh.ts +39 -0
  263. package/ui/src/i18n/ui.ts +363 -0
  264. package/ui/src/main.tsx +16 -0
  265. package/ui/src/pages/EvolutionPage.tsx +352 -0
  266. package/ui/src/pages/FeedbackPage.tsx +140 -0
  267. package/ui/src/pages/GateMonitorPage.tsx +136 -0
  268. package/ui/src/pages/LoginPage.tsx +88 -0
  269. package/ui/src/pages/OverviewPage.tsx +238 -0
  270. package/ui/src/pages/SamplesPage.tsx +174 -0
  271. package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
  272. package/ui/src/styles.css +1661 -0
  273. package/ui/src/types.ts +368 -0
  274. package/ui/src/utils/format.ts +15 -0
  275. package/vitest.config.ts +23 -0
  276. package/dist/commands/capabilities.d.ts +0 -3
  277. package/dist/commands/capabilities.js +0 -73
  278. package/dist/commands/context.d.ts +0 -5
  279. package/dist/commands/evolution-status.d.ts +0 -4
  280. package/dist/commands/evolution-status.js +0 -117
  281. package/dist/commands/evolver.d.ts +0 -9
  282. package/dist/commands/evolver.js +0 -26
  283. package/dist/commands/export.d.ts +0 -2
  284. package/dist/commands/export.js +0 -98
  285. package/dist/commands/focus.d.ts +0 -14
  286. package/dist/commands/focus.js +0 -457
  287. package/dist/commands/nocturnal-review.d.ts +0 -24
  288. package/dist/commands/nocturnal-review.js +0 -265
  289. package/dist/commands/nocturnal-rollout.d.ts +0 -27
  290. package/dist/commands/nocturnal-rollout.js +0 -671
  291. package/dist/commands/nocturnal-train.d.ts +0 -25
  292. package/dist/commands/nocturnal-train.js +0 -919
  293. package/dist/commands/pain.d.ts +0 -5
  294. package/dist/commands/principle-rollback.d.ts +0 -4
  295. package/dist/commands/principle-rollback.js +0 -22
  296. package/dist/commands/rollback.d.ts +0 -19
  297. package/dist/commands/samples.d.ts +0 -2
  298. package/dist/commands/samples.js +0 -55
  299. package/dist/commands/strategy.d.ts +0 -3
  300. package/dist/commands/strategy.js +0 -29
  301. package/dist/commands/thinking-os.d.ts +0 -2
  302. package/dist/config/defaults/runtime.d.ts +0 -40
  303. package/dist/config/errors.d.ts +0 -84
  304. package/dist/config/errors.js +0 -94
  305. package/dist/config/index.js +0 -7
  306. package/dist/constants/diagnostician.d.ts +0 -12
  307. package/dist/constants/diagnostician.js +0 -56
  308. package/dist/constants/tools.d.ts +0 -17
  309. package/dist/constants/tools.js +0 -54
  310. package/dist/core/adaptive-thresholds.d.ts +0 -186
  311. package/dist/core/adaptive-thresholds.js +0 -300
  312. package/dist/core/config-service.d.ts +0 -15
  313. package/dist/core/config.d.ts +0 -129
  314. package/dist/core/control-ui-db.d.ts +0 -95
  315. package/dist/core/control-ui-db.js +0 -292
  316. package/dist/core/detection-funnel.d.ts +0 -33
  317. package/dist/core/detection-service.d.ts +0 -15
  318. package/dist/core/dictionary-service.d.ts +0 -15
  319. package/dist/core/dictionary.d.ts +0 -38
  320. package/dist/core/event-log.d.ts +0 -82
  321. package/dist/core/event-log.js +0 -463
  322. package/dist/core/evolution-engine.d.ts +0 -118
  323. package/dist/core/evolution-engine.js +0 -464
  324. package/dist/core/evolution-logger.d.ts +0 -137
  325. package/dist/core/evolution-logger.js +0 -256
  326. package/dist/core/evolution-migration.d.ts +0 -5
  327. package/dist/core/evolution-migration.js +0 -65
  328. package/dist/core/evolution-reducer.d.ts +0 -98
  329. package/dist/core/evolution-reducer.js +0 -465
  330. package/dist/core/evolution-types.d.ts +0 -287
  331. package/dist/core/evolution-types.js +0 -78
  332. package/dist/core/external-training-contract.d.ts +0 -276
  333. package/dist/core/external-training-contract.js +0 -269
  334. package/dist/core/focus-history.d.ts +0 -210
  335. package/dist/core/focus-history.js +0 -1185
  336. package/dist/core/hygiene/tracker.d.ts +0 -22
  337. package/dist/core/hygiene/tracker.js +0 -106
  338. package/dist/core/init.d.ts +0 -12
  339. package/dist/core/local-worker-routing.d.ts +0 -175
  340. package/dist/core/local-worker-routing.js +0 -525
  341. package/dist/core/migration.d.ts +0 -6
  342. package/dist/core/model-deployment-registry.d.ts +0 -218
  343. package/dist/core/model-deployment-registry.js +0 -503
  344. package/dist/core/model-training-registry.d.ts +0 -295
  345. package/dist/core/model-training-registry.js +0 -475
  346. package/dist/core/nocturnal-arbiter.d.ts +0 -159
  347. package/dist/core/nocturnal-arbiter.js +0 -534
  348. package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
  349. package/dist/core/nocturnal-candidate-scoring.js +0 -266
  350. package/dist/core/nocturnal-compliance.d.ts +0 -175
  351. package/dist/core/nocturnal-compliance.js +0 -824
  352. package/dist/core/nocturnal-dataset.d.ts +0 -224
  353. package/dist/core/nocturnal-dataset.js +0 -443
  354. package/dist/core/nocturnal-executability.d.ts +0 -85
  355. package/dist/core/nocturnal-executability.js +0 -331
  356. package/dist/core/nocturnal-export.d.ts +0 -124
  357. package/dist/core/nocturnal-export.js +0 -275
  358. package/dist/core/nocturnal-paths.d.ts +0 -124
  359. package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
  360. package/dist/core/nocturnal-trajectory-extractor.js +0 -307
  361. package/dist/core/nocturnal-trinity.d.ts +0 -311
  362. package/dist/core/nocturnal-trinity.js +0 -880
  363. package/dist/core/pain.d.ts +0 -4
  364. package/dist/core/pain.js +0 -70
  365. package/dist/core/path-resolver.d.ts +0 -46
  366. package/dist/core/paths.d.ts +0 -65
  367. package/dist/core/principle-training-state.d.ts +0 -121
  368. package/dist/core/principle-training-state.js +0 -321
  369. package/dist/core/profile.d.ts +0 -62
  370. package/dist/core/profile.js +0 -210
  371. package/dist/core/promotion-gate.d.ts +0 -238
  372. package/dist/core/promotion-gate.js +0 -529
  373. package/dist/core/risk-calculator.d.ts +0 -22
  374. package/dist/core/session-tracker.d.ts +0 -101
  375. package/dist/core/shadow-observation-registry.d.ts +0 -217
  376. package/dist/core/shadow-observation-registry.js +0 -308
  377. package/dist/core/system-logger.d.ts +0 -8
  378. package/dist/core/thinking-models.d.ts +0 -38
  379. package/dist/core/thinking-models.js +0 -170
  380. package/dist/core/training-program.d.ts +0 -233
  381. package/dist/core/training-program.js +0 -433
  382. package/dist/core/trajectory.d.ts +0 -411
  383. package/dist/core/trajectory.js +0 -1307
  384. package/dist/core/workspace-context.d.ts +0 -71
  385. package/dist/hooks/bash-risk.d.ts +0 -57
  386. package/dist/hooks/bash-risk.js +0 -137
  387. package/dist/hooks/edit-verification.d.ts +0 -62
  388. package/dist/hooks/edit-verification.js +0 -256
  389. package/dist/hooks/gate-block-helper.d.ts +0 -44
  390. package/dist/hooks/gate-block-helper.js +0 -119
  391. package/dist/hooks/gate.d.ts +0 -24
  392. package/dist/hooks/gate.js +0 -173
  393. package/dist/hooks/gfi-gate.d.ts +0 -40
  394. package/dist/hooks/gfi-gate.js +0 -113
  395. package/dist/hooks/lifecycle.d.ts +0 -5
  396. package/dist/hooks/lifecycle.js +0 -284
  397. package/dist/hooks/llm.d.ts +0 -13
  398. package/dist/hooks/message-sanitize.d.ts +0 -3
  399. package/dist/hooks/message-sanitize.js +0 -37
  400. package/dist/hooks/pain.d.ts +0 -5
  401. package/dist/hooks/pain.js +0 -301
  402. package/dist/hooks/progressive-trust-gate.d.ts +0 -52
  403. package/dist/hooks/progressive-trust-gate.js +0 -134
  404. package/dist/hooks/prompt.d.ts +0 -49
  405. package/dist/hooks/prompt.js +0 -905
  406. package/dist/hooks/subagent.d.ts +0 -10
  407. package/dist/hooks/subagent.js +0 -387
  408. package/dist/hooks/thinking-checkpoint.d.ts +0 -37
  409. package/dist/hooks/thinking-checkpoint.js +0 -51
  410. package/dist/hooks/trajectory-collector.d.ts +0 -32
  411. package/dist/hooks/trajectory-collector.js +0 -256
  412. package/dist/http/principles-console-route.d.ts +0 -9
  413. package/dist/http/principles-console-route.js +0 -681
  414. package/dist/i18n/commands.d.ts +0 -26
  415. package/dist/i18n/commands.js +0 -116
  416. package/dist/index.d.ts +0 -7
  417. package/dist/index.js +0 -581
  418. package/dist/service/central-database.d.ts +0 -104
  419. package/dist/service/central-database.js +0 -649
  420. package/dist/service/control-ui-query-service.d.ts +0 -221
  421. package/dist/service/control-ui-query-service.js +0 -543
  422. package/dist/service/empathy-observer-manager.d.ts +0 -88
  423. package/dist/service/empathy-observer-manager.js +0 -414
  424. package/dist/service/evolution-query-service.d.ts +0 -155
  425. package/dist/service/evolution-query-service.js +0 -258
  426. package/dist/service/evolution-worker.d.ts +0 -101
  427. package/dist/service/evolution-worker.js +0 -975
  428. package/dist/service/health-query-service.d.ts +0 -170
  429. package/dist/service/health-query-service.js +0 -662
  430. package/dist/service/nocturnal-runtime.d.ts +0 -183
  431. package/dist/service/nocturnal-service.d.ts +0 -163
  432. package/dist/service/nocturnal-service.js +0 -787
  433. package/dist/service/nocturnal-target-selector.d.ts +0 -145
  434. package/dist/service/nocturnal-target-selector.js +0 -315
  435. package/dist/service/phase3-input-filter.d.ts +0 -73
  436. package/dist/service/phase3-input-filter.js +0 -172
  437. package/dist/service/runtime-summary-service.d.ts +0 -122
  438. package/dist/service/runtime-summary-service.js +0 -485
  439. package/dist/service/subagent-workflow/empathy-observer-workflow-manager.d.ts +0 -48
  440. package/dist/service/subagent-workflow/index.d.ts +0 -4
  441. package/dist/service/subagent-workflow/index.js +0 -3
  442. package/dist/service/subagent-workflow/runtime-direct-driver.d.ts +0 -77
  443. package/dist/service/subagent-workflow/runtime-direct-driver.js +0 -75
  444. package/dist/service/subagent-workflow/types.js +0 -11
  445. package/dist/service/subagent-workflow/workflow-store.d.ts +0 -26
  446. package/dist/service/subagent-workflow/workflow-store.js +0 -165
  447. package/dist/service/trajectory-service.d.ts +0 -2
  448. package/dist/service/trajectory-service.js +0 -15
  449. package/dist/tools/critique-prompt.d.ts +0 -14
  450. package/dist/tools/deep-reflect.d.ts +0 -39
  451. package/dist/tools/deep-reflect.js +0 -350
  452. package/dist/tools/model-index.d.ts +0 -9
  453. package/dist/types/event-types.d.ts +0 -306
  454. package/dist/types/event-types.js +0 -106
  455. package/dist/types/hygiene-types.d.ts +0 -20
  456. package/dist/types/hygiene-types.js +0 -12
  457. package/dist/types/runtime-summary.d.ts +0 -47
  458. package/dist/types/runtime-summary.js +0 -1
  459. package/dist/types.d.ts +0 -50
  460. package/dist/types.js +0 -22
  461. package/dist/utils/file-lock.d.ts +0 -71
  462. package/dist/utils/file-lock.js +0 -309
  463. package/dist/utils/glob-match.d.ts +0 -28
  464. package/dist/utils/hashing.d.ts +0 -9
  465. package/dist/utils/io.d.ts +0 -6
  466. package/dist/utils/io.js +0 -106
  467. package/dist/utils/nlp.d.ts +0 -9
  468. package/dist/utils/plugin-logger.d.ts +0 -39
  469. package/dist/utils/subagent-probe.d.ts +0 -34
  470. package/dist/utils/subagent-probe.js +0 -81
@@ -0,0 +1,450 @@
1
+ /**
2
+ * Principle Training State Store
3
+ * ================================================================
4
+ *
5
+ * Independent persistence layer for principle internalization tracking.
6
+ * Clearly separates the four truth states defined in the architecture:
7
+ * 1. sample_generated — reflection pair produced and passed arbiter
8
+ * 2. sample_included_in_train_run — training run consumed the sample
9
+ * 3. checkpoint_deployed — adapter/checkpoint is routable in OpenClaw
10
+ * 4. behavior_internalized — deployed worker improves on holdout eval
11
+ *
12
+ * DESIGN CONSTRAINTS (Phase 1):
13
+ * - No runtime target selection (Task 1.2 scope)
14
+ * - No training logic (Phase 2+ scope)
15
+ * - No evolution-reducer modifications
16
+ *
17
+ * FILE: {stateDir}/principle_training_state.json
18
+ */
19
+
20
+ import * as fs from 'fs';
21
+ import * as path from 'path';
22
+ import { withLock, withLockAsync } from '../utils/file-lock.js';
23
+ import type { PrincipleEvaluatorLevel } from './evolution-types.js';
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Constants
27
+ // ---------------------------------------------------------------------------
28
+
29
+ /** File name for principle training state persistence */
30
+ export const PRINCIPLE_TRAINING_FILE = 'principle_training_state.json';
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Types
34
+ // ---------------------------------------------------------------------------
35
+
36
+ // PrincipleEvaluatorLevel is imported from evolution-types.ts to ensure a single canonical definition.
37
+ // Do not re-define here — use the import instead.
38
+
39
+ /**
40
+ * Internalization status — tracks progress through the four truth states:
41
+ * sample_generated → sample_included_in_train_run → checkpoint_deployed → behavior_internalized
42
+ */
43
+ export type InternalizationStatus =
44
+ | 'prompt_only' // Principle has no machine-checkable detector; stays in prompts only
45
+ | 'needs_training' // Evaluable but not yet included in any training run
46
+ | 'in_training' // Currently being used in an active training run
47
+ | 'deployed_pending_eval' // Checkpoint deployed, awaiting holdout evaluation
48
+ | 'internalized' // Passed holdout eval — behavior is learned
49
+ | 'regressed'; // Previously internalized but recent eval shows degradation
50
+
51
+ /**
52
+ * Per-principle training state record.
53
+ * Tracks the full lineage from sample generation through deployment.
54
+ */
55
+ export interface PrincipleTrainingState {
56
+ /** Principle identifier (e.g., "T-01", "P_write_before_delete") */
57
+ principleId: string;
58
+
59
+ /** Evaluability classification — controls whether automatic targeting is allowed */
60
+ evaluability: PrincipleEvaluatorLevel;
61
+
62
+ /** Number of applicable decision-point opportunities observed */
63
+ applicableOpportunityCount: number;
64
+
65
+ /** Number of violations of this principle observed */
66
+ observedViolationCount: number;
67
+
68
+ /** Observed compliance rate (0.0 – 1.0) */
69
+ complianceRate: number;
70
+
71
+ /** Trend direction for violations (+1 = improving, 0 = stable, -1 = worsening) */
72
+ violationTrend: number;
73
+
74
+ /** Number of reflection samples generated for this principle */
75
+ generatedSampleCount: number;
76
+
77
+ /** Number of generated samples approved by arbiter */
78
+ approvedSampleCount: number;
79
+
80
+ /** Training run IDs that included samples from this principle */
81
+ includedTrainRunIds: string[];
82
+
83
+ /** Deployed checkpoint IDs for this principle */
84
+ deployedCheckpointIds: string[];
85
+
86
+ /** Last holdout evaluation score (0.0 – 1.0), if available */
87
+ lastEvalScore?: number;
88
+
89
+ /** Current internalization status */
90
+ internalizationStatus: InternalizationStatus;
91
+ }
92
+
93
+ /**
94
+ * The full principle training store — a map of principleId -> state.
95
+ * Stored as a single JSON object in principle_training_state.json.
96
+ */
97
+ export type PrincipleTrainingStore = Record<string, PrincipleTrainingState>;
98
+
99
+ // ---------------------------------------------------------------------------
100
+ // Valid Status Values (for validation)
101
+ // ---------------------------------------------------------------------------
102
+
103
+ const VALID_EVALUABILITIES: PrincipleEvaluatorLevel[] = ['deterministic', 'weak_heuristic', 'manual_only'];
104
+ const VALID_INTERNALIZATION_STATUSES: InternalizationStatus[] = [
105
+ 'prompt_only',
106
+ 'needs_training',
107
+ 'in_training',
108
+ 'deployed_pending_eval',
109
+ 'internalized',
110
+ 'regressed',
111
+ ];
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Schema Version
115
+ // ---------------------------------------------------------------------------
116
+ // Factory
117
+ // ---------------------------------------------------------------------------
118
+
119
+ /**
120
+ * Creates a default principle training state for a newly tracked principle.
121
+ * Safe defaults: evaluability='manual_only' (requires explicit upgrade to auto-training),
122
+ * internalizationStatus='prompt_only' (starts as prompt-only, not eligible for
123
+ * automatic training until upgraded).
124
+ */
125
+ export function createDefaultPrincipleState(principleId: string): PrincipleTrainingState {
126
+ return {
127
+ principleId,
128
+ evaluability: 'manual_only', // Safe default: requires explicit upgrade
129
+ applicableOpportunityCount: 0,
130
+ observedViolationCount: 0,
131
+ complianceRate: 0,
132
+ violationTrend: 0,
133
+ generatedSampleCount: 0,
134
+ approvedSampleCount: 0,
135
+ includedTrainRunIds: [],
136
+ deployedCheckpointIds: [],
137
+ internalizationStatus: 'prompt_only', // Safe default: starts as prompt-only
138
+ };
139
+ }
140
+
141
+ // ---------------------------------------------------------------------------
142
+ // File Operations
143
+ // ---------------------------------------------------------------------------
144
+
145
+ function getFilePath(stateDir: string): string {
146
+ return path.join(stateDir, PRINCIPLE_TRAINING_FILE);
147
+ }
148
+
149
+ /**
150
+ * Applies migration-safe defaults to a raw parsed store.
151
+ * Handles:
152
+ * - Missing top-level entries (principles added since last load)
153
+ * - Missing fields on existing entries (schema evolution)
154
+ * - Invalid enum values (falls back to safe defaults)
155
+ * - NaN / out-of-range numeric values (clamped or defaulted)
156
+ */
157
+ function applyMigrationDefaults(raw: unknown): PrincipleTrainingStore {
158
+ if (!raw || typeof raw !== 'object') {
159
+ return {};
160
+ }
161
+
162
+ const store = raw as Record<string, unknown>;
163
+ const result: PrincipleTrainingStore = {};
164
+
165
+ for (const [principleId, state] of Object.entries(store)) {
166
+ if (!state || typeof state !== 'object') {
167
+ // Corrupted entry — skip
168
+ continue;
169
+ }
170
+
171
+ const s = state as Record<string, unknown>;
172
+
173
+ // evaluability — validate enum
174
+ const rawEval = s.evaluability;
175
+ const evaluability: PrincipleEvaluatorLevel = VALID_EVALUABILITIES.includes(rawEval as PrincipleEvaluatorLevel)
176
+ ? (rawEval as PrincipleEvaluatorLevel)
177
+ : 'manual_only';
178
+
179
+ // internalizationStatus — validate enum
180
+ const rawStatus = s.internalizationStatus;
181
+ const internalizationStatus: InternalizationStatus = VALID_INTERNALIZATION_STATUSES.includes(rawStatus as InternalizationStatus)
182
+ ? (rawStatus as InternalizationStatus)
183
+ : 'prompt_only';
184
+
185
+ // Numeric fields — clamp to valid ranges
186
+ const applicableOpportunityCount = clampInt(s.applicableOpportunityCount, 0, Infinity, 0);
187
+ const observedViolationCount = clampInt(s.observedViolationCount, 0, Infinity, 0);
188
+ const complianceRate = clampFloat(s.complianceRate, 0, 1, 0);
189
+ const violationTrend = clampFloat(s.violationTrend, -1, 1, 0);
190
+ const generatedSampleCount = clampInt(s.generatedSampleCount, 0, Infinity, 0);
191
+ const approvedSampleCount = clampInt(s.approvedSampleCount, 0, Infinity, 0);
192
+
193
+ // Optional float — only set if in range [0, 1]
194
+ const rawLastEval = s.lastEvalScore;
195
+ let lastEvalScore: number | undefined;
196
+ if (rawLastEval != null && typeof rawLastEval === 'number') {
197
+ const clamped = Math.max(0, Math.min(1, rawLastEval));
198
+ if (Number.isFinite(clamped)) {
199
+ lastEvalScore = clamped;
200
+ }
201
+ }
202
+
203
+ // Arrays — ensure always arrays
204
+ const includedTrainRunIds = Array.isArray(s.includedTrainRunIds)
205
+ ? s.includedTrainRunIds.filter((id): id is string => typeof id === 'string')
206
+ : [];
207
+ const deployedCheckpointIds = Array.isArray(s.deployedCheckpointIds)
208
+ ? s.deployedCheckpointIds.filter((id): id is string => typeof id === 'string')
209
+ : [];
210
+
211
+ // Skip entries where the stored principleId doesn't match the map key.
212
+ // This indicates a corrupted or tampered entry.
213
+ const storedPrincipleId = s.principleId;
214
+ if (typeof storedPrincipleId !== 'string' || storedPrincipleId !== principleId) {
215
+ continue;
216
+ }
217
+
218
+ result[principleId] = {
219
+ principleId,
220
+ evaluability,
221
+ applicableOpportunityCount,
222
+ observedViolationCount,
223
+ complianceRate,
224
+ violationTrend,
225
+ generatedSampleCount,
226
+ approvedSampleCount,
227
+ includedTrainRunIds,
228
+ deployedCheckpointIds,
229
+ lastEvalScore,
230
+ internalizationStatus,
231
+ };
232
+ }
233
+
234
+ return result;
235
+ }
236
+
237
+ /** Clamp an unknown value to a float range, returning default if invalid */
238
+ function clampFloat(
239
+ value: unknown,
240
+ min: number,
241
+ max: number,
242
+ fallback: number
243
+ ): number {
244
+ if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
245
+ return Math.max(min, Math.min(max, value));
246
+ }
247
+
248
+ /** Clamp an unknown value to an integer range, returning default if invalid */
249
+ function clampInt(
250
+ value: unknown,
251
+ min: number,
252
+ max: number,
253
+ fallback: number
254
+ ): number {
255
+ if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
256
+ const rounded = Math.round(value);
257
+ return Math.max(min, Math.min(max, rounded));
258
+ }
259
+
260
+ // ---------------------------------------------------------------------------
261
+ // Synchronous Read/Write
262
+ // ---------------------------------------------------------------------------
263
+
264
+ /**
265
+ * Loads the full principle training store from disk.
266
+ * Returns an empty store if the file does not exist or is corrupted.
267
+ */
268
+ export function loadStore(stateDir: string): PrincipleTrainingStore {
269
+ const filePath = getFilePath(stateDir);
270
+
271
+ if (!fs.existsSync(filePath)) {
272
+ return {};
273
+ }
274
+
275
+ try {
276
+ const raw = fs.readFileSync(filePath, 'utf-8');
277
+ const parsed = JSON.parse(raw);
278
+ return applyMigrationDefaults(parsed);
279
+ } catch (err) {
280
+ // Corrupted file — fail-safe, return empty store
281
+ console.warn(`[principle-training-state] Failed to load store from "${filePath}": ${err instanceof Error ? err.message : String(err)}. Returning empty store.`);
282
+ return {};
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Synchronously saves the full principle training store to disk.
288
+ * Uses file locking to prevent concurrent write corruption.
289
+ */
290
+ export function saveStore(stateDir: string, store: PrincipleTrainingStore): void {
291
+ const filePath = getFilePath(stateDir);
292
+ const dir = path.dirname(filePath);
293
+
294
+ if (!fs.existsSync(dir)) {
295
+ fs.mkdirSync(dir, { recursive: true });
296
+ }
297
+
298
+ withLock(filePath, () => {
299
+ fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');
300
+ });
301
+ }
302
+
303
+ // ---------------------------------------------------------------------------
304
+ // Async Read/Write (for use in async contexts)
305
+ // ---------------------------------------------------------------------------
306
+
307
+ /**
308
+ * Asynchronously loads the full principle training store from disk.
309
+ * Returns an empty store if the file does not exist or is corrupted.
310
+ */
311
+ export async function loadStoreAsync(stateDir: string): Promise<PrincipleTrainingStore> {
312
+ const filePath = getFilePath(stateDir);
313
+
314
+ if (!fs.existsSync(filePath)) {
315
+ return {};
316
+ }
317
+
318
+ try {
319
+ const raw = await fs.promises.readFile(filePath, 'utf-8');
320
+ const parsed = JSON.parse(raw);
321
+ return applyMigrationDefaults(parsed);
322
+ } catch (err) {
323
+ console.warn(`[principle-training-state] Failed to load store asynchronously from "${filePath}": ${err instanceof Error ? err.message : String(err)}. Returning empty store.`);
324
+ return {};
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Asynchronously saves the full principle training store to disk.
330
+ * Uses file locking to prevent concurrent write corruption.
331
+ */
332
+ export async function saveStoreAsync(stateDir: string, store: PrincipleTrainingStore): Promise<void> {
333
+ const filePath = getFilePath(stateDir);
334
+ const dir = path.dirname(filePath);
335
+
336
+ if (!fs.existsSync(dir)) {
337
+ await fs.promises.mkdir(dir, { recursive: true });
338
+ }
339
+
340
+ await withLockAsync(filePath, async () => {
341
+ await fs.promises.writeFile(filePath, JSON.stringify(store, null, 2), 'utf-8');
342
+ });
343
+ }
344
+
345
+ // ---------------------------------------------------------------------------
346
+ // Single-Principle Accessors
347
+ // ---------------------------------------------------------------------------
348
+
349
+ /**
350
+ * Gets the training state for a single principle.
351
+ * Returns a default state if the principle is not yet tracked.
352
+ */
353
+ export function getPrincipleState(
354
+ stateDir: string,
355
+ principleId: string
356
+ ): PrincipleTrainingState {
357
+ const store = loadStore(stateDir);
358
+ return store[principleId] ?? createDefaultPrincipleState(principleId);
359
+ }
360
+
361
+ /**
362
+ * Updates or inserts the training state for a single principle.
363
+ * Persists the full store after the update.
364
+ *
365
+ * Uses file locking around the entire read-modify-write sequence to prevent
366
+ * concurrent updates from causing lost writes.
367
+ */
368
+ export function setPrincipleState(
369
+ stateDir: string,
370
+ state: PrincipleTrainingState
371
+ ): void {
372
+ const filePath = getFilePath(stateDir);
373
+ withLock(filePath, () => {
374
+ // Read current store while holding the lock
375
+ const store = loadStoreUnlocked(filePath);
376
+ store[state.principleId] = state;
377
+ // Write directly — no nested lock needed (we hold the outer lock)
378
+ const dir = path.dirname(filePath);
379
+ if (!fs.existsSync(dir)) {
380
+ fs.mkdirSync(dir, { recursive: true });
381
+ }
382
+ fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');
383
+ });
384
+ }
385
+
386
+ /**
387
+ * Internal: loads store from a specific file path without acquiring a lock.
388
+ * Caller must hold the lock. Use only inside locked sections.
389
+ */
390
+ function loadStoreUnlocked(filePath: string): PrincipleTrainingStore {
391
+ if (!fs.existsSync(filePath)) {
392
+ return {};
393
+ }
394
+ try {
395
+ const raw = fs.readFileSync(filePath, 'utf-8');
396
+ return applyMigrationDefaults(JSON.parse(raw));
397
+ } catch {
398
+ return {};
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Removes a principle from the training store.
404
+ * Does nothing if the principle is not tracked.
405
+ *
406
+ * Uses file locking around the entire read-modify-write sequence.
407
+ */
408
+ export function removePrincipleState(stateDir: string, principleId: string): void {
409
+ const filePath = getFilePath(stateDir);
410
+ withLock(filePath, () => {
411
+ const store = loadStoreUnlocked(filePath);
412
+ if (Object.prototype.hasOwnProperty.call(store, principleId)) {
413
+ delete store[principleId];
414
+ const dir = path.dirname(filePath);
415
+ if (!fs.existsSync(dir)) {
416
+ fs.mkdirSync(dir, { recursive: true });
417
+ }
418
+ fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');
419
+ }
420
+ });
421
+ }
422
+
423
+ /**
424
+ * Returns all principles currently tracked in the store.
425
+ */
426
+ export function listPrincipleIds(stateDir: string): string[] {
427
+ return Object.keys(loadStore(stateDir));
428
+ }
429
+
430
+ /**
431
+ * Returns all principles matching a given internalization status.
432
+ */
433
+ export function listPrinciplesByStatus(
434
+ stateDir: string,
435
+ status: InternalizationStatus
436
+ ): PrincipleTrainingState[] {
437
+ const store = loadStore(stateDir);
438
+ return Object.values(store).filter((s) => s.internalizationStatus === status);
439
+ }
440
+
441
+ /**
442
+ * Returns all principles with 'deterministic' or 'weak_heuristic' evaluability
443
+ * that are eligible for automatic nocturnal targeting.
444
+ */
445
+ export function listEvaluablePrinciples(stateDir: string): PrincipleTrainingState[] {
446
+ const store = loadStore(stateDir);
447
+ return Object.values(store).filter(
448
+ (s) => s.evaluability !== 'manual_only' && s.internalizationStatus !== 'prompt_only'
449
+ );
450
+ }
@@ -0,0 +1,226 @@
1
+ export const PROFILE_AUDIT_LEVELS = new Set(["low", "medium", "high"]);
2
+ export const PROFILE_EVOLUTION_MODES = new Set(["realtime", "async"]);
3
+ export const PROFILE_TEST_LEVELS = new Set(["smoke", "unit", "full"]);
4
+
5
+ export const PROFILE_DEFAULTS = {
6
+ audit_level: "medium",
7
+ risk_paths: [] as string[],
8
+ evolution_mode: "realtime",
9
+ gate: {
10
+ require_plan_for_risk_paths: true,
11
+ require_audit_before_write: true,
12
+ require_reviewer_after_write: true,
13
+ },
14
+ tests: {
15
+ on_change: "smoke",
16
+ on_risk_change: "unit",
17
+ commands: {} as Record<string, string>,
18
+ },
19
+ pain: {
20
+ soft_capture_threshold: 30,
21
+ adaptive: {
22
+ enabled: true,
23
+ spiral_boost: 20,
24
+ min_threshold: 15,
25
+ max_threshold: 70,
26
+ backlog_trigger: 6,
27
+ hard_failure_trigger: 1,
28
+ low_recent_success_boost: 15,
29
+ high_recent_pain_boost: 10,
30
+ },
31
+ },
32
+ lifecycle: {
33
+ enabled: true,
34
+ heartbeat_stale_hours: 72,
35
+ },
36
+ progressive_gate: {
37
+ enabled: true,
38
+ plan_approvals: {
39
+ enabled: false,
40
+ max_lines_override: -1,
41
+ allowed_patterns: [] as string[],
42
+ allowed_operations: [] as string[],
43
+ },
44
+ },
45
+ edit_verification: {
46
+ enabled: true,
47
+ max_file_size_bytes: 10 * 1024 * 1024, // 10MB
48
+ fuzzy_match_enabled: true,
49
+ fuzzy_match_threshold: 0.8,
50
+ skip_large_file_action: "warn" as "warn" | "block", // "warn" or "block"
51
+ },
52
+ thinking_checkpoint: {
53
+ enabled: false, // Default OFF to avoid blocking new users
54
+ window_ms: 5 * 60 * 1000, // 5 minute window
55
+ high_risk_tools: ['run_shell_command', 'delete_file', 'move_file'],
56
+ },
57
+ custom_guards: [] as Array<{ pattern: string; message: string; severity: string }>,
58
+ };
59
+
60
+ export function normalizeProfile(rawProfile: any): any {
61
+ const defaults = JSON.parse(JSON.stringify(PROFILE_DEFAULTS));
62
+ const warnings: string[] = [];
63
+ const normalized = { ...defaults };
64
+ let invalid = false;
65
+
66
+ if (!rawProfile || typeof rawProfile !== "object" || Array.isArray(rawProfile)) {
67
+ warnings.push("PROFILE root must be an object; defaults applied.");
68
+ invalid = true;
69
+ } else {
70
+ // Merge known fields (Support both snake_case and camelCase)
71
+ const auditLevel = rawProfile.audit_level ?? rawProfile.auditLevel;
72
+ if (PROFILE_AUDIT_LEVELS.has(auditLevel)) {
73
+ normalized.audit_level = auditLevel;
74
+ } else if (auditLevel !== undefined) {
75
+ warnings.push(`Invalid audit_level '${auditLevel}'`);
76
+ }
77
+
78
+ const evolutionMode = rawProfile.evolution_mode ?? rawProfile.evolutionMode;
79
+ if (PROFILE_EVOLUTION_MODES.has(evolutionMode)) {
80
+ normalized.evolution_mode = evolutionMode;
81
+ } else if (evolutionMode !== undefined) {
82
+ warnings.push(`Invalid evolution_mode '${evolutionMode}'`);
83
+ }
84
+
85
+ const riskPaths = rawProfile.risk_paths ?? rawProfile.riskPaths;
86
+ if (Array.isArray(riskPaths)) {
87
+ normalized.risk_paths = riskPaths.filter((p: any) => typeof p === 'string');
88
+ } else if (typeof riskPaths === 'string') {
89
+ normalized.risk_paths = [riskPaths];
90
+ } else if (riskPaths !== undefined) {
91
+ warnings.push("risk_paths must be an array of strings");
92
+ }
93
+
94
+ // Gate settings
95
+ if (rawProfile.gate && typeof rawProfile.gate === 'object') {
96
+ const g = rawProfile.gate;
97
+ normalized.gate.require_plan_for_risk_paths = g.require_plan_for_risk_paths ?? g.requirePlanForRiskPaths ?? defaults.gate.require_plan_for_risk_paths;
98
+ normalized.gate.require_audit_before_write = g.require_audit_before_write ?? g.requireAuditBeforeWrite ?? defaults.gate.require_audit_before_write;
99
+ normalized.gate.require_reviewer_after_write = g.require_reviewer_after_write ?? g.requireReviewerAfterWrite ?? defaults.gate.require_reviewer_after_write;
100
+ }
101
+
102
+ // Progressive Gate
103
+ if (rawProfile.progressive_gate && typeof rawProfile.progressive_gate === 'object') {
104
+ const pg = rawProfile.progressive_gate;
105
+ normalized.progressive_gate.enabled = pg.enabled ?? pg.enabled ?? defaults.progressive_gate.enabled;
106
+
107
+ // Plan approvals configuration
108
+ if (pg.plan_approvals && typeof pg.plan_approvals === 'object') {
109
+ const pa = pg.plan_approvals;
110
+ normalized.progressive_gate.plan_approvals.enabled = pa.enabled ?? pa.planApprovals ?? defaults.progressive_gate.plan_approvals.enabled;
111
+
112
+ const maxLines = pa.max_lines_override ?? pa.maxLinesOverride;
113
+ if (typeof maxLines === 'number' && maxLines >= -1) {
114
+ normalized.progressive_gate.plan_approvals.max_lines_override = maxLines;
115
+ }
116
+
117
+ if (Array.isArray(pa.allowed_patterns)) {
118
+ normalized.progressive_gate.plan_approvals.allowed_patterns = pa.allowed_patterns.filter((p: any) => typeof p === 'string');
119
+ }
120
+
121
+ if (Array.isArray(pa.allowed_operations)) {
122
+ normalized.progressive_gate.plan_approvals.allowed_operations = pa.allowed_operations.filter((o: any) => typeof o === 'string');
123
+ }
124
+ }
125
+ } else if (rawProfile.progressiveGate && typeof rawProfile.progressiveGate === 'object') {
126
+ const pg = rawProfile.progressiveGate;
127
+ normalized.progressive_gate.enabled = pg.enabled ?? defaults.progressive_gate.enabled;
128
+
129
+ // Plan approvals configuration (camelCase)
130
+ if (pg.planApprovals && typeof pg.planApprovals === 'object') {
131
+ const pa = pg.planApprovals;
132
+ normalized.progressive_gate.plan_approvals.enabled = pa.enabled ?? defaults.progressive_gate.plan_approvals.enabled;
133
+
134
+ const maxLines = pa.maxLinesOverride;
135
+ if (typeof maxLines === 'number' && maxLines >= -1) {
136
+ normalized.progressive_gate.plan_approvals.max_lines_override = maxLines;
137
+ }
138
+
139
+ if (Array.isArray(pa.allowedPatterns)) {
140
+ normalized.progressive_gate.plan_approvals.allowed_patterns = pa.allowedPatterns.filter((p: any) => typeof p === 'string');
141
+ }
142
+
143
+ if (Array.isArray(pa.allowedOperations)) {
144
+ normalized.progressive_gate.plan_approvals.allowed_operations = pa.allowedOperations.filter((o: any) => typeof o === 'string');
145
+ }
146
+ }
147
+ }
148
+
149
+ // Edit verification settings (P-03)
150
+ const evRaw = rawProfile.edit_verification ?? rawProfile.editVerification;
151
+ if (evRaw && typeof evRaw === 'object') {
152
+ normalized.edit_verification.enabled = evRaw.enabled ?? defaults.edit_verification.enabled;
153
+ const maxSize = evRaw.max_file_size_bytes ?? evRaw.maxFileSizeBytes;
154
+ if (typeof maxSize === 'number' && maxSize >= 0) {
155
+ normalized.edit_verification.max_file_size_bytes = maxSize;
156
+ }
157
+ normalized.edit_verification.fuzzy_match_enabled = evRaw.fuzzy_match_enabled ?? evRaw.fuzzyMatchEnabled ?? defaults.edit_verification.fuzzy_match_enabled;
158
+ const threshold = evRaw.fuzzy_match_threshold ?? evRaw.fuzzyMatchThreshold;
159
+ if (typeof threshold === 'number' && threshold > 0 && threshold <= 1) {
160
+ normalized.edit_verification.fuzzy_match_threshold = threshold;
161
+ }
162
+ const action = evRaw.skip_large_file_action ?? evRaw.skipLargeFileAction;
163
+ if (typeof action === 'string' && ['warn', 'block'].includes(action)) {
164
+ normalized.edit_verification.skip_large_file_action = action as "warn" | "block";
165
+ }
166
+ }
167
+
168
+ // Test settings
169
+ if (rawProfile.tests && typeof rawProfile.tests === 'object') {
170
+ const t = rawProfile.tests;
171
+ const onChange = t.on_change ?? t.onChange;
172
+ if (PROFILE_TEST_LEVELS.has(onChange)) {
173
+ normalized.tests.on_change = onChange;
174
+ }
175
+ const onRiskChange = t.on_risk_change ?? t.onRiskChange;
176
+ if (PROFILE_TEST_LEVELS.has(onRiskChange)) {
177
+ normalized.tests.on_risk_change = onRiskChange;
178
+ }
179
+ if (t.commands && typeof t.commands === 'object') {
180
+ normalized.tests.commands = { ...defaults.tests.commands, ...t.commands };
181
+ }
182
+ }
183
+
184
+ // Pain settings
185
+ if (rawProfile.pain && typeof rawProfile.pain === 'object') {
186
+ const p = rawProfile.pain;
187
+ normalized.pain.soft_capture_threshold = p.soft_capture_threshold ?? p.softCaptureThreshold ?? defaults.pain.soft_capture_threshold;
188
+ if (p.adaptive && typeof p.adaptive === 'object') {
189
+ normalized.pain.adaptive = { ...defaults.pain.adaptive, ...p.adaptive };
190
+ }
191
+ }
192
+
193
+ // Thinking OS Checkpoint settings (P-10)
194
+ const tcRaw = rawProfile.thinking_checkpoint ?? rawProfile.thinkingCheckpoint;
195
+ if (tcRaw && typeof tcRaw === 'object') {
196
+ normalized.thinking_checkpoint.enabled = tcRaw.enabled ?? defaults.thinking_checkpoint.enabled;
197
+ const windowMs = tcRaw.window_ms ?? tcRaw.windowMs;
198
+ if (typeof windowMs === 'number' && windowMs > 0) {
199
+ normalized.thinking_checkpoint.window_ms = windowMs;
200
+ }
201
+ if (Array.isArray(tcRaw.high_risk_tools ?? tcRaw.highRiskTools)) {
202
+ normalized.thinking_checkpoint.high_risk_tools = (tcRaw.high_risk_tools ?? tcRaw.highRiskTools).filter((t: any) => typeof t === 'string');
203
+ }
204
+ }
205
+
206
+ if (Array.isArray(rawProfile.custom_guards)) {
207
+ normalized.custom_guards = rawProfile.custom_guards.map((item: any) => {
208
+ let severity = "error";
209
+ const itemSeverity = item.severity;
210
+ if (itemSeverity && ["info", "warning", "error", "fatal"].includes(String(itemSeverity).toLowerCase())) {
211
+ severity = String(itemSeverity).toLowerCase();
212
+ }
213
+ return {
214
+ pattern: String(item.pattern || ""),
215
+ message: String(item.message || "Custom guard triggered"),
216
+ severity,
217
+ };
218
+ }).filter((item: any) => item.pattern);
219
+ }
220
+ }
221
+
222
+ normalized._profile_invalid = invalid;
223
+ normalized._profile_warnings = warnings;
224
+
225
+ return normalized;
226
+ }