onto-mcp 0.3.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 (447) hide show
  1. package/.onto/authority/core-lens-registry.yaml +134 -0
  2. package/.onto/authority/core-lexicon.yaml +1562 -0
  3. package/.onto/authority/diagnostic-codes.yaml +94 -0
  4. package/.onto/domains/accounting/competency_qs.md +384 -0
  5. package/.onto/domains/accounting/concepts.md +186 -0
  6. package/.onto/domains/accounting/conciseness_rules.md +160 -0
  7. package/.onto/domains/accounting/dependency_rules.md +239 -0
  8. package/.onto/domains/accounting/domain_scope.md +213 -0
  9. package/.onto/domains/accounting/extension_cases.md +416 -0
  10. package/.onto/domains/accounting/logic_rules.md +226 -0
  11. package/.onto/domains/accounting/structure_spec.md +298 -0
  12. package/.onto/domains/accounting-kr/competency_qs.md +562 -0
  13. package/.onto/domains/accounting-kr/concepts.md +187 -0
  14. package/.onto/domains/accounting-kr/conciseness_rules.md +125 -0
  15. package/.onto/domains/accounting-kr/dependency_rules.md +93 -0
  16. package/.onto/domains/accounting-kr/domain_scope.md +140 -0
  17. package/.onto/domains/accounting-kr/extension_cases.md +343 -0
  18. package/.onto/domains/accounting-kr/logic_rules.md +160 -0
  19. package/.onto/domains/accounting-kr/structure_spec.md +85 -0
  20. package/.onto/domains/business/competency_qs.md +263 -0
  21. package/.onto/domains/business/concepts.md +200 -0
  22. package/.onto/domains/business/conciseness_rules.md +135 -0
  23. package/.onto/domains/business/dependency_rules.md +113 -0
  24. package/.onto/domains/business/domain_scope.md +240 -0
  25. package/.onto/domains/business/extension_cases.md +249 -0
  26. package/.onto/domains/business/logic_rules.md +134 -0
  27. package/.onto/domains/business/structure_spec.md +114 -0
  28. package/.onto/domains/finance/competency_qs.md +362 -0
  29. package/.onto/domains/finance/concepts.md +194 -0
  30. package/.onto/domains/finance/conciseness_rules.md +155 -0
  31. package/.onto/domains/finance/dependency_rules.md +171 -0
  32. package/.onto/domains/finance/domain_scope.md +215 -0
  33. package/.onto/domains/finance/extension_cases.md +350 -0
  34. package/.onto/domains/finance/logic_rules.md +191 -0
  35. package/.onto/domains/finance/structure_spec.md +182 -0
  36. package/.onto/domains/llm-native-development/competency_qs.md +430 -0
  37. package/.onto/domains/llm-native-development/concepts.md +242 -0
  38. package/.onto/domains/llm-native-development/conciseness_rules.md +163 -0
  39. package/.onto/domains/llm-native-development/dependency_rules.md +216 -0
  40. package/.onto/domains/llm-native-development/domain_scope.md +197 -0
  41. package/.onto/domains/llm-native-development/extension_cases.md +474 -0
  42. package/.onto/domains/llm-native-development/logic_rules.md +123 -0
  43. package/.onto/domains/llm-native-development/prompt_interface.md +49 -0
  44. package/.onto/domains/llm-native-development/structure_spec.md +245 -0
  45. package/.onto/domains/market-intelligence/competency_qs.md +274 -0
  46. package/.onto/domains/market-intelligence/concepts.md +233 -0
  47. package/.onto/domains/market-intelligence/conciseness_rules.md +165 -0
  48. package/.onto/domains/market-intelligence/dependency_rules.md +197 -0
  49. package/.onto/domains/market-intelligence/domain_scope.md +231 -0
  50. package/.onto/domains/market-intelligence/extension_cases.md +425 -0
  51. package/.onto/domains/market-intelligence/logic_rules.md +247 -0
  52. package/.onto/domains/market-intelligence/structure_spec.md +209 -0
  53. package/.onto/domains/ontology/competency_qs.md +394 -0
  54. package/.onto/domains/ontology/concepts.md +172 -0
  55. package/.onto/domains/ontology/conciseness_rules.md +134 -0
  56. package/.onto/domains/ontology/dependency_rules.md +125 -0
  57. package/.onto/domains/ontology/domain_scope.md +114 -0
  58. package/.onto/domains/ontology/extension_cases.md +501 -0
  59. package/.onto/domains/ontology/logic_rules.md +114 -0
  60. package/.onto/domains/ontology/problem_framing_profile.md +67 -0
  61. package/.onto/domains/ontology/structure_spec.md +115 -0
  62. package/.onto/domains/palantir-foundry/RESEARCH_NOTES.md +911 -0
  63. package/.onto/domains/palantir-foundry/competency_qs.md +191 -0
  64. package/.onto/domains/palantir-foundry/competitive_comparison.md +329 -0
  65. package/.onto/domains/palantir-foundry/concepts.md +197 -0
  66. package/.onto/domains/palantir-foundry/conciseness_rules.md +245 -0
  67. package/.onto/domains/palantir-foundry/dependency_rules.md +135 -0
  68. package/.onto/domains/palantir-foundry/domain_scope.md +395 -0
  69. package/.onto/domains/palantir-foundry/extension_cases.md +210 -0
  70. package/.onto/domains/palantir-foundry/logic_rules.md +172 -0
  71. package/.onto/domains/palantir-foundry/structure_spec.md +291 -0
  72. package/.onto/domains/software-engineering/competency_qs.md +538 -0
  73. package/.onto/domains/software-engineering/concepts.md +238 -0
  74. package/.onto/domains/software-engineering/conciseness_rules.md +167 -0
  75. package/.onto/domains/software-engineering/dependency_rules.md +216 -0
  76. package/.onto/domains/software-engineering/domain_scope.md +183 -0
  77. package/.onto/domains/software-engineering/extension_cases.md +551 -0
  78. package/.onto/domains/software-engineering/logic_rules.md +240 -0
  79. package/.onto/domains/software-engineering/problem_framing_profile.md +68 -0
  80. package/.onto/domains/software-engineering/structure_spec.md +185 -0
  81. package/.onto/domains/ui-design/competency_qs.md +567 -0
  82. package/.onto/domains/ui-design/concepts.md +194 -0
  83. package/.onto/domains/ui-design/conciseness_rules.md +190 -0
  84. package/.onto/domains/ui-design/dependency_rules.md +323 -0
  85. package/.onto/domains/ui-design/domain_scope.md +340 -0
  86. package/.onto/domains/ui-design/extension_cases.md +563 -0
  87. package/.onto/domains/ui-design/logic_rules.md +349 -0
  88. package/.onto/domains/ui-design/structure_spec.md +252 -0
  89. package/.onto/domains/visual-design/competency_qs.md +472 -0
  90. package/.onto/domains/visual-design/concepts.md +147 -0
  91. package/.onto/domains/visual-design/conciseness_rules.md +186 -0
  92. package/.onto/domains/visual-design/dependency_rules.md +282 -0
  93. package/.onto/domains/visual-design/domain_scope.md +290 -0
  94. package/.onto/domains/visual-design/extension_cases.md +480 -0
  95. package/.onto/domains/visual-design/logic_rules.md +232 -0
  96. package/.onto/domains/visual-design/structure_spec.md +213 -0
  97. package/.onto/principles/llm-native-development-guideline.md +401 -0
  98. package/.onto/principles/llm-runtime-interface-principles.md +665 -0
  99. package/.onto/principles/non-specialist-communication-guideline.md +74 -0
  100. package/.onto/principles/ontology-as-code-guideline.md +243 -0
  101. package/.onto/principles/ontology-as-code-naming-charter.md +130 -0
  102. package/.onto/principles/product-locality-principle.md +129 -0
  103. package/.onto/principles/productization-charter.md +569 -0
  104. package/.onto/processes/evolve/material-kind-adapter-contract.md +113 -0
  105. package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +366 -0
  106. package/.onto/processes/reconstruct/source-profile-contract.md +107 -0
  107. package/.onto/processes/reconstruct/source-profiles/code.md +72 -0
  108. package/.onto/processes/reconstruct/source-profiles/database.md +74 -0
  109. package/.onto/processes/reconstruct/source-profiles/document.md +71 -0
  110. package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +79 -0
  111. package/.onto/processes/review/binding-contract.md +270 -0
  112. package/.onto/processes/review/execution-preparation-artifacts.md +281 -0
  113. package/.onto/processes/review/interpretation-contract.md +245 -0
  114. package/.onto/processes/review/issue-stance-deliberation-contract.md +761 -0
  115. package/.onto/processes/review/lens-prompt-contract.md +402 -0
  116. package/.onto/processes/review/lens-registry.md +127 -0
  117. package/.onto/processes/review/pre-dispatch-contracts.md +428 -0
  118. package/.onto/processes/review/productized-live-path.md +398 -0
  119. package/.onto/processes/review/prompt-execution-runner-contract.md +187 -0
  120. package/.onto/processes/review/record-contract.md +427 -0
  121. package/.onto/processes/review/record-field-mapping.md +337 -0
  122. package/.onto/processes/review/review-context-manifest-contract.md +356 -0
  123. package/.onto/processes/review/review-execution-ux-contract.md +809 -0
  124. package/.onto/processes/review/review-target-profile-contract.md +259 -0
  125. package/.onto/processes/review/shared-phenomenon-contract.md +129 -0
  126. package/.onto/processes/review/synthesize-prompt-contract.md +343 -0
  127. package/.onto/processes/shared/target-material-kind-contract.md +198 -0
  128. package/.onto/roles/axiology.md +81 -0
  129. package/.onto/roles/conciseness.md +36 -0
  130. package/.onto/roles/coverage.md +34 -0
  131. package/.onto/roles/dependency.md +37 -0
  132. package/.onto/roles/evolution.md +35 -0
  133. package/.onto/roles/logic.md +104 -0
  134. package/.onto/roles/pragmatics.md +32 -0
  135. package/.onto/roles/semantics.md +36 -0
  136. package/.onto/roles/structure.md +33 -0
  137. package/.onto/roles/synthesize.md +92 -0
  138. package/AGENTS.md +240 -0
  139. package/CLAUDE.md +39 -0
  140. package/README.md +287 -0
  141. package/bin/onto +92 -0
  142. package/dist/cli.js +101 -0
  143. package/dist/core-api/reconstruct-api.js +222 -0
  144. package/dist/core-api/review-api.js +1271 -0
  145. package/dist/core-runtime/cli/assemble-review-record.js +431 -0
  146. package/dist/core-runtime/cli/bootstrap-review-binding.js +186 -0
  147. package/dist/core-runtime/cli/codex-nested-dispatch.js +226 -0
  148. package/dist/core-runtime/cli/codex-nested-dispatch.test.js +390 -0
  149. package/dist/core-runtime/cli/codex-nested-teamlead-executor.js +464 -0
  150. package/dist/core-runtime/cli/codex-nested-teamlead-executor.test.js +335 -0
  151. package/dist/core-runtime/cli/codex-review-unit-executor.js +228 -0
  152. package/dist/core-runtime/cli/complete-review-session.js +64 -0
  153. package/dist/core-runtime/cli/complexity-assessment.js +153 -0
  154. package/dist/core-runtime/cli/coordinator-helpers.js +583 -0
  155. package/dist/core-runtime/cli/coordinator-state-machine-deliberation.test.js +167 -0
  156. package/dist/core-runtime/cli/coordinator-state-machine.js +794 -0
  157. package/dist/core-runtime/cli/e2e-codex-multi-agent-fixes.test.js +615 -0
  158. package/dist/core-runtime/cli/e2e-start-review-session.test.js +312 -0
  159. package/dist/core-runtime/cli/health.js +44 -0
  160. package/dist/core-runtime/cli/inline-http-review-unit-executor.js +656 -0
  161. package/dist/core-runtime/cli/inline-http-review-unit-executor.test.js +567 -0
  162. package/dist/core-runtime/cli/materialize-review-execution-preparation.js +104 -0
  163. package/dist/core-runtime/cli/materialize-review-prompt-packets.js +952 -0
  164. package/dist/core-runtime/cli/migrate-session-roots.js +118 -0
  165. package/dist/core-runtime/cli/mock-review-unit-executor.js +285 -0
  166. package/dist/core-runtime/cli/onto-tools.js +369 -0
  167. package/dist/core-runtime/cli/prepare-review-session.js +272 -0
  168. package/dist/core-runtime/cli/render-review-final-output.js +350 -0
  169. package/dist/core-runtime/cli/repo-layout-migration-replace.smoke.test.js +106 -0
  170. package/dist/core-runtime/cli/review-invoke-auto-resolution.test.js +268 -0
  171. package/dist/core-runtime/cli/review-invoke-coordinator-topology.test.js +136 -0
  172. package/dist/core-runtime/cli/review-invoke-resolver-caching.test.js +201 -0
  173. package/dist/core-runtime/cli/review-invoke-topology-dispatch.test.js +192 -0
  174. package/dist/core-runtime/cli/review-invoke.js +2030 -0
  175. package/dist/core-runtime/cli/run-review-prompt-execution.js +2152 -0
  176. package/dist/core-runtime/cli/session-root-guard.js +168 -0
  177. package/dist/core-runtime/cli/spawn-watcher.js +173 -0
  178. package/dist/core-runtime/cli/spawn-watcher.test.js +457 -0
  179. package/dist/core-runtime/cli/start-review-session.js +68 -0
  180. package/dist/core-runtime/cli/strip-wrapping-code-fence.js +56 -0
  181. package/dist/core-runtime/cli/strip-wrapping-code-fence.test.js +79 -0
  182. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.js +412 -0
  183. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.test.js +351 -0
  184. package/dist/core-runtime/cli/topology-executor-mapping.js +139 -0
  185. package/dist/core-runtime/cli/topology-executor-mapping.test.js +173 -0
  186. package/dist/core-runtime/cli/write-review-interpretation.js +81 -0
  187. package/dist/core-runtime/config/onto-config-cli.js +278 -0
  188. package/dist/core-runtime/config/onto-config-key-path.js +288 -0
  189. package/dist/core-runtime/config/onto-config-key-path.test.js +195 -0
  190. package/dist/core-runtime/config/onto-config-preview.js +108 -0
  191. package/dist/core-runtime/config/onto-config-preview.test.js +132 -0
  192. package/dist/core-runtime/discovery/config-chain.js +118 -0
  193. package/dist/core-runtime/discovery/config-chain.test.js +103 -0
  194. package/dist/core-runtime/discovery/config-profile.js +199 -0
  195. package/dist/core-runtime/discovery/config-profile.test.js +233 -0
  196. package/dist/core-runtime/discovery/host-detection.js +33 -0
  197. package/dist/core-runtime/discovery/host-detection.test.js +186 -0
  198. package/dist/core-runtime/discovery/installation-paths.js +21 -0
  199. package/dist/core-runtime/discovery/installation-paths.test.js +65 -0
  200. package/dist/core-runtime/discovery/lens-registry.js +60 -0
  201. package/dist/core-runtime/discovery/lens-registry.test.js +81 -0
  202. package/dist/core-runtime/discovery/onto-home.js +71 -0
  203. package/dist/core-runtime/discovery/path-normalization.js +28 -0
  204. package/dist/core-runtime/discovery/path-normalization.test.js +22 -0
  205. package/dist/core-runtime/discovery/plugin-path.js +72 -0
  206. package/dist/core-runtime/discovery/plugin-path.test.js +95 -0
  207. package/dist/core-runtime/discovery/project-root.js +47 -0
  208. package/dist/core-runtime/discovery/settings-chain.js +353 -0
  209. package/dist/core-runtime/discovery/walk-up.js +17 -0
  210. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.js +344 -0
  211. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.test.js +915 -0
  212. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.js +564 -0
  213. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.test.js +708 -0
  214. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.js +165 -0
  215. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.test.js +227 -0
  216. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.js +59 -0
  217. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.test.js +205 -0
  218. package/dist/core-runtime/evolve/adapters/methodology/adapter.js +16 -0
  219. package/dist/core-runtime/evolve/adapters/methodology/adapter.test.js +9 -0
  220. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.js +298 -0
  221. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.test.js +70 -0
  222. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.js +46 -0
  223. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.test.js +73 -0
  224. package/dist/core-runtime/evolve/adapters/registry.js +47 -0
  225. package/dist/core-runtime/evolve/adapters/registry.test.js +67 -0
  226. package/dist/core-runtime/evolve/cli.js +256 -0
  227. package/dist/core-runtime/evolve/commands/align.js +194 -0
  228. package/dist/core-runtime/evolve/commands/align.test.js +82 -0
  229. package/dist/core-runtime/evolve/commands/apply.js +161 -0
  230. package/dist/core-runtime/evolve/commands/apply.test.js +138 -0
  231. package/dist/core-runtime/evolve/commands/close.js +39 -0
  232. package/dist/core-runtime/evolve/commands/close.test.js +99 -0
  233. package/dist/core-runtime/evolve/commands/defer.js +40 -0
  234. package/dist/core-runtime/evolve/commands/defer.test.js +134 -0
  235. package/dist/core-runtime/evolve/commands/draft.js +323 -0
  236. package/dist/core-runtime/evolve/commands/draft.test.js +178 -0
  237. package/dist/core-runtime/evolve/commands/e2e-evolve-full-cycle.test.js +208 -0
  238. package/dist/core-runtime/evolve/commands/error-messages.js +125 -0
  239. package/dist/core-runtime/evolve/commands/error-messages.test.js +167 -0
  240. package/dist/core-runtime/evolve/commands/propose-align.js +222 -0
  241. package/dist/core-runtime/evolve/commands/propose-align.test.js +136 -0
  242. package/dist/core-runtime/evolve/commands/reconstruct.js +330 -0
  243. package/dist/core-runtime/evolve/commands/reconstruct.test.js +278 -0
  244. package/dist/core-runtime/evolve/commands/shared.js +22 -0
  245. package/dist/core-runtime/evolve/commands/stale-check.js +103 -0
  246. package/dist/core-runtime/evolve/commands/stale-check.test.js +84 -0
  247. package/dist/core-runtime/evolve/commands/start.js +887 -0
  248. package/dist/core-runtime/evolve/commands/start.test.js +396 -0
  249. package/dist/core-runtime/evolve/config/project-config.js +99 -0
  250. package/dist/core-runtime/evolve/config/project-config.test.js +170 -0
  251. package/dist/core-runtime/evolve/renderers/align-packet.js +280 -0
  252. package/dist/core-runtime/evolve/renderers/align-packet.test.js +332 -0
  253. package/dist/core-runtime/evolve/renderers/draft-packet.js +303 -0
  254. package/dist/core-runtime/evolve/renderers/draft-packet.test.js +377 -0
  255. package/dist/core-runtime/evolve/renderers/format.js +5 -0
  256. package/dist/core-runtime/evolve/renderers/scope-md.js +237 -0
  257. package/dist/core-runtime/evolve/renderers/scope-md.test.js +306 -0
  258. package/dist/core-runtime/govern/cli.js +369 -0
  259. package/dist/core-runtime/govern/cli.test.js +314 -0
  260. package/dist/core-runtime/govern/drift-engine.js +103 -0
  261. package/dist/core-runtime/govern/drift-engine.test.js +319 -0
  262. package/dist/core-runtime/govern/promote-principle.js +206 -0
  263. package/dist/core-runtime/govern/promote-principle.test.js +368 -0
  264. package/dist/core-runtime/govern/queue.js +81 -0
  265. package/dist/core-runtime/govern/types.js +16 -0
  266. package/dist/core-runtime/install/cli.js +530 -0
  267. package/dist/core-runtime/install/detect.js +128 -0
  268. package/dist/core-runtime/install/detect.test.js +155 -0
  269. package/dist/core-runtime/install/gitignore-update.js +74 -0
  270. package/dist/core-runtime/install/gitignore-update.test.js +64 -0
  271. package/dist/core-runtime/install/install-integration.test.js +373 -0
  272. package/dist/core-runtime/install/prompts.js +389 -0
  273. package/dist/core-runtime/install/prompts.test.js +293 -0
  274. package/dist/core-runtime/install/types.js +26 -0
  275. package/dist/core-runtime/install/validation.js +295 -0
  276. package/dist/core-runtime/install/validation.test.js +313 -0
  277. package/dist/core-runtime/install/writer.js +254 -0
  278. package/dist/core-runtime/install/writer.test.js +218 -0
  279. package/dist/core-runtime/learning/extractor.js +461 -0
  280. package/dist/core-runtime/learning/feedback.js +179 -0
  281. package/dist/core-runtime/learning/health-report.js +165 -0
  282. package/dist/core-runtime/learning/health-report.test.js +169 -0
  283. package/dist/core-runtime/learning/loader.js +388 -0
  284. package/dist/core-runtime/learning/loader.test.js +102 -0
  285. package/dist/core-runtime/learning/promote/apply-state.js +240 -0
  286. package/dist/core-runtime/learning/promote/audit-obligation.js +195 -0
  287. package/dist/core-runtime/learning/promote/collector.js +432 -0
  288. package/dist/core-runtime/learning/promote/degraded-state.js +125 -0
  289. package/dist/core-runtime/learning/promote/domain-doc-proposer.js +166 -0
  290. package/dist/core-runtime/learning/promote/e2e-promote.test.js +6385 -0
  291. package/dist/core-runtime/learning/promote/health-snapshot.js +150 -0
  292. package/dist/core-runtime/learning/promote/insight-reclassifier.js +544 -0
  293. package/dist/core-runtime/learning/promote/judgment-auditor.js +517 -0
  294. package/dist/core-runtime/learning/promote/panel-reviewer.js +1158 -0
  295. package/dist/core-runtime/learning/promote/promote-executor.js +1675 -0
  296. package/dist/core-runtime/learning/promote/promoter.js +307 -0
  297. package/dist/core-runtime/learning/promote/retirement.js +122 -0
  298. package/dist/core-runtime/learning/promote/types.js +23 -0
  299. package/dist/core-runtime/learning/prompt-sections.js +51 -0
  300. package/dist/core-runtime/learning/shared/artifact-registry-init.js +45 -0
  301. package/dist/core-runtime/learning/shared/artifact-registry.js +254 -0
  302. package/dist/core-runtime/learning/shared/audit-obligation-kernel.js +73 -0
  303. package/dist/core-runtime/learning/shared/audit-state.js +99 -0
  304. package/dist/core-runtime/learning/shared/duplicate-check.js +28 -0
  305. package/dist/core-runtime/learning/shared/llm-caller.js +831 -0
  306. package/dist/core-runtime/learning/shared/llm-caller.test.js +601 -0
  307. package/dist/core-runtime/learning/shared/llm-tool-loop.js +393 -0
  308. package/dist/core-runtime/learning/shared/mode.js +25 -0
  309. package/dist/core-runtime/learning/shared/paths.js +84 -0
  310. package/dist/core-runtime/learning/shared/paths.test.js +79 -0
  311. package/dist/core-runtime/learning/shared/patterns.js +37 -0
  312. package/dist/core-runtime/learning/shared/recoverability.js +355 -0
  313. package/dist/core-runtime/learning/shared/recovery-context.js +374 -0
  314. package/dist/core-runtime/learning/shared/scope.js +1 -0
  315. package/dist/core-runtime/learning/shared/semantic-classifier.js +94 -0
  316. package/dist/core-runtime/learning/shared/specs/apply-execution-state-spec.js +42 -0
  317. package/dist/core-runtime/learning/shared/specs/audit-state-spec.js +37 -0
  318. package/dist/core-runtime/learning/shared/specs/backup-metadata-spec.js +39 -0
  319. package/dist/core-runtime/learning/shared/specs/emergency-log-spec.js +41 -0
  320. package/dist/core-runtime/learning/shared/specs/layout-version-spec.js +38 -0
  321. package/dist/core-runtime/learning/shared/specs/promote-decisions-spec.js +43 -0
  322. package/dist/core-runtime/learning/shared/specs/promote-report-spec.js +113 -0
  323. package/dist/core-runtime/learning/shared/specs/prune-log-spec.js +36 -0
  324. package/dist/core-runtime/learning/shared/specs/recovery-resolution-spec.js +48 -0
  325. package/dist/core-runtime/learning/shared/specs/restore-manifest-spec.js +43 -0
  326. package/dist/core-runtime/learning/shared/specs/spec-helpers.js +64 -0
  327. package/dist/core-runtime/learning/usage-tracker.js +190 -0
  328. package/dist/core-runtime/learning/usage-tracker.test.js +176 -0
  329. package/dist/core-runtime/llm/llm-caller.js +649 -0
  330. package/dist/core-runtime/llm/llm-tool-loop.js +401 -0
  331. package/dist/core-runtime/llm/model-switcher.js +62 -0
  332. package/dist/core-runtime/logger.js +22 -0
  333. package/dist/core-runtime/onboard/detect-review-axes.js +122 -0
  334. package/dist/core-runtime/onboard/detect-review-axes.test.js +127 -0
  335. package/dist/core-runtime/onboard/write-review-block.js +188 -0
  336. package/dist/core-runtime/onboard/write-review-block.test.js +240 -0
  337. package/dist/core-runtime/readers/brownfield-builder.js +150 -0
  338. package/dist/core-runtime/readers/brownfield-builder.test.js +136 -0
  339. package/dist/core-runtime/readers/code-chunk-collector.js +53 -0
  340. package/dist/core-runtime/readers/code-chunk-collector.test.js +136 -0
  341. package/dist/core-runtime/readers/file-utils.js +240 -0
  342. package/dist/core-runtime/readers/file-utils.test.js +146 -0
  343. package/dist/core-runtime/readers/lexicon-citation-check.js +93 -0
  344. package/dist/core-runtime/readers/lexicon-citation-check.test.js +77 -0
  345. package/dist/core-runtime/readers/mcp-figma.js +30 -0
  346. package/dist/core-runtime/readers/mcp-figma.test.js +82 -0
  347. package/dist/core-runtime/readers/mcp-generic.js +31 -0
  348. package/dist/core-runtime/readers/mcp-generic.test.js +76 -0
  349. package/dist/core-runtime/readers/ontology-index.js +148 -0
  350. package/dist/core-runtime/readers/ontology-index.test.js +245 -0
  351. package/dist/core-runtime/readers/ontology-query.js +168 -0
  352. package/dist/core-runtime/readers/ontology-query.test.js +311 -0
  353. package/dist/core-runtime/readers/ontology-resolve.js +48 -0
  354. package/dist/core-runtime/readers/ontology-resolve.test.js +48 -0
  355. package/dist/core-runtime/readers/patterns/index.js +7 -0
  356. package/dist/core-runtime/readers/review-log.js +213 -0
  357. package/dist/core-runtime/readers/review-log.test.js +313 -0
  358. package/dist/core-runtime/readers/scan-local.js +102 -0
  359. package/dist/core-runtime/readers/scan-local.test.js +102 -0
  360. package/dist/core-runtime/readers/scan-tarball.js +121 -0
  361. package/dist/core-runtime/readers/scan-tarball.test.js +283 -0
  362. package/dist/core-runtime/readers/scan-vault.js +34 -0
  363. package/dist/core-runtime/readers/scan-vault.test.js +81 -0
  364. package/dist/core-runtime/readers/types.js +42 -0
  365. package/dist/core-runtime/readers/types.test.js +94 -0
  366. package/dist/core-runtime/readers/viewpoint-collectors.js +229 -0
  367. package/dist/core-runtime/reconstruct/artifact-types.js +1 -0
  368. package/dist/core-runtime/reconstruct/directive-validation.js +123 -0
  369. package/dist/core-runtime/reconstruct/materialize-preparation.js +251 -0
  370. package/dist/core-runtime/reconstruct/record.js +198 -0
  371. package/dist/core-runtime/reconstruct/run.js +578 -0
  372. package/dist/core-runtime/reconstruct/seed-candidate-validation.js +356 -0
  373. package/dist/core-runtime/reconstruct/source-observations.js +62 -0
  374. package/dist/core-runtime/reconstruct/source-profiles.js +73 -0
  375. package/dist/core-runtime/release-channel/release-channel.js +90 -0
  376. package/dist/core-runtime/review/artifact-types.js +13 -0
  377. package/dist/core-runtime/review/citation-audit.js +204 -0
  378. package/dist/core-runtime/review/citation-audit.test.js +165 -0
  379. package/dist/core-runtime/review/controlled-lens-deliberation.js +125 -0
  380. package/dist/core-runtime/review/execution-plan-resolver.js +247 -0
  381. package/dist/core-runtime/review/execution-plan-resolver.test.js +243 -0
  382. package/dist/core-runtime/review/execution-topology-resolver-axis-first.test.js +246 -0
  383. package/dist/core-runtime/review/execution-topology-resolver.js +401 -0
  384. package/dist/core-runtime/review/execution-topology-resolver.test.js +315 -0
  385. package/dist/core-runtime/review/failure-records.js +57 -0
  386. package/dist/core-runtime/review/inline-context-embedder.js +141 -0
  387. package/dist/core-runtime/review/inline-context-embedder.test.js +154 -0
  388. package/dist/core-runtime/review/issue-artifact-runtime.js +859 -0
  389. package/dist/core-runtime/review/legacy-mode-policy.js +88 -0
  390. package/dist/core-runtime/review/lens-completion-policy.js +17 -0
  391. package/dist/core-runtime/review/materializers-effort-persist.test.js +79 -0
  392. package/dist/core-runtime/review/materializers.js +963 -0
  393. package/dist/core-runtime/review/ontology-path-classifier.js +179 -0
  394. package/dist/core-runtime/review/ontology-path-classifier.test.js +216 -0
  395. package/dist/core-runtime/review/packet-boundary-policy.js +215 -0
  396. package/dist/core-runtime/review/packet-boundary-policy.test.js +107 -0
  397. package/dist/core-runtime/review/participating-lens-paths.js +61 -0
  398. package/dist/core-runtime/review/participating-lens-paths.test.js +73 -0
  399. package/dist/core-runtime/review/review-artifact-utils.js +287 -0
  400. package/dist/core-runtime/review/review-config-legacy-translate.js +244 -0
  401. package/dist/core-runtime/review/review-config-legacy-translate.test.js +161 -0
  402. package/dist/core-runtime/review/review-config-validator.js +289 -0
  403. package/dist/core-runtime/review/review-config-validator.test.js +236 -0
  404. package/dist/core-runtime/review/review-execution-profile.js +193 -0
  405. package/dist/core-runtime/review/review-execution-route.js +52 -0
  406. package/dist/core-runtime/review/review-progress-contract.js +123 -0
  407. package/dist/core-runtime/review/review-record-validation.js +251 -0
  408. package/dist/core-runtime/review/review-result-classification.js +379 -0
  409. package/dist/core-runtime/review/review-state-machine.js +39 -0
  410. package/dist/core-runtime/review/route-visibility.js +125 -0
  411. package/dist/core-runtime/review/shape-pipeline-audit.test.js +311 -0
  412. package/dist/core-runtime/review/shape-to-topology-id.js +117 -0
  413. package/dist/core-runtime/review/shape-to-topology-id.test.js +132 -0
  414. package/dist/core-runtime/review/topology-shape-derivation.js +155 -0
  415. package/dist/core-runtime/review/topology-shape-derivation.test.js +195 -0
  416. package/dist/core-runtime/scope-runtime/constants.js +12 -0
  417. package/dist/core-runtime/scope-runtime/constraint-pool.js +166 -0
  418. package/dist/core-runtime/scope-runtime/constraint-pool.test.js +674 -0
  419. package/dist/core-runtime/scope-runtime/domain-validation-log.js +135 -0
  420. package/dist/core-runtime/scope-runtime/domain-validation-log.test.js +156 -0
  421. package/dist/core-runtime/scope-runtime/eval-persistence.js +65 -0
  422. package/dist/core-runtime/scope-runtime/eval-persistence.test.js +84 -0
  423. package/dist/core-runtime/scope-runtime/event-pipeline.js +64 -0
  424. package/dist/core-runtime/scope-runtime/event-pipeline.test.js +450 -0
  425. package/dist/core-runtime/scope-runtime/event-store.js +39 -0
  426. package/dist/core-runtime/scope-runtime/event-store.test.js +95 -0
  427. package/dist/core-runtime/scope-runtime/gate-guard.js +348 -0
  428. package/dist/core-runtime/scope-runtime/gate-guard.test.js +1047 -0
  429. package/dist/core-runtime/scope-runtime/hash.js +4 -0
  430. package/dist/core-runtime/scope-runtime/hash.test.js +33 -0
  431. package/dist/core-runtime/scope-runtime/id.js +4 -0
  432. package/dist/core-runtime/scope-runtime/id.test.js +17 -0
  433. package/dist/core-runtime/scope-runtime/reducer.js +297 -0
  434. package/dist/core-runtime/scope-runtime/reducer.test.js +759 -0
  435. package/dist/core-runtime/scope-runtime/scope-manager.js +161 -0
  436. package/dist/core-runtime/scope-runtime/state-machine.js +309 -0
  437. package/dist/core-runtime/scope-runtime/state-machine.test.js +704 -0
  438. package/dist/core-runtime/scope-runtime/types.js +116 -0
  439. package/dist/core-runtime/scope-runtime/types.test.js +69 -0
  440. package/dist/core-runtime/target-material-kind.js +256 -0
  441. package/dist/core-runtime/translate/render-for-user.js +169 -0
  442. package/dist/core-runtime/translate/render-for-user.test.js +122 -0
  443. package/dist/mcp/server.js +1011 -0
  444. package/dist/mcp/tool-schemas.js +93 -0
  445. package/dist/providers/capability-contract.js +1 -0
  446. package/package.json +68 -0
  447. package/settings.example.json +33 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Review UX Redesign P1 — legacy → v3 axis translation (pure functions).
