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,382 @@
1
+ import { createHash } from "node:crypto";
2
+ import { toolSkip } from "#app/mcp/shared";
3
+ import type { IacLanguage } from "#app/mcp/terraform/iacLanguages";
4
+
5
+ /**
6
+ * A degrade-green skip result carrying the structured envelope
7
+ * (`ok: false` + machine `code` + human `detail`) PLUS the legacy alias the tool
8
+ * returned before it converged on the envelope — `ran`/`found` and
9
+ * `skipped_reason`/`reason` — so existing prompt + test contracts keep working.
10
+ * Additive, never breaking. `extra` folds in any tool-specific fields (e.g.
11
+ * read_findings' empty `concerns`/`groups`).
12
+ */
13
+ export function skipResult(
14
+ code: string,
15
+ detail: string,
16
+ opts: {
17
+ key?: "ran" | "found";
18
+ reasonKey?: "skipped_reason" | "reason";
19
+ extra?: Record<string, any>;
20
+ } = {},
21
+ ): Record<string, any> {
22
+ const key = opts.key ?? "ran";
23
+ const reasonKey = opts.reasonKey ?? "skipped_reason";
24
+ return {
25
+ ...toolSkip(code, detail),
26
+ [key]: false,
27
+ [reasonKey]: detail,
28
+ ...(opts.extra ?? {}),
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Internal "concern" model — the Remediator's ground truth for "what is not
34
+ * best practice". Produced by `terraform_scan` from the fork's own deterministic
35
+ * Terraform check tools (fmt / validate / tflint / trivy / checkov).
36
+ *
37
+ * This is a deliberate SUBSET of the reviewer's `findings.schema.json` v1.0
38
+ * (../terraform-reviewer/schemas/findings.schema.json). The reviewer's findings
39
+ * add `lens` / `standard` / `control_id` / `state` on top. Keeping the shape a
40
+ * subset means a future reviewer integration (read_findings) can emit the same
41
+ * Concern[] with no change to the modes or the rest of the tools — only the
42
+ * SOURCE of concerns swaps.
43
+ */
44
+ export interface Concern {
45
+ /** stable content id: sha1(source|rule_id|file|line). idempotency key for branch/PR naming. */
46
+ id: string;
47
+ /** producing tool. `infraweaver` is the NATIVE rule pack ([[nativeRules]]) — the
48
+ * findings no upstream scanner can produce, re-derived on every scan so they stay
49
+ * ✗→✓ verifiable. `reviewer` marks a concern loaded from a terraform-reviewer
50
+ * findings.json whose original tool isn't one Infraweaver re-runs (tfsec / infracost
51
+ * / llm) — its provenance lives in `rule_id`. */
52
+ source:
53
+ | "terraform-fmt"
54
+ | "terraform-validate"
55
+ | "tflint"
56
+ | "trivy"
57
+ | "checkov"
58
+ | "infraweaver"
59
+ | "reviewer";
60
+ /** original namespaced rule, e.g. "trivy:AVD-AWS-0088" */
61
+ rule_id: string;
62
+ severity: Severity;
63
+ category: "security" | "style" | "correctness" | "cost";
64
+ /** the scanner message — what is wrong */
65
+ evidence: string;
66
+ location: { file: string; line: number | null };
67
+ /** the IaC language the flagged file is written in (from the scanner's own
68
+ * classification — trivy `Type` / checkov `check_type`). Absent on the
69
+ * Terraform-only scanners (fmt/validate/tflint) and reviewer-loaded concerns;
70
+ * scope filtering falls back to a path classification then terraform.
71
+ * NOT part of the content `id` — purely descriptive, additive. */
72
+ language?: IacLanguage;
73
+ /** the offending source line(s) the scanner flagged (trivy cause lines /
74
+ * checkov code block), so a reader sees the exact code, not just file:line.
75
+ * Absent when the scanner doesn't attach source context. */
76
+ code_snippet?: string | null;
77
+ remediation_hint: string | null;
78
+ suppression?: ConcernSuppression;
79
+ /** 2c taxonomy: the canonical resource+misconfig class this rule maps to (e.g.
80
+ * "aws-s3-encryption"), set when cross-scanner normalisation recognises it. */
81
+ canonical_class?: string;
82
+ /** 2c taxonomy: the scanner(s) that flagged this canonical issue, after a
83
+ * cross-scanner merge (e.g. ["checkov", "trivy"]). */
84
+ flagged_by?: string[];
85
+ }
86
+
87
+ export interface ConcernSuppression {
88
+ source: "inline" | "policy";
89
+ reason: string;
90
+ expires: string | null;
91
+ }
92
+
93
+ export const SEVERITIES = [
94
+ "critical",
95
+ "high",
96
+ "medium",
97
+ "low",
98
+ "info",
99
+ ] as const;
100
+ export type Severity = (typeof SEVERITIES)[number];
101
+
102
+ export const SEVERITY_RANK: Record<Severity, number> = {
103
+ critical: 4,
104
+ high: 3,
105
+ medium: 2,
106
+ low: 1,
107
+ info: 0,
108
+ };
109
+
110
+ export const SEVERITY_CVSS_SCORE: Record<Severity, number> = {
111
+ critical: 9.5,
112
+ high: 8.0,
113
+ medium: 5.0,
114
+ low: 2.0,
115
+ info: 0.0,
116
+ };
117
+
118
+ export const CVSS_SEVERITY_BANDS: ReadonlyArray<{
119
+ min: number;
120
+ severity: Severity;
121
+ }> = [
122
+ { min: 9.0, severity: "critical" },
123
+ { min: 7.0, severity: "high" },
124
+ { min: 4.0, severity: "medium" },
125
+ { min: 0.1, severity: "low" },
126
+ ];
127
+
128
+ export function severityFromCvss(score: number): Severity {
129
+ for (const band of CVSS_SEVERITY_BANDS) {
130
+ if (score >= band.min) return band.severity;
131
+ }
132
+ return "info";
133
+ }
134
+
135
+ export function cvssScoreForSeverity(severity: Severity): number {
136
+ return SEVERITY_CVSS_SCORE[severity];
137
+ }
138
+
139
+ export function concernId(
140
+ source: string,
141
+ ruleId: string,
142
+ file: string,
143
+ line: number | null,
144
+ ): string {
145
+ return createHash("sha1")
146
+ .update(`${source}|${ruleId}|${file}|${line ?? ""}`)
147
+ .digest("hex")
148
+ .slice(0, 12);
149
+ }
150
+
151
+ /**
152
+ * The single constructor every scanner parser uses to turn a raw finding into a
153
+ * `Concern`. It owns the one coupling that must never drift: the content `id`
154
+ * (`sha1(source|rule|file|line)`) and the namespaced `rule_id` (`source:rule`)
155
+ * are BOTH derived from the same bare `rule` here, so a parser can't accidentally
156
+ * hash one rule string while labelling the concern with another — which would
157
+ * silently break `remediate/<id>` branch naming and the ✗→✓ re-scan match.
158
+ *
159
+ * The per-scanner bits that genuinely differ (severity map, category, evidence
160
+ * text, remediation hint, whether a source snippet is attached) stay explicit at
161
+ * the call site — they're not uniform enough to hide behind a config object
162
+ * without obscuring each parser. `code_snippet` is only set when provided, so
163
+ * fmt/validate/tflint concerns keep their exact prior shape (no `code_snippet`
164
+ * key) and trivy/checkov keep theirs (`code_snippet` before `remediation_hint`).
165
+ */
166
+ export function buildConcern(input: {
167
+ source: Concern["source"];
168
+ /** the BARE rule (e.g. `unformatted`, `AVD-AWS-0088`), NOT `source:rule`. */
169
+ rule: string;
170
+ file: string;
171
+ line: number | null;
172
+ severity: Severity;
173
+ category: Concern["category"];
174
+ evidence: string;
175
+ remediation_hint: string | null;
176
+ code_snippet?: string | null;
177
+ /** the scanner-reported IaC language (trivy `Type` / checkov `check_type`);
178
+ * omit for the Terraform-only scanners — descriptive only, never hashed. */
179
+ language?: IacLanguage | null;
180
+ }): Concern {
181
+ const {
182
+ source,
183
+ rule,
184
+ file,
185
+ line,
186
+ severity,
187
+ category,
188
+ evidence,
189
+ remediation_hint,
190
+ } = input;
191
+ const base = {
192
+ id: concernId(source, rule, file, line),
193
+ source,
194
+ rule_id: `${source}:${rule}`,
195
+ severity,
196
+ category,
197
+ evidence,
198
+ location: { file, line },
199
+ ...(input.language ? { language: input.language } : {}),
200
+ };
201
+ return input.code_snippet !== undefined
202
+ ? { ...base, code_snippet: input.code_snippet, remediation_hint }
203
+ : { ...base, remediation_hint };
204
+ }
205
+
206
+ /**
207
+ * A LINE-INDEPENDENT identity for a concern — which rule fires in which file,
208
+ * ignoring the exact line. Two instances of the same rule in the same file at
209
+ * different lines share a key.
210
+ *
211
+ * The full content `id` keys on the line so it's unique per instance (right for
212
+ * SARIF alerts + branch naming), but that makes it UNSTABLE under a fix: almost
213
+ * every fix adds or removes lines, shifting every concern below it to a new line
214
+ * → a new id. If ✗→✓ verification compared raw ids, a shifted-but-unfixed concern
215
+ * would look RESOLVED (old id gone) and simultaneously look like a REGRESSION
216
+ * (new id appeared) — a false attestation either way. `terraform_verify_remediation`
217
+ * compares on this key instead, so a line shift can't fabricate a resolution or a
218
+ * regression. Derived identically to `id` minus the line (same bare-rule
219
+ * normalization) so keys match across the original scan and the re-scan.
220
+ */
221
+ /** Strip a rule id's own `<source>:` namespace prefix, if present — the
222
+ * normalization shared by `concernKeyOf` (per-file key) and the fix-memory
223
+ * finding-TYPE key (`source|bareRule`, file-independent). One helper so the two
224
+ * can never disagree on what "the same rule" means. */
225
+ export function bareRuleOf(source: string, ruleId: string): string {
226
+ const prefix = `${source}:`;
227
+ return ruleId.startsWith(prefix) ? ruleId.slice(prefix.length) : ruleId;
228
+ }
229
+
230
+ export function concernKeyOf(
231
+ c: Pick<Concern, "source" | "rule_id" | "location">,
232
+ ): string {
233
+ return createHash("sha1")
234
+ .update(`${c.source}|${bareRuleOf(c.source, c.rule_id)}|${c.location.file}`)
235
+ .digest("hex")
236
+ .slice(0, 12);
237
+ }
238
+
239
+ export type ScannerOutcome = {
240
+ source: Concern["source"];
241
+ ran: boolean;
242
+ skipped_reason?: string;
243
+ concerns: Concern[];
244
+ /**
245
+ * For `terraform validate` only: count of roots where terraform RAN but its
246
+ * `-json` output could not be parsed (a real CLI-level failure, not a missing
247
+ * binary). Lets the validate tool report `passed` as fail-closed instead of
248
+ * silently treating an un-validated root as clean. Undefined/0 elsewhere.
249
+ */
250
+ unvalidated?: number;
251
+ /**
252
+ * A scanner that RAN but whose coverage was incomplete — one named check inside
253
+ * it could not execute. Distinct from `ran: false` (nothing ran) and from an
254
+ * empty `concerns` (everything ran and found nothing), which is exactly the
255
+ * distinction that stops a partially-blind scan reading as a clean one. Folded
256
+ * into the verification summary's INCONCLUSIVE list, never dropped.
257
+ */
258
+ partial?: { check: string; reason: string };
259
+ /**
260
+ * Set when this scanner executed under egress denial (supply-chain 0.2).
261
+ * Always the honest word "partial": the control is an env-level proxy
262
+ * contract, not a kernel boundary — a malicious binary can ignore it. The
263
+ * run summary records it so an assessor can see WHICH findings were produced
264
+ * under bounded egress; absence means the tool ran with open egress.
265
+ */
266
+ egress_isolation?: "partial";
267
+ };
268
+
269
+ export function skipped(
270
+ source: Concern["source"],
271
+ reason: string,
272
+ ): ScannerOutcome {
273
+ return { source, ran: false, skipped_reason: reason, concerns: [] };
274
+ }
275
+
276
+ /**
277
+ * Re-base a concern produced by a per-root command (its file is relative to the
278
+ * root dir) onto the scan `cwd` by prefixing the root's `relDir`, and recompute
279
+ * the content id so it stays consistent with the cwd-relative scanners (✗→✓).
280
+ * A no-op when `relDir` is "" (the root IS cwd).
281
+ */
282
+ export function rebaseConcern(c: Concern, relDir: string): Concern {
283
+ if (!relDir) return c;
284
+ const file = `${relDir}/${c.location.file}`.replace(/\/+/g, "/");
285
+ const prefix = `${c.source}:`;
286
+ const bareRule = c.rule_id.startsWith(prefix)
287
+ ? c.rule_id.slice(prefix.length)
288
+ : c.rule_id;
289
+ return {
290
+ ...c,
291
+ location: { ...c.location, file },
292
+ id: concernId(c.source, bareRule, file, c.location.line),
293
+ };
294
+ }
295
+
296
+ /** true when a path is a Terraform source file Infraweaver may remediate. */
297
+ export function isTerraformFile(file: string): boolean {
298
+ const f = file.toLowerCase();
299
+ return f.endsWith(".tf") || f.endsWith(".tfvars");
300
+ }
301
+
302
+ /**
303
+ * The FIX-LOOP filter: Remediate is Terraform-first. A concern in a
304
+ * non-`.tf`/`.tfvars` file can never be remediated (the `allowed_paths` push
305
+ * guardrail blocks the edit, and the `✗→✓` proof machinery is Terraform-specific).
306
+ * The single chokepoint that enforces this is `buildConcernResult`
307
+ * (concernResult.ts), through which EVERY fixer-feeding surface routes —
308
+ * `terraform_scan`, `read_findings`, `detect_plan_drift` and
309
+ * `ingest_external_findings` — so a non-Terraform concern can never reach grouping,
310
+ * a PR branch, or the verifier no matter which tool produced it.
311
+ * The READ-ONLY surfaces (Assess / SARIF / evidence) deliberately do NOT use this
312
+ * filter: they scope by detected IaC language instead (`inLanguageScope`), which is
313
+ * how multi-language Assess widens breadth without ever faking a fix proof for a
314
+ * format the machinery can't verify.
315
+ */
316
+ export function isTerraformConcern(c: Concern): boolean {
317
+ return isTerraformFile(c.location.file);
318
+ }
319
+
320
+ export function dedupe(concerns: Concern[]): Concern[] {
321
+ const seen = new Set<string>();
322
+ const out: Concern[] = [];
323
+ for (const c of concerns) {
324
+ if (seen.has(c.id)) continue;
325
+ seen.add(c.id);
326
+ out.push(c);
327
+ }
328
+ return out;
329
+ }
330
+
331
+ export function sortConcerns(concerns: Concern[]): Concern[] {
332
+ return [...concerns].sort((a, b) => {
333
+ const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];
334
+ if (sev !== 0) return sev;
335
+ return a.id.localeCompare(b.id);
336
+ });
337
+ }
338
+
339
+ export function lowerSeverity(s: string | undefined): Severity {
340
+ const v = (s ?? "").toLowerCase();
341
+ return (SEVERITIES as readonly string[]).includes(v)
342
+ ? (v as Severity)
343
+ : "medium";
344
+ }
345
+
346
+ /**
347
+ * A scoped unit of work = all concerns in one file. Different scanners flag the
348
+ * same underlying defect under different rule ids (trivy ∩ checkov overlap
349
+ * heavily on e.g. S3 buckets), so per-concern PRs would spam many PRs for one
350
+ * bad file. Remediate acts on ONE group per PR (branch `remediate/<group.id>`),
351
+ * fixing every concern in the file together and proving them all cleared (✗→✓).
352
+ */
353
+ export interface ConcernGroup {
354
+ /** stable id — the remediation branch/PR key (`remediate/<id>`). Derived from
355
+ * the file (by-file grouping) or the rule (by-rule grouping). */
356
+ id: string;
357
+ /** the group's primary file (by-file) or a human label like "3 files"
358
+ * (by-rule); `files` carries the full list for by-rule groups. */
359
+ file: string;
360
+ /** every file the group spans. one entry for a by-file group; the
361
+ * full set for a by-rule group (the agent must fix the rule in all of them). */
362
+ files?: string[];
363
+ /** how the group was formed — `file` (default) or `rule`. */
364
+ grouping?: "file" | "rule";
365
+ /** highest severity among the group's concerns. */
366
+ severity: Severity;
367
+ concern_count: number;
368
+ /** distinct rule ids in the group, for the PR body. */
369
+ rule_ids: string[];
370
+ /** the concern ids the re-scan must confirm are gone to call this ✓. */
371
+ concern_ids: string[];
372
+ /** `auto` (open a normal PR) or `needs-human` (escalate). attached by
373
+ * the scan tool from the group's concerns, not by `groupConcerns` (which has
374
+ * no autonomy threshold). undefined until the scan tool annotates it. */
375
+ autonomy?: Autonomy;
376
+ /** why the group was escalated (empty/absent for `auto`). */
377
+ autonomy_reasons?: string[];
378
+ }
379
+
380
+ export type Autonomy = "auto" | "needs-human";
381
+
382
+ export type BlastTier = "low" | "medium" | "high";
@@ -0,0 +1,150 @@
1
+ import { classifyRefusal } from "#app/mcp/terraform/decisions";
2
+ import { bandVerdictReason, nativeRuleOf } from "#app/mcp/terraform/nativeRules";
3
+ import type { Concern, ScannerOutcome } from "#app/mcp/terraform/types";
4
+
5
+ /**
6
+ * Five-status verification taxonomy (the auditor-credibility win the evidence
7
+ * pack + crosswalk both lean on). The point is HONESTY: never let "no finding"
8
+ * read as "compliant", and never claim the engine proved something it cannot see
9
+ * from code. Every assessment statement carries exactly one of these:
10
+ *
11
+ * - `pass` — a check ran and code-verified compliance.
12
+ * - `fail` — a check ran and code-verified a violation.
13
+ * - `not-applicable` — the control does not apply to the resources present.
14
+ * - `inconclusive` — a relevant check did NOT run (gated / not installed /
15
+ * unparseable). A coverage gap, never silently a pass.
16
+ * - `not-code-verifiable` — the control needs human / process evidence
17
+ * (governance, training, a key-policy decision); IaC
18
+ * scanning structurally cannot prove it either way.
19
+ *
20
+ * What this engine asserts today: `fail` and `not-code-verifiable` per concern,
21
+ * and `inconclusive` per scanner that didn't run. It deliberately does NOT
22
+ * fabricate `pass` / `not-applicable` for controls nothing fired on — absence of
23
+ * a finding is not proof, and over-claiming is exactly what costs credibility
24
+ * with an assessor. The two reserved statuses are part of the shared vocabulary
25
+ * for the evidence consumer (and a future full-framework crosswalk). Pure.
26
+ */
27
+
28
+ export const VERIFICATION_STATUSES = [
29
+ "pass",
30
+ "fail",
31
+ "not-applicable",
32
+ "inconclusive",
33
+ "not-code-verifiable",
34
+ ] as const;
35
+ export type VerificationStatus = (typeof VERIFICATION_STATUSES)[number];
36
+
37
+ /** one-line legend per status — for the report / evidence bundle. */
38
+ export const VERIFICATION_STATUS_LABEL: Record<VerificationStatus, string> = {
39
+ pass: "a check ran and code-verified compliance",
40
+ fail: "a check ran and code-verified a violation",
41
+ "not-applicable": "the control does not apply to the resources present",
42
+ inconclusive: "a relevant check did not run — a coverage gap, not a pass",
43
+ "not-code-verifiable": "needs human / process evidence — IaC cannot prove it",
44
+ };
45
+
46
+ /** the statuses the engine asserts per concern (a concern is always one or the
47
+ * other — it fired, the only question is whether code can prove the fix). */
48
+ export type ConcernVerificationStatus = Extract<VerificationStatus, "fail" | "not-code-verifiable">;
49
+
50
+ /**
51
+ * Classify one concern: a code-verified violation (`fail`) — UNLESS its
52
+ * remediation is a human decision the engine can flag but not prove from code
53
+ * (IAM least-privilege, a KMS key policy, a real CIDR — the refusal set), in
54
+ * which case it is `not-code-verifiable`. Pure.
55
+ *
56
+ * A NATIVE rule ([[nativeRules]]) is decided by its declared band FIRST, and the
57
+ * band is checked before the keyword-matching refusal set on purpose: a
58
+ * governance rule's own text (which names what it deliberately does not assert)
59
+ * must never be able to trip a refusal regex into a different reason, and a
60
+ * `verified` native rule must never be downgraded because its evidence happens
61
+ * to contain a word like "policy".
62
+ */
63
+ export function concernVerificationStatus(concern: Pick<Concern, "rule_id" | "evidence">): {
64
+ status: ConcernVerificationStatus;
65
+ reason?: string;
66
+ } {
67
+ const native = nativeRuleOf(concern.rule_id);
68
+ if (native) {
69
+ const reason = bandVerdictReason(native);
70
+ return reason ? { status: "not-code-verifiable", reason } : { status: "fail" };
71
+ }
72
+ const refusal = classifyRefusal(concern);
73
+ if (refusal.refuse) {
74
+ return refusal.reason
75
+ ? { status: "not-code-verifiable", reason: refusal.reason }
76
+ : { status: "not-code-verifiable" };
77
+ }
78
+ return { status: "fail" };
79
+ }
80
+
81
+ export interface VerifiedConcern {
82
+ id: string;
83
+ status: ConcernVerificationStatus;
84
+ reason?: string;
85
+ }
86
+
87
+ export interface VerificationSummary {
88
+ /** per-concern verification status. */
89
+ concerns: VerifiedConcern[];
90
+ counts: {
91
+ fail: number;
92
+ not_code_verifiable: number;
93
+ /** scanners that did not run (each is a coverage gap). */
94
+ inconclusive: number;
95
+ };
96
+ coverage: {
97
+ /** scanners that ran — their checks are code-verified for what they cover. */
98
+ verified: string[];
99
+ /** scanners that did NOT run — their checks are INCONCLUSIVE, never a pass. */
100
+ inconclusive: { source: string; reason: string }[];
101
+ };
102
+ /** the honesty caveat an assessor should read alongside the statuses. */
103
+ note: string;
104
+ }
105
+
106
+ const HONESTY_NOTE =
107
+ "Statuses are code-verified only. A scanner that did not run leaves its checks " +
108
+ "INCONCLUSIVE (a coverage gap, not a pass); controls needing human/process " +
109
+ "evidence are NOT-CODE-VERIFIABLE. Absence of a finding is not proof of compliance.";
110
+
111
+ /**
112
+ * Roll a scan up into a verification summary: every concern classified
113
+ * (fail / not-code-verifiable) and every scanner partitioned into verified (ran)
114
+ * vs inconclusive (skipped — gated, not installed, or unparseable). Pure;
115
+ * `outcomes` is the raw `runScanners` result, `concerns` the deduped,
116
+ * Terraform-only set the assessment reports on.
117
+ */
118
+ export function buildVerificationSummary(
119
+ concerns: Pick<Concern, "id" | "rule_id" | "evidence">[],
120
+ outcomes: ScannerOutcome[],
121
+ ): VerificationSummary {
122
+ const verified: VerifiedConcern[] = concerns.map((c) => {
123
+ const v = concernVerificationStatus(c);
124
+ return v.reason
125
+ ? { id: c.id, status: v.status, reason: v.reason }
126
+ : { id: c.id, status: v.status };
127
+ });
128
+
129
+ const verifiedTools: string[] = [];
130
+ const inconclusiveTools: { source: string; reason: string }[] = [];
131
+ for (const o of outcomes) {
132
+ if (o.ran) verifiedTools.push(o.source);
133
+ else inconclusiveTools.push({ source: o.source, reason: o.skipped_reason ?? "did not run" });
134
+ // A scanner can run AND still be partially blind. That named sub-check is a
135
+ // coverage gap in its own right — listing it alongside the scanners that
136
+ // didn't run at all is the only way "verified" stays a truthful word.
137
+ if (o.partial) inconclusiveTools.push({ source: o.partial.check, reason: o.partial.reason });
138
+ }
139
+
140
+ return {
141
+ concerns: verified,
142
+ counts: {
143
+ fail: verified.filter((c) => c.status === "fail").length,
144
+ not_code_verifiable: verified.filter((c) => c.status === "not-code-verifiable").length,
145
+ inconclusive: inconclusiveTools.length,
146
+ },
147
+ coverage: { verified: verifiedTools, inconclusive: inconclusiveTools },
148
+ note: HONESTY_NOTE,
149
+ };
150
+ }