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,335 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildNestedTeamleadPrompt, parseNestedTeamleadSummary, runCodexNestedTeamlead, } from "./codex-nested-teamlead-executor.js";
3
+ // ---------------------------------------------------------------------------
4
+ // These tests assert the PR-C orchestrator invariants:
5
+ //
6
+ // (1) The prompt embeds every lens in the same order with packet/output
7
+ // paths and the sandbox flag the outer codex needs.
8
+ // (2) The summary parser extracts the LENS_DISPATCH_SUMMARY line and
9
+ // tolerates surrounding noise; malformed lines are ignored; last-one
10
+ // wins when multiple are present.
11
+ // (3) `runCodexNestedTeamlead` reconciles inputs with reported outcomes:
12
+ // missing lens_ids become `fail` (teamlead noncompliance), reported
13
+ // failures carry the reported error, timeouts mark every lens failed.
14
+ // ---------------------------------------------------------------------------
15
+ const LENSES = [
16
+ {
17
+ lens_id: "logic",
18
+ packet_path: "/tmp/session/round1/logic-packet.md",
19
+ output_path: "/tmp/session/round1/logic.md",
20
+ },
21
+ {
22
+ lens_id: "pragmatics",
23
+ packet_path: "/tmp/session/round1/pragmatics-packet.md",
24
+ output_path: "/tmp/session/round1/pragmatics.md",
25
+ },
26
+ {
27
+ lens_id: "axiology",
28
+ packet_path: "/tmp/session/round1/axiology-packet.md",
29
+ output_path: "/tmp/session/round1/axiology.md",
30
+ },
31
+ ];
32
+ // ---------------------------------------------------------------------------
33
+ // buildNestedTeamleadPrompt
34
+ // ---------------------------------------------------------------------------
35
+ describe("buildNestedTeamleadPrompt", () => {
36
+ it("embeds every lens's id, packet path, and output path", () => {
37
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
38
+ for (const lens of LENSES) {
39
+ expect(prompt).toContain(lens.lens_id);
40
+ expect(prompt).toContain(lens.packet_path);
41
+ expect(prompt).toContain(lens.output_path);
42
+ }
43
+ });
44
+ it("includes sandbox danger-full-access and ephemeral flags for inner codex", () => {
45
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
46
+ expect(prompt).toContain("--sandbox danger-full-access");
47
+ expect(prompt).toContain("--ephemeral");
48
+ expect(prompt).toContain("--skip-git-repo-check");
49
+ });
50
+ it("declares the LENS_DISPATCH_SUMMARY sentinel the parser looks for", () => {
51
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
52
+ expect(prompt).toContain("LENS_DISPATCH_SUMMARY:");
53
+ });
54
+ it("passes through model + reasoning_effort when provided", () => {
55
+ const prompt = buildNestedTeamleadPrompt({
56
+ lenses: LENSES.slice(0, 1),
57
+ model: "gpt-5.4",
58
+ reasoning_effort: "high",
59
+ });
60
+ expect(prompt).toContain("-m gpt-5.4");
61
+ expect(prompt).toContain("model_reasoning_effort=high");
62
+ });
63
+ it("omits the model/effort flags when unset (codex uses its defaults)", () => {
64
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES.slice(0, 1) });
65
+ expect(prompt).not.toContain(" -m ");
66
+ expect(prompt).not.toContain("model_reasoning_effort=");
67
+ });
68
+ it("states the number of lenses explicitly (sanity check for the outer codex)", () => {
69
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
70
+ expect(prompt).toContain(`${LENSES.length} lenses`);
71
+ });
72
+ it("surfaces nested model/effort in the diagnostic header for outer log readers", () => {
73
+ const prompt = buildNestedTeamleadPrompt({
74
+ lenses: LENSES.slice(0, 1),
75
+ model: "gpt-5.4",
76
+ reasoning_effort: "medium",
77
+ });
78
+ expect(prompt).toContain("model=gpt-5.4");
79
+ expect(prompt).toContain("effort=medium");
80
+ });
81
+ it("falls back to (codex default) in diagnostic header when unset", () => {
82
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES.slice(0, 1) });
83
+ expect(prompt).toContain("model=(codex default)");
84
+ expect(prompt).toContain("effort=(codex default)");
85
+ });
86
+ it("embeds ENV-BEFORE and ENV-AFTER diagnostic emissions in the script body", () => {
87
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
88
+ expect(prompt).toContain("ENV-BEFORE lens=");
89
+ expect(prompt).toContain("ENV-AFTER lens=");
90
+ });
91
+ it("delivers instructions as a literal bash script piped to bash -s", () => {
92
+ // Regression guard for the descriptive→literal rewrite. Earlier prompts
93
+ // asked outer to "invoke nested codex for each lens", which outer
94
+ // interpreted as a self-assignment (using its own file-edit tools) and
95
+ // never spawned nested subprocesses. The literal-script formulation
96
+ // removes that interpretation latitude — outer's only action is to
97
+ // pipe the block below to bash.
98
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
99
+ expect(prompt).toContain("bash -s");
100
+ expect(prompt).toContain("```bash");
101
+ expect(prompt).toContain("#!/usr/bin/env bash");
102
+ expect(prompt).toContain("LENSES=(");
103
+ });
104
+ it("dispatches lenses in parallel via background subshells + wait", () => {
105
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
106
+ // subshell + background + wait pattern
107
+ expect(prompt).toMatch(/\)\s*&\s*\ndone\s*\n\s*wait/);
108
+ });
109
+ it("persists per-lens running log as nested-stderr.log on failure", () => {
110
+ // Regression guard: post-hoc audit needs to answer "what failed
111
+ // inside this lens run?" after dispatch exits. Now that the running
112
+ // log lives under sessionRoot/round1 for real-time tail -f, the
113
+ // failure path simply renames it to .<lens>.nested-stderr.log; the
114
+ // success path removes it. Previous `tail -200` bounded copy is no
115
+ // longer necessary since the source log is already file-system
116
+ // resident at the destination directory.
117
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
118
+ expect(prompt).toContain(".nested-stderr.log");
119
+ expect(prompt).toContain(".running.log");
120
+ });
121
+ it("writes per-lens running log under sessionRoot (not TMPDIR) for live tail -f", () => {
122
+ // Regression guard for commit 5 streaming: per-lens $LOG must live
123
+ // under OUTPUT_DIR (sessionRoot/round1) so the watcher pane can
124
+ // tail it as codex emits. Keeping $LOG in TMPDIR would revert to
125
+ // post-hoc-only visibility.
126
+ const prompt = buildNestedTeamleadPrompt({ lenses: LENSES });
127
+ expect(prompt).toContain('LOG="$OUTPUT_DIR/.$LENS_ID.running.log"');
128
+ // $STAT remains in TMPDIR (short-lived handoff from lens subshell
129
+ // to the summary emitter; no value to the watcher).
130
+ expect(prompt).toContain('STAT="$TMPDIR/$LENS_ID.status"');
131
+ });
132
+ });
133
+ // ---------------------------------------------------------------------------
134
+ // parseNestedTeamleadSummary
135
+ // ---------------------------------------------------------------------------
136
+ describe("parseNestedTeamleadSummary", () => {
137
+ it("returns null when no summary line is present", () => {
138
+ expect(parseNestedTeamleadSummary("just model commentary\nnothing here\n")).toBeNull();
139
+ });
140
+ it("extracts a valid summary line with all lens results", () => {
141
+ const stdout = [
142
+ "dispatched lens#1...",
143
+ "dispatched lens#2...",
144
+ 'LENS_DISPATCH_SUMMARY:{"lens_results":[{"lens_id":"logic","status":"ok"},{"lens_id":"pragmatics","status":"fail","error":"exit 1"}]}',
145
+ ].join("\n");
146
+ const result = parseNestedTeamleadSummary(stdout);
147
+ expect(result).not.toBeNull();
148
+ expect(result.lens_results).toHaveLength(2);
149
+ expect(result.lens_results[0]).toEqual({ lens_id: "logic", status: "ok" });
150
+ expect(result.lens_results[1]).toEqual({
151
+ lens_id: "pragmatics",
152
+ status: "fail",
153
+ error: "exit 1",
154
+ });
155
+ });
156
+ it("ignores malformed summary lines", () => {
157
+ const stdout = "LENS_DISPATCH_SUMMARY:not-json-at-all\nno summary visible\n";
158
+ expect(parseNestedTeamleadSummary(stdout)).toBeNull();
159
+ });
160
+ it("takes the last summary line when multiple appear", () => {
161
+ const stdout = [
162
+ 'LENS_DISPATCH_SUMMARY:{"lens_results":[{"lens_id":"a","status":"fail"}]}',
163
+ 'LENS_DISPATCH_SUMMARY:{"lens_results":[{"lens_id":"a","status":"ok"}]}',
164
+ ].join("\n");
165
+ const result = parseNestedTeamleadSummary(stdout);
166
+ expect(result.lens_results[0].status).toBe("ok");
167
+ });
168
+ it("tolerates leading/trailing whitespace around the summary line", () => {
169
+ const stdout = ' LENS_DISPATCH_SUMMARY:{"lens_results":[]} \n';
170
+ const result = parseNestedTeamleadSummary(stdout);
171
+ expect(result).not.toBeNull();
172
+ expect(result.lens_results).toEqual([]);
173
+ });
174
+ });
175
+ function fakeSpawn(stdout, stderr, exit_code, timed_out = false) {
176
+ return async () => ({ stdout, stderr, exit_code, timed_out });
177
+ }
178
+ describe("runCodexNestedTeamlead", () => {
179
+ it("returns outcomes in input order with ok statuses on clean exit", async () => {
180
+ const input = { lenses: LENSES };
181
+ const stdout = `LENS_DISPATCH_SUMMARY:${JSON.stringify({
182
+ lens_results: [
183
+ { lens_id: "logic", status: "ok" },
184
+ { lens_id: "pragmatics", status: "ok" },
185
+ { lens_id: "axiology", status: "ok" },
186
+ ],
187
+ })}`;
188
+ const result = await runCodexNestedTeamlead(input, fakeSpawn(stdout, "", 0));
189
+ expect(result.summary_parsed).toBe(true);
190
+ expect(result.outer_exit_code).toBe(0);
191
+ expect(result.outcomes.map((o) => o.lens_id)).toEqual(["logic", "pragmatics", "axiology"]);
192
+ expect(result.outcomes.every((o) => o.status === "ok")).toBe(true);
193
+ });
194
+ it("propagates per-lens failures from the summary", async () => {
195
+ const input = { lenses: LENSES };
196
+ const stdout = `LENS_DISPATCH_SUMMARY:${JSON.stringify({
197
+ lens_results: [
198
+ { lens_id: "logic", status: "ok" },
199
+ { lens_id: "pragmatics", status: "fail", error: "inner codex exit 1" },
200
+ { lens_id: "axiology", status: "ok" },
201
+ ],
202
+ })}`;
203
+ const result = await runCodexNestedTeamlead(input, fakeSpawn(stdout, "", 0));
204
+ expect(result.outcomes[0].status).toBe("ok");
205
+ expect(result.outcomes[1].status).toBe("fail");
206
+ expect(result.outcomes[1].error).toContain("inner codex exit 1");
207
+ expect(result.outcomes[2].status).toBe("ok");
208
+ });
209
+ it("marks missing lens_ids as fail with teamlead-noncompliance reason", async () => {
210
+ const input = { lenses: LENSES };
211
+ // Summary omits axiology entirely.
212
+ const stdout = `LENS_DISPATCH_SUMMARY:${JSON.stringify({
213
+ lens_results: [
214
+ { lens_id: "logic", status: "ok" },
215
+ { lens_id: "pragmatics", status: "ok" },
216
+ ],
217
+ })}`;
218
+ const result = await runCodexNestedTeamlead(input, fakeSpawn(stdout, "", 0));
219
+ expect(result.outcomes[2].status).toBe("fail");
220
+ expect(result.outcomes[2].error).toContain("axiology");
221
+ expect(result.outcomes[2].error).toContain("summary missing");
222
+ });
223
+ it("marks all lenses fail when outer codex never emits a summary", async () => {
224
+ const input = { lenses: LENSES };
225
+ const stdout = "just commentary, no summary line\n";
226
+ const result = await runCodexNestedTeamlead(input, fakeSpawn(stdout, "something went wrong", 1));
227
+ expect(result.summary_parsed).toBe(false);
228
+ expect(result.outer_exit_code).toBe(1);
229
+ expect(result.outcomes.every((o) => o.status === "fail")).toBe(true);
230
+ for (const outcome of result.outcomes) {
231
+ expect(outcome.error).toContain("did not emit");
232
+ }
233
+ });
234
+ it("timeout marks all lenses fail with explicit timeout reason", async () => {
235
+ const input = { lenses: LENSES, timeout_ms: 1234 };
236
+ const result = await runCodexNestedTeamlead(input, fakeSpawn("", "", 137, true));
237
+ expect(result.summary_parsed).toBe(false);
238
+ expect(result.outcomes.every((o) => o.status === "fail")).toBe(true);
239
+ for (const outcome of result.outcomes) {
240
+ expect(outcome.error).toContain("1234");
241
+ expect(outcome.error).toContain("timed out");
242
+ }
243
+ });
244
+ it("trusts per-lens summary even when outer exit code is non-zero", async () => {
245
+ const input = { lenses: LENSES };
246
+ const stdout = `LENS_DISPATCH_SUMMARY:${JSON.stringify({
247
+ lens_results: [
248
+ { lens_id: "logic", status: "ok" },
249
+ { lens_id: "pragmatics", status: "ok" },
250
+ { lens_id: "axiology", status: "fail", error: "model context length exceeded" },
251
+ ],
252
+ })}`;
253
+ // Outer codex exits 1 (e.g., because one nested lens failed), but
254
+ // summary is still reliable.
255
+ const result = await runCodexNestedTeamlead(input, fakeSpawn(stdout, "", 1));
256
+ expect(result.summary_parsed).toBe(true);
257
+ expect(result.outer_exit_code).toBe(1);
258
+ expect(result.outcomes[0].status).toBe("ok");
259
+ expect(result.outcomes[1].status).toBe("ok");
260
+ expect(result.outcomes[2].status).toBe("fail");
261
+ expect(result.outcomes[2].error).toContain("context length");
262
+ });
263
+ it("captures outer stdout/stderr verbatim for debugging", async () => {
264
+ const input = { lenses: LENSES.slice(0, 1) };
265
+ const stdoutRaw = "outer commentary\nmore details\n";
266
+ const stderrRaw = "some warning\n";
267
+ const result = await runCodexNestedTeamlead(input, fakeSpawn(stdoutRaw, stderrRaw, 0));
268
+ expect(result.outer_stdout).toBe(stdoutRaw);
269
+ expect(result.outer_stderr).toBe(stderrRaw);
270
+ });
271
+ it("forwards model and reasoning_effort to outer codex spawn options", async () => {
272
+ // Regression: outer codex previously inherited ~/.codex/config.toml
273
+ // defaults (e.g. xhigh effort), ignoring .onto/config.yml overrides and
274
+ // causing orchestration timeouts. The input fields must reach the
275
+ // spawn callsite so the CLI can add `-c model_reasoning_effort=…` and
276
+ // `-m <model>` args.
277
+ let captured = null;
278
+ const capturingSpawn = async (_prompt, options) => {
279
+ captured = options;
280
+ return { stdout: "", stderr: "", exit_code: 0, timed_out: false };
281
+ };
282
+ const input = {
283
+ lenses: LENSES.slice(0, 1),
284
+ model: "gpt-5.4",
285
+ reasoning_effort: "medium",
286
+ };
287
+ await runCodexNestedTeamlead(input, capturingSpawn);
288
+ expect(captured).not.toBeNull();
289
+ expect(captured.model).toBe("gpt-5.4");
290
+ expect(captured.reasoning_effort).toBe("medium");
291
+ });
292
+ it("omits model and reasoning_effort from spawn options when unset", async () => {
293
+ let captured = null;
294
+ const capturingSpawn = async (_prompt, options) => {
295
+ captured = options;
296
+ return { stdout: "", stderr: "", exit_code: 0, timed_out: false };
297
+ };
298
+ const input = { lenses: LENSES.slice(0, 1) };
299
+ await runCodexNestedTeamlead(input, capturingSpawn);
300
+ expect(captured).not.toBeNull();
301
+ expect(captured.model).toBeUndefined();
302
+ expect(captured.reasoning_effort).toBeUndefined();
303
+ });
304
+ it("forwards stream_stdout_path and stream_stderr_path to spawn options", async () => {
305
+ // Regression guard for real-time watcher streaming: if these fields
306
+ // drop, the outer codex stdout/stderr fall back to memory-only
307
+ // capture and the watcher pane's tail -f hint loses its target.
308
+ let captured = null;
309
+ const capturingSpawn = async (_prompt, options) => {
310
+ captured = options;
311
+ return { stdout: "", stderr: "", exit_code: 0, timed_out: false };
312
+ };
313
+ const input = {
314
+ lenses: LENSES.slice(0, 1),
315
+ stream_stdout_path: "/tmp/fake/nested-outer-stdout.log",
316
+ stream_stderr_path: "/tmp/fake/nested-outer-stderr.log",
317
+ };
318
+ await runCodexNestedTeamlead(input, capturingSpawn);
319
+ expect(captured).not.toBeNull();
320
+ expect(captured.stream_stdout_path).toBe("/tmp/fake/nested-outer-stdout.log");
321
+ expect(captured.stream_stderr_path).toBe("/tmp/fake/nested-outer-stderr.log");
322
+ });
323
+ it("omits stream_*_path from spawn options when unset (memory-only capture)", async () => {
324
+ let captured = null;
325
+ const capturingSpawn = async (_prompt, options) => {
326
+ captured = options;
327
+ return { stdout: "", stderr: "", exit_code: 0, timed_out: false };
328
+ };
329
+ const input = { lenses: LENSES.slice(0, 1) };
330
+ await runCodexNestedTeamlead(input, capturingSpawn);
331
+ expect(captured).not.toBeNull();
332
+ expect(captured.stream_stdout_path).toBeUndefined();
333
+ expect(captured.stream_stderr_path).toBeUndefined();
334
+ });
335
+ });
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs/promises";
3
+ import fsSync from "node:fs";
4
+ import path from "node:path";
5
+ import { spawn } from "node:child_process";
6
+ import { parseArgs } from "node:util";
7
+ import { pathToFileURL } from "node:url";
8
+ function requireString(value, optionName) {
9
+ if (typeof value !== "string" || value.length === 0) {
10
+ throw new Error(`Missing required option --${optionName}`);
11
+ }
12
+ return value;
13
+ }
14
+ function buildBoundedPrompt(packetPath, packetText, outputPath, unitId, unitKind) {
15
+ return `You are executing a single bounded review unit as a ContextIsolatedReasoningUnit.
16
+
17
+ Unit id: ${unitId}
18
+ Unit kind: ${unitKind}
19
+ Authoritative prompt packet path: ${packetPath}
20
+ Canonical output path: ${outputPath}
21
+
22
+ Rules:
23
+ - Treat the prompt packet below as the authoritative contract.
24
+ - Treat the Boundary Policy and Effective Boundary State in the packet as hard constraints.
25
+ - Read the files referenced by the prompt packet when needed.
26
+ - Stay within the smallest sufficient file set implied by the packet.
27
+ - Do not recursively follow reference chains beyond the files explicitly listed in the packet unless the packet requires it.
28
+ - Do not use web research when the packet says web research is denied.
29
+ - Do not read outside the allowed filesystem scope described in the packet.
30
+ - Produce only the final markdown content for the canonical output path.
31
+ - Do not wrap the answer in code fences.
32
+ - Do not add commentary before or after the markdown.
33
+ - Do not modify repository files yourself.
34
+ - Do not change the required output structure from the packet.
35
+ - If the packet asks you to preserve disagreement or uncertainty, preserve it explicitly.
36
+ - If you cannot complete the task within the declared boundary, preserve that limitation explicitly as insufficient access or insufficient evidence within boundary instead of broadening the search.
37
+
38
+ Authoritative prompt packet follows:
39
+
40
+ ${packetText}
41
+ `;
42
+ }
43
+ async function runCodexWorker(projectRoot, boundedPrompt, outputPath, model, sandboxMode, reasoningEffort, configOverrides, unitId) {
44
+ const codexArgs = [
45
+ "exec",
46
+ "-C",
47
+ projectRoot,
48
+ "-s",
49
+ requireString(sandboxMode, "sandbox-mode"),
50
+ "-o",
51
+ outputPath,
52
+ "--skip-git-repo-check",
53
+ ];
54
+ if (typeof reasoningEffort === "string" && reasoningEffort.length > 0) {
55
+ codexArgs.push("-c", `model_reasoning_effort="${reasoningEffort}"`);
56
+ }
57
+ if (typeof model === "string" && model.length > 0) {
58
+ codexArgs.push("-m", model);
59
+ }
60
+ for (const override of configOverrides) {
61
+ codexArgs.push("-c", override);
62
+ }
63
+ codexArgs.push("-");
64
+ const child = spawn("codex", codexArgs, {
65
+ cwd: projectRoot,
66
+ stdio: ["pipe", "pipe", "pipe"],
67
+ });
68
+ // Real-time tee to disk: each codex stdout/stderr chunk is appended to
69
+ // the running log under the lens output directory so a watcher pane
70
+ // can `tail -f` it live. The in-memory buffers remain for final error
71
+ // reporting. Stream path mirrors the nested worker pattern
72
+ // (hidden filename, sessionRoot/round1/.<lens>.running.log). The
73
+ // lifecycle — rename on failure / rm on success — happens after the
74
+ // child exits, below.
75
+ const outputDir = path.dirname(outputPath);
76
+ const runningLogPath = path.join(outputDir, `.${unitId}.running.log`);
77
+ let runningLogStream = null;
78
+ try {
79
+ fsSync.mkdirSync(outputDir, { recursive: true });
80
+ runningLogStream = fsSync.createWriteStream(runningLogPath, { flags: "w" });
81
+ runningLogStream.write(`ENV-BEFORE unit=${unitId} output=${outputPath}\n`);
82
+ }
83
+ catch {
84
+ // Best-effort; streaming failure must not block the actual codex run.
85
+ runningLogStream = null;
86
+ }
87
+ let stdout = "";
88
+ let stderr = "";
89
+ child.stdout.on("data", (chunk) => {
90
+ stdout += String(chunk);
91
+ if (runningLogStream)
92
+ runningLogStream.write(chunk);
93
+ });
94
+ child.stderr.on("data", (chunk) => {
95
+ stderr += String(chunk);
96
+ if (runningLogStream)
97
+ runningLogStream.write(chunk);
98
+ });
99
+ child.stdin.write(boundedPrompt);
100
+ child.stdin.end();
101
+ const exitCode = await new Promise((resolve, reject) => {
102
+ child.on("error", (err) => {
103
+ if (err.code === "ENOENT") {
104
+ reject(new Error("codex CLI not found. Install codex or use a different executor."));
105
+ }
106
+ else {
107
+ reject(err);
108
+ }
109
+ });
110
+ child.on("close", (code) => resolve(code ?? 1));
111
+ });
112
+ // Flush the stream before deciding cleanup so tail -f readers see final
113
+ // bytes. ENV-AFTER line is written before close for parse parity with
114
+ // the codex-nested running log.
115
+ if (runningLogStream) {
116
+ try {
117
+ runningLogStream.write(`ENV-AFTER unit=${unitId} exit=${exitCode}\n`);
118
+ }
119
+ catch {
120
+ // ignore
121
+ }
122
+ try {
123
+ runningLogStream.end();
124
+ }
125
+ catch {
126
+ // ignore
127
+ }
128
+ }
129
+ if (exitCode !== 0) {
130
+ // Failure path — persist running log for post-hoc inspection at a
131
+ // stable path (renaming from .running.log to .nested-stderr.log
132
+ // keeps a single per-lens failure trace filename).
133
+ try {
134
+ const nestedErrPath = path.join(outputDir, `.${unitId}.nested-stderr.log`);
135
+ fsSync.renameSync(runningLogPath, nestedErrPath);
136
+ }
137
+ catch {
138
+ // running log may not exist (stream setup failed) — best effort
139
+ }
140
+ const combinedMessage = [stderr.trim(), stdout.trim()]
141
+ .filter((message) => message.length > 0)
142
+ .join("\n");
143
+ throw new Error(combinedMessage.length > 0
144
+ ? combinedMessage
145
+ : `Codex worker executor exited with code ${exitCode}`);
146
+ }
147
+ // Success — remove the running log to keep round1/ listing principal-
148
+ // facing lens outputs only. The watcher pane saw it live; the final
149
+ // result is in <outputPath>.
150
+ try {
151
+ fsSync.rmSync(runningLogPath, { force: true });
152
+ }
153
+ catch {
154
+ // ignore
155
+ }
156
+ // Codex CLI -o flag may not reliably write the output file.
157
+ // If the file is missing or empty, fall back to stdout.
158
+ const outputExists = await fs.access(outputPath).then(() => true, () => false);
159
+ const outputSize = outputExists ? (await fs.stat(outputPath)).size : 0;
160
+ if (!outputExists || outputSize === 0) {
161
+ const normalizedOutput = stdout.trim();
162
+ if (normalizedOutput.length === 0) {
163
+ throw new Error("Codex worker executor produced no output (neither -o file nor stdout).");
164
+ }
165
+ await fs.writeFile(outputPath, `${normalizedOutput}\n`, "utf8");
166
+ }
167
+ }
168
+ export async function runCodexReviewUnitExecutorCli(argv) {
169
+ const { values } = parseArgs({
170
+ options: {
171
+ "project-root": { type: "string", default: "." },
172
+ "session-root": { type: "string" },
173
+ "unit-id": { type: "string" },
174
+ "unit-kind": { type: "string" },
175
+ "packet-path": { type: "string" },
176
+ "output-path": { type: "string" },
177
+ model: { type: "string" },
178
+ "sandbox-mode": { type: "string", default: "read-only" },
179
+ "reasoning-effort": { type: "string" },
180
+ "config-override": { type: "string", multiple: true, default: [] },
181
+ },
182
+ strict: true,
183
+ allowPositionals: false,
184
+ args: argv,
185
+ });
186
+ const projectRoot = path.resolve(requireString(values["project-root"], "project-root"));
187
+ const unitId = requireString(values["unit-id"], "unit-id");
188
+ const unitKind = requireString(values["unit-kind"], "unit-kind");
189
+ const packetPath = path.resolve(requireString(values["packet-path"], "packet-path"));
190
+ const outputPath = path.resolve(requireString(values["output-path"], "output-path"));
191
+ // Review Recovery PR-1 (R1 observability symmetry). The codex executor does
192
+ // NOT go through callLlm — it spawns `codex exec` directly — so the PR-1
193
+ // [model-call] logs in llm-caller.ts cover the background-task path only.
194
+ // This single startup emit gives parent-process log correlators a breadcrumb
195
+ // for the lens-execution Codex worker too, so a 5-lens review produces
196
+ // one [plan:executor] line per lens regardless of provider identity.
197
+ process.stderr.write(`[plan:executor] kind=codex unit_id=${unitId} model=${typeof values.model === "string" && values.model.length > 0
198
+ ? values.model
199
+ : "(codex default)"} sandbox=${values["sandbox-mode"] ?? "read-only"} effort=${typeof values["reasoning-effort"] === "string" && values["reasoning-effort"].length > 0
200
+ ? values["reasoning-effort"]
201
+ : "(codex default)"}\n`);
202
+ const packetText = await fs.readFile(packetPath, "utf8");
203
+ const boundedPrompt = buildBoundedPrompt(packetPath, packetText, outputPath, unitId, unitKind);
204
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
205
+ await runCodexWorker(projectRoot, boundedPrompt, outputPath, values.model, values["sandbox-mode"], values["reasoning-effort"], values["config-override"], unitId);
206
+ const outputText = await fs.readFile(outputPath, "utf8");
207
+ if (outputText.trim().length === 0) {
208
+ throw new Error(`Codex executor produced empty output: ${outputPath}`);
209
+ }
210
+ console.log(JSON.stringify({
211
+ unit_id: unitId,
212
+ unit_kind: unitKind,
213
+ packet_path: packetPath,
214
+ output_path: outputPath,
215
+ realization: "worker",
216
+ host_runtime: "codex",
217
+ }, null, 2));
218
+ return 0;
219
+ }
220
+ async function main() {
221
+ return runCodexReviewUnitExecutorCli(process.argv.slice(2));
222
+ }
223
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
224
+ main().then((exitCode) => process.exit(exitCode), (error) => {
225
+ console.error(error instanceof Error ? error.message : String(error));
226
+ process.exit(1);
227
+ });
228
+ }
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { pathToFileURL } from "node:url";
4
+ import { runAssembleReviewRecordCli } from "./assemble-review-record.js";
5
+ import { runRenderReviewFinalOutputCli } from "./render-review-final-output.js";
6
+ import { printOntoReleaseChannelNotice } from "../release-channel/release-channel.js";
7
+ function requireString(value, optionName) {
8
+ if (typeof value !== "string" || value.length === 0) {
9
+ throw new Error(`Missing required option --${optionName}`);
10
+ }
11
+ return value;
12
+ }
13
+ async function main() {
14
+ await printOntoReleaseChannelNotice();
15
+ return runCompleteReviewSessionCli(process.argv.slice(2));
16
+ }
17
+ export async function completeReviewSession(argv) {
18
+ const { values } = parseArgs({
19
+ options: {
20
+ "project-root": { type: "string", default: "." },
21
+ "onto-home": { type: "string" },
22
+ "session-root": { type: "string" },
23
+ "request-text": { type: "string" },
24
+ },
25
+ strict: true,
26
+ allowPositionals: false,
27
+ args: argv,
28
+ });
29
+ const projectRoot = requireString(values["project-root"], "project-root");
30
+ const sessionRoot = requireString(values["session-root"], "session-root");
31
+ const requestText = requireString(values["request-text"], "request-text");
32
+ await runRenderReviewFinalOutputCli([
33
+ "--project-root",
34
+ projectRoot,
35
+ "--session-root",
36
+ sessionRoot,
37
+ ]);
38
+ await runAssembleReviewRecordCli([
39
+ "--project-root",
40
+ projectRoot,
41
+ "--session-root",
42
+ sessionRoot,
43
+ "--request-text",
44
+ requestText,
45
+ ]);
46
+ return {
47
+ session_root: sessionRoot,
48
+ bounded_complete_steps: [
49
+ "review:render-final-output",
50
+ "review:finalize-session",
51
+ ],
52
+ };
53
+ }
54
+ export async function runCompleteReviewSessionCli(argv) {
55
+ const result = await completeReviewSession(argv);
56
+ console.log(JSON.stringify(result, null, 2));
57
+ return 0;
58
+ }
59
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
60
+ main().then((exitCode) => process.exit(exitCode), (error) => {
61
+ console.error(error instanceof Error ? error.message : String(error));
62
+ process.exit(1);
63
+ });
64
+ }