onto-mcp 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/.onto/processes/reconstruct/actionable-ontology-seed-recomposition-design.md +447 -0
  2. package/.onto/processes/reconstruct/foundry-style-ontology-seed-contract.md +934 -0
  3. package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +303 -725
  4. package/.onto/processes/reconstruct/reconstruct-contract-registry.yaml +1645 -0
  5. package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +26 -22
  6. package/.onto/processes/reconstruct/source-profile-contract.md +49 -23
  7. package/.onto/processes/reconstruct/source-profiles/code.md +6 -3
  8. package/.onto/processes/reconstruct/source-profiles/database.md +5 -2
  9. package/.onto/processes/reconstruct/source-profiles/document.md +5 -2
  10. package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +5 -4
  11. package/.onto/processes/review/review-execution-ux-contract.md +40 -0
  12. package/.onto/processes/shared/pipeline-execution-ledger-contract.md +26 -10
  13. package/.onto/processes/shared/target-material-kind-contract.md +29 -16
  14. package/AGENTS.md +6 -4
  15. package/README.md +149 -76
  16. package/dist/cli.js +8 -8
  17. package/dist/core-api/reconstruct-api.js +117 -31
  18. package/dist/core-api/review-api.js +47 -0
  19. package/dist/core-runtime/cli/codex-review-unit-executor.js +39 -2
  20. package/dist/core-runtime/cli/complete-review-session.js +2 -2
  21. package/dist/core-runtime/cli/mock-review-unit-executor.js +1 -1
  22. package/dist/core-runtime/cli/review-invoke.js +9 -9
  23. package/dist/core-runtime/cli/run-review-prompt-execution.js +39 -5
  24. package/dist/core-runtime/cli/spawn-watcher.js +266 -47
  25. package/dist/core-runtime/cli/start-review-session.js +3 -3
  26. package/dist/core-runtime/llm/llm-caller.js +11 -0
  27. package/dist/core-runtime/llm/llm-tool-loop.js +2 -0
  28. package/dist/core-runtime/observability/runtime-stream-observation.js +118 -0
  29. package/dist/core-runtime/onboard/cli-host.js +174 -0
  30. package/dist/core-runtime/onboard/host-target.js +22 -0
  31. package/dist/core-runtime/onboard/json-config-host.js +122 -0
  32. package/dist/core-runtime/onboard/path-scan.js +26 -0
  33. package/dist/core-runtime/onboard/prompt.js +51 -0
  34. package/dist/core-runtime/onboard/register.js +214 -0
  35. package/dist/core-runtime/onboard/types.js +27 -0
  36. package/dist/core-runtime/reconstruct/actionable-seed-validation.js +1777 -0
  37. package/dist/core-runtime/reconstruct/artifact-types.js +10 -4
  38. package/dist/core-runtime/reconstruct/contract-registry.js +623 -0
  39. package/dist/core-runtime/reconstruct/domain-id.js +10 -0
  40. package/dist/core-runtime/reconstruct/governing-snapshot.js +716 -0
  41. package/dist/core-runtime/reconstruct/material-profile-validation.js +191 -0
  42. package/dist/core-runtime/reconstruct/materialize-preparation.js +49 -11
  43. package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +269 -79
  44. package/dist/core-runtime/reconstruct/post-seed-validation.js +1194 -51
  45. package/dist/core-runtime/reconstruct/record.js +104 -20
  46. package/dist/core-runtime/reconstruct/run.js +2107 -413
  47. package/dist/core-runtime/reconstruct/seed-claim-projections.js +268 -0
  48. package/dist/core-runtime/reconstruct/source-profiles.js +93 -4
  49. package/dist/core-runtime/reconstruct/terminal-validation.js +807 -0
  50. package/dist/core-runtime/review/review-invocation-runner.js +4 -4
  51. package/dist/mcp/server.js +110 -38
  52. package/dist/mcp/tool-schemas.js +20 -6
  53. package/package.json +8 -17
  54. package/scripts/onto-review-watch.sh +486 -0
  55. package/scripts/onto-runtime-watch.sh +122 -0
  56. package/scripts/postinstall-hint.js +22 -0
  57. package/.onto/processes/reconstruct/top-level-concept-discovery-contract.md +0 -387
  58. package/dist/core-runtime/cli/bootstrap-review-binding.js +0 -186
  59. package/dist/core-runtime/cli/codex-nested-dispatch.test.js +0 -390
  60. package/dist/core-runtime/cli/codex-nested-teamlead-executor.test.js +0 -335
  61. package/dist/core-runtime/cli/coordinator-helpers.js +0 -583
  62. package/dist/core-runtime/cli/coordinator-state-machine-deliberation.test.js +0 -167
  63. package/dist/core-runtime/cli/coordinator-state-machine.js +0 -794
  64. package/dist/core-runtime/cli/e2e-codex-multi-agent-fixes.test.js +0 -615
  65. package/dist/core-runtime/cli/e2e-start-review-session.test.js +0 -312
  66. package/dist/core-runtime/cli/health.js +0 -44
  67. package/dist/core-runtime/cli/inline-http-review-unit-executor.test.js +0 -567
  68. package/dist/core-runtime/cli/materialize-review-execution-preparation.js +0 -104
  69. package/dist/core-runtime/cli/migrate-session-roots.js +0 -118
  70. package/dist/core-runtime/cli/repo-layout-migration-replace.smoke.test.js +0 -106
  71. package/dist/core-runtime/cli/review-invoke-auto-resolution.test.js +0 -268
  72. package/dist/core-runtime/cli/review-invoke-coordinator-topology.test.js +0 -136
  73. package/dist/core-runtime/cli/review-invoke-resolver-caching.test.js +0 -201
  74. package/dist/core-runtime/cli/review-invoke-topology-dispatch.test.js +0 -192
  75. package/dist/core-runtime/cli/session-root-guard.js +0 -168
  76. package/dist/core-runtime/cli/spawn-watcher.test.js +0 -457
  77. package/dist/core-runtime/cli/strip-wrapping-code-fence.test.js +0 -79
  78. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.js +0 -412
  79. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.test.js +0 -351
  80. package/dist/core-runtime/cli/topology-executor-mapping.js +0 -139
  81. package/dist/core-runtime/cli/topology-executor-mapping.test.js +0 -173
  82. package/dist/core-runtime/cli/write-review-interpretation.js +0 -81
  83. package/dist/core-runtime/config/onto-config-cli.js +0 -278
  84. package/dist/core-runtime/config/onto-config-key-path.js +0 -288
  85. package/dist/core-runtime/config/onto-config-key-path.test.js +0 -195
  86. package/dist/core-runtime/config/onto-config-preview.js +0 -108
  87. package/dist/core-runtime/config/onto-config-preview.test.js +0 -132
  88. package/dist/core-runtime/discovery/config-chain.js +0 -118
  89. package/dist/core-runtime/discovery/config-chain.test.js +0 -103
  90. package/dist/core-runtime/discovery/config-profile.js +0 -199
  91. package/dist/core-runtime/discovery/config-profile.test.js +0 -233
  92. package/dist/core-runtime/discovery/host-detection.test.js +0 -186
  93. package/dist/core-runtime/discovery/installation-paths.test.js +0 -65
  94. package/dist/core-runtime/discovery/lens-registry.test.js +0 -81
  95. package/dist/core-runtime/discovery/path-normalization.test.js +0 -22
  96. package/dist/core-runtime/discovery/plugin-path.js +0 -72
  97. package/dist/core-runtime/discovery/plugin-path.test.js +0 -95
  98. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.js +0 -344
  99. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.test.js +0 -915
  100. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.js +0 -564
  101. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.test.js +0 -708
  102. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.js +0 -165
  103. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.test.js +0 -227
  104. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.js +0 -59
  105. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.test.js +0 -205
  106. package/dist/core-runtime/evolve/adapters/methodology/adapter.js +0 -16
  107. package/dist/core-runtime/evolve/adapters/methodology/adapter.test.js +0 -9
  108. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.js +0 -298
  109. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.test.js +0 -70
  110. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.js +0 -46
  111. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.test.js +0 -73
  112. package/dist/core-runtime/evolve/adapters/registry.js +0 -47
  113. package/dist/core-runtime/evolve/adapters/registry.test.js +0 -67
  114. package/dist/core-runtime/evolve/cli.js +0 -256
  115. package/dist/core-runtime/evolve/commands/align.js +0 -194
  116. package/dist/core-runtime/evolve/commands/align.test.js +0 -82
  117. package/dist/core-runtime/evolve/commands/apply.js +0 -161
  118. package/dist/core-runtime/evolve/commands/apply.test.js +0 -138
  119. package/dist/core-runtime/evolve/commands/close.js +0 -39
  120. package/dist/core-runtime/evolve/commands/close.test.js +0 -99
  121. package/dist/core-runtime/evolve/commands/defer.js +0 -40
  122. package/dist/core-runtime/evolve/commands/defer.test.js +0 -134
  123. package/dist/core-runtime/evolve/commands/draft.js +0 -323
  124. package/dist/core-runtime/evolve/commands/draft.test.js +0 -178
  125. package/dist/core-runtime/evolve/commands/e2e-evolve-full-cycle.test.js +0 -208
  126. package/dist/core-runtime/evolve/commands/error-messages.js +0 -125
  127. package/dist/core-runtime/evolve/commands/error-messages.test.js +0 -167
  128. package/dist/core-runtime/evolve/commands/propose-align.js +0 -222
  129. package/dist/core-runtime/evolve/commands/propose-align.test.js +0 -136
  130. package/dist/core-runtime/evolve/commands/reconstruct.js +0 -330
  131. package/dist/core-runtime/evolve/commands/reconstruct.test.js +0 -278
  132. package/dist/core-runtime/evolve/commands/shared.js +0 -22
  133. package/dist/core-runtime/evolve/commands/stale-check.js +0 -103
  134. package/dist/core-runtime/evolve/commands/stale-check.test.js +0 -84
  135. package/dist/core-runtime/evolve/commands/start.js +0 -887
  136. package/dist/core-runtime/evolve/commands/start.test.js +0 -396
  137. package/dist/core-runtime/evolve/config/project-config.js +0 -99
  138. package/dist/core-runtime/evolve/config/project-config.test.js +0 -170
  139. package/dist/core-runtime/evolve/renderers/align-packet.js +0 -280
  140. package/dist/core-runtime/evolve/renderers/align-packet.test.js +0 -332
  141. package/dist/core-runtime/evolve/renderers/draft-packet.js +0 -303
  142. package/dist/core-runtime/evolve/renderers/draft-packet.test.js +0 -377
  143. package/dist/core-runtime/evolve/renderers/format.js +0 -5
  144. package/dist/core-runtime/evolve/renderers/scope-md.js +0 -237
  145. package/dist/core-runtime/evolve/renderers/scope-md.test.js +0 -306
  146. package/dist/core-runtime/govern/cli.js +0 -369
  147. package/dist/core-runtime/govern/cli.test.js +0 -314
  148. package/dist/core-runtime/govern/drift-engine.js +0 -103
  149. package/dist/core-runtime/govern/drift-engine.test.js +0 -319
  150. package/dist/core-runtime/govern/promote-principle.js +0 -206
  151. package/dist/core-runtime/govern/promote-principle.test.js +0 -368
  152. package/dist/core-runtime/govern/queue.js +0 -81
  153. package/dist/core-runtime/govern/types.js +0 -16
  154. package/dist/core-runtime/install/cli.js +0 -530
  155. package/dist/core-runtime/install/detect.js +0 -128
  156. package/dist/core-runtime/install/detect.test.js +0 -155
  157. package/dist/core-runtime/install/gitignore-update.js +0 -74
  158. package/dist/core-runtime/install/gitignore-update.test.js +0 -64
  159. package/dist/core-runtime/install/install-integration.test.js +0 -373
  160. package/dist/core-runtime/install/prompts.js +0 -389
  161. package/dist/core-runtime/install/prompts.test.js +0 -293
  162. package/dist/core-runtime/install/types.js +0 -26
  163. package/dist/core-runtime/install/validation.js +0 -295
  164. package/dist/core-runtime/install/validation.test.js +0 -313
  165. package/dist/core-runtime/install/writer.js +0 -254
  166. package/dist/core-runtime/install/writer.test.js +0 -218
  167. package/dist/core-runtime/learning/extractor.js +0 -461
  168. package/dist/core-runtime/learning/feedback.js +0 -179
  169. package/dist/core-runtime/learning/health-report.js +0 -165
  170. package/dist/core-runtime/learning/health-report.test.js +0 -169
  171. package/dist/core-runtime/learning/loader.js +0 -388
  172. package/dist/core-runtime/learning/loader.test.js +0 -102
  173. package/dist/core-runtime/learning/promote/apply-state.js +0 -240
  174. package/dist/core-runtime/learning/promote/audit-obligation.js +0 -195
  175. package/dist/core-runtime/learning/promote/collector.js +0 -432
  176. package/dist/core-runtime/learning/promote/degraded-state.js +0 -125
  177. package/dist/core-runtime/learning/promote/domain-doc-proposer.js +0 -166
  178. package/dist/core-runtime/learning/promote/e2e-promote.test.js +0 -6385
  179. package/dist/core-runtime/learning/promote/health-snapshot.js +0 -150
  180. package/dist/core-runtime/learning/promote/insight-reclassifier.js +0 -544
  181. package/dist/core-runtime/learning/promote/judgment-auditor.js +0 -517
  182. package/dist/core-runtime/learning/promote/panel-reviewer.js +0 -1158
  183. package/dist/core-runtime/learning/promote/promote-executor.js +0 -1675
  184. package/dist/core-runtime/learning/promote/promoter.js +0 -307
  185. package/dist/core-runtime/learning/promote/retirement.js +0 -122
  186. package/dist/core-runtime/learning/promote/types.js +0 -23
  187. package/dist/core-runtime/learning/prompt-sections.js +0 -51
  188. package/dist/core-runtime/learning/shared/artifact-registry-init.js +0 -45
  189. package/dist/core-runtime/learning/shared/artifact-registry.js +0 -254
  190. package/dist/core-runtime/learning/shared/audit-obligation-kernel.js +0 -73
  191. package/dist/core-runtime/learning/shared/audit-state.js +0 -99
  192. package/dist/core-runtime/learning/shared/duplicate-check.js +0 -28
  193. package/dist/core-runtime/learning/shared/llm-caller.js +0 -831
  194. package/dist/core-runtime/learning/shared/llm-caller.test.js +0 -601
  195. package/dist/core-runtime/learning/shared/llm-tool-loop.js +0 -393
  196. package/dist/core-runtime/learning/shared/mode.js +0 -25
  197. package/dist/core-runtime/learning/shared/paths.js +0 -84
  198. package/dist/core-runtime/learning/shared/paths.test.js +0 -79
  199. package/dist/core-runtime/learning/shared/patterns.js +0 -37
  200. package/dist/core-runtime/learning/shared/recoverability.js +0 -355
  201. package/dist/core-runtime/learning/shared/recovery-context.js +0 -374
  202. package/dist/core-runtime/learning/shared/scope.js +0 -1
  203. package/dist/core-runtime/learning/shared/semantic-classifier.js +0 -94
  204. package/dist/core-runtime/learning/shared/specs/apply-execution-state-spec.js +0 -42
  205. package/dist/core-runtime/learning/shared/specs/audit-state-spec.js +0 -37
  206. package/dist/core-runtime/learning/shared/specs/backup-metadata-spec.js +0 -39
  207. package/dist/core-runtime/learning/shared/specs/emergency-log-spec.js +0 -41
  208. package/dist/core-runtime/learning/shared/specs/layout-version-spec.js +0 -38
  209. package/dist/core-runtime/learning/shared/specs/promote-decisions-spec.js +0 -43
  210. package/dist/core-runtime/learning/shared/specs/promote-report-spec.js +0 -113
  211. package/dist/core-runtime/learning/shared/specs/prune-log-spec.js +0 -36
  212. package/dist/core-runtime/learning/shared/specs/recovery-resolution-spec.js +0 -48
  213. package/dist/core-runtime/learning/shared/specs/restore-manifest-spec.js +0 -43
  214. package/dist/core-runtime/learning/shared/specs/spec-helpers.js +0 -64
  215. package/dist/core-runtime/learning/usage-tracker.js +0 -190
  216. package/dist/core-runtime/learning/usage-tracker.test.js +0 -176
  217. package/dist/core-runtime/onboard/detect-review-axes.js +0 -122
  218. package/dist/core-runtime/onboard/detect-review-axes.test.js +0 -127
  219. package/dist/core-runtime/onboard/write-review-block.js +0 -188
  220. package/dist/core-runtime/onboard/write-review-block.test.js +0 -240
  221. package/dist/core-runtime/readers/brownfield-builder.js +0 -150
  222. package/dist/core-runtime/readers/brownfield-builder.test.js +0 -136
  223. package/dist/core-runtime/readers/code-chunk-collector.js +0 -53
  224. package/dist/core-runtime/readers/code-chunk-collector.test.js +0 -136
  225. package/dist/core-runtime/readers/file-utils.js +0 -240
  226. package/dist/core-runtime/readers/file-utils.test.js +0 -146
  227. package/dist/core-runtime/readers/lexicon-citation-check.js +0 -93
  228. package/dist/core-runtime/readers/lexicon-citation-check.test.js +0 -77
  229. package/dist/core-runtime/readers/mcp-figma.js +0 -30
  230. package/dist/core-runtime/readers/mcp-figma.test.js +0 -82
  231. package/dist/core-runtime/readers/mcp-generic.js +0 -31
  232. package/dist/core-runtime/readers/mcp-generic.test.js +0 -76
  233. package/dist/core-runtime/readers/ontology-index.js +0 -148
  234. package/dist/core-runtime/readers/ontology-index.test.js +0 -245
  235. package/dist/core-runtime/readers/ontology-query.js +0 -168
  236. package/dist/core-runtime/readers/ontology-query.test.js +0 -311
  237. package/dist/core-runtime/readers/ontology-resolve.js +0 -48
  238. package/dist/core-runtime/readers/ontology-resolve.test.js +0 -48
  239. package/dist/core-runtime/readers/patterns/index.js +0 -7
  240. package/dist/core-runtime/readers/review-log.js +0 -213
  241. package/dist/core-runtime/readers/review-log.test.js +0 -313
  242. package/dist/core-runtime/readers/scan-local.js +0 -102
  243. package/dist/core-runtime/readers/scan-local.test.js +0 -102
  244. package/dist/core-runtime/readers/scan-tarball.js +0 -121
  245. package/dist/core-runtime/readers/scan-tarball.test.js +0 -283
  246. package/dist/core-runtime/readers/scan-vault.js +0 -34
  247. package/dist/core-runtime/readers/scan-vault.test.js +0 -81
  248. package/dist/core-runtime/readers/types.js +0 -42
  249. package/dist/core-runtime/readers/types.test.js +0 -94
  250. package/dist/core-runtime/readers/viewpoint-collectors.js +0 -229
  251. package/dist/core-runtime/reconstruct/seed-candidate-validation.js +0 -385
  252. package/dist/core-runtime/review/citation-audit.test.js +0 -165
  253. package/dist/core-runtime/review/execution-plan-resolver.js +0 -247
  254. package/dist/core-runtime/review/execution-plan-resolver.test.js +0 -243
  255. package/dist/core-runtime/review/execution-topology-resolver-axis-first.test.js +0 -246
  256. package/dist/core-runtime/review/execution-topology-resolver.js +0 -401
  257. package/dist/core-runtime/review/execution-topology-resolver.test.js +0 -315
  258. package/dist/core-runtime/review/inline-context-embedder.test.js +0 -154
  259. package/dist/core-runtime/review/legacy-mode-policy.js +0 -88
  260. package/dist/core-runtime/review/materializers-effort-persist.test.js +0 -79
  261. package/dist/core-runtime/review/ontology-path-classifier.js +0 -179
  262. package/dist/core-runtime/review/ontology-path-classifier.test.js +0 -216
  263. package/dist/core-runtime/review/packet-boundary-policy.test.js +0 -107
  264. package/dist/core-runtime/review/participating-lens-paths.test.js +0 -73
  265. package/dist/core-runtime/review/review-config-legacy-translate.js +0 -244
  266. package/dist/core-runtime/review/review-config-legacy-translate.test.js +0 -161
  267. package/dist/core-runtime/review/review-config-validator.js +0 -289
  268. package/dist/core-runtime/review/review-config-validator.test.js +0 -236
  269. package/dist/core-runtime/review/shape-pipeline-audit.test.js +0 -311
  270. package/dist/core-runtime/review/shape-to-topology-id.js +0 -117
  271. package/dist/core-runtime/review/shape-to-topology-id.test.js +0 -132
  272. package/dist/core-runtime/review/topology-shape-derivation.js +0 -155
  273. package/dist/core-runtime/review/topology-shape-derivation.test.js +0 -195
  274. package/dist/core-runtime/scope-runtime/constants.js +0 -12
  275. package/dist/core-runtime/scope-runtime/constraint-pool.js +0 -166
  276. package/dist/core-runtime/scope-runtime/constraint-pool.test.js +0 -674
  277. package/dist/core-runtime/scope-runtime/domain-validation-log.js +0 -135
  278. package/dist/core-runtime/scope-runtime/domain-validation-log.test.js +0 -156
  279. package/dist/core-runtime/scope-runtime/eval-persistence.js +0 -65
  280. package/dist/core-runtime/scope-runtime/eval-persistence.test.js +0 -84
  281. package/dist/core-runtime/scope-runtime/event-pipeline.js +0 -64
  282. package/dist/core-runtime/scope-runtime/event-pipeline.test.js +0 -450
  283. package/dist/core-runtime/scope-runtime/event-store.js +0 -39
  284. package/dist/core-runtime/scope-runtime/event-store.test.js +0 -95
  285. package/dist/core-runtime/scope-runtime/gate-guard.js +0 -348
  286. package/dist/core-runtime/scope-runtime/gate-guard.test.js +0 -1047
  287. package/dist/core-runtime/scope-runtime/hash.js +0 -4
  288. package/dist/core-runtime/scope-runtime/hash.test.js +0 -33
  289. package/dist/core-runtime/scope-runtime/id.js +0 -4
  290. package/dist/core-runtime/scope-runtime/id.test.js +0 -17
  291. package/dist/core-runtime/scope-runtime/reducer.js +0 -297
  292. package/dist/core-runtime/scope-runtime/reducer.test.js +0 -759
  293. package/dist/core-runtime/scope-runtime/scope-manager.js +0 -161
  294. package/dist/core-runtime/scope-runtime/state-machine.js +0 -309
  295. package/dist/core-runtime/scope-runtime/state-machine.test.js +0 -704
  296. package/dist/core-runtime/scope-runtime/types.js +0 -116
  297. package/dist/core-runtime/scope-runtime/types.test.js +0 -69
  298. package/dist/core-runtime/translate/render-for-user.js +0 -169
  299. package/dist/core-runtime/translate/render-for-user.test.js +0 -122
  300. package/dist/providers/capability-contract.js +0 -1
