infraweaver 0.1.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 (524) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +244 -0
  3. package/dist/agents/claude.d.ts +113 -0
  4. package/dist/agents/claudePretoolGate.d.ts +137 -0
  5. package/dist/agents/dispatchMetrics.d.ts +77 -0
  6. package/dist/agents/gateServer.d.ts +7 -0
  7. package/dist/agents/index.d.ts +6 -0
  8. package/dist/agents/nativeFsDenies.d.ts +46 -0
  9. package/dist/agents/opencode.d.ts +284 -0
  10. package/dist/agents/opencodePlugin.d.ts +96 -0
  11. package/dist/agents/opencodeShared.d.ts +40 -0
  12. package/dist/agents/postRun.d.ts +126 -0
  13. package/dist/agents/reviewer.d.ts +41 -0
  14. package/dist/agents/sessionLabeler.d.ts +97 -0
  15. package/dist/agents/shared.d.ts +246 -0
  16. package/dist/agents/subagentModels.d.ts +19 -0
  17. package/dist/agents/tokenQuota.d.ts +118 -0
  18. package/dist/agents/writeGateSource.d.ts +22 -0
  19. package/dist/agents/writePolicy.d.ts +79 -0
  20. package/dist/brand.d.ts +67 -0
  21. package/dist/cli.mjs +247846 -0
  22. package/dist/external.d.ts +227 -0
  23. package/dist/i18n/scaffolding.d.ts +59 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.js +247061 -0
  26. package/dist/internal/index.d.ts +18 -0
  27. package/dist/internal.js +2398 -0
  28. package/dist/lifecycle.d.ts +2 -0
  29. package/dist/main.d.ts +8 -0
  30. package/dist/mcp/arkConfig.d.ts +1 -0
  31. package/dist/mcp/assess.d.ts +157 -0
  32. package/dist/mcp/capabilityContext.d.ts +71 -0
  33. package/dist/mcp/changeSummary.d.ts +52 -0
  34. package/dist/mcp/checkSuite.d.ts +27 -0
  35. package/dist/mcp/checkout.d.ts +92 -0
  36. package/dist/mcp/comment.d.ts +127 -0
  37. package/dist/mcp/commitInfo.d.ts +11 -0
  38. package/dist/mcp/crosswalk.d.ts +178 -0
  39. package/dist/mcp/crosswalkDigest.d.ts +1 -0
  40. package/dist/mcp/cyberEssentials.d.ts +24 -0
  41. package/dist/mcp/dashboard.d.ts +125 -0
  42. package/dist/mcp/dependencies.d.ts +12 -0
  43. package/dist/mcp/frameworks.d.ts +74 -0
  44. package/dist/mcp/geminiSanitizer.d.ts +28 -0
  45. package/dist/mcp/git.d.ts +60 -0
  46. package/dist/mcp/guardrails.d.ts +222 -0
  47. package/dist/mcp/issue.d.ts +20 -0
  48. package/dist/mcp/issueComments.d.ts +11 -0
  49. package/dist/mcp/issueEvents.d.ts +11 -0
  50. package/dist/mcp/issueInfo.d.ts +11 -0
  51. package/dist/mcp/labels.d.ts +14 -0
  52. package/dist/mcp/localContext.d.ts +26 -0
  53. package/dist/mcp/moduleExtraction.d.ts +79 -0
  54. package/dist/mcp/moduleTests.d.ts +106 -0
  55. package/dist/mcp/modules.d.ts +198 -0
  56. package/dist/mcp/output.d.ts +16 -0
  57. package/dist/mcp/pathSafety.d.ts +14 -0
  58. package/dist/mcp/policy.d.ts +50 -0
  59. package/dist/mcp/pr.d.ts +64 -0
  60. package/dist/mcp/prInfo.d.ts +11 -0
  61. package/dist/mcp/providerSchema.d.ts +52 -0
  62. package/dist/mcp/review.d.ts +212 -0
  63. package/dist/mcp/reviewComments.d.ts +245 -0
  64. package/dist/mcp/roots.d.ts +60 -0
  65. package/dist/mcp/scope.d.ts +26 -0
  66. package/dist/mcp/selectMode.d.ts +20 -0
  67. package/dist/mcp/server.d.ts +61 -0
  68. package/dist/mcp/shared.d.ts +62 -0
  69. package/dist/mcp/shell.d.ts +58 -0
  70. package/dist/mcp/staleFix.d.ts +138 -0
  71. package/dist/mcp/terraform/azurePrices.d.ts +8 -0
  72. package/dist/mcp/terraform/baseline.d.ts +57 -0
  73. package/dist/mcp/terraform/concernResult.d.ts +38 -0
  74. package/dist/mcp/terraform/cost.d.ts +55 -0
  75. package/dist/mcp/terraform/cspm.d.ts +80 -0
  76. package/dist/mcp/terraform/currency.d.ts +110 -0
  77. package/dist/mcp/terraform/decisions.d.ts +178 -0
  78. package/dist/mcp/terraform/eidas.d.ts +100 -0
  79. package/dist/mcp/terraform/evidence.d.ts +343 -0
  80. package/dist/mcp/terraform/findings.d.ts +76 -0
  81. package/dist/mcp/terraform/fixMemory.d.ts +81 -0
  82. package/dist/mcp/terraform/governance.d.ts +56 -0
  83. package/dist/mcp/terraform/hcl.d.ts +115 -0
  84. package/dist/mcp/terraform/iacLanguages.d.ts +120 -0
  85. package/dist/mcp/terraform/idleFloor.d.ts +78 -0
  86. package/dist/mcp/terraform/keyless.d.ts +68 -0
  87. package/dist/mcp/terraform/moduleDocs.d.ts +56 -0
  88. package/dist/mcp/terraform/nativeRules.d.ts +38 -0
  89. package/dist/mcp/terraform/nativeScan.d.ts +11 -0
  90. package/dist/mcp/terraform/noiseProfile.d.ts +100 -0
  91. package/dist/mcp/terraform/normalization.d.ts +52 -0
  92. package/dist/mcp/terraform/oscal.d.ts +103 -0
  93. package/dist/mcp/terraform/packs/azurerm-3-4.d.ts +2 -0
  94. package/dist/mcp/terraform/packs/cloudflare-4-5.d.ts +2 -0
  95. package/dist/mcp/terraform/paths.d.ts +28 -0
  96. package/dist/mcp/terraform/plan.d.ts +157 -0
  97. package/dist/mcp/terraform/planDrift.d.ts +199 -0
  98. package/dist/mcp/terraform/policyAuthor.d.ts +191 -0
  99. package/dist/mcp/terraform/prowlerOcsf.d.ts +136 -0
  100. package/dist/mcp/terraform/refactor.d.ts +183 -0
  101. package/dist/mcp/terraform/registry.d.ts +108 -0
  102. package/dist/mcp/terraform/risk.d.ts +41 -0
  103. package/dist/mcp/terraform/scanSession.d.ts +116 -0
  104. package/dist/mcp/terraform/scannerCache.d.ts +15 -0
  105. package/dist/mcp/terraform/scannerEgress.d.ts +72 -0
  106. package/dist/mcp/terraform/scannerJson.d.ts +13 -0
  107. package/dist/mcp/terraform/scanners.d.ts +205 -0
  108. package/dist/mcp/terraform/signing.d.ts +61 -0
  109. package/dist/mcp/terraform/stateLocking.d.ts +18 -0
  110. package/dist/mcp/terraform/subprocess.d.ts +43 -0
  111. package/dist/mcp/terraform/suppressions.d.ts +90 -0
  112. package/dist/mcp/terraform/taxonomy.d.ts +39 -0
  113. package/dist/mcp/terraform/tfquery.d.ts +47 -0
  114. package/dist/mcp/terraform/toolchainIntegrity.d.ts +82 -0
  115. package/dist/mcp/terraform/tools/authorPolicy.d.ts +59 -0
  116. package/dist/mcp/terraform/tools/detectPlanDrift.d.ts +20 -0
  117. package/dist/mcp/terraform/tools/emitCost.d.ts +11 -0
  118. package/dist/mcp/terraform/tools/emitSarif.d.ts +14 -0
  119. package/dist/mcp/terraform/tools/fixMemory.d.ts +19 -0
  120. package/dist/mcp/terraform/tools/infracostDiff.d.ts +22 -0
  121. package/dist/mcp/terraform/tools/ingestExternalFindings.d.ts +21 -0
  122. package/dist/mcp/terraform/tools/moduleLookup.d.ts +14 -0
  123. package/dist/mcp/terraform/tools/moduleSearch.d.ts +23 -0
  124. package/dist/mcp/terraform/tools/plan.d.ts +59 -0
  125. package/dist/mcp/terraform/tools/providerUpgrade.d.ts +55 -0
  126. package/dist/mcp/terraform/tools/readFindings.d.ts +17 -0
  127. package/dist/mcp/terraform/tools/scan.d.ts +114 -0
  128. package/dist/mcp/terraform/tools/validate.d.ts +31 -0
  129. package/dist/mcp/terraform/tools/verifyRemediation.d.ts +31 -0
  130. package/dist/mcp/terraform/tools/versionCurrency.d.ts +5 -0
  131. package/dist/mcp/terraform/tools.d.ts +16 -0
  132. package/dist/mcp/terraform/transformPacks.d.ts +267 -0
  133. package/dist/mcp/terraform/types.d.ts +226 -0
  134. package/dist/mcp/terraform/verification.d.ts +81 -0
  135. package/dist/mcp/terraform/vex.d.ts +115 -0
  136. package/dist/mcp/terraform/writeOnly.d.ts +67 -0
  137. package/dist/mcp/terraform.d.ts +51 -0
  138. package/dist/mcp/terratest.d.ts +85 -0
  139. package/dist/mcp/untrustedContent.d.ts +76 -0
  140. package/dist/mcp/upload.d.ts +8 -0
  141. package/dist/models.d.ts +181 -0
  142. package/dist/modes/address-reviews.d.ts +2 -0
  143. package/dist/modes/assess.d.ts +2 -0
  144. package/dist/modes/build.d.ts +2 -0
  145. package/dist/modes/compliance-audit.d.ts +2 -0
  146. package/dist/modes/cost-optimization.d.ts +2 -0
  147. package/dist/modes/drift-detect.d.ts +2 -0
  148. package/dist/modes/fix.d.ts +2 -0
  149. package/dist/modes/incremental-review.d.ts +2 -0
  150. package/dist/modes/index.d.ts +24 -0
  151. package/dist/modes/modernize-deprecated.d.ts +2 -0
  152. package/dist/modes/plan.d.ts +2 -0
  153. package/dist/modes/policy-gate.d.ts +2 -0
  154. package/dist/modes/prFormats.d.ts +3 -0
  155. package/dist/modes/refactor.d.ts +2 -0
  156. package/dist/modes/refresh-remediation.d.ts +2 -0
  157. package/dist/modes/remediate-and-refactor.d.ts +2 -0
  158. package/dist/modes/remediate.d.ts +2 -0
  159. package/dist/modes/resolve-conflicts.d.ts +2 -0
  160. package/dist/modes/review.d.ts +2 -0
  161. package/dist/modes/summarize-pr.d.ts +2 -0
  162. package/dist/modes/task.d.ts +2 -0
  163. package/dist/modes/terraform-code-review.d.ts +2 -0
  164. package/dist/modes/types.d.ts +9 -0
  165. package/dist/modes/update-dependencies.d.ts +2 -0
  166. package/dist/prep/index.d.ts +7 -0
  167. package/dist/prep/installNodeDependencies.d.ts +2 -0
  168. package/dist/prep/installPythonDependencies.d.ts +2 -0
  169. package/dist/prep/types.d.ts +31 -0
  170. package/dist/reviewQuality.d.ts +107 -0
  171. package/dist/skills/terraform-best-practices/SKILL.md +379 -0
  172. package/dist/toolState.d.ts +123 -0
  173. package/dist/utils/activity.d.ts +40 -0
  174. package/dist/utils/agent.d.ts +47 -0
  175. package/dist/utils/agentHangReport.d.ts +38 -0
  176. package/dist/utils/annotations.d.ts +17 -0
  177. package/dist/utils/apiFetch.d.ts +11 -0
  178. package/dist/utils/apiKeys.d.ts +48 -0
  179. package/dist/utils/apiUrl.d.ts +28 -0
  180. package/dist/utils/assets.d.ts +8 -0
  181. package/dist/utils/baseRefConfig.d.ts +121 -0
  182. package/dist/utils/billingErrors.d.ts +85 -0
  183. package/dist/utils/body.d.ts +34 -0
  184. package/dist/utils/buildInfraweaverFooter.d.ts +29 -0
  185. package/dist/utils/byokFallback.d.ts +85 -0
  186. package/dist/utils/changeImpact.d.ts +101 -0
  187. package/dist/utils/claudeSubscription.d.ts +30 -0
  188. package/dist/utils/cli.d.ts +10 -0
  189. package/dist/utils/cloudClient.d.ts +33 -0
  190. package/dist/utils/cloudFetchCore.d.ts +42 -0
  191. package/dist/utils/cloudReport.d.ts +114 -0
  192. package/dist/utils/codexHome.d.ts +29 -0
  193. package/dist/utils/codexOAuth.d.ts +60 -0
  194. package/dist/utils/diffCoverage.d.ts +63 -0
  195. package/dist/utils/env.d.ts +46 -0
  196. package/dist/utils/errorReport.d.ts +17 -0
  197. package/dist/utils/exitHandler.d.ts +8 -0
  198. package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
  199. package/dist/utils/gitAuth.d.ts +84 -0
  200. package/dist/utils/gitAuthServer.d.ts +24 -0
  201. package/dist/utils/github.d.ts +104 -0
  202. package/dist/utils/globals.d.ts +3 -0
  203. package/dist/utils/infraweaverConfig.d.ts +56 -0
  204. package/dist/utils/install.d.ts +37 -0
  205. package/dist/utils/instructions.d.ts +48 -0
  206. package/dist/utils/keylessOidc.d.ts +28 -0
  207. package/dist/utils/leapingComment.d.ts +11 -0
  208. package/dist/utils/learnings.d.ts +62 -0
  209. package/dist/utils/learningsTruncate.d.ts +25 -0
  210. package/dist/utils/lifecycle.d.ts +57 -0
  211. package/dist/utils/log.d.ts +111 -0
  212. package/dist/utils/modelResolver.d.ts +63 -0
  213. package/dist/utils/moduleFetch.d.ts +39 -0
  214. package/dist/utils/normalizeEnv.d.ts +30 -0
  215. package/dist/utils/openCodeModels.d.ts +11 -0
  216. package/dist/utils/openaiCompatible.d.ts +26 -0
  217. package/dist/utils/opentofuMcp.d.ts +50 -0
  218. package/dist/utils/overrides.d.ts +40 -0
  219. package/dist/utils/packageManager.d.ts +49 -0
  220. package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
  221. package/dist/utils/payload.d.ts +249 -0
  222. package/dist/utils/prSummary.d.ts +61 -0
  223. package/dist/utils/presets.d.ts +36 -0
  224. package/dist/utils/progressComment.d.ts +146 -0
  225. package/dist/utils/providerErrors.d.ts +31 -0
  226. package/dist/utils/proxyModel.d.ts +76 -0
  227. package/dist/utils/rangeDiff.d.ts +51 -0
  228. package/dist/utils/redact.d.ts +33 -0
  229. package/dist/utils/registryAuth.d.ts +52 -0
  230. package/dist/utils/remediationCommand.d.ts +58 -0
  231. package/dist/utils/retry.d.ts +38 -0
  232. package/dist/utils/reviewCleanup.d.ts +14 -0
  233. package/dist/utils/run.d.ts +9 -0
  234. package/dist/utils/runContext.d.ts +112 -0
  235. package/dist/utils/runContextData.d.ts +42 -0
  236. package/dist/utils/runErrorRenderer.d.ts +64 -0
  237. package/dist/utils/runLifecycle.d.ts +89 -0
  238. package/dist/utils/runStartupLog.d.ts +15 -0
  239. package/dist/utils/secrets.d.ts +34 -0
  240. package/dist/utils/setup.d.ts +90 -0
  241. package/dist/utils/shell.d.ts +44 -0
  242. package/dist/utils/skills.d.ts +10 -0
  243. package/dist/utils/subprocess.d.ts +81 -0
  244. package/dist/utils/terraformMcp.d.ts +46 -0
  245. package/dist/utils/time.d.ts +15 -0
  246. package/dist/utils/timer.d.ts +23 -0
  247. package/dist/utils/todoTracking.d.ts +16 -0
  248. package/dist/utils/token.d.ts +52 -0
  249. package/dist/utils/toolLicensing.d.ts +56 -0
  250. package/dist/utils/toolSelection.d.ts +73 -0
  251. package/dist/utils/toon.d.ts +16 -0
  252. package/dist/utils/version.d.ts +2 -0
  253. package/dist/utils/versioning.d.ts +7 -0
  254. package/dist/utils/vertex.d.ts +16 -0
  255. package/dist/utils/workflow.d.ts +13 -0
  256. package/package.json +132 -0
  257. package/src/agents/claude.ts +1588 -0
  258. package/src/agents/claudePretoolGate.ts +286 -0
  259. package/src/agents/dispatchMetrics.ts +162 -0
  260. package/src/agents/gateServer.ts +178 -0
  261. package/src/agents/index.ts +10 -0
  262. package/src/agents/nativeFsDenies.ts +164 -0
  263. package/src/agents/opencode.ts +1600 -0
  264. package/src/agents/opencodePlugin.ts +304 -0
  265. package/src/agents/opencodeShared.ts +134 -0
  266. package/src/agents/postRun.ts +615 -0
  267. package/src/agents/reviewer.ts +134 -0
  268. package/src/agents/sessionLabeler.ts +185 -0
  269. package/src/agents/shared.ts +377 -0
  270. package/src/agents/subagentModels.ts +40 -0
  271. package/src/agents/tokenQuota.ts +203 -0
  272. package/src/agents/writeGateSource.ts +148 -0
  273. package/src/agents/writePolicy.ts +132 -0
  274. package/src/brand.ts +84 -0
  275. package/src/cli.ts +117 -0
  276. package/src/commands/gha.ts +188 -0
  277. package/src/commands/mcp.ts +126 -0
  278. package/src/commands/verifyEvidence.ts +100 -0
  279. package/src/entry.ts +7 -0
  280. package/src/entryPost.ts +109 -0
  281. package/src/external.ts +308 -0
  282. package/src/i18n/scaffolding.ts +191 -0
  283. package/src/index.ts +7 -0
  284. package/src/internal/index.ts +74 -0
  285. package/src/lifecycle.ts +2 -0
  286. package/src/main.ts +815 -0
  287. package/src/mcp/__fixtures__/infraweaver-scratch-pr-49-review-3485940013.json +110 -0
  288. package/src/mcp/__fixtures__/infraweaver-scratch-pr-64-review-3531000326.json +14 -0
  289. package/src/mcp/__fixtures__/infraweaver-test-repo-pr-1.diff.json +67 -0
  290. package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
  291. package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
  292. package/src/mcp/arkConfig.ts +7 -0
  293. package/src/mcp/assess.ts +723 -0
  294. package/src/mcp/capabilityContext.ts +80 -0
  295. package/src/mcp/changeSummary.ts +145 -0
  296. package/src/mcp/checkSuite.ts +261 -0
  297. package/src/mcp/checkout.ts +1015 -0
  298. package/src/mcp/comment.ts +683 -0
  299. package/src/mcp/commitInfo.ts +57 -0
  300. package/src/mcp/crosswalk.ts +1253 -0
  301. package/src/mcp/crosswalkDigest.ts +5 -0
  302. package/src/mcp/cyberEssentials.ts +60 -0
  303. package/src/mcp/dashboard.ts +232 -0
  304. package/src/mcp/dependencies.ts +190 -0
  305. package/src/mcp/frameworks.ts +236 -0
  306. package/src/mcp/geminiSanitizer.ts +212 -0
  307. package/src/mcp/git.ts +1116 -0
  308. package/src/mcp/guardrails.ts +771 -0
  309. package/src/mcp/issue.ts +74 -0
  310. package/src/mcp/issueComments.ts +48 -0
  311. package/src/mcp/issueEvents.ts +100 -0
  312. package/src/mcp/issueInfo.ts +72 -0
  313. package/src/mcp/labels.ts +35 -0
  314. package/src/mcp/localContext.ts +65 -0
  315. package/src/mcp/localServer.ts +217 -0
  316. package/src/mcp/moduleExtraction.ts +368 -0
  317. package/src/mcp/moduleTests.ts +421 -0
  318. package/src/mcp/modules.ts +752 -0
  319. package/src/mcp/output.ts +71 -0
  320. package/src/mcp/pathSafety.ts +28 -0
  321. package/src/mcp/policy.ts +226 -0
  322. package/src/mcp/pr.ts +238 -0
  323. package/src/mcp/prInfo.ts +91 -0
  324. package/src/mcp/providerSchema.ts +175 -0
  325. package/src/mcp/review.ts +1081 -0
  326. package/src/mcp/reviewComments.ts +1137 -0
  327. package/src/mcp/roots.ts +217 -0
  328. package/src/mcp/scope.ts +82 -0
  329. package/src/mcp/selectMode.ts +207 -0
  330. package/src/mcp/server.ts +498 -0
  331. package/src/mcp/shared.ts +120 -0
  332. package/src/mcp/shell.ts +631 -0
  333. package/src/mcp/staleFix.ts +557 -0
  334. package/src/mcp/terraform/__snapshots__/moduleDocs.test.ts.snap +40 -0
  335. package/src/mcp/terraform/azurePrices.ts +38 -0
  336. package/src/mcp/terraform/baseline.ts +172 -0
  337. package/src/mcp/terraform/concernResult.ts +111 -0
  338. package/src/mcp/terraform/cost.ts +175 -0
  339. package/src/mcp/terraform/cspm.ts +326 -0
  340. package/src/mcp/terraform/currency.ts +354 -0
  341. package/src/mcp/terraform/decisions.ts +590 -0
  342. package/src/mcp/terraform/eidas.ts +134 -0
  343. package/src/mcp/terraform/evidence.ts +771 -0
  344. package/src/mcp/terraform/findings.ts +383 -0
  345. package/src/mcp/terraform/fixMemory.ts +253 -0
  346. package/src/mcp/terraform/governance.ts +231 -0
  347. package/src/mcp/terraform/hcl.ts +273 -0
  348. package/src/mcp/terraform/iacLanguages.ts +431 -0
  349. package/src/mcp/terraform/idleFloor.ts +304 -0
  350. package/src/mcp/terraform/keyless.ts +123 -0
  351. package/src/mcp/terraform/moduleDocs.ts +303 -0
  352. package/src/mcp/terraform/nativeRules.ts +152 -0
  353. package/src/mcp/terraform/nativeScan.ts +67 -0
  354. package/src/mcp/terraform/noiseProfile.ts +183 -0
  355. package/src/mcp/terraform/normalization.ts +265 -0
  356. package/src/mcp/terraform/oscal.ts +283 -0
  357. package/src/mcp/terraform/packs/azurerm-3-4.ts +382 -0
  358. package/src/mcp/terraform/packs/cloudflare-4-5.ts +114 -0
  359. package/src/mcp/terraform/paths.ts +59 -0
  360. package/src/mcp/terraform/plan.ts +377 -0
  361. package/src/mcp/terraform/planDrift.ts +520 -0
  362. package/src/mcp/terraform/policyAuthor.ts +886 -0
  363. package/src/mcp/terraform/prowlerOcsf.ts +380 -0
  364. package/src/mcp/terraform/refactor.ts +879 -0
  365. package/src/mcp/terraform/registry.ts +317 -0
  366. package/src/mcp/terraform/risk.ts +99 -0
  367. package/src/mcp/terraform/scanSession.ts +242 -0
  368. package/src/mcp/terraform/scannerCache.ts +86 -0
  369. package/src/mcp/terraform/scannerEgress.ts +141 -0
  370. package/src/mcp/terraform/scannerJson.ts +22 -0
  371. package/src/mcp/terraform/scanners.ts +1134 -0
  372. package/src/mcp/terraform/signing.ts +151 -0
  373. package/src/mcp/terraform/stateLocking.ts +106 -0
  374. package/src/mcp/terraform/subprocess.ts +102 -0
  375. package/src/mcp/terraform/suppressions.ts +551 -0
  376. package/src/mcp/terraform/taxonomy.ts +0 -0
  377. package/src/mcp/terraform/tfquery.ts +159 -0
  378. package/src/mcp/terraform/toolchainIntegrity.ts +151 -0
  379. package/src/mcp/terraform/tools/authorPolicy.ts +185 -0
  380. package/src/mcp/terraform/tools/detectPlanDrift.ts +279 -0
  381. package/src/mcp/terraform/tools/emitCost.ts +130 -0
  382. package/src/mcp/terraform/tools/emitSarif.ts +108 -0
  383. package/src/mcp/terraform/tools/fixMemory.ts +82 -0
  384. package/src/mcp/terraform/tools/infracostDiff.ts +110 -0
  385. package/src/mcp/terraform/tools/ingestExternalFindings.ts +259 -0
  386. package/src/mcp/terraform/tools/moduleLookup.ts +86 -0
  387. package/src/mcp/terraform/tools/moduleSearch.ts +46 -0
  388. package/src/mcp/terraform/tools/plan.ts +384 -0
  389. package/src/mcp/terraform/tools/providerUpgrade.ts +217 -0
  390. package/src/mcp/terraform/tools/readFindings.ts +138 -0
  391. package/src/mcp/terraform/tools/scan.ts +303 -0
  392. package/src/mcp/terraform/tools/validate.ts +160 -0
  393. package/src/mcp/terraform/tools/verifyRemediation.ts +190 -0
  394. package/src/mcp/terraform/tools/versionCurrency.ts +64 -0
  395. package/src/mcp/terraform/tools.ts +62 -0
  396. package/src/mcp/terraform/transformPacks.ts +594 -0
  397. package/src/mcp/terraform/types.ts +382 -0
  398. package/src/mcp/terraform/verification.ts +150 -0
  399. package/src/mcp/terraform/vex.ts +367 -0
  400. package/src/mcp/terraform/writeOnly.ts +252 -0
  401. package/src/mcp/terraform.ts +52 -0
  402. package/src/mcp/terratest.ts +215 -0
  403. package/src/mcp/untrustedContent.ts +126 -0
  404. package/src/mcp/upload.ts +123 -0
  405. package/src/models.ts +753 -0
  406. package/src/modes/address-reviews.ts +35 -0
  407. package/src/modes/assess.ts +27 -0
  408. package/src/modes/build.ts +86 -0
  409. package/src/modes/compliance-audit.ts +25 -0
  410. package/src/modes/cost-optimization.ts +36 -0
  411. package/src/modes/drift-detect.ts +31 -0
  412. package/src/modes/fix.ts +29 -0
  413. package/src/modes/incremental-review.ts +103 -0
  414. package/src/modes/index.ts +94 -0
  415. package/src/modes/modernize-deprecated.ts +36 -0
  416. package/src/modes/plan.ts +21 -0
  417. package/src/modes/policy-gate.ts +27 -0
  418. package/src/modes/prFormats.ts +325 -0
  419. package/src/modes/refactor.ts +74 -0
  420. package/src/modes/refresh-remediation.ts +40 -0
  421. package/src/modes/remediate-and-refactor.ts +42 -0
  422. package/src/modes/remediate.ts +78 -0
  423. package/src/modes/resolve-conflicts.ts +32 -0
  424. package/src/modes/review.ts +135 -0
  425. package/src/modes/summarize-pr.ts +42 -0
  426. package/src/modes/task.ts +26 -0
  427. package/src/modes/terraform-code-review.ts +68 -0
  428. package/src/modes/types.ts +17 -0
  429. package/src/modes/update-dependencies.ts +44 -0
  430. package/src/prep/index.ts +96 -0
  431. package/src/prep/installNodeDependencies.ts +251 -0
  432. package/src/prep/installPythonDependencies.ts +235 -0
  433. package/src/prep/types.ts +38 -0
  434. package/src/reviewQuality.ts +237 -0
  435. package/src/runCli.ts +335 -0
  436. package/src/skills/terraform-best-practices/SKILL.md +379 -0
  437. package/src/toolState.ts +241 -0
  438. package/src/utils/activity.ts +210 -0
  439. package/src/utils/agent.ts +245 -0
  440. package/src/utils/agentHangReport.ts +180 -0
  441. package/src/utils/annotations.ts +56 -0
  442. package/src/utils/apiFetch.ts +19 -0
  443. package/src/utils/apiKeys.ts +305 -0
  444. package/src/utils/apiUrl.ts +42 -0
  445. package/src/utils/assets.ts +123 -0
  446. package/src/utils/baseRefConfig.ts +254 -0
  447. package/src/utils/billingErrors.ts +210 -0
  448. package/src/utils/body.ts +168 -0
  449. package/src/utils/buildInfraweaverFooter.ts +104 -0
  450. package/src/utils/byokFallback.ts +137 -0
  451. package/src/utils/changeImpact.ts +330 -0
  452. package/src/utils/claudeSubscription.ts +93 -0
  453. package/src/utils/cli.ts +36 -0
  454. package/src/utils/cloudClient.ts +57 -0
  455. package/src/utils/cloudFetchCore.ts +139 -0
  456. package/src/utils/cloudReport.ts +316 -0
  457. package/src/utils/codexHome.ts +204 -0
  458. package/src/utils/codexOAuth.ts +154 -0
  459. package/src/utils/codexRefreshDetect.ts +36 -0
  460. package/src/utils/diffCoverage.ts +404 -0
  461. package/src/utils/env.ts +84 -0
  462. package/src/utils/errorReport.ts +94 -0
  463. package/src/utils/exitHandler.ts +35 -0
  464. package/src/utils/fixDoubleEscapedString.ts +9 -0
  465. package/src/utils/ghaCore.ts +13 -0
  466. package/src/utils/gitAuth.ts +268 -0
  467. package/src/utils/gitAuthServer.ts +186 -0
  468. package/src/utils/github.ts +676 -0
  469. package/src/utils/globals.ts +9 -0
  470. package/src/utils/humanEditCapture.ts +198 -0
  471. package/src/utils/infraweaverConfig.ts +202 -0
  472. package/src/utils/install.ts +279 -0
  473. package/src/utils/instructions.ts +640 -0
  474. package/src/utils/keylessOidc.ts +47 -0
  475. package/src/utils/leapingComment.ts +20 -0
  476. package/src/utils/learnings.ts +145 -0
  477. package/src/utils/learningsTruncate.ts +42 -0
  478. package/src/utils/lifecycle.ts +198 -0
  479. package/src/utils/log.ts +452 -0
  480. package/src/utils/modelResolver.ts +105 -0
  481. package/src/utils/moduleFetch.ts +138 -0
  482. package/src/utils/normalizeEnv.ts +106 -0
  483. package/src/utils/openCodeModels.ts +86 -0
  484. package/src/utils/openaiCompatible.ts +52 -0
  485. package/src/utils/opentofuMcp.ts +61 -0
  486. package/src/utils/overrides.ts +100 -0
  487. package/src/utils/packageManager.ts +257 -0
  488. package/src/utils/patchWorkflowRunFields.ts +173 -0
  489. package/src/utils/payload.ts +1206 -0
  490. package/src/utils/prSummary.ts +148 -0
  491. package/src/utils/presets.ts +105 -0
  492. package/src/utils/progressComment.ts +266 -0
  493. package/src/utils/providerErrors.ts +189 -0
  494. package/src/utils/proxyModel.ts +239 -0
  495. package/src/utils/rangeDiff.ts +182 -0
  496. package/src/utils/redact.ts +86 -0
  497. package/src/utils/registryAuth.ts +115 -0
  498. package/src/utils/remediationCommand.ts +144 -0
  499. package/src/utils/retry.ts +180 -0
  500. package/src/utils/reviewCleanup.ts +116 -0
  501. package/src/utils/run.ts +100 -0
  502. package/src/utils/runContext.ts +276 -0
  503. package/src/utils/runContextData.ts +121 -0
  504. package/src/utils/runErrorRenderer.ts +282 -0
  505. package/src/utils/runFixture.ts +91 -0
  506. package/src/utils/runLifecycle.ts +360 -0
  507. package/src/utils/runStartupLog.ts +67 -0
  508. package/src/utils/secrets.ts +208 -0
  509. package/src/utils/setup.ts +368 -0
  510. package/src/utils/shell.ts +132 -0
  511. package/src/utils/skills.ts +67 -0
  512. package/src/utils/subprocess.ts +474 -0
  513. package/src/utils/terraformMcp.ts +99 -0
  514. package/src/utils/time.ts +59 -0
  515. package/src/utils/timer.ts +72 -0
  516. package/src/utils/todoTracking.ts +168 -0
  517. package/src/utils/token.ts +294 -0
  518. package/src/utils/toolLicensing.ts +152 -0
  519. package/src/utils/toolSelection.ts +239 -0
  520. package/src/utils/toon.ts +76 -0
  521. package/src/utils/version.ts +10 -0
  522. package/src/utils/versioning.ts +44 -0
  523. package/src/utils/vertex.ts +94 -0
  524. package/src/utils/workflow.ts +25 -0
