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,47 @@
1
+ /**
2
+ * Stash for the GitHub Actions OIDC request creds used by KEYLESS (Sigstore)
3
+ * evidence signing.
4
+ *
5
+ * The `terraform_emit_evidence` / `terraform_emit_vex` tools run DURING the agent
6
+ * loop — after `main.ts` scrubs `ACTIONS_ID_TOKEN_REQUEST_*` from the env (in
7
+ * every shell mode) — so they can't call `core.getIDToken()` / read those vars
8
+ * themselves. Infraweaver already snapshots the request creds early (see
9
+ * `resolveTokens` in `utils/token.ts`, which reads them for mid-run token
10
+ * re-mints); this module lets that same snapshot feed a `sigstore`-audience OIDC
11
+ * token to Fulcio at emit time.
12
+ *
13
+ * Fulcio requires the OIDC token's `aud` to be exactly `sigstore` (its configured
14
+ * audience), distinct from Infraweaver Cloud's own `cloudOidcAudience()`.
15
+ */
16
+
17
+ import { fetchOidcIdToken, type OidcCreds } from "#app/utils/github";
18
+
19
+ /** Fulcio's required OIDC audience for the public-good instance. */
20
+ export const SIGSTORE_OIDC_AUDIENCE = "sigstore" as const;
21
+
22
+ let stashedCreds: OidcCreds | undefined;
23
+
24
+ /** Record the OIDC request creds for later keyless signing. Call once at startup
25
+ * (before the restricted-mode env scrub), passing `readOidcCreds()`. `undefined`
26
+ * off-CI, which simply disables keyless signing (there is no ambient identity). */
27
+ export function stashKeylessOidcCreds(creds: OidcCreds | undefined): void {
28
+ stashedCreds = creds;
29
+ }
30
+
31
+ /** True when an ambient GitHub Actions OIDC identity was captured — i.e. keyless
32
+ * signing is possible (running in CI with `id-token: write`). */
33
+ export function keylessOidcAvailable(): boolean {
34
+ return stashedCreds !== undefined;
35
+ }
36
+
37
+ /** Fetch a fresh `sigstore`-audience OIDC JWT for Fulcio from the stashed creds.
38
+ * Throws when no creds were stashed (off-CI, or the workflow lacks id-token:write). */
39
+ export async function fetchSigstoreOidcToken(): Promise<string> {
40
+ if (!stashedCreds) {
41
+ throw new Error(
42
+ "keyless signing needs a GitHub Actions OIDC identity, but none was captured — " +
43
+ "run inside GitHub Actions with `permissions: id-token: write`.",
44
+ );
45
+ }
46
+ return fetchOidcIdToken(stashedCreds, SIGSTORE_OIDC_AUDIENCE);
47
+ }
@@ -0,0 +1,20 @@
1
+ import { stripExistingFooter } from "#app/utils/buildInfraweaverFooter";
2
+
3
+ /**
4
+ * The prefix text for the initial "leaping into action" comment.
5
+ * Used to detect whether a progress comment is still in its initial state
6
+ * and hasn't been updated with real progress or error messages.
7
+ *
8
+ * Lives in `utils/` (not `mcp/`) so it can be re-exported via `infraweaver/internal`
9
+ * without dragging the MCP server's transitive imports into the Next.js app's
10
+ * type-check graph.
11
+ */
12
+ export const LEAPING_INTO_ACTION_PREFIX = "Leaping into action";
13
+
14
+ export function isLeapingIntoActionCommentBody(body: string): boolean {
15
+ const content = stripExistingFooter(body).trimStart();
16
+ const firstLine = content.split(/\r?\n/, 1)[0]?.trimEnd() ?? "";
17
+ return new RegExp(`(^|\\s)${LEAPING_INTO_ACTION_PREFIX}(\\.\\.\\.)?$`).test(
18
+ firstLine,
19
+ );
20
+ }
@@ -0,0 +1,145 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { LEARNINGS_FILE } from "#app/brand";
4
+ import type { ToolContext } from "#app/mcp/server";
5
+ import { cloudRequest } from "#app/utils/cloudClient";
6
+ import { isBackendConfigured } from "#app/utils/apiUrl";
7
+ import { log } from "#app/utils/cli";
8
+ import {
9
+ MAX_LEARNINGS_LENGTH,
10
+ truncateAtLineBoundary,
11
+ } from "#app/utils/learningsTruncate";
12
+
13
+ export { MAX_LEARNINGS_LENGTH, truncateAtLineBoundary };
14
+
15
+ /**
16
+ * Repo-level learnings — operational facts about a repo (setup steps, test
17
+ * commands, conventions, gotchas) that accumulate across agent runs and feed
18
+ * back into future runs as durable context. Modeled on the PR-summary tmpfile
19
+ * pattern (see action/utils/prSummary.ts):
20
+ *
21
+ * 1. server seeds `infraweaver-learnings.md` with the verbatim body of
22
+ * `Repo.learnings` (or empty for fresh repos), and parses headings
23
+ * server-side (`utils/learningsToc.ts`) — the parsed TOC is rendered
24
+ * into the LEARNINGS prompt section, not into the file
25
+ * 2. the agent reads the TOC in the prompt and uses listed line ranges
26
+ * to read just the sections relevant to the current task — file can
27
+ * grow large, but only targeted ranges hit the agent's context
28
+ * 3. agent edits the file in place at end-of-run during the reflection
29
+ * turn (see action/agents/postRun.ts buildLearningsReflectionPrompt)
30
+ * 4. main.ts reads the file back at end-of-run and PATCHes
31
+ * `/api/repo/[owner]/[repo]/learnings` if the body changed
32
+ *
33
+ * Edit-in-place avoids stuffing the entire learnings list into both the
34
+ * prompt context and an `update_learnings` MCP tool call (which previously
35
+ * required passing the FULL merged list as a string parameter — an
36
+ * output-token tax that grew linearly with the learnings size).
37
+ *
38
+ * Section structure is agent-curated. The reflection prompt teaches
39
+ * hierarchy + a soft 300-line-per-section cap to keep TOC ranges
40
+ * agent-targetable on long-lived repos; there is no fixed taxonomy.
41
+ */
42
+
43
+ export const LEARNINGS_FILE_NAME = LEARNINGS_FILE;
44
+
45
+ export function learningsFilePath(tmpdir: string): string {
46
+ return join(tmpdir, LEARNINGS_FILE_NAME);
47
+ }
48
+
49
+ /** seed the rolling learnings tmpfile with the verbatim DB body (or empty
50
+ * string for fresh repos). returns the absolute path. the parsed TOC is
51
+ * carried separately via `RepoSettings.learningsHeadings` and rendered
52
+ * into the prompt by `resolveInstructions`, so the file on disk is just
53
+ * the body — no markers, no scaffold, no in-file TOC. */
54
+ export async function seedLearningsFile(params: {
55
+ tmpdir: string;
56
+ current: string | null;
57
+ }): Promise<string> {
58
+ const path = learningsFilePath(params.tmpdir);
59
+ await mkdir(dirname(path), { recursive: true });
60
+ await writeFile(path, params.current ?? "", "utf8");
61
+ return path;
62
+ }
63
+
64
+ /** read the agent-edited learnings file. returns null when the file is
65
+ * missing or unreadable (treated as "no change"). caps content at the
66
+ * server's max length to avoid a 400 round-trip. */
67
+ export async function readLearningsFile(path: string): Promise<string | null> {
68
+ let raw: string;
69
+ try {
70
+ raw = await readFile(path, "utf8");
71
+ } catch {
72
+ return null;
73
+ }
74
+ return truncateAtLineBoundary(raw.trim(), MAX_LEARNINGS_LENGTH);
75
+ }
76
+
77
+ /**
78
+ * Read the agent-edited repo-level learnings tmpfile and PATCH it to
79
+ * `Repo.learnings`.
80
+ *
81
+ * Best-effort: any failure is logged and does not affect the run's success
82
+ * status. Skips the PATCH when the file is byte-trim-identical to its seed —
83
+ * the agent didn't touch it, so writing the same content back would just
84
+ * burn a `LearningsRevision` row and an API round-trip.
85
+ *
86
+ * `ctx.toolState.model` is forwarded so `LearningsRevision.model` keeps
87
+ * populating; it powers the per-revision attribution badge in the UI
88
+ * history view.
89
+ *
90
+ * `learningsPersistAttempted` guards against double-execution between the
91
+ * normal end-of-run path and the SIGINT/SIGTERM handler.
92
+ */
93
+ export async function persistLearnings(ctx: ToolContext): Promise<void> {
94
+ const filePath = ctx.toolState.learningsFilePath;
95
+ if (!filePath) return;
96
+ if (ctx.toolState.learningsPersistAttempted) return;
97
+ ctx.toolState.learningsPersistAttempted = true;
98
+ // dormant open-core seam: with no backend configured (standalone BYOK), there
99
+ // is nowhere to persist repo learnings — no-op silently instead of PATCHing
100
+ // the default marketing host and warning on its 404.
101
+ if (!isBackendConfigured()) {
102
+ log.debug(
103
+ "no backend configured (API_URL unset) — skipping learnings persist",
104
+ );
105
+ return;
106
+ }
107
+ const current = await readLearningsFile(filePath);
108
+ if (current === null) {
109
+ log.debug(
110
+ `learnings tmpfile missing or unreadable at ${filePath} — skipping persist`,
111
+ );
112
+ return;
113
+ }
114
+ const seed = ctx.toolState.learningsSeed?.trim() ?? "";
115
+ if (current === seed) {
116
+ log.debug("learnings tmpfile unchanged from seed — skipping persist");
117
+ return;
118
+ }
119
+ try {
120
+ const response = await cloudRequest({
121
+ path: `/api/repo/${ctx.repo.owner}/${ctx.repo.name}/learnings`,
122
+ method: "PATCH",
123
+ credential: ctx.apiToken,
124
+ json: {
125
+ learnings: current,
126
+ model: ctx.toolState.model,
127
+ },
128
+ timeoutMs: 10_000,
129
+ });
130
+ if (!response.ok) {
131
+ const error = await response.text().catch(() => "(no body)");
132
+ // promoted from debug → warning: this path means the agent edited the
133
+ // file (we already short-circuited the unchanged-from-seed case above)
134
+ // but the PATCH dropped it on the floor. silently losing real work is
135
+ // worse than the noise of a CI warning.
136
+ log.warning(`learnings persist failed (${response.status}): ${error}`);
137
+ return;
138
+ }
139
+ log.info("» learnings updated");
140
+ } catch (err) {
141
+ log.warning(
142
+ `learnings persist failed: ${err instanceof Error ? err.message : String(err)}`,
143
+ );
144
+ }
145
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * pure string helpers for capping and line-boundary-truncating the
3
+ * `Repo.learnings` body. lives in its own module (vs alongside
4
+ * `learnings.ts`) so the proprietary root app can re-export it through
5
+ * `action/internal/index.ts` without dragging the entire MCP type graph
6
+ * along — `learnings.ts` imports `ToolContext` for its runtime helpers,
7
+ * and pulling that into the SDK-facing `internal` barrel expands the
8
+ * type graph reachable from root `tsc` and `cf-worker-indexing` to every
9
+ * tool module under `action/mcp/`. keeping these helpers MCP-free is the
10
+ * cheap structural fix.
11
+ *
12
+ * see `action/utils/learnings.ts` for the full learnings-file lifecycle.
13
+ */
14
+
15
+ /** maximum size of `Repo.learnings` body in chars. action truncates the
16
+ * read-back BEFORE the PATCH to avoid sending an oversized payload; the
17
+ * server applies the same truncation as a defense-in-depth backstop (any
18
+ * caller that misses the client-side step would otherwise persist a
19
+ * mid-line tail, breaking the next-run TOC parse).
20
+ *
21
+ * raised from 10k → 100k once the TOC affordance landed: with line-range
22
+ * reads via the server-parsed TOC the agent doesn't ingest the whole
23
+ * file, so the cap is governed by curation discipline rather than a
24
+ * tight byte ceiling. 100k holds ~400-500 short bullets. */
25
+ export const MAX_LEARNINGS_LENGTH = 100_000;
26
+
27
+ /** truncate at the last newline boundary before `cap` so we don't leave
28
+ * a partial line at the tail (a half-truncated `## Headi` confuses the
29
+ * server's next-seed TOC parse and shrinks visible structure). falls
30
+ * back to a hard `slice` when the line boundary would discard a large
31
+ * run of content — i.e. when the tail of `head` is one giant line (rare:
32
+ * minified pastes, fenced log dumps). losing a partial last line is
33
+ * preferable to losing kilobytes of body. */
34
+ const TRUNCATION_LINE_BOUNDARY_TOLERANCE = 4096;
35
+ export function truncateAtLineBoundary(body: string, cap: number): string {
36
+ if (body.length <= cap) return body;
37
+ const head = body.slice(0, cap);
38
+ const lastNewline = head.lastIndexOf("\n");
39
+ if (lastNewline <= 0) return head;
40
+ if (cap - lastNewline > TRUNCATION_LINE_BOUNDARY_TOLERANCE) return head;
41
+ return head.slice(0, lastNewline);
42
+ }
@@ -0,0 +1,198 @@
1
+ import { LIFECYCLE_HOOK_TIMEOUT_MS } from "#app/lifecycle";
2
+ import { log } from "#app/utils/cli";
3
+ import {
4
+ SPAWN_ACTIVITY_TIMEOUT_CODE,
5
+ SPAWN_TIMEOUT_CODE,
6
+ SpawnTimeoutError,
7
+ spawn,
8
+ } from "#app/utils/subprocess";
9
+
10
+ export interface ExecuteLifecycleHookParams {
11
+ event: string;
12
+ script: string | null;
13
+ /**
14
+ * when true, after the hook runs (success or failure), discard tracked-file
15
+ * mods so the agent doesn't see hook-generated drift (e.g. `pnpm install`
16
+ * rewriting a lockfile). untracked files are preserved — hooks that
17
+ * intentionally materialize files (e.g. a `.env` from a template) stay
18
+ * visible to the agent. skipped (with a warning) if the tree had
19
+ * pre-existing tracked changes before the hook ran, so we never clobber
20
+ * pre-existing work; pre-existing untracked files are ignored for this
21
+ * gate because `git restore --staged --worktree .` doesn't touch them
22
+ * anyway. no-op when no script was configured.
23
+ */
24
+ normalizeWorkingTreeAfter?: boolean;
25
+ }
26
+
27
+ /** structured failure info — `output` on the `exit` variant is trimmed
28
+ * stderr, falling back to stdout when stderr is empty. */
29
+ export type LifecycleHookFailure =
30
+ | { kind: "exit"; exitCode: number; output: string }
31
+ | { kind: "timeout" }
32
+ | { kind: "spawn"; spawnError: string };
33
+
34
+ /** one-line, agent-facing description of a hook failure. empty string when
35
+ * there was no failure, so callers can pass the result straight through to a
36
+ * prompt section that omits itself on empty. */
37
+ export function describeSetupFailure(failure: LifecycleHookFailure | undefined): string {
38
+ if (!failure) return "";
39
+ switch (failure.kind) {
40
+ case "exit":
41
+ return `It exited with code ${failure.exitCode}. Output:\n\n${failure.output || "(empty)"}`;
42
+ case "timeout":
43
+ return "It timed out and was killed before completing.";
44
+ case "spawn":
45
+ return `It failed to start: ${failure.spawnError}`;
46
+ default: {
47
+ const _exhaustive: never = failure;
48
+ return _exhaustive satisfies never;
49
+ }
50
+ }
51
+ }
52
+
53
+ export interface LifecycleHookResult {
54
+ /**
55
+ * human-readable warning when the hook failed. includes retry guidance:
56
+ * transient spawn/exit errors are worth retrying, timeouts and
57
+ * persistent failures are not. absent when the hook succeeded or was
58
+ * skipped. setup/post-checkout callers surface this verbatim; prepush
59
+ * builds its own message from `failure` instead.
60
+ */
61
+ warning?: string;
62
+ /**
63
+ * structured failure info — undefined when the hook succeeded or was
64
+ * skipped. lets callers compose their own messaging without parsing the
65
+ * `warning` string.
66
+ */
67
+ failure?: LifecycleHookFailure;
68
+ }
69
+
70
+ /**
71
+ * execute a lifecycle hook script if one is configured.
72
+ *
73
+ * soft-fails: instead of throwing on hook errors, returns a warning string
74
+ * (and structured failure info) so callers can choose how to surface it
75
+ * (mcp tools relay it to the agent; setup logs it and adds a prompt banner).
76
+ * timeouts are flagged as non-retryable in the warning text.
77
+ */
78
+ export async function executeLifecycleHook(
79
+ params: ExecuteLifecycleHookParams,
80
+ ): Promise<LifecycleHookResult> {
81
+ if (!params.script) return {};
82
+
83
+ log.info(`» executing ${params.event} lifecycle hook...`);
84
+
85
+ // snapshot tracked-file mods BEFORE the hook runs so we can distinguish
86
+ // hook-generated drift from pre-existing work. both hook windows should
87
+ // start clean in normal operation (setup runs before any working-tree
88
+ // writes; checkout_pr refuses to run with a dirty tree), but if that
89
+ // invariant breaks we'd rather warn than discard whatever was there.
90
+ // pre-existing untracked files don't matter here — `git restore --staged
91
+ // --worktree .` never touches untracked files, so they're never at risk.
92
+ const preHookTrackedCount = params.normalizeWorkingTreeAfter
93
+ ? (await runGitLines(["diff", "--name-only", "HEAD"])).length
94
+ : 0;
95
+
96
+ // single try/finally so normalization fires on success AND failure paths.
97
+ // a hook that fails partway through (e.g. `pnpm install` updates the
98
+ // lockfile then explodes on a peer-dep conflict) leaves the same kind of
99
+ // drift a successful run does, and the agent will see it next regardless
100
+ // of which path we took. failure-mode messaging is unchanged; the only
101
+ // delta is that we don't return tracked drift to the agent.
102
+ let result: LifecycleHookResult;
103
+ try {
104
+ try {
105
+ const spawnResult = await spawn({
106
+ cmd: "bash",
107
+ args: ["-c", params.script],
108
+ env: process.env,
109
+ timeout: LIFECYCLE_HOOK_TIMEOUT_MS,
110
+ activityTimeout: 0,
111
+ onStdout: (chunk) => process.stdout.write(chunk),
112
+ onStderr: (chunk) => process.stderr.write(chunk),
113
+ });
114
+
115
+ if (spawnResult.exitCode !== 0) {
116
+ const output = (spawnResult.stderr || spawnResult.stdout).trim();
117
+ result = {
118
+ failure: { kind: "exit", output, exitCode: spawnResult.exitCode },
119
+ warning:
120
+ `lifecycle hook '${params.event}' failed with exit code ${spawnResult.exitCode}. ` +
121
+ `output: ${output || "(empty)"}. ` +
122
+ `retry the operation if the failure looks flaky (network blips, transient rate limits). ` +
123
+ `do NOT retry if the script is broken (missing commands, syntax errors) or the error is persistent.`,
124
+ };
125
+ } else {
126
+ log.info(`» ${params.event} lifecycle hook completed successfully`);
127
+ result = {};
128
+ }
129
+ } catch (err) {
130
+ const isTimeout =
131
+ err instanceof SpawnTimeoutError &&
132
+ (err.code === SPAWN_TIMEOUT_CODE || err.code === SPAWN_ACTIVITY_TIMEOUT_CODE);
133
+ if (isTimeout) {
134
+ const minutes = Math.round(LIFECYCLE_HOOK_TIMEOUT_MS / 60000);
135
+ result = {
136
+ failure: { kind: "timeout" },
137
+ warning:
138
+ `lifecycle hook '${params.event}' timed out after ${minutes}min. ` +
139
+ `do NOT retry — the script is likely hung or doing too much work. ` +
140
+ `ask the repo owner to simplify the hook (e.g. move long-running work out of the hook, add caching, or split it).`,
141
+ };
142
+ } else {
143
+ const msg = err instanceof Error ? err.message : String(err);
144
+ result = {
145
+ failure: { kind: "spawn", spawnError: msg },
146
+ warning:
147
+ `lifecycle hook '${params.event}' failed to spawn: ${msg}. ` +
148
+ `this is likely a transient failure — retry the operation.`,
149
+ };
150
+ }
151
+ }
152
+ } finally {
153
+ if (params.normalizeWorkingTreeAfter) {
154
+ await normalizeWorkingTreeAfterHook({ event: params.event, preHookTrackedCount });
155
+ }
156
+ }
157
+ return result;
158
+ }
159
+
160
+ /**
161
+ * discard tracked-file mods left by a lifecycle hook so the agent's next
162
+ * `git status` matches the pre-hook state. untracked files (e.g. a `.env`
163
+ * the hook materialized from a template) are left alone — the agent decides
164
+ * what to do with them. skipped (with a warning) when the tree had
165
+ * pre-existing tracked changes before the hook ran, so pre-existing work
166
+ * is never clobbered. idempotent: a second call on a clean tree is a no-op
167
+ * and stays quiet.
168
+ */
169
+ async function normalizeWorkingTreeAfterHook(params: {
170
+ event: string;
171
+ preHookTrackedCount: number;
172
+ }): Promise<void> {
173
+ if (params.preHookTrackedCount > 0) {
174
+ log.warning(
175
+ `» working tree had ${params.preHookTrackedCount} pre-existing tracked changes before ${params.event} hook; ` +
176
+ `skipping post-hook normalization to avoid clobbering pre-existing work`,
177
+ );
178
+ return;
179
+ }
180
+ const trackedCount = (await runGitLines(["diff", "--name-only", "HEAD"])).length;
181
+ if (trackedCount === 0) return;
182
+ await runGit(["restore", "--staged", "--worktree", "."]);
183
+ log.info(`» discarded ${trackedCount} tracked changes from ${params.event} hook`);
184
+ }
185
+
186
+ async function runGit(args: string[]): Promise<string> {
187
+ const result = await spawn({ cmd: "git", args, env: process.env, activityTimeout: 0 });
188
+ if (result.exitCode !== 0) {
189
+ throw new Error(
190
+ `git ${args.join(" ")} failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`,
191
+ );
192
+ }
193
+ return result.stdout;
194
+ }
195
+
196
+ async function runGitLines(args: string[]): Promise<string[]> {
197
+ return (await runGit(args)).split("\n").filter(Boolean);
198
+ }