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,706 @@
1
+ /**
2
+ * Nocturnal Arbiter — Deterministic Validation of Reflection Artifacts
3
+ * ===================================================================
4
+ *
5
+ * PURPOSE: Validate that a reflection artifact passes all deterministic checks
6
+ * before being approved for persistence. This module is PURE FUNCTIONS —
7
+ * no side effects, no file I/O.
8
+ *
9
+ * VALIDATION RULES:
10
+ * 1. JSON is parseable and has required fields
11
+ * 2. principleId matches the target principle
12
+ * 3. sessionId matches the source snapshot
13
+ * 4. All required string fields are non-empty
14
+ * 5. No fields contain placeholder or dummy values
15
+ * 6. artifactId is a valid unique identifier
16
+ * 7. No raw/private content in any text field
17
+ *
18
+ * DESIGN CONSTRAINTS:
19
+ * - Pure functions only — no I/O, no side effects
20
+ * - Deterministic — same input always produces same output
21
+ * - Fail closed — invalid artifacts are rejected, never sanitized
22
+ * - No LLM involvement — all checks are algorithmic
23
+ */
24
+
25
+ import type { NocturnalSessionSnapshot } from './nocturnal-trajectory-extractor.js';
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Types
29
+ // ---------------------------------------------------------------------------
30
+
31
+ /**
32
+ * A raw reflection artifact as generated by the reflector.
33
+ * This is the raw output before arbiter validation.
34
+ */
35
+ export interface RawReflectionArtifact {
36
+ artifactId?: unknown;
37
+ sessionId?: unknown;
38
+ principleId?: unknown;
39
+ sourceSnapshotRef?: unknown;
40
+ badDecision?: unknown;
41
+ betterDecision?: unknown;
42
+ rationale?: unknown;
43
+ createdAt?: unknown;
44
+ thinkingModelDelta?: unknown;
45
+ planningRatioGain?: unknown;
46
+ invalid?: unknown;
47
+ reason?: unknown;
48
+ }
49
+
50
+ /**
51
+ * A validated and approved reflection artifact.
52
+ * This is the output after arbiter validation passes.
53
+ */
54
+ export interface NocturnalArtifact {
55
+ artifactId: string;
56
+ sessionId: string;
57
+ principleId: string;
58
+ sourceSnapshotRef: string;
59
+ badDecision: string;
60
+ betterDecision: string;
61
+ rationale: string;
62
+ createdAt: string;
63
+ /** Design-alignment metric: delta in thinking model activation (-1 to 1) */
64
+ thinkingModelDelta?: number;
65
+ /** Design-alignment metric: gain in planning ratio (-1 to 1) */
66
+ planningRatioGain?: number;
67
+ }
68
+
69
+ /**
70
+ * Validation failure reason.
71
+ */
72
+ export interface ArbiterFailure {
73
+ reason: string;
74
+ field?: string;
75
+ }
76
+
77
+ /**
78
+ * Result of arbiter validation.
79
+ */
80
+ export interface ArbiterResult {
81
+ /** Whether the artifact passed validation */
82
+ passed: boolean;
83
+ /** The validated artifact (if passed) */
84
+ artifact?: NocturnalArtifact;
85
+ /** The raw input (if failed) */
86
+ rawInput?: RawReflectionArtifact;
87
+ /** Failure reasons (if failed) */
88
+ failures: ArbiterFailure[];
89
+ }
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Validation Helpers
93
+ // ---------------------------------------------------------------------------
94
+
95
+ function isNonEmptyString(val: unknown): val is string {
96
+ return typeof val === 'string' && val.trim().length > 0;
97
+ }
98
+
99
+ function isValidUUID(val: string): boolean {
100
+ // Simple UUID v4 pattern check
101
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(val);
102
+ }
103
+
104
+ function isISO8601(val: string): boolean {
105
+ // ISO 8601 timestamp check
106
+ return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(val);
107
+ }
108
+
109
+ /**
110
+ * Check if a string contains placeholder/dummy values.
111
+ */
112
+ function containsPlaceholder(val: string): boolean {
113
+ const placeholders = [
114
+ '<placeholder>',
115
+ '<uuid>',
116
+ '<session-id>',
117
+ '<principle-id>',
118
+ '<reason>',
119
+ '<action>',
120
+ 'undefined',
121
+ 'null',
122
+ 'n/a',
123
+ 'tbd',
124
+ 'todo',
125
+ 'fixme',
126
+ ];
127
+ const lower = val.toLowerCase();
128
+ return placeholders.some((p) => lower === p || lower.startsWith(p + ' '));
129
+ }
130
+
131
+ /**
132
+ * Check if a string contains raw/private content patterns.
133
+ * This is a heuristic check — not foolproof.
134
+ */
135
+ function containsRawContent(val: string): boolean {
136
+ // Detect file paths with actual code (not just path shapes)
137
+ const rawPatterns = [
138
+ /function\s+\w+\s*\(/, // function definitions
139
+ /class\s+\w+/, // class definitions
140
+ /const\s+\w+\s*=/, // variable declarations
141
+ /import\s+.*from/, // import statements
142
+ /export\s+(default\s+)?/, // export statements
143
+ /api_key|secret|password|token/, // credential patterns (case insensitive)
144
+ ];
145
+ return rawPatterns.some((p) => p.test(val));
146
+ }
147
+
148
+ // ---------------------------------------------------------------------------
149
+ // Trinity Intermediate Validation
150
+ // ---------------------------------------------------------------------------
151
+
152
+ /**
153
+ * Validation result for a Trinity stage output.
154
+ */
155
+ export interface TrinityStageValidationResult {
156
+ valid: boolean;
157
+ failures: string[];
158
+ }
159
+
160
+ /**
161
+ * Validate a Dreamer output contract.
162
+ * Ensures the output is well-formed before passing to Philosopher.
163
+ */
164
+ export function validateDreamerOutput(output: unknown): TrinityStageValidationResult {
165
+ const failures: string[] = [];
166
+
167
+ if (output === null || output === undefined || typeof output !== 'object') {
168
+ return { valid: false, failures: ['Dreamer output must be a JSON object'] };
169
+ }
170
+
171
+ const obj = output as Record<string, unknown>;
172
+
173
+ // Check valid flag
174
+ if (obj.valid !== true) {
175
+ if (typeof obj.reason === 'string' && obj.reason.length > 0) {
176
+ failures.push(`Dreamer marked invalid: ${obj.reason}`);
177
+ } else {
178
+ failures.push('Dreamer output marked invalid with no reason');
179
+ }
180
+ }
181
+
182
+ // Check candidates array
183
+ if (!Array.isArray(obj.candidates)) {
184
+ failures.push('Dreamer output must have a candidates array');
185
+ } else {
186
+ // Validate each candidate
187
+ obj.candidates.forEach((candidate: unknown, idx: number) => {
188
+ if (candidate === null || candidate === undefined || typeof candidate !== 'object') {
189
+ failures.push(`Dreamer candidate at index ${idx} is not an object`);
190
+ return;
191
+ }
192
+ const c = candidate as Record<string, unknown>;
193
+
194
+ if (typeof c.candidateIndex !== 'number') {
195
+ failures.push(`Dreamer candidate ${idx} missing candidateIndex`);
196
+ }
197
+ if (typeof c.badDecision !== 'string' || c.badDecision.trim().length === 0) {
198
+ failures.push(`Dreamer candidate ${idx} missing non-empty badDecision`);
199
+ }
200
+ if (typeof c.betterDecision !== 'string' || c.betterDecision.trim().length === 0) {
201
+ failures.push(`Dreamer candidate ${idx} missing non-empty betterDecision`);
202
+ }
203
+ if (typeof c.rationale !== 'string' || c.rationale.trim().length === 0) {
204
+ failures.push(`Dreamer candidate ${idx} missing non-empty rationale`);
205
+ }
206
+ if (typeof c.confidence !== 'number' || c.confidence < 0 || c.confidence > 1) {
207
+ failures.push(`Dreamer candidate ${idx} has invalid confidence (must be 0-1)`);
208
+ }
209
+
210
+ // badDecision and betterDecision should not be identical
211
+ if (
212
+ typeof c.badDecision === 'string' &&
213
+ typeof c.betterDecision === 'string' &&
214
+ c.badDecision.trim() === c.betterDecision.trim()
215
+ ) {
216
+ failures.push(`Dreamer candidate ${idx}: badDecision and betterDecision are identical`);
217
+ }
218
+ });
219
+
220
+ // Check for duplicate candidateIndices
221
+ const indices = (obj.candidates as Array<Record<string, unknown>>)
222
+ .map((c) => c.candidateIndex)
223
+ .filter((i) => typeof i === 'number');
224
+ const uniqueIndices = new Set(indices);
225
+ if (indices.length !== uniqueIndices.size) {
226
+ failures.push('Dreamer candidates have duplicate candidateIndex values');
227
+ }
228
+ }
229
+
230
+ // Check generatedAt
231
+ if (typeof obj.generatedAt !== 'string' || !isISO8601(obj.generatedAt)) {
232
+ failures.push('Dreamer output missing valid ISO 8601 generatedAt');
233
+ }
234
+
235
+ return { valid: failures.length === 0, failures };
236
+ }
237
+
238
+ /**
239
+ * Validate a Philosopher output contract.
240
+ * Ensures the output is well-formed before passing to Scribe.
241
+ */
242
+ export function validatePhilosopherOutput(output: unknown): TrinityStageValidationResult {
243
+ const failures: string[] = [];
244
+
245
+ if (output === null || output === undefined || typeof output !== 'object') {
246
+ return { valid: false, failures: ['Philosopher output must be a JSON object'] };
247
+ }
248
+
249
+ const obj = output as Record<string, unknown>;
250
+
251
+ // Check valid flag
252
+ if (obj.valid !== true) {
253
+ if (typeof obj.reason === 'string' && obj.reason.length > 0) {
254
+ failures.push(`Philosopher marked invalid: ${obj.reason}`);
255
+ } else {
256
+ failures.push('Philosopher output marked invalid with no reason');
257
+ }
258
+ }
259
+
260
+ // Check judgments array
261
+ if (!Array.isArray(obj.judgments)) {
262
+ failures.push('Philosopher output must have a judgments array');
263
+ } else {
264
+ // Validate each judgment
265
+ obj.judgments.forEach((judgment: unknown, idx: number) => {
266
+ if (judgment === null || judgment === undefined || typeof judgment !== 'object') {
267
+ failures.push(`Philosopher judgment at index ${idx} is not an object`);
268
+ return;
269
+ }
270
+ const j = judgment as Record<string, unknown>;
271
+
272
+ if (typeof j.candidateIndex !== 'number') {
273
+ failures.push(`Philosopher judgment ${idx} missing candidateIndex`);
274
+ }
275
+ if (typeof j.critique !== 'string' || j.critique.trim().length === 0) {
276
+ failures.push(`Philosopher judgment ${idx} missing non-empty critique`);
277
+ }
278
+ if (typeof j.principleAligned !== 'boolean') {
279
+ failures.push(`Philosopher judgment ${idx} missing principleAligned boolean`);
280
+ }
281
+ if (typeof j.score !== 'number' || j.score < 0 || j.score > 1) {
282
+ failures.push(`Philosopher judgment ${idx} has invalid score (must be 0-1)`);
283
+ }
284
+ if (typeof j.rank !== 'number' || j.rank < 1) {
285
+ failures.push(`Philosopher judgment ${idx} has invalid rank (must be >= 1)`);
286
+ }
287
+ });
288
+
289
+ // Check ranks are unique and sequential (1, 2, 3...)
290
+ const ranks = (obj.judgments as Array<Record<string, unknown>>)
291
+ .map((j) => j.rank)
292
+ .filter((r) => typeof r === 'number')
293
+ .sort((a, b) => a - b);
294
+ for (let i = 0; i < ranks.length; i++) {
295
+ if (ranks[i] !== i + 1) {
296
+ failures.push('Philosopher judgments must have sequential ranks starting from 1');
297
+ break;
298
+ }
299
+ }
300
+ }
301
+
302
+ // Check overallAssessment
303
+ if (typeof obj.overallAssessment !== 'string' || obj.overallAssessment.trim().length === 0) {
304
+ failures.push('Philosopher output missing non-empty overallAssessment');
305
+ }
306
+
307
+ // Check generatedAt
308
+ if (typeof obj.generatedAt !== 'string' || !isISO8601(obj.generatedAt)) {
309
+ failures.push('Philosopher output missing valid ISO 8601 generatedAt');
310
+ }
311
+
312
+ return { valid: failures.length === 0, failures };
313
+ }
314
+
315
+ /**
316
+ * Validate a TrinityDraftArtifact contract.
317
+ * This is the final artifact before arbiter approval.
318
+ */
319
+ export function validateTrinityDraft(draft: unknown): TrinityStageValidationResult {
320
+ const failures: string[] = [];
321
+
322
+ if (draft === null || draft === undefined || typeof draft !== 'object') {
323
+ return { valid: false, failures: ['Trinity draft must be a JSON object'] };
324
+ }
325
+
326
+ const obj = draft as Record<string, unknown>;
327
+
328
+ // Required fields
329
+ if (typeof obj.selectedCandidateIndex !== 'number') {
330
+ failures.push('Trinity draft missing selectedCandidateIndex');
331
+ }
332
+ if (typeof obj.badDecision !== 'string' || obj.badDecision.trim().length === 0) {
333
+ failures.push('Trinity draft missing non-empty badDecision');
334
+ }
335
+ if (typeof obj.betterDecision !== 'string' || obj.betterDecision.trim().length === 0) {
336
+ failures.push('Trinity draft missing non-empty betterDecision');
337
+ }
338
+ if (typeof obj.rationale !== 'string' || obj.rationale.trim().length < 20) {
339
+ failures.push('Trinity draft rationale must be at least 20 characters');
340
+ }
341
+ if (typeof obj.sessionId !== 'string' || obj.sessionId.trim().length === 0) {
342
+ failures.push('Trinity draft missing non-empty sessionId');
343
+ }
344
+ if (typeof obj.principleId !== 'string' || obj.principleId.trim().length === 0) {
345
+ failures.push('Trinity draft missing non-empty principleId');
346
+ }
347
+ if (typeof obj.sourceSnapshotRef !== 'string') {
348
+ failures.push('Trinity draft missing sourceSnapshotRef');
349
+ }
350
+
351
+ // Semantic validation
352
+ if (
353
+ typeof obj.badDecision === 'string' &&
354
+ typeof obj.betterDecision === 'string' &&
355
+ obj.badDecision.trim() === obj.betterDecision.trim()
356
+ ) {
357
+ failures.push('Trinity draft badDecision and betterDecision are identical');
358
+ }
359
+
360
+ // Validate telemetry
361
+ if (typeof obj.telemetry === 'object' && obj.telemetry !== null) {
362
+ const t = obj.telemetry as Record<string, unknown>;
363
+ if (t.chainMode !== 'trinity' && t.chainMode !== 'single-reflector') {
364
+ failures.push('Trinity draft telemetry must have valid chainMode');
365
+ }
366
+ if (typeof t.dreamerPassed !== 'boolean') {
367
+ failures.push('Trinity draft telemetry missing dreamerPassed boolean');
368
+ }
369
+ if (typeof t.philosopherPassed !== 'boolean') {
370
+ failures.push('Trinity draft telemetry missing philosopherPassed boolean');
371
+ }
372
+ if (typeof t.scribePassed !== 'boolean') {
373
+ failures.push('Trinity draft telemetry missing scribePassed boolean');
374
+ }
375
+ } else {
376
+ failures.push('Trinity draft missing telemetry object');
377
+ }
378
+
379
+ return { valid: failures.length === 0, failures };
380
+ }
381
+
382
+ /**
383
+ * Parse and validate a Dreamer output from JSON string.
384
+ */
385
+ export function parseAndValidateDreamerOutput(jsonString: string): TrinityStageValidationResult {
386
+ try {
387
+ const parsed = JSON.parse(jsonString);
388
+ return validateDreamerOutput(parsed);
389
+ } catch (err) {
390
+ return {
391
+ valid: false,
392
+ failures: [`Failed to parse Dreamer output JSON: ${err instanceof Error ? err.message : String(err)}`],
393
+ };
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Parse and validate a Philosopher output from JSON string.
399
+ */
400
+ export function parseAndValidatePhilosopherOutput(jsonString: string): TrinityStageValidationResult {
401
+ try {
402
+ const parsed = JSON.parse(jsonString);
403
+ return validatePhilosopherOutput(parsed);
404
+ } catch (err) {
405
+ return {
406
+ valid: false,
407
+ failures: [`Failed to parse Philosopher output JSON: ${err instanceof Error ? err.message : String(err)}`],
408
+ };
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Parse and validate a Trinity draft artifact from JSON string.
414
+ */
415
+ export function parseAndValidateTrinityDraft(jsonString: string): TrinityStageValidationResult {
416
+ try {
417
+ const parsed = JSON.parse(jsonString);
418
+ return validateTrinityDraft(parsed);
419
+ } catch (err) {
420
+ return {
421
+ valid: false,
422
+ failures: [`Failed to parse Trinity draft JSON: ${err instanceof Error ? err.message : String(err)}`],
423
+ };
424
+ }
425
+ }
426
+
427
+ // ---------------------------------------------------------------------------
428
+ // Core Arbiter
429
+ // ---------------------------------------------------------------------------
430
+
431
+ export interface ArbiterOptions {
432
+ /**
433
+ * Expected principle ID (from target selection).
434
+ * If provided, the artifact's principleId must match this.
435
+ */
436
+ expectedPrincipleId?: string;
437
+
438
+ /**
439
+ * Expected session ID (from snapshot).
440
+ * If provided, the artifact's sessionId must match this.
441
+ */
442
+ expectedSessionId?: string;
443
+
444
+ /**
445
+ * Minimum quality thresholds for reflection metrics.
446
+ * If provided, artifacts failing these thresholds are rejected.
447
+ */
448
+ qualityThresholds?: {
449
+ /**
450
+ * Minimum thinkingModelDelta (delta in thinking model activation).
451
+ * Must be > 0 for artifact to pass (cognitive improvement required).
452
+ * Default: undefined (no threshold — only range check [-1, 1])
453
+ */
454
+ thinkingModelDeltaMin?: number;
455
+ /**
456
+ * Minimum planningRatioGain.
457
+ * Must be >= -0.5 for artifact to pass (no catastrophic planning regression).
458
+ * Default: undefined (no threshold — only range check [-1, 1])
459
+ */
460
+ planningRatioGainMin?: number;
461
+ };
462
+ }
463
+
464
+ /**
465
+ * Validate a raw reflection artifact against all arbiter rules.
466
+ *
467
+ * @param raw - The raw artifact JSON (already parsed)
468
+ * @param options - Expected values for cross-validation
469
+ * @returns ArbiterResult with passed/failed status and details
470
+ */
471
+ export function validateArtifact(
472
+ raw: unknown,
473
+ options: ArbiterOptions = {}
474
+ ): ArbiterResult {
475
+ const failures: ArbiterFailure[] = [];
476
+
477
+ // Rule 1: Must be an object
478
+ if (raw === null || raw === undefined || typeof raw !== 'object' || Array.isArray(raw)) {
479
+ return {
480
+ passed: false,
481
+ rawInput: raw as RawReflectionArtifact,
482
+ failures: [{ reason: 'Artifact must be a JSON object' }],
483
+ };
484
+ }
485
+
486
+ const obj = raw as Record<string, unknown>;
487
+
488
+ // Rule 2: Check for invalid flag (reflector said it couldn't generate)
489
+ if (obj.invalid === true || obj.invalid === 'true') {
490
+ return {
491
+ passed: false,
492
+ rawInput: obj as RawReflectionArtifact,
493
+ failures: [{ reason: `Reflector marked artifact as invalid: ${String(obj.reason ?? 'no reason provided')}` }],
494
+ };
495
+ }
496
+
497
+ // Rule 3: Required string fields must be present and non-empty
498
+ const requiredFields: Array<{ key: keyof RawReflectionArtifact; label: string }> = [
499
+ { key: 'artifactId', label: 'artifactId' },
500
+ { key: 'sessionId', label: 'sessionId' },
501
+ { key: 'principleId', label: 'principleId' },
502
+ { key: 'badDecision', label: 'badDecision' },
503
+ { key: 'betterDecision', label: 'betterDecision' },
504
+ { key: 'rationale', label: 'rationale' },
505
+ { key: 'createdAt', label: 'createdAt' },
506
+ ];
507
+
508
+ for (const field of requiredFields) {
509
+ const val = obj[field.key];
510
+ if (!isNonEmptyString(val)) {
511
+ failures.push({ reason: `Field '${field.label}' is missing or empty`, field: field.label });
512
+ } else {
513
+ // Additional checks for string fields
514
+ if (field.label === 'artifactId' && !isValidUUID(String(val))) {
515
+ failures.push({ reason: `Field '${field.label}' must be a valid UUID`, field: field.label });
516
+ }
517
+ if (field.label === 'createdAt' && !isISO8601(String(val))) {
518
+ failures.push({ reason: `Field '${field.label}' must be a valid ISO 8601 timestamp`, field: field.label });
519
+ }
520
+ }
521
+ }
522
+
523
+ // Rule 4: Cross-validate principleId
524
+ if (options.expectedPrincipleId !== undefined) {
525
+ const principleId = obj.principleId;
526
+ if (!isNonEmptyString(principleId)) {
527
+ failures.push({ reason: 'principleId is required but missing', field: 'principleId' });
528
+ } else if (String(principleId) !== options.expectedPrincipleId) {
529
+ failures.push({
530
+ reason: `principleId mismatch: expected '${options.expectedPrincipleId}', got '${String(principleId)}'`,
531
+ field: 'principleId',
532
+ });
533
+ }
534
+ }
535
+
536
+ // Rule 5: Cross-validate sessionId
537
+ if (options.expectedSessionId !== undefined) {
538
+ const sessionId = obj.sessionId;
539
+ if (!isNonEmptyString(sessionId)) {
540
+ failures.push({ reason: 'sessionId is required but missing', field: 'sessionId' });
541
+ } else if (String(sessionId) !== options.expectedSessionId) {
542
+ failures.push({
543
+ reason: `sessionId mismatch: expected '${options.expectedSessionId}', got '${String(sessionId)}'`,
544
+ field: 'sessionId',
545
+ });
546
+ }
547
+ }
548
+
549
+ // Rule 6: Check for placeholder values in text fields
550
+ const textFields: Array<keyof RawReflectionArtifact> = [
551
+ 'badDecision',
552
+ 'betterDecision',
553
+ 'rationale',
554
+ ];
555
+ for (const field of textFields) {
556
+ const val = obj[field];
557
+ if (isNonEmptyString(val)) {
558
+ const strVal = String(val);
559
+ if (containsPlaceholder(strVal)) {
560
+ failures.push({ reason: `Field '${String(field)}' contains a placeholder value`, field: String(field) });
561
+ }
562
+ if (containsRawContent(strVal)) {
563
+ failures.push({
564
+ reason: `Field '${String(field)}' may contain raw/private content — not allowed in nocturnal artifacts`,
565
+ field: String(field),
566
+ });
567
+ }
568
+ }
569
+ }
570
+
571
+ // Rule 7: Check sourceSnapshotRef if present
572
+ const sourceSnapshotRef = obj.sourceSnapshotRef;
573
+ if (sourceSnapshotRef !== undefined && !isNonEmptyString(sourceSnapshotRef)) {
574
+ failures.push({ reason: 'Field "sourceSnapshotRef" must be a non-empty string if present', field: 'sourceSnapshotRef' });
575
+ }
576
+
577
+ // Rule 8: badDecision should not be identical to betterDecision
578
+ const badDecision = obj.badDecision;
579
+ const betterDecision = obj.betterDecision;
580
+ if (isNonEmptyString(badDecision) && isNonEmptyString(betterDecision)) {
581
+ if (String(badDecision).trim() === String(betterDecision).trim()) {
582
+ failures.push({
583
+ reason: 'badDecision and betterDecision cannot be identical',
584
+ field: 'betterDecision',
585
+ });
586
+ }
587
+ }
588
+
589
+ // Rule 9: Rationale should not be too short (needs explanation)
590
+ const rationale = obj.rationale;
591
+ if (isNonEmptyString(rationale) && String(rationale).trim().length < 20) {
592
+ failures.push({
593
+ reason: 'rationale is too short — must provide meaningful explanation',
594
+ field: 'rationale',
595
+ });
596
+ }
597
+
598
+ // Rule 10: Validate optional reflection quality metrics (if present)
599
+ const thinkingModelDelta = obj.thinkingModelDelta;
600
+ if (thinkingModelDelta !== undefined && typeof thinkingModelDelta !== 'number') {
601
+ failures.push({
602
+ reason: 'thinkingModelDelta must be a number if present',
603
+ field: 'thinkingModelDelta',
604
+ });
605
+ } else if (typeof thinkingModelDelta === 'number' && (thinkingModelDelta < -1 || thinkingModelDelta > 1)) {
606
+ failures.push({
607
+ reason: 'thinkingModelDelta must be between -1 and 1',
608
+ field: 'thinkingModelDelta',
609
+ });
610
+ }
611
+
612
+ const planningRatioGain = obj.planningRatioGain;
613
+ if (planningRatioGain !== undefined && typeof planningRatioGain !== 'number') {
614
+ failures.push({
615
+ reason: 'planningRatioGain must be a number if present',
616
+ field: 'planningRatioGain',
617
+ });
618
+ } else if (typeof planningRatioGain === 'number' && (planningRatioGain < -1 || planningRatioGain > 1)) {
619
+ failures.push({
620
+ reason: 'planningRatioGain must be between -1 and 1',
621
+ field: 'planningRatioGain',
622
+ });
623
+ }
624
+
625
+ // Rule 11: Quality threshold gate — reject low-signal artifacts
626
+ // A reflection artifact must show positive cognitive improvement (thinkingModelDelta > 0).
627
+ // planningRatioGain must not show catastrophic regression (< -0.5).
628
+ if (
629
+ options.qualityThresholds?.thinkingModelDeltaMin !== undefined &&
630
+ thinkingModelDelta !== undefined &&
631
+ typeof thinkingModelDelta === 'number' &&
632
+ thinkingModelDelta <= options.qualityThresholds.thinkingModelDeltaMin
633
+ ) {
634
+ failures.push({
635
+ reason: `thinkingModelDelta (${thinkingModelDelta}) does not meet minimum quality threshold (${options.qualityThresholds.thinkingModelDeltaMin}) — reflection shows no cognitive improvement`,
636
+ field: 'thinkingModelDelta',
637
+ });
638
+ }
639
+
640
+ if (
641
+ options.qualityThresholds?.planningRatioGainMin !== undefined &&
642
+ planningRatioGain !== undefined &&
643
+ typeof planningRatioGain === 'number' &&
644
+ planningRatioGain < options.qualityThresholds.planningRatioGainMin
645
+ ) {
646
+ failures.push({
647
+ reason: `planningRatioGain (${planningRatioGain}) shows catastrophic planning regression — below minimum threshold (${options.qualityThresholds.planningRatioGainMin})`,
648
+ field: 'planningRatioGain',
649
+ });
650
+ }
651
+
652
+ // Final decision
653
+ if (failures.length > 0) {
654
+ return {
655
+ passed: false,
656
+ rawInput: obj as RawReflectionArtifact,
657
+ failures,
658
+ };
659
+ }
660
+
661
+ // Construct validated artifact
662
+ const artifact: NocturnalArtifact = {
663
+ artifactId: String(obj.artifactId),
664
+ sessionId: String(obj.sessionId),
665
+ principleId: String(obj.principleId),
666
+ sourceSnapshotRef: isNonEmptyString(obj.sourceSnapshotRef) ? String(obj.sourceSnapshotRef) : '',
667
+ badDecision: String(obj.badDecision),
668
+ betterDecision: String(obj.betterDecision),
669
+ rationale: String(obj.rationale),
670
+ createdAt: String(obj.createdAt),
671
+ thinkingModelDelta: typeof obj.thinkingModelDelta === 'number' ? obj.thinkingModelDelta : undefined,
672
+ planningRatioGain: typeof obj.planningRatioGain === 'number' ? obj.planningRatioGain : undefined,
673
+ };
674
+
675
+ return {
676
+ passed: true,
677
+ artifact,
678
+ failures: [],
679
+ };
680
+ }
681
+
682
+ /**
683
+ * Parse and validate a JSON string as a reflection artifact.
684
+ *
685
+ * @param jsonString - Raw JSON string from reflector
686
+ * @param options - Expected values for cross-validation
687
+ * @returns ArbiterResult
688
+ */
689
+ export function parseAndValidateArtifact(
690
+ jsonString: string,
691
+ options: ArbiterOptions = {}
692
+ ): ArbiterResult {
693
+ // Step 1: Parse JSON
694
+ let parsed: unknown;
695
+ try {
696
+ parsed = JSON.parse(jsonString);
697
+ } catch (err) {
698
+ return {
699
+ passed: false,
700
+ failures: [{ reason: `Failed to parse JSON: ${err instanceof Error ? err.message : String(err)}` }],
701
+ };
702
+ }
703
+
704
+ // Step 2: Validate
705
+ return validateArtifact(parsed, options);
706
+ }