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,71 @@
1
+ import type { StandardJSONSchemaV1, StandardSchemaV1 } from "@standard-schema/spec";
2
+ import { Ajv } from "ajv";
3
+ import { type } from "arktype";
4
+ import type { ToolContext } from "#app/mcp/server";
5
+ import { execute, tool } from "#app/mcp/shared";
6
+
7
+ export const SetOutputParams = type({
8
+ value: type.string.describe("the output value to expose as a GitHub Action output"),
9
+ });
10
+
11
+ type JsonSchema = Record<string, unknown>;
12
+
13
+ function jsonSchemaToStandardSchema({
14
+ $schema: _,
15
+ ...jsonSchema
16
+ }: JsonSchema): StandardJSONSchemaV1<any> & StandardSchemaV1<any> {
17
+ const ajv = new Ajv();
18
+ const validate = ajv.compile(jsonSchema);
19
+
20
+ return {
21
+ "~standard": {
22
+ version: 1,
23
+ vendor: "json-schema",
24
+ jsonSchema: {
25
+ input: () => jsonSchema,
26
+ output: () => jsonSchema,
27
+ },
28
+ validate(input: unknown) {
29
+ if (validate(input)) {
30
+ return { value: input };
31
+ }
32
+ return {
33
+ issues: (validate.errors ?? []).map((err) => ({
34
+ message: `${err.instancePath || "/"}: ${err.message ?? "validation error"}`,
35
+ path: err.instancePath ? err.instancePath.split("/").filter(Boolean) : [],
36
+ })),
37
+ };
38
+ },
39
+ },
40
+ };
41
+ }
42
+
43
+ function storeOutput(ctx: ToolContext, value: string) {
44
+ ctx.toolState.output = value;
45
+ return { success: true };
46
+ }
47
+
48
+ export function SetOutputTool(ctx: ToolContext, outputSchema?: JsonSchema) {
49
+ if (outputSchema) {
50
+ return tool({
51
+ mutates: true,
52
+ name: "set_output",
53
+ description:
54
+ "Set the structured action output. You MUST call this tool before finishing — the output is required. Pass the output object directly as the tool arguments (no wrapping needed).",
55
+ parameters: jsonSchemaToStandardSchema(outputSchema),
56
+ execute: execute(async (params) => {
57
+ return storeOutput(ctx, JSON.stringify(params));
58
+ }),
59
+ });
60
+ }
61
+
62
+ return tool({
63
+ name: "set_output",
64
+ description:
65
+ "Set the action output. Exposes the value as the 'result' GitHub Action output for downstream workflow steps. Do NOT use this for progress reporting — use report_progress instead.",
66
+ parameters: SetOutputParams,
67
+ execute: execute(async (params) => {
68
+ return storeOutput(ctx, params.value);
69
+ }),
70
+ });
71
+ }
@@ -0,0 +1,28 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+
3
+ /**
4
+ * Resolve an agent-supplied path against `cwd` and confine it to that workspace.
5
+ *
6
+ * Returns the absolute path when it stays inside `cwd`; throws otherwise. Blocks
7
+ * both `..` traversal and absolute paths that point outside `cwd` (including a
8
+ * different drive on Windows, where `relative` returns an absolute path).
9
+ *
10
+ * Infraweaver treats the agent as semi-trusted (attacker-controlled PR content can
11
+ * prompt-inject it), so any tool that reads or writes a file path the agent
12
+ * controls — read_findings, terraform_emit_sarif, terraform_module_interface —
13
+ * must confine that path to the workspace. Without it the agent has an arbitrary
14
+ * file read (findings) or write (SARIF) primitive on the runner.
15
+ */
16
+ export function resolveWithinCwd(cwd: string, userPath: string): string {
17
+ const base = resolve(cwd);
18
+ const target = resolve(base, userPath);
19
+ const rel = relative(base, target);
20
+ // rel === "" means target IS the workspace root; a child path neither starts
21
+ // with ".." nor is absolute. Anything else escaped the workspace.
22
+ if (rel === "" || (!rel.startsWith("..") && !isAbsolute(rel))) {
23
+ return target;
24
+ }
25
+ throw new Error(
26
+ `path '${userPath}' escapes the workspace; only paths inside the working directory are allowed.`,
27
+ );
28
+ }
@@ -0,0 +1,226 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { type } from "arktype";
5
+ import { resolveWithinCwd } from "#app/mcp/pathSafety";
6
+ import type { LocalToolContext } from "#app/mcp/localContext";
7
+ import { execute, tool, toolOk, toolSkip } from "#app/mcp/shared";
8
+ import { SUBPROCESS_TIMEOUT_MS } from "#app/mcp/terraform/subprocess";
9
+ import { log } from "#app/utils/cli";
10
+ import { resolveEnv } from "#app/utils/secrets";
11
+
12
+ /**
13
+ * Policy-as-code gate (OPA/Conftest). An optional, opt-in tool that runs
14
+ * the operator's own Rego policies against the Terraform plan JSON (or the HCL),
15
+ * so an org's policy-as-code can gate a remediation/generation the same way the
16
+ * deterministic scanners do — pairs with prevent recurrence. Infraweaver is
17
+ * an ORCHESTRATOR here, never a redistributor: it invokes the external
18
+ * `conftest` (OPA) binary as a separate process and consumes its normalized
19
+ * output. Degrades green — when conftest isn't installed or no policy dir
20
+ * exists, it returns `ok: false` with a `code` and never fails the run.
21
+ *
22
+ * The parsing is pure + unit-tested; the tool just shells out and parses.
23
+ */
24
+
25
+ export interface PolicyFailure {
26
+ /** the policy rule message (the human-readable violation). */
27
+ msg: string;
28
+ /** the file conftest evaluated (repo-relative when conftest reported it). */
29
+ file: string;
30
+ /** "failure" (a deny) or "warning" (a warn). */
31
+ level: "failure" | "warning";
32
+ }
33
+
34
+ export interface PolicyResult {
35
+ /** true when there were zero failures (warnings don't fail the gate). */
36
+ passed: boolean;
37
+ failures: PolicyFailure[];
38
+ warnings: PolicyFailure[];
39
+ /** total tests conftest ran (across files), for a confidence signal. */
40
+ tested: number;
41
+ }
42
+
43
+ interface ConftestResultEntry {
44
+ filename?: string;
45
+ namespace?: string;
46
+ successes?: number;
47
+ failures?: { msg?: string }[];
48
+ warnings?: { msg?: string }[];
49
+ }
50
+
51
+ /**
52
+ * Parse `conftest test --output json` output into a normalized PolicyResult.
53
+ * Conftest emits an array of per-file result objects, each with `failures` /
54
+ * `warnings` / `successes`. Pure; tolerant of malformed/empty input (returns a
55
+ * clean pass). A non-empty `failures` anywhere means the gate did NOT pass;
56
+ * warnings are surfaced but don't fail it.
57
+ */
58
+ export function parseConftestOutput(stdout: string): PolicyResult {
59
+ let parsed: ConftestResultEntry[];
60
+ try {
61
+ const raw = JSON.parse(stdout || "[]");
62
+ parsed = Array.isArray(raw) ? raw : [];
63
+ } catch {
64
+ return { passed: true, failures: [], warnings: [], tested: 0 };
65
+ }
66
+ const failures: PolicyFailure[] = [];
67
+ const warnings: PolicyFailure[] = [];
68
+ let tested = 0;
69
+ for (const entry of parsed) {
70
+ const file = entry.filename || "(plan)";
71
+ const fails = entry.failures ?? [];
72
+ const warns = entry.warnings ?? [];
73
+ tested += (entry.successes ?? 0) + fails.length + warns.length;
74
+ for (const f of fails)
75
+ failures.push({
76
+ msg: f.msg || "policy violation",
77
+ file,
78
+ level: "failure",
79
+ });
80
+ for (const w of warns)
81
+ warnings.push({ msg: w.msg || "policy warning", file, level: "warning" });
82
+ }
83
+ return { passed: failures.length === 0, failures, warnings, tested };
84
+ }
85
+
86
+ /** the default dirs a repo keeps Rego policies in (checked in order). */
87
+ const DEFAULT_POLICY_DIRS = ["policy", "policies", ".conftest"];
88
+
89
+ /** resolve the policy dir to use: the explicit arg, else the first default dir
90
+ * that exists. Returns null when none is found. */
91
+ function resolvePolicyDir(
92
+ cwd: string,
93
+ explicit: string | undefined,
94
+ ): string | null {
95
+ if (explicit) {
96
+ // Confine the agent-supplied dir to the workspace so it can't load Rego from
97
+ // outside the repo; escape degrades to a skip (same doctrine as the siblings).
98
+ let abs: string;
99
+ try {
100
+ abs = resolveWithinCwd(cwd, explicit);
101
+ } catch {
102
+ return null;
103
+ }
104
+ return existsSync(abs) ? abs : null;
105
+ }
106
+ for (const d of DEFAULT_POLICY_DIRS) {
107
+ const abs = join(cwd, d);
108
+ if (existsSync(abs)) return abs;
109
+ }
110
+ return null;
111
+ }
112
+
113
+ export const PolicyCheckParams = type({
114
+ "target?": type.string.describe(
115
+ "the file conftest evaluates — a terraform plan JSON (preferred; produce it with `terraform show -json plan.tfplan`) or an HCL file. Default: ./plan.json, then ./tfplan.json, in the workspace.",
116
+ ),
117
+ "policy_dir?": type.string.describe(
118
+ "dir holding the Rego policies. Default: the first of ./policy, ./policies, ./.conftest that exists.",
119
+ ),
120
+ });
121
+
122
+ export function PolicyCheckTool(ctx: LocalToolContext) {
123
+ return tool({
124
+ name: "policy_check",
125
+ description:
126
+ "Run the repo's own policy-as-code (Rego) against the Terraform plan/HCL via the external `conftest` " +
127
+ "(OPA) binary, so org policy can gate a fix. Opt-in and degrades green — returns `ok: false` " +
128
+ "(never fails the run) when conftest isn't installed or no policy dir is present. On success returns " +
129
+ "`passed` (false when any policy DENY fired), the `failures` and `warnings` (each with msg + file), and " +
130
+ "the count `tested`. When `passed` is false, treat it like a failed validate: fix the violation or " +
131
+ "label the PR needs-human — do NOT push past a policy denial.",
132
+ parameters: PolicyCheckParams,
133
+ execute: execute(async ({ target, policy_dir }) => {
134
+ const cwd = ctx.payload.cwd ?? process.cwd();
135
+ const policyDir = resolvePolicyDir(cwd, policy_dir);
136
+ if (!policyDir) {
137
+ return toolSkip(
138
+ "no_policy_dir",
139
+ "no Rego policy dir found (looked for ./policy, ./policies, ./.conftest, or the policy_dir arg) — policy_check is opt-in",
140
+ );
141
+ }
142
+ // resolve the target file: explicit arg, else a conventional plan JSON.
143
+ let targetFile: string | null = null;
144
+ if (target) {
145
+ // Confine the agent-supplied target to the workspace (see resolvePolicyDir).
146
+ let abs: string | null = null;
147
+ try {
148
+ abs = resolveWithinCwd(cwd, target);
149
+ } catch {
150
+ abs = null;
151
+ }
152
+ targetFile = abs && existsSync(abs) ? abs : null;
153
+ if (!targetFile) {
154
+ return toolSkip(
155
+ "target_not_found",
156
+ `policy target '${target}' not found in the workspace`,
157
+ );
158
+ }
159
+ } else {
160
+ for (const candidate of ["plan.json", "tfplan.json"]) {
161
+ const abs = join(cwd, candidate);
162
+ if (existsSync(abs)) {
163
+ targetFile = abs;
164
+ break;
165
+ }
166
+ }
167
+ if (!targetFile) {
168
+ return toolSkip(
169
+ "no_target",
170
+ "no plan JSON to evaluate — produce one with `terraform show -json plan.tfplan > plan.json`, or pass `target`",
171
+ );
172
+ }
173
+ }
174
+ const r = spawnSync(
175
+ "conftest",
176
+ ["test", "--output", "json", "-p", policyDir, targetFile],
177
+ {
178
+ cwd,
179
+ encoding: "utf-8",
180
+ env: resolveEnv("restricted") as NodeJS.ProcessEnv,
181
+ stdio: ["ignore", "pipe", "pipe"],
182
+ maxBuffer: 64 * 1024 * 1024,
183
+ // bound a hung conftest (e.g. a policy that pulls a remote bundle).
184
+ timeout: SUBPROCESS_TIMEOUT_MS,
185
+ },
186
+ );
187
+ if (r.error && (r.error as NodeJS.ErrnoException).code === "ENOENT") {
188
+ return toolSkip(
189
+ "conftest_not_installed",
190
+ "conftest (OPA) is not installed — policy_check is opt-in and best-effort; install conftest to enable it",
191
+ );
192
+ }
193
+ // conftest exits non-zero when a policy DENY fires — that's a normal
194
+ // denial (JSON on stdout), not a tool error. But it ALSO exits non-zero
195
+ // when it couldn't evaluate at all (bad policy, parse error, no tests) —
196
+ // there it emits nothing parseable. Distinguish: a non-zero exit that
197
+ // yielded no evaluated tests AND no failures/warnings is a real error, so
198
+ // report it as a skip rather than a false PASS. A genuine denial has
199
+ // failures > 0 and flows through to `passed: false`.
200
+ const result = parseConftestOutput(r.stdout);
201
+ const evaluated =
202
+ result.tested > 0 ||
203
+ result.failures.length > 0 ||
204
+ result.warnings.length > 0;
205
+ if (r.status !== 0 && !evaluated) {
206
+ return toolSkip(
207
+ "conftest_failed",
208
+ `conftest could not evaluate the target: ${r.stderr.trim().slice(0, 300) || "unknown error"}`,
209
+ );
210
+ }
211
+ log.info(
212
+ `» policy_check: ${result.passed ? "PASS" : "FAIL"} — ${result.failures.length} failure(s), ${result.warnings.length} warning(s) over ${result.tested} test(s)`,
213
+ );
214
+ return toolOk({
215
+ passed: result.passed,
216
+ policy_dir: policyDir,
217
+ target: targetFile,
218
+ failure_count: result.failures.length,
219
+ warning_count: result.warnings.length,
220
+ failures: result.failures,
221
+ warnings: result.warnings,
222
+ tested: result.tested,
223
+ });
224
+ }),
225
+ });
226
+ }
package/src/mcp/pr.ts ADDED
@@ -0,0 +1,238 @@
1
+ import { type } from "arktype";
2
+ import type { GitHubWriteToolContext } from "#app/mcp/capabilityContext";
3
+ import {
4
+ assertUnderOpenPrCaps,
5
+ assertUnderPrCap,
6
+ recordRemediationPrOpened,
7
+ } from "#app/mcp/guardrails";
8
+ import { assertTargetInScope, recordCreatedTarget } from "#app/mcp/scope";
9
+ import { execute, tool } from "#app/mcp/shared";
10
+ import {
11
+ buildInfraweaverFooter,
12
+ stripExistingFooter,
13
+ } from "#app/utils/buildInfraweaverFooter";
14
+ import { log } from "#app/utils/cli";
15
+ import { fixDoubleEscapedString } from "#app/utils/fixDoubleEscapedString";
16
+ import { patchWorkflowRunFields } from "#app/utils/patchWorkflowRunFields";
17
+ import type { ResolvedPayload } from "#app/utils/payload";
18
+ import { redactSecrets } from "#app/utils/redact";
19
+ import type { RunContextData } from "#app/utils/runContextData";
20
+ import { $ } from "#app/utils/shell";
21
+
22
+ /**
23
+ * The slice `resolveBaseBranch` reads: the declared base-branch input and the
24
+ * repository's default branch. Shared with `terraform_change_summary`, which
25
+ * resolves the same base without needing the rest of the GitHub surface.
26
+ */
27
+ export interface BaseBranchContext {
28
+ payload: ResolvedPayload;
29
+ repo: RunContextData["repo"];
30
+ }
31
+
32
+ export const PullRequest = type({
33
+ title: type.string.describe("the title of the pull request"),
34
+ body: type.string.describe("the body content of the pull request"),
35
+ "base?": type.string.describe(
36
+ "the base branch to merge into (e.g. 'main'). Omit to use the run's resolved base branch: the `base_branch` input, else the repository's default branch (main, or master).",
37
+ ),
38
+ "draft?": type.boolean.describe(
39
+ "if true, create the pull request as a draft. use when the user explicitly asks for a draft PR.",
40
+ ),
41
+ });
42
+
43
+ /**
44
+ * Pure base-branch picker. Precedence: an explicit `base_branch` declaration
45
+ * always wins; otherwise the repository's default branch (GitHub reports it —
46
+ * normally `main`, sometimes `master`); otherwise prefer `main`, then `master`;
47
+ * final fallback `main`. Split out from git/ctx so it's exhaustively testable.
48
+ */
49
+ export function pickBaseBranch(opts: {
50
+ declared?: string | undefined;
51
+ defaultBranch?: string | undefined;
52
+ mainExists: boolean;
53
+ masterExists: boolean;
54
+ }): string {
55
+ if (opts.declared) return opts.declared;
56
+ if (opts.defaultBranch) return opts.defaultBranch;
57
+ if (opts.mainExists) return "main";
58
+ if (opts.masterExists) return "master";
59
+ return "main";
60
+ }
61
+
62
+ /** true when `branch` exists as a remote-tracking or local ref. */
63
+ function branchExists(branch: string): boolean {
64
+ for (const ref of [`refs/remotes/origin/${branch}`, `refs/heads/${branch}`]) {
65
+ try {
66
+ $("git", ["rev-parse", "--verify", "--quiet", ref], { log: false });
67
+ return true;
68
+ } catch {
69
+ // ref absent — try the next form
70
+ }
71
+ }
72
+ return false;
73
+ }
74
+
75
+ /**
76
+ * Deterministically resolve the branch a PR targets, so the base is never left
77
+ * to the agent's guess. Resolves to the repository's default branch (`main`, or
78
+ * `master`), overridable by the `base_branch` input. Git is only probed for
79
+ * main/master in the last-resort case where neither an explicit declaration nor
80
+ * a GitHub default branch is available (essentially never).
81
+ */
82
+ export function resolveBaseBranch(ctx: BaseBranchContext): string {
83
+ const declared = ctx.payload.baseBranch?.trim() || undefined;
84
+ const defaultBranch = ctx.repo.data.default_branch?.trim() || undefined;
85
+ const needsProbe = !declared && !defaultBranch;
86
+ return pickBaseBranch({
87
+ declared,
88
+ defaultBranch,
89
+ mainExists: needsProbe && branchExists("main"),
90
+ masterExists: needsProbe && branchExists("master"),
91
+ });
92
+ }
93
+
94
+ function buildPrBodyWithFooter(
95
+ ctx: GitHubWriteToolContext,
96
+ body: string,
97
+ ): string {
98
+ const footer = buildInfraweaverFooter({
99
+ triggeredBy: true,
100
+ model: ctx.toolState.model,
101
+ fallbackFrom: ctx.toolState.modelFallback?.from,
102
+ language: ctx.payload.language,
103
+ });
104
+
105
+ const bodyWithoutFooter = stripExistingFooter(fixDoubleEscapedString(body));
106
+ // LLM02: scrub any secret the agent echoed from a hostile repo before it lands in
107
+ // a durable, public artifact. redactSecrets is idempotent + a no-op on clean text.
108
+ return redactSecrets(`${bodyWithoutFooter}${footer}`);
109
+ }
110
+
111
+ export const UpdatePullRequestBody = type({
112
+ pull_number: type.number.describe("the pull request number to update"),
113
+ body: type.string.describe("the new body content for the pull request"),
114
+ });
115
+
116
+ export function UpdatePullRequestBodyTool(ctx: GitHubWriteToolContext) {
117
+ return tool({
118
+ mutates: true,
119
+ name: "update_pull_request_body",
120
+ description: "Update the body/description of an existing pull request",
121
+ parameters: UpdatePullRequestBody,
122
+ execute: execute(async (params) => {
123
+ assertTargetInScope(ctx, params.pull_number, "update the body of");
124
+ const bodyWithFooter = buildPrBodyWithFooter(ctx, params.body);
125
+
126
+ const result = await ctx.octokit.rest.pulls.update({
127
+ owner: ctx.repo.owner,
128
+ repo: ctx.repo.name,
129
+ pull_number: params.pull_number,
130
+ body: bodyWithFooter,
131
+ });
132
+ log.info(`» updated pull request #${result.data.number}`);
133
+
134
+ ctx.toolState.wasUpdated = true;
135
+
136
+ return {
137
+ success: true,
138
+ number: result.data.number,
139
+ url: result.data.html_url,
140
+ };
141
+ }),
142
+ });
143
+ }
144
+
145
+ export function CreatePullRequestTool(ctx: GitHubWriteToolContext) {
146
+ return tool({
147
+ mutates: true,
148
+ name: "create_pull_request",
149
+ description: "Create a pull request from the current branch",
150
+ parameters: PullRequest,
151
+ execute: execute(async (params) => {
152
+ // permission gate: opening a PR is a repo write. `push: disabled` means the
153
+ // repository is configured for read-only access, so block it here the same
154
+ // way push_branch/create_issue do — an injected or read-only-intended agent
155
+ // must not be able to open PRs.
156
+ if (ctx.payload.push === "disabled") {
157
+ throw new Error(
158
+ "Creating a pull request is disabled. This repository is configured for read-only access (push: disabled).",
159
+ );
160
+ }
161
+
162
+ // Remediate-mode guardrail: stop at the configured max_prs. No-op otherwise.
163
+ assertUnderPrCap(ctx);
164
+ // Cross-run flood guards: cap simultaneously-open and per-hour remediation
165
+ // PRs (queries GitHub). Complements the per-run max_prs cap above. No-op
166
+ // outside guarded mode or when both limits are disabled.
167
+ await assertUnderOpenPrCaps(ctx);
168
+
169
+ const currentBranch = $("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
170
+ log: false,
171
+ });
172
+ const base = params.base ?? resolveBaseBranch(ctx);
173
+ log.debug(`Current branch: ${currentBranch}; PR base: ${base}`);
174
+
175
+ const bodyWithFooter = buildPrBodyWithFooter(ctx, params.body);
176
+
177
+ const result = await ctx.octokit.rest.pulls.create({
178
+ owner: ctx.repo.owner,
179
+ repo: ctx.repo.name,
180
+ // title bypasses buildPrBodyWithFooter, so redact it on its own (LLM02).
181
+ title: redactSecrets(params.title),
182
+ body: bodyWithFooter,
183
+ head: currentBranch,
184
+ base,
185
+ draft: params.draft ?? false,
186
+ });
187
+ log.info(
188
+ `» created pull request #${result.data.number} (id ${result.data.id})`,
189
+ );
190
+
191
+ // record so the agent may update THIS PR's body / comment on it later even
192
+ // though its number differs from the run's triggering issue_number.
193
+ recordCreatedTarget(ctx, result.data.number);
194
+
195
+ // best-effort: request review from the user who triggered the workflow
196
+ const reviewer = ctx.payload.triggerer;
197
+ if (reviewer) {
198
+ try {
199
+ log.debug(
200
+ `requesting review from ${reviewer} on PR #${result.data.number}`,
201
+ );
202
+ await ctx.octokit.rest.pulls.requestReviewers({
203
+ owner: ctx.repo.owner,
204
+ repo: ctx.repo.name,
205
+ pull_number: result.data.number,
206
+ reviewers: [reviewer],
207
+ });
208
+ } catch {
209
+ log.info(
210
+ `failed to request review from ${reviewer} on PR #${result.data.number}`,
211
+ );
212
+ }
213
+ }
214
+
215
+ if (
216
+ typeof result.data.node_id === "string" &&
217
+ result.data.node_id.length > 0
218
+ ) {
219
+ await patchWorkflowRunFields(ctx, {
220
+ prNodeId: result.data.node_id,
221
+ });
222
+ }
223
+
224
+ // count this toward the per-run remediation PR cap (Remediate mode only).
225
+ recordRemediationPrOpened(ctx);
226
+
227
+ return {
228
+ success: true,
229
+ pullRequestId: result.data.id,
230
+ number: result.data.number,
231
+ url: result.data.html_url,
232
+ title: result.data.title,
233
+ head: result.data.head.ref,
234
+ base: result.data.base.ref,
235
+ };
236
+ }),
237
+ });
238
+ }
@@ -0,0 +1,91 @@
1
+ import { type } from "arktype";
2
+ import type { GitHubToolContext } from "#app/mcp/capabilityContext";
3
+ import { execute, tool } from "#app/mcp/shared";
4
+ import { resolveBodyAssets } from "#app/utils/body";
5
+
6
+ const CLOSING_ISSUES_QUERY = `
7
+ query($owner: String!, $repo: String!, $number: Int!) {
8
+ repository(owner: $owner, name: $repo) {
9
+ pullRequest(number: $number) {
10
+ closingIssuesReferences(first: 10) {
11
+ nodes { number title }
12
+ }
13
+ }
14
+ }
15
+ }
16
+ `;
17
+
18
+ type ClosingIssuesResponse = {
19
+ repository: {
20
+ pullRequest: {
21
+ closingIssuesReferences: { nodes: Array<{ number: number; title: string }> };
22
+ };
23
+ };
24
+ };
25
+
26
+ export const PullRequestInfo = type({
27
+ pull_number: type.number.describe("The pull request number to fetch"),
28
+ });
29
+
30
+ export function PullRequestInfoTool(ctx: GitHubToolContext) {
31
+ return tool({
32
+ name: "get_pull_request",
33
+ description:
34
+ "Retrieve PR metadata (title, body, state, branches, author, labels, linked issues). " +
35
+ "Example: `get_pull_request({ pull_number: 1234 })`. " +
36
+ "To checkout a PR branch locally, use checkout_pr instead.",
37
+ parameters: PullRequestInfo,
38
+ execute: execute(async ({ pull_number }) => {
39
+ // fetch REST and GraphQL in parallel. the issues.get call is only for body_html
40
+ // (PRs are issues; the pulls.get response type omits body_html) so attachment urls
41
+ // resolve to signed CDN urls — see resolveBodyAssets.
42
+ const [restResponse, issueResponse, graphqlResponse] = await Promise.all([
43
+ ctx.octokit.rest.pulls.get({
44
+ owner: ctx.repo.owner,
45
+ repo: ctx.repo.name,
46
+ pull_number,
47
+ }),
48
+ ctx.octokit.rest.issues.get({
49
+ owner: ctx.repo.owner,
50
+ repo: ctx.repo.name,
51
+ issue_number: pull_number,
52
+ headers: { accept: "application/vnd.github.full+json" },
53
+ }),
54
+ ctx.octokit.graphql<ClosingIssuesResponse>(CLOSING_ISSUES_QUERY, {
55
+ owner: ctx.repo.owner,
56
+ repo: ctx.repo.name,
57
+ number: pull_number,
58
+ }),
59
+ ]);
60
+
61
+ const data = restResponse.data;
62
+ const isFork = data.head.repo?.full_name !== data.base.repo.full_name;
63
+ const closingIssues = graphqlResponse.repository.pullRequest.closingIssuesReferences.nodes;
64
+
65
+ const body = await resolveBodyAssets({
66
+ body: data.body,
67
+ bodyHtml: issueResponse.data.body_html,
68
+ tmpdir: ctx.tmpdir,
69
+ githubToken: ctx.githubInstallationToken,
70
+ });
71
+
72
+ return {
73
+ number: data.number,
74
+ url: data.html_url,
75
+ title: data.title,
76
+ body: body,
77
+ state: data.state,
78
+ draft: data.draft,
79
+ merged: data.merged,
80
+ maintainerCanModify: data.maintainer_can_modify,
81
+ base: data.base.ref,
82
+ head: data.head.ref,
83
+ isFork,
84
+ author: data.user?.login,
85
+ assignees: data.assignees?.map((a) => a.login),
86
+ labels: data.labels.map((l) => l.name),
87
+ closingIssues: closingIssues.map((i) => ({ number: i.number, title: i.title })),
88
+ };
89
+ }),
90
+ });
91
+ }