3
+ *
4
+ * # What this module is
5
+ *
6
+ * Two pure translators that convert **legacy** config representations
7
+ * (`execution_topology_priority` entries, or legacy provider-profile YAML)
8
+ * into the new `OntoReviewConfig` axis form:
9
+ *
10
+ * - `legacyTopologyIdToAxes(id)` — single topology id → partial axes.
11
+ * - `legacyFieldsToReviewConfig(raw)` — top-level YAML (possibly holding
12
+ * `execution_topology_priority`) → partial `OntoReviewConfig`.
13
+ *
14
+ * # Why it exists
15
+ *
16
+ * P4 (onboard) and P5 (`onto config`) migrate existing configs to the new
17
+ * schema. Doing the translation in a pure, side-effect-free module means
18
+ * both flows share identical semantics and P1 can ship coverage tests
19
+ * without any runtime wiring. P1 does NOT call these functions from
20
+ * runtime — they are library-only.
21
+ *
22
+ * # How it relates
23
+ *
24
+ * - Input: legacy identifier(s) from the existing sketch-v3 schema.
25
+ * - Output: `Partial<OntoReviewConfig>` — caller overlays remaining
26
+ * user preferences (effort, concurrency) on top.
27
+ * - Mapping table: see design doc §7.2 (authoritative).
28
+ *
29
+ * # Scope note (post-P9.2, 2026-04-21)
30
+ *
31
+ * P9.2 removed `execution_topology_priority` from the `OntoConfig` type.
32
+ * In-process code can no longer carry this field, so this translator's
33
+ * only remaining caller is **disk-based legacy YAML migration** (onboard
34
+ * re-detect reading an old `.onto/config.yml` before any typing pass).
35
+ * The `raw` parameter stays typed as `Record<string, unknown>` precisely
36
+ * to support that pre-type reading — the input shape is what YAML
37
+ * produced, not a current OntoConfig.
38
+ */
39
+ // ---------------------------------------------------------------------------
40
+ // Legacy topology id → axes
41
+ // ---------------------------------------------------------------------------
42
+ /**
43
+ * Translate a single legacy topology id (from `execution_topology_priority`)
44
+ * to partial axis config.
45
+ *
46
+ * Returns `null` for:
47
+ * - Unknown ids.
48
+ * - `generic-*` ids (explicitly marked "unimplemented / invalid" in
49
+ * design doc §7.2, dropped from the v3 catalog).
50
+ *
51
+ * Mapping table is the authoritative design doc §7.2.
52
+ */
53
+ export function legacyTopologyIdToAxes(id) {
54
+ switch (id) {
55
+ case "cc-main-agent-subagent":
56
+ return {
57
+ teamlead: { model: "main" },
58
+ subagent: { provider: "main-native" },
59
+ runtime_preconditions: {},
60
+ };
61
+ case "cc-main-codex-subprocess":
62
+ return {
63
+ teamlead: { model: "main" },
64
+ subagent: {
65
+ provider: "codex",
66
+ // model_id is required by the discriminated union. Legacy configs
67
+ // did not carry it at this level (codex.* block held it). Caller
68
+ // overlays from `config.codex.model` if available; absent that,
69
+ // the validator will later flag this partial translation.
70
+ model_id: "",
71
+ },
72
+ runtime_preconditions: {},
73
+ };
74
+ case "cc-teams-agent-subagent":
75
+ return {
76
+ teamlead: { model: "main" },
77
+ subagent: { provider: "main-native" },
78
+ runtime_preconditions: {
79
+ requires_agent_teams_env: true,
80
+ },
81
+ };
82
+ case "cc-teams-codex-subprocess":
83
+ return {
84
+ teamlead: { model: "main" },
85
+ subagent: {
86
+ provider: "codex",
87
+ model_id: "",
88
+ },
89
+ runtime_preconditions: {
90
+ requires_agent_teams_env: true,
91
+ },
92
+ };
93
+ case "cc-teams-litellm-sessions":
94
+ return {
95
+ teamlead: { model: "main" },
96
+ subagent: {
97
+ provider: "litellm",
98
+ model_id: "",
99
+ },
100
+ runtime_preconditions: {
101
+ requires_agent_teams_env: true,
102
+ },
103
+ };
104
+ case "cc-teams-lens-agent-deliberation":
105
+ return {
106
+ teamlead: { model: "main" },
107
+ subagent: { provider: "main-native" },
108
+ lens_deliberation: "sendmessage-a2a",
109
+ runtime_preconditions: {
110
+ requires_agent_teams_env: true,
111
+ },
112
+ };
113
+ case "codex-main-subprocess":
114
+ return {
115
+ teamlead: { model: "main" },
116
+ subagent: { provider: "main-native" },
117
+ runtime_preconditions: {
118
+ implies_host_codex: true,
119
+ },
120
+ };
121
+ case "codex-nested-subprocess":
122
+ return {
123
+ teamlead: {
124
+ model: {
125
+ provider: "codex",
126
+ model_id: "",
127
+ },
128
+ },
129
+ subagent: {
130
+ provider: "codex",
131
+ model_id: "",
132
+ },
133
+ runtime_preconditions: {
134
+ implies_host_plain_terminal: true,
135
+ },
136
+ };
137
+ // generic-nested-subagent / generic-main-subagent: dropped per §7.2.
138
+ default:
139
+ return null;
140
+ }
141
+ }
142
+ /**
143
+ * Translate a legacy-shaped YAML object (top-level, post-cast) to partial
144
+ * OntoReviewConfig. Consults `execution_topology_priority` first entry and
145
+ * overlays model/effort from per-provider blocks (codex.*, litellm.*, etc.)
146
+ * when available.
147
+ *
148
+ * Returns `null` when no legacy signal is present (no
149
+ * `execution_topology_priority` entry and no recognized provider block).
150
+ */
151
+ export function legacyFieldsToReviewConfig(raw) {
152
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
153
+ return null;
154
+ }
155
+ const obj = raw;
156
+ const priority = obj.execution_topology_priority;
157
+ if (!Array.isArray(priority) || priority.length === 0) {
158
+ return null;
159
+ }
160
+ const firstId = priority[0];
161
+ if (typeof firstId !== "string") {
162
+ return null;
163
+ }
164
+ const axes = legacyTopologyIdToAxes(firstId);
165
+ if (!axes) {
166
+ return null;
167
+ }
168
+ const warnings = [];
169
+ const out = {};
170
+ if (axes.teamlead) {
171
+ out.teamlead = overlayTeamleadModelFields(axes.teamlead, obj, warnings);
172
+ }
173
+ if (axes.subagent) {
174
+ out.subagent = overlaySubagentModelFields(axes.subagent, obj, warnings);
175
+ }
176
+ if (axes.lens_deliberation) {
177
+ out.lens_deliberation = axes.lens_deliberation;
178
+ }
179
+ return {
180
+ config: out,
181
+ source_topology_id: firstId,
182
+ runtime_preconditions: axes.runtime_preconditions,
183
+ warnings,
184
+ };
185
+ }
186
+ function overlayTeamleadModelFields(teamlead, raw, warnings) {
187
+ if (teamlead.model === "main") {
188
+ return teamlead;
189
+ }
190
+ // External teamlead — overlay model_id / effort from legacy per-provider
191
+ // block (only codex is reachable via current legacy topology ids).
192
+ const provider = teamlead.model.provider;
193
+ const block = readProviderBlock(raw, provider);
194
+ const modelId = teamlead.model.model_id || readModelIdFromBlock(block) || "";
195
+ const effort = teamlead.model.effort || readEffortFromBlock(block);
196
+ if (!modelId) {
197
+ warnings.push(`teamlead.model.model_id 미지정 — 기존 config 의 ${provider}.model 이 없습니다. ` +
198
+ "새 config 의 teamlead.model.model_id 를 직접 채워주세요.");
199
+ }
200
+ return {
201
+ model: {
202
+ provider,
203
+ model_id: modelId,
204
+ ...(effort ? { effort } : {}),
205
+ },
206
+ };
207
+ }
208
+ function overlaySubagentModelFields(subagent, raw, warnings) {
209
+ if (subagent.provider === "main-native") {
210
+ return subagent;
211
+ }
212
+ const provider = subagent.provider;
213
+ const block = readProviderBlock(raw, provider);
214
+ const modelId = subagent.model_id || readModelIdFromBlock(block) || "";
215
+ const effort = subagent.effort || readEffortFromBlock(block);
216
+ if (!modelId) {
217
+ warnings.push(`subagent.model_id 미지정 — 기존 config 의 ${provider}.model 이 없습니다. ` +
218
+ "새 config 의 subagent.model_id 를 직접 채워주세요.");
219
+ }
220
+ return {
221
+ provider,
222
+ model_id: modelId,
223
+ ...(effort ? { effort } : {}),
224
+ };
225
+ }
226
+ function readProviderBlock(raw, provider) {
227
+ const block = raw[provider];
228
+ if (typeof block === "object" && block !== null && !Array.isArray(block)) {
229
+ return block;
230
+ }
231
+ return null;
232
+ }
233
+ function readModelIdFromBlock(block) {
234
+ if (!block)
235
+ return null;
236
+ const model = block.model;
237
+ return typeof model === "string" && model.length > 0 ? model : null;
238
+ }
239
+ function readEffortFromBlock(block) {
240
+ if (!block)
241
+ return null;
242
+ const effort = block.effort;
243
+ return typeof effort === "string" && effort.length > 0 ? effort : null;
244
+ }
@@ -0,0 +1,161 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { legacyFieldsToReviewConfig, legacyTopologyIdToAxes, } from "./review-config-legacy-translate.js";
3
+ // ---------------------------------------------------------------------------
4
+ // legacy translation — Review UX Redesign P1 (2026-04-20)
5
+ // ---------------------------------------------------------------------------
6
+ //
7
+ // Authoritative mapping table: design doc §7.2.
8
+ // - 8 known legacy topology ids → partial axes (each with specific runtime
9
+ // preconditions where applicable).
10
+ // - 2 generic-* ids → null (dropped from v3 catalog).
11
+ // - unknown ids → null.
12
+ //
13
+ // legacyFieldsToReviewConfig also overlays model_id / effort from legacy
14
+ // per-provider blocks (codex.* / litellm.* / etc.) into the translated axes.
15
+ // ---------------------------------------------------------------------------
16
+ describe("legacyTopologyIdToAxes — §7.2 mapping table", () => {
17
+ it("cc-main-agent-subagent → teamlead=main, subagent=main-native", () => {
18
+ const a = legacyTopologyIdToAxes("cc-main-agent-subagent");
19
+ expect(a).not.toBeNull();
20
+ expect(a?.teamlead).toEqual({ model: "main" });
21
+ expect(a?.subagent).toEqual({ provider: "main-native" });
22
+ expect(a?.runtime_preconditions).toEqual({});
23
+ });
24
+ it("cc-main-codex-subprocess → teamlead=main, subagent=codex", () => {
25
+ const a = legacyTopologyIdToAxes("cc-main-codex-subprocess");
26
+ expect(a?.subagent).toMatchObject({ provider: "codex" });
27
+ expect(a?.runtime_preconditions).toEqual({});
28
+ });
29
+ it("cc-teams-agent-subagent → requires_agent_teams_env=true", () => {
30
+ const a = legacyTopologyIdToAxes("cc-teams-agent-subagent");
31
+ expect(a?.subagent).toEqual({ provider: "main-native" });
32
+ expect(a?.runtime_preconditions.requires_agent_teams_env).toBe(true);
33
+ });
34
+ it("cc-teams-codex-subprocess → requires_agent_teams_env=true + codex", () => {
35
+ const a = legacyTopologyIdToAxes("cc-teams-codex-subprocess");
36
+ expect(a?.subagent).toMatchObject({ provider: "codex" });
37
+ expect(a?.runtime_preconditions.requires_agent_teams_env).toBe(true);
38
+ });
39
+ it("cc-teams-litellm-sessions → requires_agent_teams_env=true + litellm", () => {
40
+ const a = legacyTopologyIdToAxes("cc-teams-litellm-sessions");
41
+ expect(a?.subagent).toMatchObject({ provider: "litellm" });
42
+ expect(a?.runtime_preconditions.requires_agent_teams_env).toBe(true);
43
+ });
44
+ it("cc-teams-lens-agent-deliberation → lens_deliberation=sendmessage-a2a", () => {
45
+ const a = legacyTopologyIdToAxes("cc-teams-lens-agent-deliberation");
46
+ expect(a?.subagent).toEqual({ provider: "main-native" });
47
+ expect(a?.lens_deliberation).toBe("sendmessage-a2a");
48
+ expect(a?.runtime_preconditions.requires_agent_teams_env).toBe(true);
49
+ });
50
+ it("codex-main-subprocess → implies_host_codex=true", () => {
51
+ const a = legacyTopologyIdToAxes("codex-main-subprocess");
52
+ expect(a?.subagent).toEqual({ provider: "main-native" });
53
+ expect(a?.runtime_preconditions.implies_host_codex).toBe(true);
54
+ });
55
+ it("codex-nested-subprocess → external teamlead=codex + plain-terminal host", () => {
56
+ const a = legacyTopologyIdToAxes("codex-nested-subprocess");
57
+ expect(a?.teamlead?.model).toMatchObject({ provider: "codex" });
58
+ expect(a?.subagent).toMatchObject({ provider: "codex" });
59
+ expect(a?.runtime_preconditions.implies_host_plain_terminal).toBe(true);
60
+ });
61
+ it("generic-nested-subagent → null (dropped from v3 catalog)", () => {
62
+ expect(legacyTopologyIdToAxes("generic-nested-subagent")).toBeNull();
63
+ });
64
+ it("generic-main-subagent → null (dropped from v3 catalog)", () => {
65
+ expect(legacyTopologyIdToAxes("generic-main-subagent")).toBeNull();
66
+ });
67
+ it("unknown id → null", () => {
68
+ expect(legacyTopologyIdToAxes("not-a-real-topology")).toBeNull();
69
+ expect(legacyTopologyIdToAxes("")).toBeNull();
70
+ });
71
+ });
72
+ describe("legacyFieldsToReviewConfig — overlay provider blocks", () => {
73
+ it("returns null when no execution_topology_priority", () => {
74
+ expect(legacyFieldsToReviewConfig({})).toBeNull();
75
+ expect(legacyFieldsToReviewConfig({ codex: { model: "gpt-5.4" } })).toBeNull();
76
+ });
77
+ it("returns null for empty priority array", () => {
78
+ expect(legacyFieldsToReviewConfig({ execution_topology_priority: [] })).toBeNull();
79
+ });
80
+ it("uses first entry of priority array", () => {
81
+ const r = legacyFieldsToReviewConfig({
82
+ execution_topology_priority: [
83
+ "cc-main-codex-subprocess",
84
+ "codex-main-subprocess",
85
+ ],
86
+ codex: { model: "gpt-5.4", effort: "high" },
87
+ });
88
+ expect(r).not.toBeNull();
89
+ expect(r?.source_topology_id).toBe("cc-main-codex-subprocess");
90
+ expect(r?.config.subagent).toEqual({
91
+ provider: "codex",
92
+ model_id: "gpt-5.4",
93
+ effort: "high",
94
+ });
95
+ });
96
+ it("overlays codex.model + codex.effort into subagent axes", () => {
97
+ const r = legacyFieldsToReviewConfig({
98
+ execution_topology_priority: ["cc-teams-codex-subprocess"],
99
+ codex: { model: "gpt-5.4-preview", effort: "xhigh" },
100
+ });
101
+ expect(r?.config.subagent).toEqual({
102
+ provider: "codex",
103
+ model_id: "gpt-5.4-preview",
104
+ effort: "xhigh",
105
+ });
106
+ expect(r?.runtime_preconditions.requires_agent_teams_env).toBe(true);
107
+ });
108
+ it("overlays litellm.model into litellm subagent", () => {
109
+ const r = legacyFieldsToReviewConfig({
110
+ execution_topology_priority: ["cc-teams-litellm-sessions"],
111
+ litellm: { model: "llama-8b" },
112
+ });
113
+ expect(r?.config.subagent).toMatchObject({
114
+ provider: "litellm",
115
+ model_id: "llama-8b",
116
+ });
117
+ });
118
+ it("warns when foreign provider block has no model", () => {
119
+ const r = legacyFieldsToReviewConfig({
120
+ execution_topology_priority: ["cc-main-codex-subprocess"],
121
+ // codex block absent — no model to overlay
122
+ });
123
+ expect(r).not.toBeNull();
124
+ expect(r?.warnings.some((w) => w.includes("model_id"))).toBe(true);
125
+ });
126
+ it("preserves lens_deliberation for deliberation topology", () => {
127
+ const r = legacyFieldsToReviewConfig({
128
+ execution_topology_priority: ["cc-teams-lens-agent-deliberation"],
129
+ });
130
+ expect(r?.config.lens_deliberation).toBe("sendmessage-a2a");
131
+ });
132
+ it("codex-nested overlays codex.model into both teamlead and subagent", () => {
133
+ const r = legacyFieldsToReviewConfig({
134
+ execution_topology_priority: ["codex-nested-subprocess"],
135
+ codex: { model: "gpt-5.4", effort: "high" },
136
+ });
137
+ expect(r?.config.teamlead?.model).toEqual({
138
+ provider: "codex",
139
+ model_id: "gpt-5.4",
140
+ effort: "high",
141
+ });
142
+ expect(r?.config.subagent).toEqual({
143
+ provider: "codex",
144
+ model_id: "gpt-5.4",
145
+ effort: "high",
146
+ });
147
+ expect(r?.runtime_preconditions.implies_host_plain_terminal).toBe(true);
148
+ });
149
+ it("returns null when first priority entry is generic-*", () => {
150
+ const r = legacyFieldsToReviewConfig({
151
+ execution_topology_priority: ["generic-main-subagent"],
152
+ });
153
+ expect(r).toBeNull();
154
+ });
155
+ it("rejects non-string first entry gracefully", () => {
156
+ const r = legacyFieldsToReviewConfig({
157
+ execution_topology_priority: [42, "cc-main-agent-subagent"],
158
+ });
159
+ expect(r).toBeNull();
160
+ });
161
+ });
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Review UX Redesign P1 — pure validator for the `review:` config block.
3
+ *
4
+ * # What this module is
5
+ *
6
+ * A pure function suite that accepts an `unknown` (the shape YAML casting
7
+ * produces under `OntoConfig.review`) and returns either a typed
8
+ * `OntoReviewConfig` or a list of structured validation errors. The
9
+ * validator enforces the **discriminated union semantics** that YAML
10
+ * cast-reads cannot verify — e.g. `subagent.provider = "main-native"` must
11
+ * not carry `model_id` / `effort`, and `subagent.provider` of a foreign
12
+ * provider must carry `model_id`.
13
+ *
14
+ * # Why it exists
15
+ *
16
+ * `readConfigAt` in `config-chain.ts` casts raw YAML into `OntoConfig`
17
+ * without runtime structure checks. Downstream consumers (P2 topology
18
+ * derivation, P4 onboard, P5 config CLI) need a single seat that both
19
+ * (a) surfaces config errors with precise `review.*.path` location and
20
+ * (b) narrows the discriminated union so compile-time type guards hold
21
+ * for the rest of the pipeline.
22
+ *
23
+ * # How it relates
24
+ *
25
+ * - Input: raw `review` block (from YAML cast). Permissively typed.
26
+ * - Output: `{ ok: true, config: OntoReviewConfig }` or
27
+ * `{ ok: false, errors: ValidationError[] }`.
28
+ * - P1 does NOT call this validator from runtime — it is pure/library.
29
+ * P2 wires the call inside the review-invoke path.
30
+ */
31
+ // Domain tables kept next to the validator — same file changes together with
32
+ // schema changes, so drift between type and validator is impossible.
33
+ const FOREIGN_PROVIDERS = ["codex"];
34
+ const SUBAGENT_PROVIDERS = ["main-native", ...FOREIGN_PROVIDERS];
35
+ const LENS_DELIBERATIONS = [
36
+ "controlled-lens-deliberation",
37
+ ];
38
+ /**
39
+ * Validate a raw `review` block (as cast from YAML) and return either the
40
+ * narrowed OntoReviewConfig or a structured error list.
41
+ *
42
+ * `undefined` / missing block → `{ ok: true, config: {}, errors: [] }`.
43
+ * Consumers should treat `{}` as the review defaults.
44
+ */
45
+ export function validateReviewConfig(raw) {
46
+ const errors = [];
47
+ if (raw === undefined || raw === null) {
48
+ return { ok: true, config: {}, errors: [] };
49
+ }
50
+ if (typeof raw !== "object" || Array.isArray(raw)) {
51
+ errors.push({
52
+ path: "review",
53
+ message: "review block must be a YAML mapping (object), not scalar/array.",
54
+ });
55
+ return { ok: false, errors };
56
+ }
57
+ const obj = raw;
58
+ const out = {};
59
+ rejectUnknownKeys(obj, ["teamlead", "subagent", "max_concurrent_lenses", "lens_deliberation"], "review", errors);
60
+ if ("teamlead" in obj) {
61
+ const teamlead = validateTeamlead(obj.teamlead, errors);
62
+ if (teamlead)
63
+ out.teamlead = teamlead;
64
+ }
65
+ if ("subagent" in obj) {
66
+ const subagent = validateSubagent(obj.subagent, errors);
67
+ if (subagent)
68
+ out.subagent = subagent;
69
+ }
70
+ if ("max_concurrent_lenses" in obj) {
71
+ const concurrency = validateConcurrency(obj.max_concurrent_lenses, errors);
72
+ if (concurrency !== null)
73
+ out.max_concurrent_lenses = concurrency;
74
+ }
75
+ if ("lens_deliberation" in obj) {
76
+ const deliberation = validateDeliberation(obj.lens_deliberation, errors);
77
+ if (deliberation)
78
+ out.lens_deliberation = deliberation;
79
+ }
80
+ if (errors.length > 0) {
81
+ return { ok: false, errors };
82
+ }
83
+ return { ok: true, config: out, errors: [] };
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // Teamlead
87
+ // ---------------------------------------------------------------------------
88
+ function validateTeamlead(raw, errors) {
89
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
90
+ errors.push({
91
+ path: "review.teamlead",
92
+ message: "teamlead must be a mapping with a `model` field.",
93
+ });
94
+ return null;
95
+ }
96
+ const obj = raw;
97
+ rejectUnknownKeys(obj, ["model"], "review.teamlead", errors);
98
+ if (!("model" in obj)) {
99
+ errors.push({
100
+ path: "review.teamlead.model",
101
+ message: "teamlead.model is required when teamlead block is declared.",
102
+ });
103
+ return null;
104
+ }
105
+ const model = obj.model;
106
+ if (model === "main") {
107
+ return { model: "main" };
108
+ }
109
+ const explicit = validateExplicitModel(model, "review.teamlead.model", errors);
110
+ if (!explicit)
111
+ return null;
112
+ return { model: explicit };
113
+ }
114
+ function validateExplicitModel(raw, pathPrefix, errors) {
115
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
116
+ errors.push({
117
+ path: pathPrefix,
118
+ message: 'model must be either "main" (string) or a mapping ' +
119
+ "{provider, model_id, effort?}.",
120
+ });
121
+ return null;
122
+ }
123
+ const obj = raw;
124
+ rejectUnknownKeys(obj, ["provider", "model_id", "effort"], pathPrefix, errors);
125
+ const provider = obj.provider;
126
+ if (typeof provider !== "string") {
127
+ errors.push({
128
+ path: `${pathPrefix}.provider`,
129
+ message: "provider must be a string.",
130
+ });
131
+ return null;
132
+ }
133
+ if (!FOREIGN_PROVIDERS.includes(provider)) {
134
+ errors.push({
135
+ path: `${pathPrefix}.provider`,
136
+ message: `provider must be one of: ${FOREIGN_PROVIDERS.join(", ")} (got "${provider}"). "main-native" is only valid under subagent, not under an explicit model spec.`,
137
+ });
138
+ return null;
139
+ }
140
+ const modelId = obj.model_id;
141
+ if (typeof modelId !== "string" || modelId.length === 0) {
142
+ errors.push({
143
+ path: `${pathPrefix}.model_id`,
144
+ message: "model_id is required (non-empty string) for foreign providers.",
145
+ });
146
+ return null;
147
+ }
148
+ const spec = {
149
+ provider: provider,
150
+ model_id: modelId,
151
+ };
152
+ if ("effort" in obj) {
153
+ if (typeof obj.effort !== "string" || obj.effort.length === 0) {
154
+ errors.push({
155
+ path: `${pathPrefix}.effort`,
156
+ message: "effort must be a non-empty string when present.",
157
+ });
158
+ return null;
159
+ }
160
+ spec.effort = obj.effort;
161
+ }
162
+ return spec;
163
+ }
164
+ // ---------------------------------------------------------------------------
165
+ // Subagent
166
+ // ---------------------------------------------------------------------------
167
+ function validateSubagent(raw, errors) {
168
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
169
+ errors.push({
170
+ path: "review.subagent",
171
+ message: "subagent must be a mapping with a `provider` field.",
172
+ });
173
+ return null;
174
+ }
175
+ const obj = raw;
176
+ rejectUnknownKeys(obj, ["provider", "model_id", "effort"], "review.subagent", errors);
177
+ const provider = obj.provider;
178
+ if (typeof provider !== "string") {
179
+ errors.push({
180
+ path: "review.subagent.provider",
181
+ message: "subagent.provider is required and must be a string.",
182
+ });
183
+ return null;
184
+ }
185
+ if (!SUBAGENT_PROVIDERS.includes(provider)) {
186
+ errors.push({
187
+ path: "review.subagent.provider",
188
+ message: `subagent.provider must be one of: ${SUBAGENT_PROVIDERS.join(", ")} (got "${provider}").`,
189
+ });
190
+ return null;
191
+ }
192
+ if (provider === "main-native") {
193
+ // Discriminated-union enforcement: main-native branch must not carry
194
+ // model_id / effort (those are foreign-provider-only).
195
+ if ("model_id" in obj) {
196
+ errors.push({
197
+ path: "review.subagent.model_id",
198
+ message: "model_id is not allowed when subagent.provider=main-native. " +
199
+ "main-native resolves via the host's native subagent mechanism.",
200
+ });
201
+ }
202
+ if ("effort" in obj) {
203
+ errors.push({
204
+ path: "review.subagent.effort",
205
+ message: "effort is not allowed when subagent.provider=main-native. " +
206
+ "Effort configuration for main-native is host-managed (e.g. Claude Code Agent tool).",
207
+ });
208
+ }
209
+ if (errors.some((e) => e.path.startsWith("review.subagent"))) {
210
+ return null;
211
+ }
212
+ return { provider: "main-native" };
213
+ }
214
+ // Foreign branch
215
+ const modelId = obj.model_id;
216
+ if (typeof modelId !== "string" || modelId.length === 0) {
217
+ errors.push({
218
+ path: "review.subagent.model_id",
219
+ message: `model_id is required (non-empty string) when subagent.provider=${provider}.`,
220
+ });
221
+ return null;
222
+ }
223
+ const spec = {
224
+ provider: provider,
225
+ model_id: modelId,
226
+ };
227
+ if ("effort" in obj) {
228
+ if (typeof obj.effort !== "string" || obj.effort.length === 0) {
229
+ errors.push({
230
+ path: "review.subagent.effort",
231
+ message: "effort must be a non-empty string when present.",
232
+ });
233
+ return null;
234
+ }
235
+ spec.effort = obj.effort;
236
+ }
237
+ return spec;
238
+ }
239
+ // ---------------------------------------------------------------------------
240
+ // Scalar axes
241
+ // ---------------------------------------------------------------------------
242
+ function validateConcurrency(raw, errors) {
243
+ if (typeof raw !== "number" || !Number.isFinite(raw)) {
244
+ errors.push({
245
+ path: "review.max_concurrent_lenses",
246
+ message: "max_concurrent_lenses must be a finite number.",
247
+ });
248
+ return null;
249
+ }
250
+ if (!Number.isInteger(raw) || raw < 1) {
251
+ errors.push({
252
+ path: "review.max_concurrent_lenses",
253
+ message: "max_concurrent_lenses must be a positive integer (>= 1).",
254
+ });
255
+ return null;
256
+ }
257
+ return raw;
258
+ }
259
+ function validateDeliberation(raw, errors) {
260
+ if (typeof raw !== "string") {
261
+ errors.push({
262
+ path: "review.lens_deliberation",
263
+ message: "lens_deliberation must be a string.",
264
+ });
265
+ return null;
266
+ }
267
+ if (!LENS_DELIBERATIONS.includes(raw)) {
268
+ errors.push({
269
+ path: "review.lens_deliberation",
270
+ message: `lens_deliberation must be one of: ${LENS_DELIBERATIONS.join(", ")} (got "${raw}").`,
271
+ });
272
+ return null;
273
+ }
274
+ return raw;
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // Shared helpers
278
+ // ---------------------------------------------------------------------------
279
+ function rejectUnknownKeys(obj, allowed, pathPrefix, errors) {
280
+ const allowedSet = new Set(allowed);
281
+ for (const key of Object.keys(obj)) {
282
+ if (!allowedSet.has(key)) {
283
+ errors.push({
284
+ path: `${pathPrefix}.${key}`,
285
+ message: `Unknown field. Allowed: ${allowed.join(", ")}.`,
286
+ });
287
+ }
288
+ }
289
+ }