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
package/src/main.ts ADDED
@@ -0,0 +1,815 @@
1
+ // changes to tool permissions should be reflected in wiki/granular-tools.md
2
+
3
+ import { existsSync, readdirSync } from "node:fs";
4
+ import { readFile } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ import { agents } from "#app/agents/index";
7
+ import {
8
+ createTokenQuota,
9
+ RUN_TOKEN_QUOTA_INPUT,
10
+ resolveRunTokenQuota,
11
+ } from "#app/agents/tokenQuota";
12
+ import { reportProgress } from "#app/mcp/comment";
13
+ import { startInstallation } from "#app/mcp/dependencies";
14
+ import {
15
+ startMcpHttpServer,
16
+ subagentDeniedToolNames,
17
+ type ToolContext,
18
+ } from "#app/mcp/server";
19
+ import { coerceLibrary, loadFixMemory } from "#app/mcp/terraform/fixMemory";
20
+ import { coerceNoiseProfile } from "#app/mcp/terraform/noiseProfile";
21
+ import { scanSessionOf } from "#app/mcp/terraform/scanSession";
22
+ import { coerceProvenTransforms } from "#app/mcp/terraform/transformPacks";
23
+ import { computeModes } from "#app/modes";
24
+ import {
25
+ mergeRemediationModeInstructions,
26
+ mergeReviewModeInstructions,
27
+ } from "#app/reviewQuality";
28
+ import { initToolState } from "#app/toolState";
29
+ import {
30
+ type ActivityTimeout,
31
+ AGENT_ACTIVITY_TIMEOUT_MS,
32
+ createProcessOutputActivityTimeout,
33
+ DEFAULT_ACTIVITY_CHECK_INTERVAL_MS,
34
+ } from "#app/utils/activity";
35
+ import { isBackendConfigured } from "#app/utils/apiUrl";
36
+ import { resolveBody } from "#app/utils/body";
37
+ import { log } from "#app/utils/cli";
38
+ import { INFRAWEAVER_DATA_DIR } from "#app/utils/codexHome";
39
+ import { recordDiffReadFromToolUse } from "#app/utils/diffCoverage";
40
+ import { onExitSignal } from "#app/utils/exitHandler";
41
+ import { resolveGit, setGitAuthServer } from "#app/utils/gitAuth";
42
+ import { startGitAuthServer } from "#app/utils/gitAuthServer";
43
+ import {
44
+ createOctokit,
45
+ writeGitHubUsageSummaryToFile,
46
+ } from "#app/utils/github";
47
+ import { resolveInstructions } from "#app/utils/instructions";
48
+ import { persistLearnings, seedLearningsFile } from "#app/utils/learnings";
49
+ import {
50
+ describeSetupFailure,
51
+ executeLifecycleHook,
52
+ } from "#app/utils/lifecycle";
53
+ import {
54
+ captureModelAuthority,
55
+ resolveRunModel,
56
+ } from "#app/utils/modelResolver";
57
+ import { normalizeEnv } from "#app/utils/normalizeEnv";
58
+ import { applyOverrides } from "#app/utils/overrides";
59
+ import {
60
+ ensurePackageManager,
61
+ packageManagerBinDir,
62
+ resolvePackageManagerSpec,
63
+ } from "#app/utils/packageManager";
64
+ import {
65
+ aggregateUsage,
66
+ patchWorkflowRunFields,
67
+ } from "#app/utils/patchWorkflowRunFields";
68
+ import {
69
+ resolveOutputSchema,
70
+ resolvePayload,
71
+ resolvePromptInput,
72
+ } from "#app/utils/payload";
73
+ import {
74
+ fetchPreviousSnapshot,
75
+ persistSummary,
76
+ seedSummaryFile,
77
+ } from "#app/utils/prSummary";
78
+ import { handleAgentResult } from "#app/utils/run";
79
+ import { resolveRunContextData } from "#app/utils/runContextData";
80
+ import { renderRunError } from "#app/utils/runErrorRenderer";
81
+ import {
82
+ finalizeSuccessRun,
83
+ persistRunArtifacts,
84
+ writeRunErrorOutputs,
85
+ } from "#app/utils/runLifecycle";
86
+ import { logRunStartup } from "#app/utils/runStartupLog";
87
+ import { setEnvAllowlist } from "#app/utils/secrets";
88
+ import {
89
+ createTempDirectory,
90
+ setupGit,
91
+ wipeRunnerLeakSurface,
92
+ } from "#app/utils/setup";
93
+ import { killTrackedChildren } from "#app/utils/subprocess";
94
+ import { resolveTimeoutMs, TIMEOUT_DISABLED } from "#app/utils/time";
95
+ import { Timer } from "#app/utils/timer";
96
+ import { createTodoTracker } from "#app/utils/todoTracking";
97
+ import {
98
+ getGitHubInstallationToken,
99
+ getJobToken,
100
+ getMcpTokenRefresh,
101
+ resolveTokens,
102
+ } from "#app/utils/token";
103
+ import {
104
+ cleanupVertexCredentials,
105
+ materializeVertexCredentials,
106
+ type VertexCredentials,
107
+ } from "#app/utils/vertex";
108
+ import { resolveRun } from "#app/utils/workflow";
109
+
110
+ export { Inputs } from "#app/utils/payload";
111
+
112
+ export interface MainResult {
113
+ success: boolean;
114
+ output?: string | undefined;
115
+ error?: string | undefined;
116
+ result?: string | undefined;
117
+ }
118
+
119
+ export async function main(): Promise<MainResult> {
120
+ // normalize env var names to uppercase (handles case-insensitive workflow files)
121
+ normalizeEnv();
122
+
123
+ // apply caller-supplied env overrides — JSON object forwarded as the
124
+ // UNSAFE_OVERRIDES env var (NOT a `with:` input). gated by `actions:write`
125
+ // on the repo and refuses integrity-critical names; see utils/overrides.ts
126
+ // for the deny-list and wiki/e2e-testing.md for usage + threat model.
127
+ // the `unsafe` prefix is intentional: GH echoes the env-block value in the
128
+ // step-header log, so the raw JSON is visible to anyone with `actions:read`.
129
+ const overridesRaw = process.env.UNSAFE_OVERRIDES ?? "";
130
+ if (overridesRaw.trim()) {
131
+ const result = applyOverrides({ raw: overridesRaw, env: process.env });
132
+ if (result.applied.length > 0) {
133
+ log.info(
134
+ `» applied ${result.applied.length} env override(s): ${result.applied.join(", ")}`,
135
+ );
136
+ }
137
+ if (result.denied.length > 0) {
138
+ log.warning(
139
+ `» refused to override ${result.denied.length} protected env var(s): ${result.denied.join(", ")}`,
140
+ );
141
+ }
142
+ }
143
+
144
+ // write usage summary on SIGINT/SIGTERM so the worker can read it after sandbox.exec
145
+ const usageSummaryPath = process.env.INFRAWEAVER_USAGE_SUMMARY_PATH;
146
+ if (usageSummaryPath) {
147
+ onExitSignal(() => writeGitHubUsageSummaryToFile(usageSummaryPath));
148
+ }
149
+
150
+ const timer = new Timer();
151
+ let activityTimeout: ActivityTimeout | null = null;
152
+ let safetyNetTimer: NodeJS.Timeout | undefined;
153
+
154
+ // parse prompt early to extract progressComment for toolState
155
+ const resolvedPromptInput = resolvePromptInput();
156
+
157
+ const toolState = initToolState({
158
+ progressComment:
159
+ typeof resolvedPromptInput !== "string"
160
+ ? resolvedPromptInput.progressComment
161
+ : undefined,
162
+ });
163
+
164
+ // resolve and fingerprint git binary before any agent code runs
165
+ resolveGit();
166
+
167
+ // get job token for initial API calls
168
+ const jobToken = getJobToken();
169
+ const initialOctokit = createOctokit(jobToken);
170
+ const runContext = await resolveRunContextData({
171
+ octokit: initialOctokit,
172
+ token: jobToken,
173
+ });
174
+ timer.checkpoint("runContextData");
175
+
176
+ // Called for its side effect: `createTempDirectory()` sets INFRAWEAVER_TEMP_DIR,
177
+ // which `installFromNpmTarball` reads when the opencode CLI install runs below
178
+ // for BYOK introspection, and which agent + mcp server setup further down also
179
+ // consume. The returned path isn't needed directly here.
180
+ createTempDirectory();
181
+
182
+ // install OpenCode (fs-cached, so the duplicate call inside the opencode
183
+ // agent's run() is a no-op), then capture the BYOK model authority. The
184
+ // baseline→Codex-auth→authorized ordering that used to live inline here is
185
+ // owned by captureModelAuthority; the returned set feeds resolveRunModel.
186
+ const opencodeCliPath = await agents.opencode.install();
187
+ const authorizedModels = captureModelAuthority(opencodeCliPath);
188
+
189
+ // configure env allowlist for subprocess filtering
190
+ if (runContext.repoSettings.envAllowlist) {
191
+ setEnvAllowlist(runContext.repoSettings.envAllowlist);
192
+ }
193
+
194
+ // resolve payload to determine shell permission. The org's Cloud "required
195
+ // controls" policy (org-scoped, from run-context) is merged into the gate here.
196
+ const payload = resolvePayload(
197
+ resolvedPromptInput,
198
+ runContext.repoSettings,
199
+ runContext.requiredControls,
200
+ runContext.moduleCredentials,
201
+ );
202
+ toolState.model = payload.model;
203
+ // user-facing language for the fixed comment/footer chrome — mirrored onto the
204
+ // tool state so surfaces that only hold a ToolState (errorReport) localize too.
205
+ toolState.language = payload.language;
206
+ if (payload.event.trigger === "pull_request_synchronize") {
207
+ toolState.beforeSha = payload.event.before_sha;
208
+ }
209
+
210
+ // §5.12 seed the proven-fix library so the terraform_fix_memory tool can offer
211
+ // proven priors during Remediate: the org's Cloud fleet library (has reuse
212
+ // stats) first, then any committed local `.infraweaver.fix-memory.json`. Deduped
213
+ // by finding-type at match time (Cloud wins on a tie). Only when opted in.
214
+ if (payload.fixMemory) {
215
+ scanSessionOf(toolState).fixMemoryLibrary = [
216
+ ...coerceLibrary(runContext.provenFixes),
217
+ ...loadFixMemory(payload.cwd),
218
+ ];
219
+ }
220
+
221
+ // G7 seed the org's fleet-wide dismissal record so terraform_scan can down-rank
222
+ // finding types this org has repeatedly waived, with the reasons shown. Not
223
+ // opt-in like fix memory: it changes only the ORDER of a report that already
224
+ // contains everything, so there is nothing to consent to. Empty for OSS and
225
+ // unentitled runs, which then rank exactly as they do today.
226
+ scanSessionOf(toolState).noiseProfile = coerceNoiseProfile(
227
+ runContext.noiseProfile,
228
+ );
229
+
230
+ // TC-2.2 seed the org's proven-transform counters so terraform_provider_upgrade
231
+ // can say how widely a migration has already planned cleanly across the fleet.
232
+ // Not opt-in for the same reason as the noise profile: it adds a count beside a
233
+ // transform that is reported either way, and never decides anything.
234
+ scanSessionOf(toolState).provenTransformLibrary = coerceProvenTransforms(
235
+ runContext.provenTransforms,
236
+ );
237
+
238
+ // resolve tokens first — acquireNewToken needs OIDC env vars for token exchange
239
+ await using tokenRef = await resolveTokens({ push: payload.push });
240
+
241
+ // wipe the GHA runner's known credential leak surface inside $RUNNER_TEMP
242
+ // before the agent spawns. our installation token is already in memory
243
+ // (tokenRef above), and setupGit's includeIf strip handles the matching
244
+ // dangling references in the user's .git/config. see wipeRunnerLeakSurface
245
+ // for the leak inventory and threat model.
246
+ wipeRunnerLeakSurface();
247
+
248
+ // clear OIDC env vars to prevent the agent from minting tokens. this is NOT
249
+ // gated on shell mode: `shell: "enabled"` widens the command surface, it does
250
+ // not grant credential access, and resolveTokens() above already took what the
251
+ // engine needs. inheritEnv() also denies the pair, so this is defence in depth.
252
+ delete process.env.ACTIONS_ID_TOKEN_REQUEST_URL;
253
+ delete process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
254
+
255
+ // create octokit with MCP token for GitHub API calls. the refresh fn lets it
256
+ // re-acquire a fresh token on a 401 (post-mint replication window). see #891.
257
+ const octokit = createOctokit(tokenRef.mcpToken, getMcpTokenRefresh());
258
+
259
+ const runInfo = await resolveRun({ octokit });
260
+ let toolContext: ToolContext | undefined;
261
+ let progressCallbackDisabled = false;
262
+ let todoTracker: ReturnType<typeof createTodoTracker> | undefined;
263
+ let vertexCredentials: VertexCredentials | undefined;
264
+
265
+ try {
266
+ if (payload.cwd && process.cwd() !== payload.cwd) {
267
+ process.chdir(payload.cwd);
268
+ }
269
+
270
+ const tmpdir = createTempDirectory();
271
+
272
+ // resolve body - fetches body_html and converts to markdown if images present
273
+ // this ensures agents receive markdown with working signed image URLs
274
+ const originalBody = payload.event.body;
275
+ const resolvedBody = await resolveBody({
276
+ event: payload.event,
277
+ octokit,
278
+ repo: runContext.repo,
279
+ tmpdir,
280
+ githubToken: tokenRef.mcpToken,
281
+ });
282
+ if (resolvedBody !== originalBody) {
283
+ payload.event.body = resolvedBody;
284
+ // also update prompt if original body was included there
285
+ if (originalBody && payload.prompt.includes(originalBody)) {
286
+ payload.prompt = payload.prompt
287
+ .split(originalBody)
288
+ .join(resolvedBody ?? "");
289
+ }
290
+ }
291
+
292
+ await using gitAuthServer = await startGitAuthServer(tmpdir);
293
+ setGitAuthServer(gitAuthServer);
294
+
295
+ // Resolve the model + auth in one call: BYOK gate → managed EU Bedrock proxy
296
+ // overlay → env patch → api-key validation. Surfaces a BillingError if the org
297
+ // has no payment method; keeps the free fallback if the proxy isn't live.
298
+ const routed = await resolveRunModel({
299
+ slug: payload.model,
300
+ plan: runContext.plan,
301
+ credential: runContext.apiToken,
302
+ authorized: authorizedModels,
303
+ repo: { owner: runContext.repo.owner, name: runContext.repo.name },
304
+ });
305
+ for (const warning of routed.warnings) {
306
+ log.warning(warning);
307
+ }
308
+ if (routed.fallback) {
309
+ toolState.modelFallback = { from: routed.fallback.from };
310
+ }
311
+
312
+ const resolvedModel = routed.model;
313
+ const effectiveSlug = routed.effectiveSlug;
314
+ const agent = routed.agent;
315
+
316
+ vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
317
+
318
+ // surface the effective model in comment/review footers. payload.model is
319
+ // just the stored slug (often undefined when the agent auto-selects).
320
+ toolState.model = resolvedModel ?? effectiveSlug;
321
+
322
+ await setupGit({
323
+ gitToken: tokenRef.gitToken,
324
+ owner: runContext.repo.owner,
325
+ name: runContext.repo.name,
326
+ octokit,
327
+ toolState,
328
+ shell: payload.shell,
329
+ postCheckoutScript: runContext.repoSettings.postCheckoutScript,
330
+ });
331
+ timer.checkpoint("git");
332
+
333
+ // pin the project's package manager via corepack BEFORE the setup hook
334
+ // runs. without this, a customer setup script like `npm i -g pnpm &&
335
+ // pnpm install` installs whatever pnpm is "latest" today and writes
336
+ // unrelated lockfile drift (e.g. the `packageManagerDependencies`
337
+ // block pnpm 11.3 added) into our commit — see #844. resolution
338
+ // honors pnpm 11+ precedence (`devEngines.packageManager` over
339
+ // `packageManager`); failure is non-fatal — we fall back to whatever
340
+ // is on PATH with a warning. the shim lands in a private bin dir
341
+ // (prepended to PATH), not the node bin dir, so a setup `npm i -g pnpm`
342
+ // can't collide with it.
343
+ const pmSpec = await resolvePackageManagerSpec(process.cwd());
344
+ if (pmSpec) {
345
+ await ensurePackageManager({
346
+ spec: pmSpec,
347
+ binDir: packageManagerBinDir(tmpdir),
348
+ });
349
+ }
350
+ timer.checkpoint("packageManager");
351
+
352
+ // execute the setup lifecycle hook (runs once at initialization). best-effort:
353
+ // a failure no longer aborts the run — we warn the operator and surface it to
354
+ // the agent via the SETUP HOOK FAILED banner so it can verify the env and adapt.
355
+ const setupHook = await executeLifecycleHook({
356
+ event: "setup",
357
+ script: runContext.repoSettings.setupScript,
358
+ normalizeWorkingTreeAfter: true,
359
+ });
360
+ if (setupHook.warning) {
361
+ log.warning(setupHook.warning);
362
+ }
363
+ timer.checkpoint("lifecycleHooks::setup");
364
+
365
+ const agentId = agent.name;
366
+ const modes = [...computeModes(agentId), ...runContext.repoSettings.modes];
367
+
368
+ const outputSchema = resolveOutputSchema();
369
+
370
+ // mcpServerUrl and tmpdir are set after server starts
371
+ toolContext = {
372
+ agentId,
373
+ repo: runContext.repo,
374
+ payload,
375
+ octokit,
376
+ // a getter (not the static mint-time value) so raw-token consumers that
377
+ // bypass octokit's refresh hook — issue/PR comment GETs, prSummary,
378
+ // selectMode, install — pick up a mid-run re-minted MCP token. see #891.
379
+ get githubInstallationToken() {
380
+ return getGitHubInstallationToken();
381
+ },
382
+ // live getter, same reason as githubInstallationToken above: after a
383
+ // mid-run git-token re-mint the old token is revoked, so push/tags/delete/
384
+ // fetch tools reading ctx.gitToken must see the current one, never a
385
+ // stale snapshot captured at ctx-construction time. see #964.
386
+ get gitToken() {
387
+ return tokenRef.gitToken;
388
+ },
389
+ refreshGitToken: tokenRef.refreshGitToken,
390
+ apiToken: runContext.apiToken,
391
+ modes,
392
+ postCheckoutScript: runContext.repoSettings.postCheckoutScript,
393
+ prepushScript: runContext.repoSettings.prepushScript,
394
+ prApproveEnabled: runContext.repoSettings.prApproveEnabled,
395
+ // workflow-file review policy / FP precedents compose with the
396
+ // backend-provided per-mode instructions (both owner-controlled). The two
397
+ // mergers stack — review instructions onto the Review key, then the
398
+ // remediation/refactor addenda onto their mode keys — so all four
399
+ // instruction inputs land additively; no engine-owned prompt is replaced.
400
+ modeInstructions: mergeRemediationModeInstructions(
401
+ mergeReviewModeInstructions(runContext.repoSettings.modeInstructions, {
402
+ reviewInstructions: payload.reviewInstructions,
403
+ fpFilteringInstructions: payload.fpFilteringInstructions,
404
+ }),
405
+ {
406
+ remediationInstructions: payload.remediationInstructions,
407
+ refactorInstructions: payload.refactorInstructions,
408
+ },
409
+ ),
410
+ toolState,
411
+ runId: runInfo.runId,
412
+ mcpServerUrl: "",
413
+ mcpServerToken: "",
414
+ tmpdir,
415
+ oss: runContext.oss,
416
+ plan: runContext.plan,
417
+ resolvedModel,
418
+ };
419
+ await using mcpHttpServer = await startMcpHttpServer(toolContext, {
420
+ outputSchema,
421
+ });
422
+ toolContext.mcpServerUrl = mcpHttpServer.url;
423
+ toolContext.mcpServerToken = mcpHttpServer.token;
424
+ log.info(`» MCP server started at ${mcpHttpServer.url}`);
425
+ timer.checkpoint("mcpServer");
426
+
427
+ // derive the subagent deny set from the same tool registry the server just
428
+ // registered (each tool's `mutates` flag), to embed into the agent's gate.
429
+ const subagentDeniedTools = subagentDeniedToolNames(
430
+ toolContext,
431
+ outputSchema,
432
+ );
433
+
434
+ // seed the rolling repo-level learnings tmpfile. the agent reads the file
435
+ // at startup (path is surfaced in the LEARNINGS section of the prompt) and
436
+ // may edit it during the post-run reflection turn. persistLearnings reads
437
+ // it back at end-of-run and PATCHes any changes to Repo.learnings.
438
+ //
439
+ // gated on a configured backend: learnings only have somewhere to persist
440
+ // when a real backend is wired (hosted SaaS / local dev). in a standalone
441
+ // BYOK run there is no store, so seeding the file would only provoke the
442
+ // post-run reflection turn (an extra billed LLM turn) to edit a file whose
443
+ // changes get dropped — and persistLearnings would then PATCH the default
444
+ // marketing host and warn on its 404. leaving learningsFilePath unset makes
445
+ // every downstream consumer (`persistLearnings`, agent harnesses,
446
+ // `resolveInstructions`) treat this as "no learnings affordance this run".
447
+ //
448
+ // wrapped in best-effort try/catch: an unwrapped filesystem failure
449
+ // (ENOSPC, EACCES, hostile sandbox) would unwind into the outer main()
450
+ // catch and flip an otherwise-successful run to "❌ Infraweaver failed".
451
+ if (isBackendConfigured()) {
452
+ try {
453
+ const learningsPath = await seedLearningsFile({
454
+ tmpdir,
455
+ current: runContext.repoSettings.learnings,
456
+ });
457
+ toolState.learningsFilePath = learningsPath;
458
+ // file on disk is the verbatim DB body, so the seed used for
459
+ // change-detection is just `current ?? ""` (trimmed). persistLearnings
460
+ // byte-compares against the trimmed read-back to skip no-op PATCHes.
461
+ toolState.learningsSeed = (
462
+ runContext.repoSettings.learnings ?? ""
463
+ ).trim();
464
+ log.info(
465
+ `» learnings seeded at ${learningsPath} (existing=${runContext.repoSettings.learnings ? "yes" : "no"})`,
466
+ );
467
+ const ctxForExit = toolContext;
468
+ onExitSignal(() => persistLearnings(ctxForExit));
469
+ } catch (err) {
470
+ log.warning(
471
+ `» learnings seed failed: ${err instanceof Error ? err.message : String(err)} — continuing without learnings file`,
472
+ );
473
+ }
474
+ } else {
475
+ log.debug(
476
+ "no backend configured (API_URL unset) — skipping learnings seed + reflection turn",
477
+ );
478
+ }
479
+
480
+ // seed the rolling PR summary tmpfile when the dispatcher requested it.
481
+ // gated on event being a PR — issue/workflow_dispatch runs have no
482
+ // summarySnapshot to maintain. file path is exposed to the agent via
483
+ // the select_mode response addendum (action/mcp/selectMode.ts).
484
+ if (
485
+ payload.generateSummary &&
486
+ payload.event.is_pr &&
487
+ payload.event.issue_number
488
+ ) {
489
+ const previousSnapshot = await fetchPreviousSnapshot(
490
+ toolContext,
491
+ payload.event.issue_number,
492
+ );
493
+ const filePath = await seedSummaryFile({ tmpdir, previousSnapshot });
494
+ toolState.summaryFilePath = filePath;
495
+ // capture the exact bytes the agent will see at startup. used by
496
+ // the post-run retry loop to detect the agent forgetting to edit
497
+ // the file (byte-identical to seed → nudge once via resume turn)
498
+ // and by persistSummary to skip the DB write when nothing changed.
499
+ try {
500
+ toolState.summarySeed = await readFile(filePath, "utf8");
501
+ } catch {
502
+ // intentionally empty — summarySeed stays undefined
503
+ }
504
+ log.info(
505
+ `» summary snapshot seeded at ${filePath} (previous=${previousSnapshot ? "yes" : "no"})`,
506
+ );
507
+ // on SIGINT/SIGTERM we still want to persist whatever the agent has
508
+ // written so far. handler is best-effort: any failure inside is
509
+ // swallowed by Promise.allSettled in exitHandler.ts, and the
510
+ // summaryPersistAttempted guard prevents double-execution if the
511
+ // signal arrives after the normal path already persisted. capture a
512
+ // narrowed reference so the closure doesn't depend on the outer
513
+ // `toolContext` variable being defined later.
514
+ const ctxForExit = toolContext;
515
+ onExitSignal(() => persistSummary(ctxForExit));
516
+ }
517
+
518
+ startInstallation(toolContext);
519
+
520
+ logRunStartup({ payload, resolvedModel, agentName: agent.name });
521
+
522
+ const instructions = resolveInstructions({
523
+ payload,
524
+ repo: runContext.repo,
525
+ modes,
526
+ agentId,
527
+ outputSchema,
528
+ learningsFilePath: toolState.learningsFilePath ?? null,
529
+ learningsHeadings: runContext.repoSettings.learningsHeadings,
530
+ setupHookFailure: describeSetupFailure(setupHook.failure),
531
+ });
532
+ const logParts = [
533
+ instructions.eventInstructions
534
+ ? `EVENT-LEVEL INSTRUCTIONS:\n${instructions.eventInstructions}`
535
+ : null,
536
+ instructions.user ? `USER REQUEST:\n${instructions.user}` : null,
537
+ instructions.event,
538
+ ].filter(Boolean);
539
+ log.box(logParts.join("\n\n---\n\n"), {
540
+ title: "Instructions",
541
+ });
542
+ log.group("View full prompt", () => {
543
+ log.info(instructions.full);
544
+ });
545
+
546
+ // OpenCode loads .opencode/plugin/ files at startup. if the repo has any,
547
+ // eagerly await dependency installation so plugin imports can resolve.
548
+ if (agentId === "opencode") {
549
+ const pluginDir = join(process.cwd(), ".opencode", "plugin");
550
+ const hasPlugins =
551
+ existsSync(pluginDir) &&
552
+ readdirSync(pluginDir).some((f) => /\.[jt]sx?$/.test(f));
553
+ if (hasPlugins && toolState.dependencyInstallation?.promise) {
554
+ log.info(
555
+ "» .opencode/plugin/ detected — awaiting dependency installation before agent start",
556
+ );
557
+ await toolState.dependencyInstallation.promise.catch(() => {});
558
+ timer.checkpoint("awaitDepsForPlugins");
559
+ }
560
+ }
561
+
562
+ // LLM10 — bound the run in TOKENS as well as in time. The watchdogs below
563
+ // bound idleness; a remediation loop that cannot converge streams the whole
564
+ // way and never trips them, and on a self-hosted run no Cloud meter sees it.
565
+ const tokenQuota = createTokenQuota(
566
+ resolveRunTokenQuota(payload.maxRunTokens),
567
+ );
568
+ log.info(
569
+ tokenQuota.limit > 0
570
+ ? `» run token quota: ${tokenQuota.limit.toLocaleString("en-GB")} billable tokens`
571
+ : `» run token quota: disabled (${RUN_TOKEN_QUOTA_INPUT}: 0)`,
572
+ );
573
+
574
+ // run agent, optionally with timeout enforcement
575
+ activityTimeout = createProcessOutputActivityTimeout({
576
+ timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
577
+ checkIntervalMs: DEFAULT_ACTIVITY_CHECK_INTERVAL_MS,
578
+ });
579
+ activityTimeout.promise.catch(() => {}); // prevent unhandled rejection if agent wins race
580
+ todoTracker = createTodoTracker(async (body) => {
581
+ if (progressCallbackDisabled || !toolContext) return;
582
+ try {
583
+ // liveProgress: this is the auto-rendered checklist, not a deliberate
584
+ // final answer — must not flip wasUpdated / lastProgressBody (see #868).
585
+ await reportProgress(toolContext, { body, liveProgress: true });
586
+ } catch (err) {
587
+ log.debug(`progress update failed: ${err}`);
588
+ }
589
+ });
590
+ toolState.todoTracker = todoTracker;
591
+
592
+ // on cancellation, stop scheduling new tracker writes immediately. without this, a
593
+ // debounced write queued just before SIGTERM could land at GitHub *after* the
594
+ // workflow_run.completed webhook has already replaced the comment with the
595
+ // "This run was cancelled" body, clobbering it back to the task list. we can't
596
+ // await in-flight writes (the process is exiting), but cancelling the timer
597
+ // shrinks the race window.
598
+ onExitSignal(() => {
599
+ todoTracker?.cancel();
600
+ });
601
+
602
+ // when the agent subprocess is killed for inner activity timeout, stop
603
+ // the MCP HTTP server so mcp-proxy's SSE reconnect attempts don't keep
604
+ // the outer activity timer alive. start a short safety-net timer — if
605
+ // the agent promise hasn't resolved within 5min after the inner kill,
606
+ // force-reject the outer timer so the run can exit.
607
+ let innerTimeoutFired = false;
608
+ const onInnerActivityTimeout = () => {
609
+ if (innerTimeoutFired) return;
610
+ innerTimeoutFired = true;
611
+ log.info(
612
+ "» inner activity timeout fired — stopping MCP server and starting 5min safety-net timer",
613
+ );
614
+ // fire and forget — the server's dispose is idempotent so the
615
+ // `await using` cleanup at block exit is still safe.
616
+ mcpHttpServer[Symbol.asyncDispose]().catch((err) => {
617
+ log.debug(
618
+ `mcp server stop after inner kill failed: ${err instanceof Error ? err.message : String(err)}`,
619
+ );
620
+ });
621
+ safetyNetTimer = setTimeout(
622
+ () => {
623
+ activityTimeout?.forceReject(
624
+ "agent still pending 5min after inner activity kill — forcing exit",
625
+ );
626
+ },
627
+ 5 * 60 * 1000,
628
+ );
629
+ safetyNetTimer.unref?.();
630
+ };
631
+
632
+ const agentPromise = agent.run({
633
+ payload,
634
+ resolvedModel,
635
+ mcpServerUrl: mcpHttpServer.url,
636
+ mcpServerToken: mcpHttpServer.token,
637
+ tmpdir,
638
+ // INFRAWEAVER_DATA_DIR (/var/lib/infraweaver) holds codex auth.json + any
639
+ // future infraweaver-managed on-disk secrets. bash via MCP tmpfs-overlays
640
+ // it; agent native FS tools deny it via the same secretDenyPaths plumbing
641
+ // used for vertex creds. see wiki/security.md "Filesystem Sandbox".
642
+ secretDenyPaths: [
643
+ INFRAWEAVER_DATA_DIR,
644
+ ...(vertexCredentials ? [vertexCredentials.secretDir] : []),
645
+ ],
646
+ subagentDeniedTools,
647
+ instructions,
648
+ todoTracker,
649
+ stopScript: runContext.repoSettings.stopScript,
650
+ toolState,
651
+ apiToken: runContext.apiToken,
652
+ onActivityTimeout: onInnerActivityTimeout,
653
+ tokenQuota,
654
+ onToolUse: (event) => {
655
+ const wasTracked = recordDiffReadFromToolUse({
656
+ state: toolState.diffCoverage,
657
+ toolName: event.toolName,
658
+ input: event.input,
659
+ cwd: process.cwd(),
660
+ });
661
+ if (!wasTracked) return;
662
+ const trackedRanges = toolState.diffCoverage?.coveredRanges ?? [];
663
+ log.debug(
664
+ `» diff coverage tracked from tool ${event.toolName} (${trackedRanges.length} merged range${trackedRanges.length === 1 ? "" : "s"})`,
665
+ );
666
+ },
667
+ });
668
+ // symmetric with the activityTimeout/timeoutPromise catches below: if a
669
+ // timeout wins the race, agentPromise is stranded and its later rejection
670
+ // becomes an unhandled rejection. node 15+ terminates the process on
671
+ // unhandled rejection by default, which would kill main() mid-cleanup and
672
+ // lose the error-reporting / usage-summary work that follows. the race
673
+ // still sees the rejection (the original promise is shared); this catch
674
+ // only keeps node from treating a post-race rejection as unobserved.
675
+ agentPromise.catch(() => {});
676
+
677
+ // timeout enforcement: default is 1 hour, but can be overridden via flags in the prompt:
678
+ // - --timeout=2h (or any duration like "--timeout=30m", "--timeout=1h30m") to set a custom timeout
679
+ // - --notimeout to disable timeout entirely
680
+ let result: Awaited<typeof agentPromise>;
681
+ if (payload.timeout === TIMEOUT_DISABLED) {
682
+ result = await Promise.race([agentPromise, activityTimeout.promise]);
683
+ } else {
684
+ // resolveTimeoutMs rejects unparseable / zero / setTimeout-overflow inputs
685
+ // so a bad string can't silently resolve to an instant timeout. fall back
686
+ // to the 1h default with a warning — users who want runtime measured in
687
+ // weeks should use --notimeout.
688
+ const usable = resolveTimeoutMs(payload.timeout);
689
+ if (payload.timeout && usable === null) {
690
+ log.warning(
691
+ `invalid timeout "${payload.timeout}" (use --notimeout to disable), using 1h`,
692
+ );
693
+ }
694
+ const timeoutMs = usable ?? 3600000;
695
+ const actualTimeout = usable !== null ? payload.timeout : "1h";
696
+ let timeoutId: NodeJS.Timeout | undefined;
697
+ const timeoutPromise = new Promise<never>((_, reject) => {
698
+ timeoutId = setTimeout(() => {
699
+ reject(new Error(`agent run timed out after ${actualTimeout}`));
700
+ }, timeoutMs);
701
+ });
702
+ timeoutPromise.catch(() => {}); // prevent unhandled rejection if agent wins race
703
+ try {
704
+ result = await Promise.race([
705
+ agentPromise,
706
+ timeoutPromise,
707
+ activityTimeout.promise,
708
+ ]);
709
+ } finally {
710
+ clearTimeout(timeoutId);
711
+ }
712
+ }
713
+
714
+ // accumulate top-level agent usage
715
+ if (result.usage) {
716
+ toolState.usageEntries.push(result.usage);
717
+ }
718
+
719
+ // validate this before writing job summary to avoid masking the error
720
+ if (outputSchema && !toolState.output) {
721
+ throw new Error(
722
+ "output_schema was provided but agent did not call set_output — structured output is required",
723
+ );
724
+ }
725
+
726
+ // success-path cleanup: postReview → persistSummary → persistLearnings →
727
+ // failure-error-report → stranded-comment cleanup → job summary → output
728
+ // marker. each step is best-effort; see `finalizeSuccessRun` for ordering
729
+ // rationale (notably: progress-comment deletion lives in
730
+ // create_pull_request_review for review-mode runs, so deletion here
731
+ // covers the non-review success paths).
732
+ await finalizeSuccessRun({
733
+ toolContext,
734
+ toolState,
735
+ result,
736
+ repo: runContext.repo,
737
+ // Prefer the run-context-resolved credential (an explicit org token, or the
738
+ // run token Cloud mints from our OIDC identity on the App path) over the
739
+ // raw `api_token` input — the latter is empty under tokenless OIDC, and the
740
+ // OIDC env is already stripped here so reportToCloud can't re-mint one.
741
+ cloudApiToken: toolContext.apiToken || payload.cloudApiToken,
742
+ });
743
+
744
+ return await handleAgentResult({
745
+ result,
746
+ toolContext,
747
+ silent: payload.event.silent ?? false,
748
+ });
749
+ } catch (error) {
750
+ const errorMessage =
751
+ error instanceof Error ? error.message : "unknown error occurred";
752
+ progressCallbackDisabled = true;
753
+ todoTracker?.cancel();
754
+ killTrackedChildren();
755
+ log.error(errorMessage);
756
+
757
+ // classify (BillingError reclassification + hang detection + API-key auth
758
+ // detection) and render to {summary, comment} markdown bodies.
759
+ const rendered = renderRunError({
760
+ errorMessage,
761
+ repo: runContext.repo,
762
+ agentDiagnostic: toolState.agentDiagnostic,
763
+ });
764
+ await writeRunErrorOutputs({ rendered, toolState });
765
+
766
+ // best-effort cleanup: review dispatch, summary persist, learnings persist.
767
+ // a partial edit before the crash is still worth keeping.
768
+ if (toolContext) {
769
+ await persistRunArtifacts(toolContext);
770
+ }
771
+
772
+ return {
773
+ success: false,
774
+ error: errorMessage,
775
+ };
776
+ } finally {
777
+ activityTimeout?.stop();
778
+ if (safetyNetTimer) clearTimeout(safetyNetTimer);
779
+ // also reap on the success-with-failure path (agent returned
780
+ // `{success: false}`) which skips the catch above and would otherwise hang
781
+ // ~60s on the eager dep install. idempotent SIGKILL. see #862.
782
+ killTrackedChildren();
783
+ if (usageSummaryPath) {
784
+ // a write error here (ENOSPC, EACCES, dirname removed) must not mask
785
+ // either the try's successful return or the catch's error return.
786
+ // the summary is informational — log and move on.
787
+ try {
788
+ await writeGitHubUsageSummaryToFile(usageSummaryPath);
789
+ } catch (err) {
790
+ log.debug(
791
+ `failed to write usage summary to ${usageSummaryPath}: ${err instanceof Error ? err.message : String(err)}`,
792
+ );
793
+ }
794
+ }
795
+
796
+ // persist aggregated token + cost usage to the WorkflowRun row.
797
+ // this is the single shared cleanup path across every agent implementation:
798
+ // each agent harness returns a single AgentUsage from agent.run() that
799
+ // already aggregates its internal retries via mergeAgentUsage, and the
800
+ // success branch above pushes that entry into toolState.usageEntries.
801
+ // aggregateUsage sums across those entries (one per agent.run()).
802
+ //
803
+ // caveat: if the agent promise rejected (timeout or uncaught throw) the
804
+ // usage was never pushed, so nothing gets persisted for that run. runs
805
+ // that returned AgentResult with success=false still report their partial
806
+ // usage because the harness populates AgentUsage before returning.
807
+ if (toolContext) {
808
+ const patch = aggregateUsage(toolState.usageEntries);
809
+ if (Object.keys(patch).length > 0) {
810
+ await patchWorkflowRunFields(toolContext, patch);
811
+ }
812
+ }
813
+ cleanupVertexCredentials(vertexCredentials);
814
+ }
815
+ }