infraweaver 0.3.7 → 0.3.8

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 (175) hide show
  1. package/README.md +2 -2
  2. package/dist/agents/claude.d.ts +1 -1
  3. package/dist/agents/claudePretoolGate.d.ts +0 -36
  4. package/dist/agents/toolPlaneWatch.d.ts +31 -0
  5. package/dist/cli.mjs +31903 -18736
  6. package/dist/external.d.ts +2 -1
  7. package/dist/index.js +31987 -18749
  8. package/dist/internal.js +132 -52
  9. package/dist/mcp/baseBranch.d.ts +41 -0
  10. package/dist/mcp/changeSummary.d.ts +1 -1
  11. package/dist/mcp/findingAudit.d.ts +2 -0
  12. package/dist/mcp/guardrails.d.ts +38 -0
  13. package/dist/mcp/localContext.d.ts +1 -1
  14. package/dist/mcp/moduleExtraction.d.ts +5 -0
  15. package/dist/mcp/pr.d.ts +0 -31
  16. package/dist/mcp/reproveSuggestions.d.ts +27 -0
  17. package/dist/mcp/review.d.ts +126 -2
  18. package/dist/mcp/reviewCommentLimit.d.ts +17 -0
  19. package/dist/mcp/reviewComments.d.ts +9 -5
  20. package/dist/mcp/reviewDedup.d.ts +1 -0
  21. package/dist/mcp/reviewMarkers.d.ts +10 -0
  22. package/dist/mcp/reviewProvenance.d.ts +20 -6
  23. package/dist/mcp/shared.d.ts +15 -0
  24. package/dist/mcp/suggestionProver.d.ts +3 -2
  25. package/dist/mcp/terraform/checkovSeverities.d.ts +7 -0
  26. package/dist/mcp/terraform/consolidation.d.ts +26 -0
  27. package/dist/mcp/terraform/cost.d.ts +2 -2
  28. package/dist/mcp/terraform/currency.d.ts +11 -0
  29. package/dist/mcp/terraform/deltaSummary.d.ts +11 -1
  30. package/dist/mcp/terraform/emittedArtefacts.d.ts +11 -0
  31. package/dist/mcp/terraform/evidence.d.ts +10 -0
  32. package/dist/mcp/terraform/gateScan.d.ts +2 -16
  33. package/dist/mcp/terraform/hcl.d.ts +15 -0
  34. package/dist/mcp/terraform/initArtefacts.d.ts +21 -0
  35. package/dist/mcp/terraform/localModules.d.ts +29 -0
  36. package/dist/mcp/terraform/moduleFindings.d.ts +38 -0
  37. package/dist/mcp/terraform/refactor/attribution.d.ts +1 -1
  38. package/dist/mcp/terraform/refactor/equivalence.d.ts +7 -0
  39. package/dist/mcp/terraform/refactor/expressions.d.ts +62 -0
  40. package/dist/mcp/terraform/refactor/references.d.ts +15 -0
  41. package/dist/mcp/terraform/refactor/resources.d.ts +11 -0
  42. package/dist/mcp/terraform/refactor/substitution.d.ts +55 -37
  43. package/dist/mcp/terraform/scanDelta.d.ts +28 -0
  44. package/dist/mcp/terraform/scanSession.d.ts +13 -0
  45. package/dist/mcp/terraform/scanners.d.ts +67 -18
  46. package/dist/mcp/terraform/secretScan.d.ts +19 -0
  47. package/dist/mcp/terraform/standardsReport.d.ts +1 -1
  48. package/dist/mcp/terraform/tools/plan.d.ts +1 -1
  49. package/dist/mcp/terraform/tools/scan.d.ts +7 -7
  50. package/dist/mcp/terraform/tools/validate.d.ts +7 -2
  51. package/dist/mcp/terraform/tools/verifyRemediation.d.ts +1 -1
  52. package/dist/mcp/terraform/treeLayout.d.ts +57 -0
  53. package/dist/mcp/terraform/types.d.ts +1 -1
  54. package/dist/phases/applyPlan.d.ts +0 -2
  55. package/dist/toolState.d.ts +3 -0
  56. package/dist/utils/agent/codexOAuth.d.ts +1 -1
  57. package/dist/utils/cli.d.ts +1 -7
  58. package/dist/utils/cloud/cloudReport.d.ts +1 -1
  59. package/dist/utils/config/baseRefConfig.d.ts +1 -1
  60. package/dist/utils/config/infraweaverConfig.d.ts +1 -1
  61. package/dist/utils/config/payload.d.ts +5 -0
  62. package/dist/utils/markdownTable.d.ts +6 -0
  63. package/dist/utils/setup/toolLicensing.d.ts +1 -1
  64. package/dist/utils/unifiedDiff.d.ts +69 -0
  65. package/package.json +34 -28
  66. package/src/agents/claude.ts +48 -13
  67. package/src/agents/claudePretoolGate.ts +9 -17
  68. package/src/agents/sessionLabeler.ts +3 -3
  69. package/src/agents/toolPlaneWatch.ts +71 -0
  70. package/src/external.ts +3 -1
  71. package/src/mcp/assess.ts +8 -8
  72. package/src/mcp/baseBranch.ts +96 -0
  73. package/src/mcp/changeSummary.ts +10 -11
  74. package/src/mcp/checkSuite.ts +7 -10
  75. package/src/mcp/checkout.ts +13 -40
  76. package/src/mcp/crosswalk.ts +5 -0
  77. package/src/mcp/findingAudit.ts +1 -1
  78. package/src/mcp/git.ts +44 -2
  79. package/src/mcp/guardrails.ts +188 -36
  80. package/src/mcp/localContext.ts +2 -0
  81. package/src/mcp/localServer.ts +1 -0
  82. package/src/mcp/moduleExtraction.ts +17 -5
  83. package/src/mcp/moduleTests.ts +9 -2
  84. package/src/mcp/modules.ts +10 -7
  85. package/src/mcp/pr.ts +17 -65
  86. package/src/mcp/reproveSuggestions.ts +86 -0
  87. package/src/mcp/review.ts +249 -75
  88. package/src/mcp/reviewAnchor.ts +11 -23
  89. package/src/mcp/reviewCommentLimit.ts +79 -0
  90. package/src/mcp/reviewComments.ts +34 -81
  91. package/src/mcp/reviewDedup.ts +1 -1
  92. package/src/mcp/reviewMarkers.ts +25 -2
  93. package/src/mcp/reviewProvenance.ts +56 -21
  94. package/src/mcp/roots.ts +3 -2
  95. package/src/mcp/server.ts +2 -1
  96. package/src/mcp/shared.ts +40 -1
  97. package/src/mcp/shell.ts +27 -28
  98. package/src/mcp/suggestionProver.ts +8 -4
  99. package/src/mcp/terraform/checkovSeverities.ts +1156 -0
  100. package/src/mcp/terraform/concernResult.ts +2 -1
  101. package/src/mcp/terraform/consolidation.ts +232 -19
  102. package/src/mcp/terraform/cost.ts +16 -7
  103. package/src/mcp/terraform/cspm.ts +8 -4
  104. package/src/mcp/terraform/currency.ts +28 -12
  105. package/src/mcp/terraform/decisions.ts +1 -1
  106. package/src/mcp/terraform/deltaSummary.ts +50 -1
  107. package/src/mcp/terraform/emittedArtefacts.ts +63 -0
  108. package/src/mcp/terraform/evidence.ts +23 -3
  109. package/src/mcp/terraform/gateScan.ts +191 -128
  110. package/src/mcp/terraform/hcl.ts +27 -2
  111. package/src/mcp/terraform/idleFloor.ts +2 -1
  112. package/src/mcp/terraform/initArtefacts.ts +76 -0
  113. package/src/mcp/terraform/localModules.ts +112 -0
  114. package/src/mcp/terraform/moduleDocs.ts +2 -5
  115. package/src/mcp/terraform/moduleFindings.ts +102 -0
  116. package/src/mcp/terraform/moduleVersionConstraints.ts +1 -1
  117. package/src/mcp/terraform/planPairs.ts +2 -20
  118. package/src/mcp/terraform/policyGate.ts +0 -15
  119. package/src/mcp/terraform/refactor/attribution.ts +39 -5
  120. package/src/mcp/terraform/refactor/equivalence.ts +49 -10
  121. package/src/mcp/terraform/refactor/expressions.ts +323 -0
  122. package/src/mcp/terraform/refactor/references.ts +101 -0
  123. package/src/mcp/terraform/refactor/resources.ts +79 -7
  124. package/src/mcp/terraform/refactor/substitution.ts +852 -256
  125. package/src/mcp/terraform/scanDelta.ts +34 -0
  126. package/src/mcp/terraform/scanSession.ts +30 -0
  127. package/src/mcp/terraform/scannerCache.ts +4 -0
  128. package/src/mcp/terraform/scanners.ts +553 -233
  129. package/src/mcp/terraform/secretScan.ts +131 -0
  130. package/src/mcp/terraform/standardsReport.ts +14 -13
  131. package/src/mcp/terraform/tools/consolidationCandidates.ts +3 -0
  132. package/src/mcp/terraform/tools/emitEvidence.ts +13 -5
  133. package/src/mcp/terraform/tools/emitOscal.ts +3 -2
  134. package/src/mcp/terraform/tools/emitVex.ts +10 -4
  135. package/src/mcp/terraform/tools/equivalenceCheck.ts +139 -21
  136. package/src/mcp/terraform/tools/infracostDiff.ts +2 -2
  137. package/src/mcp/terraform/tools/plan.ts +30 -17
  138. package/src/mcp/terraform/tools/reviewScanDelta.ts +3 -0
  139. package/src/mcp/terraform/tools/scan.ts +5 -3
  140. package/src/mcp/terraform/tools/standardsReport.ts +1 -1
  141. package/src/mcp/terraform/tools/validate.ts +20 -5
  142. package/src/mcp/terraform/tools/verifyRemediation.ts +14 -7
  143. package/src/mcp/terraform/tools/versionCurrency.ts +3 -1
  144. package/src/mcp/terraform/treeLayout.ts +378 -0
  145. package/src/mcp/terraform/types.ts +4 -1
  146. package/src/mcp/terraform/versionRequirements.ts +11 -2
  147. package/src/modes/__snapshots__/assemblePrompt.test.ts.snap +2 -0
  148. package/src/modes/modernize-deprecated.ts +2 -2
  149. package/src/modes/refactor.ts +9 -9
  150. package/src/modes/remediate.ts +1 -1
  151. package/src/modes/terraform-code-review.ts +6 -3
  152. package/src/modes/update-dependencies.ts +6 -6
  153. package/src/phases/applyPlan.ts +33 -14
  154. package/src/phases/applySuggestions.ts +2 -2
  155. package/src/phases/runAgentWithWatchdogs.ts +2 -1
  156. package/src/toolState.ts +7 -0
  157. package/src/utils/agent/codexOAuth.ts +7 -7
  158. package/src/utils/agent/openCodeModels.ts +4 -6
  159. package/src/utils/cli.ts +1 -31
  160. package/src/utils/cloud/runContext.ts +1 -8
  161. package/src/utils/config/baseRefConfig.ts +6 -0
  162. package/src/utils/config/infraweaverConfig.ts +2 -0
  163. package/src/utils/config/payload.ts +41 -0
  164. package/src/utils/github/assets.ts +1 -6
  165. package/src/utils/github/github.ts +42 -150
  166. package/src/utils/github/token.ts +6 -11
  167. package/src/utils/log.ts +4 -5
  168. package/src/utils/markdownTable.ts +11 -0
  169. package/src/utils/prompt/changeImpact.ts +18 -26
  170. package/src/utils/prompt/instructions.ts +1 -1
  171. package/src/utils/prompt/promptDirectives.ts +1 -1
  172. package/src/utils/prompt/toolSelection.ts +11 -2
  173. package/src/utils/setup/toolLicensing.ts +7 -0
  174. package/src/utils/telemetry.ts +2 -1
  175. package/src/utils/unifiedDiff.ts +120 -0
