principles-disciple 1.8.0 → 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 (460) 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 +6 -1
  10. package/package.json +13 -15
  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} +185 -63
  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} +166 -139
  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} +263 -36
  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/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +603 -0
  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/src/service/subagent-workflow/types.ts +378 -0
  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 -127
  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 -99
  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 -12
  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 -51
  403. package/dist/hooks/progressive-trust-gate.js +0 -89
  404. package/dist/hooks/prompt.d.ts +0 -47
  405. package/dist/hooks/prompt.js +0 -884
  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 -567
  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 -52
  423. package/dist/service/empathy-observer-manager.js +0 -229
  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 -974
  428. package/dist/service/nocturnal-runtime.d.ts +0 -183
  429. package/dist/service/nocturnal-service.d.ts +0 -163
  430. package/dist/service/nocturnal-service.js +0 -787
  431. package/dist/service/nocturnal-target-selector.d.ts +0 -145
  432. package/dist/service/nocturnal-target-selector.js +0 -315
  433. package/dist/service/phase3-input-filter.d.ts +0 -73
  434. package/dist/service/phase3-input-filter.js +0 -172
  435. package/dist/service/runtime-summary-service.d.ts +0 -122
  436. package/dist/service/runtime-summary-service.js +0 -485
  437. package/dist/service/trajectory-service.d.ts +0 -2
  438. package/dist/service/trajectory-service.js +0 -15
  439. package/dist/tools/critique-prompt.d.ts +0 -14
  440. package/dist/tools/deep-reflect.d.ts +0 -39
  441. package/dist/tools/deep-reflect.js +0 -350
  442. package/dist/tools/model-index.d.ts +0 -9
  443. package/dist/types/event-types.d.ts +0 -306
  444. package/dist/types/event-types.js +0 -106
  445. package/dist/types/hygiene-types.d.ts +0 -20
  446. package/dist/types/hygiene-types.js +0 -12
  447. package/dist/types/runtime-summary.d.ts +0 -47
  448. package/dist/types/runtime-summary.js +0 -1
  449. package/dist/types.d.ts +0 -50
  450. package/dist/types.js +0 -22
  451. package/dist/utils/file-lock.d.ts +0 -71
  452. package/dist/utils/file-lock.js +0 -309
  453. package/dist/utils/glob-match.d.ts +0 -28
  454. package/dist/utils/hashing.d.ts +0 -9
  455. package/dist/utils/io.d.ts +0 -6
  456. package/dist/utils/io.js +0 -106
  457. package/dist/utils/nlp.d.ts +0 -9
  458. package/dist/utils/plugin-logger.d.ts +0 -39
  459. package/dist/utils/subagent-probe.d.ts +0 -34
  460. package/dist/utils/subagent-probe.js +0 -81