@@ -0,0 +1,96 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { installNodeDependencies } from "#app/prep/installNodeDependencies";
3
+ import { installPythonDependencies } from "#app/prep/installPythonDependencies";
4
+ import type { PrepDefinition, PrepOptions, PrepResult } from "#app/prep/types";
5
+ import { log } from "#app/utils/cli";
6
+ import { spawn } from "#app/utils/subprocess";
7
+
8
+ export type { PrepOptions, PrepResult } from "#app/prep/types";
9
+
10
+ // register all prep steps here
11
+ const prepSteps: PrepDefinition[] = [installNodeDependencies, installPythonDependencies];
12
+
13
+ /** tracked paths with staged or unstaged modifications. */
14
+ async function dirtyTrackedPaths(): Promise<Set<string>> {
15
+ const result = await spawn({
16
+ cmd: "git",
17
+ args: ["diff", "--name-only", "HEAD"],
18
+ env: process.env,
19
+ activityTimeout: 0,
20
+ });
21
+ if (result.exitCode !== 0) {
22
+ throw new Error(
23
+ `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`,
24
+ );
25
+ }
26
+ return new Set(result.stdout.split("\n").filter(Boolean));
27
+ }
28
+
29
+ /**
30
+ * discard tracked-file mods left by prep steps so the customer checkout is
31
+ * clean before agent tools run (#906: frozen installs run package lifecycle
32
+ * scripts that rewrite tracked generated files like the msw worker, and the
33
+ * resulting dirt makes `checkout_pr` refuse). only paths that were clean
34
+ * before prep are restored — pre-existing dirt and files the agent touched
35
+ * elsewhere are never clobbered. untracked files (e.g. node_modules) are
36
+ * unaffected.
37
+ */
38
+ async function restorePrepDirtiedFiles(preDirty: Set<string>): Promise<void> {
39
+ const dirtied = [...(await dirtyTrackedPaths())].filter((path) => !preDirty.has(path));
40
+ if (dirtied.length === 0) return;
41
+ const result = await spawn({
42
+ cmd: "git",
43
+ args: ["restore", "--staged", "--worktree", "--", ...dirtied],
44
+ env: process.env,
45
+ activityTimeout: 0,
46
+ });
47
+ if (result.exitCode !== 0) {
48
+ log.warning(
49
+ `» failed to restore ${dirtied.length} tracked file(s) modified by prep: ${result.stderr.trim() || "(no stderr)"}`,
50
+ );
51
+ return;
52
+ }
53
+ log.info(`» restored ${dirtied.length} tracked file(s) modified by prep: ${dirtied.join(", ")}`);
54
+ }
55
+
56
+ /**
57
+ * run all prep steps sequentially.
58
+ * failures are logged as warnings but don't stop the run.
59
+ */
60
+ export async function runPrepPhase(options: PrepOptions): Promise<PrepResult[]> {
61
+ log.debug("» starting prep phase...");
62
+ const startTime = performance.now();
63
+ const results: PrepResult[] = [];
64
+
65
+ // prep is non-mutating by contract; snapshot so any tracked drift from
66
+ // lifecycle scripts can be attributed to prep and restored, even when a
67
+ // step fails partway through.
68
+ const preDirty = await dirtyTrackedPaths();
69
+
70
+ try {
71
+ for (const step of prepSteps) {
72
+ const shouldRun = await step.shouldRun();
73
+ if (!shouldRun) {
74
+ log.debug(`» skipping ${step.name} (not applicable)`);
75
+ continue;
76
+ }
77
+
78
+ log.debug(`» running ${step.name}...`);
79
+ const result = await step.run(options);
80
+ results.push(result);
81
+
82
+ if (result.dependenciesInstalled) {
83
+ log.debug(`» ${step.name}: dependencies installed`);
84
+ } else if (result.issues.length > 0) {
85
+ log.warning(`» ${step.name}: ${result.issues[0]}`);
86
+ }
87
+ }
88
+ } finally {
89
+ await restorePrepDirtiedFiles(preDirty);
90
+ }
91
+
92
+ const totalDurationMs = performance.now() - startTime;
93
+ log.debug(`» prep phase completed (${Math.round(totalDurationMs)}ms)`);
94
+
95
+ return results;
96
+ }
@@ -0,0 +1,251 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { detect } from "package-manager-detector";
4
+ import { resolveCommand } from "package-manager-detector/commands";
5
+ import type {
6
+ NodePackageManager,
7
+ NodePrepResult,
8
+ PrepDefinition,
9
+ PrepOptions,
10
+ } from "#app/prep/types";
11
+ import { log } from "#app/utils/cli";
12
+ import {
13
+ ensurePackageManager,
14
+ resolvePackageManagerSpec,
15
+ } from "#app/utils/packageManager";
16
+ import { spawn } from "#app/utils/subprocess";
17
+
18
+ async function isCommandAvailable(command: string): Promise<boolean> {
19
+ const result = await spawn({
20
+ cmd: "which",
21
+ args: [command],
22
+ env: { PATH: process.env.PATH || "" },
23
+ });
24
+ return result.exitCode === 0;
25
+ }
26
+
27
+ /**
28
+ * Escape hatch for the one installer we cannot verify (see `installFallback`).
29
+ * Opt-in by name so enabling it is a deliberate, auditable choice.
30
+ */
31
+ const ALLOW_REMOTE_INSTALL_SCRIPT = "INFRAWEAVER_ALLOW_REMOTE_INSTALL_SCRIPT";
32
+
33
+ // fallback installers for managers corepack doesn't ship shims for.
34
+ // pnpm and yarn are handled by `ensurePackageManager` (corepack); bun and
35
+ // deno fall through to here because corepack ignores them.
36
+ async function installFallback(
37
+ name: NodePackageManager,
38
+ installSpec: string,
39
+ ): Promise<string | null> {
40
+ if (name === "npm") return null;
41
+
42
+ // Deno has no npm-installable shim, so upstream's documented path is
43
+ // `curl … | sh` — piping a remote script straight into a shell, with no
44
+ // pinned version and nothing to verify it against. That contradicts the
45
+ // supply-chain posture the rest of the engine holds (the agent CLIs are
46
+ // version-pinned AND digest-verified, see utils/install.ts), so it is
47
+ // fail-closed: we do not execute an unverifiable remote script by default.
48
+ //
49
+ // Pre-installing deno on the runner is the supported path — `isCommandAvailable`
50
+ // above short-circuits before we ever get here.
51
+ if (name === "deno" && process.env[ALLOW_REMOTE_INSTALL_SCRIPT] !== "true") {
52
+ return (
53
+ `refusing to install deno by piping a remote script into a shell ` +
54
+ `(curl https://deno.land/install.sh | sh) — it is neither version-pinned nor ` +
55
+ `integrity-verified. Install deno on the runner before this step (e.g. the ` +
56
+ `denoland/setup-deno action, which pins a version), or set ` +
57
+ `${ALLOW_REMOTE_INSTALL_SCRIPT}=true to accept the risk explicitly.`
58
+ );
59
+ }
60
+
61
+ log.info(
62
+ `» installing ${installSpec} via npm install -g (corepack does not manage ${name})`,
63
+ );
64
+ const args =
65
+ name === "deno"
66
+ ? ["-c", "curl -fsSL https://deno.land/install.sh | sh"]
67
+ : ["install", "-g", installSpec];
68
+ const cmd = name === "deno" ? "sh" : "npm";
69
+ if (name === "deno") {
70
+ log.warning(
71
+ `» ${ALLOW_REMOTE_INSTALL_SCRIPT}=true — executing an unverified remote install script`,
72
+ );
73
+ }
74
+ const result = await spawn({
75
+ cmd,
76
+ args,
77
+ env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
78
+ onStderr: (chunk) => process.stderr.write(chunk),
79
+ });
80
+ if (result.exitCode !== 0) {
81
+ return result.stderr || `failed to install ${name}`;
82
+ }
83
+ if (name === "deno") {
84
+ const denoPath = join(process.env.HOME || "", ".deno", "bin");
85
+ process.env.PATH = `${denoPath}:${process.env.PATH}`;
86
+ }
87
+ log.info(`» installed ${name}`);
88
+ return null;
89
+ }
90
+
91
+ export const installNodeDependencies: PrepDefinition = {
92
+ name: "installNodeDependencies",
93
+
94
+ shouldRun: () => {
95
+ const packageJsonPath = join(process.cwd(), "package.json");
96
+ return existsSync(packageJsonPath);
97
+ },
98
+
99
+ run: async (options: PrepOptions): Promise<NodePrepResult> => {
100
+ // prefer the project's declared spec (devEngines.packageManager wins over
101
+ // packageManager). fall back to lockfile detection when nothing is declared.
102
+ // restrict detect() to the lockfile strategy: `detected` here doubles as
103
+ // the lockfile-presence gate below, and the default strategy set also
104
+ // returns positives off `packageManager`/`devEngines` fields (which would
105
+ // mask the very case we're trying to detect — declared manager but no
106
+ // lockfile committed).
107
+ const declared = await resolvePackageManagerSpec(process.cwd());
108
+ const detected = await detect({
109
+ cwd: process.cwd(),
110
+ strategies: ["lockfile"],
111
+ });
112
+
113
+ const packageManager: NodePackageManager =
114
+ declared?.name ?? (detected?.name as NodePackageManager) ?? "npm";
115
+ const agent = detected?.agent ?? packageManager;
116
+
117
+ if (declared) {
118
+ log.info(
119
+ `» using ${packageManager}@${declared.version} from package.json (${declared.source})`,
120
+ );
121
+ } else if (detected) {
122
+ log.info(`» detected package manager: ${packageManager} (${agent})`);
123
+ } else {
124
+ log.info(`» no package manager declared, defaulting to npm`);
125
+ }
126
+
127
+ // provisioning: corepack for pnpm/yarn, legacy npm-install-g for bun/deno.
128
+ // when shell is disabled we can't run installers (they execute code), so
129
+ // we require the binary to already be on PATH.
130
+ if (!(await isCommandAvailable(packageManager))) {
131
+ if (options.ignoreScripts) {
132
+ return {
133
+ language: "node",
134
+ packageManager,
135
+ dependenciesInstalled: false,
136
+ issues: [
137
+ `${packageManager} is not available and cannot be installed when shell is disabled (would execute code)`,
138
+ ],
139
+ };
140
+ }
141
+
142
+ let provisioned = false;
143
+ if (declared)
144
+ provisioned = await ensurePackageManager({
145
+ spec: declared,
146
+ binDir: options.binDir,
147
+ });
148
+ if (!provisioned) {
149
+ const fallbackSpec = declared
150
+ ? `${declared.name}@${declared.version}`
151
+ : packageManager;
152
+ const installError = await installFallback(
153
+ packageManager,
154
+ fallbackSpec,
155
+ );
156
+ if (installError) {
157
+ return {
158
+ language: "node",
159
+ packageManager,
160
+ dependenciesInstalled: false,
161
+ issues: [installError],
162
+ };
163
+ }
164
+ }
165
+ } else if (declared) {
166
+ // PATH already has the binary — but it may be the wrong version.
167
+ // ensurePackageManager is idempotent (caches on `--version` match) so
168
+ // this is cheap when main.ts already activated it.
169
+ await ensurePackageManager({ spec: declared, binDir: options.binDir });
170
+ }
171
+
172
+ // frozen-lockfile install only. eager prep is non-mutating by contract:
173
+ // we run it before the agent starts and any artifact it leaves in the
174
+ // tree (e.g. a generated `package-lock.json`) trips the dirty-tree
175
+ // post-run gate and produces a spurious PR. `frozen` commands
176
+ // (`npm ci`, `pnpm install --frozen-lockfile`, etc.) were assumed to
177
+ // fail cleanly without a lockfile — that assumption is false for
178
+ // pnpm 11.1.1 against a no-deps `package.json` (it silently writes an
179
+ // empty `pnpm-lock.yaml` despite the flag). gate on `detect()` having
180
+ // found a lockfile; it walks up the tree (so monorepo subpackages
181
+ // resolve to the workspace-root lockfile) and recognizes every
182
+ // manager's accepted lockfile variants (`bun.lockb` + `bun.lock`,
183
+ // `npm-shrinkwrap.json` + `package-lock.json`, etc.). when none is
184
+ // present, the project either has no installable dependencies or
185
+ // opts into install via a `setup` lifecycle hook
186
+ // (`action/utils/lifecycle.ts`); either way, eager prep should skip.
187
+ if (!detected) {
188
+ log.info(
189
+ `» skipping ${packageManager} install: no lockfile found (would otherwise risk lockfile drift)`,
190
+ );
191
+ return {
192
+ language: "node",
193
+ packageManager,
194
+ dependenciesInstalled: false,
195
+ issues: [],
196
+ };
197
+ }
198
+
199
+ const resolved = resolveCommand(agent, "frozen", []);
200
+ if (!resolved) {
201
+ return {
202
+ language: "node",
203
+ packageManager,
204
+ dependenciesInstalled: false,
205
+ issues: [`no frozen-install command available for ${agent}`],
206
+ };
207
+ }
208
+
209
+ // SECURITY: when shell is disabled, suppress lifecycle scripts to prevent
210
+ // agents from injecting arbitrary code execution via package.json scripts
211
+ if (options.ignoreScripts) {
212
+ resolved.args.push("--ignore-scripts");
213
+ log.info("» --ignore-scripts enabled (shell disabled)");
214
+ }
215
+
216
+ const fullCommand = `${resolved.command} ${resolved.args.join(" ")}`;
217
+ log.info(`» running: ${fullCommand}`);
218
+ const result = await spawn({
219
+ cmd: resolved.command,
220
+ args: resolved.args,
221
+ env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
222
+ });
223
+
224
+ const output = [result.stdout, result.stderr]
225
+ .filter(Boolean)
226
+ .join("\n")
227
+ .trim();
228
+ if (output) {
229
+ log.startGroup(`${fullCommand} output`);
230
+ log.info(output);
231
+ log.endGroup();
232
+ }
233
+
234
+ if (result.exitCode !== 0) {
235
+ const errorMessage = output || `exited with code ${result.exitCode}`;
236
+ return {
237
+ language: "node",
238
+ packageManager,
239
+ dependenciesInstalled: false,
240
+ issues: [`\`${fullCommand}\` failed:\n${errorMessage}`],
241
+ };
242
+ }
243
+
244
+ return {
245
+ language: "node",
246
+ packageManager,
247
+ dependenciesInstalled: true,
248
+ issues: [],
249
+ };
250
+ },
251
+ };
@@ -0,0 +1,235 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import type {
4
+ PrepDefinition,
5
+ PrepOptions,
6
+ PythonPackageManager,
7
+ PythonPrepResult,
8
+ } from "#app/prep/types";
9
+ import { log } from "#app/utils/cli";
10
+ import { spawn } from "#app/utils/subprocess";
11
+
12
+ interface PythonConfig {
13
+ file: string;
14
+ tool: PythonPackageManager;
15
+ // non-empty: the first element is the executable, the rest are args
16
+ installCmd: [string, ...string[]];
17
+ }
18
+
19
+ // python dependency file patterns in priority order
20
+ const PYTHON_CONFIGS: PythonConfig[] = [
21
+ {
22
+ file: "requirements.txt",
23
+ tool: "pip",
24
+ installCmd: ["pip", "install", "-r", "requirements.txt"],
25
+ },
26
+ {
27
+ file: "pyproject.toml",
28
+ tool: "pip",
29
+ installCmd: ["pip", "install", "."],
30
+ },
31
+ {
32
+ file: "Pipfile",
33
+ tool: "pipenv",
34
+ installCmd: ["pipenv", "install"],
35
+ },
36
+ {
37
+ file: "Pipfile.lock",
38
+ tool: "pipenv",
39
+ installCmd: ["pipenv", "sync"],
40
+ },
41
+ {
42
+ file: "poetry.lock",
43
+ tool: "poetry",
44
+ installCmd: ["poetry", "install", "--no-interaction"],
45
+ },
46
+ {
47
+ file: "setup.py",
48
+ tool: "pip",
49
+ installCmd: ["pip", "install", "-e", "."],
50
+ },
51
+ ];
52
+
53
+ /**
54
+ * A root `pyproject.toml` no longer implies a pip-installable package. When it
55
+ * lacks a `[build-system]` table (PEP 517/518) it is a tool-config / PEP 735
56
+ * dependency-groups file (e.g. ruff/mypy under uv), and `pip install .` falls
57
+ * back to legacy setuptools flat-layout discovery, which hard-fails on monorepos
58
+ * ("Multiple top-level packages discovered in a flat-layout"). The gate is a
59
+ * heuristic proxy for "scaffolded as a distributable package": pip treats a
60
+ * pyproject without `[build-system]` as the legacy setuptools backend and would
61
+ * proceed, so we trade a rare false-negative to kill the common tooling-only
62
+ * false positive. Unreadable → treat as not installable (skip, don't crash prep).
63
+ */
64
+ function pyprojectDeclaresBuildSystem(cwd: string): boolean {
65
+ try {
66
+ const content = readFileSync(join(cwd, "pyproject.toml"), "utf8");
67
+ return /^\s*\[build-system\]/m.test(content);
68
+ } catch {
69
+ return false;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Whether a detected config file should actually drive an install. Everything
75
+ * applies except a `pyproject.toml` with no build system — that one is skipped
76
+ * so a tooling-only pyproject doesn't trigger a doomed `pip install .`.
77
+ */
78
+ function configApplies(config: PythonConfig, cwd: string): boolean {
79
+ if (config.file === "pyproject.toml") return pyprojectDeclaresBuildSystem(cwd);
80
+ return true;
81
+ }
82
+
83
+ // tool install commands (via pip). Each command is non-empty (executable + args).
84
+ const TOOL_INSTALL_COMMANDS: Record<string, [string, ...string[]]> = {
85
+ pipenv: ["pip", "install", "pipenv"],
86
+ poetry: ["pip", "install", "poetry"],
87
+ };
88
+
89
+ async function isCommandAvailable(command: string): Promise<boolean> {
90
+ const result = await spawn({
91
+ cmd: "which",
92
+ args: [command],
93
+ env: { PATH: process.env.PATH || "" },
94
+ });
95
+ return result.exitCode === 0;
96
+ }
97
+
98
+ async function installTool(name: string): Promise<string | null> {
99
+ const installCmd = TOOL_INSTALL_COMMANDS[name];
100
+ if (!installCmd) {
101
+ // tool doesn't need installation (e.g., pip)
102
+ return null;
103
+ }
104
+
105
+ log.info(`» installing ${name}...`);
106
+ const [cmd, ...args] = installCmd;
107
+ const result = await spawn({
108
+ cmd,
109
+ args,
110
+ env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
111
+ onStderr: (chunk) => process.stderr.write(chunk),
112
+ });
113
+
114
+ if (result.exitCode !== 0) {
115
+ return result.stderr || `failed to install ${name}`;
116
+ }
117
+
118
+ log.info(`» installed ${name}`);
119
+ return null;
120
+ }
121
+
122
+ export const installPythonDependencies: PrepDefinition = {
123
+ name: "installPythonDependencies",
124
+
125
+ shouldRun: async () => {
126
+ // check if python is available
127
+ const hasPython = (await isCommandAvailable("python3")) || (await isCommandAvailable("python"));
128
+ if (!hasPython) {
129
+ return false;
130
+ }
131
+
132
+ // check if any python config file exists AND actually drives an install
133
+ // (a tooling-only pyproject.toml without a [build-system] table does not).
134
+ const cwd = process.cwd();
135
+ return PYTHON_CONFIGS.some(
136
+ (config) => existsSync(join(cwd, config.file)) && configApplies(config, cwd),
137
+ );
138
+ },
139
+
140
+ run: async (options: PrepOptions): Promise<PythonPrepResult> => {
141
+ const cwd = process.cwd();
142
+
143
+ // find the first matching config that actually drives an install (skips a
144
+ // tooling-only pyproject.toml, letting a lower-priority config win instead).
145
+ const config = PYTHON_CONFIGS.find(
146
+ (c) => existsSync(join(cwd, c.file)) && configApplies(c, cwd),
147
+ );
148
+ if (!config) {
149
+ return {
150
+ language: "python",
151
+ packageManager: "pip",
152
+ configFile: "unknown",
153
+ dependenciesInstalled: false,
154
+ issues: ["no python config file found"],
155
+ };
156
+ }
157
+
158
+ log.info(`» detected python config: ${config.file} (using ${config.tool})`);
159
+
160
+ // SECURITY: when shell is disabled, skip ALL python dependency installation.
161
+ // every python install path can potentially execute arbitrary code:
162
+ // - setup.py / pyproject.toml: directly execute build backends
163
+ // - requirements.txt: can contain "-e ." or local path references that
164
+ // trigger setup.py execution
165
+ // - Pipfile/poetry.lock: can contain path dependencies pointing to local
166
+ // directories with malicious setup.py
167
+ // - source distributions from PyPI also execute setup.py
168
+ // there is no equivalent of npm's --ignore-scripts for pip.
169
+ if (options.ignoreScripts) {
170
+ log.info(
171
+ `» skipping python install (shell disabled, python packages can execute arbitrary code)`,
172
+ );
173
+ return {
174
+ language: "python",
175
+ packageManager: config.tool,
176
+ configFile: config.file,
177
+ dependenciesInstalled: false,
178
+ issues: [
179
+ `skipped: python dependency installation can execute arbitrary code (setup.py, build backends, local path references), which is blocked when shell is disabled`,
180
+ ],
181
+ };
182
+ }
183
+
184
+ // check if the tool is available, install if needed
185
+ const isAvailable = await isCommandAvailable(config.tool);
186
+ if (!isAvailable) {
187
+ log.info(`» ${config.tool} not found, attempting to install...`);
188
+ const installError = await installTool(config.tool);
189
+ if (installError) {
190
+ return {
191
+ language: "python",
192
+ packageManager: config.tool,
193
+ configFile: config.file,
194
+ dependenciesInstalled: false,
195
+ issues: [installError],
196
+ };
197
+ }
198
+ }
199
+
200
+ // run the install command
201
+ const [cmd, ...args] = config.installCmd;
202
+ const fullCommand = `${cmd} ${args.join(" ")}`;
203
+ log.info(`» running: ${fullCommand}`);
204
+ const result = await spawn({
205
+ cmd,
206
+ args,
207
+ env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
208
+ });
209
+
210
+ const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
211
+ if (output) {
212
+ log.startGroup(`${fullCommand} output`);
213
+ log.info(output);
214
+ log.endGroup();
215
+ }
216
+
217
+ if (result.exitCode !== 0) {
218
+ return {
219
+ language: "python",
220
+ packageManager: config.tool,
221
+ configFile: config.file,
222
+ dependenciesInstalled: false,
223
+ issues: [output || `${cmd} exited with code ${result.exitCode}`],
224
+ };
225
+ }
226
+
227
+ return {
228
+ language: "python",
229
+ packageManager: config.tool,
230
+ configFile: config.file,
231
+ dependenciesInstalled: true,
232
+ issues: [],
233
+ };
234
+ },
235
+ };
@@ -0,0 +1,38 @@
1
+ interface PrepResultBase {
2
+ dependenciesInstalled: boolean;
3
+ issues: string[];
4
+ }
5
+
6
+ export type NodePackageManager = "npm" | "pnpm" | "yarn" | "bun" | "deno";
7
+
8
+ export interface NodePrepResult extends PrepResultBase {
9
+ language: "node";
10
+ packageManager: NodePackageManager;
11
+ }
12
+
13
+ export type PythonPackageManager = "pip" | "pipenv" | "poetry";
14
+
15
+ export interface PythonPrepResult extends PrepResultBase {
16
+ language: "python";
17
+ packageManager: PythonPackageManager;
18
+ configFile: string;
19
+ }
20
+
21
+ export interface UnknownLanguagePrepResult extends PrepResultBase {
22
+ language: "unknown";
23
+ }
24
+
25
+ export type PrepResult = NodePrepResult | PythonPrepResult | UnknownLanguagePrepResult;
26
+
27
+ export type PrepOptions = {
28
+ /** when true, lifecycle scripts (postinstall, etc.) are suppressed */
29
+ ignoreScripts: boolean;
30
+ /** directory the corepack shim is installed into (see `packageManagerBinDir`) */
31
+ binDir: string;
32
+ };
33
+
34
+ export interface PrepDefinition {
35
+ name: string;
36
+ shouldRun: () => Promise<boolean> | boolean;
37
+ run: (options: PrepOptions) => Promise<PrepResult>;
38
+ }