package/dist/mcp/pr.d.ts CHANGED
@@ -1,41 +1,10 @@
1
1
  import type { GitHubWriteToolContext } from "./capabilityContext.js";
2
- import type { RunContextData } from "../utils/cloud/runContextData.js";
3
- import type { ResolvedPayload } from "../utils/config/payload.js";
4
- /**
5
- * The slice `resolveBaseBranch` reads: the declared base-branch input and the
6
- * repository's default branch. Shared with `terraform_change_summary`, which
7
- * resolves the same base without needing the rest of the GitHub surface.
8
- */
9
- export interface BaseBranchContext {
10
- payload: ResolvedPayload;
11
- repo: RunContextData["repo"];
12
- }
13
2
  export declare const PullRequest: import("arktype/internal/variants/object.ts").ObjectType<{
14
3
  title: string;
15
4
  body: string;
16
5
  base?: string;
17
6
  draft?: boolean;
18
7
  }, {}>;
19
- /**
20
- * Pure base-branch picker. Precedence: an explicit `base_branch` declaration
21
- * always wins; otherwise the repository's default branch (GitHub reports it —
22
- * normally `main`, sometimes `master`); otherwise prefer `main`, then `master`;
23
- * final fallback `main`. Split out from git/ctx so it's exhaustively testable.
24
- */
25
- export declare function pickBaseBranch(opts: {
26
- declared?: string | undefined;
27
- defaultBranch?: string | undefined;
28
- mainExists: boolean;
29
- masterExists: boolean;
30
- }): string;
31
- /**
32
- * Deterministically resolve the branch a PR targets, so the base is never left
33
- * to the agent's guess. Resolves to the repository's default branch (`main`, or
34
- * `master`), overridable by the `base_branch` input. Git is only probed for
35
- * main/master in the last-resort case where neither an explicit declaration nor
36
- * a GitHub default branch is available (essentially never).
37
- */
38
- export declare function resolveBaseBranch(ctx: BaseBranchContext): string;
39
8
  /**
40
9
  * Append the extraction detector's `selection_reason` for each adopted module
41
10
  * the body does not already state — pure half, so the rule is testable without
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Re-proving the open, proven suggestions a later push made stale.
3
+ *
4
+ * A proof holds for the commit it was made on, so the apply command commits a
5
+ * suggestion only at that head. After a push, the review's restatement of the
6
+ * same finding is withheld as a duplicate of its open thread — so without this
7
+ * step a proven suggestion could never be applied again once anything else was
8
+ * pushed.
9
+ *
10
+ * Each such thread's OWN suggestion is re-proved, by the same prover, at the
11
+ * thread's current lines on the new head. When it still holds, the thread gets
12
+ * a reply carrying a `reproof` marker for this head and those lines, which is
13
+ * what the apply command honours. One that no longer holds gets no reply, and
14
+ * apply keeps refusing it.
15
+ */
16
+ import type { OpenInfraweaverThread } from "./reviewComments.js";
17
+ import type { SuggestionCandidate, SuggestionProof } from "./suggestionProver.js";
18
+ import { type GateDelta } from "./terraform/scanDelta.js";
19
+ /** Returns how many threads were re-proved and replied to. */
20
+ export declare function reproveStaleSuggestions(input: {
21
+ threads: readonly OpenInfraweaverThread[];
22
+ delta: GateDelta;
23
+ /** the head the review is submitted at */
24
+ headSha: string;
25
+ prove: (candidates: SuggestionCandidate[]) => Promise<SuggestionProof[]>;
26
+ reply: (rootCommentId: number, body: string) => Promise<void>;
27
+ }): Promise<number>;
@@ -1,5 +1,6 @@
1
1
  import type { RestEndpointMethodTypes } from "@octokit/rest";
