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,551 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ import { CONFIG_FILE, CONFIG_FILE_JSON } from "#app/brand";
5
+ import { isPathAllowed } from "#app/mcp/guardrails";
6
+ import { NATIVE_SOURCE } from "#app/mcp/terraform/nativeRules";
7
+ import type { Concern, ConcernSuppression } from "#app/mcp/terraform/types";
8
+ import { neutralizeMarkup } from "#app/mcp/untrustedContent";
9
+ import { readConfigAtBaseRef } from "#app/utils/baseRefConfig";
10
+ import { log } from "#app/utils/cli";
11
+ import { INFRAWEAVER_CONFIG_FILENAMES } from "#app/utils/infraweaverConfig";
12
+
13
+ export type SuppressionSource = ConcernSuppression["source"];
14
+
15
+ export interface Suppression {
16
+ source: SuppressionSource;
17
+ rule: string;
18
+ reason: string;
19
+ expires: string | null;
20
+ paths: string[];
21
+ file: string | null;
22
+ /** Set when this came from a NATIVE scanner skip directive (checkov/tfsec/trivy)
23
+ * rather than a `#infraweaver:ignore`. The owning scanner already honours it; we
24
+ * carry the provenance so the unified audit trail shows where it came from. */
25
+ tool?: string;
26
+ }
27
+
28
+ export interface ParsedSuppressions {
29
+ suppressions: Suppression[];
30
+ warnings: string[];
31
+ }
32
+
33
+ const NAMESPACES: ReadonlySet<string> = new Set([
34
+ "trivy",
35
+ "checkov",
36
+ "tflint",
37
+ "tfsec",
38
+ "terraform-fmt",
39
+ "terraform-validate",
40
+ // the native rule pack — `#infraweaver:ignore:infraweaver:<rule>: reason`. The bare
41
+ // form (`#infraweaver:ignore:<rule>: reason`) also works via `ruleMatches`.
42
+ NATIVE_SOURCE,
43
+ ]);
44
+
45
+ const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
46
+ const INLINE_DIRECTIVE = /#\s*infraweaver:ignore:(.+)$/i;
47
+ const EXPIRES_TOKEN = /\b(?:expires|until)=(\d{4}-\d{2}-\d{2})\b/i;
48
+
49
+ function splitRuleAndReason(
50
+ rest: string,
51
+ ): { rule: string; reason: string } | null {
52
+ const parts = rest.split(":");
53
+ if (parts.length < 2) return null;
54
+ const first = (parts[0] ?? "").trim();
55
+ let rule: string;
56
+ let reasonParts: string[];
57
+ if (NAMESPACES.has(first.toLowerCase()) && parts.length >= 3) {
58
+ rule = `${first}:${(parts[1] ?? "").trim()}`;
59
+ reasonParts = parts.slice(2);
60
+ } else {
61
+ rule = first;
62
+ reasonParts = parts.slice(1);
63
+ }
64
+ const reason = reasonParts.join(":").trim();
65
+ if (!rule || !reason) return null;
66
+ return { rule, reason };
67
+ }
68
+
69
+ function extractExpiry(reason: string): {
70
+ reason: string;
71
+ expires: string | null;
72
+ } {
73
+ const match = reason.match(EXPIRES_TOKEN);
74
+ if (!match) return { reason, expires: null };
75
+ const cleaned = reason
76
+ .replace(EXPIRES_TOKEN, "")
77
+ .replace(/\s{2,}/g, " ")
78
+ .trim();
79
+ return { reason: cleaned, expires: match[1] ?? null };
80
+ }
81
+
82
+ export function parseInlineSuppressions(
83
+ content: string,
84
+ file: string,
85
+ ): ParsedSuppressions {
86
+ const suppressions: Suppression[] = [];
87
+ const warnings: string[] = [];
88
+ const lines = content.split(/\r?\n/);
89
+ for (let i = 0; i < lines.length; i++) {
90
+ const line = lines[i] ?? "";
91
+ const directive = line.match(INLINE_DIRECTIVE);
92
+ if (!directive) continue;
93
+ const split = splitRuleAndReason((directive[1] ?? "").trim());
94
+ if (!split) {
95
+ warnings.push(
96
+ `${file}:${i + 1}: #infraweaver:ignore needs <rule>:<reason> — "${line.trim()}" ignored`,
97
+ );
98
+ continue;
99
+ }
100
+ const { reason: rawReason, expires } = extractExpiry(split.reason);
101
+ // LLM01. The reason is free text written by whoever authored the file under
102
+ // examination, and it travels a long way: into the agent's context via
103
+ // `terraform_scan`'s `suppressed[].suppression`, and outward into the SARIF
104
+ // suppression justification and the PR body. Neutralise the markup here, at
105
+ // the single parse point, rather than at each of those surfaces. The
106
+ // directive is matched per line, so the newline collapse is a no-op and the
107
+ // reason stays readable. A reason that neutralises to nothing was never a
108
+ // reason — it falls into the existing "needs a reason" warning below.
109
+ const reason = neutralizeMarkup(rawReason);
110
+ if (!reason) {
111
+ warnings.push(
112
+ `${file}:${i + 1}: #infraweaver:ignore needs a reason — ignored`,
113
+ );
114
+ continue;
115
+ }
116
+ suppressions.push({
117
+ source: "inline",
118
+ rule: split.rule,
119
+ reason,
120
+ expires,
121
+ paths: [],
122
+ file,
123
+ });
124
+ }
125
+ return { suppressions, warnings };
126
+ }
127
+
128
+ interface NativePattern {
129
+ tool: string;
130
+ re: RegExp;
131
+ }
132
+
133
+ // Native scanner skip directives. The owning scanner already honours these (so the
134
+ // finding never reaches Infraweaver), but we parse them too so a native skip is
135
+ // VISIBLE in Infraweaver's unified audit trail — carrying the scanner provenance —
136
+ // instead of silently vanishing. `#infraweaver:ignore` (above) remains the portable,
137
+ // reason-mandatory form; these stay honoured by their own scanners (pass-through).
138
+ const NATIVE_PATTERNS: readonly NativePattern[] = [
139
+ // checkov:skip=CKV_AWS_20[:optional reason]
140
+ {
141
+ tool: "checkov",
142
+ re: /#\s*checkov:skip=([A-Za-z0-9_]+)(?::\s*(.*\S))?\s*$/i,
143
+ },
144
+ // tfsec:ignore:rule[:exp:YYYY-MM-DD]
145
+ {
146
+ tool: "tfsec",
147
+ re: /#\s*tfsec:ignore:([A-Za-z0-9._-]+)(?::exp:(\d{4}-\d{2}-\d{2}))?\s*$/i,
148
+ },
149
+ // trivy:ignore:rule [exp:YYYY-MM-DD]
150
+ {
151
+ tool: "trivy",
152
+ re: /#\s*trivy:ignore:([A-Za-z0-9._\-*]+)(?:\s+exp:(\d{4}-\d{2}-\d{2}))?\s*$/i,
153
+ },
154
+ ];
155
+
156
+ /** A native scanner-skip directive with its source location — the line-aware shape
157
+ * behind both the suppression pipeline and the orphan-skip audit. */
158
+ export interface NativeSkip {
159
+ tool: string;
160
+ /** namespaced rule, e.g. "checkov:CKV_AWS_20" — matches a concern's `rule_id`. */
161
+ rule: string;
162
+ reason: string;
163
+ expires: string | null;
164
+ file: string;
165
+ /** 1-based line of the directive. */
166
+ line: number;
167
+ }
168
+
169
+ /** Collect every native scanner-skip directive in a file, WITH line numbers. The
170
+ * single source of truth for native-skip parsing (used by the suppression pipeline
171
+ * and the orphan-skip audit). At most one directive per line. */
172
+ export function collectNativeSkips(
173
+ content: string,
174
+ file: string,
175
+ ): NativeSkip[] {
176
+ const out: NativeSkip[] = [];
177
+ const lines = content.split(/\r?\n/);
178
+ for (let i = 0; i < lines.length; i++) {
179
+ const line = lines[i] ?? "";
180
+ for (const { tool, re } of NATIVE_PATTERNS) {
181
+ const m = line.match(re);
182
+ if (!m) continue;
183
+ const ruleId = (m[1] ?? "").trim();
184
+ if (!ruleId) break;
185
+ // checkov captures a reason in group 2; tfsec/trivy capture an expiry there.
186
+ // The reason is repo-authored free text — neutralised for the same reason
187
+ // as `parseInlineSuppressions` below, and it reaches one channel that form
188
+ // doesn't: `orphan_native_skips[].reason`, which is surfaced precisely
189
+ // because nothing else audits it.
190
+ const reason = tool === "checkov" ? neutralizeMarkup(m[2] ?? "") : "";
191
+ const expires = tool === "checkov" ? null : (m[2] ?? null);
192
+ out.push({
193
+ tool,
194
+ rule: `${tool}:${ruleId}`,
195
+ reason: reason || `Native ${tool} skip directive`,
196
+ expires,
197
+ file,
198
+ line: i + 1,
199
+ });
200
+ break; // at most one directive per line
201
+ }
202
+ }
203
+ return out;
204
+ }
205
+
206
+ /**
207
+ * Parse native scanner skip directives (`#checkov:skip=…`, `#tfsec:ignore:…`,
208
+ * `#trivy:ignore:…`) into the unified `Suppression` shape so they can be honoured
209
+ * and audited alongside `#infraweaver:ignore`. Native skips don't mandate a reason
210
+ * (their tools don't), so a synthetic one records the provenance. The rule is
211
+ * namespaced (`checkov:CKV_AWS_20`) so it matches a surviving concern's `rule_id`.
212
+ */
213
+ export function parseNativeSuppressions(
214
+ content: string,
215
+ file: string,
216
+ ): ParsedSuppressions {
217
+ const suppressions: Suppression[] = collectNativeSkips(content, file).map(
218
+ (s) => ({
219
+ source: "inline",
220
+ tool: s.tool,
221
+ rule: s.rule,
222
+ reason: s.reason,
223
+ expires: s.expires,
224
+ paths: [],
225
+ file: s.file,
226
+ }),
227
+ );
228
+ return { suppressions, warnings: [] };
229
+ }
230
+
231
+ /**
232
+ * Native skips that NO concern corresponds to — the owning scanner already dropped
233
+ * the finding (or the rule never fired), so the skip is invisible to Infraweaver's
234
+ * gate and posture. Surfacing these keeps scanner-native suppressions auditable
235
+ * (a `#checkov:skip` can silently hide a real issue forever). A skip "matches" a
236
+ * concern when its rule matches (exact / bare / `:suffix`) AND the file is the same.
237
+ * Canonical cross-rule matching (a trivy skip vs a checkov concern for the *same*
238
+ * issue) is a future taxonomy refinement — see `taxonomy.ts`.
239
+ */
240
+ export function findOrphanNativeSkips(
241
+ skips: NativeSkip[],
242
+ concerns: Concern[],
243
+ ): NativeSkip[] {
244
+ return skips.filter(
245
+ (s) =>
246
+ !concerns.some(
247
+ (c) => c.location.file === s.file && ruleMatches(s.rule, c),
248
+ ),
249
+ );
250
+ }
251
+
252
+ export interface NativeSkipAudit {
253
+ /** every native skip found in the scanned tree. */
254
+ skips: NativeSkip[];
255
+ /** the subset with no corresponding concern (the audit signal). */
256
+ orphans: NativeSkip[];
257
+ }
258
+
259
+ /**
260
+ * Walk a file list, collect native skips, and partition them against the scan's
261
+ * concern set. `read` returns a file's content or null (missing). Pure given its
262
+ * inputs, so it's unit-testable without a real tree.
263
+ */
264
+ export function auditNativeSkips(
265
+ files: string[],
266
+ concerns: Concern[],
267
+ read: (relPath: string) => string | null,
268
+ ): NativeSkipAudit {
269
+ const skips: NativeSkip[] = [];
270
+ for (const f of files) {
271
+ const content = read(f);
272
+ if (content === null) continue;
273
+ skips.push(...collectNativeSkips(content, f));
274
+ }
275
+ return { skips, orphans: findOrphanNativeSkips(skips, concerns) };
276
+ }
277
+
278
+ interface RawPolicyEntry {
279
+ rule?: unknown;
280
+ reason?: unknown;
281
+ expires?: unknown;
282
+ paths?: unknown;
283
+ }
284
+
285
+ function normalizePaths(value: unknown): string[] {
286
+ if (typeof value === "string") {
287
+ return value
288
+ .split(/[\n,]/)
289
+ .map((s) => s.trim())
290
+ .filter(Boolean);
291
+ }
292
+ if (Array.isArray(value)) {
293
+ return value
294
+ .filter((v): v is string => typeof v === "string")
295
+ .map((v) => v.trim())
296
+ .filter(Boolean);
297
+ }
298
+ return [];
299
+ }
300
+
301
+ export function parseSuppressionPolicy(
302
+ raw: string,
303
+ format: "yaml" | "json",
304
+ ): ParsedSuppressions {
305
+ const label = format === "json" ? CONFIG_FILE_JSON : CONFIG_FILE;
306
+ const suppressions: Suppression[] = [];
307
+ const warnings: string[] = [];
308
+ let doc: unknown;
309
+ try {
310
+ if (format === "json") {
311
+ if (raw.trim() === "") return { suppressions, warnings };
312
+ doc = JSON.parse(raw);
313
+ } else {
314
+ doc = parseYaml(raw);
315
+ }
316
+ } catch {
317
+ return { suppressions, warnings };
318
+ }
319
+ if (!doc || typeof doc !== "object" || Array.isArray(doc))
320
+ return { suppressions, warnings };
321
+ const block = (doc as Record<string, unknown>).suppressions;
322
+ if (block === undefined) return { suppressions, warnings };
323
+ if (!Array.isArray(block)) {
324
+ warnings.push(
325
+ `${label}: "suppressions" must be a list of { rule, reason } entries — ignored`,
326
+ );
327
+ return { suppressions, warnings };
328
+ }
329
+ block.forEach((entry, idx) => {
330
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
331
+ warnings.push(
332
+ `${label}: suppressions[${idx}] must be a mapping — ignored`,
333
+ );
334
+ return;
335
+ }
336
+ const e = entry as RawPolicyEntry;
337
+ const rule = typeof e.rule === "string" ? e.rule.trim() : "";
338
+ // Neutralised like the two inline forms above, so all three suppression
339
+ // sources are treated identically at their parse point. This one is
340
+ // base-ref-read (a fork PR cannot introduce it), but it is the only form
341
+ // that can carry a multi-line YAML scalar — exactly the shape that renders
342
+ // as its own section in a PR body.
343
+ const reason =
344
+ typeof e.reason === "string" ? neutralizeMarkup(e.reason) : "";
345
+ if (!rule || !reason) {
346
+ warnings.push(
347
+ `${label}: suppressions[${idx}] needs a non-empty "rule" and "reason" — ignored`,
348
+ );
349
+ return;
350
+ }
351
+ let expires: string | null = null;
352
+ if (e.expires !== undefined && e.expires !== null) {
353
+ const exp = String(e.expires).trim();
354
+ if (!ISO_DATE.test(exp)) {
355
+ warnings.push(
356
+ `${label}: suppressions[${idx}] "expires" must be YYYY-MM-DD — entry ignored`,
357
+ );
358
+ return;
359
+ }
360
+ expires = exp;
361
+ }
362
+ suppressions.push({
363
+ source: "policy",
364
+ rule,
365
+ reason,
366
+ expires,
367
+ paths: normalizePaths(e.paths),
368
+ file: null,
369
+ });
370
+ });
371
+ return { suppressions, warnings };
372
+ }
373
+
374
+ export function loadSuppressionPolicy(
375
+ cwd: string | undefined,
376
+ ): ParsedSuppressions {
377
+ const root = cwd ?? process.cwd();
378
+ for (const name of INFRAWEAVER_CONFIG_FILENAMES) {
379
+ let raw: string;
380
+ try {
381
+ raw = readFileSync(join(root, name), "utf-8");
382
+ } catch {
383
+ continue;
384
+ }
385
+ return parseSuppressionPolicy(
386
+ raw,
387
+ name.endsWith(".json") ? "json" : "yaml",
388
+ );
389
+ }
390
+ return { suppressions: [], warnings: [] };
391
+ }
392
+
393
+ /**
394
+ * The suppression policy that APPLIES to this run.
395
+ *
396
+ * On a pull-request run the `suppressions:` block is read from the **base ref**,
397
+ * not the PR's head: a waiver is an accepted risk, and accepting it is exactly
398
+ * what the review is for. Letting a PR silence the finding that would otherwise
399
+ * block it is the self-approval hole the two-person SoD on waivers (§5.3) exists
400
+ * to close — this closes the file-shaped version of it. A PR that adds a waiver
401
+ * still sees the finding; the waiver applies from the next run on the merged base.
402
+ *
403
+ * Everything degrades to the head value with a warning when the base ref can't
404
+ * be read (shallow clone) or the run isn't a PR — stated, never silent.
405
+ */
406
+ export function loadSuppressionPolicyForRun(
407
+ cwd: string | undefined,
408
+ ): ParsedSuppressions {
409
+ const root = cwd ?? process.cwd();
410
+ const baseRef = process.env.GITHUB_BASE_REF?.trim() || undefined;
411
+ if (!baseRef) return loadSuppressionPolicy(root);
412
+
413
+ const source = readConfigAtBaseRef(root, baseRef);
414
+ if (source.kind === "unavailable") {
415
+ const head = loadSuppressionPolicy(root);
416
+ if (head.suppressions.length > 0) {
417
+ head.warnings.push(
418
+ `could not read the base ref (${baseRef}) to resolve the suppression policy — applying ` +
419
+ `this ref's ${head.suppressions.length} suppression(s). A shallow clone causes this; ` +
420
+ "`fetch-depth: 0` (or fetching the base branch) restores the check.",
421
+ );
422
+ }
423
+ return head;
424
+ }
425
+
426
+ const base =
427
+ source.kind === "file"
428
+ ? parseSuppressionPolicy(source.raw, source.format)
429
+ : { suppressions: [], warnings: [] };
430
+ const headCount = loadSuppressionPolicy(root).suppressions.length;
431
+ if (headCount !== base.suppressions.length) {
432
+ base.warnings.push(
433
+ `the suppression policy differs from the base ref (${source.ref}) — applying the BASE ` +
434
+ `policy (${base.suppressions.length} entry/entries, not ${headCount}) so this change ` +
435
+ "cannot waive the findings reviewing it. It takes effect once merged.",
436
+ );
437
+ }
438
+ return base;
439
+ }
440
+
441
+ function toIsoDate(d: Date): string {
442
+ return d.toISOString().slice(0, 10);
443
+ }
444
+
445
+ function isActive(s: Suppression, now: Date): boolean {
446
+ if (!s.expires) return true;
447
+ return s.expires >= toIsoDate(now);
448
+ }
449
+
450
+ function ruleMatches(rule: string, concern: Concern): boolean {
451
+ const wanted = rule.toLowerCase();
452
+ const ruleId = concern.rule_id.toLowerCase();
453
+ if (ruleId === wanted) return true;
454
+ const prefix = `${concern.source.toLowerCase()}:`;
455
+ const bare = ruleId.startsWith(prefix) ? ruleId.slice(prefix.length) : ruleId;
456
+ if (bare === wanted) return true;
457
+ return ruleId.endsWith(`:${wanted}`);
458
+ }
459
+
460
+ function scopeMatches(s: Suppression, file: string): boolean {
461
+ if (s.source === "inline") return s.file === file;
462
+ if (s.paths.length === 0) return true;
463
+ return isPathAllowed(file, s.paths);
464
+ }
465
+
466
+ function matches(s: Suppression, concern: Concern, now: Date): boolean {
467
+ return (
468
+ isActive(s, now) &&
469
+ ruleMatches(s.rule, concern) &&
470
+ scopeMatches(s, concern.location.file)
471
+ );
472
+ }
473
+
474
+ export interface ApplySuppressionsOptions {
475
+ policy: Suppression[];
476
+ cwd: string;
477
+ now?: Date;
478
+ readFile?: (relPath: string) => string | null;
479
+ onWarn?: (warning: string) => void;
480
+ }
481
+
482
+ export function applySuppressions(
483
+ concerns: Concern[],
484
+ opts: ApplySuppressionsOptions,
485
+ ): Concern[] {
486
+ const now = opts.now ?? new Date();
487
+ const read = opts.readFile ?? ((rel) => defaultRead(opts.cwd, rel));
488
+ const inlineByFile = new Map<string, Suppression[]>();
489
+
490
+ const inlineFor = (file: string): Suppression[] => {
491
+ const cached = inlineByFile.get(file);
492
+ if (cached) return cached;
493
+ const content = read(file);
494
+ const parsed =
495
+ content === null ? [] : collectInline(content, file, opts.onWarn);
496
+ inlineByFile.set(file, parsed);
497
+ return parsed;
498
+ };
499
+
500
+ return concerns.map((concern) => {
501
+ const candidates = [...inlineFor(concern.location.file), ...opts.policy];
502
+ const hit = candidates.find((s) => matches(s, concern, now));
503
+ if (!hit) return concern;
504
+ return {
505
+ ...concern,
506
+ // A native skip keeps source "inline" (it IS an inline directive) but tags its
507
+ // scanner provenance into the reason so the audit trail shows where it came from.
508
+ suppression: {
509
+ source: hit.source,
510
+ reason: hit.tool ? `${hit.reason} [via ${hit.tool} skip]` : hit.reason,
511
+ expires: hit.expires,
512
+ },
513
+ };
514
+ });
515
+ }
516
+
517
+ function collectInline(
518
+ content: string,
519
+ file: string,
520
+ onWarn: ((warning: string) => void) | undefined,
521
+ ): Suppression[] {
522
+ const inline = parseInlineSuppressions(content, file);
523
+ // Also fold in native scanner skips so they're honoured + audited in one pipeline.
524
+ const native = parseNativeSuppressions(content, file);
525
+ if (onWarn)
526
+ for (const w of [...inline.warnings, ...native.warnings]) onWarn(w);
527
+ return [...inline.suppressions, ...native.suppressions];
528
+ }
529
+
530
+ function defaultRead(cwd: string, rel: string): string | null {
531
+ try {
532
+ return readFileSync(join(cwd, rel), "utf-8");
533
+ } catch {
534
+ return null;
535
+ }
536
+ }
537
+
538
+ export function suppressConcerns(
539
+ concerns: Concern[],
540
+ cwd: string,
541
+ now?: Date,
542
+ ): Concern[] {
543
+ const { suppressions, warnings } = loadSuppressionPolicyForRun(cwd);
544
+ for (const w of warnings) log.warning(`» ${w}`);
545
+ return applySuppressions(concerns, {
546
+ policy: suppressions,
547
+ cwd,
548
+ ...(now ? { now } : {}),
549
+ onWarn: (w) => log.warning(`» ${w}`),
550
+ });
551
+ }
Binary file