@@ -1,224 +0,0 @@
1
- /**
2
- * Nocturnal Dataset — Sample Lineage Store and Review State Registry
3
- * =================================================================
4
- *
5
- * PURPOSE: Establish each approved nocturnal sample as a first-class auditable
6
- * data asset with fingerprint, lineage, review state, and model family binding.
7
- *
8
- * ARCHITECTURE:
9
- * - Registry file: {stateDir}/.state/nocturnal/dataset-registry.json
10
- * - One JSON array of NocturnalDatasetRecord
11
- * - Each record is immutable except for reviewStatus and reviewReason
12
- * - sampleFingerprint is the primary key (deterministic: SHA-256 of artifactId+principleId+sessionId)
13
- *
14
- * RELATIONSHIP TO NOCTURNAL ARTIFACTS:
15
- * - Artifacts live in: .state/nocturnal/samples/{artifactId}.json
16
- * - Dataset records reference artifacts via artifactId and artifactPath
17
- * - Artifacts are NOT modified by dataset operations
18
- *
19
- * DESIGN CONSTRAINTS:
20
- * - No training run registry (Phase 4)
21
- * - No checkpoint registry (Phase 4)
22
- * - No worker routing changes
23
- * - No JSONL export (that's Task 3.2)
24
- * - Lineage is append-only for approved records
25
- * - reviewStatus transitions are the only state mutations allowed
26
- */
27
- import type { NocturnalArtifact } from './nocturnal-arbiter.js';
28
- /**
29
- * Review status for a nocturnal dataset sample.
30
- * Follows the lifecycle: pending_review → approved_for_training | rejected | superseded
31
- */
32
- export type NocturnalReviewStatus = 'pending_review' | 'approved_for_training' | 'rejected' | 'superseded';
33
- /**
34
- * A nocturnal dataset record — the immutable lineage entry for one sample.
35
- *
36
- * PRIMARY KEY: sampleFingerprint (deterministic SHA-256)
37
- * MUTABLE FIELDS: reviewStatus, reviewReason only
38
- * IMMUTABLE FIELDS: all others
39
- */
40
- export interface NocturnalDatasetRecord {
41
- /**
42
- * Deterministic fingerprint: SHA-256(artifactId + principleId + sessionId).
43
- * Primary key for dataset operations.
44
- */
45
- sampleFingerprint: string;
46
- /** Reference to the original artifact */
47
- artifactId: string;
48
- /** Source session */
49
- sessionId: string;
50
- /** Target principle that generated this sample */
51
- principleId: string;
52
- /** Reference to the trajectory snapshot used */
53
- sourceSnapshotRef: string;
54
- /**
55
- * Current review state.
56
- * Only transitions allowed: pending_review → approved_for_training | rejected | superseded
57
- */
58
- reviewStatus: NocturnalReviewStatus;
59
- /**
60
- * Human-provided reason for the review decision.
61
- * Required for approved_for_training and rejected; optional for superseded.
62
- */
63
- reviewReason?: string;
64
- /**
65
- * Target model family this sample is bound to.
66
- * REQUIRED for export-ready samples.
67
- * NULL means "not yet assigned" (pending_review defaults to null).
68
- */
69
- targetModelFamily: string | null;
70
- /**
71
- * When this sample was first registered in the dataset.
72
- */
73
- createdAt: string;
74
- /**
75
- * Last time reviewStatus or reviewReason was updated.
76
- */
77
- updatedAt: string;
78
- /**
79
- * Absolute path to the artifact file.
80
- */
81
- artifactPath: string;
82
- }
83
- /**
84
- * Filter options for listing dataset records.
85
- */
86
- export interface DatasetFilterOptions {
87
- /**
88
- * Filter by review status.
89
- */
90
- reviewStatus?: NocturnalReviewStatus | NocturnalReviewStatus[];
91
- /**
92
- * Filter by target model family.
93
- * NULL means "any" (including null/unassigned).
94
- */
95
- targetModelFamily?: string | null;
96
- /**
97
- * Include only export-ready records.
98
- * An export-ready record must have:
99
- * - reviewStatus === 'approved_for_training'
100
- * - targetModelFamily !== null
101
- * - artifactPath points to an existing file
102
- */
103
- exportReadyOnly?: boolean;
104
- }
105
- /**
106
- * Result of registering a sample.
107
- */
108
- export interface RegisterSampleResult {
109
- /** The registered record */
110
- record: NocturnalDatasetRecord;
111
- /** Whether this was a new registration (true) or duplicate link (false) */
112
- isNew: boolean;
113
- /**
114
- * If isNew === false, this points to the existing record.
115
- */
116
- existingRecord?: NocturnalDatasetRecord;
117
- }
118
- /**
119
- * Generate a deterministic sample fingerprint from an artifact.
120
- *
121
- * FINGERPRINT = SHA-256(artifactId || principleId || sessionId)
122
- *
123
- * The fingerprint is deterministic so the same sample always produces
124
- * the same fingerprint, enabling duplicate detection.
125
- */
126
- export declare function generateSampleFingerprint(artifactId: string, principleId: string, sessionId: string): string;
127
- /**
128
- * Generate a fingerprint from an existing NocturnalArtifact.
129
- */
130
- export declare function generateFingerprintFromArtifact(artifact: NocturnalArtifact): string;
131
- /**
132
- * Register an approved nocturnal artifact in the dataset registry.
133
- *
134
- * DUPLICATE HANDLING:
135
- * - If a record with the same sampleFingerprint already exists, returns
136
- * existingRecord (isNew === false) instead of creating a duplicate.
137
- * - The original artifact file is never modified.
138
- *
139
- * @param workspaceDir - Workspace directory
140
- * @param artifact - The approved NocturnalArtifact
141
- * @param artifactPath - Absolute path where the artifact file is stored
142
- * @param targetModelFamily - Model family binding (required for export-ready)
143
- * @returns RegisterSampleResult
144
- */
145
- export declare function registerSample(workspaceDir: string, artifact: NocturnalArtifact, artifactPath: string, targetModelFamily?: string | null): RegisterSampleResult;
146
- /**
147
- * Get a dataset record by fingerprint.
148
- */
149
- export declare function getDatasetRecord(workspaceDir: string, sampleFingerprint: string): NocturnalDatasetRecord | null;
150
- /**
151
- * Get a dataset record by artifactId.
152
- */
153
- export declare function getDatasetRecordByArtifactId(workspaceDir: string, artifactId: string): NocturnalDatasetRecord | null;
154
- /**
155
- * List dataset records with optional filtering.
156
- *
157
- * @param workspaceDir - Workspace directory
158
- * @param filter - Optional filter criteria
159
- * @returns Filtered records sorted by createdAt descending
160
- */
161
- export declare function listDatasetRecords(workspaceDir: string, filter?: DatasetFilterOptions): NocturnalDatasetRecord[];
162
- /**
163
- * Update the review status of a dataset record.
164
- *
165
- * @param workspaceDir - Workspace directory
166
- * @param sampleFingerprint - The fingerprint of the record to update
167
- * @param newStatus - The new review status
168
- * @param reason - Optional reason (required for approved/rejected per spec)
169
- * @returns Updated record, or null if not found
170
- * @throws Error if transition is invalid
171
- */
172
- export declare function updateReviewStatus(workspaceDir: string, sampleFingerprint: string, newStatus: NocturnalReviewStatus, reason?: string): NocturnalDatasetRecord;
173
- /**
174
- * Update the target model family binding.
175
- */
176
- export declare function updateTargetModelFamily(workspaceDir: string, sampleFingerprint: string, targetModelFamily: string | null): NocturnalDatasetRecord;
177
- /**
178
- * Check if a sample is export-ready.
179
- *
180
- * EXPORT-READY means:
181
- * - reviewStatus === 'approved_for_training'
182
- * - targetModelFamily !== null
183
- * - artifact file exists
184
- * - lineage fields are complete
185
- */
186
- export declare function isExportReady(workspaceDir: string, sampleFingerprint: string): boolean;
187
- /**
188
- * List all export-ready records for a specific target model family.
189
- */
190
- export declare function listExportReadyRecords(workspaceDir: string, targetModelFamily?: string | null): NocturnalDatasetRecord[];
191
- /**
192
- * Get the artifact path for a dataset record.
193
- * Verifies the file exists before returning.
194
- */
195
- export declare function getArtifactPath(workspaceDir: string, sampleFingerprint: string): string | null;
196
- /**
197
- * Read the artifact file for a dataset record.
198
- * @throws Error if record not found, artifact file missing, or unreadable
199
- */
200
- export declare function readDatasetArtifact(workspaceDir: string, sampleFingerprint: string): NocturnalArtifact;
201
- /**
202
- * Count records by status for dashboard purposes.
203
- */
204
- export declare function getDatasetStats(workspaceDir: string): {
205
- total: number;
206
- pendingReview: number;
207
- approvedForTraining: number;
208
- rejected: number;
209
- superseded: number;
210
- exportReadyByFamily: Record<string, number>;
211
- };
212
- /**
213
- * Scan the samples directory and register any approved artifacts
214
- * that are not yet in the dataset registry.
215
- *
216
- * This is used for:
217
- * 1. Initial migration of Phase 2 artifacts to Phase 3 dataset
218
- * 2. Recovering from registry corruption
219
- *
220
- * @param workspaceDir - Workspace directory
221
- * @param targetModelFamily - Default target family for migrated samples
222
- * @returns Number of newly registered samples
223
- */
224
- export declare function migrateSampleArtifacts(workspaceDir: string, targetModelFamily?: string | null): number;
@@ -1,443 +0,0 @@
1
- /**
2
- * Nocturnal Dataset — Sample Lineage Store and Review State Registry
3
- * =================================================================
4
- *
5
- * PURPOSE: Establish each approved nocturnal sample as a first-class auditable
6
- * data asset with fingerprint, lineage, review state, and model family binding.
7
- *
8
- * ARCHITECTURE:
9
- * - Registry file: {stateDir}/.state/nocturnal/dataset-registry.json
10
- * - One JSON array of NocturnalDatasetRecord
11
- * - Each record is immutable except for reviewStatus and reviewReason
12
- * - sampleFingerprint is the primary key (deterministic: SHA-256 of artifactId+principleId+sessionId)
13
- *
14
- * RELATIONSHIP TO NOCTURNAL ARTIFACTS:
15
- * - Artifacts live in: .state/nocturnal/samples/{artifactId}.json
16
- * - Dataset records reference artifacts via artifactId and artifactPath
17
- * - Artifacts are NOT modified by dataset operations
18
- *
19
- * DESIGN CONSTRAINTS:
20
- * - No training run registry (Phase 4)
21
- * - No checkpoint registry (Phase 4)
22
- * - No worker routing changes
23
- * - No JSONL export (that's Task 3.2)
24
- * - Lineage is append-only for approved records
25
- * - reviewStatus transitions are the only state mutations allowed
26
- */
27
- import * as fs from 'fs';
28
- import * as path from 'path';
29
- import * as crypto from 'crypto';
30
- import { NocturnalPathResolver, resolveNocturnalDir } from './nocturnal-paths.js';
31
- import { withLock } from '../utils/file-lock.js';
32
- // ---------------------------------------------------------------------------
33
- // Fingerprint Generation
34
- // ---------------------------------------------------------------------------
35
- /**
36
- * Generate a deterministic sample fingerprint from an artifact.
37
- *
38
- * FINGERPRINT = SHA-256(artifactId || principleId || sessionId)
39
- *
40
- * The fingerprint is deterministic so the same sample always produces
41
- * the same fingerprint, enabling duplicate detection.
42
- */
43
- export function generateSampleFingerprint(artifactId, principleId, sessionId) {
44
- const input = `${artifactId}|${principleId}|${sessionId}`;
45
- return crypto.createHash('sha256').update(input, 'utf8').digest('hex');
46
- }
47
- /**
48
- * Generate a fingerprint from an existing NocturnalArtifact.
49
- */
50
- export function generateFingerprintFromArtifact(artifact) {
51
- return generateSampleFingerprint(artifact.artifactId, artifact.principleId, artifact.sessionId);
52
- }
53
- // ---------------------------------------------------------------------------
54
- // Registry Path
55
- // ---------------------------------------------------------------------------
56
- /**
57
- * Path to the dataset registry file.
58
- */
59
- function getRegistryPath(workspaceDir) {
60
- // Registry lives in .state/nocturnal/dataset-registry.json
61
- const nocturnalRoot = resolveNocturnalDir(workspaceDir, 'ROOT');
62
- return path.join(nocturnalRoot, 'dataset-registry.json');
63
- }
64
- /**
65
- * Ensure the registry directory exists.
66
- */
67
- function ensureRegistryDir(workspaceDir) {
68
- const registryPath = getRegistryPath(workspaceDir);
69
- const dir = path.dirname(registryPath);
70
- if (!fs.existsSync(dir)) {
71
- fs.mkdirSync(dir, { recursive: true });
72
- }
73
- }
74
- /**
75
- * Read the registry file. Returns empty array if missing.
76
- */
77
- function readRegistry(workspaceDir) {
78
- const registryPath = getRegistryPath(workspaceDir);
79
- if (!fs.existsSync(registryPath)) {
80
- return [];
81
- }
82
- try {
83
- const content = fs.readFileSync(registryPath, 'utf-8');
84
- return JSON.parse(content);
85
- }
86
- catch (err) {
87
- // Corrupted registry — fail-safe to empty array, but log the problem
88
- console.warn(`[nocturnal-dataset] Registry corrupted at ${registryPath}, recovering with empty state: ${String(err)}`);
89
- return [];
90
- }
91
- }
92
- /**
93
- * Write the registry file atomically (write-then-rename for atomicity).
94
- * Caller must hold the registry lock (via withRegistryLock).
95
- */
96
- function writeRegistry(workspaceDir, records) {
97
- ensureRegistryDir(workspaceDir);
98
- const registryPath = getRegistryPath(workspaceDir);
99
- const tmpPath = `${registryPath}.tmp`;
100
- fs.writeFileSync(tmpPath, JSON.stringify(records, null, 2), 'utf-8');
101
- fs.renameSync(tmpPath, registryPath);
102
- }
103
- // ---------------------------------------------------------------------------
104
- // Core Operations
105
- // ---------------------------------------------------------------------------
106
- /**
107
- * Execute a read-modify-write on the registry under an exclusive lock.
108
- * This prevents concurrent writers from racing on the same file.
109
- */
110
- function withRegistryLock(workspaceDir, fn) {
111
- const registryPath = getRegistryPath(workspaceDir);
112
- return withLock(registryPath, () => {
113
- const records = readRegistry(workspaceDir);
114
- return fn(records);
115
- });
116
- }
117
- /**
118
- * Register an approved nocturnal artifact in the dataset registry.
119
- *
120
- * DUPLICATE HANDLING:
121
- * - If a record with the same sampleFingerprint already exists, returns
122
- * existingRecord (isNew === false) instead of creating a duplicate.
123
- * - The original artifact file is never modified.
124
- *
125
- * @param workspaceDir - Workspace directory
126
- * @param artifact - The approved NocturnalArtifact
127
- * @param artifactPath - Absolute path where the artifact file is stored
128
- * @param targetModelFamily - Model family binding (required for export-ready)
129
- * @returns RegisterSampleResult
130
- */
131
- export function registerSample(workspaceDir, artifact, artifactPath, targetModelFamily = null) {
132
- const fingerprint = generateFingerprintFromArtifact(artifact);
133
- const now = new Date().toISOString();
134
- return withRegistryLock(workspaceDir, (records) => {
135
- const existing = records.find((r) => r.sampleFingerprint === fingerprint);
136
- if (existing) {
137
- return {
138
- record: existing,
139
- isNew: false,
140
- existingRecord: existing,
141
- };
142
- }
143
- const record = {
144
- sampleFingerprint: fingerprint,
145
- artifactId: artifact.artifactId,
146
- sessionId: artifact.sessionId,
147
- principleId: artifact.principleId,
148
- sourceSnapshotRef: artifact.sourceSnapshotRef,
149
- reviewStatus: 'pending_review',
150
- reviewReason: undefined,
151
- targetModelFamily,
152
- createdAt: now,
153
- updatedAt: now,
154
- artifactPath: path.normalize(artifactPath),
155
- };
156
- records.push(record);
157
- writeRegistry(workspaceDir, records);
158
- return { record, isNew: true };
159
- });
160
- }
161
- /**
162
- * Get a dataset record by fingerprint.
163
- */
164
- export function getDatasetRecord(workspaceDir, sampleFingerprint) {
165
- const records = readRegistry(workspaceDir);
166
- return records.find((r) => r.sampleFingerprint === sampleFingerprint) ?? null;
167
- }
168
- /**
169
- * Get a dataset record by artifactId.
170
- */
171
- export function getDatasetRecordByArtifactId(workspaceDir, artifactId) {
172
- const records = readRegistry(workspaceDir);
173
- return records.find((r) => r.artifactId === artifactId) ?? null;
174
- }
175
- /**
176
- * List dataset records with optional filtering.
177
- *
178
- * @param workspaceDir - Workspace directory
179
- * @param filter - Optional filter criteria
180
- * @returns Filtered records sorted by createdAt descending
181
- */
182
- export function listDatasetRecords(workspaceDir, filter) {
183
- let records = readRegistry(workspaceDir);
184
- if (!filter) {
185
- return records.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
186
- }
187
- // Filter by reviewStatus
188
- if (filter.reviewStatus !== undefined) {
189
- const statuses = Array.isArray(filter.reviewStatus)
190
- ? filter.reviewStatus
191
- : [filter.reviewStatus];
192
- records = records.filter((r) => statuses.includes(r.reviewStatus));
193
- }
194
- // Filter by targetModelFamily
195
- if (filter.targetModelFamily !== undefined) {
196
- if (filter.targetModelFamily === null) {
197
- // Include only null/unassigned
198
- records = records.filter((r) => r.targetModelFamily === null);
199
- }
200
- else {
201
- records = records.filter((r) => r.targetModelFamily === filter.targetModelFamily);
202
- }
203
- }
204
- // Filter export-ready only
205
- if (filter.exportReadyOnly === true) {
206
- records = records.filter((r) => {
207
- if (r.reviewStatus !== 'approved_for_training')
208
- return false;
209
- if (r.targetModelFamily === null)
210
- return false;
211
- // Verify artifact file exists
212
- if (!fs.existsSync(r.artifactPath))
213
- return false;
214
- return true;
215
- });
216
- }
217
- return records.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
218
- }
219
- /**
220
- * Valid review status transitions.
221
- *pending_review → approved_for_training | rejected | superseded
222
- * approved_for_training → superseded (if a better sample replaces it)
223
- * rejected → pending_review (if re-review is requested)
224
- * superseded → (terminal state, no transitions)
225
- */
226
- const VALID_TRANSITIONS = {
227
- pending_review: ['approved_for_training', 'rejected', 'superseded'],
228
- approved_for_training: ['superseded'],
229
- rejected: ['pending_review', 'superseded'],
230
- superseded: [], // terminal
231
- };
232
- /**
233
- * Update the review status of a dataset record.
234
- *
235
- * @param workspaceDir - Workspace directory
236
- * @param sampleFingerprint - The fingerprint of the record to update
237
- * @param newStatus - The new review status
238
- * @param reason - Optional reason (required for approved/rejected per spec)
239
- * @returns Updated record, or null if not found
240
- * @throws Error if transition is invalid
241
- */
242
- export function updateReviewStatus(workspaceDir, sampleFingerprint, newStatus, reason) {
243
- return withRegistryLock(workspaceDir, (records) => {
244
- const idx = records.findIndex((r) => r.sampleFingerprint === sampleFingerprint);
245
- if (idx === -1) {
246
- throw new Error(`Dataset record not found: ${sampleFingerprint}`);
247
- }
248
- const record = records[idx];
249
- // Validate transition
250
- const allowed = VALID_TRANSITIONS[record.reviewStatus];
251
- if (!allowed.includes(newStatus)) {
252
- throw new Error(`Invalid review status transition: ${record.reviewStatus} → ${newStatus}. ` +
253
- `Allowed transitions from ${record.reviewStatus}: ${allowed.join(', ') || 'none'}`);
254
- }
255
- // Enforce reason requirement for approved/rejected
256
- if ((newStatus === 'approved_for_training' || newStatus === 'rejected') &&
257
- !reason) {
258
- throw new Error(`reviewReason is required when transitioning to ${newStatus}`);
259
- }
260
- // Apply update
261
- records[idx] = {
262
- ...record,
263
- reviewStatus: newStatus,
264
- reviewReason: reason ?? record.reviewReason,
265
- updatedAt: new Date().toISOString(),
266
- };
267
- writeRegistry(workspaceDir, records);
268
- return records[idx];
269
- });
270
- }
271
- /**
272
- * Update the target model family binding.
273
- */
274
- export function updateTargetModelFamily(workspaceDir, sampleFingerprint, targetModelFamily) {
275
- return withRegistryLock(workspaceDir, (records) => {
276
- const idx = records.findIndex((r) => r.sampleFingerprint === sampleFingerprint);
277
- if (idx === -1) {
278
- throw new Error(`Dataset record not found: ${sampleFingerprint}`);
279
- }
280
- records[idx] = {
281
- ...records[idx],
282
- targetModelFamily,
283
- updatedAt: new Date().toISOString(),
284
- };
285
- writeRegistry(workspaceDir, records);
286
- return records[idx];
287
- });
288
- }
289
- /**
290
- * Check if a sample is export-ready.
291
- *
292
- * EXPORT-READY means:
293
- * - reviewStatus === 'approved_for_training'
294
- * - targetModelFamily !== null
295
- * - artifact file exists
296
- * - lineage fields are complete
297
- */
298
- export function isExportReady(workspaceDir, sampleFingerprint) {
299
- const record = getDatasetRecord(workspaceDir, sampleFingerprint);
300
- if (!record)
301
- return false;
302
- if (record.reviewStatus !== 'approved_for_training')
303
- return false;
304
- if (record.targetModelFamily === null)
305
- return false;
306
- if (!fs.existsSync(record.artifactPath))
307
- return false;
308
- return true;
309
- }
310
- /**
311
- * List all export-ready records for a specific target model family.
312
- */
313
- export function listExportReadyRecords(workspaceDir, targetModelFamily) {
314
- return listDatasetRecords(workspaceDir, {
315
- exportReadyOnly: true,
316
- targetModelFamily: targetModelFamily ?? undefined,
317
- });
318
- }
319
- /**
320
- * Get the artifact path for a dataset record.
321
- * Verifies the file exists before returning.
322
- */
323
- export function getArtifactPath(workspaceDir, sampleFingerprint) {
324
- const record = getDatasetRecord(workspaceDir, sampleFingerprint);
325
- if (!record)
326
- return null;
327
- if (!fs.existsSync(record.artifactPath))
328
- return null;
329
- return record.artifactPath;
330
- }
331
- /**
332
- * Read the artifact file for a dataset record.
333
- * @throws Error if record not found, artifact file missing, or unreadable
334
- */
335
- export function readDatasetArtifact(workspaceDir, sampleFingerprint) {
336
- const artifactPath = getArtifactPath(workspaceDir, sampleFingerprint);
337
- if (!artifactPath) {
338
- throw new Error(`Artifact file not found for sample ${sampleFingerprint}`);
339
- }
340
- const content = fs.readFileSync(artifactPath, 'utf-8');
341
- const parsed = JSON.parse(content);
342
- // Return only the NocturnalArtifact fields (not the extended sample record)
343
- return {
344
- artifactId: parsed.artifactId,
345
- sessionId: parsed.sessionId,
346
- principleId: parsed.principleId,
347
- sourceSnapshotRef: parsed.sourceSnapshotRef,
348
- badDecision: parsed.badDecision,
349
- betterDecision: parsed.betterDecision,
350
- rationale: parsed.rationale,
351
- createdAt: parsed.createdAt,
352
- };
353
- }
354
- /**
355
- * Count records by status for dashboard purposes.
356
- */
357
- export function getDatasetStats(workspaceDir) {
358
- const records = readRegistry(workspaceDir);
359
- const counts = {
360
- total: records.length,
361
- pendingReview: 0,
362
- approvedForTraining: 0,
363
- rejected: 0,
364
- superseded: 0,
365
- exportReadyByFamily: {},
366
- };
367
- for (const record of records) {
368
- switch (record.reviewStatus) {
369
- case 'pending_review':
370
- counts.pendingReview++;
371
- break;
372
- case 'approved_for_training':
373
- counts.approvedForTraining++;
374
- break;
375
- case 'rejected':
376
- counts.rejected++;
377
- break;
378
- case 'superseded':
379
- counts.superseded++;
380
- break;
381
- }
382
- // Count export-ready by family
383
- if (record.reviewStatus === 'approved_for_training' &&
384
- record.targetModelFamily !== null &&
385
- fs.existsSync(record.artifactPath)) {
386
- const family = record.targetModelFamily;
387
- counts.exportReadyByFamily[family] = (counts.exportReadyByFamily[family] || 0) + 1;
388
- }
389
- }
390
- return counts;
391
- }
392
- // ---------------------------------------------------------------------------
393
- // Auto-registration from persisted samples
394
- // ---------------------------------------------------------------------------
395
- /**
396
- * Scan the samples directory and register any approved artifacts
397
- * that are not yet in the dataset registry.
398
- *
399
- * This is used for:
400
- * 1. Initial migration of Phase 2 artifacts to Phase 3 dataset
401
- * 2. Recovering from registry corruption
402
- *
403
- * @param workspaceDir - Workspace directory
404
- * @param targetModelFamily - Default target family for migrated samples
405
- * @returns Number of newly registered samples
406
- */
407
- export function migrateSampleArtifacts(workspaceDir, targetModelFamily = null) {
408
- const samplePaths = NocturnalPathResolver.listSamples(workspaceDir);
409
- let newCount = 0;
410
- for (const samplePath of samplePaths) {
411
- try {
412
- const content = fs.readFileSync(samplePath, 'utf-8');
413
- const sample = JSON.parse(content);
414
- // Only process approved samples
415
- if (sample.status !== 'approved')
416
- continue;
417
- if (!sample.artifactId || !sample.sessionId || !sample.principleId)
418
- continue;
419
- // Skip if already in registry
420
- const fingerprint = generateSampleFingerprint(sample.artifactId, sample.principleId, sample.sessionId);
421
- const existing = getDatasetRecord(workspaceDir, fingerprint);
422
- if (existing)
423
- continue;
424
- // Register the artifact
425
- const artifact = {
426
- artifactId: sample.artifactId,
427
- sessionId: sample.sessionId,
428
- principleId: sample.principleId,
429
- sourceSnapshotRef: sample.sourceSnapshotRef || '',
430
- badDecision: sample.badDecision || '',
431
- betterDecision: sample.betterDecision || '',
432
- rationale: sample.rationale || '',
433
- createdAt: sample.createdAt || new Date().toISOString(),
434
- };
435
- registerSample(workspaceDir, artifact, samplePath, targetModelFamily);
436
- newCount++;
437
- }
438
- catch {
439
- // Skip malformed files
440
- }
441
- }
442
- return newCount;
443
- }