2
2
  import type { GitHubWriteToolContext } from "./capabilityContext.js";
3
+ import { type Dismissal } from "./reviewProvenance.js";
3
4
  import type { CommentableLines } from "../toolState.js";
4
5
  export type { CommentableLines };
5
6
  /**
@@ -138,6 +139,127 @@ export declare function reviewSkipDecision(params: {
138
139
  prApproveEnabled: boolean;
139
140
  }): ReviewSkipDecision | null;
140
141
  export declare function formatDroppedCommentsNote(dropped: DroppedComment[]): string;
142
+ /** One inline comment of a review, as `create_pull_request_review` and `stage_review` take it. */
143
+ declare const ReviewComment: import("arktype/internal/variants/object.ts").ObjectType<{
144
+ path: string;
145
+ line: number;
146
+ side?: "LEFT" | "RIGHT";
147
+ body?: string;
148
+ suggestion?: string;
149
+ start_line?: number;
150
+ existing_code?: string;
151
+ finding_id?: string;
152
+ audit?: {
153
+ resource_address?: string;
154
+ coherence?: {
155
+ cited_code_exists?: "fail" | "not_applicable" | "pass" | "unknown";
156
+ config_reachable?: "fail" | "not_applicable" | "pass" | "unknown";
157
+ exposure_path?: "fail" | "not_applicable" | "pass" | "unknown";
158
+ not_mitigated_elsewhere?: "fail" | "not_applicable" | "pass" | "unknown";
159
+ };
160
+ exposure_path?: string;
161
+ impact: number;
162
+ likelihood: number;
163
+ exposure: "internal" | "internet" | "none" | "privileged";
164
+ caps?: {
165
+ defense_in_depth_only?: "applies" | "does_not_apply" | "unknown";
166
+ hygiene_only?: "applies" | "does_not_apply" | "unknown";
167
+ non_default_input?: "applies" | "does_not_apply" | "unknown";
168
+ non_production_scope?: "applies" | "does_not_apply" | "unknown";
169
+ requires_existing_admin?: "applies" | "does_not_apply" | "unknown";
170
+ requires_user_action?: "applies" | "does_not_apply" | "unknown";
171
+ single_resource_blast?: "applies" | "does_not_apply" | "unknown";
172
+ };
173
+ };
174
+ }, {}>;
175
+ type SubmittedComment = typeof ReviewComment.infer;
176
+ /** Comments and dismissals `stage_review` holds for the next submission on one PR. */
177
+ export interface StagedReview {
178
+ pullNumber: number;
179
+ comments: SubmittedComment[];
180
+ dismissed: Dismissal[];
181
+ }
182
+ export declare function StageReviewTool(ctx: GitHubWriteToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
183
+ pull_number: number;
184
+ comments?: {
185
+ path: string;
186
+ line: number;
187
+ side?: "LEFT" | "RIGHT";
188
+ body?: string;
189
+ suggestion?: string;
190
+ start_line?: number;
191
+ existing_code?: string;
192
+ finding_id?: string;
193
+ audit?: {
194
+ resource_address?: string;
195
+ coherence?: {
196
+ cited_code_exists?: "fail" | "not_applicable" | "pass" | "unknown";
197
+ config_reachable?: "fail" | "not_applicable" | "pass" | "unknown";
198
+ exposure_path?: "fail" | "not_applicable" | "pass" | "unknown";
199
+ not_mitigated_elsewhere?: "fail" | "not_applicable" | "pass" | "unknown";
200
+ };
201
+ exposure_path?: string;
202
+ impact: number;
203
+ likelihood: number;
204
+ exposure: "internal" | "internet" | "none" | "privileged";
205
+ caps?: {
206
+ defense_in_depth_only?: "applies" | "does_not_apply" | "unknown";
207
+ hygiene_only?: "applies" | "does_not_apply" | "unknown";
208
+ non_default_input?: "applies" | "does_not_apply" | "unknown";
209
+ non_production_scope?: "applies" | "does_not_apply" | "unknown";
210
+ requires_existing_admin?: "applies" | "does_not_apply" | "unknown";
211
+ requires_user_action?: "applies" | "does_not_apply" | "unknown";
212
+ single_resource_blast?: "applies" | "does_not_apply" | "unknown";
213
+ };
214
+ };
215
+ }[];
216
+ dismissed?: {
217
+ finding_id?: string;
218
+ finding_ids?: string[];
219
+ reason: string;
220
+ }[];
221
+ }, {
222
+ pull_number: number;
223
+ comments?: {
224
+ path: string;
225
+ line: number;
226
+ side?: "LEFT" | "RIGHT";
227
+ body?: string;
228
+ suggestion?: string;
229
+ start_line?: number;
230
+ existing_code?: string;
231
+ finding_id?: string;
232
+ audit?: {
233
+ resource_address?: string;
234
+ coherence?: {
235
+ cited_code_exists?: "fail" | "not_applicable" | "pass" | "unknown";
236
+ config_reachable?: "fail" | "not_applicable" | "pass" | "unknown";
237
+ exposure_path?: "fail" | "not_applicable" | "pass" | "unknown";
238
+ not_mitigated_elsewhere?: "fail" | "not_applicable" | "pass" | "unknown";
239
+ };
240
+ exposure_path?: string;
241
+ impact: number;
242
+ likelihood: number;
243
+ exposure: "internal" | "internet" | "none" | "privileged";
244
+ caps?: {
245
+ defense_in_depth_only?: "applies" | "does_not_apply" | "unknown";
246
+ hygiene_only?: "applies" | "does_not_apply" | "unknown";
247
+ non_default_input?: "applies" | "does_not_apply" | "unknown";
248
+ non_production_scope?: "applies" | "does_not_apply" | "unknown";
249
+ requires_existing_admin?: "applies" | "does_not_apply" | "unknown";
250
+ requires_user_action?: "applies" | "does_not_apply" | "unknown";
251
+ single_resource_blast?: "applies" | "does_not_apply" | "unknown";
252
+ };
253
+ };
254
+ }[];
255
+ dismissed?: {
256
+ finding_id?: string;
257
+ finding_ids?: string[];
258
+ reason: string;
259
+ }[];
260
+ }>> & {
261
+ mutates?: boolean;
262
+ };
141
263
  export declare function CreatePullRequestReviewTool(ctx: GitHubWriteToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
142
264
  pull_number: number;
143
265
  body: string;
@@ -177,7 +299,8 @@ export declare function CreatePullRequestReviewTool(ctx: GitHubWriteToolContext)
177
299
  };