@@ -1,351 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
- import { DeliberationOptInError, buildDeliberationPlan, buildDeliberationRound1Prompt, buildDeliberationRound2Prompt, deliberationArtifactPath, extractDisagreements, readDeliberationArtifact, requireDeliberationOptIn, runLensAgentDeliberation, writeDeliberationArtifact, } from "./teamcreate-lens-deliberation-executor.js";
6
- // ---------------------------------------------------------------------------
7
- // These tests assert the PR-D deliberation protocol invariants:
8
- //
9
- // (1) Triple opt-in is enforced at module boundary — missing any of
10
- // CLAUDECODE, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS, or
11
- // config.lens_agent_teams_mode throws DeliberationOptInError with
12
- // the missing items enumerated.
13
- // (2) Round 1 prompt embeds OTHER lens outputs (not own), asks for
14
- // re-evaluation, declares the required response section headings.
15
- // (3) Round 2 prompt embeds ALL round-1 responses, asks for convergence
16
- // + explicit persistent disagreements.
17
- // (4) Artifact paths are deterministic: <dir>/round{N}/<lens>-deliberation.md.
18
- // (5) Read/write round-trip preserves content.
19
- // (6) Disagreement extraction finds "## 지속적 이견" sections, parses
20
- // "- **이견 항목**:" entries, tolerates English variant heading.
21
- // (7) runLensAgentDeliberation produces a plan with N*round steps in
22
- // stable order, each with prompt + artifact_path populated.
23
- // ---------------------------------------------------------------------------
24
- const LENSES = [
25
- { lens_id: "logic", output_path: "/tmp/fake/round0/logic.md" },
26
- { lens_id: "pragmatics", output_path: "/tmp/fake/round0/pragmatics.md" },
27
- { lens_id: "axiology", output_path: "/tmp/fake/round0/axiology.md" },
28
- ];
29
- // ---------------------------------------------------------------------------
30
- // requireDeliberationOptIn
31
- // ---------------------------------------------------------------------------
32
- describe("requireDeliberationOptIn", () => {
33
- it("passes when all three flags satisfied", () => {
34
- expect(() => requireDeliberationOptIn({ lens_agent_teams_mode: true }, {
35
- CLAUDECODE: "1",
36
- CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1",
37
- })).not.toThrow();
38
- });
39
- it("throws with CLAUDECODE missing", () => {
40
- try {
41
- requireDeliberationOptIn({ lens_agent_teams_mode: true }, { CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" });
42
- expect.fail("expected throw");
43
- }
44
- catch (err) {
45
- expect(err).toBeInstanceOf(DeliberationOptInError);
46
- expect(err.missing.join("\n")).toContain("CLAUDECODE=1");
47
- }
48
- });
49
- it("throws with experimental flag missing", () => {
50
- try {
51
- requireDeliberationOptIn({ lens_agent_teams_mode: true }, { CLAUDECODE: "1" });
52
- expect.fail("expected throw");
53
- }
54
- catch (err) {
55
- const m = err.missing.join("\n");
56
- expect(m).toContain("EXPERIMENTAL_AGENT_TEAMS");
57
- }
58
- });
59
- it("throws with config.lens_agent_teams_mode missing", () => {
60
- try {
61
- requireDeliberationOptIn({}, {
62
- CLAUDECODE: "1",
63
- CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1",
64
- });
65
- expect.fail("expected throw");
66
- }
67
- catch (err) {
68
- const m = err.missing.join("\n");
69
- expect(m).toContain("lens_agent_teams_mode");
70
- }
71
- });
72
- it("message enumerates ALL missing flags (not just the first)", () => {
73
- try {
74
- requireDeliberationOptIn({ lens_agent_teams_mode: false }, {});
75
- expect.fail("expected throw");
76
- }
77
- catch (err) {
78
- const msg = err.message;
79
- expect(msg).toContain("CLAUDECODE=1");
80
- expect(msg).toContain("EXPERIMENTAL_AGENT_TEAMS");
81
- expect(msg).toContain("lens_agent_teams_mode");
82
- }
83
- });
84
- });
85
- // ---------------------------------------------------------------------------
86
- // Prompt templates
87
- // ---------------------------------------------------------------------------
88
- describe("buildDeliberationRound1Prompt", () => {
89
- it("embeds every OTHER lens output as its own block", () => {
90
- const prompt = buildDeliberationRound1Prompt({
91
- own_lens_id: "logic",
92
- own_output_summary: "logic 의 기존 결론",
93
- other_lens_outputs: [
94
- { lens_id: "pragmatics", content: "pragmatics output body" },
95
- { lens_id: "axiology", content: "axiology output body" },
96
- ],
97
- });
98
- expect(prompt).toContain("## Lens: pragmatics");
99
- expect(prompt).toContain("pragmatics output body");
100
- expect(prompt).toContain("## Lens: axiology");
101
- expect(prompt).toContain("axiology output body");
102
- });
103
- it("does NOT embed the lens's own output verbatim (it's already in its session memory)", () => {
104
- const prompt = buildDeliberationRound1Prompt({
105
- own_lens_id: "logic",
106
- own_output_summary: "summary of logic body",
107
- other_lens_outputs: [{ lens_id: "pragmatics", content: "other body" }],
108
- });
109
- expect(prompt).toContain("summary of logic body");
110
- expect(prompt).not.toContain("## Lens: logic");
111
- });
112
- it("declares the required response section headings", () => {
113
- const prompt = buildDeliberationRound1Prompt({
114
- own_lens_id: "logic",
115
- own_output_summary: "x",
116
- other_lens_outputs: [],
117
- });
118
- expect(prompt).toContain("재평가 요약");
119
- expect(prompt).toContain("동의/강화 지점");
120
- expect(prompt).toContain("충돌/수정 지점");
121
- expect(prompt).toContain("추가 발견");
122
- });
123
- });
124
- describe("buildDeliberationRound2Prompt", () => {
125
- it("embeds all round-1 responses", () => {
126
- const prompt = buildDeliberationRound2Prompt({
127
- own_lens_id: "logic",
128
- round1_responses: [
129
- { lens_id: "logic", content: "logic r1" },
130
- { lens_id: "pragmatics", content: "pragmatics r1" },
131
- ],
132
- });
133
- expect(prompt).toContain("Round 1 response — lens: logic");
134
- expect(prompt).toContain("Round 1 response — lens: pragmatics");
135
- expect(prompt).toContain("logic r1");
136
- expect(prompt).toContain("pragmatics r1");
137
- });
138
- it("declares required round-2 section headings (수렴 / 이견 / 최종)", () => {
139
- const prompt = buildDeliberationRound2Prompt({
140
- own_lens_id: "logic",
141
- round1_responses: [],
142
- });
143
- expect(prompt).toContain("수렴 요약");
144
- expect(prompt).toContain("지속적 이견");
145
- expect(prompt).toContain("최종 입장");
146
- });
147
- it("explicitly instructs NOT to hide disagreement", () => {
148
- const prompt = buildDeliberationRound2Prompt({
149
- own_lens_id: "logic",
150
- round1_responses: [],
151
- });
152
- expect(prompt).toContain("숨기지");
153
- });
154
- });
155
- // ---------------------------------------------------------------------------
156
- // Artifact path / read / write
157
- // ---------------------------------------------------------------------------
158
- describe("deliberationArtifactPath", () => {
159
- it("composes <dir>/round{N}/<lens>-deliberation.md", () => {
160
- expect(deliberationArtifactPath("/base", 1, "logic")).toBe(path.join("/base", "round1", "logic-deliberation.md"));
161
- expect(deliberationArtifactPath("/base", 2, "axiology")).toBe(path.join("/base", "round2", "axiology-deliberation.md"));
162
- });
163
- });
164
- describe("writeDeliberationArtifact / readDeliberationArtifact", () => {
165
- let tmpRoot;
166
- beforeEach(async () => {
167
- tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "onto-deliberation-"));
168
- });
169
- afterEach(async () => {
170
- await fs.rm(tmpRoot, { recursive: true, force: true });
171
- });
172
- it("round-trips content through disk, creating parent directories", async () => {
173
- const content = "## 재평가 요약\n\n유지.\n";
174
- const filePath = await writeDeliberationArtifact(tmpRoot, 1, "logic", content);
175
- expect(filePath).toBe(deliberationArtifactPath(tmpRoot, 1, "logic"));
176
- const read = await readDeliberationArtifact(tmpRoot, 1, "logic");
177
- expect(read).toBe(content);
178
- });
179
- it("readDeliberationArtifact returns null for missing artifact (not an error)", async () => {
180
- const read = await readDeliberationArtifact(tmpRoot, 2, "never-written");
181
- expect(read).toBeNull();
182
- });
183
- });
184
- // ---------------------------------------------------------------------------
185
- // extractDisagreements
186
- // ---------------------------------------------------------------------------
187
- describe("extractDisagreements", () => {
188
- it("extracts items from a '## 지속적 이견' section", () => {
189
- const round2 = [
190
- {
191
- lens_id: "logic",
192
- content: [
193
- "## 수렴 요약",
194
- "- 모두 동의",
195
- "",
196
- "## 지속적 이견",
197
- "- **이견 항목**: scope creep 정의",
198
- " - 당신의 입장: task 내 한정",
199
- " - 반대 입장 (axiology): 가치 질문 포함 필요",
200
- "- **이견 항목**: severity 스케일",
201
- " - 당신의 입장: 3단계",
202
- " - 반대 입장 (pragmatics): 5단계",
203
- "",
204
- "## 최종 입장",
205
- "입장 유지.",
206
- ].join("\n"),
207
- },
208
- ];
209
- const result = extractDisagreements(round2);
210
- expect(result).toHaveLength(2);
211
- expect(result[0].source_lens_id).toBe("logic");
212
- expect(result[0].title).toBe("scope creep 정의");
213
- expect(result[0].body).toContain("task 내 한정");
214
- expect(result[1].title).toBe("severity 스케일");
215
- });
216
- it("empty section yields empty array", () => {
217
- const round2 = [
218
- { lens_id: "logic", content: "## 수렴 요약\n- OK\n\n## 최종 입장\n입장 유지." },
219
- ];
220
- expect(extractDisagreements(round2)).toEqual([]);
221
- });
222
- it("tolerates English heading 'Persistent Disagreements'", () => {
223
- const round2 = [
224
- {
225
- lens_id: "pragmatics",
226
- content: [
227
- "## Persistent Disagreements",
228
- "- **이견 항목**: naming convention",
229
- " - details here",
230
- ].join("\n"),
231
- },
232
- ];
233
- const result = extractDisagreements(round2);
234
- expect(result).toHaveLength(1);
235
- expect(result[0].title).toBe("naming convention");
236
- });
237
- it("stops at the next ## heading", () => {
238
- const round2 = [
239
- {
240
- lens_id: "logic",
241
- content: [
242
- "## 지속적 이견",
243
- "- **이견 항목**: X",
244
- " - detail",
245
- "## 최종 입장",
246
- "- **이견 항목**: should-not-appear",
247
- ].join("\n"),
248
- },
249
- ];
250
- const result = extractDisagreements(round2);
251
- expect(result).toHaveLength(1);
252
- expect(result[0].title).toBe("X");
253
- });
254
- it("aggregates across multiple round-2 artifacts", () => {
255
- const round2 = [
256
- {
257
- lens_id: "logic",
258
- content: "## 지속적 이견\n- **이견 항목**: A\n - body A",
259
- },
260
- {
261
- lens_id: "pragmatics",
262
- content: "## 지속적 이견\n- **이견 항목**: B\n - body B",
263
- },
264
- ];
265
- const result = extractDisagreements(round2);
266
- expect(result).toHaveLength(2);
267
- expect(result.map((d) => `${d.source_lens_id}:${d.title}`)).toEqual([
268
- "logic:A",
269
- "pragmatics:B",
270
- ]);
271
- });
272
- });
273
- // ---------------------------------------------------------------------------
274
- // buildDeliberationPlan
275
- // ---------------------------------------------------------------------------
276
- describe("buildDeliberationPlan", () => {
277
- it("emits N round-1 steps when rounds=1", () => {
278
- const plan = buildDeliberationPlan({ lenses: LENSES, deliberation_dir: "/tmp/d", rounds: 1 }, (lens) => `round1-prompt-for-${lens.lens_id}`);
279
- expect(plan.steps).toHaveLength(3);
280
- for (let i = 0; i < 3; i += 1) {
281
- expect(plan.steps[i].round).toBe(1);
282
- expect(plan.steps[i].lens_id).toBe(LENSES[i].lens_id);
283
- expect(plan.steps[i].prompt).toContain(LENSES[i].lens_id);
284
- }
285
- });
286
- it("emits 2N steps when rounds=2 with round1 before round2", () => {
287
- const plan = buildDeliberationPlan({ lenses: LENSES, deliberation_dir: "/tmp/d", rounds: 2 }, (lens) => `round1-${lens.lens_id}`, (lens) => `round2-${lens.lens_id}`);
288
- expect(plan.steps).toHaveLength(6);
289
- expect(plan.steps.slice(0, 3).every((s) => s.round === 1)).toBe(true);
290
- expect(plan.steps.slice(3).every((s) => s.round === 2)).toBe(true);
291
- });
292
- it("all_artifact_paths lists every step's target", () => {
293
- const plan = buildDeliberationPlan({ lenses: LENSES, deliberation_dir: "/tmp/d", rounds: 2 }, (lens) => `r1-${lens.lens_id}`, (lens) => `r2-${lens.lens_id}`);
294
- expect(plan.all_artifact_paths).toHaveLength(6);
295
- expect(plan.all_artifact_paths[0]).toContain("round1");
296
- expect(plan.all_artifact_paths[3]).toContain("round2");
297
- });
298
- });
299
- // ---------------------------------------------------------------------------
300
- // runLensAgentDeliberation
301
- // ---------------------------------------------------------------------------
302
- describe("runLensAgentDeliberation", () => {
303
- const VALID_ENV = {
304
- CLAUDECODE: "1",
305
- CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1",
306
- };
307
- it("throws DeliberationOptInError when opt-in not met", async () => {
308
- await expect(runLensAgentDeliberation({
309
- ontoConfig: {},
310
- input: { lenses: LENSES, deliberation_dir: "/tmp/d", rounds: 1 },
311
- env: {},
312
- })).rejects.toThrow(DeliberationOptInError);
313
- });
314
- it("reads primary lens outputs via injected reader and builds round-1 prompts", async () => {
315
- const primaries = new Map([
316
- ["logic", "LOGIC primary output body with findings."],
317
- ["pragmatics", "PRAG primary output body."],
318
- ["axiology", "AXIOLOGY primary output body."],
319
- ]);
320
- const plan = await runLensAgentDeliberation({
321
- ontoConfig: { lens_agent_teams_mode: true },
322
- input: { lenses: LENSES, deliberation_dir: "/tmp/d", rounds: 1 },
323
- env: VALID_ENV,
324
- readPrimary: async (p) => {
325
- const lensId = path.basename(p).replace(".md", "");
326
- return primaries.get(lensId) ?? "";
327
- },
328
- });
329
- expect(plan.steps).toHaveLength(3);
330
- // Logic's prompt should contain PRAG + AXIOLOGY bodies (as "other" blocks)
331
- // but should NOT include a "## Lens: logic" block — logic's own body
332
- // stays in its session memory. The own_output_summary header may
333
- // echo a truncated first paragraph (that's the name anchor) which
334
- // is intentional; we check the block-shaped inclusion only.
335
- const logicStep = plan.steps.find((s) => s.lens_id === "logic");
336
- expect(logicStep.prompt).toContain("PRAG primary output body");
337
- expect(logicStep.prompt).toContain("AXIOLOGY primary output body");
338
- expect(logicStep.prompt).not.toContain("## Lens: logic");
339
- });
340
- it("rounds=2 produces round-1 + round-2 steps (round-2 prompt has runtime placeholder)", async () => {
341
- const plan = await runLensAgentDeliberation({
342
- ontoConfig: { lens_agent_teams_mode: true },
343
- input: { lenses: LENSES, deliberation_dir: "/tmp/d", rounds: 2 },
344
- env: VALID_ENV,
345
- readPrimary: async () => "primary body",
346
- });
347
- expect(plan.steps).toHaveLength(6);
348
- const round2Step = plan.steps.find((s) => s.round === 2);
349
- expect(round2Step.prompt).toContain("coordinator-replace-at-runtime");
350
- });
351
- });
@@ -1,139 +0,0 @@
1
- /**
2
- * Topology → ReviewUnitExecutor mapping.
3
- *
4
- * # What this module is
5
- *
6
- * A thin function seat that maps a resolved `ExecutionTopology` (from
7
- * `src/core-runtime/review/execution-topology-resolver.ts`) to the concrete
8
- * `ReviewUnitExecutorConfig` (bin + argv) used by
9
- * `executeReviewPromptExecution` to spawn each lens / synthesize unit.
10
- *
11
- * # Why it exists
12
- *
13
- * Topology is the primary decision seat. This module maps topology metadata
14
- * to the executor binary for per-lens reasoning.
15
- *
16
- * The mapping is deterministic — it reads only `topology.lens_spawn_mechanism`:
17
- *
18
- * - `codex-subprocess` → codex-review-unit-executor.ts
19
- * - `claude-agent-tool` → coordinator-start handoff path
20
- * (no standalone executor binary; the
21
- * Claude coordinator subagent spawns
22
- * lens subagents via its own Agent tool)
23
- * - `claude-teamcreate-member` → controlled lens deliberation transport
24
- *
25
- * # How it relates
26
- *
27
- * - `resolveExecutionTopology()` decides WHICH topology applies.
28
- * - `mapTopologyToExecutorConfig()` (here) decides HOW to run each lens
29
- * under that topology at the TS subprocess level.
30
- * - The TeamCreate teamlead layer (`cc-teams-*` variants vs `cc-main-*`)
31
- * is an orthogonal coordinator-state-machine concern — same lens
32
- * executor applies within either teamlead pattern.
33
- */
34
- // ---------------------------------------------------------------------------
35
- // Direct executor support set
36
- // ---------------------------------------------------------------------------
37
- /**
38
- * Topology ids whose lens spawn path is wired to a direct executor.
39
- */
40
- export const EXECUTOR_MAPPING_SUPPORTED_TOPOLOGIES = new Set([
41
- "cc-main-agent-subagent",
42
- "cc-main-codex-subprocess",
43
- "codex-main-subprocess",
44
- "cc-teams-agent-subagent",
45
- "cc-teams-codex-subprocess",
46
- ]);
47
- /**
48
- * Mechanisms whose executor binary lives in the onto TS distribution.
49
- *
50
- * `claude-agent-tool` is NOT in this set — there is no standalone binary
51
- * for it; lens subagents are spawned by the Claude coordinator via its
52
- * own Agent tool invocation, not via `child_process.spawn` from TS.
53
- */
54
- const TS_EXECUTABLE_MECHANISMS = new Set([
55
- "codex-subprocess",
56
- ]);
57
- /**
58
- * True when the topology's lens spawn mechanism resolves to a TS-executable
59
- * binary (`codex-review-unit-executor.ts`), i.e. the caller can invoke
60
- * `mapTopologyToExecutorConfig()` and feed the result to
61
- * `executeReviewPromptExecution()`.
62
- *
63
- * For `claude-agent-tool` topologies the caller must route via the
64
- * coordinator-start handoff instead — no subprocess executor exists.
65
- */
66
- export function hasStandaloneLensExecutor(topology) {
67
- return TS_EXECUTABLE_MECHANISMS.has(topology.lens_spawn_mechanism);
68
- }
69
- // ---------------------------------------------------------------------------
70
- // Error types
71
- // ---------------------------------------------------------------------------
72
- export class TopologyExecutorMappingError extends Error {
73
- topologyId;
74
- reason;
75
- constructor(topologyId, reason) {
76
- super(`ExecutionTopology id="${topologyId}" 를 ReviewUnitExecutor 로 매핑할 수 없습니다: ${reason}`);
77
- this.topologyId = topologyId;
78
- this.reason = reason;
79
- this.name = "TopologyExecutorMappingError";
80
- }
81
- }
82
- // ---------------------------------------------------------------------------
83
- // Executor config builders (delegate to existing binary paths)
84
- // ---------------------------------------------------------------------------
85
- /**
86
- * Kept local (not imported from review-invoke) to avoid circular imports
87
- * — review-invoke.ts already imports from cli/run-review-prompt-execution,
88
- * and this module imports from cli/run-review-prompt-execution's type
89
- * exports. Direct dependency on review-invoke would close the cycle.
90
- */
91
- import path from "node:path";
92
- function codexExecutorConfig(ontoHome) {
93
- return {
94
- bin: "node",
95
- args: [path.join(ontoHome, "dist", "core-runtime", "cli", "codex-review-unit-executor.js")],
96
- };
97
- }
98
- // ---------------------------------------------------------------------------
99
- // Main mapping function
100
- // ---------------------------------------------------------------------------
101
- /**
102
- * Map a resolved topology to the review-unit executor that handles each
103
- * lens / synthesize invocation under that topology.
104
- *
105
- * Throws `TopologyExecutorMappingError` when:
106
- * - The topology id is not in `EXECUTOR_MAPPING_SUPPORTED_TOPOLOGIES` (caller should
107
- * not reach this function for unsupported ids; guard upstream).
108
- * - The lens_spawn_mechanism requires a TS-invisible dispatch path
109
- * (`claude-agent-tool`, `claude-teamcreate-member`) —
110
- * these are not subprocess executors; see `hasStandaloneLensExecutor`.
111
- *
112
- * This module's scope is mechanism→binary, not config→argv.
113
- */
114
- export function mapTopologyToExecutorConfig(topology, ontoHome) {
115
- if (!EXECUTOR_MAPPING_SUPPORTED_TOPOLOGIES.has(topology.id)) {
116
- throw new TopologyExecutorMappingError(topology.id, `Executor mapping 지원 set 밖. 지원되는 옵션: ${[...EXECUTOR_MAPPING_SUPPORTED_TOPOLOGIES].join(", ")}`);
117
- }
118
- switch (topology.lens_spawn_mechanism) {
119
- case "codex-subprocess":
120
- return codexExecutorConfig(ontoHome);
121
- case "claude-agent-tool":
122
- throw new TopologyExecutorMappingError(topology.id, "claude-agent-tool lens spawn 은 coordinator-start handoff 로 route 하세요 " +
123
- "(Claude coordinator subagent 가 Agent tool 로 lens subagent 를 spawn). " +
124
- "Subprocess executor 가 존재하지 않습니다.");
125
- case "claude-teamcreate-member":
126
- throw new TopologyExecutorMappingError(topology.id, "claude-teamcreate-member lens spawn 은 controlled lens deliberation transport 에서 다룹니다.");
127
- }
128
- }
129
- /** Drop `plan_trace` for handoff transmission. */
130
- export function toCoordinatorTopologyDescriptor(topology) {
131
- return {
132
- id: topology.id,
133
- teamlead_location: topology.teamlead_location,
134
- lens_spawn_mechanism: topology.lens_spawn_mechanism,
135
- max_concurrent_lenses: topology.max_concurrent_lenses,
136
- transport_rank: topology.transport_rank,
137
- deliberation_channel: topology.deliberation_channel,
138
- };
139
- }
@@ -1,173 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { TOPOLOGY_CATALOG, } from "../review/execution-topology-resolver.js";
3
- import { PR_B_SUPPORTED_TOPOLOGIES, TopologyExecutorMappingError, hasStandaloneLensExecutor, mapTopologyToExecutorConfig, toCoordinatorTopologyDescriptor, } from "./topology-executor-mapping.js";
4
- // ---------------------------------------------------------------------------
5
- // These tests assert the PR-B mapping invariants:
6
- //
7
- // (1) The PR-B supported set is exactly {2-1, 2-2, codex-B, 1-1, 1-2, 3-1} —
8
- // the 3 PR-A options plus the 3 TeamCreate-teamlead options whose lens
9
- // spawn mechanism reuses existing executor binaries.
10
- //
11
- // (2) Mapping is deterministic per lens_spawn_mechanism:
12
- // codex-subprocess → codex-review-unit-executor
13
- // litellm-http → inline-http-review-unit-executor
14
- // claude-agent-tool / claude-teamcreate-member / generic-subagent
15
- // → throw (no subprocess binary exists)
16
- //
17
- // (3) `hasStandaloneLensExecutor` agrees with the mapping's throw/return shape.
18
- //
19
- // (4) `toCoordinatorTopologyDescriptor` strips plan_trace but preserves all
20
- // other topology attributes — the handoff payload stays compact.
21
- // ---------------------------------------------------------------------------
22
- const FAKE_ONTO_HOME = "/tmp/fake-onto-home";
23
- function synthesize(id) {
24
- return {
25
- ...TOPOLOGY_CATALOG[id],
26
- plan_trace: [`synthesized for test: ${id}`],
27
- };
28
- }
29
- // ---------------------------------------------------------------------------
30
- // Support set
31
- // ---------------------------------------------------------------------------
32
- describe("PR_B_SUPPORTED_TOPOLOGIES", () => {
33
- it("contains exactly 6 topologies (PR-A 3 + PR-B 3)", () => {
34
- expect(PR_B_SUPPORTED_TOPOLOGIES.size).toBe(6);
35
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("cc-main-agent-subagent")).toBe(true);
36
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("cc-main-codex-subprocess")).toBe(true);
37
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("codex-main-subprocess")).toBe(true);
38
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("cc-teams-agent-subagent")).toBe(true);
39
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("cc-teams-codex-subprocess")).toBe(true);
40
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("cc-teams-litellm-sessions")).toBe(true);
41
- });
42
- it("does NOT include 1-0 deliberation (PR-D scope)", () => {
43
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("cc-teams-lens-agent-deliberation")).toBe(false);
44
- });
45
- it("does NOT include codex-nested (PR-C scope)", () => {
46
- expect(PR_B_SUPPORTED_TOPOLOGIES.has("codex-nested-subprocess")).toBe(false);
47
- });
48
- // P7 (2026-04-21): generic-* removed entirely from TopologyId enum.
49
- // Previous test "does NOT include generic-*" is no longer meaningful —
50
- // the type system now prevents generic-* from existing anywhere.
51
- });
52
- // ---------------------------------------------------------------------------
53
- // mapTopologyToExecutorConfig — codex mechanisms
54
- // ---------------------------------------------------------------------------
55
- describe("mapTopologyToExecutorConfig — codex-subprocess", () => {
56
- it("2-2 cc-main-codex-subprocess → codex executor", () => {
57
- const cfg = mapTopologyToExecutorConfig(synthesize("cc-main-codex-subprocess"), FAKE_ONTO_HOME);
58
- expect(cfg.bin).toBe("node");
59
- expect(cfg.args[0]).toContain("codex-review-unit-executor.js");
60
- expect(cfg.args[0]).toContain(FAKE_ONTO_HOME);
61
- });
62
- it("codex-B codex-main-subprocess → codex executor", () => {
63
- const cfg = mapTopologyToExecutorConfig(synthesize("codex-main-subprocess"), FAKE_ONTO_HOME);
64
- expect(cfg.args[0]).toContain("codex-review-unit-executor.js");
65
- });
66
- it("1-2 cc-teams-codex-subprocess → codex executor (same as 2-2 at TS level)", () => {
67
- const cfg = mapTopologyToExecutorConfig(synthesize("cc-teams-codex-subprocess"), FAKE_ONTO_HOME);
68
- expect(cfg.args[0]).toContain("codex-review-unit-executor.js");
69
- });
70
- });
71
- // ---------------------------------------------------------------------------
72
- // mapTopologyToExecutorConfig — litellm-http
73
- // ---------------------------------------------------------------------------
74
- describe("mapTopologyToExecutorConfig — litellm-http", () => {
75
- it("3-1 cc-teams-litellm-sessions → inline-http executor", () => {
76
- const cfg = mapTopologyToExecutorConfig(synthesize("cc-teams-litellm-sessions"), FAKE_ONTO_HOME);
77
- expect(cfg.bin).toBe("node");
78
- expect(cfg.args[0]).toContain("inline-http-review-unit-executor.js");
79
- });
80
- });
81
- // ---------------------------------------------------------------------------
82
- // mapTopologyToExecutorConfig — claude-agent-tool (no binary; throw)
83
- // ---------------------------------------------------------------------------
84
- describe("mapTopologyToExecutorConfig — claude-agent-tool", () => {
85
- it("2-1 cc-main-agent-subagent throws (route via coordinator-start handoff)", () => {
86
- expect(() => mapTopologyToExecutorConfig(synthesize("cc-main-agent-subagent"), FAKE_ONTO_HOME)).toThrow(TopologyExecutorMappingError);
87
- });
88
- it("1-1 cc-teams-agent-subagent throws (route via coordinator-start handoff)", () => {
89
- expect(() => mapTopologyToExecutorConfig(synthesize("cc-teams-agent-subagent"), FAKE_ONTO_HOME)).toThrow(TopologyExecutorMappingError);
90
- });
91
- it("claude-agent-tool throw mentions coordinator-start handoff path", () => {
92
- try {
93
- mapTopologyToExecutorConfig(synthesize("cc-main-agent-subagent"), FAKE_ONTO_HOME);
94
- expect.fail("expected throw");
95
- }
96
- catch (err) {
97
- expect(err).toBeInstanceOf(TopologyExecutorMappingError);
98
- expect(err.message).toContain("coordinator-start handoff");
99
- }
100
- });
101
- });
102
- // ---------------------------------------------------------------------------
103
- // mapTopologyToExecutorConfig — unsupported ids
104
- // ---------------------------------------------------------------------------
105
- describe("mapTopologyToExecutorConfig — unsupported", () => {
106
- it("1-0 cc-teams-lens-agent-deliberation throws (outside PR-B support set)", () => {
107
- expect(() => mapTopologyToExecutorConfig(synthesize("cc-teams-lens-agent-deliberation"), FAKE_ONTO_HOME)).toThrow(TopologyExecutorMappingError);
108
- });
109
- it("codex-A codex-nested-subprocess throws (outside PR-B; PR-C scope)", () => {
110
- expect(() => mapTopologyToExecutorConfig(synthesize("codex-nested-subprocess"), FAKE_ONTO_HOME)).toThrow(TopologyExecutorMappingError);
111
- });
112
- // P7 (2026-04-21): generic-* removed from TopologyId. Their "reserved"
113
- // guard is no longer needed — the type system prevents the values from
114
- // appearing at all.
115
- it("error message lists all PR-B supported ids for discoverability", () => {
116
- try {
117
- mapTopologyToExecutorConfig(synthesize("codex-nested-subprocess"), FAKE_ONTO_HOME);
118
- expect.fail("expected throw");
119
- }
120
- catch (err) {
121
- const msg = err.message;
122
- for (const id of PR_B_SUPPORTED_TOPOLOGIES) {
123
- expect(msg).toContain(id);
124
- }
125
- }
126
- });
127
- });
128
- // ---------------------------------------------------------------------------
129
- // hasStandaloneLensExecutor
130
- // ---------------------------------------------------------------------------
131
- describe("hasStandaloneLensExecutor", () => {
132
- it("codex-subprocess mechanisms have a TS executor binary", () => {
133
- expect(hasStandaloneLensExecutor(synthesize("cc-main-codex-subprocess"))).toBe(true);
134
- expect(hasStandaloneLensExecutor(synthesize("cc-teams-codex-subprocess"))).toBe(true);
135
- expect(hasStandaloneLensExecutor(synthesize("codex-main-subprocess"))).toBe(true);
136
- expect(hasStandaloneLensExecutor(synthesize("codex-nested-subprocess"))).toBe(true);
137
- });
138
- it("litellm-http mechanism has a TS executor binary", () => {
139
- expect(hasStandaloneLensExecutor(synthesize("cc-teams-litellm-sessions"))).toBe(true);
140
- });
141
- it("claude-agent-tool mechanisms do NOT have a TS executor binary", () => {
142
- expect(hasStandaloneLensExecutor(synthesize("cc-main-agent-subagent"))).toBe(false);
143
- expect(hasStandaloneLensExecutor(synthesize("cc-teams-agent-subagent"))).toBe(false);
144
- });
145
- it("claude-teamcreate-member (1-0 deliberation) does NOT have a TS executor binary", () => {
146
- expect(hasStandaloneLensExecutor(synthesize("cc-teams-lens-agent-deliberation"))).toBe(false);
147
- });
148
- // P7 (2026-04-21): generic-subagent mechanism tests removed along with
149
- // generic-* TopologyId values.
150
- });
151
- // ---------------------------------------------------------------------------
152
- // toCoordinatorTopologyDescriptor
153
- // ---------------------------------------------------------------------------
154
- describe("toCoordinatorTopologyDescriptor", () => {
155
- it("preserves all topology attributes except plan_trace", () => {
156
- const topology = synthesize("cc-teams-codex-subprocess");
157
- const descriptor = toCoordinatorTopologyDescriptor(topology);
158
- expect(descriptor.id).toBe(topology.id);
159
- expect(descriptor.teamlead_location).toBe(topology.teamlead_location);
160
- expect(descriptor.lens_spawn_mechanism).toBe(topology.lens_spawn_mechanism);
161
- expect(descriptor.max_concurrent_lenses).toBe(topology.max_concurrent_lenses);
162
- expect(descriptor.transport_rank).toBe(topology.transport_rank);
163
- expect(descriptor.deliberation_channel).toBe(topology.deliberation_channel);
164
- expect(Object.keys(descriptor)).not.toContain("plan_trace");
165
- });
166
- it("is JSON-serializable (handoff transport requirement)", () => {
167
- const topology = synthesize("cc-teams-lens-agent-deliberation");
168
- const descriptor = toCoordinatorTopologyDescriptor(topology);
169
- const json = JSON.stringify(descriptor);
170
- const parsed = JSON.parse(json);
171
- expect(parsed).toEqual(descriptor);
172
- });
173
- });