@the-open-engine/zeroshot 6.38.1 → 6.39.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 (383) hide show
  1. package/README.md +6 -0
  2. package/cli/event-copy.js +8 -7
  3. package/cli/event-copy.ts +12 -0
  4. package/cli/index.js +67 -48
  5. package/cli/json-export.js +61 -64
  6. package/cli/json-export.ts +112 -0
  7. package/cli/message-formatter-utils.js +68 -56
  8. package/cli/message-formatter-utils.ts +121 -0
  9. package/cli/message-formatters-normal.js +124 -259
  10. package/cli/message-formatters-normal.ts +250 -0
  11. package/cli/message-formatters-watch.js +81 -84
  12. package/cli/message-formatters-watch.ts +189 -0
  13. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  14. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  15. package/lib/cluster/generated/protocol.d.cts +8 -0
  16. package/lib/cluster/generated/protocol.d.mts +8 -0
  17. package/lib/cluster/generated/protocol.d.ts +8 -0
  18. package/lib/clusters-registry.d.ts +23 -0
  19. package/lib/clusters-registry.js +17 -29
  20. package/lib/completion.d.ts +12 -0
  21. package/lib/completion.js +84 -94
  22. package/lib/compose-utils.d.ts +32 -0
  23. package/lib/compose-utils.js +57 -72
  24. package/lib/detached-startup.d.ts +84 -0
  25. package/lib/detached-startup.js +232 -302
  26. package/lib/docker-config.d.ts +43 -0
  27. package/lib/docker-config.js +150 -325
  28. package/lib/docker-env-auth.d.ts +17 -0
  29. package/lib/docker-env-auth.js +75 -0
  30. package/lib/git-remote-utils.d.ts +48 -0
  31. package/lib/git-remote-utils.js +147 -213
  32. package/lib/id-detector.d.ts +15 -0
  33. package/lib/id-detector.js +37 -41
  34. package/lib/path-check.d.ts +30 -0
  35. package/lib/path-check.js +42 -45
  36. package/lib/process-liveness.d.ts +16 -0
  37. package/lib/process-liveness.js +19 -12
  38. package/lib/provider-credential-path.d.ts +16 -0
  39. package/lib/provider-credential-path.js +31 -29
  40. package/lib/provider-defaults.d.ts +30 -0
  41. package/lib/provider-defaults.js +47 -42
  42. package/lib/provider-detection.d.ts +11 -0
  43. package/lib/provider-detection.js +91 -54
  44. package/lib/provider-names.d.ts +38 -0
  45. package/lib/provider-names.js +56 -64
  46. package/lib/repo-settings.d.ts +28 -0
  47. package/lib/repo-settings.js +83 -59
  48. package/lib/run-mode.d.ts +21 -0
  49. package/lib/run-mode.js +21 -20
  50. package/lib/run-plan.d.ts +28 -0
  51. package/lib/run-plan.js +17 -16
  52. package/lib/settings/claude-auth.d.ts +35 -0
  53. package/lib/settings/claude-auth.js +30 -47
  54. package/lib/settings-defaults.d.ts +20 -0
  55. package/lib/settings-defaults.js +149 -0
  56. package/lib/settings-error.d.ts +7 -0
  57. package/lib/settings-error.js +8 -0
  58. package/lib/settings-issue-providers.d.ts +10 -0
  59. package/lib/settings-issue-providers.js +12 -0
  60. package/lib/settings-models.d.ts +22 -0
  61. package/lib/settings-models.js +93 -0
  62. package/lib/settings-storage.d.ts +23 -0
  63. package/lib/settings-storage.js +205 -0
  64. package/lib/settings-validation.d.ts +7 -0
  65. package/lib/settings-validation.js +182 -0
  66. package/lib/settings.d.ts +29 -0
  67. package/lib/settings.js +41 -736
  68. package/lib/setup-apply-types.d.ts +66 -0
  69. package/lib/setup-apply-types.js +2 -0
  70. package/lib/setup-apply.d.ts +39 -0
  71. package/lib/setup-apply.js +267 -264
  72. package/lib/setup-journal.d.ts +41 -0
  73. package/lib/setup-journal.js +119 -76
  74. package/lib/setup-plan-types.d.ts +102 -0
  75. package/lib/setup-plan-types.js +2 -0
  76. package/lib/setup-plan.d.ts +30 -0
  77. package/lib/setup-plan.js +300 -324
  78. package/lib/setup-undo.d.ts +44 -0
  79. package/lib/setup-undo.js +61 -74
  80. package/lib/start-cluster-config.d.ts +26 -0
  81. package/lib/start-cluster-config.js +56 -0
  82. package/lib/start-cluster-environment.d.ts +41 -0
  83. package/lib/start-cluster-environment.js +134 -0
  84. package/lib/start-cluster-run-options.d.ts +54 -0
  85. package/lib/start-cluster-run-options.js +148 -0
  86. package/lib/start-cluster.d.ts +64 -0
  87. package/lib/start-cluster.js +98 -454
  88. package/lib/stream-json-parser.d.ts +17 -0
  89. package/lib/stream-json-parser.js +51 -52
  90. package/npm-shrinkwrap.json +6 -8
  91. package/package.json +14 -8
  92. package/scripts/postinstall.js +27 -0
  93. package/scripts/rust-distribution.js +36 -45
  94. package/src/agent/agent-command-proofs-context.js +35 -45
  95. package/src/agent/agent-command-proofs-context.ts +87 -0
  96. package/src/agent/agent-config-settings.js +19 -0
  97. package/src/agent/agent-config-settings.ts +41 -0
  98. package/src/agent/agent-config.js +122 -231
  99. package/src/agent/agent-config.ts +285 -0
  100. package/src/agent/agent-context-builder.js +38 -273
  101. package/src/agent/agent-context-builder.ts +51 -0
  102. package/src/agent/agent-context-environment-sections.js +105 -0
  103. package/src/agent/agent-context-environment-sections.ts +134 -0
  104. package/src/agent/agent-context-packs.js +165 -0
  105. package/src/agent/agent-context-packs.ts +296 -0
  106. package/src/agent/agent-context-prompt-sections.js +100 -0
  107. package/src/agent/agent-context-prompt-sections.ts +148 -0
  108. package/src/agent/agent-context-sections.js +25 -334
  109. package/src/agent/agent-context-sections.ts +36 -0
  110. package/src/agent/agent-context-sources.js +96 -149
  111. package/src/agent/agent-context-sources.ts +253 -0
  112. package/src/agent/agent-context-types.js +2 -0
  113. package/src/agent/agent-context-types.ts +132 -0
  114. package/src/agent/agent-context-validation-sections.js +73 -0
  115. package/src/agent/agent-context-validation-sections.ts +129 -0
  116. package/src/agent/agent-input-injector.js +99 -118
  117. package/src/agent/agent-input-injector.ts +195 -0
  118. package/src/agent/agent-liveness-poll.js +74 -78
  119. package/src/agent/agent-liveness-poll.ts +163 -0
  120. package/src/agent/agent-quality-gate-schema.js +77 -86
  121. package/src/agent/agent-quality-gate-schema.ts +135 -0
  122. package/src/agent/agent-quality-gates-context.js +44 -50
  123. package/src/agent/agent-quality-gates-context.ts +91 -0
  124. package/src/agent/agent-stuck-detector.js +171 -239
  125. package/src/agent/agent-stuck-detector.ts +288 -0
  126. package/src/agent/agent-trigger-evaluator.js +29 -46
  127. package/src/agent/agent-trigger-evaluator.ts +98 -0
  128. package/src/agent/context-metrics.js +110 -141
  129. package/src/agent/context-metrics.ts +261 -0
  130. package/src/agent/context-pack-builder.js +72 -358
  131. package/src/agent/context-pack-builder.ts +105 -0
  132. package/src/agent/context-pack-core.js +70 -0
  133. package/src/agent/context-pack-core.ts +96 -0
  134. package/src/agent/context-pack-selection.js +119 -0
  135. package/src/agent/context-pack-selection.ts +187 -0
  136. package/src/agent/context-pack-truncation.js +139 -0
  137. package/src/agent/context-pack-truncation.ts +208 -0
  138. package/src/agent/context-pack-types.js +2 -0
  139. package/src/agent/context-pack-types.ts +98 -0
  140. package/src/agent/context-replay-policy.js +30 -39
  141. package/src/agent/context-replay-policy.ts +71 -0
  142. package/src/agent/critical-agent-policy.js +6 -10
  143. package/src/agent/critical-agent-policy.ts +20 -0
  144. package/src/agent/guidance-queue.js +74 -87
  145. package/src/agent/guidance-queue.ts +166 -0
  146. package/src/agent/output-extraction-error-detail.js +45 -0
  147. package/src/agent/output-extraction-error-detail.ts +49 -0
  148. package/src/agent/output-extraction-failures.js +125 -0
  149. package/src/agent/output-extraction-failures.ts +149 -0
  150. package/src/agent/output-extraction-json.js +234 -0
  151. package/src/agent/output-extraction-json.ts +235 -0
  152. package/src/agent/output-extraction-pi.js +124 -0
  153. package/src/agent/output-extraction-pi.ts +137 -0
  154. package/src/agent/output-extraction-types.js +2 -0
  155. package/src/agent/output-extraction-types.ts +49 -0
  156. package/src/agent/output-extraction.js +17 -617
  157. package/src/agent/output-extraction.ts +30 -0
  158. package/src/agent/output-reformatter-errors.js +83 -0
  159. package/src/agent/output-reformatter-errors.ts +106 -0
  160. package/src/agent/output-reformatter-types.js +2 -0
  161. package/src/agent/output-reformatter-types.ts +86 -0
  162. package/src/agent/output-reformatter.js +140 -185
  163. package/src/agent/output-reformatter.ts +238 -0
  164. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  165. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  166. package/src/agent/pi-terminal-lifecycle.js +186 -206
  167. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  168. package/src/agent/provider-control-plane.js +22 -21
  169. package/src/agent/provider-control-plane.ts +52 -0
  170. package/src/agent/provider-terminal-failure-types.js +2 -0
  171. package/src/agent/provider-terminal-failure-types.ts +60 -0
  172. package/src/agent/provider-terminal-failure.js +194 -191
  173. package/src/agent/provider-terminal-failure.ts +262 -0
  174. package/src/agent/rate-limit-backoff.js +31 -74
  175. package/src/agent/rate-limit-backoff.ts +71 -0
  176. package/src/agent/schema-utils.js +85 -125
  177. package/src/agent/schema-utils.ts +148 -0
  178. package/src/agent/structured-output-error.js +34 -33
  179. package/src/agent/structured-output-error.ts +105 -0
  180. package/src/agent/validation-platform.js +27 -27
  181. package/src/agent/validation-platform.ts +49 -0
  182. package/src/agents/git-pusher-template.js +17 -34
  183. package/src/attach/attach-client.js +232 -405
  184. package/src/attach/attach-client.ts +300 -0
  185. package/src/attach/attach-server-cleanup.js +43 -0
  186. package/src/attach/attach-server-cleanup.ts +39 -0
  187. package/src/attach/attach-server-clients.js +117 -0
  188. package/src/attach/attach-server-clients.ts +122 -0
  189. package/src/attach/attach-server-events.js +38 -0
  190. package/src/attach/attach-server-events.ts +36 -0
  191. package/src/attach/attach-server-pty.js +45 -0
  192. package/src/attach/attach-server-pty.ts +64 -0
  193. package/src/attach/attach-server-runtime.js +73 -0
  194. package/src/attach/attach-server-runtime.ts +62 -0
  195. package/src/attach/attach-server-socket.js +28 -0
  196. package/src/attach/attach-server-socket.ts +23 -0
  197. package/src/attach/attach-server-types.js +2 -0
  198. package/src/attach/attach-server-types.ts +82 -0
  199. package/src/attach/attach-server.js +106 -523
  200. package/src/attach/attach-server.ts +158 -0
  201. package/src/attach/index.js +18 -35
  202. package/src/attach/index.ts +18 -0
  203. package/src/attach/protocol.js +95 -184
  204. package/src/attach/protocol.ts +181 -0
  205. package/src/attach/ring-buffer.js +76 -102
  206. package/src/attach/ring-buffer.ts +109 -0
  207. package/src/attach/send-input.js +64 -75
  208. package/src/attach/send-input.ts +94 -0
  209. package/src/attach/socket-discovery.js +164 -218
  210. package/src/attach/socket-discovery.ts +230 -0
  211. package/src/attach/socket-paths.js +42 -61
  212. package/src/attach/socket-paths.ts +81 -0
  213. package/src/claude-credentials.js +51 -54
  214. package/src/claude-credentials.ts +89 -0
  215. package/src/cluster/generated/protocol-schema.ts +1 -1
  216. package/src/cluster/generated/protocol.ts +2 -1
  217. package/src/command-proofs.js +110 -141
  218. package/src/command-proofs.ts +216 -0
  219. package/src/config-router.js +81 -73
  220. package/src/config-router.ts +131 -0
  221. package/src/copy-containment.js +191 -0
  222. package/src/copy-containment.ts +259 -0
  223. package/src/copy-worker.js +53 -30
  224. package/src/copy-worker.ts +88 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/isolation-manager.js +59 -20
  232. package/src/ledger-sequence.js +45 -48
  233. package/src/ledger-sequence.ts +63 -0
  234. package/src/legacy-lib/clusters-registry.ts +40 -0
  235. package/src/legacy-lib/completion.ts +148 -0
  236. package/src/legacy-lib/compose-utils.ts +102 -0
  237. package/src/legacy-lib/detached-startup.ts +451 -0
  238. package/src/legacy-lib/docker-config.ts +282 -0
  239. package/src/legacy-lib/docker-env-auth.ts +116 -0
  240. package/src/legacy-lib/git-remote-utils.ts +244 -0
  241. package/src/legacy-lib/id-detector.ts +57 -0
  242. package/src/legacy-lib/js-yaml.d.ts +3 -0
  243. package/src/legacy-lib/omelette.d.ts +15 -0
  244. package/src/legacy-lib/path-check.ts +89 -0
  245. package/src/legacy-lib/process-liveness.ts +36 -0
  246. package/src/legacy-lib/provider-credential-path.ts +57 -0
  247. package/src/legacy-lib/provider-defaults.ts +114 -0
  248. package/src/legacy-lib/provider-detection.ts +67 -0
  249. package/src/legacy-lib/provider-names.ts +126 -0
  250. package/src/legacy-lib/repo-settings.ts +88 -0
  251. package/src/legacy-lib/run-mode.ts +58 -0
  252. package/src/legacy-lib/run-plan.ts +49 -0
  253. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  254. package/src/legacy-lib/settings-defaults.ts +212 -0
  255. package/src/legacy-lib/settings-error.ts +8 -0
  256. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  257. package/src/legacy-lib/settings-models.ts +124 -0
  258. package/src/legacy-lib/settings-storage.ts +277 -0
  259. package/src/legacy-lib/settings-validation.ts +220 -0
  260. package/src/legacy-lib/settings.ts +87 -0
  261. package/src/legacy-lib/setup-apply-types.ts +70 -0
  262. package/src/legacy-lib/setup-apply.ts +456 -0
  263. package/src/legacy-lib/setup-journal.ts +185 -0
  264. package/src/legacy-lib/setup-plan-types.ts +96 -0
  265. package/src/legacy-lib/setup-plan.ts +500 -0
  266. package/src/legacy-lib/setup-undo.ts +142 -0
  267. package/src/legacy-lib/start-cluster-config.ts +124 -0
  268. package/src/legacy-lib/start-cluster-environment.ts +166 -0
  269. package/src/legacy-lib/start-cluster-run-options.ts +281 -0
  270. package/src/legacy-lib/start-cluster.ts +237 -0
  271. package/src/legacy-lib/stream-json-parser.ts +88 -0
  272. package/src/message-buffer.js +55 -71
  273. package/src/message-buffer.ts +107 -0
  274. package/src/message-bus-bridge.js +92 -133
  275. package/src/message-bus-bridge.ts +149 -0
  276. package/src/name-generator-shared.js +220 -0
  277. package/src/name-generator-shared.ts +231 -0
  278. package/src/name-generator.js +8 -217
  279. package/src/name-generator.ts +27 -0
  280. package/src/omp-blob-root.js +83 -64
  281. package/src/omp-blob-root.ts +116 -0
  282. package/src/omp-config-overlay.js +65 -38
  283. package/src/omp-config-overlay.ts +110 -0
  284. package/src/omp-execution-fingerprint.js +38 -43
  285. package/src/omp-execution-fingerprint.ts +92 -0
  286. package/src/omp-session-limits.js +10 -15
  287. package/src/omp-session-limits.ts +53 -0
  288. package/src/omp-session-partition.js +2 -2
  289. package/src/omp-session-verifier.js +1 -1
  290. package/src/orchestrator.js +32 -7
  291. package/src/pr-body-template.js +71 -0
  292. package/src/providers/anthropic/index.js +3 -1
  293. package/src/providers/anthropic/index.ts +13 -0
  294. package/src/providers/capabilities.js +19 -27
  295. package/src/providers/capabilities.ts +44 -0
  296. package/src/providers/google/index.js +3 -1
  297. package/src/providers/google/index.ts +13 -0
  298. package/src/providers/openai/index.js +3 -1
  299. package/src/providers/openai/index.ts +13 -0
  300. package/src/providers/opencode/index.js +3 -1
  301. package/src/providers/opencode/index.ts +13 -0
  302. package/src/quality-gates.js +67 -127
  303. package/src/quality-gates.ts +149 -0
  304. package/src/repo-settings-access.js +40 -0
  305. package/src/repo-settings-access.ts +64 -0
  306. package/src/schemas/sub-cluster.js +127 -183
  307. package/src/schemas/sub-cluster.ts +238 -0
  308. package/src/state-snapshot-normalization.js +224 -0
  309. package/src/state-snapshot-normalization.ts +222 -0
  310. package/src/state-snapshot.js +192 -359
  311. package/src/state-snapshot.ts +291 -0
  312. package/src/state-snapshotter.js +118 -130
  313. package/src/state-snapshotter.ts +167 -0
  314. package/src/sub-cluster-wrapper.js +4 -13
  315. package/src/task-run-model-args.js +87 -124
  316. package/src/task-run-model-args.ts +204 -0
  317. package/src/task-runner.js +5 -25
  318. package/src/task-runner.ts +28 -0
  319. package/src/task-startup-error.js +73 -58
  320. package/src/task-startup-error.ts +126 -0
  321. package/src/template-validation/consensus-gate-contracts.js +2 -0
  322. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  323. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  324. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  325. package/src/template-validation/consensus-gate-stage.js +34 -0
  326. package/src/template-validation/consensus-gate-stage.ts +56 -0
  327. package/src/template-validation/random-topology-contracts.js +2 -0
  328. package/src/template-validation/random-topology-contracts.ts +54 -0
  329. package/src/template-validation/random-topology-dispatch.js +25 -0
  330. package/src/template-validation/random-topology-dispatch.ts +33 -0
  331. package/src/template-validation/random-topology-message-loop.js +53 -0
  332. package/src/template-validation/random-topology-message-loop.ts +73 -0
  333. package/src/template-validation/random-topology-operations.js +79 -0
  334. package/src/template-validation/random-topology-operations.ts +101 -0
  335. package/src/template-validation/random-topology-runtime.js +25 -0
  336. package/src/template-validation/random-topology-runtime.ts +43 -0
  337. package/src/template-validation/random-topology-scenario.js +52 -0
  338. package/src/template-validation/random-topology-scenario.ts +57 -0
  339. package/src/template-validation/random-topology-schema.js +159 -0
  340. package/src/template-validation/random-topology-schema.ts +190 -0
  341. package/src/template-validation/random-topology-state.js +28 -0
  342. package/src/template-validation/random-topology-state.ts +30 -0
  343. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  344. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  345. package/src/template-validation/random-topology-trigger.js +75 -0
  346. package/src/template-validation/random-topology-trigger.ts +88 -0
  347. package/src/template-validation/report-formatter.js +40 -46
  348. package/src/template-validation/report-formatter.ts +101 -0
  349. package/src/template-validation/simulate-consensus-gates.js +111 -302
  350. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  351. package/src/template-validation/simulate-random-topology.js +26 -519
  352. package/src/template-validation/simulate-random-topology.ts +57 -0
  353. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  354. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  355. package/src/template-validation/simulation-agent-runtime.js +25 -0
  356. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  357. package/src/template-validation/simulation-agent.js +29 -0
  358. package/src/template-validation/simulation-agent.ts +73 -0
  359. package/src/template-validation/simulation-runtime.js +34 -0
  360. package/src/template-validation/simulation-runtime.ts +72 -0
  361. package/src/template-validation/two-stage-contracts.js +2 -0
  362. package/src/template-validation/two-stage-contracts.ts +41 -0
  363. package/src/template-validation/two-stage-inputs.js +21 -0
  364. package/src/template-validation/two-stage-inputs.ts +29 -0
  365. package/src/template-validation/two-stage-results.js +30 -0
  366. package/src/template-validation/two-stage-results.ts +40 -0
  367. package/src/template-validation/two-stage-scenario.js +86 -0
  368. package/src/template-validation/two-stage-scenario.ts +120 -0
  369. package/src/worktree-claude-config.js +182 -220
  370. package/src/worktree-claude-config.ts +272 -0
  371. package/src/worktree-tooling-env.js +103 -125
  372. package/src/worktree-tooling-env.ts +142 -0
  373. package/task-lib/completion.js +2 -3
  374. package/task-lib/completion.ts +9 -0
  375. package/task-lib/config.js +1 -4
  376. package/task-lib/config.ts +11 -0
  377. package/task-lib/name-generator.js +4 -226
  378. package/task-lib/name-generator.ts +11 -0
  379. package/task-lib/omp-session-cleanup.js +1 -1
  380. package/task-lib/omp-storage-root.js +8 -12
  381. package/task-lib/omp-storage-root.ts +62 -0
  382. package/task-lib/process-termination.js +143 -166
  383. package/task-lib/process-termination.ts +268 -0