178
300
  }[];
179
301
  dismissed?: {
180
- finding_id: string;
302
+ finding_id?: string;
303
+ finding_ids?: string[];
181
304
  reason: string;
182
305
  }[];
183
306
  }, {
@@ -219,7 +342,8 @@ export declare function CreatePullRequestReviewTool(ctx: GitHubWriteToolContext)
219
342
  };
220
343
  }[];
221
344
  dismissed?: {
222
- finding_id: string;
345
+ finding_id?: string;
346
+ finding_ids?: string[];
223
347
  reason: string;
224
348
  }[];
225
349
  }>> & {
@@ -0,0 +1,17 @@
1
+ interface LimitableComment {
2
+ path: string;
3
+ line?: number | undefined;
4
+ body?: string | undefined;
5
+ }
6
+ /**
7
+ * Split `comments` into those posted inline and those folded into the body.
8
+ * `limit` 0 or undefined means no limit. Both halves keep the input order, so
9
+ * the posted review reads in the order the reviewer wrote it.
10
+ */
11
+ export declare function limitInlineComments<T extends LimitableComment>(comments: readonly T[], limit: number | undefined): {
12
+ kept: T[];
13
+ overflow: T[];
14
+ };
15
+ /** The review-body note listing the comments the limit folded, or "" for none. */
16
+ export declare function formatOverflowNote(overflow: readonly LimitableComment[], limit: number): string;
17
+ export {};
@@ -2,6 +2,7 @@ import type { Octokit } from "@octokit/rest";
2
2
  import type { GitHubToolContext } from "./capabilityContext.js";
3
3
  import type { ThreadSpan } from "./reviewDedup.js";
4
4
  import { type CommentMarker } from "./reviewMarkers.js";
5
+ import { type HunkHeader } from "../utils/unifiedDiff.js";
5
6
  /**
6
7
  * A GraphQL review-thread fetch worth retrying: an HTTP 5xx / network blip
7
8
  * ({@link isTransientServerError}), OR GitHub's transient "Something went wrong
@@ -32,6 +33,9 @@ export type OutstandingThreadsResponse = {
32
33
  nodes: ({
33
34
  databaseId?: number | null;
34
35
  body?: string | null;
36
+ originalCommit?: {
37
+ oid: string;
38
+ } | null;
35
39
  author: {
36
40
  login: string;
37
41
  __typename?: string;
@@ -53,6 +57,10 @@ export type OpenInfraweaverThread = {
53
57
  rootCommentId?: number;
54
58
  /** the marker the root comment carries, when the engine wrote one */
55
59
  marker?: CommentMarker;
60
+ /** the root comment's body */
61
+ rootBody?: string;
62
+ /** the commit the root comment was made on */
63
+ rootCommit?: string;
56
64
  };
