onto-mcp 0.3.2 → 0.4.0

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 (300) hide show
  1. package/.onto/processes/reconstruct/actionable-ontology-seed-recomposition-design.md +447 -0
  2. package/.onto/processes/reconstruct/foundry-style-ontology-seed-contract.md +934 -0
  3. package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +303 -725
  4. package/.onto/processes/reconstruct/reconstruct-contract-registry.yaml +1645 -0
  5. package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +26 -22
  6. package/.onto/processes/reconstruct/source-profile-contract.md +49 -23
  7. package/.onto/processes/reconstruct/source-profiles/code.md +6 -3
  8. package/.onto/processes/reconstruct/source-profiles/database.md +5 -2
  9. package/.onto/processes/reconstruct/source-profiles/document.md +5 -2
  10. package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +5 -4
  11. package/.onto/processes/review/review-execution-ux-contract.md +40 -0
  12. package/.onto/processes/shared/pipeline-execution-ledger-contract.md +26 -10
  13. package/.onto/processes/shared/target-material-kind-contract.md +29 -16
  14. package/AGENTS.md +6 -4
  15. package/README.md +135 -76
  16. package/dist/cli.js +8 -8
  17. package/dist/core-api/reconstruct-api.js +117 -31
  18. package/dist/core-api/review-api.js +47 -0
  19. package/dist/core-runtime/cli/codex-review-unit-executor.js +39 -2
  20. package/dist/core-runtime/cli/complete-review-session.js +2 -2
  21. package/dist/core-runtime/cli/mock-review-unit-executor.js +1 -1
  22. package/dist/core-runtime/cli/review-invoke.js +9 -9
  23. package/dist/core-runtime/cli/run-review-prompt-execution.js +39 -5
  24. package/dist/core-runtime/cli/spawn-watcher.js +266 -47
  25. package/dist/core-runtime/cli/start-review-session.js +3 -3
  26. package/dist/core-runtime/llm/llm-caller.js +11 -0
  27. package/dist/core-runtime/llm/llm-tool-loop.js +2 -0
  28. package/dist/core-runtime/observability/runtime-stream-observation.js +118 -0
  29. package/dist/core-runtime/onboard/cli-host.js +149 -0
  30. package/dist/core-runtime/onboard/host-target.js +22 -0
  31. package/dist/core-runtime/onboard/json-config-host.js +122 -0
  32. package/dist/core-runtime/onboard/path-scan.js +26 -0
  33. package/dist/core-runtime/onboard/prompt.js +51 -0
  34. package/dist/core-runtime/onboard/register.js +207 -0
  35. package/dist/core-runtime/onboard/types.js +27 -0
  36. package/dist/core-runtime/reconstruct/actionable-seed-validation.js +1777 -0
  37. package/dist/core-runtime/reconstruct/artifact-types.js +10 -4
  38. package/dist/core-runtime/reconstruct/contract-registry.js +623 -0
  39. package/dist/core-runtime/reconstruct/domain-id.js +10 -0
  40. package/dist/core-runtime/reconstruct/governing-snapshot.js +716 -0
  41. package/dist/core-runtime/reconstruct/material-profile-validation.js +191 -0
  42. package/dist/core-runtime/reconstruct/materialize-preparation.js +49 -11
  43. package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +269 -79
  44. package/dist/core-runtime/reconstruct/post-seed-validation.js +1194 -51
  45. package/dist/core-runtime/reconstruct/record.js +104 -20
  46. package/dist/core-runtime/reconstruct/run.js +2107 -413
  47. package/dist/core-runtime/reconstruct/seed-claim-projections.js +268 -0
  48. package/dist/core-runtime/reconstruct/source-profiles.js +93 -4
  49. package/dist/core-runtime/reconstruct/terminal-validation.js +807 -0
  50. package/dist/core-runtime/review/review-invocation-runner.js +4 -4
  51. package/dist/mcp/server.js +110 -38
  52. package/dist/mcp/tool-schemas.js +20 -6
  53. package/package.json +8 -17
  54. package/scripts/onto-review-watch.sh +486 -0
  55. package/scripts/onto-runtime-watch.sh +122 -0
  56. package/scripts/postinstall-hint.js +22 -0
  57. package/.onto/processes/reconstruct/top-level-concept-discovery-contract.md +0 -387
  58. package/dist/core-runtime/cli/bootstrap-review-binding.js +0 -186
  59. package/dist/core-runtime/cli/codex-nested-dispatch.test.js +0 -390
  60. package/dist/core-runtime/cli/codex-nested-teamlead-executor.test.js +0 -335
  61. package/dist/core-runtime/cli/coordinator-helpers.js +0 -583
  62. package/dist/core-runtime/cli/coordinator-state-machine-deliberation.test.js +0 -167
  63. package/dist/core-runtime/cli/coordinator-state-machine.js +0 -794
  64. package/dist/core-runtime/cli/e2e-codex-multi-agent-fixes.test.js +0 -615
  65. package/dist/core-runtime/cli/e2e-start-review-session.test.js +0 -312
  66. package/dist/core-runtime/cli/health.js +0 -44
  67. package/dist/core-runtime/cli/inline-http-review-unit-executor.test.js +0 -567
  68. package/dist/core-runtime/cli/materialize-review-execution-preparation.js +0 -104
  69. package/dist/core-runtime/cli/migrate-session-roots.js +0 -118
  70. package/dist/core-runtime/cli/repo-layout-migration-replace.smoke.test.js +0 -106
  71. package/dist/core-runtime/cli/review-invoke-auto-resolution.test.js +0 -268
  72. package/dist/core-runtime/cli/review-invoke-coordinator-topology.test.js +0 -136
  73. package/dist/core-runtime/cli/review-invoke-resolver-caching.test.js +0 -201
  74. package/dist/core-runtime/cli/review-invoke-topology-dispatch.test.js +0 -192
  75. package/dist/core-runtime/cli/session-root-guard.js +0 -168
  76. package/dist/core-runtime/cli/spawn-watcher.test.js +0 -457
  77. package/dist/core-runtime/cli/strip-wrapping-code-fence.test.js +0 -79
  78. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.js +0 -412
  79. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.test.js +0 -351
  80. package/dist/core-runtime/cli/topology-executor-mapping.js +0 -139
  81. package/dist/core-runtime/cli/topology-executor-mapping.test.js +0 -173
  82. package/dist/core-runtime/cli/write-review-interpretation.js +0 -81
  83. package/dist/core-runtime/config/onto-config-cli.js +0 -278
  84. package/dist/core-runtime/config/onto-config-key-path.js +0 -288
  85. package/dist/core-runtime/config/onto-config-key-path.test.js +0 -195
  86. package/dist/core-runtime/config/onto-config-preview.js +0 -108
  87. package/dist/core-runtime/config/onto-config-preview.test.js +0 -132
  88. package/dist/core-runtime/discovery/config-chain.js +0 -118
  89. package/dist/core-runtime/discovery/config-chain.test.js +0 -103
  90. package/dist/core-runtime/discovery/config-profile.js +0 -199
  91. package/dist/core-runtime/discovery/config-profile.test.js +0 -233
  92. package/dist/core-runtime/discovery/host-detection.test.js +0 -186
  93. package/dist/core-runtime/discovery/installation-paths.test.js +0 -65
  94. package/dist/core-runtime/discovery/lens-registry.test.js +0 -81
  95. package/dist/core-runtime/discovery/path-normalization.test.js +0 -22
  96. package/dist/core-runtime/discovery/plugin-path.js +0 -72
  97. package/dist/core-runtime/discovery/plugin-path.test.js +0 -95
  98. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.js +0 -344
  99. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.test.js +0 -915
  100. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.js +0 -564
  101. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.test.js +0 -708
  102. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.js +0 -165
  103. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.test.js +0 -227
  104. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.js +0 -59
  105. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.test.js +0 -205
  106. package/dist/core-runtime/evolve/adapters/methodology/adapter.js +0 -16
  107. package/dist/core-runtime/evolve/adapters/methodology/adapter.test.js +0 -9
  108. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.js +0 -298
  109. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.test.js +0 -70
  110. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.js +0 -46
  111. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.test.js +0 -73
  112. package/dist/core-runtime/evolve/adapters/registry.js +0 -47
  113. package/dist/core-runtime/evolve/adapters/registry.test.js +0 -67
  114. package/dist/core-runtime/evolve/cli.js +0 -256
  115. package/dist/core-runtime/evolve/commands/align.js +0 -194
  116. package/dist/core-runtime/evolve/commands/align.test.js +0 -82
  117. package/dist/core-runtime/evolve/commands/apply.js +0 -161
  118. package/dist/core-runtime/evolve/commands/apply.test.js +0 -138
  119. package/dist/core-runtime/evolve/commands/close.js +0 -39
  120. package/dist/core-runtime/evolve/commands/close.test.js +0 -99
  121. package/dist/core-runtime/evolve/commands/defer.js +0 -40
  122. package/dist/core-runtime/evolve/commands/defer.test.js +0 -134
  123. package/dist/core-runtime/evolve/commands/draft.js +0 -323
  124. package/dist/core-runtime/evolve/commands/draft.test.js +0 -178
  125. package/dist/core-runtime/evolve/commands/e2e-evolve-full-cycle.test.js +0 -208
  126. package/dist/core-runtime/evolve/commands/error-messages.js +0 -125
  127. package/dist/core-runtime/evolve/commands/error-messages.test.js +0 -167
  128. package/dist/core-runtime/evolve/commands/propose-align.js +0 -222
  129. package/dist/core-runtime/evolve/commands/propose-align.test.js +0 -136
  130. package/dist/core-runtime/evolve/commands/reconstruct.js +0 -330
  131. package/dist/core-runtime/evolve/commands/reconstruct.test.js +0 -278
  132. package/dist/core-runtime/evolve/commands/shared.js +0 -22
  133. package/dist/core-runtime/evolve/commands/stale-check.js +0 -103
  134. package/dist/core-runtime/evolve/commands/stale-check.test.js +0 -84
  135. package/dist/core-runtime/evolve/commands/start.js +0 -887
  136. package/dist/core-runtime/evolve/commands/start.test.js +0 -396
  137. package/dist/core-runtime/evolve/config/project-config.js +0 -99
  138. package/dist/core-runtime/evolve/config/project-config.test.js +0 -170
  139. package/dist/core-runtime/evolve/renderers/align-packet.js +0 -280
  140. package/dist/core-runtime/evolve/renderers/align-packet.test.js +0 -332
  141. package/dist/core-runtime/evolve/renderers/draft-packet.js +0 -303
  142. package/dist/core-runtime/evolve/renderers/draft-packet.test.js +0 -377
  143. package/dist/core-runtime/evolve/renderers/format.js +0 -5
  144. package/dist/core-runtime/evolve/renderers/scope-md.js +0 -237
  145. package/dist/core-runtime/evolve/renderers/scope-md.test.js +0 -306
  146. package/dist/core-runtime/govern/cli.js +0 -369
  147. package/dist/core-runtime/govern/cli.test.js +0 -314
  148. package/dist/core-runtime/govern/drift-engine.js +0 -103
  149. package/dist/core-runtime/govern/drift-engine.test.js +0 -319
  150. package/dist/core-runtime/govern/promote-principle.js +0 -206
  151. package/dist/core-runtime/govern/promote-principle.test.js +0 -368
  152. package/dist/core-runtime/govern/queue.js +0 -81
  153. package/dist/core-runtime/govern/types.js +0 -16
  154. package/dist/core-runtime/install/cli.js +0 -530
  155. package/dist/core-runtime/install/detect.js +0 -128
  156. package/dist/core-runtime/install/detect.test.js +0 -155
  157. package/dist/core-runtime/install/gitignore-update.js +0 -74
  158. package/dist/core-runtime/install/gitignore-update.test.js +0 -64
  159. package/dist/core-runtime/install/install-integration.test.js +0 -373
  160. package/dist/core-runtime/install/prompts.js +0 -389
  161. package/dist/core-runtime/install/prompts.test.js +0 -293
  162. package/dist/core-runtime/install/types.js +0 -26
  163. package/dist/core-runtime/install/validation.js +0 -295
  164. package/dist/core-runtime/install/validation.test.js +0 -313
  165. package/dist/core-runtime/install/writer.js +0 -254
  166. package/dist/core-runtime/install/writer.test.js +0 -218
  167. package/dist/core-runtime/learning/extractor.js +0 -461
  168. package/dist/core-runtime/learning/feedback.js +0 -179
  169. package/dist/core-runtime/learning/health-report.js +0 -165
  170. package/dist/core-runtime/learning/health-report.test.js +0 -169
  171. package/dist/core-runtime/learning/loader.js +0 -388
  172. package/dist/core-runtime/learning/loader.test.js +0 -102
  173. package/dist/core-runtime/learning/promote/apply-state.js +0 -240
  174. package/dist/core-runtime/learning/promote/audit-obligation.js +0 -195
  175. package/dist/core-runtime/learning/promote/collector.js +0 -432
  176. package/dist/core-runtime/learning/promote/degraded-state.js +0 -125
  177. package/dist/core-runtime/learning/promote/domain-doc-proposer.js +0 -166
  178. package/dist/core-runtime/learning/promote/e2e-promote.test.js +0 -6385
  179. package/dist/core-runtime/learning/promote/health-snapshot.js +0 -150
  180. package/dist/core-runtime/learning/promote/insight-reclassifier.js +0 -544
  181. package/dist/core-runtime/learning/promote/judgment-auditor.js +0 -517
  182. package/dist/core-runtime/learning/promote/panel-reviewer.js +0 -1158
  183. package/dist/core-runtime/learning/promote/promote-executor.js +0 -1675
  184. package/dist/core-runtime/learning/promote/promoter.js +0 -307
  185. package/dist/core-runtime/learning/promote/retirement.js +0 -122
  186. package/dist/core-runtime/learning/promote/types.js +0 -23
  187. package/dist/core-runtime/learning/prompt-sections.js +0 -51
  188. package/dist/core-runtime/learning/shared/artifact-registry-init.js +0 -45
  189. package/dist/core-runtime/learning/shared/artifact-registry.js +0 -254
  190. package/dist/core-runtime/learning/shared/audit-obligation-kernel.js +0 -73
  191. package/dist/core-runtime/learning/shared/audit-state.js +0 -99
  192. package/dist/core-runtime/learning/shared/duplicate-check.js +0 -28
  193. package/dist/core-runtime/learning/shared/llm-caller.js +0 -831
  194. package/dist/core-runtime/learning/shared/llm-caller.test.js +0 -601
  195. package/dist/core-runtime/learning/shared/llm-tool-loop.js +0 -393
  196. package/dist/core-runtime/learning/shared/mode.js +0 -25
  197. package/dist/core-runtime/learning/shared/paths.js +0 -84
  198. package/dist/core-runtime/learning/shared/paths.test.js +0 -79
  199. package/dist/core-runtime/learning/shared/patterns.js +0 -37
  200. package/dist/core-runtime/learning/shared/recoverability.js +0 -355
  201. package/dist/core-runtime/learning/shared/recovery-context.js +0 -374
  202. package/dist/core-runtime/learning/shared/scope.js +0 -1
  203. package/dist/core-runtime/learning/shared/semantic-classifier.js +0 -94
  204. package/dist/core-runtime/learning/shared/specs/apply-execution-state-spec.js +0 -42
  205. package/dist/core-runtime/learning/shared/specs/audit-state-spec.js +0 -37
  206. package/dist/core-runtime/learning/shared/specs/backup-metadata-spec.js +0 -39
  207. package/dist/core-runtime/learning/shared/specs/emergency-log-spec.js +0 -41
  208. package/dist/core-runtime/learning/shared/specs/layout-version-spec.js +0 -38
  209. package/dist/core-runtime/learning/shared/specs/promote-decisions-spec.js +0 -43
  210. package/dist/core-runtime/learning/shared/specs/promote-report-spec.js +0 -113
  211. package/dist/core-runtime/learning/shared/specs/prune-log-spec.js +0 -36
  212. package/dist/core-runtime/learning/shared/specs/recovery-resolution-spec.js +0 -48
  213. package/dist/core-runtime/learning/shared/specs/restore-manifest-spec.js +0 -43
  214. package/dist/core-runtime/learning/shared/specs/spec-helpers.js +0 -64
  215. package/dist/core-runtime/learning/usage-tracker.js +0 -190
  216. package/dist/core-runtime/learning/usage-tracker.test.js +0 -176
  217. package/dist/core-runtime/onboard/detect-review-axes.js +0 -122
  218. package/dist/core-runtime/onboard/detect-review-axes.test.js +0 -127
  219. package/dist/core-runtime/onboard/write-review-block.js +0 -188
  220. package/dist/core-runtime/onboard/write-review-block.test.js +0 -240
  221. package/dist/core-runtime/readers/brownfield-builder.js +0 -150
  222. package/dist/core-runtime/readers/brownfield-builder.test.js +0 -136
  223. package/dist/core-runtime/readers/code-chunk-collector.js +0 -53
  224. package/dist/core-runtime/readers/code-chunk-collector.test.js +0 -136
  225. package/dist/core-runtime/readers/file-utils.js +0 -240
  226. package/dist/core-runtime/readers/file-utils.test.js +0 -146
  227. package/dist/core-runtime/readers/lexicon-citation-check.js +0 -93
  228. package/dist/core-runtime/readers/lexicon-citation-check.test.js +0 -77
  229. package/dist/core-runtime/readers/mcp-figma.js +0 -30
  230. package/dist/core-runtime/readers/mcp-figma.test.js +0 -82
  231. package/dist/core-runtime/readers/mcp-generic.js +0 -31
  232. package/dist/core-runtime/readers/mcp-generic.test.js +0 -76
  233. package/dist/core-runtime/readers/ontology-index.js +0 -148
  234. package/dist/core-runtime/readers/ontology-index.test.js +0 -245
  235. package/dist/core-runtime/readers/ontology-query.js +0 -168
  236. package/dist/core-runtime/readers/ontology-query.test.js +0 -311
  237. package/dist/core-runtime/readers/ontology-resolve.js +0 -48
  238. package/dist/core-runtime/readers/ontology-resolve.test.js +0 -48
  239. package/dist/core-runtime/readers/patterns/index.js +0 -7
  240. package/dist/core-runtime/readers/review-log.js +0 -213
  241. package/dist/core-runtime/readers/review-log.test.js +0 -313
  242. package/dist/core-runtime/readers/scan-local.js +0 -102
  243. package/dist/core-runtime/readers/scan-local.test.js +0 -102
  244. package/dist/core-runtime/readers/scan-tarball.js +0 -121
  245. package/dist/core-runtime/readers/scan-tarball.test.js +0 -283
  246. package/dist/core-runtime/readers/scan-vault.js +0 -34
  247. package/dist/core-runtime/readers/scan-vault.test.js +0 -81
  248. package/dist/core-runtime/readers/types.js +0 -42
  249. package/dist/core-runtime/readers/types.test.js +0 -94
  250. package/dist/core-runtime/readers/viewpoint-collectors.js +0 -229
  251. package/dist/core-runtime/reconstruct/seed-candidate-validation.js +0 -385
  252. package/dist/core-runtime/review/citation-audit.test.js +0 -165
  253. package/dist/core-runtime/review/execution-plan-resolver.js +0 -247
  254. package/dist/core-runtime/review/execution-plan-resolver.test.js +0 -243
  255. package/dist/core-runtime/review/execution-topology-resolver-axis-first.test.js +0 -246
  256. package/dist/core-runtime/review/execution-topology-resolver.js +0 -401
  257. package/dist/core-runtime/review/execution-topology-resolver.test.js +0 -315
  258. package/dist/core-runtime/review/inline-context-embedder.test.js +0 -154
  259. package/dist/core-runtime/review/legacy-mode-policy.js +0 -88
  260. package/dist/core-runtime/review/materializers-effort-persist.test.js +0 -79
  261. package/dist/core-runtime/review/ontology-path-classifier.js +0 -179
  262. package/dist/core-runtime/review/ontology-path-classifier.test.js +0 -216
  263. package/dist/core-runtime/review/packet-boundary-policy.test.js +0 -107
  264. package/dist/core-runtime/review/participating-lens-paths.test.js +0 -73
  265. package/dist/core-runtime/review/review-config-legacy-translate.js +0 -244
  266. package/dist/core-runtime/review/review-config-legacy-translate.test.js +0 -161
  267. package/dist/core-runtime/review/review-config-validator.js +0 -289
  268. package/dist/core-runtime/review/review-config-validator.test.js +0 -236
  269. package/dist/core-runtime/review/shape-pipeline-audit.test.js +0 -311
  270. package/dist/core-runtime/review/shape-to-topology-id.js +0 -117
  271. package/dist/core-runtime/review/shape-to-topology-id.test.js +0 -132
  272. package/dist/core-runtime/review/topology-shape-derivation.js +0 -155
  273. package/dist/core-runtime/review/topology-shape-derivation.test.js +0 -195
  274. package/dist/core-runtime/scope-runtime/constants.js +0 -12
  275. package/dist/core-runtime/scope-runtime/constraint-pool.js +0 -166
  276. package/dist/core-runtime/scope-runtime/constraint-pool.test.js +0 -674
  277. package/dist/core-runtime/scope-runtime/domain-validation-log.js +0 -135
  278. package/dist/core-runtime/scope-runtime/domain-validation-log.test.js +0 -156
  279. package/dist/core-runtime/scope-runtime/eval-persistence.js +0 -65
  280. package/dist/core-runtime/scope-runtime/eval-persistence.test.js +0 -84
  281. package/dist/core-runtime/scope-runtime/event-pipeline.js +0 -64
  282. package/dist/core-runtime/scope-runtime/event-pipeline.test.js +0 -450
  283. package/dist/core-runtime/scope-runtime/event-store.js +0 -39
  284. package/dist/core-runtime/scope-runtime/event-store.test.js +0 -95
  285. package/dist/core-runtime/scope-runtime/gate-guard.js +0 -348
  286. package/dist/core-runtime/scope-runtime/gate-guard.test.js +0 -1047
  287. package/dist/core-runtime/scope-runtime/hash.js +0 -4
  288. package/dist/core-runtime/scope-runtime/hash.test.js +0 -33
  289. package/dist/core-runtime/scope-runtime/id.js +0 -4
  290. package/dist/core-runtime/scope-runtime/id.test.js +0 -17
  291. package/dist/core-runtime/scope-runtime/reducer.js +0 -297
  292. package/dist/core-runtime/scope-runtime/reducer.test.js +0 -759
  293. package/dist/core-runtime/scope-runtime/scope-manager.js +0 -161
  294. package/dist/core-runtime/scope-runtime/state-machine.js +0 -309
  295. package/dist/core-runtime/scope-runtime/state-machine.test.js +0 -704
  296. package/dist/core-runtime/scope-runtime/types.js +0 -116
  297. package/dist/core-runtime/scope-runtime/types.test.js +0 -69
  298. package/dist/core-runtime/translate/render-for-user.js +0 -169
  299. package/dist/core-runtime/translate/render-for-user.test.js +0 -122
  300. package/dist/providers/capability-contract.js +0 -1
