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,368 @@
1
+ import { execFileSync, execSync } from "node:child_process";
2
+ import { mkdtempSync, readdirSync, realpathSync, unlinkSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { BOT_EMAIL, BOT_LOGIN, PRODUCT_SLUG } from "#app/brand";
6
+ import type { ShellPermission } from "#app/external";
7
+ import type { ToolState } from "#app/toolState";
8
+ import { log } from "#app/utils/cli";
9
+ import type { OctokitWithPlugins } from "#app/utils/github";
10
+ import { isInsideDocker } from "#app/utils/globals";
11
+ import { $ } from "#app/utils/shell";
12
+
13
+ export interface SetupOptions {
14
+ tempDir: string;
15
+ }
16
+
17
+ /**
18
+ * Create a shared temp directory for the action
19
+ */
20
+ export function createTempDirectory(): string {
21
+ const sharedTempDir = mkdtempSync(join(tmpdir(), `${PRODUCT_SLUG}-`));
22
+ process.env.INFRAWEAVER_TEMP_DIR = sharedTempDir;
23
+ log.info(`» created temp dir at ${sharedTempDir}`);
24
+ return sharedTempDir;
25
+ }
26
+
27
+ /**
28
+ * snapshot-and-delete the GHA runner's known credential leak surfaces inside
29
+ * `$RUNNER_TEMP` before the agent spawns. without this, a shell-capable agent
30
+ * can grep:
31
+ * - `_runner_file_commands/set_output_*` for `core.setOutput('token', ghs_…)`
32
+ * calls made by earlier composite-action steps (e.g.
33
+ * infraweaver-io/infraweaver-action/get-installation-token);
34
+ * - `<uuid>.sh` rendered step scripts whose `run: |` body embeds
35
+ * `${{ steps.token.outputs.token }}` literally (GHA expands BEFORE writing);
36
+ * - `git-credentials-*.config` written by `actions/checkout@v6` for the
37
+ * workflow GITHUB_TOKEN.
38
+ *
39
+ * the running bash process already has its own `.sh` open via fd, so the
40
+ * unlink is safe — `unlink` removes the dirent, the kernel keeps reading.
41
+ *
42
+ * preserves every `_runner_file_commands/` file path the runner pre-allocated
43
+ * for OUR step — `$GITHUB_OUTPUT`, `$GITHUB_ENV`, `$GITHUB_PATH`,
44
+ * `$GITHUB_STATE`, `$GITHUB_STEP_SUMMARY`. those are read by the runner
45
+ * AFTER we exit (or by our own `post:` hook), and wiping them would break
46
+ * infraweaver's `result` output, `post:` state handoff, and job summary.
47
+ *
48
+ * silent no-op when `$RUNNER_TEMP` is unset (local dev, `pnpm dev:run`).
49
+ * per-file errors are tolerated — the runner may delete files between
50
+ * our readdir and our unlink.
51
+ */
52
+ export function wipeRunnerLeakSurface(): void {
53
+ const runnerTemp = process.env.RUNNER_TEMP;
54
+ if (!runnerTemp) return;
55
+
56
+ const preserve = new Set<string>();
57
+ for (const envVar of [
58
+ "GITHUB_OUTPUT",
59
+ "GITHUB_ENV",
60
+ "GITHUB_PATH",
61
+ "GITHUB_STATE",
62
+ "GITHUB_STEP_SUMMARY",
63
+ ]) {
64
+ const path = process.env[envVar];
65
+ if (!path) continue;
66
+ try {
67
+ preserve.add(realpathSync(path));
68
+ } catch {
69
+ // path may not exist yet — preserve the literal in case it gets created later
70
+ preserve.add(path);
71
+ }
72
+ }
73
+
74
+ const wiped: string[] = [];
75
+
76
+ const tryUnlink = (path: string): void => {
77
+ let resolved = path;
78
+ try {
79
+ resolved = realpathSync(path);
80
+ } catch {
81
+ // file may already be gone — fall through to unlink for the race-tolerant path
82
+ }
83
+ if (preserve.has(resolved) || preserve.has(path)) return;
84
+ try {
85
+ unlinkSync(path);
86
+ wiped.push(path);
87
+ } catch {
88
+ // race-tolerant: file may have been deleted between readdir and unlink
89
+ }
90
+ };
91
+
92
+ const listDir = (dir: string): string[] => {
93
+ try {
94
+ return readdirSync(dir);
95
+ } catch {
96
+ return [];
97
+ }
98
+ };
99
+
100
+ const fileCommandsDir = join(runnerTemp, "_runner_file_commands");
101
+ for (const entry of listDir(fileCommandsDir)) {
102
+ tryUnlink(join(fileCommandsDir, entry));
103
+ }
104
+
105
+ for (const entry of listDir(runnerTemp)) {
106
+ if (entry.endsWith(".sh") || /^git-credentials-.*\.config$/.test(entry)) {
107
+ tryUnlink(join(runnerTemp, entry));
108
+ }
109
+ }
110
+
111
+ if (wiped.length > 0) {
112
+ log.info(`» wiped ${wiped.length} leak-surface file(s) from $RUNNER_TEMP`);
113
+ log.debug(`» wiped paths: ${wiped.join(", ")}`);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Setup the test repository for running actions
119
+ */
120
+ export function setupTestRepo(options: SetupOptions): void {
121
+ const tempDir = options.tempDir;
122
+ const repo = process.env.GITHUB_REPOSITORY;
123
+ if (!repo) throw new Error("GITHUB_REPOSITORY is required");
124
+ log.info(`» cloning ${repo} into ${tempDir}...`);
125
+
126
+ // use https with token in ci or when running inside docker
127
+ if (process.env.CI || isInsideDocker) {
128
+ const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
129
+ if (!token) {
130
+ throw new Error(
131
+ "GITHUB_TOKEN or GH_TOKEN is required for https clone in ci or docker",
132
+ );
133
+ }
134
+ $("git", [
135
+ "clone",
136
+ `https://x-access-token:${token}@github.com/${repo}.git`,
137
+ tempDir,
138
+ ]);
139
+ } else {
140
+ $("git", ["clone", `git@github.com:${repo}.git`, tempDir]);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * build an env suitable for targeting a specific git repo via `cwd`.
146
+ *
147
+ * inherited GIT_DIR / GIT_WORK_TREE / GIT_INDEX_FILE override cwd resolution,
148
+ * which matters when this code runs as a child of `git push` (pre-push hook)
149
+ * or inside another git subcommand. if we don't strip them, a call that
150
+ * names `repoDir` in cwd silently operates on the outer repo instead.
151
+ */
152
+ function envScopedToRepo(): NodeJS.ProcessEnv {
153
+ const scoped = { ...process.env };
154
+ for (const key of Object.keys(scoped)) {
155
+ if (key.startsWith("GIT_")) delete scoped[key];
156
+ }
157
+ return scoped;
158
+ }
159
+
160
+ /**
161
+ * remove any `[includeIf ...]` entries from the local git config so that
162
+ * actions/checkout-persisted credentials don't ride alongside ASKPASS-provided
163
+ * auth for subsequent git operations.
164
+ *
165
+ * SECURITY: git config subsection values can contain arbitrary characters
166
+ * including `$(...)` command substitutions, and `${IFS}` spacing tricks defeat
167
+ * naive split-on-space filtering. we read keys via the `-z` (null-terminated)
168
+ * output format and feed them to a spawn-array `git config --unset-all` so
169
+ * the shell never interpolates key contents — closing the RCE path that a
170
+ * string-interpolated `execSync(...)` would expose.
171
+ */
172
+ export function removeIncludeIfEntries(repoDir: string): void {
173
+ const env = envScopedToRepo();
174
+ let configOutput: string;
175
+ try {
176
+ configOutput = execSync(
177
+ "git config --local --get-regexp -z ^includeif\\.",
178
+ {
179
+ cwd: repoDir,
180
+ encoding: "utf-8",
181
+ stdio: "pipe",
182
+ env,
183
+ },
184
+ );
185
+ } catch {
186
+ log.debug("» no includeIf credential entries to remove");
187
+ return;
188
+ }
189
+ const seen = new Set<string>();
190
+ for (const entry of configOutput.split("\0")) {
191
+ if (!entry) continue;
192
+ // -z format: each entry is "<key>\n<value>". the key is up to the first newline.
193
+ const nl = entry.indexOf("\n");
194
+ const key = nl === -1 ? entry : entry.slice(0, nl);
195
+ if (!key || seen.has(key)) continue;
196
+ seen.add(key);
197
+ try {
198
+ // execFileSync (not execSync) so the key — which can contain arbitrary
199
+ // characters including shell metacharacters and $() command substitutions
200
+ // — is passed as an argv element and never interpolated by a shell.
201
+ // this is the load-bearing side of a9aa3b2b's injection fix.
202
+ execFileSync("git", ["config", "--local", "--unset-all", key], {
203
+ cwd: repoDir,
204
+ stdio: "pipe",
205
+ env,
206
+ });
207
+ } catch (error) {
208
+ log.debug(
209
+ `» failed to unset ${key}: ${error instanceof Error ? error.message : String(error)}`,
210
+ );
211
+ }
212
+ }
213
+ if (seen.size > 0)
214
+ log.info(
215
+ `» removed ${seen.size} includeIf credential ${seen.size === 1 ? "entry" : "entries"}`,
216
+ );
217
+ }
218
+
219
+ export interface GitContext {
220
+ gitToken: string;
221
+ owner: string;
222
+ name: string;
223
+ octokit: OctokitWithPlugins;
224
+ toolState: ToolState;
225
+ // shell permission level — controls hook and security behavior:
226
+ // enabled: full shell, hooks run, no restrictions
227
+ // restricted: MCP shell in stripped env, hooks run, token protection on auth ops
228
+ // disabled: no shell, hooks disabled globally, all code execution paths blocked
229
+ shell: ShellPermission;
230
+ postCheckoutScript: string | null;
231
+ }
232
+
233
+ export type SetupGitParams = GitContext;
234
+
235
+ /**
236
+ * setup git configuration and authentication for the repository.
237
+ * - configures git identity (user.email, user.name)
238
+ * - sets up authentication via gitToken (minimal contents:write)
239
+ *
240
+ * gitToken is a minimal-permission token (contents + workflows) used for git operations.
241
+ * it is assumed to be potentially exfiltratable, so it has limited scope.
242
+ */
243
+ export async function setupGit(params: SetupGitParams): Promise<void> {
244
+ const repoDir = process.cwd();
245
+
246
+ // 1. configure git identity
247
+ log.info("» setting up git configuration...");
248
+ try {
249
+ // check current config - only set defaults if not configured or using generic bot
250
+ let currentEmail = "";
251
+ try {
252
+ currentEmail = execSync("git config user.email", {
253
+ cwd: repoDir,
254
+ stdio: "pipe",
255
+ encoding: "utf-8",
256
+ }).trim();
257
+ } catch {
258
+ // not configured
259
+ }
260
+
261
+ const shouldSetDefaults =
262
+ !currentEmail ||
263
+ currentEmail === "github-actions[bot]@users.noreply.github.com";
264
+
265
+ if (shouldSetDefaults) {
266
+ // plain noreply email with no numeric account id — the upstream id
267
+ // resolved commits to the wrong bot account on GitHub.
268
+ execSync(`git config --local user.email "${BOT_EMAIL}"`, {
269
+ cwd: repoDir,
270
+ stdio: "pipe",
271
+ });
272
+ execSync(`git config --local user.name "${BOT_LOGIN}"`, {
273
+ cwd: repoDir,
274
+ stdio: "pipe",
275
+ });
276
+ log.debug("» git user configured (using defaults)");
277
+ } else {
278
+ log.debug(`» git user already configured (${currentEmail}), skipping`);
279
+ }
280
+
281
+ // SECURITY: disable git hooks when shell is disabled to prevent code execution.
282
+ // in restricted mode, hooks run in the stripped sandbox — that's fine.
283
+ // in enabled mode, the agent has full shell anyway.
284
+ // in disabled mode, hooks are the primary code-execution escape vector.
285
+ if (params.shell === "disabled") {
286
+ execSync("git config --local core.hooksPath /dev/null", {
287
+ cwd: repoDir,
288
+ stdio: "pipe",
289
+ });
290
+ log.debug("» git hooks disabled (shell=disabled)");
291
+ }
292
+ } catch (error) {
293
+ // If git config fails, log warning but don't fail the action
294
+ // This can happen if we're not in a git repo or git isn't available
295
+ log.info(
296
+ `Failed to set git config: ${error instanceof Error ? error.message : String(error)}`,
297
+ );
298
+ }
299
+
300
+ // 2. setup authentication
301
+ // remove existing git auth headers that actions/checkout might have set
302
+ try {
303
+ execSync(
304
+ "git config --local --unset-all http.https://github.com/.extraheader",
305
+ {
306
+ cwd: repoDir,
307
+ stdio: "pipe",
308
+ },
309
+ );
310
+ log.info("» removed existing authentication headers");
311
+ } catch {
312
+ log.debug("» no existing authentication headers to remove");
313
+ }
314
+
315
+ // remove includeIf entries that actions/checkout@v6 uses for credential persistence.
316
+ // v6 stores credentials in an external file loaded via includeIf.gitdir, which our
317
+ // --unset-all above doesn't catch. without this, stale credentials from actions/checkout
318
+ // would be sent alongside ASKPASS-provided credentials.
319
+ removeIncludeIfEntries(repoDir);
320
+
321
+ // SECURITY: set origin URL without token - auth is injected via GIT_ASKPASS
322
+ // in $git() calls. this prevents token leakage to git hooks and subprocesses.
323
+ const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
324
+ $("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
325
+
326
+ // initialize pushUrl to base repo - may be updated by checkout_pr for fork PRs
327
+ params.toolState.pushUrl = originUrl;
328
+
329
+ // disable credential helpers to prevent prompts and ensure clean auth state
330
+ $("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
331
+
332
+ // pin the run-entry HEAD for the checkout_pr initial-branch invariant; see
333
+ // captureInitialHead for the named-branch vs detached split and why it
334
+ // matters (zed-industries/cloud 2026-05-18 cross-PR clobber shape).
335
+ params.toolState.initialHead = captureInitialHead(repoDir);
336
+
337
+ log.info("» git authentication configured");
338
+ }
339
+
340
+ /**
341
+ * snapshot the current HEAD as either a branch name (when on a named branch)
342
+ * or a literal SHA (when detached). used by setupGit to pin the run-entry
343
+ * position and by checkout_pr to compare the live HEAD against it.
344
+ *
345
+ * splitting the two cases is load-bearing: `git rev-parse --abbrev-ref HEAD`
346
+ * returns the sentinel string `"HEAD"` on detached entry — which is the
347
+ * default `actions/checkout` state for `pull_request` events. storing that
348
+ * raw string would make any future detached state (including a subagent's
349
+ * `git checkout --detach <sha>`) compare equal.
350
+ */
351
+ export function captureInitialHead(
352
+ repoDir: string,
353
+ ): { kind: "branch"; name: string } | { kind: "detached"; sha: string } {
354
+ try {
355
+ const name = $("git", ["symbolic-ref", "--short", "HEAD"], {
356
+ cwd: repoDir,
357
+ log: false,
358
+ }).trim();
359
+ if (name) return { kind: "branch", name };
360
+ } catch {
361
+ // detached HEAD — fall through
362
+ }
363
+ const sha = $("git", ["rev-parse", "HEAD"], {
364
+ cwd: repoDir,
365
+ log: false,
366
+ }).trim();
367
+ return { kind: "detached", sha };
368
+ }
@@ -0,0 +1,132 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { type EnvMode, resolveEnv } from "#app/utils/secrets";
3
+
4
+ interface ShellOptions {
5
+ cwd?: string;
6
+ encoding?:
7
+ | "utf-8"
8
+ | "utf8"
9
+ | "ascii"
10
+ | "base64"
11
+ | "base64url"
12
+ | "hex"
13
+ | "latin1"
14
+ | "ucs-2"
15
+ | "ucs2"
16
+ | "utf16le";
17
+ log?: boolean;
18
+ /**
19
+ * env mode: "restricted" (default) filters secrets, "inherit" passes full env,
20
+ * or provide a custom env object (merged with restricted base)
21
+ */
22
+ env?: EnvMode;
23
+ onError?: (result: { status: number; stdout: string; stderr: string }) => void;
24
+ /** wall-clock cap in ms; defaults to DEFAULT_TIMEOUT_MS. a stalled remote or
25
+ * wedged repo hook would otherwise hang until the run-level idle watchdog. */
26
+ timeoutMs?: number;
27
+ /** stdout/stderr cap in bytes; defaults to DEFAULT_MAX_BUFFER. node's 1 MiB
28
+ * spawnSync default silently truncates large `git diff` output into a
29
+ * generic failure. */
30
+ maxBuffer?: number;
31
+ }
32
+
33
+ /** every `$` caller is a git invocation; the longest legitimate one is a
34
+ * clone/fetch of a large repo, well under this. */
35
+ export const DEFAULT_TIMEOUT_MS = 10 * 60_000;
36
+ /** big-PR `git diff` output can far exceed node's 1 MiB default. */
37
+ export const DEFAULT_MAX_BUFFER = 64 * 1024 * 1024;
38
+
39
+ /**
40
+ * Execute a shell command safely using spawnSync with argument arrays.
41
+ * Prevents shell injection by avoiding string interpolation in shell commands.
42
+ *
43
+ * SECURITY: by default, env vars are filtered to remove secrets (tokens, keys, passwords).
44
+ * this prevents malicious code (git hooks, npm scripts, etc.) from exfiltrating credentials.
45
+ * use env: "inherit" only when absolutely necessary.
46
+ *
47
+ * @param cmd - The command to execute
48
+ * @param args - Array of arguments to pass to the command
49
+ * @param options - Optional configuration (cwd, encoding, onError)
50
+ * @returns The trimmed stdout output
51
+ * @throws Error if command fails and no onError handler is provided
52
+ */
53
+ export function $(cmd: string, args: string[], options?: ShellOptions): string {
54
+ const encoding = options?.encoding ?? "utf-8";
55
+ const env = resolveEnv(options?.env);
56
+
57
+ // CRITICAL: use "ignore" for stdin instead of "inherit" to avoid breaking MCP transport
58
+ // when running inside an MCP server, stdin is used for JSON-RPC protocol
59
+ const timeout = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
60
+ const result = spawnSync(cmd, args, {
61
+ stdio: ["ignore", "pipe", "pipe"],
62
+ encoding,
63
+ cwd: options?.cwd,
64
+ env,
65
+ timeout,
66
+ maxBuffer: options?.maxBuffer ?? DEFAULT_MAX_BUFFER,
67
+ });
68
+
69
+ const stdout = result.stdout ?? "";
70
+ const stderr = result.stderr ?? "";
71
+
72
+ // Write output to process streams so it behaves like stdio: "inherit"
73
+ // CRITICAL: when running inside an MCP server, stdout is used for JSON-RPC protocol
74
+ // so we must write to stderr instead to avoid corrupting the protocol
75
+ // Only log if log option is not explicitly set to false
76
+ if (options?.log !== false) {
77
+ // if stdout is a TTY, it's safe to write to it; otherwise it's likely a pipe used for JSON-RPC
78
+ const canWriteToStdout = process.stdout.isTTY === true;
79
+ if (stdout) {
80
+ if (canWriteToStdout) {
81
+ process.stdout.write(stdout);
82
+ } else {
83
+ // stdout is a pipe (MCP context) - write to stderr instead
84
+ process.stderr.write(stdout);
85
+ }
86
+ }
87
+ if (stderr) {
88
+ process.stderr.write(stderr);
89
+ }
90
+ }
91
+
92
+ // Handle errors
93
+ if (result.status !== 0) {
94
+ const errorResult = {
95
+ status: result.status ?? -1,
96
+ stdout,
97
+ stderr,
98
+ };
99
+
100
+ if (options?.onError) {
101
+ options.onError(errorResult);
102
+ return stdout.trim();
103
+ }
104
+
105
+ // spawn-level failures (timeout, output-cap overflow, missing binary)
106
+ // report through result.error with status null — name the cause instead
107
+ // of a generic failure so the agent can react (narrow the diff, retry).
108
+ const code = (result.error as NodeJS.ErrnoException | undefined)?.code;
109
+ if (code === "ETIMEDOUT") {
110
+ throw new Error(`Command timed out after ${timeout}ms: ${cmd} ${args.join(" ")}`);
111
+ }
112
+ if (code === "ENOBUFS") {
113
+ throw new Error(
114
+ `Command output exceeded the ${options?.maxBuffer ?? DEFAULT_MAX_BUFFER}-byte cap: ${cmd} ${args.join(" ")} — narrow the invocation (e.g. path-limit the diff)`,
115
+ );
116
+ }
117
+
118
+ // many git subcommands write context-bearing diagnostics to stdout, not
119
+ // stderr (merge conflicts, cherry-pick rejections, diff --exit-code,
120
+ // ls-files --error-unmatch). Falling back to "Unknown error" robbed the
121
+ // agent of any signal and forced an extra MCP round-trip. see #766.
122
+ const detail = [stderr, stdout, result.error?.message]
123
+ .map((s) => s?.trim())
124
+ .filter(Boolean)
125
+ .join("\n");
126
+ throw new Error(
127
+ `Command failed with exit code ${errorResult.status}: ${detail || "Unknown error"}`,
128
+ );
129
+ }
130
+
131
+ return stdout.trim();
132
+ }
@@ -0,0 +1,67 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { log } from "#app/utils/cli";
5
+
6
+ /**
7
+ * skills bundled with the action runtime. the SKILL.md files live in
8
+ * `action/skills/<name>/SKILL.md` and are read at runtime — no esbuild loader,
9
+ * no codegen. this matters because the preview / oss path runs `cli.ts` from
10
+ * source (see `runCli.ts#runLocalCli`) where esbuild loaders don't apply.
11
+ */
12
+ const BUNDLED_SKILL_NAMES = ["terraform-best-practices"] as const;
13
+
14
+ /**
15
+ * resolve the on-disk path of a bundled SKILL.md by checking the two locations
16
+ * the file may live in:
17
+ * - source mode (`runLocalCli`): `<actionRoot>/skills/<name>/SKILL.md`,
18
+ * reached as `../skills/...` from `utils/skills.ts`.
19
+ * - bundled mode (npx published package): `<distDir>/skills/<name>/SKILL.md`,
20
+ * reached as `./skills/...` from `dist/cli.mjs`.
21
+ *
22
+ * the bundled-mode copy is produced by an esbuild post-build step in
23
+ * `esbuild.config.js`.
24
+ */
25
+ function resolveSkillPath(name: string): string {
26
+ const here = dirname(fileURLToPath(import.meta.url));
27
+ const candidates = [
28
+ join(here, "..", "skills", name, "SKILL.md"),
29
+ join(here, "skills", name, "SKILL.md"),
30
+ ];
31
+ for (const candidate of candidates) {
32
+ if (existsSync(candidate)) return candidate;
33
+ }
34
+ throw new Error(`bundled skill not found: ${name} (looked in ${candidates.join(", ")})`);
35
+ }
36
+
37
+ /**
38
+ * each agent has its own auto-scan dir under HOME. we write to all of them so
39
+ * the same `installBundledSkills` call works regardless of which agent is
40
+ * running, without coupling skills.ts to agent identity.
41
+ *
42
+ * verified empirically (PR #565):
43
+ * - OpenCode registers skills from `$HOME/.agents/skills/` and `.opencode/skills/`.
44
+ * - Claude Code only registers skills from `$HOME/.claude/skills/` —
45
+ * it does NOT scan `.agents/skills/`, so writing only there leaves the
46
+ * skill on disk but invisible to Claude's `Skill` tool.
47
+ */
48
+ const SKILL_TARGET_DIRS = [".opencode/skills", ".claude/skills", ".agents/skills"] as const;
49
+
50
+ /**
51
+ * write all bundled skills into the fake HOME so OpenCode / Claude Code discover
52
+ * them via their auto-scan directories.
53
+ *
54
+ * called once per agent run from each agent's `run()`. cheap (small file
55
+ * writes), no network, idempotent.
56
+ */
57
+ export function installBundledSkills(params: { home: string }): void {
58
+ for (const name of BUNDLED_SKILL_NAMES) {
59
+ const content = readFileSync(resolveSkillPath(name), "utf8");
60
+ for (const targetDir of SKILL_TARGET_DIRS) {
61
+ const skillDir = join(params.home, targetDir, name);
62
+ mkdirSync(skillDir, { recursive: true });
63
+ writeFileSync(join(skillDir, "SKILL.md"), content);
64
+ }
65
+ }
66
+ log.success(`installed bundled skills: ${BUNDLED_SKILL_NAMES.join(", ")}`);
67
+ }