57
65
  /**
58
66
  * Every unresolved review thread on a PR whose ROOT comment was authored by
@@ -125,12 +133,8 @@ export type ReviewThreadsQueryResponse = {
125
133
  } | null;
126
134
  };
127
135
  export declare function countRenderedLines(str: string): number;
128
- export type ParsedHunk = {
136
+ export type ParsedHunk = HunkHeader & {
129
137
  header: string;
130
- oldStart: number;
131
- oldCount: number;
132
- newStart: number;
133
- newCount: number;
134
138
  content: string[];
135
139
  };
136
140
  export declare function parseFilePatches(patch: string): ParsedHunk[];
@@ -61,6 +61,7 @@ export type DuplicateComment = {
61
61
  */
62
62
  gist?: string;
63
63
  };
64
+ export declare function gistOf(body: unknown): string | undefined;
64
65
  /**
65
66
  * Split comments into those to post and those that restate an open thread.
66
67
  *
@@ -4,9 +4,19 @@ export type CommentMarker = {
4
4
  proven: boolean;
5
5
  } | {
6
6
  kind: "judgement";
7
+ }
8
+ /** a reply re-proving its thread's suggestion on a later head, at the
9
+ * thread's current lines — what lets the apply command take it there */
10
+ | {
11
+ kind: "reproof";
12
+ head: string;
13
+ startLine: number;
14
+ line: number;
7
15
  };
8
16
  export declare function renderCommentMarker(marker: CommentMarker): string;
9
17
  export declare function parseCommentMarker(body: string | null | undefined): CommentMarker | null;
