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,195 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { applySet, SUPPORTED_SET_PATHS } from "./onto-config-key-path.js";
3
- // ---------------------------------------------------------------------------
4
- // applySet — Review UX Redesign P5 (2026-04-21)
5
- // ---------------------------------------------------------------------------
6
- //
7
- // These tests cover the coercion + discriminated-union invariants the
8
- // `onto config set` and `edit` subcommands depend on:
9
- //
10
- // (1) Happy paths for each supported key, round-tripping through the
11
- // expected OntoReviewConfig shape.
12
- // (2) Discriminated-union preservation — switching subagent.provider
13
- // from `main-native` to a foreign value adds model_id/effort slots;
14
- // switching back to `main-native` drops them.
15
- // (3) Value coercion errors (integers, enums) returned as `ok: false`
16
- // with a clear error string — caller forwards verbatim to the user.
17
- // (4) Unsupported paths return an error pointing to `edit` for richer
18
- // spec objects.
19
- // ---------------------------------------------------------------------------
20
- describe("applySet — supported paths declared", () => {
21
- it("SUPPORTED_SET_PATHS matches README / help text exactly", () => {
22
- expect(SUPPORTED_SET_PATHS).toEqual([
23
- "teamlead.model",
24
- "subagent.provider",
25
- "subagent.model_id",
26
- "subagent.effort",
27
- "max_concurrent_lenses",
28
- "lens_deliberation",
29
- ]);
30
- });
31
- });
32
- describe("applySet — teamlead.model", () => {
33
- it("accepts `main` literal", () => {
34
- const r = applySet({}, "teamlead.model", "main");
35
- expect(r.ok).toBe(true);
36
- if (r.ok)
37
- expect(r.config.teamlead).toEqual({ model: "main" });
38
- });
39
- it("rejects foreign teamlead values and points to `edit`", () => {
40
- const r = applySet({}, "teamlead.model", "codex");
41
- expect(r.ok).toBe(false);
42
- if (!r.ok)
43
- expect(r.error).toMatch(/edit/);
44
- });
45
- });
46
- describe("applySet — subagent.provider (discriminated-union preservation)", () => {
47
- it("main-native → main-native is idempotent", () => {
48
- const r = applySet({ subagent: { provider: "main-native" } }, "subagent.provider", "main-native");
49
- expect(r.ok).toBe(true);
50
- if (r.ok)
51
- expect(r.config.subagent).toEqual({ provider: "main-native" });
52
- });
53
- it("main-native → codex preserves (empty) model_id slot", () => {
54
- const r = applySet({ subagent: { provider: "main-native" } }, "subagent.provider", "codex");
55
- expect(r.ok).toBe(true);
56
- if (r.ok) {
57
- expect(r.config.subagent).toEqual({ provider: "codex", model_id: "" });
58
- }
59
- });
60
- it("codex → litellm carries over model_id + effort (user may prune later)", () => {
61
- const r = applySet({
62
- subagent: { provider: "codex", model_id: "gpt-5.4", effort: "high" },
63
- }, "subagent.provider", "litellm");
64
- expect(r.ok).toBe(true);
65
- if (r.ok) {
66
- expect(r.config.subagent).toEqual({
67
- provider: "litellm",
68
- model_id: "gpt-5.4",
69
- effort: "high",
70
- });
71
- }
72
- });
73
- it("codex → main-native drops model_id + effort (union branch change)", () => {
74
- const r = applySet({
75
- subagent: { provider: "codex", model_id: "gpt-5.4", effort: "high" },
76
- }, "subagent.provider", "main-native");
77
- expect(r.ok).toBe(true);
78
- if (r.ok)
79
- expect(r.config.subagent).toEqual({ provider: "main-native" });
80
- });
81
- it("rejects unknown provider", () => {
82
- const r = applySet({}, "subagent.provider", "hal9000");
83
- expect(r.ok).toBe(false);
84
- });
85
- });
86
- describe("applySet — subagent.model_id", () => {
87
- it("requires a foreign provider to be set first", () => {
88
- const r = applySet({ subagent: { provider: "main-native" } }, "subagent.model_id", "gpt-5.4");
89
- expect(r.ok).toBe(false);
90
- if (!r.ok)
91
- expect(r.error).toMatch(/foreign provider/);
92
- });
93
- it("rejects empty model_id", () => {
94
- const r = applySet({
95
- subagent: { provider: "codex", model_id: "prev" },
96
- }, "subagent.model_id", "");
97
- expect(r.ok).toBe(false);
98
- });
99
- it("sets model_id on codex subagent", () => {
100
- const r = applySet({ subagent: { provider: "codex", model_id: "" } }, "subagent.model_id", "gpt-5.4");
101
- expect(r.ok).toBe(true);
102
- if (r.ok) {
103
- expect(r.config.subagent).toEqual({
104
- provider: "codex",
105
- model_id: "gpt-5.4",
106
- });
107
- }
108
- });
109
- it("preserves effort when updating model_id", () => {
110
- const r = applySet({
111
- subagent: { provider: "codex", model_id: "gpt-5.4", effort: "high" },
112
- }, "subagent.model_id", "gpt-5.4-preview");
113
- expect(r.ok).toBe(true);
114
- if (r.ok) {
115
- expect(r.config.subagent).toEqual({
116
- provider: "codex",
117
- model_id: "gpt-5.4-preview",
118
- effort: "high",
119
- });
120
- }
121
- });
122
- });
123
- describe("applySet — subagent.effort", () => {
124
- it("requires a foreign provider", () => {
125
- const r = applySet({ subagent: { provider: "main-native" } }, "subagent.effort", "high");
126
- expect(r.ok).toBe(false);
127
- });
128
- it("sets effort on a foreign subagent", () => {
129
- const r = applySet({ subagent: { provider: "codex", model_id: "gpt-5.4" } }, "subagent.effort", "xhigh");
130
- expect(r.ok).toBe(true);
131
- if (r.ok) {
132
- expect(r.config.subagent).toEqual({
133
- provider: "codex",
134
- model_id: "gpt-5.4",
135
- effort: "xhigh",
136
- });
137
- }
138
- });
139
- });
140
- describe("applySet — max_concurrent_lenses", () => {
141
- it("accepts positive integer", () => {
142
- const r = applySet({}, "max_concurrent_lenses", "9");
143
- expect(r.ok).toBe(true);
144
- if (r.ok)
145
- expect(r.config.max_concurrent_lenses).toBe(9);
146
- });
147
- it("rejects zero / negative / float / non-numeric", () => {
148
- expect(applySet({}, "max_concurrent_lenses", "0").ok).toBe(false);
149
- expect(applySet({}, "max_concurrent_lenses", "-1").ok).toBe(false);
150
- expect(applySet({}, "max_concurrent_lenses", "2.5").ok).toBe(false);
151
- expect(applySet({}, "max_concurrent_lenses", "six").ok).toBe(false);
152
- });
153
- });
154
- describe("applySet — lens_deliberation", () => {
155
- it("accepts synthesizer-only", () => {
156
- const r = applySet({}, "lens_deliberation", "synthesizer-only");
157
- expect(r.ok).toBe(true);
158
- if (r.ok)
159
- expect(r.config.lens_deliberation).toBe("synthesizer-only");
160
- });
161
- it("accepts sendmessage-a2a", () => {
162
- const r = applySet({}, "lens_deliberation", "sendmessage-a2a");
163
- expect(r.ok).toBe(true);
164
- if (r.ok)
165
- expect(r.config.lens_deliberation).toBe("sendmessage-a2a");
166
- });
167
- it("rejects unknown deliberation value", () => {
168
- const r = applySet({}, "lens_deliberation", "loud");
169
- expect(r.ok).toBe(false);
170
- });
171
- });
172
- describe("applySet — unsupported paths", () => {
173
- it("rejects unknown key path with hint to `edit`", () => {
174
- const r = applySet({}, "review_mode", "full");
175
- expect(r.ok).toBe(false);
176
- if (!r.ok) {
177
- expect(r.error).toMatch(/edit/);
178
- expect(r.error).toMatch(/Supported paths/);
179
- }
180
- });
181
- it("rejects nested teamlead.model.provider path (use edit)", () => {
182
- const r = applySet({}, "teamlead.model.provider", "codex");
183
- expect(r.ok).toBe(false);
184
- });
185
- });
186
- describe("applySet — purity", () => {
187
- it("does not mutate the input config", () => {
188
- const original = {
189
- subagent: { provider: "codex", model_id: "gpt-5.4", effort: "high" },
190
- };
191
- const snapshot = structuredClone(original);
192
- applySet(original, "subagent.provider", "main-native");
193
- expect(original).toEqual(snapshot);
194
- });
195
- });
@@ -1,108 +0,0 @@
1
- /**
2
- * Review UX Redesign P5 — `onto config validate` / `onto config show`
3
- * preview helper.
4
- *
5
- * # What this module is
6
- *
7
- * A pure function that takes a validated `OntoReviewConfig` + host signals
8
- * and returns a deterministic textual preview showing:
9
- * (a) which topology shape the config would derive to,
10
- * (b) which canonical `TopologyId` that shape would map to under the
11
- * current environment, and
12
- * (c) the exact validation or mapping point that would stop execution.
13
- *
14
- * # Why it exists
15
- *
16
- * The onboard + config-edit UX promise is "what you configured is what
17
- * runs". Without a preview step, users only see the runtime outcome after
18
- * starting a review (via the `[topology]` STDERR trace). This helper
19
- * surfaces the derivation BEFORE any review call, making config-time and
20
- * run-time answer the same question with the same inputs.
21
- *
22
- * # How it relates
23
- *
24
- * - Input: validated `OntoReviewConfig` (from `validateReviewConfig`) +
25
- * detected axes (from `detectReviewAxes`).
26
- * - Output: a typed `Preview` object (topology id, shape) plus
27
- * a rendered string for CLI display.
28
- * - Shares derivation/mapping logic with `resolveAxisFirstTopology` so
29
- * the preview and the runtime can never drift.
30
- */
31
- import { shapeToTopologyId } from "../review/shape-to-topology-id.js";
32
- import { deriveTopologyShape, } from "../review/topology-shape-derivation.js";
33
- // ---------------------------------------------------------------------------
34
- // Main
35
- // ---------------------------------------------------------------------------
36
- /**
37
- * Run derivation + mapping preview. Mirrors the
38
- * runtime resolver's axis-first path so the output matches what the user
39
- * would see in `[topology]` STDERR during a real review invocation.
40
- */
41
- export function previewTopologyDerivation(config, signals) {
42
- const trace = [];
43
- const derivation = deriveTopologyShape(config, signals);
44
- for (const line of derivation.ok ? derivation.derived.trace : derivation.trace) {
45
- trace.push(`derive: ${line}`);
46
- }
47
- if (!derivation.ok) {
48
- return {
49
- ok: false,
50
- reason: derivation.reasons[0] ?? "topology shape derivation failed",
51
- trace,
52
- };
53
- }
54
- const mapping = shapeToTopologyId({
55
- shape: derivation.derived.shape,
56
- subagent_provider: derivation.derived.subagent_provider,
57
- signals: {
58
- claudeHost: signals.claudeHost,
59
- codexSessionActive: signals.codexSessionActive,
60
- },
61
- });
62
- for (const line of mapping.trace) {
63
- trace.push(`map: ${line}`);
64
- }
65
- if (!mapping.ok) {
66
- return {
67
- ok: false,
68
- reason: mapping.reason,
69
- trace,
70
- };
71
- }
72
- trace.push(`result: shape=${derivation.derived.shape} topology=${mapping.topology_id}`);
73
- return {
74
- ok: true,
75
- shape: derivation.derived.shape,
76
- topology_id: mapping.topology_id,
77
- trace,
78
- };
79
- }
80
- // ---------------------------------------------------------------------------
81
- // Rendering
82
- // ---------------------------------------------------------------------------
83
- /**
84
- * Render a preview result as a human-readable block for CLI display.
85
- * Handles both success and failure outputs. Keep the format stable — the
86
- * onboard prose and `onto config` output use the same template so the
87
- * user learns one visual vocabulary.
88
- */
89
- export function renderPreview(result) {
90
- const lines = [];
91
- if (result.ok) {
92
- lines.push("## Topology derivation preview");
93
- lines.push("");
94
- lines.push(` shape: ${result.shape}`);
95
- lines.push(` topology_id: ${result.topology_id}`);
96
- }
97
- else {
98
- lines.push("## Topology derivation preview — FAILED");
99
- lines.push("");
100
- lines.push(` reason: ${result.reason}`);
101
- }
102
- lines.push("");
103
- lines.push(" Trace:");
104
- for (const line of result.trace) {
105
- lines.push(` ${line}`);
106
- }
107
- return lines.join("\n");
108
- }
@@ -1,132 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { previewTopologyDerivation, renderPreview, } from "./onto-config-preview.js";
3
- // ---------------------------------------------------------------------------
4
- // previewTopologyDerivation — Review UX Redesign P5 (2026-04-21)
5
- // ---------------------------------------------------------------------------
6
- //
7
- // These tests verify that the preview helper mirrors the runtime resolver's
8
- // axis-first path:
9
- //
10
- // (1) Happy path — a valid config + suitable host → correct shape +
11
- // canonical TopologyId + degraded=false.
12
- // (2) Derivation failure (a2a + no teams) → degrades to main_native.
13
- // (3) Mapping failure (main_foreign + litellm) → degrades to main_native.
14
- // (4) No Claude, no Codex → main_native unmappable → preview fails
15
- // (runtime would fall through to legacy ladder / no_host).
16
- // (5) renderPreview produces a stable human-readable block for CLI use.
17
- // ---------------------------------------------------------------------------
18
- const CLAUDE_NO_TEAMS = {
19
- claudeHost: true,
20
- codexSessionActive: false,
21
- experimentalAgentTeams: false,
22
- };
23
- const CLAUDE_TEAMS = {
24
- claudeHost: true,
25
- codexSessionActive: false,
26
- experimentalAgentTeams: true,
27
- };
28
- const CODEX_HOST = {
29
- claudeHost: false,
30
- codexSessionActive: true,
31
- experimentalAgentTeams: false,
32
- };
33
- const NEITHER = {
34
- claudeHost: false,
35
- codexSessionActive: false,
36
- experimentalAgentTeams: false,
37
- };
38
- describe("previewTopologyDerivation — happy paths", () => {
39
- it("empty config + Claude host → main_native / cc-main-agent-subagent", () => {
40
- const r = previewTopologyDerivation({}, CLAUDE_NO_TEAMS);
41
- expect(r.ok).toBe(true);
42
- if (r.ok) {
43
- expect(r.shape).toBe("main_native");
44
- expect(r.topology_id).toBe("cc-main-agent-subagent");
45
- expect(r.degraded).toBe(false);
46
- }
47
- });
48
- it("teams + main-native → main-teams_native / cc-teams-agent-subagent", () => {
49
- const config = {
50
- teamlead: { model: "main" },
51
- subagent: { provider: "main-native" },
52
- };
53
- const r = previewTopologyDerivation(config, CLAUDE_TEAMS);
54
- expect(r.ok).toBe(true);
55
- if (r.ok) {
56
- expect(r.shape).toBe("main-teams_native");
57
- expect(r.topology_id).toBe("cc-teams-agent-subagent");
58
- expect(r.degraded).toBe(false);
59
- }
60
- });
61
- it("Codex host + main-native → main_native / codex-main-subprocess", () => {
62
- const r = previewTopologyDerivation({ subagent: { provider: "main-native" } }, CODEX_HOST);
63
- expect(r.ok).toBe(true);
64
- if (r.ok) {
65
- expect(r.shape).toBe("main_native");
66
- expect(r.topology_id).toBe("codex-main-subprocess");
67
- }
68
- });
69
- });
70
- describe("previewTopologyDerivation — degrade paths", () => {
71
- it("a2a without teams → degrades to main_native", () => {
72
- const config = {
73
- subagent: { provider: "main-native" },
74
- lens_deliberation: "sendmessage-a2a",
75
- };
76
- const r = previewTopologyDerivation(config, CLAUDE_NO_TEAMS);
77
- expect(r.ok).toBe(true);
78
- if (r.ok) {
79
- expect(r.degraded).toBe(true);
80
- expect(r.shape).toBe("main_native");
81
- expect(r.topology_id).toBe("cc-main-agent-subagent");
82
- expect(r.trace.some((l) => l.startsWith("degrade:"))).toBe(true);
83
- }
84
- });
85
- it("main_foreign + litellm (Claude host) → degrades to main_native", () => {
86
- const config = {
87
- subagent: { provider: "litellm", model_id: "llama-8b" },
88
- };
89
- const r = previewTopologyDerivation(config, CLAUDE_NO_TEAMS);
90
- expect(r.ok).toBe(true);
91
- if (r.ok) {
92
- expect(r.degraded).toBe(true);
93
- expect(r.topology_id).toBe("cc-main-agent-subagent");
94
- expect(r.trace.some((l) => l.includes("main_foreign(litellm)"))).toBe(true);
95
- }
96
- });
97
- });
98
- describe("previewTopologyDerivation — total failure (no host)", () => {
99
- it("main_native unmappable → preview fails with explanatory reason", () => {
100
- const r = previewTopologyDerivation({}, NEITHER);
101
- expect(r.ok).toBe(false);
102
- if (!r.ok) {
103
- expect(r.reason).toContain("main_native fallback");
104
- expect(r.trace.some((l) => l.includes("unmappable"))).toBe(true);
105
- }
106
- });
107
- });
108
- describe("renderPreview — human-readable output", () => {
109
- it("success block includes shape + topology_id + trace", () => {
110
- const r = previewTopologyDerivation({}, CLAUDE_NO_TEAMS);
111
- const text = renderPreview(r);
112
- expect(text).toContain("Topology derivation preview");
113
- expect(text).toContain("shape:");
114
- expect(text).toContain("cc-main-agent-subagent");
115
- expect(text).toContain("Trace:");
116
- });
117
- it("degraded block includes (degraded) marker and fallback note", () => {
118
- const config = {
119
- subagent: { provider: "litellm", model_id: "llama-8b" },
120
- };
121
- const r = previewTopologyDerivation(config, CLAUDE_NO_TEAMS);
122
- const text = renderPreview(r);
123
- expect(text).toContain("(degraded)");
124
- expect(text).toContain("P3 universal fallback");
125
- });
126
- it("failure block includes reason + FAILED header", () => {
127
- const r = previewTopologyDerivation({}, NEITHER);
128
- const text = renderPreview(r);
129
- expect(text).toContain("FAILED");
130
- expect(text).toContain("reason:");
131
- });
132
- });
@@ -1,118 +0,0 @@
1
- import path from "node:path";
2
- import { fileExists, readYamlDocument } from "../review/review-artifact-utils.js";
3
- import { adoptProfile, mergeOrthogonalFields, } from "./config-profile.js";
4
- async function readConfigAt(dir) {
5
- const configPath = path.join(dir, ".onto", "config.yml");
6
- if (!(await fileExists(configPath))) {
7
- return {};
8
- }
9
- const raw = await readYamlDocument(configPath);
10
- if (raw === null || typeof raw !== "object") {
11
- return {};
12
- }
13
- assertKnownConfigKeys(raw, configPath);
14
- return raw;
15
- }
16
- const TOP_LEVEL_CONFIG_KEYS = [
17
- "llm",
18
- "review",
19
- "review_mode",
20
- "max_concurrent_lenses",
21
- "domain",
22
- "secondary_domains",
23
- "domains",
24
- "excluded_names",
25
- "max_listing_depth",
26
- "max_listing_entries",
27
- "max_embed_lines",
28
- "output_language",
29
- "learning_extract_mode",
30
- "main_llm",
31
- "lens_agent_teams_mode",
32
- ];
33
- function assertKnownConfigKeys(raw, configPath) {
34
- const allowed = new Set(TOP_LEVEL_CONFIG_KEYS);
35
- const unknown = Object.keys(raw).filter((key) => !allowed.has(key));
36
- if (unknown.length === 0)
37
- return;
38
- throw new Error([
39
- `Unsupported .onto config key(s) in ${configPath}: ${unknown.join(", ")}`,
40
- "Supported top-level keys:",
41
- ` ${TOP_LEVEL_CONFIG_KEYS.join(", ")}`,
42
- "LLM selection belongs under:",
43
- " llm:",
44
- " auth: oauth | api_key | local",
45
- " provider: openai | anthropic | grok | lmstudio",
46
- " model: <model-id>",
47
- " effort: high",
48
- " base_url: <optional>",
49
- ].join("\n"));
50
- }
51
- /**
52
- * Orthogonal-only config chain resolver.
53
- *
54
- * # What this is
55
- *
56
- * Reads home + project `.onto/config.yml`, merges ONLY the orthogonal
57
- * fields (output_language, domains, review_mode, learning_extract_mode,
58
- * etc. — see `config-profile.ts:PROFILE_FIELDS` for the complement set),
59
- * and returns the merged partial config without running `adoptProfile`.
60
- *
61
- * # Why this exists
62
- *
63
- * Callers that only need a single orthogonal field (e.g.,
64
- * `resolveReviewSessionExtractMode` reading `learning_extract_mode`) do
65
- * NOT need provider-profile validation. Routing them through
66
- * `resolveConfigChain` caused false fail-fast throws once PR #96's atomic
67
- * profile adoption started rejecting "no provider profile declared"
68
- * configs — a test/tooling fixture that cares only about orthogonal
69
- * settings would be blocked by an unrelated profile gate.
70
- *
71
- * # How it relates
72
- *
73
- * Same underlying `readConfigAt` + `mergeOrthogonalFields` that
74
- * `resolveConfigChain` uses, sequenced without profile adoption.
75
- * Callers that need a full config continue to use `resolveConfigChain`.
76
- */
77
- export async function resolveOrthogonalConfigChain(ontoHome, projectRoot) {
78
- const homeConfig = await readConfigAt(ontoHome);
79
- const sameRoot = ontoHome === projectRoot;
80
- const projectConfig = sameRoot ? homeConfig : await readConfigAt(projectRoot);
81
- return mergeOrthogonalFields(homeConfig, projectConfig);
82
- }
83
- /**
84
- * Config chain resolver (home + project) with atomic profile adoption.
85
- *
86
- * # Behavior
87
- *
88
- * - Project declares any profile fields → project owns the profile atomically.
89
- * - Project declares none, home declares some → global profile adopted silently.
90
- * - Neither side declares any profile fields → empty profile returned.
91
- *
92
- * Orthogonal fields (output_language, domains, review_mode, listing limits,
93
- * learning_extract_mode, etc.) continue to merge last-wins — they do not
94
- * carry cross-provider semantics.
95
- *
96
- * # Why atomic adoption still runs
97
- *
98
- * Atomic ownership prevents mixed provider state from different config files.
99
- * `extractProfileFields` + `adoptProfile` transfer PROFILE_FIELDS as a group
100
- * from exactly one source.
101
- */
102
- export async function resolveConfigChain(ontoHome, projectRoot) {
103
- const homeConfig = await readConfigAt(ontoHome);
104
- const sameRoot = ontoHome === projectRoot;
105
- const projectConfig = sameRoot ? homeConfig : await readConfigAt(projectRoot);
106
- const homePath = path.join(ontoHome, ".onto", "config.yml");
107
- const projectPath = path.join(projectRoot, ".onto", "config.yml");
108
- const adoption = adoptProfile({
109
- home: homeConfig,
110
- project: projectConfig,
111
- homePath,
112
- projectPath,
113
- sameRoot,
114
- });
115
- const orthogonal = mergeOrthogonalFields(homeConfig, projectConfig);
116
- const merged = { ...orthogonal, ...adoption.profile };
117
- return merged;
118
- }
@@ -1,103 +0,0 @@
1
- import { afterEach, describe, expect, it } from "vitest";
2
- import fs from "node:fs";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { resolveConfigChain } from "./config-chain.js";
6
- // ---------------------------------------------------------------------------
7
- // config-chain — P9.5 graceful-ignore regression guard (2026-04-21).
8
- //
9
- // P9.5 retired `legacy-field-deprecation.ts`. Legacy provider-profile
10
- // fields (host_runtime, execution_realization, execution_mode,
11
- // executor_realization, api_provider) in YAML no longer throw
12
- // `LegacyFieldRemovedError` at config load. The OntoConfig type omits
13
- // them, so typed code cannot read them; Record-cast paths can still
14
- // see the values, but no production consumer does so — the fields are
15
- // effectively inert.
16
- //
17
- // These tests lock in the graceful-ignore contract so a future refactor
18
- // that reintroduces a throw surfaces as a test failure, and so the
19
- // "config loads + downstream path still works" invariant is explicit.
20
- // ---------------------------------------------------------------------------
21
- const cleanupDirs = [];
22
- function makeTmpDir(prefix) {
23
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), `onto-p95-${prefix}-`));
24
- cleanupDirs.push(dir);
25
- return dir;
26
- }
27
- function writeConfig(dir, yaml) {
28
- fs.mkdirSync(path.join(dir, ".onto"), { recursive: true });
29
- fs.writeFileSync(path.join(dir, ".onto", "config.yml"), yaml, "utf8");
30
- }
31
- afterEach(() => {
32
- while (cleanupDirs.length > 0) {
33
- const dir = cleanupDirs.pop();
34
- if (dir) {
35
- try {
36
- fs.rmSync(dir, { recursive: true, force: true });
37
- }
38
- catch {
39
- /* ignore */
40
- }
41
- }
42
- }
43
- });
44
- describe("resolveConfigChain — P9.5 legacy field graceful ignore", () => {
45
- it("legacy-only project config → loads without throw; OntoConfig type omits legacy keys", async () => {
46
- // Pre-P9.5: `host_runtime: codex` + no `review:` block threw
47
- // LegacyFieldRemovedError. Post-P9.5: loads successfully.
48
- const homeDir = makeTmpDir("legacy-h");
49
- const projDir = makeTmpDir("legacy-p");
50
- writeConfig(projDir, "host_runtime: codex\napi_provider: codex\n");
51
- // Must not throw. The promise resolving is the primary invariant.
52
- const config = await resolveConfigChain(homeDir, projDir);
53
- expect(config).toBeDefined();
54
- // The OntoConfig type omits the legacy fields — typed access via
55
- // `config.host_runtime` would be a TypeScript error. No runtime
56
- // consumer reads these values; they remain in the underlying
57
- // Record only for Record-cast backward compatibility.
58
- expect(config.review).toBeUndefined();
59
- expect(config.codex).toBeUndefined();
60
- });
61
- it("legacy fields + review block → config loads, review block survives and is authoritative", async () => {
62
- const homeDir = makeTmpDir("mixed-h");
63
- const projDir = makeTmpDir("mixed-p");
64
- writeConfig(projDir, [
65
- "host_runtime: anthropic", // legacy ghost field — not consumed
66
- "review:",
67
- " subagent:",
68
- " provider: codex",
69
- " model_id: gpt-5.4",
70
- "codex:",
71
- " model: gpt-5.4",
72
- ].join("\n"));
73
- const config = await resolveConfigChain(homeDir, projDir);
74
- // Review block (orthogonal) + codex namespace (profile) are the
75
- // authoritative sources post-P9.5.
76
- expect(config.review?.subagent?.provider).toBe("codex");
77
- expect(config.codex?.model).toBe("gpt-5.4");
78
- });
79
- it("legacy-only home + absent project → home profile adopted via atomic adoption", async () => {
80
- // Home has legacy-only YAML + a codex namespace. Pre-P9.5 the
81
- // legacy throw would fire before adoption ran. Post-P9.5 adoption
82
- // sees `hasAnyProfileField(home) === true` (via `codex`) and picks
83
- // up the home profile; legacy fields are inert.
84
- const homeDir = makeTmpDir("home-legacy-h");
85
- const projDir = makeTmpDir("home-legacy-p");
86
- writeConfig(homeDir, ["host_runtime: codex", "codex:", " model: gpt-5.4"].join("\n"));
87
- // No project config.
88
- const config = await resolveConfigChain(homeDir, projDir);
89
- expect(config.codex?.model).toBe("gpt-5.4");
90
- });
91
- it("completely empty configs → loads without throw (resolver owns no_host fail-fast downstream)", async () => {
92
- // Pre-P9.4 `buildBothIncompleteError` threw; pre-P9.5
93
- // `LegacyFieldRemovedError` threw when legacy present. Post-P9.5
94
- // config load never throws for these cases — the topology resolver
95
- // is the sole fail-fast point via `no_host`.
96
- const homeDir = makeTmpDir("empty-h");
97
- const projDir = makeTmpDir("empty-p");
98
- const config = await resolveConfigChain(homeDir, projDir);
99
- expect(config).toBeDefined();
100
- expect(config.codex).toBeUndefined();
101
- expect(config.review).toBeUndefined();
102
- });
103
- });