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,520 @@
1
+ import { type } from "arktype";
2
+ import { PRODUCT_NAME } from "#app/brand";
3
+ import { isStatefulResourceType } from "#app/mcp/terraform/governance";
4
+ import {
5
+ buildConcern,
6
+ type Concern,
7
+ type Severity,
8
+ } from "#app/mcp/terraform/types";
9
+
10
+ /**
11
+ * Detect infrastructure DRIFT from a `terraform show -json` plan artifact WITHOUT the
12
+ * engine ever holding a cloud credential. The customer's CI already runs
13
+ * `terraform plan` (that is where the creds live) and writes the plan out as JSON;
14
+ * Infraweaver reads that artifact and reports which resources have drifted from code.
15
+ * This is the sovereign, zero-credential companion to running `terraform_plan`
16
+ * against live state ourselves.
17
+ *
18
+ * Scope: a plan produced on a run whose CODE is unchanged (a scheduled / drift
19
+ * workflow) shows changes only because the live state diverged — that is drift.
20
+ * Each `resource_changes[]` entry with a mutating action is a drift item. Drift is
21
+ * DETECTION ONLY here: reconciling it is an `apply` or a code change a human owns.
22
+ *
23
+ * NB the parser: this reads the `terraform show -json` DOCUMENT form
24
+ * (`resource_changes[].change.actions[]`), NOT the `terraform plan -json` log stream
25
+ * (`plan.ts`). They are different shapes; a CI plan artifact is the document form.
26
+ * Pure: no filesystem, no network (the tool supplies the JSON + the resource index).
27
+ */
28
+
29
+ // --- plan document schema ----------------------------------------------------
30
+
31
+ const PlanResourceChange = type({
32
+ address: "string",
33
+ "type?": "string",
34
+ "name?": "string",
35
+ "mode?": "string",
36
+ change: type({
37
+ actions: "string[]",
38
+ // `before`/`after` are the attribute maps the provider-noise filter diffs.
39
+ // Optional and untyped by design: their shape is the resource's own schema,
40
+ // and an absent pair simply means the filter makes no claim (never filters).
41
+ "before?": "unknown",
42
+ "after?": "unknown",
43
+ }),
44
+ });
45
+
46
+ // Terraform 1.15's plan document lists provider-action invocations (the runtime
47
+ // counterpart of the static `imperative-action-trigger` finding). Field names
48
+ // follow hashicorp/terraform-json's ActionInvocation. Everything but the address
49
+ // is optional — this parser reports what is present, never demands more.
50
+ const PlanActionInvocation = type({
51
+ address: "string",
52
+ "type?": "string",
53
+ "name?": "string",
54
+ "provider_name?": "string",
55
+ "lifecycle_action_trigger?": type({
56
+ "triggering_resource_address?": "string",
57
+ "action_trigger_event?": "string",
58
+ }),
59
+ });
60
+
61
+ export const PlanDocument = type({
62
+ /** Terraform stamps the document form with a schema version. Absent on very
63
+ * old artifacts, so it stays optional — we tolerate rather than demand. */
64
+ "format_version?": "string",
65
+ "resource_changes?": PlanResourceChange.array(),
66
+ /** provider actions this plan will invoke (TF 1.15+). Absent on older plans. */
67
+ "action_invocations?": PlanActionInvocation.array(),
68
+ });
69
+
70
+ // --- drift classification ----------------------------------------------------
71
+
72
+ /** Actions that do not mutate live infrastructure (mirrors `plan.ts`, plus the
73
+ * document-form `no-op` spelling). A change made up only of these is not drift.
74
+ * `open`/`renew`/`close` are EPHEMERAL lifecycle ops (TF 1.10+): an ephemeral
75
+ * value being (re)opened is session plumbing, not a resource being changed —
76
+ * classifying one as CRUD would fabricate drift out of a secret handshake. */
77
+ const NON_MUTATING: ReadonlySet<string> = new Set([
78
+ "no-op",
79
+ "noop",
80
+ "read",
81
+ "open",
82
+ "renew",
83
+ "close",
84
+ ]);
85
+
86
+ export type DriftKind = "modified" | "deleted" | "recreated" | "replaced";
87
+
88
+ export interface DriftItem {
89
+ address: string;
90
+ type: string | null;
91
+ name: string | null;
92
+ /** the raw plan actions, e.g. ["update"] or ["delete","create"]. */
93
+ actions: string[];
94
+ kind: DriftKind;
95
+ /** top-level attributes whose value differs between `change.before` and
96
+ * `change.after` — the input the provider-noise filter judges. `null` when
97
+ * the plan carries no diffable before/after pair (the filter then makes no
98
+ * claim about this item and always keeps it). */
99
+ changed_fields: string[] | null;
100
+ }
101
+
102
+ /** Classify a resource change's actions into a drift kind, or null when the change
103
+ * is non-mutating (no drift). */
104
+ function classify(actions: string[]): DriftKind | null {
105
+ const acts = actions.filter((a) => !NON_MUTATING.has(a));
106
+ // A `forget` drops the resource from state while the cloud object survives:
107
+ // no live change, so it is not drift. It IS a coverage gap — see
108
+ // `detectForgotten`, which reports it separately rather than silently.
109
+ if (acts.includes("forget")) return null;
110
+ if (acts.length === 0) return null;
111
+ const set = new Set(acts);
112
+ if (set.has("create") && set.has("delete")) return "replaced";
113
+ if (set.has("delete")) return "deleted";
114
+ if (set.has("create")) return "recreated"; // live is missing the resource
115
+ if (set.has("update")) return "modified";
116
+ return null;
117
+ }
118
+
119
+ /**
120
+ * The plan-JSON document schema versions this parser understands. Terraform has
121
+ * only ever shipped 1.x for the `show -json` document form and adds keys within
122
+ * it additively, so any 1.x parses; a 2.x would be a redesign we have not read.
123
+ *
124
+ * Forward-compatibility is the DEFAULT here: an unknown 1.x minor (or an absent
125
+ * version on an old artifact) parses normally, because arktype ignores keys we
126
+ * do not declare. Only a MAJOR bump is called out — and even then as an honest
127
+ * coverage gap for the caller to surface, never a silent mis-parse.
128
+ */
129
+ export const SUPPORTED_PLAN_FORMAT_MAJOR = 1;
130
+
131
+ /** True when a plan document's `format_version` is one this parser understands.
132
+ * An absent version is accepted (pre-versioning artifacts). Pure. */
133
+ export function isSupportedPlanFormat(
134
+ formatVersion: string | undefined,
135
+ ): boolean {
136
+ if (!formatVersion) return true;
137
+ const major = Number.parseInt(formatVersion.split(".")[0] ?? "", 10);
138
+ return Number.isFinite(major) && major === SUPPORTED_PLAN_FORMAT_MAJOR;
139
+ }
140
+
141
+ /** The resource TYPE for a plan entry: the declared `type` when present, else
142
+ * parsed from the address (`module.a.aws_db_instance.b` → `aws_db_instance`).
143
+ * Null when neither yields one. Pure. */
144
+ function resourceTypeOf(rc: {
145
+ address: string;
146
+ type?: string | undefined;
147
+ }): string | null {
148
+ if (rc.type) return rc.type;
149
+ const segments = rc.address.split(".");
150
+ return segments.length >= 2 ? (segments[segments.length - 2] ?? null) : null;
151
+ }
152
+
153
+ export interface ForgottenResource {
154
+ address: string;
155
+ type: string | null;
156
+ /** true when the type is data-bearing ([[governance]] `isStatefulResourceType`)
157
+ * — forgetting a database is the case that must route through needs-human:
158
+ * after it, the data-bearing object exists with NO destroy protection and no
159
+ * drift visibility, and nothing in code says so. */
160
+ stateful: boolean;
161
+ }
162
+
163
+ /**
164
+ * Resources the plan would FORGET — dropped from state while the real cloud
165
+ * object keeps existing (Terraform `removed` blocks, OpenTofu `destroy = false`).
166
+ *
167
+ * A forget is deliberately NOT drift and NOT a destroy: nothing in the cloud
168
+ * changes, so reporting it as either would be a false positive. But it is not a
169
+ * non-event either — after a forget the resource is unmanaged, and every later
170
+ * drift scan is silently blind to it. Surfaced separately so the run can state
171
+ * the coverage gap instead of quietly shrinking what 'no drift' covers. Pure.
172
+ */
173
+ export function classifyForgotten(
174
+ doc: typeof PlanDocument.infer,
175
+ ): ForgottenResource[] {
176
+ const forgotten: ForgottenResource[] = [];
177
+ for (const rc of doc.resource_changes ?? []) {
178
+ if (!rc.change.actions.includes("forget")) continue;
179
+ const resourceType = resourceTypeOf(rc);
180
+ forgotten.push({
181
+ address: rc.address,
182
+ type: resourceType,
183
+ stateful: resourceType !== null && isStatefulResourceType(resourceType),
184
+ });
185
+ }
186
+ return forgotten;
187
+ }
188
+
189
+ /** The forgotten addresses only — the compact form of {@link classifyForgotten}. */
190
+ export function detectForgotten(doc: typeof PlanDocument.infer): string[] {
191
+ return classifyForgotten(doc).map((f) => f.address);
192
+ }
193
+
194
+ /** Structural equality on plan attribute values (JSON-shaped data only). */
195
+ function sameValue(a: unknown, b: unknown): boolean {
196
+ if (Object.is(a, b)) return true;
197
+ if (
198
+ typeof a !== "object" ||
199
+ typeof b !== "object" ||
200
+ a === null ||
201
+ b === null
202
+ )
203
+ return false;
204
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
205
+ if (Array.isArray(a) && Array.isArray(b)) {
206
+ return a.length === b.length && a.every((v, i) => sameValue(v, b[i]));
207
+ }
208
+ const ka = Object.keys(a).sort();
209
+ const kb = Object.keys(b).sort();
210
+ if (ka.length !== kb.length || ka.some((k, i) => k !== kb[i])) return false;
211
+ return ka.every((k) =>
212
+ sameValue(
213
+ (a as Record<string, unknown>)[k],
214
+ (b as Record<string, unknown>)[k],
215
+ ),
216
+ );
217
+ }
218
+
219
+ /** Top-level attribute names whose value differs between `before` and `after`,
220
+ * or null when the pair isn't two plain objects (nothing diffable). Pure. */
221
+ function changedFields(before: unknown, after: unknown): string[] | null {
222
+ const isPlain = (v: unknown): v is Record<string, unknown> =>
223
+ typeof v === "object" && v !== null && !Array.isArray(v);
224
+ if (!isPlain(before) || !isPlain(after)) return null;
225
+ const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
226
+ return [...keys].filter((k) => !sameValue(before[k], after[k])).sort();
227
+ }
228
+
229
+ /** Every drifted resource in a plan document. A clean plan yields `[]`. */
230
+ export function detectDrift(doc: typeof PlanDocument.infer): DriftItem[] {
231
+ const items: DriftItem[] = [];
232
+ for (const rc of doc.resource_changes ?? []) {
233
+ const kind = classify(rc.change.actions);
234
+ if (!kind) continue;
235
+ items.push({
236
+ address: rc.address,
237
+ type: resourceTypeOf(rc),
238
+ name: rc.name ?? null,
239
+ actions: rc.change.actions,
240
+ kind,
241
+ changed_fields: changedFields(rc.change.before, rc.change.after),
242
+ });
243
+ }
244
+ return items;
245
+ }
246
+
247
+ // --- provider-noise filter ---------------------------------------------------
248
+
249
+ /**
250
+ * Computed fields whose churn is PROVIDER bookkeeping, not an operator touching
251
+ * infrastructure — the documented, always-computed merge targets that generate
252
+ * perpetual "drift" whenever provider-level defaults shift:
253
+ *
254
+ * - aws `tags_all`: the computed merge of `default_tags` into every resource's
255
+ * tags (the canonical drift-noise field of the AWS provider).
256
+ * - google `effective_labels` / `terraform_labels`: computed label merges
257
+ * introduced by provider v5's default-labels model.
258
+ *
259
+ * The list is deliberately SHORT and only ever names fields a provider computes
260
+ * — a field an operator can hand-edit in the console never belongs here, because
261
+ * filtering it would be exactly the false no-drift the roadmap forbids.
262
+ */
263
+ export const PROVIDER_NOISE_FIELDS: Readonly<
264
+ Record<string, readonly string[]>
265
+ > = {
266
+ aws: ["tags_all"],
267
+ google: ["effective_labels", "terraform_labels"],
268
+ };
269
+
270
+ /** A drift item excluded by the noise filter — retained for auditability, so the
271
+ * run can show WHAT was filtered and by which fields rather than silently
272
+ * shrinking the drift set. */
273
+ export interface NoiseFilteredDrift {
274
+ address: string;
275
+ kind: DriftKind;
276
+ /** the noisy fields that were the entire diff. */
277
+ fields: string[];
278
+ }
279
+
280
+ /**
281
+ * Split drift into signal and provider noise. An item is noise ONLY when every
282
+ * condition holds: it is a pure in-place update (`modified`), the plan carried a
283
+ * diffable before/after pair, at least one field changed, and EVERY changed
284
+ * field is on the noise list (the per-provider defaults plus any operator-
285
+ * supplied extras). Anything else — a delete, a replace, an undiffable change,
286
+ * a mixed diff where one field is real — is kept. The bias is deliberate:
287
+ * "never a false no-drift" means the filter must prove noise, not assume it.
288
+ */
289
+ export function filterProviderNoise(
290
+ items: ReadonlyArray<DriftItem>,
291
+ extraNoiseFields: readonly string[] = [],
292
+ ): { kept: DriftItem[]; filtered: NoiseFilteredDrift[] } {
293
+ const kept: DriftItem[] = [];
294
+ const filtered: NoiseFilteredDrift[] = [];
295
+ for (const item of items) {
296
+ const provider = item.type?.split("_")[0] ?? "";
297
+ const noise = new Set([
298
+ ...(PROVIDER_NOISE_FIELDS[provider] ?? []),
299
+ ...extraNoiseFields,
300
+ ]);
301
+ const noiseOnly =
302
+ item.kind === "modified" &&
303
+ item.changed_fields !== null &&
304
+ item.changed_fields.length > 0 &&
305
+ item.changed_fields.every((f) => noise.has(f));
306
+ if (noiseOnly && item.changed_fields) {
307
+ filtered.push({
308
+ address: item.address,
309
+ kind: item.kind,
310
+ fields: item.changed_fields,
311
+ });
312
+ } else {
313
+ kept.push(item);
314
+ }
315
+ }
316
+ return { kept, filtered };
317
+ }
318
+
319
+ // --- action invocations (the runtime counterpart of imperative-action-trigger) --
320
+
321
+ export interface ActionInvocationItem {
322
+ /** absolute action address, `action.<type>.<name>`. */
323
+ address: string;
324
+ action_type: string | null;
325
+ /** the resource whose lifecycle event fires this action, when the plan says. */
326
+ triggered_by: string | null;
327
+ /** the lifecycle event (`after_create`, …), when the plan says. */
328
+ event: string | null;
329
+ }
330
+
331
+ /**
332
+ * The provider actions this plan will invoke (TF 1.15's `action_invocations`).
333
+ * This is the RUNTIME counterpart of the static `imperative-action-trigger`
334
+ * finding ([[governance]]): the static rule says "an apply here can do work
335
+ * outside the resource graph"; this array is the plan saying "THIS apply will".
336
+ * Pure summarization — correlation to code happens in the tool, where the
337
+ * repo's HCL is available.
338
+ */
339
+ export function summarizeActionInvocations(
340
+ doc: typeof PlanDocument.infer,
341
+ ): ActionInvocationItem[] {
342
+ return (doc.action_invocations ?? []).map((inv) => ({
343
+ address: inv.address,
344
+ action_type: inv.type ?? null,
345
+ triggered_by:
346
+ inv.lifecycle_action_trigger?.triggering_resource_address ?? null,
347
+ event: inv.lifecycle_action_trigger?.action_trigger_event ?? null,
348
+ }));
349
+ }
350
+
351
+ // --- drift → signed evidence -------------------------------------------------
352
+
353
+ /**
354
+ * The drift statement the evidence bundle carries — the 2.1 differentiator:
355
+ * *signed, verifiable proof that live cloud matched the committed IaC at the
356
+ * time the plan artifact was produced*, with every bound on that claim stated
357
+ * in the artifact itself rather than left to the reader's optimism.
358
+ */
359
+ export interface DriftEvidenceStatement {
360
+ /** the plan artifact the claim is derived from. */
361
+ source_file: string;
362
+ /** drifted resources AFTER noise filtering — the signal set. */
363
+ detected: number;
364
+ by_kind: Record<DriftKind, number>;
365
+ items: { address: string; kind: DriftKind }[];
366
+ /** drift excluded as provider bookkeeping — listed field-by-field so the
367
+ * filtering is auditable (the unfiltered diff stays in the plan artifact). */
368
+ noise_filtered: NoiseFilteredDrift[];
369
+ /** resources this plan drops from management — the standing blind spot every
370
+ * later drift claim inherits, so it must ride the signed statement. */
371
+ forgotten: ForgottenResource[];
372
+ /** drifted addresses with no matching resource block in code. */
373
+ unlocated: number;
374
+ /** honest bounds: unsupported format major, etc. Empty = fully readable. */
375
+ coverage_gaps: string[];
376
+ asserts: string;
377
+ does_not_assert: string;
378
+ }
379
+
380
+ /**
381
+ * Build the drift evidence statement (pure). The asserts line is graded by what
382
+ * the inputs actually prove: a clean, fully-readable plan asserts the live-
383
+ * matches-code claim; drift asserts the detection; a coverage gap asserts
384
+ * nothing confident. INCONCLUSIVE-over-silence, in the signed artifact itself.
385
+ */
386
+ export function buildDriftStatement(args: {
387
+ sourceFile: string;
388
+ kept: ReadonlyArray<DriftItem>;
389
+ filtered: ReadonlyArray<NoiseFilteredDrift>;
390
+ forgotten: ReadonlyArray<ForgottenResource>;
391
+ unlocated: number;
392
+ coverageGaps?: readonly string[];
393
+ }): DriftEvidenceStatement {
394
+ const { sourceFile, kept, filtered, forgotten, unlocated } = args;
395
+ const coverage_gaps = [...(args.coverageGaps ?? [])];
396
+ const by_kind: Record<DriftKind, number> = {
397
+ modified: 0,
398
+ deleted: 0,
399
+ recreated: 0,
400
+ replaced: 0,
401
+ };
402
+ for (const item of kept) by_kind[item.kind]++;
403
+
404
+ let asserts: string;
405
+ if (coverage_gaps.length > 0) {
406
+ asserts =
407
+ "nothing confident — the plan artifact could not be fully read (see coverage_gaps); " +
408
+ "treat this statement as INCONCLUSIVE, never as 'no drift'.";
409
+ } else if (kept.length === 0) {
410
+ asserts =
411
+ "at the time the plan artifact was produced, every resource under Terraform management " +
412
+ "matched the committed configuration (no mutating change was planned).";
413
+ } else {
414
+ asserts =
415
+ `${kept.length} resource(s) had drifted from the committed configuration when the plan ` +
416
+ "artifact was produced (each listed with the reconciling action kind).";
417
+ }
418
+
419
+ const forgottenNote = forgotten.length
420
+ ? ` ${forgotten.length} resource(s) are being dropped from management (\`forgotten\`) and are not observable by any later drift scan.`
421
+ : "";
422
+ const filteredNote = filtered.length
423
+ ? ` ${filtered.length} change(s) were excluded as provider-computed noise (listed field-by-field in \`noise_filtered\`; the unfiltered diff remains in the plan artifact).`
424
+ : "";
425
+ return {
426
+ source_file: sourceFile,
427
+ detected: kept.length,
428
+ by_kind,
429
+ items: kept.map((i) => ({ address: i.address, kind: i.kind })),
430
+ noise_filtered: [...filtered],
431
+ forgotten: [...forgotten],
432
+ unlocated,
433
+ coverage_gaps,
434
+ asserts,
435
+ does_not_assert:
436
+ "anything about resources outside Terraform management, or about changes made after " +
437
+ `the plan artifact was produced.${forgottenNote}${filteredNote}`,
438
+ };
439
+ }
440
+
441
+ // --- drift → concerns --------------------------------------------------------
442
+
443
+ const DRIFT_SEVERITY: Record<DriftKind, Severity> = {
444
+ // Losing/replacing a live resource to reconcile risks data loss — the loud cases.
445
+ deleted: "high",
446
+ replaced: "high",
447
+ recreated: "medium",
448
+ modified: "medium",
449
+ };
450
+
451
+ const DRIFT_EVIDENCE: Record<DriftKind, string> = {
452
+ modified:
453
+ "configuration has drifted from code (a plan would update it to reconcile)",
454
+ deleted:
455
+ "the resource no longer exists in live infrastructure (a plan would recreate it)",
456
+ recreated:
457
+ "the resource is missing from live infrastructure and would be created",
458
+ replaced:
459
+ "live state has drifted such that a plan would destroy and recreate it",
460
+ };
461
+
462
+ /** Resolve a Terraform address to its source location, or null when the address
463
+ * isn't found in the repo's code (e.g. a resource removed from code but still in
464
+ * state). Supplied by the tool from a `.tf` resource index. */
465
+ export type LocationResolver = (
466
+ address: string,
467
+ ) => { file: string; line: number } | null;
468
+
469
+ /** A drift item that couldn't be tied to a resource block in code (reported, not dropped). */
470
+ export interface UnlocatedDrift {
471
+ address: string;
472
+ kind: DriftKind;
473
+ reason: string;
474
+ }
475
+
476
+ export interface DriftConcerns {
477
+ concerns: Concern[];
478
+ unlocated: UnlocatedDrift[];
479
+ }
480
+
481
+ /**
482
+ * Turn drift items into `reviewer`-source concerns at each resource's file:line.
483
+ * Drift is honestly `not-code-verifiable` by the ✗→✓ re-scan (proving it fixed needs
484
+ * live cloud access, which Infraweaver refuses) — the `reviewer` source carries exactly
485
+ * that meaning. Items whose address isn't in code are returned under `unlocated`.
486
+ */
487
+ export function driftToConcerns(
488
+ items: ReadonlyArray<DriftItem>,
489
+ resolve: LocationResolver,
490
+ ): DriftConcerns {
491
+ const concerns: Concern[] = [];
492
+ const unlocated: UnlocatedDrift[] = [];
493
+ for (const item of items) {
494
+ const loc = resolve(item.address);
495
+ if (!loc) {
496
+ unlocated.push({
497
+ address: item.address,
498
+ kind: item.kind,
499
+ reason: "no resource block in the repo matched this drifted address",
500
+ });
501
+ continue;
502
+ }
503
+ concerns.push(
504
+ buildConcern({
505
+ source: "reviewer",
506
+ // A stable, address-scoped rule token so the same drifted resource keeps its id.
507
+ rule: `drift-${item.kind}-${item.address}`,
508
+ file: loc.file,
509
+ line: loc.line,
510
+ severity: DRIFT_SEVERITY[item.kind],
511
+ category: "correctness",
512
+ evidence: `${item.address}: ${DRIFT_EVIDENCE[item.kind]}`,
513
+ remediation_hint:
514
+ "Reconcile the drift (an apply, or reverse the out-of-band change) or update the code to " +
515
+ `match intent — a human decision; ${PRODUCT_NAME} never applies.`,
516
+ }),
517
+ );
518
+ }
519
+ return { concerns, unlocated };
520
+ }