18
+ /** The text of a comment's `suggestion` block, without its closing newline. */
19
+ export declare function suggestionText(body: string): string | undefined;
10
20
  /**
11
21
  * A review comment the engine wrote: by the Infraweaver app, or by any Bot
12
22
  * account when it carries the marker (the workflow-token path).
@@ -1,11 +1,11 @@
1
1
  import { type WithheldFinding } from "./findingAudit.js";
2
2
  import { type DeltaVerdict } from "./terraform/deltaSummary.js";
3
- import type { DeltaFinding, GateDelta } from "./terraform/scanDelta.js";
4
- export declare const Dismissal: import("arktype/internal/variants/object.ts").ObjectType<{
3
+ import { type DeltaFinding, type GateDelta } from "./terraform/scanDelta.js";
4
+ /** An introduced finding the reviewer decided needs no comment, and why. */
5
+ export interface Dismissal {
5
6
  finding_id: string;
6
7
  reason: string;
7
- }, {}>;
8
- export type Dismissal = typeof Dismissal.infer;
8
+ }
9
9
  interface ProvenanceComment {
10
10
  path: string;
11
11
  line: number;
@@ -35,8 +35,19 @@ export declare function classifyComments<T extends ProvenanceComment>(comments:
35
35
  * comment nor dismissed. One past the per-review limit was never the reviewer's
36
36
  * to answer, so it is not counted against them. */
37
37
  export declare function unaddressedFindings(delta: GateDelta, citedIds: Iterable<string>, dismissed: readonly Dismissal[]): DeltaFinding[];
38
- /** The provenance line closing an inline comment. */
39
- export declare function provenanceLine(kind: CommentKind): string;
38
+ /**
39
+ * The provenance line closing an inline comment.
40
+ *
41
+ * A scanner-backed comment carries two severities, and the line says which one
42
+ * decides what. The marker it opens with (🚨 ⚠️ ℹ️) is the reviewer's reading of
43
+ * the risk in this configuration; the gate counts the scanner's severity and
44
+ * the required controls. When the two disagree, the line says so, so an ℹ️ that
45
+ * still blocks the merge — or a 🚨 that does not — reads as intended.
46
+ */
47
+ export declare function provenanceLine(kind: CommentKind, opts?: {
48
+ requiredControls?: string[];
49
+ reviewerMarker?: string | null;
50
+ }): string;
40
51
  /** How a suggestion is rendered once the prover has judged it. */
41
52
  export declare function renderSuggestion(suggestion: string, proof: {
42
53
  proven: boolean;
@@ -59,6 +70,9 @@ export declare function renderReviewVerdict(input: {
59
70
  resolved: number;
60
71
  unresolved: number;
61
72
  } | undefined;
73
+ /** the run's `required_controls`, so findings on renamed resources can be told
74
+ * apart among the ones the gate fails on. */
75
+ requiredControls?: readonly string[];
62
76
  }): string;
63
77
  /** The engine-written section closing a customer-PR review body. */
64
78
  export declare function renderReviewSummarySection(input: {
@@ -102,4 +102,19 @@ export declare const handleToolError: (error: unknown) => ToolResult;
102
102
  * @param toolName - optional tool name for error logging
103
103
  */
104
104
  export declare const execute: <T, R extends Record<string, any> | string>(fn: (params: T) => Promise<R>, toolName?: string) => (params: T) => Promise<ToolResult>;
105
+ /**
106
+ * How often a running tool tells the client it is still working. Claude Code
107
+ * aborts a call that sends neither a response nor a progress notification for
108
+ * five minutes, and a scan that downloads external modules, or a plan, can run
109
+ * longer than that while working normally.
110
+ */
111
+ export declare const PROGRESS_HEARTBEAT_MS = 30000;
112
+ /**
113
+ * Send a progress notification every {@link PROGRESS_HEARTBEAT_MS} while the
114
+ * tool runs, carrying the seconds elapsed (the spec requires `progress` to
115
+ * increase). It only reaches the client while the event loop is free, so a tool
116
+ * that blocks on a synchronous subprocess still looks idle — which is why the
117
+ * Terraform and scanner paths spawn asynchronously.
118
+ */
119
+ export declare function withProgressHeartbeat(tool: InfraweaverTool): InfraweaverTool;
105
120
  export declare const addTools: (ctx: ToolContext, server: FastMCP<any>, tools: InfraweaverTool[]) => FastMCP<any>;
@@ -19,8 +19,9 @@ export interface SuggestionProof {
19
19
  reason: string;
20
20
  }
21
21
  export interface ProverDeps {
22
- /** a gate-configured scan of the tree at `cwd`, ACTIVE concerns only */
23
- scan: (cwd: string) => Promise<Concern[]>;
22
+ /** a gate-configured scan of the tree at `cwd`, ACTIVE concerns only, covering
23
+ * at least the root modules that `files` (relative to `cwd`) reach */
24
+ scan: (cwd: string, files: string[]) => Promise<Concern[]>;
24
25
  }
25
26
  /**
26
27
  * Prove `candidates` against the commit checked out in `repoCwd`. `prefix` is
@@ -0,0 +1,7 @@
1
+ import type { Severity } from "./types.js";
2
+ /**
3
+ * A severity for each checkov Terraform check, which open-source checkov does
4
+ * not report. Each line names its basis: a reviewer's rating, the severity
5
+ * trivy gives the same misconfiguration, a title rule, or the medium default.
6
+ */
7
+ export declare const CHECKOV_SEVERITIES: Readonly<Record<string, Severity>>;
@@ -40,6 +40,15 @@
40
40
  * the expression as text. Multiplicity is part of the key, so those dirs
41
41
  * simply never group.
42
42
  *
43
+ * MODULE CALLS IN THE SHAPE. A root's call of a LOCAL module that the
44
+ * cluster's resources read is part of the stack as much as they are, so it can
45
+ * join the cluster: the proposed module then wraps the call (`module.data` → `module.<new>.module.data`, one
46
+ * `moved {}` block) and a reference into it stays inside the module instead of
47
+ * crossing the boundary as an input. Only calls the proof can follow make it
48
+ * in — a local source, no `count`/`for_each`/`providers`/`depends_on` — and a
49
+ * cluster that wraps calls is only the WIDER offer: when it cannot be
50
+ * proposed, the same roots are still considered without their calls.
51
+ *
43
52
  * Pure: an already-read tree in, structure out. No filesystem, no subprocess.
44
53
  */
45
54
  import { type MovedBlock } from "./refactor/movedBlocks.js";
@@ -65,6 +74,12 @@ export interface MemberResource {
65
74
  invisibleMeta: string[];
66
75
  /** attributes whose value did not parse to a close — a truncated file. */
67
76
  unreadable: string[];
77
+ /** set on a module CALL (`type` is `module`): the repo-relative directory its
78
+ * local source resolves to. Part of the shape key — two calls of different
79
+ * modules are not the same shape, whatever their inputs. */
80
+ call?: {
81
+ dir: string;
82
+ };
68
83
  }
69
84
  /**
70
85
  * The canonical shape of a set of resources: types, names, argument names and
@@ -100,13 +115,24 @@ interface ConsolidationGroup {
100
115
  dir: string;
101
116
  environment: string | null;
102
117
  name_prefix: string | null;
118
+ /** the `source` this member's call writes: `proposed_module.path` is
119
+ * repo-relative, and a local source is relative to the caller. */
120
+ call_source: string;
103
121
  }[];
122
+ /** a module CALL the shape includes is here too, as type `module`. */
104
123
  resources: {
105
124
  type: string;
106
125
  name: string;
107
126
  arg_names: string[];
108
127
  multiplicity: string | null;
109
128
  }[];
129
+ /** the module calls the new module wraps: each moves into it keeping its
130
+ * name, and `source` is what it writes THERE — relative to the new module's
131
+ * directory, not to the roots it came from. */
132
+ wrapped_calls: {
133
+ name: string;
134
+ source: string;
135
+ }[];
110
136
  proposed_module: {
111
137
  name: string;
112
138
  path: string;
@@ -45,11 +45,11 @@ export interface CostEscalation {
45
45
  * decision is auditable, not a model judgement.
46
46
  */
47
47
  export declare function classifyCostEscalation(deltaMonthly: number | null, thresholdUsd: number | undefined): CostEscalation;
48
- export declare function runInfracostBreakdown(scanCwd: string, key: string): RunResult;
48
+ export declare function runInfracostBreakdown(scanCwd: string, key: string): Promise<RunResult>;
49
49
  /**
50
50
  * Cost of the base-branch version of the same Terraform, computed in a detached
51
51
  * git worktree so the current (fixed) checkout is never disturbed. Best-effort:
52
52
  * any failure (no base ref, worktree add fails, infracost errors) returns null
53
53
  * and the caller falls back to reporting current cost only.
54
54
  */
55
- export declare function infracostBaseline(cwd: string, key: string, tmpdir: string): CostBreakdown | null;
55
+ export declare function infracostBaseline(cwd: string, key: string, tmpdir: string): Promise<CostBreakdown | null>;
@@ -42,6 +42,12 @@ export interface CurrencyVerdict {
42
42
  /** how many MAJORs the constraint's best version trails the latest by —
43
43
  * >0 signals an interface-risk upgrade that must be `needs-human`. */
44
44
  majorsBehind: number;
45
+ /** the newest stable version in the major the constraint already admits,
46
+ * when the constraint does not admit it — the upgrade that crosses no major.
47
+ * An exact pin `3.15.1` with `3.15.2` published is outdated even when the
48
+ * latest release is two majors on; reporting only `latest` hides the one
49
+ * bump that needs nobody's sign-off. Null when there is none. */
50
+ latestInMajor: string | null;
45
51
  }
46
52
  export declare function classifyCurrency(params: {
47
53
  constraint: string | null;
@@ -127,6 +133,8 @@ interface ProviderCurrencyRow {
127
133
  constraint: string | null;
128
134
  latest: string | null;
129
135
  newest_satisfying: string | null;
136
+ /** see {@link CurrencyVerdict.latestInMajor}. */
137
+ latest_in_major: string | null;
130
138
  outdated: boolean;
131
139
  majors_behind: number;
132
140
  lookup: LookupStatus;
@@ -137,7 +145,10 @@ interface ModuleCurrencyRow {
137
145
  version: string | null;
138
146
  latest: string | null;
139
147
  newest_satisfying: string | null;
148
+ /** see {@link CurrencyVerdict.latestInMajor}. */
149
+ latest_in_major: string | null;
140
150
  outdated: boolean;
151
+ majors_behind: number;
141
152
  /** registry module with no `version` attribute — pin it (to `latest`). */
142
153
  unpinned: boolean;
143
154
  lookup: ModuleLookupStatus;
@@ -1,4 +1,4 @@
1
- import type { DeltaFinding, GateDelta } from "./scanDelta.js";
1
+ import { type DeltaFinding, type GateDelta, type UndeclaredRename } from "./scanDelta.js";
2
2
  /**
3
3
  * How many introduced findings one review answers individually. Past this the
4
4
  * rest are only counted: a review of hundreds of comments is read by no one,
@@ -17,6 +17,16 @@ export interface DeltaVerdict {
17
17
  }
18
18
  /** The gate's verdict on a delta: the same two halves `findings-gate` applies. */
19
19
  export declare function deltaVerdict(delta: GateDelta, requiredControls: string[]): DeltaVerdict;
20
+ /** Whether one introduced finding fails the gate on its own — the same two
21
+ * halves `deltaVerdict` applies to the whole delta. */
22
+ export declare function failsGate(finding: DeltaFinding, requiredControls: string[]): boolean;
23
+ /**
24
+ * The undeclared renames in a delta as one paragraph — what happened, what it
25
+ * costs at apply, and the one thing to do about it — or "" when there are none.
26
+ * `fmt` code-spans a value the way the caller's surface does: every address and
27
+ * directory came out of the PR's own files.
28
+ */
29
+ export declare function renderUndeclaredRenames(renames: readonly UndeclaredRename[], fmt: (text: string) => string): string;
20
30
  /** The compliance controls the introduced findings touch, sorted and unique. */
21
31
  export declare function controlsTouched(findings: readonly DeltaFinding[]): string[];
22
32
  export declare function renderDeltaSummary(input: {
@@ -0,0 +1,11 @@
1
+ import { scanSessionOf } from "./scanSession.js";
2
+ /** The id git gives a blob with these contents — what `git rev-parse HEAD:<path>` prints. */
3
+ export declare function gitBlobId(bytes: string): string;
4
+ /** Write an emit tool's artefact to `path` (absolute) and remember the bytes written. */
5
+ export declare function writeEmittedArtefact(toolState: Parameters<typeof scanSessionOf>[0], path: string, bytes: string): void;
6
+ /**
7
+ * True when `file` — repo-relative, as `git diff` names it — is an artefact an
8
+ * emit tool wrote this run and `committedBlob` (its blob id at the pushed
9
+ * commit, null when absent) is one of the versions it wrote.
10
+ */
11
+ export declare function isUnchangedEmittedArtefact(toolState: Parameters<typeof scanSessionOf>[0], repoTop: string, file: string, committedBlob: string | null): boolean;
@@ -161,6 +161,13 @@ export interface RefactorEquivalenceInput {
161
161
  * actually happened, so a bundle never claims a value check that did not run. */
162
162
  values_verified?: number;
163
163
  }
164
+ /**
165
+ * What a proposed-unproven change IS, named from the mode that made it. The
166
+ * agent's flag says only that the change is unproven; a signed statement that
167
+ * called a version bump a module adoption would misdescribe the artefact it
168
+ * signs.
169
+ */
170
+ export declare function proposedChangeOf(mode: string | undefined): string;
164
171
  /**
165
172
  * Build the refactor evidence statement (pure). Returns undefined when nothing
166
173
  * refactor-related happened (no equivalence proof, not a proposed-unproven b.4,
@@ -183,6 +190,9 @@ export declare function buildRefactorStatement(args: {
183
190
  } | undefined;
184
191
  /** the agent recorded the reviewed-plan outcome (b.4 with credentials). */
185
192
  reviewedPlan?: boolean;
193
+ /** what the unproven change is (`proposedChangeOf`); a module adoption when
194
+ * absent. */
195
+ change?: string;
186
196
  }): EvidenceRefactorStatement | undefined;
187
197
  /** The egress bound each third-party scanner that ran was held to. */
188
198
  export interface EvidenceEgressStatement {
@@ -1,5 +1,4 @@
1
1
  import type { LocalToolContext } from "../localContext.js";
2
- import { type GateDelta } from "./scanDelta.js";
3
2
  import { type ScanScanners } from "./tools/scan.js";
4
3
  import { type Concern } from "./types.js";
5
4
  import type { PullRequestRunContext } from "../../utils/github/pullRequestEvent.js";
@@ -22,20 +21,7 @@ import type { PullRequestRunContext } from "../../utils/github/pullRequestEvent.
22
21
  * Returns undefined when the checkout has no Terraform: the outputs then stay
23
22
  * unset, which is how a workflow tells "not scanned" from "scanned clean".
24
23
  */
25
- export declare function runGateScan(ctx: LocalToolContext, scanners?: ScanScanners, isTerraform?: (c: Concern) => boolean): Promise<Concern[] | undefined>;
26
- /**
27
- * The scan delta of a pull request: the base scanned with the same scanners and
28
- * configuration as the head, in a detached worktree so the checkout the agent
29
- * works in is never touched, and the two concern sets matched (`scanDelta.ts`).
30
- *
31
- * The base is the merge base of the PR's base commit and HEAD, which is the base
32
- * commit itself on GitHub's `refs/pull/N/merge` checkout and the fork point on a
33
- * head checkout — "what this PR changed" either way.
34
- *
35
- * Undefined when the base commit is not in the clone (a shallow checkout) or the
36
- * worktree cannot be made. The run then gates as it always has, and says why.
37
- */
38
- export declare function runScanDelta(ctx: LocalToolContext, pr: Pick<PullRequestRunContext, "baseSha" | "headSha">, headConcerns: Concern[], scanners?: ScanScanners): Promise<GateDelta | undefined>;
24
+ export declare function runGateScan(ctx: LocalToolContext, scanners?: ScanScanners): Promise<Concern[] | undefined>;
39
25
  /**
40
26
  * Record the gate scan on the session. A failure leaves `gateConcerns` unset —
41
27
  * the outputs then read "not scanned", never a pass — and must not stop the run.
@@ -50,4 +36,4 @@ export declare function captureGateScan(ctx: LocalToolContext, scanners?: ScanSc
50
36
  * compares two trees, so scoping would only hide what a suggestion broke).
51
37
  * Active concerns only.
52
38
  */
53
- export declare function scanForProof(ctx: LocalToolContext, cwd: string, scanners?: ScanScanners): Promise<Concern[]>;
39
+ export declare function scanForProof(ctx: LocalToolContext, cwd: string, files?: string[], scanners?: ScanScanners): Promise<Concern[]>;
@@ -181,6 +181,21 @@ export declare function hclParseStats(): HclParseStats;
181
181
  * across scans needs only this. */
182
182
  export declare function resetHclParseStats(): void;
183
183
  export declare function parseBlocks(hcl: string, keywords: readonly string[]): HclBlock[];
184
+ /**
185
+ * One block label: a quoted string or, as the HCL grammar also allows, a bare
186
+ * identifier — `resource aws_vpc main {` is the same block as
187
+ * `resource "aws_vpc" "main" {`, and pre-0.12 code is full of it. A reader that
188
+ * knew only the quoted form saw none of those resources, so a proof read a
189
+ * `terraform fmt` that quoted them as resources being ADDED.
190
+ */
191
+ export declare const BLOCK_LABEL: string;
192
+ /** a label as written, without its quotes. */
193
+ export declare function unquoteLabel(label: string): string;
194
+ /** a `resource <type> <name> {` header in either label style; groups 1 and 2
195
+ * are the labels as written ({@link unquoteLabel}). */
196
+ export declare const RESOURCE_HEADER: string;
197
+ /** a `module <name> {` header in either label style; group 1 is the label as written. */
198
+ export declare const MODULE_HEADER: string;
184
199
  /** One `name = <value>` assignment found at the top level of a block body. */
185
200
  export interface HclAssignment {
186
201
  name: string;
@@ -0,0 +1,21 @@
1
+ export interface InitArtefacts {
2
+ /** init output git neither tracks nor ignores. */
3
+ untracked: Set<string>;
4
+ /** committed lock files with uncommitted changes. */
5
+ modifiedLocks: Set<string>;
6
+ }
7
+ /**
8
+ * The `terraform init` output in the checkout, as repo-relative paths; null
9
+ * outside a git checkout. A committed lock file counts once it is modified:
10
+ * init adds the runner's platform hash to one made on another platform (a
11
+ * lock file from a Mac lacks the linux hash).
12
+ */
13
+ export declare function initArtefacts(cwd: string): InitArtefacts | null;
14
+ /**
15
+ * Undo what the gate scan's init did to the checkout: remove the artefacts it
16
+ * created and restore the committed lock files it changed. Validate inits every
17
+ * root in place, and a checkout that is dirty before the agent starts makes
18
+ * `checkout_pr` refuse — or, on a committing run, ships the change in the fix.
19
+ * What was there before the scan is left alone.
20
+ */
21
+ export declare function removeNewInitArtefacts(cwd: string, before: InitArtefacts | null, by: string): void;