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,226 @@
1
+ /**
2
+ * Codex Nested Dispatch Bridge.
3
+ *
4
+ * # What this module is
5
+ *
6
+ * The bridge between review session artifacts and the nested Codex worker
7
+ * orchestrator.
8
+ * It reads the execution plan, constructs the
9
+ * `NestedLensDispatchInput`, invokes `runCodexNestedTeamlead`, and
10
+ * classifies per-lens outcomes into the
11
+ * `ReviewPromptExecutionResult`-compatible shape used downstream by
12
+ * `completeReviewSession`.
13
+ *
14
+ * # Why it exists
15
+ *
16
+ * `runCodexNestedTeamlead` is a pure function over lens inputs → outcomes,
17
+ * intentionally decoupled from onto's session artifacts so it can be
18
+ * unit-tested without filesystem fixtures. This bridge adds the integration that the
19
+ * runner (`runReviewInvokeCli`) can branch into when the resolved
20
+ * profile mode is `nested-workers`.
21
+ *
22
+ * Keeping this seat **separate** from `executeReviewPromptExecution`
23
+ * (which uses the per-lens worker loop) preserves the existing review flow
24
+ * for main-workers mode.
25
+ *
26
+ * # How it relates
27
+ *
28
+ * - `ReviewExecutionProfile.mode` selects whether this bridge is used.
29
+ * - `executeReviewViaCodexNested()` handles the nested worker execution phase.
30
+ * - `completeReviewSession()` downstream consumes the result to compile
31
+ * the final review record.
32
+ *
33
+ * # Scope
34
+ *
35
+ * - Bridge function `executeReviewViaCodexNested`
36
+ * - Output-file validation (exists + non-empty) on top of orchestrator
37
+ * outcomes — a per-lens `status: "ok"` in the orchestrator is
38
+ * necessary but not sufficient; the file must actually be written.
39
+ * - Tests with injected orchestrator + injected filesystem
40
+ *
41
+ * This bridge owns only nested lens dispatch. Synthesize, deliberation
42
+ * artifact handling, and final record assembly stay in the main review
43
+ * runner.
44
+ *
45
+ * # Design reference
46
+ *
47
+ * - Nested Codex validation notes under `development-records/`
48
+ */
49
+ import fs from "node:fs/promises";
50
+ import path from "node:path";
51
+ import { normalizeLlmModelSwitcher } from "../llm/model-switcher.js";
52
+ import { readYamlDocument } from "../review/review-artifact-utils.js";
53
+ import { runCodexNestedTeamlead, } from "./codex-nested-teamlead-executor.js";
54
+ const defaultInspector = async (p) => {
55
+ try {
56
+ const stat = await fs.stat(p);
57
+ return { exists: stat.isFile(), size: stat.size };
58
+ }
59
+ catch {
60
+ return { exists: false, size: 0 };
61
+ }
62
+ };
63
+ // ---------------------------------------------------------------------------
64
+ // Artifact archival
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Archive for outer codex stdout/stderr when streaming did not
68
+ * already write the files. Normally `spawnOuterCodex` is invoked with
69
+ * `stream_stdout_path` / `stream_stderr_path` and the on-disk files
70
+ * carry the authoritative content via `fs.createWriteStream`; in that
71
+ * case this helper sees non-empty files and returns without writing
72
+ * (prevents dual-writer drift — 3rd self-review U4).
73
+ *
74
+ * Silently swallows write errors — an artifact write failure must not
75
+ * mask the actual dispatch outcome. Best-effort.
76
+ */
77
+ async function archiveOuterStreamsIfMissing(sessionRoot, nestedResult) {
78
+ const stdoutPath = path.join(sessionRoot, "nested-outer-stdout.log");
79
+ const stderrPath = path.join(sessionRoot, "nested-outer-stderr.log");
80
+ await Promise.all([
81
+ archiveWriteIfMissing(stdoutPath, nestedResult.outer_stdout ?? ""),
82
+ archiveWriteIfMissing(stderrPath, nestedResult.outer_stderr ?? ""),
83
+ ]);
84
+ }
85
+ async function archiveWriteIfMissing(targetPath, content) {
86
+ try {
87
+ const stat = await fs.stat(targetPath).catch(() => null);
88
+ if (stat && stat.size > 0) {
89
+ // Streaming writer produced a non-empty file — respect it as the
90
+ // single authority. Do not overwrite.
91
+ return;
92
+ }
93
+ await fs.writeFile(targetPath, content).catch(() => { });
94
+ }
95
+ catch {
96
+ // Best-effort; never throw.
97
+ }
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // Worker setting resolution
101
+ // ---------------------------------------------------------------------------
102
+ /**
103
+ * Resolve distinct Codex model settings for the outer teamlead and inner lens
104
+ * workers. Empty objects mean Codex picks its configured defaults for that seat.
105
+ */
106
+ export function resolveCodexSpawnConfig(config) {
107
+ const execution = config.review?.execution;
108
+ const inherited = config.llm;
109
+ return {
110
+ teamlead: codexConfigFromRef(execution?.teamlead.llm, inherited) ?? {},
111
+ lens: codexConfigFromRef(execution?.lens.llm, inherited) ?? {},
112
+ };
113
+ }
114
+ function codexConfigFromRef(ref, inherited) {
115
+ const llm = ref === undefined || ref === "inherit" ? inherited : ref;
116
+ const selection = normalizeLlmModelSwitcher(llm);
117
+ if (selection?.provider !== "codex")
118
+ return null;
119
+ return {
120
+ ...(selection.model_id ? { model: selection.model_id } : {}),
121
+ ...(selection.reasoning_effort ? { effort: selection.reasoning_effort } : {}),
122
+ ...(selection.service_tier ? { service_tier: selection.service_tier } : {}),
123
+ };
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Main bridge function
127
+ // ---------------------------------------------------------------------------
128
+ /**
129
+ * Execute a review via the nested Codex worker path. Reads the execution
130
+ * plan from `sessionRoot/execution-plan.yaml`, dispatches all lens
131
+ * packets through one outer Codex teamlead plus one inner Codex worker per lens, and
132
+ * classifies outcomes into participating / degraded lens sets.
133
+ *
134
+ * An orchestrator `status: "ok"` is NOT sufficient for `participating` —
135
+ * the output file must exist AND be non-empty. This guards against the
136
+ * outer Codex reporting success when an inner worker failed to write its
137
+ * `-o` output.
138
+ *
139
+ * Injection:
140
+ * - `runImpl`: replace the orchestrator (default: `runCodexNestedTeamlead`)
141
+ * - `inspector`: replace the file-existence probe (default: `fs.stat`)
142
+ */
143
+ export async function executeReviewViaCodexNested(args, runImpl = runCodexNestedTeamlead, inspector = defaultInspector) {
144
+ const executionPlanPath = path.join(args.sessionRoot, "execution-plan.yaml");
145
+ // `readYamlDocument` throws with a descriptive message when the file
146
+ // is missing or malformed — let it propagate so the caller sees the
147
+ // session artifact problem directly rather than a generic null check.
148
+ const plan = await readYamlDocument(executionPlanPath);
149
+ const lenses = plan.lens_prompt_packet_seats.map((seat) => ({
150
+ lens_id: seat.lens_id,
151
+ packet_path: seat.packet_path,
152
+ output_path: seat.output_path,
153
+ }));
154
+ const spawnConfig = resolveCodexSpawnConfig(args.ontoConfig);
155
+ // Stream paths live under sessionRoot so the watcher pane can `tail -f`
156
+ // them from the moment the outer codex starts emitting, instead of
157
+ // waiting for the post-hoc `archiveOuterStreams` batch write. With
158
+ // streaming active, these files are the single authority — no post-
159
+ // dispatch overwrite (3rd self-review U4: prevent dual-writer drift
160
+ // where two writers could diverge if one was interrupted mid-flush).
161
+ const streamStdoutPath = path.join(args.sessionRoot, "nested-outer-stdout.log");
162
+ const streamStderrPath = path.join(args.sessionRoot, "nested-outer-stderr.log");
163
+ const nestedResult = await runImpl({
164
+ lenses,
165
+ ...(spawnConfig.teamlead.model
166
+ ? { teamlead_model: spawnConfig.teamlead.model }
167
+ : {}),
168
+ ...(spawnConfig.teamlead.effort
169
+ ? { teamlead_reasoning_effort: spawnConfig.teamlead.effort }
170
+ : {}),
171
+ ...(spawnConfig.teamlead.service_tier
172
+ ? { teamlead_service_tier: spawnConfig.teamlead.service_tier }
173
+ : {}),
174
+ ...(spawnConfig.lens.model ? { lens_model: spawnConfig.lens.model } : {}),
175
+ ...(spawnConfig.lens.effort
176
+ ? { lens_reasoning_effort: spawnConfig.lens.effort }
177
+ : {}),
178
+ ...(spawnConfig.lens.service_tier
179
+ ? { lens_service_tier: spawnConfig.lens.service_tier }
180
+ : {}),
181
+ ...(args.projectRoot ? { project_root: args.projectRoot } : {}),
182
+ ...(typeof args.timeout_ms === "number" ? { timeout_ms: args.timeout_ms } : {}),
183
+ ...(args.codex_bin ? { codex_bin: args.codex_bin } : {}),
184
+ stream_stdout_path: streamStdoutPath,
185
+ stream_stderr_path: streamStderrPath,
186
+ });
187
+ // Archive step is a no-op when streaming already produced files.
188
+ await archiveOuterStreamsIfMissing(args.sessionRoot, nestedResult);
189
+ const participating = [];
190
+ const degraded = [];
191
+ for (let i = 0; i < lenses.length; i += 1) {
192
+ const lens = lenses[i];
193
+ const outcome = nestedResult.outcomes[i];
194
+ const orchestratorOk = outcome?.status === "ok";
195
+ if (!orchestratorOk) {
196
+ degraded.push(lens.lens_id);
197
+ continue;
198
+ }
199
+ const probe = await inspector(lens.output_path);
200
+ if (probe.exists && probe.size > 0) {
201
+ participating.push(lens.lens_id);
202
+ }
203
+ else {
204
+ degraded.push(lens.lens_id);
205
+ }
206
+ }
207
+ // Determine halt_reason when orchestrator signalled teamlead-level
208
+ // failure (e.g., timeout, no summary) — surfaces to the caller for
209
+ // error reporting. Per-lens degradation alone does NOT halt.
210
+ let halt_reason;
211
+ if (!nestedResult.summary_parsed && nestedResult.outer_exit_code !== 0) {
212
+ halt_reason =
213
+ `codex-nested outer teamlead failed (exit=${nestedResult.outer_exit_code}, summary=${nestedResult.summary_parsed ? "parsed" : "missing"})`;
214
+ }
215
+ return {
216
+ session_root: args.sessionRoot,
217
+ executed_lens_count: lenses.length,
218
+ participating_lens_ids: participating,
219
+ degraded_lens_ids: degraded,
220
+ synthesis_executed: false,
221
+ synthesis_output_path: plan.synthesis_output_path,
222
+ error_log_path: plan.error_log_path ?? null,
223
+ nested_raw: nestedResult,
224
+ ...(halt_reason ? { halt_reason } : {}),
225
+ };
226
+ }
@@ -0,0 +1,390 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { writeYamlDocument } from "../review/review-artifact-utils.js";
6
+ import { executeReviewViaCodexNested, } from "./codex-nested-dispatch.js";
7
+ async function mkSession(plan) {
8
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), "onto-pr-h-"));
9
+ const sessionRoot = path.join(root, "session");
10
+ await fs.mkdir(sessionRoot, { recursive: true });
11
+ await writeYamlDocument(path.join(sessionRoot, "execution-plan.yaml"), plan);
12
+ return {
13
+ sessionRoot,
14
+ cleanup: async () => {
15
+ await fs.rm(root, { recursive: true, force: true });
16
+ },
17
+ };
18
+ }
19
+ function buildPlan(lenses, sessionRoot) {
20
+ return {
21
+ session_id: "pr-h-test",
22
+ session_root: sessionRoot,
23
+ execution_realization: "subagent",
24
+ host_runtime: "codex",
25
+ review_mode: "core-axis",
26
+ interpretation_artifact_path: path.join(sessionRoot, "interpretation.yaml"),
27
+ binding_output_path: path.join(sessionRoot, "binding.yaml"),
28
+ session_metadata_path: path.join(sessionRoot, "session-metadata.yaml"),
29
+ execution_preparation_root: path.join(sessionRoot, "prep"),
30
+ round1_root: path.join(sessionRoot, "round1"),
31
+ lens_execution_seats: lenses.map((l) => ({
32
+ lens_id: l.lens_id,
33
+ output_path: l.output_path,
34
+ })),
35
+ prompt_packets_root: path.join(sessionRoot, "prompt-packets"),
36
+ lens_prompt_packet_seats: lenses,
37
+ synthesize_prompt_packet_path: path.join(sessionRoot, "synthesize-packet.md"),
38
+ synthesis_output_path: path.join(sessionRoot, "synthesis.md"),
39
+ deliberation_output_path: path.join(sessionRoot, "deliberation.md"),
40
+ execution_result_path: path.join(sessionRoot, "execution-result.yaml"),
41
+ error_log_path: path.join(sessionRoot, "error-log.md"),
42
+ final_output_path: path.join(sessionRoot, "final.md"),
43
+ review_record_path: path.join(sessionRoot, "review-record.yaml"),
44
+ boundary_policy: {
45
+ web_research_policy: "allowed",
46
+ repo_exploration_policy: "allowed",
47
+ recursive_reference_expansion_policy: "allowed",
48
+ filesystem_scope: { allowed_roots: [], source_mutation_policy: "denied" },
49
+ },
50
+ boundary_presentation: {
51
+ web_research: { requested_policy: "allowed" },
52
+ repo_exploration: { requested_policy: "allowed" },
53
+ recursive_reference_expansion: { requested_policy: "allowed" },
54
+ source_mutation: { requested_policy: "denied" },
55
+ filesystem_scope: { requested_allowed_roots: [] },
56
+ },
57
+ boundary_enforcement_profile: {
58
+ web_research: "prompt_declared_only",
59
+ repo_exploration: "prompt_declared_only",
60
+ recursive_reference_expansion: "prompt_declared_only",
61
+ source_mutation: "prompt_declared_only",
62
+ filesystem_scope: "prompt_declared_only",
63
+ },
64
+ effective_boundary_state: {
65
+ web_research: {
66
+ requested_policy: "allowed",
67
+ effective_policy: "allowed",
68
+ guarantee_level: "prompt_declared_only",
69
+ },
70
+ repo_exploration: {
71
+ requested_policy: "allowed",
72
+ effective_policy: "allowed",
73
+ guarantee_level: "prompt_declared_only",
74
+ },
75
+ recursive_reference_expansion: {
76
+ requested_policy: "allowed",
77
+ effective_policy: "allowed",
78
+ guarantee_level: "prompt_declared_only",
79
+ },
80
+ source_mutation: {
81
+ requested_policy: "denied",
82
+ effective_policy: "denied",
83
+ guarantee_level: "prompt_declared_only",
84
+ },
85
+ filesystem_scope: {
86
+ requested_allowed_roots: [],
87
+ effective_allowed_roots: [],
88
+ guarantee_level: "prompt_declared_only",
89
+ },
90
+ },
91
+ };
92
+ }
93
+ function buildOrchestrator(outcomes, opts = {}) {
94
+ const calls = [];
95
+ const impl = async (input) => {
96
+ calls.push(input);
97
+ return {
98
+ outcomes,
99
+ outer_stdout: opts.outer_stdout ?? "",
100
+ outer_stderr: opts.outer_stderr ?? "",
101
+ outer_exit_code: opts.outer_exit_code ?? 0,
102
+ summary_parsed: opts.summary_parsed ?? true,
103
+ };
104
+ };
105
+ return { impl, calls };
106
+ }
107
+ function staticInspector(present, sizes = {}) {
108
+ return async (p) => ({
109
+ exists: present.has(p),
110
+ size: sizes[p] ?? (present.has(p) ? 1 : 0),
111
+ });
112
+ }
113
+ // ---------------------------------------------------------------------------
114
+ // Forwarding: execution-plan lenses → orchestrator input
115
+ // ---------------------------------------------------------------------------
116
+ describe("executeReviewViaCodexNested — forwarding", () => {
117
+ let fixture;
118
+ afterEach(async () => {
119
+ if (fixture)
120
+ await fixture.cleanup();
121
+ });
122
+ it("forwards lens packet triples in execution-plan order", async () => {
123
+ const plan = buildPlan([
124
+ { lens_id: "logic", packet_path: "/pkts/logic.md", output_path: "/out/logic.md" },
125
+ { lens_id: "pragmatics", packet_path: "/pkts/pr.md", output_path: "/out/pr.md" },
126
+ { lens_id: "axiology", packet_path: "/pkts/ax.md", output_path: "/out/ax.md" },
127
+ ], "");
128
+ fixture = await mkSession(plan);
129
+ const { impl, calls } = buildOrchestrator([
130
+ { lens_id: "logic", status: "ok" },
131
+ { lens_id: "pragmatics", status: "ok" },
132
+ { lens_id: "axiology", status: "ok" },
133
+ ]);
134
+ await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/out/logic.md", "/out/pr.md", "/out/ax.md"])));
135
+ expect(calls).toHaveLength(1);
136
+ expect(calls[0].lenses.map((l) => l.lens_id)).toEqual([
137
+ "logic",
138
+ "pragmatics",
139
+ "axiology",
140
+ ]);
141
+ expect(calls[0].lenses[0].packet_path).toBe("/pkts/logic.md");
142
+ expect(calls[0].lenses[0].output_path).toBe("/out/logic.md");
143
+ });
144
+ it("passes model from ontoConfig.codex.model and reasoning_effort from codex.effort", async () => {
145
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
146
+ fixture = await mkSession(plan);
147
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
148
+ await executeReviewViaCodexNested({
149
+ sessionRoot: fixture.sessionRoot,
150
+ ontoConfig: { codex: { model: "gpt-5.4", effort: "high" } },
151
+ }, impl, staticInspector(new Set(["/o"])));
152
+ expect(calls[0].model).toBe("gpt-5.4");
153
+ expect(calls[0].reasoning_effort).toBe("high");
154
+ });
155
+ it("falls back to top-level model / reasoning_effort when codex.* unset", async () => {
156
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
157
+ fixture = await mkSession(plan);
158
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
159
+ await executeReviewViaCodexNested({
160
+ sessionRoot: fixture.sessionRoot,
161
+ ontoConfig: { model: "gpt-top", reasoning_effort: "low" },
162
+ }, impl, staticInspector(new Set(["/o"])));
163
+ expect(calls[0].model).toBe("gpt-top");
164
+ expect(calls[0].reasoning_effort).toBe("low");
165
+ });
166
+ it("reads model/effort from review.subagent (P2 canonical location)", async () => {
167
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
168
+ fixture = await mkSession(plan);
169
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
170
+ await executeReviewViaCodexNested({
171
+ sessionRoot: fixture.sessionRoot,
172
+ ontoConfig: {
173
+ review: {
174
+ subagent: { provider: "codex", model_id: "gpt-sub", effort: "medium" },
175
+ },
176
+ },
177
+ }, impl, staticInspector(new Set(["/o"])));
178
+ expect(calls[0].model).toBe("gpt-sub");
179
+ expect(calls[0].reasoning_effort).toBe("medium");
180
+ });
181
+ it("reads model/effort from review.teamlead.model when external codex teamlead", async () => {
182
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
183
+ fixture = await mkSession(plan);
184
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
185
+ await executeReviewViaCodexNested({
186
+ sessionRoot: fixture.sessionRoot,
187
+ ontoConfig: {
188
+ review: {
189
+ teamlead: { model: { provider: "codex", model_id: "gpt-tl", effort: "high" } },
190
+ },
191
+ },
192
+ }, impl, staticInspector(new Set(["/o"])));
193
+ expect(calls[0].model).toBe("gpt-tl");
194
+ expect(calls[0].reasoning_effort).toBe("high");
195
+ });
196
+ it("review.subagent wins over top-level codex.* (P2 canonical > legacy)", async () => {
197
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
198
+ fixture = await mkSession(plan);
199
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
200
+ await executeReviewViaCodexNested({
201
+ sessionRoot: fixture.sessionRoot,
202
+ ontoConfig: {
203
+ review: {
204
+ subagent: { provider: "codex", model_id: "gpt-sub", effort: "medium" },
205
+ },
206
+ codex: { model: "gpt-legacy", effort: "high" },
207
+ },
208
+ }, impl, staticInspector(new Set(["/o"])));
209
+ expect(calls[0].model).toBe("gpt-sub");
210
+ expect(calls[0].reasoning_effort).toBe("medium");
211
+ });
212
+ it("review.subagent with provider=main-native does NOT claim codex slot (falls through)", async () => {
213
+ // main-native subagent is not a codex provider → resolver should move on
214
+ // to teamlead → legacy → top-level, not pick up subagent.
215
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
216
+ fixture = await mkSession(plan);
217
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
218
+ await executeReviewViaCodexNested({
219
+ sessionRoot: fixture.sessionRoot,
220
+ ontoConfig: {
221
+ review: {
222
+ subagent: { provider: "main-native" },
223
+ },
224
+ codex: { model: "gpt-legacy", effort: "high" },
225
+ },
226
+ }, impl, staticInspector(new Set(["/o"])));
227
+ expect(calls[0].model).toBe("gpt-legacy");
228
+ expect(calls[0].reasoning_effort).toBe("high");
229
+ });
230
+ it("passes sessionRoot-based stream_stdout_path/stream_stderr_path to orchestrator (live watcher)", async () => {
231
+ // The watcher pane's tail -f target is sessionRoot/nested-outer-*.log.
232
+ // The orchestrator must receive those absolute paths so spawn-watcher
233
+ // can tee outer codex stdout/stderr there as codex emits chunks. If
234
+ // the dispatch stopped plumbing these paths, streaming would silently
235
+ // fall back to memory-only capture.
236
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
237
+ fixture = await mkSession(plan);
238
+ const { impl, calls } = buildOrchestrator([{ lens_id: "l", status: "ok" }]);
239
+ await executeReviewViaCodexNested({
240
+ sessionRoot: fixture.sessionRoot,
241
+ ontoConfig: {},
242
+ }, impl, staticInspector(new Set(["/o"])));
243
+ expect(calls[0].stream_stdout_path).toBe(path.join(fixture.sessionRoot, "nested-outer-stdout.log"));
244
+ expect(calls[0].stream_stderr_path).toBe(path.join(fixture.sessionRoot, "nested-outer-stderr.log"));
245
+ });
246
+ it("archives outer stdout/stderr to nested-outer-*.log under sessionRoot", async () => {
247
+ // Regression guard: outer codex diagnostics (ENV-BEFORE / ENV-AFTER /
248
+ // LENS_DISPATCH_SUMMARY) and raw stderr are otherwise unreachable
249
+ // after dispatch completes, because review-invoke's final JSON drops
250
+ // `nested_raw`. The archive step is what makes post-hoc auditing
251
+ // possible for the principal.
252
+ const plan = buildPlan([{ lens_id: "l", packet_path: "/p", output_path: "/o" }], "");
253
+ fixture = await mkSession(plan);
254
+ const { impl } = buildOrchestrator([{ lens_id: "l", status: "ok" }], {
255
+ outer_stdout: "ENV-BEFORE lens=l packet=/p output=/o\n" +
256
+ "ENV-AFTER lens=l exit=0 output_bytes=42\n" +
257
+ 'LENS_DISPATCH_SUMMARY:{"lens_results":[{"lens_id":"l","status":"ok"}]}\n',
258
+ outer_stderr: "some-warning from outer codex\n",
259
+ });
260
+ await executeReviewViaCodexNested({
261
+ sessionRoot: fixture.sessionRoot,
262
+ ontoConfig: {},
263
+ }, impl, staticInspector(new Set(["/o"])));
264
+ const stdoutArchive = await fs.readFile(path.join(fixture.sessionRoot, "nested-outer-stdout.log"), "utf8");
265
+ const stderrArchive = await fs.readFile(path.join(fixture.sessionRoot, "nested-outer-stderr.log"), "utf8");
266
+ expect(stdoutArchive).toContain("ENV-BEFORE lens=l");
267
+ expect(stdoutArchive).toContain("ENV-AFTER lens=l");
268
+ expect(stdoutArchive).toContain("LENS_DISPATCH_SUMMARY:");
269
+ expect(stderrArchive).toContain("some-warning from outer codex");
270
+ });
271
+ });
272
+ // ---------------------------------------------------------------------------
273
+ // Classification: orchestrator-ok AND file-exists → participating
274
+ // ---------------------------------------------------------------------------
275
+ describe("executeReviewViaCodexNested — per-lens classification", () => {
276
+ let fixture;
277
+ afterEach(async () => {
278
+ if (fixture)
279
+ await fixture.cleanup();
280
+ });
281
+ it("all ok + all files present → all participating", async () => {
282
+ const plan = buildPlan([
283
+ { lens_id: "a", packet_path: "/p/a", output_path: "/o/a" },
284
+ { lens_id: "b", packet_path: "/p/b", output_path: "/o/b" },
285
+ ], "");
286
+ fixture = await mkSession(plan);
287
+ const { impl } = buildOrchestrator([
288
+ { lens_id: "a", status: "ok" },
289
+ { lens_id: "b", status: "ok" },
290
+ ]);
291
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a", "/o/b"])));
292
+ expect(result.participating_lens_ids).toEqual(["a", "b"]);
293
+ expect(result.degraded_lens_ids).toEqual([]);
294
+ expect(result.executed_lens_count).toBe(2);
295
+ });
296
+ it("orchestrator fail → degraded (no file probe needed)", async () => {
297
+ const plan = buildPlan([
298
+ { lens_id: "a", packet_path: "/p/a", output_path: "/o/a" },
299
+ { lens_id: "b", packet_path: "/p/b", output_path: "/o/b" },
300
+ ], "");
301
+ fixture = await mkSession(plan);
302
+ const { impl } = buildOrchestrator([
303
+ { lens_id: "a", status: "ok" },
304
+ { lens_id: "b", status: "fail", error: "inner exit 1" },
305
+ ]);
306
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a", "/o/b"])));
307
+ expect(result.participating_lens_ids).toEqual(["a"]);
308
+ expect(result.degraded_lens_ids).toEqual(["b"]);
309
+ });
310
+ it("orchestrator ok but output file missing → degraded", async () => {
311
+ const plan = buildPlan([
312
+ { lens_id: "a", packet_path: "/p/a", output_path: "/o/a" },
313
+ { lens_id: "b", packet_path: "/p/b", output_path: "/o/b" },
314
+ ], "");
315
+ fixture = await mkSession(plan);
316
+ const { impl } = buildOrchestrator([
317
+ { lens_id: "a", status: "ok" },
318
+ { lens_id: "b", status: "ok" },
319
+ ]);
320
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a"])));
321
+ expect(result.participating_lens_ids).toEqual(["a"]);
322
+ expect(result.degraded_lens_ids).toEqual(["b"]);
323
+ });
324
+ it("orchestrator ok but output file size=0 → degraded", async () => {
325
+ const plan = buildPlan([{ lens_id: "a", packet_path: "/p/a", output_path: "/o/a" }], "");
326
+ fixture = await mkSession(plan);
327
+ const { impl } = buildOrchestrator([{ lens_id: "a", status: "ok" }]);
328
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a"]), { "/o/a": 0 }));
329
+ expect(result.participating_lens_ids).toEqual([]);
330
+ expect(result.degraded_lens_ids).toEqual(["a"]);
331
+ });
332
+ });
333
+ // ---------------------------------------------------------------------------
334
+ // Result shape
335
+ // ---------------------------------------------------------------------------
336
+ describe("executeReviewViaCodexNested — result shape", () => {
337
+ let fixture;
338
+ afterEach(async () => {
339
+ if (fixture)
340
+ await fixture.cleanup();
341
+ });
342
+ it("synthesis_executed is always false in PR-H (deferred)", async () => {
343
+ const plan = buildPlan([{ lens_id: "a", packet_path: "/p/a", output_path: "/o/a" }], "");
344
+ fixture = await mkSession(plan);
345
+ const { impl } = buildOrchestrator([{ lens_id: "a", status: "ok" }]);
346
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a"])));
347
+ expect(result.synthesis_executed).toBe(false);
348
+ });
349
+ it("synthesis_output_path is sourced from execution-plan for downstream synthesize wire-in", async () => {
350
+ const plan = buildPlan([{ lens_id: "a", packet_path: "/p/a", output_path: "/o/a" }], "");
351
+ plan.synthesis_output_path = "/tmp/synth-target.md";
352
+ fixture = await mkSession(plan);
353
+ const { impl } = buildOrchestrator([{ lens_id: "a", status: "ok" }]);
354
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a"])));
355
+ expect(result.synthesis_output_path).toBe("/tmp/synth-target.md");
356
+ });
357
+ it("nested_raw exposes orchestrator result verbatim for debugging", async () => {
358
+ const plan = buildPlan([{ lens_id: "a", packet_path: "/p/a", output_path: "/o/a" }], "");
359
+ fixture = await mkSession(plan);
360
+ const { impl } = buildOrchestrator([{ lens_id: "a", status: "ok" }], { outer_stdout: "outer stdout content", outer_stderr: "outer stderr content" });
361
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set(["/o/a"])));
362
+ expect(result.nested_raw.outer_stdout).toBe("outer stdout content");
363
+ expect(result.nested_raw.outer_stderr).toBe("outer stderr content");
364
+ });
365
+ it("halt_reason populated when outer exit non-zero AND summary not parsed", async () => {
366
+ const plan = buildPlan([{ lens_id: "a", packet_path: "/p/a", output_path: "/o/a" }], "");
367
+ fixture = await mkSession(plan);
368
+ const { impl } = buildOrchestrator([{ lens_id: "a", status: "fail", error: "no summary" }], { outer_exit_code: 137, summary_parsed: false });
369
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set()));
370
+ expect(result.halt_reason).toBeDefined();
371
+ expect(result.halt_reason).toContain("137");
372
+ });
373
+ it("halt_reason absent when per-lens degraded but teamlead ok", async () => {
374
+ const plan = buildPlan([{ lens_id: "a", packet_path: "/p/a", output_path: "/o/a" }], "");
375
+ fixture = await mkSession(plan);
376
+ const { impl } = buildOrchestrator([{ lens_id: "a", status: "fail", error: "inner 1" }], { outer_exit_code: 0, summary_parsed: true });
377
+ const result = await executeReviewViaCodexNested({ sessionRoot: fixture.sessionRoot, ontoConfig: {} }, impl, staticInspector(new Set()));
378
+ expect(result.halt_reason).toBeUndefined();
379
+ expect(result.degraded_lens_ids).toEqual(["a"]);
380
+ });
381
+ });
382
+ // ---------------------------------------------------------------------------
383
+ // Execution-plan missing — bridge surfaces the error
384
+ // ---------------------------------------------------------------------------
385
+ describe("executeReviewViaCodexNested — missing execution-plan", () => {
386
+ it("propagates readYamlDocument error when execution-plan.yaml absent", async () => {
387
+ const { impl } = buildOrchestrator([]);
388
+ await expect(executeReviewViaCodexNested({ sessionRoot: "/nonexistent/session/path", ontoConfig: {} }, impl, staticInspector(new Set()))).rejects.toThrow(/Failed to read artifact/);
389
+ });
390
+ });