@@ -0,0 +1,96 @@
1
+ export type SettingsMap = Record<string, unknown>;
2
+ export type DecisionScope = 'global' | 'repo';
3
+
4
+ export interface DecisionTarget {
5
+ path: string;
6
+ scope: DecisionScope;
7
+ }
8
+
9
+ export interface SetupEnvironment {
10
+ CI?: string;
11
+ __isTTY?: boolean;
12
+ npm_config_global?: string;
13
+ npm_execpath?: string;
14
+ }
15
+
16
+ interface ProviderMetadata {
17
+ binary: string;
18
+ displayName: string;
19
+ installInstructions: string;
20
+ }
21
+
22
+ interface ProviderAdapter {
23
+ cliCommand?: string;
24
+ isAvailable(): boolean;
25
+ }
26
+
27
+ export interface ProviderLevelDefaults {
28
+ defaultLevel?: unknown;
29
+ maxLevel?: unknown;
30
+ minLevel?: unknown;
31
+ }
32
+
33
+ export interface SetupPlanDependencies {
34
+ checkDocker(): { available: unknown };
35
+ checkGhAuth(): { authenticated: unknown };
36
+ commandExists(command: string): boolean;
37
+ execSync(command: string, options: { cwd: string; encoding: 'utf8'; stdio: 'pipe' }): string;
38
+ getCommandPath(command: string): string | null;
39
+ getDefaultProviderId(): string;
40
+ getNodeVersion(): string;
41
+ getPackageVersion(): string;
42
+ getProvider(name: string): ProviderAdapter;
43
+ getProviderDefaults(): Record<string, ProviderLevelDefaults | undefined>;
44
+ getProviderMetadata(name: string): ProviderMetadata;
45
+ listProviders(): string[];
46
+ }
47
+
48
+ export interface ProviderFact {
49
+ available: boolean;
50
+ displayName: string;
51
+ installInstructions: string;
52
+ path: string | null;
53
+ }
54
+
55
+ export interface SetupFacts {
56
+ docker: { available: boolean };
57
+ git: {
58
+ branch: string | null;
59
+ ghAuthed: boolean | null;
60
+ ghAvailable: boolean;
61
+ isRepo: boolean;
62
+ remote: string | null;
63
+ };
64
+ node: { installSource: string; packageVersion: string; version: string };
65
+ providers: Record<string, ProviderFact>;
66
+ settings: { hasGlobal: boolean; hasRepo: boolean };
67
+ }
68
+
69
+ export interface SetupDecision {
70
+ currentValue: unknown;
71
+ decisionId: string;
72
+ domain: string;
73
+ }
74
+
75
+ export interface ProposedWrite extends DecisionTarget {
76
+ decisionId: string;
77
+ from: unknown;
78
+ to: unknown;
79
+ }
80
+
81
+ export interface BuildSetupPlanParams {
82
+ cwd?: string;
83
+ deps?: Partial<SetupPlanDependencies>;
84
+ env?: SetupEnvironment;
85
+ repoSettings?: SettingsMap | null;
86
+ settings?: SettingsMap;
87
+ }
88
+
89
+ export interface SetupPlan {
90
+ decisions: SetupDecision[];
91
+ facts: SetupFacts;
92
+ proposedWrites: ProposedWrite[];
93
+ recommended: Record<string, unknown>;
94
+ risk: Record<string, string>;
95
+ schemaVersion: number;
96
+ }
@@ -0,0 +1,500 @@
1
+ /**
2
+ * Setup plan — read-only facts collector + the pinned, versioned setup contract.
3
+ *
4
+ * buildSetupPlan() is pure over its injected inputs: no direct process.env/fs
5
+ * reads for config data, no writes, no prompts. Everything downstream (apply,
6
+ * undo, the TTY wizard, agents) consumes the object this returns, so its shape
7
+ * (schemaVersion, facts, decisions, recommended, risk, proposedWrites) and the
8
+ * decisionId registry below are a stable contract — do not rename IDs or add a
9
+ * parallel run-mode field without updating every consumer.
10
+ */
11
+
12
+ import path = require('path');
13
+ import type {
14
+ BuildSetupPlanParams,
15
+ DecisionTarget,
16
+ ProposedWrite,
17
+ SetupDecision,
18
+ SetupEnvironment,
19
+ SetupFacts,
20
+ SetupPlan,
21
+ SetupPlanDependencies,
22
+ } from './setup-plan-types';
23
+
24
+ const SCHEMA_VERSION = 2;
25
+ type SettingsMap = Record<string, unknown>;
26
+ interface ProviderFact {
27
+ available: boolean;
28
+ displayName: string;
29
+ installInstructions: string;
30
+ path: string | null;
31
+ }
32
+
33
+ // Canonical settings keys consumed by resolveEffectiveRunPlan. Never introduce
34
+ // a parallel setting or translate a decision into a differently named key.
35
+ const DECISION_PATHS: Record<string, DecisionTarget> = {
36
+ defaultProvider: { scope: 'global', path: 'defaultProvider' },
37
+ defaultIsolation: { scope: 'global', path: 'defaultIsolation' },
38
+ allowLocalNoIsolation: { scope: 'global', path: 'allowLocalNoIsolation' },
39
+ defaultDelivery: { scope: 'global', path: 'defaultDelivery' },
40
+ defaultIssueSource: { scope: 'global', path: 'defaultIssueSource' },
41
+ prBase: { scope: 'repo', path: 'prBase' },
42
+ dockerMounts: { scope: 'global', path: 'dockerMounts' },
43
+ dockerEnvPassthrough: { scope: 'global', path: 'dockerEnvPassthrough' },
44
+ updatePolicy: { scope: 'global', path: 'updatePolicy' },
45
+ };
46
+
47
+ function providerLevelDecisionId(providerName: string): string {
48
+ return `providerLevel.${providerName}`;
49
+ }
50
+
51
+ // Settings keys consumed by runtime resolvers. Shared by buildProposedWrites
52
+ // and setup apply so neither surface can advertise dead configuration.
53
+ const CONSUMED_PATHS = new Set<string>([
54
+ 'global:defaultProvider',
55
+ 'global:defaultIsolation',
56
+ 'global:defaultDelivery',
57
+ 'global:defaultIssueSource',
58
+ 'global:dockerMounts',
59
+ 'global:dockerEnvPassthrough',
60
+ // No resolver consumes this yet; consumption is deferred to a future
61
+ // update-policy issue, but issue #606 explicitly sanctions writing it now.
62
+ 'global:updatePolicy',
63
+ ]);
64
+
65
+ function isConsumedPath(scope: string, targetPath: string): boolean {
66
+ if (scope === 'global' && targetPath.startsWith('providerSettings.')) return true;
67
+ return CONSUMED_PATHS.has(`${scope}:${targetPath}`);
68
+ }
69
+
70
+ // providerLevel.<provider> decisionIds map to a per-provider settings key
71
+ // (providerSettings.<provider>) not present in DECISION_PATHS above, since
72
+ // the provider name is only known at runtime.
73
+ function resolveDecisionPath(decisionId: string): DecisionTarget | null {
74
+ if (decisionId.startsWith('providerLevel.')) {
75
+ const providerName = decisionId.slice('providerLevel.'.length);
76
+ return { scope: 'global', path: `providerSettings.${providerName}` };
77
+ }
78
+ return DECISION_PATHS[decisionId] || null;
79
+ }
80
+
81
+ function getNestedValue(source: unknown, pathStr: string): unknown {
82
+ return pathStr
83
+ .split('.')
84
+ .reduce<unknown>((acc, key) => {
85
+ if (acc === null || acc === undefined) return undefined;
86
+ // Property access intentionally retains JavaScript's primitive boxing behavior.
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
88
+ return (acc as SettingsMap)[key];
89
+ }, source);
90
+ }
91
+
92
+ function defaultDeps(): SetupPlanDependencies {
93
+ // These paths intentionally resolve beside the emitted module in lib/.
94
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
95
+ const { commandExists, getCommandPath }: Pick<
96
+ SetupPlanDependencies,
97
+ 'commandExists' | 'getCommandPath'
98
+ > = require('./provider-detection');
99
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
100
+ const { checkDocker, checkGhAuth }: Pick<
101
+ SetupPlanDependencies,
102
+ 'checkDocker' | 'checkGhAuth'
103
+ > = require('../src/preflight');
104
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
105
+ const { execSync }: Pick<SetupPlanDependencies, 'execSync'> = require('../src/lib/safe-exec');
106
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
107
+ const { listProviders, getProvider }: Pick<
108
+ SetupPlanDependencies,
109
+ 'listProviders' | 'getProvider'
110
+ > = require('../src/providers');
111
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
112
+ const { getProviderDefaults }: Pick<SetupPlanDependencies, 'getProviderDefaults'> =
113
+ require('./provider-defaults');
114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
115
+ const { getDefaultProviderId, getProviderMetadata }: Pick<
116
+ SetupPlanDependencies,
117
+ 'getDefaultProviderId' | 'getProviderMetadata'
118
+ > = require('./provider-names');
119
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
120
+ const packageJson: { version: string } = require('../package.json');
121
+
122
+ return {
123
+ commandExists,
124
+ getCommandPath,
125
+ checkDocker,
126
+ checkGhAuth,
127
+ execSync,
128
+ listProviders,
129
+ getProvider,
130
+ getProviderDefaults,
131
+ getDefaultProviderId,
132
+ getProviderMetadata,
133
+ getNodeVersion: () => process.version,
134
+ getPackageVersion: () => packageJson.version,
135
+ };
136
+ }
137
+
138
+ function detectInstallSource(cwd: string, env: SetupEnvironment): string {
139
+ if (env.npm_config_global === 'true') return 'npm-global';
140
+ if (env.npm_execpath && /_npx|npx/.test(env.npm_execpath)) return 'npx';
141
+ const ownNodeModules = path.join(__dirname, '..', 'node_modules');
142
+ if (cwd && (cwd === path.join(__dirname, '..') || cwd.startsWith(ownNodeModules))) return 'local';
143
+ return 'unknown';
144
+ }
145
+
146
+ function buildNodeFacts({
147
+ cwd,
148
+ env,
149
+ deps,
150
+ }: {
151
+ cwd: string;
152
+ deps: SetupPlanDependencies;
153
+ env: SetupEnvironment;
154
+ }): SetupFacts['node'] {
155
+ return {
156
+ version: deps.getNodeVersion(),
157
+ packageVersion: deps.getPackageVersion(),
158
+ installSource: detectInstallSource(cwd, env),
159
+ };
160
+ }
161
+
162
+ function buildProviderFacts(deps: SetupPlanDependencies): Record<string, ProviderFact> {
163
+ const providers: Record<string, ProviderFact> = {};
164
+ for (const name of deps.listProviders()) {
165
+ const metadata = deps.getProviderMetadata(name);
166
+ const provider = deps.getProvider(name);
167
+ let available = false;
168
+ try {
169
+ available = provider.isAvailable() === true;
170
+ } catch {
171
+ available = false;
172
+ }
173
+ const cliCommand = provider.cliCommand || metadata.binary;
174
+ providers[name] = {
175
+ available,
176
+ displayName: metadata.displayName,
177
+ installInstructions: metadata.installInstructions,
178
+ path: available && deps.commandExists(cliCommand) ? deps.getCommandPath(cliCommand) : null,
179
+ };
180
+ }
181
+ return providers;
182
+ }
183
+
184
+ function safeExecTrim(
185
+ deps: SetupPlanDependencies,
186
+ command: string,
187
+ cwd: string
188
+ ): string | null {
189
+ try {
190
+ return deps.execSync(command, { cwd, stdio: 'pipe', encoding: 'utf8' }).trim();
191
+ } catch {
192
+ return null;
193
+ }
194
+ }
195
+
196
+ function buildGitFacts({
197
+ cwd,
198
+ deps,
199
+ }: {
200
+ cwd: string;
201
+ deps: SetupPlanDependencies;
202
+ }): SetupFacts['git'] {
203
+ const isRepo = safeExecTrim(deps, 'git rev-parse --is-inside-work-tree', cwd) === 'true';
204
+ const ghAvailable = deps.commandExists('gh');
205
+
206
+ if (!isRepo) {
207
+ return { isRepo: false, branch: null, remote: null, ghAvailable, ghAuthed: null };
208
+ }
209
+
210
+ const branch = safeExecTrim(deps, 'git rev-parse --abbrev-ref HEAD', cwd);
211
+ const remote = safeExecTrim(deps, 'git remote get-url origin', cwd);
212
+ const ghAuthed = ghAvailable ? !!deps.checkGhAuth().authenticated : null;
213
+
214
+ return { isRepo: true, branch, remote, ghAvailable, ghAuthed };
215
+ }
216
+
217
+ function buildFacts({
218
+ cwd,
219
+ settings,
220
+ repoSettings,
221
+ env,
222
+ deps,
223
+ }: {
224
+ cwd: string;
225
+ deps: SetupPlanDependencies;
226
+ env: SetupEnvironment;
227
+ repoSettings: SettingsMap | null | undefined;
228
+ settings: SettingsMap;
229
+ }): SetupFacts {
230
+ return {
231
+ node: buildNodeFacts({ cwd, env, deps }),
232
+ providers: buildProviderFacts(deps),
233
+ git: buildGitFacts({ cwd, deps }),
234
+ docker: { available: !!deps.checkDocker().available },
235
+ settings: {
236
+ hasGlobal: settings.__meta ? Boolean(getNestedValue(settings.__meta, 'fileExists')) : true,
237
+ hasRepo: repoSettings !== null && repoSettings !== undefined,
238
+ },
239
+ };
240
+ }
241
+
242
+ function inferIssueSource(facts: SetupFacts): string | null {
243
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
244
+ const { parseGitRemoteUrl }: {
245
+ parseGitRemoteUrl(remote: string | null): { provider?: string } | null;
246
+ } = require('./git-remote-utils');
247
+ const parsed = parseGitRemoteUrl(facts.git.remote);
248
+ return parsed?.provider || null;
249
+ }
250
+
251
+ function inferPrBase(cwd: string, deps: SetupPlanDependencies): string | null {
252
+ const branch = safeExecTrim(deps, 'git rev-parse --abbrev-ref origin/HEAD', cwd);
253
+ if (!branch) return null;
254
+ return branch.replace(/^origin\//, '');
255
+ }
256
+
257
+ function buildProviderLevelRecommendation(
258
+ name: string,
259
+ deps: SetupPlanDependencies
260
+ ): Record<string, unknown> {
261
+ const providerDefaults = deps.getProviderDefaults()[name] || {};
262
+ return {
263
+ minLevel: providerDefaults.minLevel || 'level1',
264
+ defaultLevel: providerDefaults.defaultLevel || 'level2',
265
+ maxLevel: providerDefaults.maxLevel || 'level3',
266
+ };
267
+ }
268
+
269
+ function buildRecommendedAndRisk({
270
+ cwd,
271
+ facts,
272
+ env,
273
+ deps,
274
+ }: {
275
+ cwd: string;
276
+ deps: SetupPlanDependencies;
277
+ env: SetupEnvironment;
278
+ facts: SetupFacts;
279
+ }): {
280
+ inferredIssueSource: string | null;
281
+ inferredPrBase: string | null;
282
+ recommended: Record<string, unknown>;
283
+ risk: Record<string, string>;
284
+ } {
285
+ const recommended: Record<string, unknown> = {};
286
+ const risk: Record<string, string> = {};
287
+ const registryDefault = deps.getDefaultProviderId();
288
+ recommended.defaultProvider = registryDefault;
289
+ risk.defaultProvider = facts.providers[registryDefault]?.available ? 'low' : 'medium';
290
+
291
+ for (const name of Object.keys(facts.providers)) {
292
+ recommended[providerLevelDecisionId(name)] = buildProviderLevelRecommendation(name, deps);
293
+ risk[providerLevelDecisionId(name)] = 'low';
294
+ }
295
+
296
+ if (facts.git.isRepo) {
297
+ recommended.defaultIsolation = 'worktree';
298
+ risk.defaultIsolation = 'low';
299
+ } else if (facts.docker.available) {
300
+ recommended.defaultIsolation = 'docker';
301
+ risk.defaultIsolation = 'low';
302
+ } else {
303
+ recommended.defaultIsolation = 'none';
304
+ risk.defaultIsolation = 'high';
305
+ }
306
+
307
+ recommended.allowLocalNoIsolation = false;
308
+ risk.allowLocalNoIsolation = 'low';
309
+ recommended.defaultDelivery = 'none';
310
+ risk.defaultDelivery = 'low';
311
+
312
+ const inferredIssueSource = inferIssueSource(facts);
313
+ recommended.defaultIssueSource = inferredIssueSource || 'github';
314
+ risk.defaultIssueSource = inferredIssueSource ? 'low' : 'medium';
315
+
316
+ const inferredPrBase = inferPrBase(cwd, deps);
317
+ recommended.prBase = inferredPrBase || 'main';
318
+ risk.prBase = inferredPrBase ? 'low' : 'medium';
319
+ recommended.dockerMounts = ['gh', 'git', 'ssh'];
320
+ risk.dockerMounts = 'low';
321
+ recommended.dockerEnvPassthrough = [];
322
+ risk.dockerEnvPassthrough = 'low';
323
+
324
+ const nonInteractive = env.CI === 'true' || env.__isTTY === false;
325
+ recommended.updatePolicy = nonInteractive ? 'off' : 'notify';
326
+ risk.updatePolicy = 'low';
327
+
328
+ return { recommended, risk, inferredIssueSource, inferredPrBase };
329
+ }
330
+
331
+ function currentValueFor(
332
+ decisionId: string,
333
+ settings: SettingsMap,
334
+ repoSettings: SettingsMap | null | undefined
335
+ ): unknown {
336
+ const target = resolveDecisionPath(decisionId);
337
+ if (!target) return null;
338
+ const source = target.scope === 'repo' ? repoSettings || {} : settings || {};
339
+ const value = getNestedValue(source, target.path);
340
+ return value === undefined ? null : value;
341
+ }
342
+
343
+ function buildDecisions({
344
+ facts,
345
+ settings,
346
+ repoSettings,
347
+ inferredIssueSource,
348
+ inferredPrBase,
349
+ }: {
350
+ facts: SetupFacts;
351
+ inferredIssueSource: string | null;
352
+ inferredPrBase: string | null;
353
+ repoSettings: SettingsMap | null | undefined;
354
+ settings: SettingsMap;
355
+ }): SetupDecision[] {
356
+ const decisions: SetupDecision[] = [];
357
+ const hasGlobal = facts.settings.hasGlobal;
358
+ const hasRepo = facts.settings.hasRepo;
359
+
360
+ const globalDecisionIds = [
361
+ 'defaultProvider',
362
+ ...Object.keys(facts.providers).map(providerLevelDecisionId),
363
+ 'defaultIsolation',
364
+ 'allowLocalNoIsolation',
365
+ 'defaultDelivery',
366
+ 'defaultIssueSource',
367
+ 'dockerMounts',
368
+ 'dockerEnvPassthrough',
369
+ 'updatePolicy',
370
+ ];
371
+
372
+ for (const decisionId of globalDecisionIds) {
373
+ const shouldInclude =
374
+ !hasGlobal || (decisionId === 'defaultIssueSource' && !inferredIssueSource);
375
+ if (!shouldInclude) continue;
376
+ decisions.push({
377
+ decisionId,
378
+ domain: domainFor(decisionId),
379
+ currentValue: currentValueFor(decisionId, settings, repoSettings),
380
+ });
381
+ }
382
+
383
+ if (!hasRepo || !inferredPrBase) {
384
+ decisions.push({
385
+ decisionId: 'prBase',
386
+ domain: domainFor('prBase'),
387
+ currentValue: currentValueFor('prBase', settings, repoSettings),
388
+ });
389
+ }
390
+
391
+ return decisions;
392
+ }
393
+
394
+ function domainFor(decisionId: string): string {
395
+ if (decisionId.startsWith('providerLevel.')) {
396
+ return '{ minLevel, defaultLevel, maxLevel } of level1|level2|level3';
397
+ }
398
+ const domains: Record<string, string> = {
399
+ defaultProvider: 'registry provider id',
400
+ defaultIsolation: 'worktree | docker | none',
401
+ allowLocalNoIsolation: 'boolean',
402
+ defaultDelivery: 'none | pr | ship',
403
+ defaultIssueSource: 'github | gitlab | jira | azure-devops | linear',
404
+ prBase: 'string (branch)',
405
+ dockerMounts: 'array of presets/objects',
406
+ dockerEnvPassthrough: 'string[]',
407
+ updatePolicy: 'off | notify | auto',
408
+ };
409
+ return domains[decisionId] || 'unknown';
410
+ }
411
+
412
+ function buildProposedWrites({
413
+ decisions,
414
+ recommended,
415
+ }: {
416
+ decisions: SetupDecision[];
417
+ recommended: Record<string, unknown>;
418
+ }): ProposedWrite[] {
419
+ const writes: ProposedWrite[] = [];
420
+ for (const decision of decisions) {
421
+ const target = resolveDecisionPath(decision.decisionId);
422
+ if (!target) continue;
423
+ // A decision can still be surfaced for the user to make (e.g. a future
424
+ // wizard asking about prBase), but proposing a *write* for a settings key
425
+ // no resolver reads would advertise a write that apply will always skip —
426
+ // dead config. Only propose writes apply will actually perform.
427
+ if (!isConsumedPath(target.scope, target.path)) continue;
428
+ const to = recommended[decision.decisionId];
429
+ if (to === decision.currentValue) continue;
430
+ writes.push({
431
+ scope: target.scope,
432
+ path: target.path,
433
+ from: decision.currentValue ?? null,
434
+ to,
435
+ decisionId: decision.decisionId,
436
+ });
437
+ }
438
+ return writes;
439
+ }
440
+
441
+ /**
442
+ * Build the pinned, versioned setup contract. Pure over injected inputs —
443
+ * performs only cheap, read-only detection (no writes, no prompts).
444
+ */
445
+ function buildSetupPlan({
446
+ cwd,
447
+ settings,
448
+ repoSettings,
449
+ env,
450
+ deps,
451
+ }: BuildSetupPlanParams = {}): SetupPlan {
452
+ const resolvedDeps: SetupPlanDependencies = { ...defaultDeps(), ...(deps || {}) };
453
+ const resolvedEnv: SetupEnvironment = env || {};
454
+ const resolvedCwd = cwd || '.';
455
+ const resolvedSettings = settings || {};
456
+
457
+ const facts = buildFacts({
458
+ cwd: resolvedCwd,
459
+ settings: resolvedSettings,
460
+ repoSettings,
461
+ env: resolvedEnv,
462
+ deps: resolvedDeps,
463
+ });
464
+
465
+ const { recommended, risk, inferredIssueSource, inferredPrBase } = buildRecommendedAndRisk({
466
+ cwd: resolvedCwd,
467
+ facts,
468
+ env: resolvedEnv,
469
+ deps: resolvedDeps,
470
+ });
471
+
472
+ const decisions = buildDecisions({
473
+ facts,
474
+ settings: resolvedSettings,
475
+ repoSettings,
476
+ inferredIssueSource,
477
+ inferredPrBase,
478
+ });
479
+
480
+ const proposedWrites = buildProposedWrites({ decisions, recommended });
481
+
482
+ return {
483
+ schemaVersion: SCHEMA_VERSION,
484
+ facts,
485
+ decisions,
486
+ recommended,
487
+ risk,
488
+ proposedWrites,
489
+ };
490
+ }
491
+
492
+ export = {
493
+ buildSetupPlan,
494
+ resolveDecisionPath,
495
+ domainFor,
496
+ DECISION_PATHS,
497
+ getNestedValue,
498
+ isConsumedPath,
499
+ CONSUMED_PATHS,
500
+ };