onto-mcp 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/.onto/processes/reconstruct/actionable-ontology-seed-recomposition-design.md +447 -0
  2. package/.onto/processes/reconstruct/foundry-style-ontology-seed-contract.md +934 -0
  3. package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +303 -725
  4. package/.onto/processes/reconstruct/reconstruct-contract-registry.yaml +1645 -0
  5. package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +26 -22
  6. package/.onto/processes/reconstruct/source-profile-contract.md +49 -23
  7. package/.onto/processes/reconstruct/source-profiles/code.md +6 -3
  8. package/.onto/processes/reconstruct/source-profiles/database.md +5 -2
  9. package/.onto/processes/reconstruct/source-profiles/document.md +5 -2
  10. package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +5 -4
  11. package/.onto/processes/review/review-execution-ux-contract.md +40 -0
  12. package/.onto/processes/shared/pipeline-execution-ledger-contract.md +26 -10
  13. package/.onto/processes/shared/target-material-kind-contract.md +29 -16
  14. package/AGENTS.md +6 -4
  15. package/README.md +135 -76
  16. package/dist/cli.js +8 -8
  17. package/dist/core-api/reconstruct-api.js +117 -31
  18. package/dist/core-api/review-api.js +47 -0
  19. package/dist/core-runtime/cli/codex-review-unit-executor.js +39 -2
  20. package/dist/core-runtime/cli/complete-review-session.js +2 -2
  21. package/dist/core-runtime/cli/mock-review-unit-executor.js +1 -1
  22. package/dist/core-runtime/cli/review-invoke.js +9 -9
  23. package/dist/core-runtime/cli/run-review-prompt-execution.js +39 -5
  24. package/dist/core-runtime/cli/spawn-watcher.js +266 -47
  25. package/dist/core-runtime/cli/start-review-session.js +3 -3
  26. package/dist/core-runtime/llm/llm-caller.js +11 -0
  27. package/dist/core-runtime/llm/llm-tool-loop.js +2 -0
  28. package/dist/core-runtime/observability/runtime-stream-observation.js +118 -0
  29. package/dist/core-runtime/onboard/cli-host.js +149 -0
  30. package/dist/core-runtime/onboard/host-target.js +22 -0
  31. package/dist/core-runtime/onboard/json-config-host.js +122 -0
  32. package/dist/core-runtime/onboard/path-scan.js +26 -0
  33. package/dist/core-runtime/onboard/prompt.js +51 -0
  34. package/dist/core-runtime/onboard/register.js +207 -0
  35. package/dist/core-runtime/onboard/types.js +27 -0
  36. package/dist/core-runtime/reconstruct/actionable-seed-validation.js +1777 -0
  37. package/dist/core-runtime/reconstruct/artifact-types.js +10 -4
  38. package/dist/core-runtime/reconstruct/contract-registry.js +623 -0
  39. package/dist/core-runtime/reconstruct/domain-id.js +10 -0
  40. package/dist/core-runtime/reconstruct/governing-snapshot.js +716 -0
  41. package/dist/core-runtime/reconstruct/material-profile-validation.js +191 -0
  42. package/dist/core-runtime/reconstruct/materialize-preparation.js +49 -11
  43. package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +269 -79
  44. package/dist/core-runtime/reconstruct/post-seed-validation.js +1194 -51
  45. package/dist/core-runtime/reconstruct/record.js +104 -20
  46. package/dist/core-runtime/reconstruct/run.js +2107 -413
  47. package/dist/core-runtime/reconstruct/seed-claim-projections.js +268 -0
  48. package/dist/core-runtime/reconstruct/source-profiles.js +93 -4
  49. package/dist/core-runtime/reconstruct/terminal-validation.js +807 -0
  50. package/dist/core-runtime/review/review-invocation-runner.js +4 -4
  51. package/dist/mcp/server.js +110 -38
  52. package/dist/mcp/tool-schemas.js +20 -6
  53. package/package.json +8 -17
  54. package/scripts/onto-review-watch.sh +486 -0
  55. package/scripts/onto-runtime-watch.sh +122 -0
  56. package/scripts/postinstall-hint.js +22 -0
  57. package/.onto/processes/reconstruct/top-level-concept-discovery-contract.md +0 -387
  58. package/dist/core-runtime/cli/bootstrap-review-binding.js +0 -186
  59. package/dist/core-runtime/cli/codex-nested-dispatch.test.js +0 -390
  60. package/dist/core-runtime/cli/codex-nested-teamlead-executor.test.js +0 -335
  61. package/dist/core-runtime/cli/coordinator-helpers.js +0 -583
  62. package/dist/core-runtime/cli/coordinator-state-machine-deliberation.test.js +0 -167
  63. package/dist/core-runtime/cli/coordinator-state-machine.js +0 -794
  64. package/dist/core-runtime/cli/e2e-codex-multi-agent-fixes.test.js +0 -615
  65. package/dist/core-runtime/cli/e2e-start-review-session.test.js +0 -312
  66. package/dist/core-runtime/cli/health.js +0 -44
  67. package/dist/core-runtime/cli/inline-http-review-unit-executor.test.js +0 -567
  68. package/dist/core-runtime/cli/materialize-review-execution-preparation.js +0 -104
  69. package/dist/core-runtime/cli/migrate-session-roots.js +0 -118
  70. package/dist/core-runtime/cli/repo-layout-migration-replace.smoke.test.js +0 -106
  71. package/dist/core-runtime/cli/review-invoke-auto-resolution.test.js +0 -268
  72. package/dist/core-runtime/cli/review-invoke-coordinator-topology.test.js +0 -136
  73. package/dist/core-runtime/cli/review-invoke-resolver-caching.test.js +0 -201
  74. package/dist/core-runtime/cli/review-invoke-topology-dispatch.test.js +0 -192
  75. package/dist/core-runtime/cli/session-root-guard.js +0 -168
  76. package/dist/core-runtime/cli/spawn-watcher.test.js +0 -457
  77. package/dist/core-runtime/cli/strip-wrapping-code-fence.test.js +0 -79
  78. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.js +0 -412
  79. package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.test.js +0 -351
  80. package/dist/core-runtime/cli/topology-executor-mapping.js +0 -139
  81. package/dist/core-runtime/cli/topology-executor-mapping.test.js +0 -173
  82. package/dist/core-runtime/cli/write-review-interpretation.js +0 -81
  83. package/dist/core-runtime/config/onto-config-cli.js +0 -278
  84. package/dist/core-runtime/config/onto-config-key-path.js +0 -288
  85. package/dist/core-runtime/config/onto-config-key-path.test.js +0 -195
  86. package/dist/core-runtime/config/onto-config-preview.js +0 -108
  87. package/dist/core-runtime/config/onto-config-preview.test.js +0 -132
  88. package/dist/core-runtime/discovery/config-chain.js +0 -118
  89. package/dist/core-runtime/discovery/config-chain.test.js +0 -103
  90. package/dist/core-runtime/discovery/config-profile.js +0 -199
  91. package/dist/core-runtime/discovery/config-profile.test.js +0 -233
  92. package/dist/core-runtime/discovery/host-detection.test.js +0 -186
  93. package/dist/core-runtime/discovery/installation-paths.test.js +0 -65
  94. package/dist/core-runtime/discovery/lens-registry.test.js +0 -81
  95. package/dist/core-runtime/discovery/path-normalization.test.js +0 -22
  96. package/dist/core-runtime/discovery/plugin-path.js +0 -72
  97. package/dist/core-runtime/discovery/plugin-path.test.js +0 -95
  98. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.js +0 -344
  99. package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.test.js +0 -915
  100. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.js +0 -564
  101. package/dist/core-runtime/evolve/adapters/code-product/compile/compile.test.js +0 -708
  102. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.js +0 -165
  103. package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.test.js +0 -227
  104. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.js +0 -59
  105. package/dist/core-runtime/evolve/adapters/code-product/validators/validate.test.js +0 -205
  106. package/dist/core-runtime/evolve/adapters/methodology/adapter.js +0 -16
  107. package/dist/core-runtime/evolve/adapters/methodology/adapter.test.js +0 -9
  108. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.js +0 -298
  109. package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.test.js +0 -70
  110. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.js +0 -46
  111. package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.test.js +0 -73
  112. package/dist/core-runtime/evolve/adapters/registry.js +0 -47
  113. package/dist/core-runtime/evolve/adapters/registry.test.js +0 -67
  114. package/dist/core-runtime/evolve/cli.js +0 -256
  115. package/dist/core-runtime/evolve/commands/align.js +0 -194
  116. package/dist/core-runtime/evolve/commands/align.test.js +0 -82
  117. package/dist/core-runtime/evolve/commands/apply.js +0 -161
  118. package/dist/core-runtime/evolve/commands/apply.test.js +0 -138
  119. package/dist/core-runtime/evolve/commands/close.js +0 -39
  120. package/dist/core-runtime/evolve/commands/close.test.js +0 -99
  121. package/dist/core-runtime/evolve/commands/defer.js +0 -40
  122. package/dist/core-runtime/evolve/commands/defer.test.js +0 -134
  123. package/dist/core-runtime/evolve/commands/draft.js +0 -323
  124. package/dist/core-runtime/evolve/commands/draft.test.js +0 -178
  125. package/dist/core-runtime/evolve/commands/e2e-evolve-full-cycle.test.js +0 -208
  126. package/dist/core-runtime/evolve/commands/error-messages.js +0 -125
  127. package/dist/core-runtime/evolve/commands/error-messages.test.js +0 -167
  128. package/dist/core-runtime/evolve/commands/propose-align.js +0 -222
  129. package/dist/core-runtime/evolve/commands/propose-align.test.js +0 -136
  130. package/dist/core-runtime/evolve/commands/reconstruct.js +0 -330
  131. package/dist/core-runtime/evolve/commands/reconstruct.test.js +0 -278
  132. package/dist/core-runtime/evolve/commands/shared.js +0 -22
  133. package/dist/core-runtime/evolve/commands/stale-check.js +0 -103
  134. package/dist/core-runtime/evolve/commands/stale-check.test.js +0 -84
  135. package/dist/core-runtime/evolve/commands/start.js +0 -887
  136. package/dist/core-runtime/evolve/commands/start.test.js +0 -396
  137. package/dist/core-runtime/evolve/config/project-config.js +0 -99
  138. package/dist/core-runtime/evolve/config/project-config.test.js +0 -170
  139. package/dist/core-runtime/evolve/renderers/align-packet.js +0 -280
  140. package/dist/core-runtime/evolve/renderers/align-packet.test.js +0 -332
  141. package/dist/core-runtime/evolve/renderers/draft-packet.js +0 -303
  142. package/dist/core-runtime/evolve/renderers/draft-packet.test.js +0 -377
  143. package/dist/core-runtime/evolve/renderers/format.js +0 -5
  144. package/dist/core-runtime/evolve/renderers/scope-md.js +0 -237
  145. package/dist/core-runtime/evolve/renderers/scope-md.test.js +0 -306
  146. package/dist/core-runtime/govern/cli.js +0 -369
  147. package/dist/core-runtime/govern/cli.test.js +0 -314
  148. package/dist/core-runtime/govern/drift-engine.js +0 -103
  149. package/dist/core-runtime/govern/drift-engine.test.js +0 -319
  150. package/dist/core-runtime/govern/promote-principle.js +0 -206
  151. package/dist/core-runtime/govern/promote-principle.test.js +0 -368
  152. package/dist/core-runtime/govern/queue.js +0 -81
  153. package/dist/core-runtime/govern/types.js +0 -16
  154. package/dist/core-runtime/install/cli.js +0 -530
  155. package/dist/core-runtime/install/detect.js +0 -128
  156. package/dist/core-runtime/install/detect.test.js +0 -155
  157. package/dist/core-runtime/install/gitignore-update.js +0 -74
  158. package/dist/core-runtime/install/gitignore-update.test.js +0 -64
  159. package/dist/core-runtime/install/install-integration.test.js +0 -373
  160. package/dist/core-runtime/install/prompts.js +0 -389
  161. package/dist/core-runtime/install/prompts.test.js +0 -293
  162. package/dist/core-runtime/install/types.js +0 -26
  163. package/dist/core-runtime/install/validation.js +0 -295
  164. package/dist/core-runtime/install/validation.test.js +0 -313
  165. package/dist/core-runtime/install/writer.js +0 -254
  166. package/dist/core-runtime/install/writer.test.js +0 -218
  167. package/dist/core-runtime/learning/extractor.js +0 -461
  168. package/dist/core-runtime/learning/feedback.js +0 -179
  169. package/dist/core-runtime/learning/health-report.js +0 -165
  170. package/dist/core-runtime/learning/health-report.test.js +0 -169
  171. package/dist/core-runtime/learning/loader.js +0 -388
  172. package/dist/core-runtime/learning/loader.test.js +0 -102
  173. package/dist/core-runtime/learning/promote/apply-state.js +0 -240
  174. package/dist/core-runtime/learning/promote/audit-obligation.js +0 -195
  175. package/dist/core-runtime/learning/promote/collector.js +0 -432
  176. package/dist/core-runtime/learning/promote/degraded-state.js +0 -125
  177. package/dist/core-runtime/learning/promote/domain-doc-proposer.js +0 -166
  178. package/dist/core-runtime/learning/promote/e2e-promote.test.js +0 -6385
  179. package/dist/core-runtime/learning/promote/health-snapshot.js +0 -150
  180. package/dist/core-runtime/learning/promote/insight-reclassifier.js +0 -544
  181. package/dist/core-runtime/learning/promote/judgment-auditor.js +0 -517
  182. package/dist/core-runtime/learning/promote/panel-reviewer.js +0 -1158
  183. package/dist/core-runtime/learning/promote/promote-executor.js +0 -1675
  184. package/dist/core-runtime/learning/promote/promoter.js +0 -307
  185. package/dist/core-runtime/learning/promote/retirement.js +0 -122
  186. package/dist/core-runtime/learning/promote/types.js +0 -23
  187. package/dist/core-runtime/learning/prompt-sections.js +0 -51
  188. package/dist/core-runtime/learning/shared/artifact-registry-init.js +0 -45
  189. package/dist/core-runtime/learning/shared/artifact-registry.js +0 -254
  190. package/dist/core-runtime/learning/shared/audit-obligation-kernel.js +0 -73
  191. package/dist/core-runtime/learning/shared/audit-state.js +0 -99
  192. package/dist/core-runtime/learning/shared/duplicate-check.js +0 -28
  193. package/dist/core-runtime/learning/shared/llm-caller.js +0 -831
  194. package/dist/core-runtime/learning/shared/llm-caller.test.js +0 -601
  195. package/dist/core-runtime/learning/shared/llm-tool-loop.js +0 -393
  196. package/dist/core-runtime/learning/shared/mode.js +0 -25
  197. package/dist/core-runtime/learning/shared/paths.js +0 -84
  198. package/dist/core-runtime/learning/shared/paths.test.js +0 -79
  199. package/dist/core-runtime/learning/shared/patterns.js +0 -37
  200. package/dist/core-runtime/learning/shared/recoverability.js +0 -355
  201. package/dist/core-runtime/learning/shared/recovery-context.js +0 -374
  202. package/dist/core-runtime/learning/shared/scope.js +0 -1
  203. package/dist/core-runtime/learning/shared/semantic-classifier.js +0 -94
  204. package/dist/core-runtime/learning/shared/specs/apply-execution-state-spec.js +0 -42
  205. package/dist/core-runtime/learning/shared/specs/audit-state-spec.js +0 -37
  206. package/dist/core-runtime/learning/shared/specs/backup-metadata-spec.js +0 -39
  207. package/dist/core-runtime/learning/shared/specs/emergency-log-spec.js +0 -41
  208. package/dist/core-runtime/learning/shared/specs/layout-version-spec.js +0 -38
  209. package/dist/core-runtime/learning/shared/specs/promote-decisions-spec.js +0 -43
  210. package/dist/core-runtime/learning/shared/specs/promote-report-spec.js +0 -113
  211. package/dist/core-runtime/learning/shared/specs/prune-log-spec.js +0 -36
  212. package/dist/core-runtime/learning/shared/specs/recovery-resolution-spec.js +0 -48
  213. package/dist/core-runtime/learning/shared/specs/restore-manifest-spec.js +0 -43
  214. package/dist/core-runtime/learning/shared/specs/spec-helpers.js +0 -64
  215. package/dist/core-runtime/learning/usage-tracker.js +0 -190
  216. package/dist/core-runtime/learning/usage-tracker.test.js +0 -176
  217. package/dist/core-runtime/onboard/detect-review-axes.js +0 -122
  218. package/dist/core-runtime/onboard/detect-review-axes.test.js +0 -127
  219. package/dist/core-runtime/onboard/write-review-block.js +0 -188
  220. package/dist/core-runtime/onboard/write-review-block.test.js +0 -240
  221. package/dist/core-runtime/readers/brownfield-builder.js +0 -150
  222. package/dist/core-runtime/readers/brownfield-builder.test.js +0 -136
  223. package/dist/core-runtime/readers/code-chunk-collector.js +0 -53
  224. package/dist/core-runtime/readers/code-chunk-collector.test.js +0 -136
  225. package/dist/core-runtime/readers/file-utils.js +0 -240
  226. package/dist/core-runtime/readers/file-utils.test.js +0 -146
  227. package/dist/core-runtime/readers/lexicon-citation-check.js +0 -93
  228. package/dist/core-runtime/readers/lexicon-citation-check.test.js +0 -77
  229. package/dist/core-runtime/readers/mcp-figma.js +0 -30
  230. package/dist/core-runtime/readers/mcp-figma.test.js +0 -82
  231. package/dist/core-runtime/readers/mcp-generic.js +0 -31
  232. package/dist/core-runtime/readers/mcp-generic.test.js +0 -76
  233. package/dist/core-runtime/readers/ontology-index.js +0 -148
  234. package/dist/core-runtime/readers/ontology-index.test.js +0 -245
  235. package/dist/core-runtime/readers/ontology-query.js +0 -168
  236. package/dist/core-runtime/readers/ontology-query.test.js +0 -311
  237. package/dist/core-runtime/readers/ontology-resolve.js +0 -48
  238. package/dist/core-runtime/readers/ontology-resolve.test.js +0 -48
  239. package/dist/core-runtime/readers/patterns/index.js +0 -7
  240. package/dist/core-runtime/readers/review-log.js +0 -213
  241. package/dist/core-runtime/readers/review-log.test.js +0 -313
  242. package/dist/core-runtime/readers/scan-local.js +0 -102
  243. package/dist/core-runtime/readers/scan-local.test.js +0 -102
  244. package/dist/core-runtime/readers/scan-tarball.js +0 -121
  245. package/dist/core-runtime/readers/scan-tarball.test.js +0 -283
  246. package/dist/core-runtime/readers/scan-vault.js +0 -34
  247. package/dist/core-runtime/readers/scan-vault.test.js +0 -81
  248. package/dist/core-runtime/readers/types.js +0 -42
  249. package/dist/core-runtime/readers/types.test.js +0 -94
  250. package/dist/core-runtime/readers/viewpoint-collectors.js +0 -229
  251. package/dist/core-runtime/reconstruct/seed-candidate-validation.js +0 -385
  252. package/dist/core-runtime/review/citation-audit.test.js +0 -165
  253. package/dist/core-runtime/review/execution-plan-resolver.js +0 -247
  254. package/dist/core-runtime/review/execution-plan-resolver.test.js +0 -243
  255. package/dist/core-runtime/review/execution-topology-resolver-axis-first.test.js +0 -246
  256. package/dist/core-runtime/review/execution-topology-resolver.js +0 -401
  257. package/dist/core-runtime/review/execution-topology-resolver.test.js +0 -315
  258. package/dist/core-runtime/review/inline-context-embedder.test.js +0 -154
  259. package/dist/core-runtime/review/legacy-mode-policy.js +0 -88
  260. package/dist/core-runtime/review/materializers-effort-persist.test.js +0 -79
  261. package/dist/core-runtime/review/ontology-path-classifier.js +0 -179
  262. package/dist/core-runtime/review/ontology-path-classifier.test.js +0 -216
  263. package/dist/core-runtime/review/packet-boundary-policy.test.js +0 -107
  264. package/dist/core-runtime/review/participating-lens-paths.test.js +0 -73
  265. package/dist/core-runtime/review/review-config-legacy-translate.js +0 -244
  266. package/dist/core-runtime/review/review-config-legacy-translate.test.js +0 -161
  267. package/dist/core-runtime/review/review-config-validator.js +0 -289
  268. package/dist/core-runtime/review/review-config-validator.test.js +0 -236
  269. package/dist/core-runtime/review/shape-pipeline-audit.test.js +0 -311
  270. package/dist/core-runtime/review/shape-to-topology-id.js +0 -117
  271. package/dist/core-runtime/review/shape-to-topology-id.test.js +0 -132
  272. package/dist/core-runtime/review/topology-shape-derivation.js +0 -155
  273. package/dist/core-runtime/review/topology-shape-derivation.test.js +0 -195
  274. package/dist/core-runtime/scope-runtime/constants.js +0 -12
  275. package/dist/core-runtime/scope-runtime/constraint-pool.js +0 -166
  276. package/dist/core-runtime/scope-runtime/constraint-pool.test.js +0 -674
  277. package/dist/core-runtime/scope-runtime/domain-validation-log.js +0 -135
  278. package/dist/core-runtime/scope-runtime/domain-validation-log.test.js +0 -156
  279. package/dist/core-runtime/scope-runtime/eval-persistence.js +0 -65
  280. package/dist/core-runtime/scope-runtime/eval-persistence.test.js +0 -84
  281. package/dist/core-runtime/scope-runtime/event-pipeline.js +0 -64
  282. package/dist/core-runtime/scope-runtime/event-pipeline.test.js +0 -450
  283. package/dist/core-runtime/scope-runtime/event-store.js +0 -39
  284. package/dist/core-runtime/scope-runtime/event-store.test.js +0 -95
  285. package/dist/core-runtime/scope-runtime/gate-guard.js +0 -348
  286. package/dist/core-runtime/scope-runtime/gate-guard.test.js +0 -1047
  287. package/dist/core-runtime/scope-runtime/hash.js +0 -4
  288. package/dist/core-runtime/scope-runtime/hash.test.js +0 -33
  289. package/dist/core-runtime/scope-runtime/id.js +0 -4
  290. package/dist/core-runtime/scope-runtime/id.test.js +0 -17
  291. package/dist/core-runtime/scope-runtime/reducer.js +0 -297
  292. package/dist/core-runtime/scope-runtime/reducer.test.js +0 -759
  293. package/dist/core-runtime/scope-runtime/scope-manager.js +0 -161
  294. package/dist/core-runtime/scope-runtime/state-machine.js +0 -309
  295. package/dist/core-runtime/scope-runtime/state-machine.test.js +0 -704
  296. package/dist/core-runtime/scope-runtime/types.js +0 -116
  297. package/dist/core-runtime/scope-runtime/types.test.js +0 -69
  298. package/dist/core-runtime/translate/render-for-user.js +0 -169
  299. package/dist/core-runtime/translate/render-for-user.test.js +0 -122
  300. package/dist/providers/capability-contract.js +0 -1