@@ -1,374 +0,0 @@
1
- /**
2
- * Recovery context — DD-22 + DD-23.
3
- *
4
- * Design authority:
5
- * - learn-phase3-design-v9.md DD-22 (canonical attempt selection, source_kind enum)
6
- * - learn-phase3-design-v9.md DD-23 (RecoveryResolution canonical seat)
7
- * - learn-phase3-design-v8.md DD-22 (attempt_id lifecycle, conflict policy)
8
- * - learn-phase3-design-v7.md DD-22 (single consumer + freshness)
9
- *
10
- * Responsibility:
11
- * - Gather recovery sources (in-band ApplyExecutionState, out-of-band
12
- * emergency log, checkpoint manifest) for a given session
13
- * - Resolve which is the canonical truth using attempt_id + generation
14
- * - Surface manual escalation when multiple attempt_ids conflict and the
15
- * operator has not yet recorded a RecoveryResolution
16
- * - Persist operator decisions (DD-23) so subsequent --resume runs respect them
17
- */
18
- import fs from "node:fs";
19
- import path from "node:path";
20
- import { REGISTRY } from "./artifact-registry.js";
21
- import { BACKUP_ROOT } from "./recoverability.js";
22
- /** v8 axiology default — fail-close for canonical knowledge mutation. */
23
- export const DEFAULT_RECOVERY_POLICY = {
24
- cross_attempt_conflict: "manual_escalation",
25
- };
26
- // ---------------------------------------------------------------------------
27
- // Path helpers
28
- // ---------------------------------------------------------------------------
29
- export function getSessionPromoteRoot(projectRoot, sessionId) {
30
- return path.join(projectRoot, ".onto", "sessions", "promote", sessionId);
31
- }
32
- export function getApplyStatePath(projectRoot, sessionId) {
33
- return path.join(getSessionPromoteRoot(projectRoot, sessionId), "promote-execution-result.json");
34
- }
35
- export function getRecoveryResolutionPath(projectRoot, sessionId) {
36
- return path.join(getSessionPromoteRoot(projectRoot, sessionId), "recovery-resolution.yaml");
37
- }
38
- export function getCheckpointDir(sessionId) {
39
- return path.join(BACKUP_ROOT, sessionId);
40
- }
41
- export function getCheckpointManifestPath(sessionId) {
42
- return path.join(getCheckpointDir(sessionId), "restore-manifest.yaml");
43
- }
44
- export function getCheckpointMetadataPath(sessionId) {
45
- return path.join(getCheckpointDir(sessionId), "backup-metadata.yaml");
46
- }
47
- export const EMERGENCY_LOG_PATH = path.join(
48
- // ~/.onto/emergency-log.jsonl. We resolve via process.env.HOME so callers
49
- // running under tmpdir-based tests can override the home directory.
50
- process.env.HOME ?? "", ".onto", "emergency-log.jsonl");
51
- // ---------------------------------------------------------------------------
52
- // Source gathering
53
- // ---------------------------------------------------------------------------
54
- function getFreshness(source) {
55
- return source.freshness;
56
- }
57
- function readEmergencyLogEntries(sessionId, logPath) {
58
- if (!fs.existsSync(logPath))
59
- return [];
60
- const content = fs.readFileSync(logPath, "utf8");
61
- const lines = content.split("\n").filter((l) => l.trim().length > 0);
62
- const entries = [];
63
- for (const line of lines) {
64
- try {
65
- const parsed = JSON.parse(line);
66
- if (parsed.session_id === sessionId && parsed.schema_version === "1") {
67
- entries.push(parsed);
68
- }
69
- }
70
- catch {
71
- // Malformed line — skip. Real Phase 3 read protocol surfaces this via
72
- // the proper EmergencyLogReadResult; this gather-helper is best-effort.
73
- }
74
- }
75
- return entries;
76
- }
77
- function reconstructCheckpointFromManifest(manifest, metadata) {
78
- return {
79
- schema_version: "1",
80
- session_id: manifest.session_id,
81
- created_at: manifest.created_at,
82
- manifest_path: getCheckpointManifestPath(manifest.session_id),
83
- backups: manifest.backups,
84
- total_bytes: metadata.total_bytes,
85
- protected: metadata.protected,
86
- protection_reason: metadata.protection_reason,
87
- attempt_id: manifest.attempt_id,
88
- generation: manifest.generation,
89
- };
90
- }
91
- export async function gatherRecoveryContext(sessionId, projectRoot) {
92
- const context = {
93
- session_id: sessionId,
94
- gathered_at: new Date().toISOString(),
95
- apply_state: null,
96
- emergency_log: null,
97
- checkpoint_manifest: null,
98
- };
99
- // 1. apply_state (in-band)
100
- const applyStatePath = getApplyStatePath(projectRoot, sessionId);
101
- if (fs.existsSync(applyStatePath)) {
102
- try {
103
- const state = REGISTRY.loadFromFile("apply_execution_state", applyStatePath);
104
- context.apply_state = {
105
- kind: "apply_state",
106
- state,
107
- freshness: {
108
- attempt_id: state.attempt_id,
109
- generation: state.generation,
110
- source_recorded_at: state.last_updated_at,
111
- source_kind: "apply_state",
112
- },
113
- artifact_path: applyStatePath,
114
- };
115
- }
116
- catch {
117
- // Load failure — leave null. The recovery resolver will treat it as
118
- // missing and fall back to other sources.
119
- }
120
- }
121
- // 2. emergency_log (out-of-band)
122
- const emergencyEntries = readEmergencyLogEntries(sessionId, EMERGENCY_LOG_PATH);
123
- if (emergencyEntries.length > 0) {
124
- const sorted = [...emergencyEntries].sort((a, b) => b.generation - a.generation);
125
- const latest = sorted[0];
126
- context.emergency_log = {
127
- kind: "emergency_log",
128
- entries: sorted,
129
- latest_entry: latest,
130
- freshness: {
131
- attempt_id: latest.attempt_id,
132
- generation: latest.generation,
133
- source_recorded_at: latest.written_at,
134
- source_kind: "emergency_log",
135
- },
136
- log_path: EMERGENCY_LOG_PATH,
137
- };
138
- }
139
- // 3. checkpoint_manifest
140
- const manifestPath = getCheckpointManifestPath(sessionId);
141
- const metadataPath = getCheckpointMetadataPath(sessionId);
142
- if (fs.existsSync(manifestPath) && fs.existsSync(metadataPath)) {
143
- try {
144
- const manifest = REGISTRY.loadFromFile("restore_manifest", manifestPath);
145
- const metadata = REGISTRY.loadFromFile("backup_metadata", metadataPath);
146
- const checkpoint = reconstructCheckpointFromManifest(manifest, metadata);
147
- context.checkpoint_manifest = {
148
- kind: "checkpoint_manifest",
149
- manifest,
150
- checkpoint,
151
- freshness: {
152
- attempt_id: manifest.attempt_id,
153
- generation: manifest.generation,
154
- source_recorded_at: manifest.created_at,
155
- source_kind: "checkpoint_manifest",
156
- },
157
- };
158
- }
159
- catch {
160
- // Manifest corrupted: skip. Operator must intervene manually.
161
- }
162
- }
163
- return context;
164
- }
165
- // ---------------------------------------------------------------------------
166
- // DD-23 recovery resolution persistence
167
- // ---------------------------------------------------------------------------
168
- export function loadRecoveryResolution(projectRoot, sessionId) {
169
- const p = getRecoveryResolutionPath(projectRoot, sessionId);
170
- if (!fs.existsSync(p))
171
- return null;
172
- return REGISTRY.loadFromFile("recovery_resolution", p);
173
- }
174
- /**
175
- * NQ-21: append-only resolution history.
176
- *
177
- * If a prior recovery-resolution.yaml exists for this session, the new entry
178
- * is APPENDED to its resolution_history array and the top-level fields are
179
- * updated to reflect the latest decision. Older history entries are
180
- * preserved verbatim — the audit trail must show every reversal and reason.
181
- *
182
- * If no prior file exists, the new entry becomes the sole history entry.
183
- *
184
- * The caller passes a RecoveryResolution where the top-level fields describe
185
- * the new decision and resolution_history contains exactly one entry (the
186
- * new decision). saveRecoveryResolution() expands resolution_history with
187
- * the prior entries when applicable.
188
- */
189
- export function saveRecoveryResolution(projectRoot, resolution) {
190
- // m-2 fix: validate input contract before touching disk. Empty
191
- // resolution_history would crash on the [length-1] access below; throw
192
- // explicitly so the caller knows their input is malformed.
193
- if (resolution.resolution_history.length === 0) {
194
- throw new Error(`saveRecoveryResolution: resolution_history must contain at least one entry ` +
195
- `(got 0). The caller is expected to pass a single-entry history; merging ` +
196
- `with prior entries is handled here.`);
197
- }
198
- // N-3 acknowledged: this load → merge → save sequence is not atomic across
199
- // processes. Two concurrent recovery-resolution writes
200
- // for the same session could lose updates. Phase 3 is single-process per
201
- // session by design; cross-process coordination is a follow-up requiring a
202
- // file lock or rename-temp pattern. Documented as a known limitation.
203
- const p = getRecoveryResolutionPath(projectRoot, resolution.session_id);
204
- // Load prior history if any. We probe via fs.existsSync to distinguish
205
- // "first decision" from "load failed" — load failure should propagate.
206
- let priorHistory = [];
207
- if (fs.existsSync(p)) {
208
- const prior = REGISTRY.loadFromFile("recovery_resolution", p);
209
- priorHistory = prior.resolution_history;
210
- }
211
- // The caller passes a single-entry resolution_history with the new decision.
212
- // We expand it with the prior entries during merge. Multi-entry input is
213
- // rejected by the length check above so the LAST-entry fallback is no longer
214
- // needed.
215
- const newEntry = resolution.resolution_history[resolution.resolution_history.length - 1];
216
- const merged = {
217
- schema_version: "1",
218
- session_id: resolution.session_id,
219
- resolved_at: newEntry.resolved_at,
220
- resolved_by: newEntry.resolved_by,
221
- resolution_method: newEntry.resolution_method,
222
- selected_attempt_id: newEntry.selected_attempt_id,
223
- selected_attempt_reason: newEntry.selected_attempt_reason,
224
- all_attempts_at_resolution_time: newEntry.all_attempts_at_resolution_time,
225
- ...(newEntry.operator_note !== undefined
226
- ? { operator_note: newEntry.operator_note }
227
- : {}),
228
- resolution_history: [...priorHistory, newEntry],
229
- };
230
- REGISTRY.saveToFile("recovery_resolution", p, merged);
231
- }
232
- // ---------------------------------------------------------------------------
233
- // Truth resolution
234
- // ---------------------------------------------------------------------------
235
- function collectAllSources(context) {
236
- const sources = [];
237
- if (context.apply_state)
238
- sources.push(context.apply_state);
239
- if (context.emergency_log)
240
- sources.push(context.emergency_log);
241
- if (context.checkpoint_manifest)
242
- sources.push(context.checkpoint_manifest);
243
- return sources;
244
- }
245
- function getArtifactPath(source) {
246
- switch (source.kind) {
247
- case "apply_state":
248
- return source.artifact_path;
249
- case "emergency_log":
250
- return source.log_path;
251
- case "checkpoint_manifest":
252
- return source.checkpoint.manifest_path;
253
- }
254
- }
255
- function toAttemptInfo(source) {
256
- return {
257
- attempt_id: source.freshness.attempt_id,
258
- source_kind: source.freshness.source_kind,
259
- generation: source.freshness.generation,
260
- source_recorded_at: source.freshness.source_recorded_at,
261
- artifact_path: getArtifactPath(source),
262
- };
263
- }
264
- function resolveWithinAttempt(sources) {
265
- const sorted = [...sources].sort((a, b) => getFreshness(b).generation - getFreshness(a).generation);
266
- return {
267
- latest_source: sorted[0],
268
- older_sources: sorted.slice(1),
269
- };
270
- }
271
- /**
272
- * Cross-attempt selection (auto_resolve_latest_generation policy).
273
- *
274
- * SYN-CONS-01 (v9): generation is only monotonic WITHIN one attempt_id.
275
- * Cross-attempt comparison must first select a canonical attempt by ULID
276
- * timestamp ordering (lexicographic == chronological for ULID).
277
- */
278
- function selectCanonicalAttemptAuto(sources) {
279
- const byAttempt = new Map();
280
- for (const source of sources) {
281
- const id = getFreshness(source).attempt_id;
282
- const existing = byAttempt.get(id) ?? [];
283
- existing.push(source);
284
- byAttempt.set(id, existing);
285
- }
286
- const sortedAttempts = [...byAttempt.keys()].sort();
287
- const canonicalAttemptId = sortedAttempts[sortedAttempts.length - 1];
288
- return byAttempt.get(canonicalAttemptId);
289
- }
290
- export function resolveRecoveryTruth(context, projectRoot, policy = DEFAULT_RECOVERY_POLICY) {
291
- const sources = collectAllSources(context);
292
- if (sources.length === 0) {
293
- return { kind: "no_recovery_data" };
294
- }
295
- const attemptIds = new Set(sources.map((s) => getFreshness(s).attempt_id));
296
- if (attemptIds.size > 1) {
297
- if (policy.cross_attempt_conflict === "manual_escalation") {
298
- // DD-23: check existing operator resolution first
299
- const existing = loadRecoveryResolution(projectRoot, context.session_id);
300
- if (existing !== null) {
301
- const selectedSources = sources.filter((s) => getFreshness(s).attempt_id === existing.selected_attempt_id);
302
- if (selectedSources.length === 0) {
303
- // Resolution refers to an attempt that no longer has any sources.
304
- // Surface as escalation again so operator can re-decide.
305
- return {
306
- kind: "manual_escalation_required",
307
- conflicting_attempts: sources.map(toAttemptInfo),
308
- escalation_reason: `Existing recovery-resolution.yaml references attempt_id ` +
309
- `${existing.selected_attempt_id}, but no source matches that ` +
310
- `attempt anymore. Re-record the recovery decision.`,
311
- };
312
- }
313
- const within = resolveWithinAttempt(selectedSources);
314
- return {
315
- kind: "resolved",
316
- source_of_truth: "operator_resolution",
317
- latest_source: within.latest_source,
318
- older_sources: within.older_sources,
319
- has_conflict: true,
320
- resolution_artifact_path: getRecoveryResolutionPath(projectRoot, context.session_id),
321
- };
322
- }
323
- return {
324
- kind: "manual_escalation_required",
325
- conflicting_attempts: sources.map(toAttemptInfo),
326
- escalation_reason: `Multiple attempt_ids detected (${attemptIds.size}). Manual ` +
327
- `operator decision required to select canonical recovery source. ` +
328
- `Record a recovery decision selecting the canonical attempt id.`,
329
- };
330
- }
331
- // auto_resolve_latest_generation
332
- const canonicalSources = selectCanonicalAttemptAuto(sources);
333
- const within = resolveWithinAttempt(canonicalSources);
334
- return {
335
- kind: "resolved",
336
- source_of_truth: "auto_resolved",
337
- latest_source: within.latest_source,
338
- older_sources: within.older_sources,
339
- has_conflict: true,
340
- };
341
- }
342
- // Single attempt path
343
- const within = resolveWithinAttempt(sources);
344
- return {
345
- kind: "resolved",
346
- source_of_truth: "single_attempt",
347
- latest_source: within.latest_source,
348
- older_sources: within.older_sources,
349
- has_conflict: false,
350
- };
351
- }
352
- export function getResolvedFreshness(truth) {
353
- if (truth.kind !== "resolved")
354
- return null;
355
- return getFreshness(truth.latest_source);
356
- }
357
- // ---------------------------------------------------------------------------
358
- // Operator-facing message
359
- // ---------------------------------------------------------------------------
360
- export function buildEscalationMessage(resolved) {
361
- const lines = [
362
- "Recovery Manual Escalation Required",
363
- "====================================",
364
- "",
365
- `Reason: ${resolved.escalation_reason}`,
366
- "",
367
- "Conflicting attempts:",
368
- ];
369
- resolved.conflicting_attempts.forEach((c, i) => {
370
- lines.push(` ${i + 1}. attempt_id=${c.attempt_id}`, ` source=${c.source_kind}`, ` generation=${c.generation}`, ` recorded_at=${c.source_recorded_at}`, ` artifact_path=${c.artifact_path}`);
371
- });
372
- lines.push("", "Resolution options:", " A) Record recovery-resolution selection for <attempt-id>", " B) Edit decisions file with 'recovery_resolution' section", " C) Re-run apply with auto-resolve-attempt-conflict", "", "Note: option C bypasses manual review. Use only when trade-offs are understood.");
373
- return lines.join("\n");
374
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,94 +0,0 @@
1
- /**
2
- * Semantic classifier — A-11 (Phase 2).
3
- *
4
- * LLM-based semantic classification of new learning items against existing items.
5
- * U4 해소: single decision enum + optional conflict_kind.
6
- * R4-IA1: LLM 실패 → unclassified_pending (저장 안 함).
7
- */
8
- import { callLlm, hashPrompt } from "./llm-caller.js";
9
- /** Canonical single definition — CONS-5: all consumers import from here. */
10
- export const SEMANTIC_DECISIONS = [
11
- "save",
12
- "duplicate_skip",
13
- "conflict_propose_replace",
14
- "conflict_propose_keep",
15
- "conflict_propose_coexist",
16
- "unclassified_pending",
17
- ];
18
- export const CONFLICT_KINDS = [
19
- "contradiction",
20
- "supersession",
21
- "disambiguation",
22
- ];
23
- const SYSTEM_PROMPT = `You are a semantic classifier for a learning management system.
24
- Given a NEW learning item and a list of EXISTING learning items, determine:
25
-
26
- 1. Is the new item semantically equivalent to any existing item? → "duplicate_skip"
27
- 2. Does the new item conflict with an existing item?
28
- - Contradiction (opposite claims) → "conflict_propose_replace"
29
- - Supersession (new item updates/replaces) → "conflict_propose_replace"
30
- - Disambiguation (both valid in different contexts) → "conflict_propose_coexist"
31
- - If unsure whether new or existing is better → "conflict_propose_keep"
32
- 3. No semantic overlap → "save"
33
-
34
- Respond ONLY with valid JSON (no markdown fences):
35
- {
36
- "decision": "<one of: save, duplicate_skip, conflict_propose_replace, conflict_propose_keep, conflict_propose_coexist>",
37
- "conflict_kind": "<one of: contradiction, supersession, disambiguation> or null",
38
- "matched_existing_line": "<the existing line that matches/conflicts, or null>",
39
- "reason": "<brief explanation>"
40
- }`;
41
- /**
42
- * Classify a new learning item against existing items.
43
- * A-11: LLM semantic classification.
44
- */
45
- export async function classifyLearningItem(newLine, existingLines, modelId) {
46
- if (existingLines.length === 0) {
47
- return {
48
- decision: "save",
49
- reason: "No existing items to compare against.",
50
- model_id: "none",
51
- prompt_hash: "none",
52
- };
53
- }
54
- const userPrompt = `NEW ITEM:
55
- ${newLine}
56
-
57
- EXISTING ITEMS (${existingLines.length}):
58
- ${existingLines.map((l, i) => `${i + 1}. ${l}`).join("\n")}`;
59
- const promptHash = hashPrompt(SYSTEM_PROMPT + userPrompt);
60
- try {
61
- const callConfig = { max_tokens: 512 };
62
- if (modelId)
63
- callConfig.model_id = modelId;
64
- const result = await callLlm(SYSTEM_PROMPT, userPrompt, callConfig);
65
- const parsed = JSON.parse(result.text.trim());
66
- const decision = parsed.decision;
67
- // Exclude unclassified_pending — it's a fallback, not a valid LLM output
68
- const validLlmDecisions = SEMANTIC_DECISIONS.filter((d) => d !== "unclassified_pending");
69
- if (!validLlmDecisions.includes(decision)) {
70
- return {
71
- decision: "unclassified_pending",
72
- reason: `Invalid decision from LLM: "${decision}"`,
73
- model_id: result.model_id,
74
- prompt_hash: promptHash,
75
- };
76
- }
77
- return {
78
- decision: decision,
79
- conflict_kind: parsed.conflict_kind ?? undefined,
80
- matched_existing_line: parsed.matched_existing_line ?? undefined,
81
- reason: parsed.reason ?? "",
82
- model_id: result.model_id,
83
- prompt_hash: promptHash,
84
- };
85
- }
86
- catch (error) {
87
- return {
88
- decision: "unclassified_pending",
89
- reason: `LLM call failed: ${error instanceof Error ? error.message : String(error)}`,
90
- model_id: modelId ?? "claude-sonnet-4-20250514",
91
- prompt_hash: promptHash,
92
- };
93
- }
94
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * ApplyExecutionState spec — DD-15 + DD-22.
3
- *
4
- * Persisted JSON at {sessionRoot}/promote-execution-result.json. Phase B
5
- * persists this state on every meaningful step so failed_resumable runs can
6
- * pick up where they left off.
7
- */
8
- import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkString, checkNumber, checkArray, } from "./spec-helpers.js";
9
- const KIND = "apply_execution_state";
10
- const CURRENT_VERSION = "1";
11
- const SUPPORTED = ["1"];
12
- export const ApplyExecutionStateSpec = {
13
- kind: KIND,
14
- current_schema_version: CURRENT_VERSION,
15
- supported_schema_versions: SUPPORTED,
16
- supported_formats: ["json"],
17
- parse(content, format) {
18
- const raw = parseRaw(content, format);
19
- return rejectPreV7(raw, KIND, SUPPORTED);
20
- },
21
- serialize(data, format) {
22
- return serializeRaw(data, format);
23
- },
24
- validate(data) {
25
- const errors = [];
26
- if (typeof data !== "object" || data === null) {
27
- return { valid: false, errors: ["data is not an object"] };
28
- }
29
- const obj = data;
30
- checkSchemaVersion(obj, CURRENT_VERSION, errors);
31
- checkString(obj, "session_id", errors);
32
- checkString(obj, "attempt_id", errors);
33
- checkString(obj, "attempt_started_at", errors);
34
- checkNumber(obj, "generation", errors);
35
- checkString(obj, "last_updated_at", errors);
36
- checkString(obj, "status", errors);
37
- checkArray(obj, "applied_decisions", errors);
38
- checkArray(obj, "failed_decisions", errors);
39
- checkArray(obj, "pending_decisions", errors);
40
- return { valid: errors.length === 0, errors };
41
- },
42
- };
@@ -1,37 +0,0 @@
1
- /**
2
- * AuditState spec — DD-17 + DD-21.
3
- *
4
- * Persisted YAML at ~/.onto/audit-state.yaml.
5
- *
6
- * Class boundary: parse() returns plain JSON; consumers reconstruct
7
- * AuditObligation class instances via AuditObligation.fromJSON(). The spec
8
- * intentionally does NOT import the class so this module stays in the kernel
9
- * dependency layer.
10
- */
11
- import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkArray, } from "./spec-helpers.js";
12
- const KIND = "audit_state";
13
- const CURRENT_VERSION = "1";
14
- const SUPPORTED = ["1"];
15
- export const AuditStateSpec = {
16
- kind: KIND,
17
- current_schema_version: CURRENT_VERSION,
18
- supported_schema_versions: SUPPORTED,
19
- supported_formats: ["yaml"],
20
- parse(content, format) {
21
- const raw = parseRaw(content, format);
22
- return rejectPreV7(raw, KIND, SUPPORTED);
23
- },
24
- serialize(data, format) {
25
- return serializeRaw(data, format);
26
- },
27
- validate(data) {
28
- const errors = [];
29
- if (typeof data !== "object" || data === null) {
30
- return { valid: false, errors: ["data is not an object"] };
31
- }
32
- const obj = data;
33
- checkSchemaVersion(obj, CURRENT_VERSION, errors);
34
- checkArray(obj, "obligations", errors);
35
- return { valid: errors.length === 0, errors };
36
- },
37
- };
@@ -1,39 +0,0 @@
1
- /**
2
- * BackupMetadata spec — DD-16 (BACKUP-PROTECTION-01).
3
- *
4
- * Persisted YAML at ~/.onto/backups/{session-id}/backup-metadata.yaml.
5
- * Tracks protection state so prune respects active sessions and unrecoverable
6
- * failures.
7
- */
8
- import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkString, checkNumber, } from "./spec-helpers.js";
9
- const KIND = "backup_metadata";
10
- const CURRENT_VERSION = "1";
11
- const SUPPORTED = ["1"];
12
- export const BackupMetadataSpec = {
13
- kind: KIND,
14
- current_schema_version: CURRENT_VERSION,
15
- supported_schema_versions: SUPPORTED,
16
- supported_formats: ["yaml"],
17
- parse(content, format) {
18
- const raw = parseRaw(content, format);
19
- return rejectPreV7(raw, KIND, SUPPORTED);
20
- },
21
- serialize(data, format) {
22
- return serializeRaw(data, format);
23
- },
24
- validate(data) {
25
- const errors = [];
26
- if (typeof data !== "object" || data === null) {
27
- return { valid: false, errors: ["data is not an object"] };
28
- }
29
- const obj = data;
30
- checkSchemaVersion(obj, CURRENT_VERSION, errors);
31
- checkString(obj, "session_id", errors);
32
- checkString(obj, "created_at", errors);
33
- checkNumber(obj, "total_bytes", errors);
34
- if (typeof obj.protected !== "boolean") {
35
- errors.push("protected must be a boolean");
36
- }
37
- return { valid: errors.length === 0, errors };
38
- },
39
- };
@@ -1,41 +0,0 @@
1
- /**
2
- * EmergencyLogEntry spec — DD-15.
3
- *
4
- * Append-only JSONL at ~/.onto/emergency-log.jsonl. Each entry is one JSON
5
- * object on a single line. Spec.serialize emits a single object (no trailing
6
- * newline); the registry's appendToFile() adds the newline.
7
- */
8
- import { rejectPreV7, checkSchemaVersion, checkString, checkNumber, } from "./spec-helpers.js";
9
- const KIND = "emergency_log_entry";
10
- const CURRENT_VERSION = "1";
11
- const SUPPORTED = ["1"];
12
- export const EmergencyLogSpec = {
13
- kind: KIND,
14
- current_schema_version: CURRENT_VERSION,
15
- supported_schema_versions: SUPPORTED,
16
- supported_formats: ["json"],
17
- parse(content, _format) {
18
- const raw = JSON.parse(content);
19
- return rejectPreV7(raw, KIND, SUPPORTED);
20
- },
21
- serialize(data, _format) {
22
- return JSON.stringify(data);
23
- },
24
- validate(data) {
25
- const errors = [];
26
- if (typeof data !== "object" || data === null) {
27
- return { valid: false, errors: ["data is not an object"] };
28
- }
29
- const obj = data;
30
- checkSchemaVersion(obj, CURRENT_VERSION, errors);
31
- checkString(obj, "entry_id", errors);
32
- checkString(obj, "session_id", errors);
33
- checkString(obj, "written_at", errors);
34
- checkString(obj, "attempt_id", errors);
35
- checkNumber(obj, "generation", errors);
36
- checkString(obj, "fatal_error_kind", errors);
37
- checkString(obj, "fatal_error_message", errors);
38
- checkString(obj, "session_root", errors);
39
- return { valid: errors.length === 0, errors };
40
- },
41
- };
@@ -1,38 +0,0 @@
1
- /**
2
- * LayoutVersion spec — DD-8.
3
- *
4
- * Persisted at {projectRoot}/.onto/.layout-version.yaml. Identifies the
5
- * session-root layout version so old layouts trigger migration before any
6
- * promote command touches files.
7
- */
8
- import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkString, } from "./spec-helpers.js";
9
- const KIND = "layout_version";
10
- const CURRENT_VERSION = "1";
11
- const SUPPORTED = ["1"];
12
- export const LayoutVersionSpec = {
13
- kind: KIND,
14
- current_schema_version: CURRENT_VERSION,
15
- supported_schema_versions: SUPPORTED,
16
- supported_formats: ["yaml"],
17
- parse(content, format) {
18
- const raw = parseRaw(content, format);
19
- return rejectPreV7(raw, KIND, SUPPORTED);
20
- },
21
- serialize(data, format) {
22
- return serializeRaw(data, format);
23
- },
24
- validate(data) {
25
- const errors = [];
26
- if (typeof data !== "object" || data === null) {
27
- return { valid: false, errors: ["data is not an object"] };
28
- }
29
- const obj = data;
30
- checkSchemaVersion(obj, CURRENT_VERSION, errors);
31
- checkString(obj, "layout_version", errors);
32
- if (obj.layout_version !== "v3") {
33
- errors.push(`layout_version must be "v3"`);
34
- }
35
- checkString(obj, "written_at", errors);
36
- return { valid: errors.length === 0, errors };
37
- },
38
- };