@@ -1,26 +0,0 @@
1
- /**
2
- * Shared types for `onto install` — the interactive + non-interactive
3
- * first-run setup command.
4
- *
5
- * Design reference: spec v3 laid out in the install command design
6
- * discussion (2026-04-21 session). Key decisions codified here:
7
- *
8
- * 1. Two provider channels: review (for 9-lens execution) and learn
9
- * (for background tasks — learn/govern/promote). They may share
10
- * a provider or be configured separately.
11
- *
12
- * 2. `main-native` is a valid ReviewProvider but NOT a valid
13
- * LearnProvider. The background ladder in llm-caller.ts does not
14
- * support host main-model delegation (fail-fast on missing
15
- * credentials). The type-level exclusion prevents accidentally
16
- * writing a learn config that would always fail at runtime.
17
- *
18
- * 3. API keys are never captured into typed decision shape — they
19
- * flow via environment (env var or `.env` file) only. This keeps
20
- * secrets out of logs, serialized state, and command history.
21
- *
22
- * 4. Profile scope is atomic (per config-profile.ts adoption rule) —
23
- * either global owns the full profile set or project does. The
24
- * scope choice is what determines where every file writes.
25
- */
26
- export {};
@@ -1,295 +0,0 @@
1
- /**
2
- * Live provider validation for `onto install`.
3
- *
4
- * Given a freshly resolved `{ decisions, secrets, detection }`, this
5
- * module sends a minimal reachability probe to each non-main-native
6
- * provider the user selected. A failed probe produces a clear
7
- * `ValidationCheck` result that the orchestrator surfaces alongside
8
- * instructions (re-run with `--skip-validation` or fix the credential).
9
- *
10
- * # What "ping" means per provider
11
- *
12
- * - anthropic GET https://api.anthropic.com/v1/models with the
13
- * key — models list is free and confirms the key.
14
- * - openai GET https://api.openai.com/v1/models with the key
15
- * — same rationale, zero token cost.
16
- * - litellm GET {base_url}/models (OpenAI-compatible). The
17
- * `/models` suffix is the OpenAI-compat standard;
18
- * LiteLLM proxy and every listed local runtime
19
- * (Ollama, LM Studio, vLLM, MLX) respond to it.
20
- * - codex Local check only — binary present + auth.json
21
- * present. No network call; the codex CLI handles
22
- * its own OAuth dance.
23
- * - main-native Skipped — there's nothing to probe; the runtime
24
- * is the host session itself.
25
- *
26
- * # Why fetch directly instead of SDK
27
- *
28
- * The `@anthropic-ai/sdk` and `openai` SDKs carry non-trivial startup
29
- * cost and change their response shapes between majors. A raw HTTP
30
- * GET is dependency-free, gives a crisp HTTP status code (401 vs 200
31
- * vs 5xx), and doesn't couple install's validation surface to SDK
32
- * version drift. LiteLLM is already OpenAI-compatible HTTP, so the
33
- * same pattern works there.
34
- *
35
- * # Testability
36
- *
37
- * All network and filesystem access flows through a `PingDependencies`
38
- * struct. Tests inject a stub `fetch` that returns the desired
39
- * `Response` shape, and stub codex-presence booleans directly.
40
- */
41
- // ---------------------------------------------------------------------------
42
- // Shape guard
43
- // ---------------------------------------------------------------------------
44
- /**
45
- * Runtime sanity check on the `InstallDecisions` shape.
46
- *
47
- * TypeScript already enforces most of this at compile time. The one
48
- * thing that still benefits from a runtime check is the
49
- * learn-provider exclusion (it's excluded at the type level via the
50
- * `LearnProvider` union but a consumer could still construct
51
- * decisions outside the normal flow).
52
- */
53
- export function checkDecisionShape(decisions) {
54
- const checks = [];
55
- if (decisions.learnProvider === "main-native") {
56
- checks.push({
57
- name: "decisions",
58
- passed: false,
59
- message: "learn provider는 main-native를 지원하지 않습니다. " +
60
- "background ladder(llm-caller.ts)에서 main-native는 ladder의 일부가 아닙니다.",
61
- });
62
- }
63
- return checks;
64
- }
65
- // ---------------------------------------------------------------------------
66
- // Fetch helpers
67
- // ---------------------------------------------------------------------------
68
- async function fetchWithTimeout(fetchFn, url, init, timeoutMs) {
69
- const controller = new AbortController();
70
- const timer = setTimeout(() => controller.abort(), timeoutMs);
71
- try {
72
- return await fetchFn(url, { ...init, signal: controller.signal });
73
- }
74
- finally {
75
- clearTimeout(timer);
76
- }
77
- }
78
- function resolveFetch(deps) {
79
- return deps.fetch ?? globalThis.fetch;
80
- }
81
- // ---------------------------------------------------------------------------
82
- // Per-provider pings
83
- // ---------------------------------------------------------------------------
84
- export async function pingAnthropic(apiKey, deps = {}) {
85
- const fetchFn = resolveFetch(deps);
86
- const timeoutMs = deps.timeoutMs ?? 5000;
87
- try {
88
- const res = await fetchWithTimeout(fetchFn, "https://api.anthropic.com/v1/models", {
89
- method: "GET",
90
- headers: {
91
- "x-api-key": apiKey,
92
- "anthropic-version": "2023-06-01",
93
- },
94
- }, timeoutMs);
95
- if (res.status >= 200 && res.status < 300) {
96
- return { name: "anthropic", passed: true };
97
- }
98
- if (res.status === 401 || res.status === 403) {
99
- return {
100
- name: "anthropic",
101
- passed: false,
102
- message: "인증 실패 (API key 거부). 키 값을 확인하세요.",
103
- };
104
- }
105
- return {
106
- name: "anthropic",
107
- passed: false,
108
- message: `api.anthropic.com 응답 HTTP ${res.status}`,
109
- };
110
- }
111
- catch (err) {
112
- return {
113
- name: "anthropic",
114
- passed: false,
115
- message: `네트워크 오류: ${err instanceof Error ? err.message : String(err)}`,
116
- };
117
- }
118
- }
119
- export async function pingOpenai(apiKey, deps = {}) {
120
- const fetchFn = resolveFetch(deps);
121
- const timeoutMs = deps.timeoutMs ?? 5000;
122
- try {
123
- const res = await fetchWithTimeout(fetchFn, "https://api.openai.com/v1/models", {
124
- method: "GET",
125
- headers: { Authorization: `Bearer ${apiKey}` },
126
- }, timeoutMs);
127
- if (res.status >= 200 && res.status < 300) {
128
- return { name: "openai", passed: true };
129
- }
130
- if (res.status === 401 || res.status === 403) {
131
- return {
132
- name: "openai",
133
- passed: false,
134
- message: "인증 실패 (API key 거부). 키 값을 확인하세요.",
135
- };
136
- }
137
- return {
138
- name: "openai",
139
- passed: false,
140
- message: `api.openai.com 응답 HTTP ${res.status}`,
141
- };
142
- }
143
- catch (err) {
144
- return {
145
- name: "openai",
146
- passed: false,
147
- message: `네트워크 오류: ${err instanceof Error ? err.message : String(err)}`,
148
- };
149
- }
150
- }
151
- export async function pingLitellm(baseUrl, apiKey, deps = {}) {
152
- const fetchFn = resolveFetch(deps);
153
- const timeoutMs = deps.timeoutMs ?? 5000;
154
- const url = baseUrl.replace(/\/+$/, "") + "/models";
155
- try {
156
- const headers = {};
157
- if (apiKey)
158
- headers.Authorization = `Bearer ${apiKey}`;
159
- const res = await fetchWithTimeout(fetchFn, url, { method: "GET", headers }, timeoutMs);
160
- if (res.status >= 200 && res.status < 300) {
161
- return { name: "litellm", passed: true };
162
- }
163
- if (res.status === 401 || res.status === 403) {
164
- return {
165
- name: "litellm",
166
- passed: false,
167
- message: "인증 실패. 엔드포인트가 key를 요구합니다 — LITELLM_API_KEY를 설정하세요.",
168
- };
169
- }
170
- return {
171
- name: "litellm",
172
- passed: false,
173
- message: `${url} 응답 HTTP ${res.status}`,
174
- };
175
- }
176
- catch (err) {
177
- return {
178
- name: "litellm",
179
- passed: false,
180
- message: `연결 실패 (${url}): ${err instanceof Error ? err.message : String(err)}`,
181
- };
182
- }
183
- }
184
- export function verifyCodex(detection, deps = {}) {
185
- const binaryPresent = deps.codexBinaryPresent
186
- ? deps.codexBinaryPresent()
187
- : detection.hasCodexBinary;
188
- const authPresent = deps.codexAuthPresent
189
- ? deps.codexAuthPresent()
190
- : detection.hasCodexAuth;
191
- if (!binaryPresent) {
192
- return {
193
- name: "codex",
194
- passed: false,
195
- message: "codex binary가 PATH에 없습니다.",
196
- };
197
- }
198
- if (!authPresent) {
199
- return {
200
- name: "codex",
201
- passed: false,
202
- message: "~/.codex/auth.json 없음. `codex login` 실행 필요.",
203
- };
204
- }
205
- return { name: "codex", passed: true };
206
- }
207
- /**
208
- * Validate the full install outcome.
209
- *
210
- * Dedupes the review + learn providers (when same, only pings once),
211
- * reads credentials from `secrets` with `process.env` as the fallback
212
- * (so a user who set ANTHROPIC_API_KEY in the shell gets validated
213
- * without install having to re-capture the key).
214
- *
215
- * Never throws — all errors surface as failed `ValidationCheck`
216
- * entries so the orchestrator can render a complete summary.
217
- */
218
- export async function validateInstall(args) {
219
- const { decisions, secrets, detection, deps = {} } = args;
220
- const checks = [];
221
- checks.push(...checkDecisionShape(decisions));
222
- const providers = new Set();
223
- providers.add(decisions.reviewProvider);
224
- providers.add(decisions.learnProvider);
225
- for (const provider of providers) {
226
- switch (provider) {
227
- case "main-native":
228
- // Nothing to probe — host session is the runtime.
229
- break;
230
- case "anthropic": {
231
- const apiKey = secrets.anthropicApiKey ?? process.env.ANTHROPIC_API_KEY;
232
- if (!apiKey) {
233
- checks.push({
234
- name: "anthropic",
235
- passed: false,
236
- message: "ANTHROPIC_API_KEY를 찾을 수 없습니다.",
237
- });
238
- }
239
- else {
240
- checks.push(await pingAnthropic(apiKey, deps));
241
- }
242
- break;
243
- }
244
- case "openai": {
245
- const apiKey = secrets.openaiApiKey ?? process.env.OPENAI_API_KEY;
246
- if (!apiKey) {
247
- checks.push({
248
- name: "openai",
249
- passed: false,
250
- message: "OPENAI_API_KEY를 찾을 수 없습니다.",
251
- });
252
- }
253
- else {
254
- checks.push(await pingOpenai(apiKey, deps));
255
- }
256
- break;
257
- }
258
- case "litellm": {
259
- const baseUrl = secrets.litellmBaseUrl ?? process.env.LITELLM_BASE_URL;
260
- const apiKey = secrets.litellmApiKey ?? process.env.LITELLM_API_KEY;
261
- if (!baseUrl) {
262
- checks.push({
263
- name: "litellm",
264
- passed: false,
265
- message: "LITELLM_BASE_URL을 찾을 수 없습니다.",
266
- });
267
- }
268
- else {
269
- checks.push(await pingLitellm(baseUrl, apiKey, deps));
270
- }
271
- break;
272
- }
273
- case "codex":
274
- checks.push(verifyCodex(detection, deps));
275
- break;
276
- }
277
- }
278
- return {
279
- ok: checks.every((c) => c.passed),
280
- checks,
281
- };
282
- }
283
- /**
284
- * Pretty-print a validation result as text. One line per check,
285
- * `✓` / `✗` prefix, and indented error message on the same line.
286
- */
287
- export function formatValidationResult(result) {
288
- const lines = [];
289
- for (const check of result.checks) {
290
- const mark = check.passed ? "✓" : "✗";
291
- const suffix = check.message ? ` — ${check.message}` : "";
292
- lines.push(` ${mark} ${check.name}${suffix}`);
293
- }
294
- return lines.join("\n");
295
- }
@@ -1,313 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { formatValidationResult, pingAnthropic, pingLitellm, pingOpenai, validateInstall, verifyCodex, } from "./validation.js";
3
- // ---------------------------------------------------------------------------
4
- // Helpers
5
- // ---------------------------------------------------------------------------
6
- const BLANK_DETECTION = {
7
- existingGlobalConfig: false,
8
- existingProjectConfig: false,
9
- hasAnthropicKey: false,
10
- hasOpenAiKey: false,
11
- hasLitellmBaseUrl: false,
12
- hasCodexBinary: false,
13
- hasCodexAuth: false,
14
- hostIsClaudeCode: false,
15
- };
16
- /** Build a stub fetch that returns a fixed Response for every call. */
17
- function stubFetchReturning(status, body = {}) {
18
- return (async () => new Response(JSON.stringify(body), {
19
- status,
20
- headers: { "content-type": "application/json" },
21
- }));
22
- }
23
- /** Build a stub fetch that throws — network error scenario. */
24
- function stubFetchThrowing(message) {
25
- return (async () => {
26
- throw new Error(message);
27
- });
28
- }
29
- /** Capture the URL + headers of the first request. */
30
- function spyFetch() {
31
- const calls = [];
32
- const fetchFn = async (url, init) => {
33
- const headers = {};
34
- const raw = init?.headers;
35
- if (raw && !Array.isArray(raw) && !(raw instanceof Headers)) {
36
- Object.assign(headers, raw);
37
- }
38
- calls.push({ url: String(url), headers });
39
- return new Response("{}", { status: 200 });
40
- };
41
- return { fetch: fetchFn, calls };
42
- }
43
- // ---------------------------------------------------------------------------
44
- // pingAnthropic
45
- // ---------------------------------------------------------------------------
46
- describe("pingAnthropic", () => {
47
- it("returns passed=true on 200", async () => {
48
- const check = await pingAnthropic("sk-ant-test", {
49
- fetch: stubFetchReturning(200),
50
- });
51
- expect(check).toEqual({ name: "anthropic", passed: true });
52
- });
53
- it("reports auth failure on 401", async () => {
54
- const check = await pingAnthropic("sk-ant-bad", {
55
- fetch: stubFetchReturning(401),
56
- });
57
- expect(check.passed).toBe(false);
58
- expect(check.message).toContain("인증 실패");
59
- });
60
- it("reports generic HTTP failure on 5xx", async () => {
61
- const check = await pingAnthropic("sk-ant-test", {
62
- fetch: stubFetchReturning(500),
63
- });
64
- expect(check.passed).toBe(false);
65
- expect(check.message).toContain("500");
66
- });
67
- it("reports network error on fetch throw", async () => {
68
- const check = await pingAnthropic("sk-ant-test", {
69
- fetch: stubFetchThrowing("ECONNREFUSED"),
70
- });
71
- expect(check.passed).toBe(false);
72
- expect(check.message).toContain("네트워크");
73
- expect(check.message).toContain("ECONNREFUSED");
74
- });
75
- it("sends x-api-key header and anthropic-version", async () => {
76
- const spy = spyFetch();
77
- await pingAnthropic("sk-ant-xyz", { fetch: spy.fetch });
78
- expect(spy.calls[0]?.url).toBe("https://api.anthropic.com/v1/models");
79
- expect(spy.calls[0]?.headers["x-api-key"]).toBe("sk-ant-xyz");
80
- expect(spy.calls[0]?.headers["anthropic-version"]).toBeTruthy();
81
- });
82
- });
83
- // ---------------------------------------------------------------------------
84
- // pingOpenai
85
- // ---------------------------------------------------------------------------
86
- describe("pingOpenai", () => {
87
- it("returns passed=true on 200", async () => {
88
- const check = await pingOpenai("sk-test", {
89
- fetch: stubFetchReturning(200),
90
- });
91
- expect(check.passed).toBe(true);
92
- });
93
- it("sends Authorization: Bearer header", async () => {
94
- const spy = spyFetch();
95
- await pingOpenai("sk-test", { fetch: spy.fetch });
96
- expect(spy.calls[0]?.url).toBe("https://api.openai.com/v1/models");
97
- expect(spy.calls[0]?.headers.Authorization).toBe("Bearer sk-test");
98
- });
99
- it("reports 401 as auth failure", async () => {
100
- const check = await pingOpenai("bad", {
101
- fetch: stubFetchReturning(401),
102
- });
103
- expect(check.passed).toBe(false);
104
- expect(check.message).toContain("인증 실패");
105
- });
106
- });
107
- // ---------------------------------------------------------------------------
108
- // pingLitellm
109
- // ---------------------------------------------------------------------------
110
- describe("pingLitellm", () => {
111
- it("appends /models to the base URL", async () => {
112
- const spy = spyFetch();
113
- await pingLitellm("http://localhost:4000/v1", undefined, {
114
- fetch: spy.fetch,
115
- });
116
- expect(spy.calls[0]?.url).toBe("http://localhost:4000/v1/models");
117
- });
118
- it("strips trailing slashes before appending /models", async () => {
119
- const spy = spyFetch();
120
- await pingLitellm("http://localhost:4000/v1/", undefined, {
121
- fetch: spy.fetch,
122
- });
123
- expect(spy.calls[0]?.url).toBe("http://localhost:4000/v1/models");
124
- });
125
- it("omits Authorization when no apiKey given", async () => {
126
- const spy = spyFetch();
127
- await pingLitellm("http://localhost:11434/v1", undefined, {
128
- fetch: spy.fetch,
129
- });
130
- expect(spy.calls[0]?.headers.Authorization).toBeUndefined();
131
- });
132
- it("sends Bearer token when apiKey provided", async () => {
133
- const spy = spyFetch();
134
- await pingLitellm("https://litellm.example.com/v1", "sk-proxy", {
135
- fetch: spy.fetch,
136
- });
137
- expect(spy.calls[0]?.headers.Authorization).toBe("Bearer sk-proxy");
138
- });
139
- it("reports 401 with guidance to set LITELLM_API_KEY", async () => {
140
- const check = await pingLitellm("http://localhost:4000/v1", undefined, {
141
- fetch: stubFetchReturning(401),
142
- });
143
- expect(check.passed).toBe(false);
144
- expect(check.message).toContain("LITELLM_API_KEY");
145
- });
146
- it("reports network failure on ECONNREFUSED", async () => {
147
- const check = await pingLitellm("http://localhost:4000/v1", undefined, {
148
- fetch: stubFetchThrowing("fetch failed"),
149
- });
150
- expect(check.passed).toBe(false);
151
- expect(check.message).toContain("연결 실패");
152
- });
153
- });
154
- // ---------------------------------------------------------------------------
155
- // verifyCodex (filesystem-level, no network)
156
- // ---------------------------------------------------------------------------
157
- describe("verifyCodex", () => {
158
- it("passes when both binary and auth present in detection", () => {
159
- const check = verifyCodex({
160
- ...BLANK_DETECTION,
161
- hasCodexBinary: true,
162
- hasCodexAuth: true,
163
- });
164
- expect(check).toEqual({ name: "codex", passed: true });
165
- });
166
- it("fails with binary missing message", () => {
167
- const check = verifyCodex(BLANK_DETECTION);
168
- expect(check.passed).toBe(false);
169
- expect(check.message).toContain("binary");
170
- });
171
- it("fails with auth missing message when binary present", () => {
172
- const check = verifyCodex({ ...BLANK_DETECTION, hasCodexBinary: true });
173
- expect(check.passed).toBe(false);
174
- expect(check.message).toContain("codex login");
175
- });
176
- it("dependency overrides win over detection values", () => {
177
- const check = verifyCodex(BLANK_DETECTION, {
178
- codexBinaryPresent: () => true,
179
- codexAuthPresent: () => true,
180
- });
181
- expect(check.passed).toBe(true);
182
- });
183
- });
184
- // ---------------------------------------------------------------------------
185
- // validateInstall orchestrator
186
- // ---------------------------------------------------------------------------
187
- const ANTHROPIC_DECISIONS = {
188
- profileScope: "project",
189
- reviewProvider: "anthropic",
190
- learnProvider: "anthropic",
191
- outputLanguage: "ko",
192
- };
193
- describe("validateInstall", () => {
194
- it("skips network probe for main-native review + anthropic learn", async () => {
195
- const spy = spyFetch();
196
- const result = await validateInstall({
197
- decisions: {
198
- ...ANTHROPIC_DECISIONS,
199
- reviewProvider: "main-native",
200
- },
201
- secrets: { anthropicApiKey: "sk-ant-test" },
202
- detection: BLANK_DETECTION,
203
- deps: { fetch: spy.fetch },
204
- });
205
- // Only anthropic is probed — main-native contributes no network call.
206
- expect(spy.calls.length).toBe(1);
207
- expect(spy.calls[0]?.url).toContain("api.anthropic.com");
208
- expect(result.ok).toBe(true);
209
- });
210
- it("dedupes when review and learn providers match", async () => {
211
- const spy = spyFetch();
212
- await validateInstall({
213
- decisions: ANTHROPIC_DECISIONS,
214
- secrets: { anthropicApiKey: "sk-ant-test" },
215
- detection: BLANK_DETECTION,
216
- deps: { fetch: spy.fetch },
217
- });
218
- expect(spy.calls.length).toBe(1);
219
- });
220
- it("probes both providers when they differ", async () => {
221
- const spy = spyFetch();
222
- await validateInstall({
223
- decisions: {
224
- ...ANTHROPIC_DECISIONS,
225
- reviewProvider: "anthropic",
226
- learnProvider: "openai",
227
- },
228
- secrets: { anthropicApiKey: "sk-ant", openaiApiKey: "sk-oai" },
229
- detection: BLANK_DETECTION,
230
- deps: { fetch: spy.fetch },
231
- });
232
- const urls = spy.calls.map((c) => c.url);
233
- expect(urls.some((u) => u.includes("api.anthropic.com"))).toBe(true);
234
- expect(urls.some((u) => u.includes("api.openai.com"))).toBe(true);
235
- });
236
- it("fails when credential is missing entirely", async () => {
237
- const result = await validateInstall({
238
- decisions: ANTHROPIC_DECISIONS,
239
- secrets: {},
240
- detection: BLANK_DETECTION,
241
- deps: { fetch: stubFetchReturning(200) },
242
- });
243
- expect(result.ok).toBe(false);
244
- expect(result.checks.some((c) => c.message?.includes("ANTHROPIC_API_KEY"))).toBe(true);
245
- });
246
- it("falls back to process.env when secrets are empty", async () => {
247
- const prev = process.env.ANTHROPIC_API_KEY;
248
- process.env.ANTHROPIC_API_KEY = "from-env";
249
- try {
250
- const spy = spyFetch();
251
- const result = await validateInstall({
252
- decisions: ANTHROPIC_DECISIONS,
253
- secrets: {},
254
- detection: BLANK_DETECTION,
255
- deps: { fetch: spy.fetch },
256
- });
257
- expect(result.ok).toBe(true);
258
- expect(spy.calls[0]?.headers["x-api-key"]).toBe("from-env");
259
- }
260
- finally {
261
- if (prev === undefined)
262
- delete process.env.ANTHROPIC_API_KEY;
263
- else
264
- process.env.ANTHROPIC_API_KEY = prev;
265
- }
266
- });
267
- it("surfaces codex check in mixed-provider setup", async () => {
268
- const result = await validateInstall({
269
- decisions: {
270
- ...ANTHROPIC_DECISIONS,
271
- reviewProvider: "codex",
272
- learnProvider: "anthropic",
273
- },
274
- secrets: { anthropicApiKey: "sk-ant" },
275
- detection: BLANK_DETECTION,
276
- deps: { fetch: stubFetchReturning(200) },
277
- });
278
- expect(result.checks.some((c) => c.name === "codex")).toBe(true);
279
- expect(result.ok).toBe(false); // codex check fails on blank detection
280
- });
281
- it("catches learn-provider=main-native shape violation", async () => {
282
- const result = await validateInstall({
283
- decisions: {
284
- ...ANTHROPIC_DECISIONS,
285
- reviewProvider: "main-native",
286
- // @ts-expect-error — intentional runtime-only invalid shape
287
- learnProvider: "main-native",
288
- },
289
- secrets: {},
290
- detection: BLANK_DETECTION,
291
- deps: { fetch: stubFetchReturning(200) },
292
- });
293
- expect(result.ok).toBe(false);
294
- expect(result.checks.some((c) => c.message?.includes("main-native"))).toBe(true);
295
- });
296
- });
297
- // ---------------------------------------------------------------------------
298
- // formatValidationResult
299
- // ---------------------------------------------------------------------------
300
- describe("formatValidationResult", () => {
301
- it("marks passed checks with ✓ and failed with ✗", () => {
302
- const text = formatValidationResult({
303
- ok: false,
304
- checks: [
305
- { name: "anthropic", passed: true },
306
- { name: "openai", passed: false, message: "oops" },
307
- ],
308
- });
309
- expect(text).toContain("✓ anthropic");
310
- expect(text).toContain("✗ openai");
311
- expect(text).toContain("oops");
312
- });
313
- });