infraweaver 0.3.11 → 0.3.13
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.
- package/README.md +1 -1
- package/dist/agents/opencode.d.ts +6 -0
- package/dist/agents/quotaTokens.d.ts +6 -0
- package/dist/cli.mjs +846 -412
- package/dist/index.js +806 -372
- package/dist/internal.js +4 -4
- package/dist/mcp/git.d.ts +6 -4
- package/dist/mcp/localContext.d.ts +7 -0
- package/dist/mcp/reviewCommentLimit.d.ts +55 -5
- package/dist/mcp/reviewMarkers.d.ts +5 -0
- package/dist/mcp/staleFix.d.ts +36 -1
- package/dist/mcp/terraform/awsPrices.d.ts +1 -1
- package/dist/mcp/terraform/azurePrices.d.ts +1 -1
- package/dist/mcp/terraform/concernResult.d.ts +9 -0
- package/dist/mcp/terraform/deltaSummary.d.ts +3 -0
- package/dist/mcp/terraform/hardcodedSecrets.d.ts +24 -10
- package/dist/mcp/terraform/refactorScope.d.ts +14 -2
- package/dist/mcp/terraform/ruleContext.d.ts +3 -0
- package/dist/mcp/terraform/scanSession.d.ts +2 -0
- package/dist/mcp/terraform/tree.d.ts +5 -0
- package/dist/mcp/terraform/types.d.ts +2 -1
- package/dist/mcp/terraform/verifySites.d.ts +56 -0
- package/dist/vendor/@infraweaver-io/models/tokenQuota.d.ts +7 -6
- package/package.json +2 -2
- package/src/agents/opencode.ts +8 -1
- package/src/agents/quotaTokens.ts +7 -1
- package/src/mcp/git.ts +64 -12
- package/src/mcp/localContext.ts +6 -1
- package/src/mcp/moduleExtraction.ts +5 -4
- package/src/mcp/review.ts +52 -3
- package/src/mcp/reviewCommentLimit.ts +169 -26
- package/src/mcp/reviewMarkers.ts +11 -0
- package/src/mcp/reviewProvenance.ts +1 -1
- package/src/mcp/staleFix.ts +73 -2
- package/src/mcp/terraform/awsPrices.ts +1 -1
- package/src/mcp/terraform/azurePrices.ts +23 -23
- package/src/mcp/terraform/concernResult.ts +18 -9
- package/src/mcp/terraform/deltaSummary.ts +4 -0
- package/src/mcp/terraform/hardcodedSecrets.ts +148 -27
- package/src/mcp/terraform/nativeRuleScanners.ts +2 -1
- package/src/mcp/terraform/nativeScan.ts +4 -0
- package/src/mcp/terraform/refactor/equivalence.ts +42 -9
- package/src/mcp/terraform/refactorScope.ts +90 -21
- package/src/mcp/terraform/ruleContext.ts +4 -0
- package/src/mcp/terraform/scanDelta.ts +67 -26
- package/src/mcp/terraform/scanSession.ts +6 -0
- package/src/mcp/terraform/tools/detectPlanDrift.ts +2 -0
- package/src/mcp/terraform/tools/ingestExternalFindings.ts +2 -0
- package/src/mcp/terraform/tools/normalizationCandidates.ts +5 -5
- package/src/mcp/terraform/tools/readFindings.ts +2 -0
- package/src/mcp/terraform/tools/scan.ts +3 -0
- package/src/mcp/terraform/tools/verifyRemediation.ts +23 -1
- package/src/mcp/terraform/tree.ts +8 -0
- package/src/mcp/terraform/types.ts +2 -1
- package/src/mcp/terraform/verifySites.ts +124 -0
- package/src/modes/refactor.ts +1 -1
- package/src/modes/remediate-and-refactor.ts +1 -1
- package/src/modes/remediate.ts +1 -1
- package/src/phases/runAgentWithWatchdogs.ts +3 -2
package/dist/cli.mjs
CHANGED
|
@@ -80148,7 +80148,7 @@ var require_polyfill = __commonJS({
|
|
|
80148
80148
|
var {
|
|
80149
80149
|
dirname: dirname16,
|
|
80150
80150
|
isAbsolute: isAbsolute10,
|
|
80151
|
-
join:
|
|
80151
|
+
join: join78,
|
|
80152
80152
|
parse: parse8,
|
|
80153
80153
|
resolve: resolve15,
|
|
80154
80154
|
sep: sep12,
|
|
@@ -80405,8 +80405,8 @@ var require_polyfill = __commonJS({
|
|
|
80405
80405
|
const dir = await readdir2(src);
|
|
80406
80406
|
for (let i = 0; i < dir.length; i++) {
|
|
80407
80407
|
const item = dir[i];
|
|
80408
|
-
const srcItem =
|
|
80409
|
-
const destItem =
|
|
80408
|
+
const srcItem = join78(src, item);
|
|
80409
|
+
const destItem = join78(dest, item);
|
|
80410
80410
|
const { destStat } = await checkPaths2(srcItem, destItem, opts);
|
|
80411
80411
|
await startCopy(destStat, srcItem, destItem, opts);
|
|
80412
80412
|
}
|
|
@@ -80479,7 +80479,7 @@ var require_cp = __commonJS({
|
|
|
80479
80479
|
// node_modules/.pnpm/@npmcli+fs@6.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js
|
|
80480
80480
|
var require_with_temp_dir = __commonJS({
|
|
80481
80481
|
"node_modules/.pnpm/@npmcli+fs@6.0.0/node_modules/@npmcli/fs/lib/with-temp-dir.js"(exports2, module) {
|
|
80482
|
-
var { join:
|
|
80482
|
+
var { join: join78, sep: sep12 } = __require("path");
|
|
80483
80483
|
var getOptions2 = require_get_options();
|
|
80484
80484
|
var { mkdir: mkdir5, mkdtemp, rm: rm2 } = __require("fs/promises");
|
|
80485
80485
|
var withTempDir = async (root, fn2, opts) => {
|
|
@@ -80487,7 +80487,7 @@ var require_with_temp_dir = __commonJS({
|
|
|
80487
80487
|
copy: ["tmpPrefix"]
|
|
80488
80488
|
});
|
|
80489
80489
|
await mkdir5(root, { recursive: true });
|
|
80490
|
-
const target = await mkdtemp(
|
|
80490
|
+
const target = await mkdtemp(join78(`${root}${sep12}`, options.tmpPrefix || ""));
|
|
80491
80491
|
let err;
|
|
80492
80492
|
let result;
|
|
80493
80493
|
try {
|
|
@@ -80512,13 +80512,13 @@ var require_with_temp_dir = __commonJS({
|
|
|
80512
80512
|
var require_readdir_scoped = __commonJS({
|
|
80513
80513
|
"node_modules/.pnpm/@npmcli+fs@6.0.0/node_modules/@npmcli/fs/lib/readdir-scoped.js"(exports2, module) {
|
|
80514
80514
|
var { readdir: readdir2 } = __require("fs/promises");
|
|
80515
|
-
var { join:
|
|
80515
|
+
var { join: join78 } = __require("path");
|
|
80516
80516
|
var readdirScoped = async (dir) => {
|
|
80517
80517
|
const results = [];
|
|
80518
80518
|
for (const item of await readdir2(dir)) {
|
|
80519
80519
|
if (item.startsWith("@")) {
|
|
80520
|
-
for (const scopedItem of await readdir2(
|
|
80521
|
-
results.push(
|
|
80520
|
+
for (const scopedItem of await readdir2(join78(dir, item))) {
|
|
80521
|
+
results.push(join78(item, scopedItem));
|
|
80522
80522
|
}
|
|
80523
80523
|
} else {
|
|
80524
80524
|
results.push(item);
|
|
@@ -80533,7 +80533,7 @@ var require_readdir_scoped = __commonJS({
|
|
|
80533
80533
|
// node_modules/.pnpm/@npmcli+fs@6.0.0/node_modules/@npmcli/fs/lib/move-file.js
|
|
80534
80534
|
var require_move_file = __commonJS({
|
|
80535
80535
|
"node_modules/.pnpm/@npmcli+fs@6.0.0/node_modules/@npmcli/fs/lib/move-file.js"(exports2, module) {
|
|
80536
|
-
var { dirname: dirname16, join:
|
|
80536
|
+
var { dirname: dirname16, join: join78, resolve: resolve15, relative: relative10, isAbsolute: isAbsolute10 } = __require("path");
|
|
80537
80537
|
var fs12 = __require("fs/promises");
|
|
80538
80538
|
var pathExists2 = async (path15) => {
|
|
80539
80539
|
try {
|
|
@@ -80563,7 +80563,7 @@ var require_move_file = __commonJS({
|
|
|
80563
80563
|
if (sourceStat.isDirectory()) {
|
|
80564
80564
|
const files = await fs12.readdir(source);
|
|
80565
80565
|
await Promise.all(files.map(
|
|
80566
|
-
(file2) => moveFile(
|
|
80566
|
+
(file2) => moveFile(join78(source, file2), join78(destination, file2), options, false, symlinks)
|
|
80567
80567
|
));
|
|
80568
80568
|
} else if (sourceStat.isSymbolicLink()) {
|
|
80569
80569
|
symlinks.push({ source, destination });
|
|
@@ -90400,23 +90400,23 @@ var require_helpers = __commonJS({
|
|
|
90400
90400
|
"node_modules/.pnpm/ip-address@10.7.3/node_modules/ip-address/dist/v6/helpers.js"(exports2) {
|
|
90401
90401
|
"use strict";
|
|
90402
90402
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
90403
|
-
exports2.escapeHtml =
|
|
90403
|
+
exports2.escapeHtml = escapeHtml2;
|
|
90404
90404
|
exports2.spanAllZeroes = spanAllZeroes;
|
|
90405
90405
|
exports2.spanAll = spanAll;
|
|
90406
90406
|
exports2.spanLeadingZeroes = spanLeadingZeroes;
|
|
90407
90407
|
exports2.simpleGroup = simpleGroup;
|
|
90408
|
-
function
|
|
90408
|
+
function escapeHtml2(s) {
|
|
90409
90409
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
90410
90410
|
}
|
|
90411
90411
|
function spanAllZeroes(s) {
|
|
90412
|
-
return
|
|
90412
|
+
return escapeHtml2(s).replace(/(0+)/g, '<span class="zero">$1</span>');
|
|
90413
90413
|
}
|
|
90414
90414
|
function spanAll(s, offset = 0) {
|
|
90415
90415
|
const letters = s.split("");
|
|
90416
|
-
return letters.map((n, i) => `<span class="digit value-${
|
|
90416
|
+
return letters.map((n, i) => `<span class="digit value-${escapeHtml2(n)} position-${i + offset}">${spanAllZeroes(n)}</span>`).join("");
|
|
90417
90417
|
}
|
|
90418
90418
|
function spanLeadingZeroesSimple(group2) {
|
|
90419
|
-
return
|
|
90419
|
+
return escapeHtml2(group2).replace(/^(0+)/, '<span class="zero">$1</span>');
|
|
90420
90420
|
}
|
|
90421
90421
|
function spanLeadingZeroes(address) {
|
|
90422
90422
|
const groups2 = address.split(":");
|
|
@@ -112581,14 +112581,14 @@ var require_turndown_cjs = __commonJS({
|
|
|
112581
112581
|
} else if (node3.nodeType === 1) {
|
|
112582
112582
|
replacement = replacementForNode.call(self2, node3);
|
|
112583
112583
|
}
|
|
112584
|
-
return
|
|
112584
|
+
return join78(output2, replacement);
|
|
112585
112585
|
}, "");
|
|
112586
112586
|
}
|
|
112587
112587
|
function postProcess(output2) {
|
|
112588
112588
|
var self2 = this;
|
|
112589
112589
|
this.rules.forEach(function(rule) {
|
|
112590
112590
|
if (typeof rule.append === "function") {
|
|
112591
|
-
output2 =
|
|
112591
|
+
output2 = join78(output2, rule.append(self2.options));
|
|
112592
112592
|
}
|
|
112593
112593
|
});
|
|
112594
112594
|
return output2.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -112600,7 +112600,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
112600
112600
|
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
112601
112601
|
return whitespace.leading + rule.replacement(content, node3, this.options) + whitespace.trailing;
|
|
112602
112602
|
}
|
|
112603
|
-
function
|
|
112603
|
+
function join78(output2, replacement) {
|
|
112604
112604
|
var s1 = trimTrailingNewlines(output2);
|
|
112605
112605
|
var s2 = trimLeadingNewlines(replacement);
|
|
112606
112606
|
var nls = Math.max(output2.length - s1.length, replacement.length - s2.length);
|
|
@@ -160536,7 +160536,7 @@ var init_cacheTwirpClient = __esm({
|
|
|
160536
160536
|
});
|
|
160537
160537
|
|
|
160538
160538
|
// node_modules/.pnpm/@actions+cache@6.3.0_supports-color@7.2.0/node_modules/@actions/cache/lib/internal/tar.js
|
|
160539
|
-
import { existsSync as
|
|
160539
|
+
import { existsSync as existsSync18, writeFileSync as writeFileSync21 } from "fs";
|
|
160540
160540
|
import * as path13 from "path";
|
|
160541
160541
|
function getTarPath() {
|
|
160542
160542
|
return __awaiter18(this, void 0, void 0, function* () {
|
|
@@ -160546,7 +160546,7 @@ function getTarPath() {
|
|
|
160546
160546
|
const systemTar = SystemTarPathOnWindows;
|
|
160547
160547
|
if (gnuTar) {
|
|
160548
160548
|
return { path: gnuTar, type: ArchiveToolType.GNU };
|
|
160549
|
-
} else if (
|
|
160549
|
+
} else if (existsSync18(systemTar)) {
|
|
160550
160550
|
return { path: systemTar, type: ArchiveToolType.BSD };
|
|
160551
160551
|
}
|
|
160552
160552
|
break;
|
|
@@ -191031,7 +191031,7 @@ var BOT_EMAIL = `${BOT_LOGIN}@users.noreply.github.com`;
|
|
|
191031
191031
|
var OIDC_AUDIENCE = `${PRODUCT_SLUG}-api`;
|
|
191032
191032
|
|
|
191033
191033
|
// src/commands/assess.ts
|
|
191034
|
-
import { existsSync as
|
|
191034
|
+
import { existsSync as existsSync9, statSync as statSync8 } from "node:fs";
|
|
191035
191035
|
import { isAbsolute as isAbsolute4, resolve as resolve7 } from "node:path";
|
|
191036
191036
|
var import_arg = __toESM(require_arg(), 1);
|
|
191037
191037
|
|
|
@@ -199939,7 +199939,7 @@ var log = {
|
|
|
199939
199939
|
debug: (...args2) => current.debug(...args2)
|
|
199940
199940
|
};
|
|
199941
199941
|
|
|
199942
|
-
// node_modules/.pnpm/@infraweaver-io+models@0.1.
|
|
199942
|
+
// node_modules/.pnpm/@infraweaver-io+models@0.1.7/node_modules/@infraweaver-io/models/dist/usage.js
|
|
199943
199943
|
function formatCostUsd(costUsd) {
|
|
199944
199944
|
return costUsd.toFixed(4);
|
|
199945
199945
|
}
|
|
@@ -200490,7 +200490,7 @@ import { randomBytes } from "node:crypto";
|
|
|
200490
200490
|
// package.json
|
|
200491
200491
|
var package_default = {
|
|
200492
200492
|
name: "infraweaver",
|
|
200493
|
-
version: "0.3.
|
|
200493
|
+
version: "0.3.13",
|
|
200494
200494
|
description: "GitHub Action that remediates Terraform to best practices and opens one scoped pull request per concern.",
|
|
200495
200495
|
keywords: [
|
|
200496
200496
|
"ai-coding-agent",
|
|
@@ -200593,7 +200593,7 @@ var package_default = {
|
|
|
200593
200593
|
"@infraweaver-io/ci": "^0.1.8",
|
|
200594
200594
|
"@infraweaver-io/core": "^0.1.5",
|
|
200595
200595
|
"@infraweaver-io/crosswalk": "^1.2.0",
|
|
200596
|
-
"@infraweaver-io/models": "^0.1.
|
|
200596
|
+
"@infraweaver-io/models": "^0.1.7",
|
|
200597
200597
|
"@infraweaver-io/policy-spec": "^1.2.0",
|
|
200598
200598
|
"@infraweaver-io/report-contract": "^0.1.5",
|
|
200599
200599
|
"@infraweaver-io/sandbox": "^0.1.8",
|
|
@@ -207495,7 +207495,18 @@ var SECRET_WORDS = /* @__PURE__ */ new Set([
|
|
|
207495
207495
|
"credential",
|
|
207496
207496
|
"credentials"
|
|
207497
207497
|
]);
|
|
207498
|
-
var SECRET_KEY_PREFIXES = /* @__PURE__ */ new Set([
|
|
207498
|
+
var SECRET_KEY_PREFIXES = /* @__PURE__ */ new Set([
|
|
207499
|
+
"api",
|
|
207500
|
+
"secret",
|
|
207501
|
+
"private",
|
|
207502
|
+
"signing",
|
|
207503
|
+
"access",
|
|
207504
|
+
"account",
|
|
207505
|
+
"client",
|
|
207506
|
+
"shared",
|
|
207507
|
+
"preshared",
|
|
207508
|
+
"master"
|
|
207509
|
+
]);
|
|
207499
207510
|
var NOT_SECRET_TOKENS = /* @__PURE__ */ new Set(["creation", "idempotency", "client", "request", "continuation"]);
|
|
207500
207511
|
function words(name) {
|
|
207501
207512
|
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[_-]+/).filter(Boolean);
|
|
@@ -207507,24 +207518,70 @@ function isSecretName(name) {
|
|
|
207507
207518
|
if (last === void 0) return false;
|
|
207508
207519
|
if (last === "key") return prev !== void 0 && SECRET_KEY_PREFIXES.has(prev);
|
|
207509
207520
|
if (last === "token" && prev !== void 0 && NOT_SECRET_TOKENS.has(prev)) return false;
|
|
207521
|
+
if (last === "string") return prev === "connection";
|
|
207522
|
+
if (last === "secret" && w.length === 1) return false;
|
|
207510
207523
|
return SECRET_WORDS.has(last);
|
|
207511
207524
|
}
|
|
207512
207525
|
function isPlaceholder(inner) {
|
|
207513
|
-
return inner.trim() === "" || /^[*xX.]+$/.test(inner) || /^<[^>]*>$/.test(inner) || //
|
|
207514
|
-
|
|
207526
|
+
return inner.trim() === "" || /^[*xX.]+$/.test(inner) || /^<[^>]*>$/.test(inner) || /^(?:true|false|null)$/.test(inner) || /^-?\d+(?:\.\d+)?$/.test(inner) || // a template directive is computed, like an interpolation: `"%{ if … }…%{ endif }"`
|
|
207527
|
+
inner.includes("%{") || // the dummy credentials offline plans and LocalStack are given (`secret_key = "test"`,
|
|
207528
|
+
// `"example-secret"`) — but only when that is the whole value: a lowercase tail at
|
|
207529
|
+
// most, so `"Test-Pr0dDbPassw0rd!"` is a password that happens to start with a word
|
|
207530
|
+
isDummy(inner) || // a token's lifetime unit: `token_validity_units { access_token = "hours" }`
|
|
207515
207531
|
/^(?:seconds|minutes|hours|days)$/.test(inner);
|
|
207516
207532
|
}
|
|
207517
|
-
|
|
207533
|
+
function isDummy(inner) {
|
|
207534
|
+
const m = /^(?:test|mock|fake|dummy|fixture|example|placeholder|sample)([_-].*)?$/i.exec(inner);
|
|
207535
|
+
return m !== null && (m[1] === void 0 || /^[_-][a-z0-9_-]*$/.test(m[1]));
|
|
207536
|
+
}
|
|
207537
|
+
function isSecretReference(inner) {
|
|
207538
|
+
return inner.startsWith("arn:") || /^projects\/[^/]+\/secrets\//.test(inner) || /^https:\/\/[\w-]+\.vault\.azure\.net\/secrets\//i.test(inner) || /^\/[\w./-]+$/.test(inner);
|
|
207539
|
+
}
|
|
207540
|
+
var HEADER = /^(resource|data|provider|module|locals|variable|output|terraform)\b([^{]*)\{(.*)$/;
|
|
207518
207541
|
var ASSIGNMENT = /^\s*(?:"([A-Za-z_][\w-]*)"|([A-Za-z_][\w-]*))\s*=(?!=)\s*(.*)$/;
|
|
207519
207542
|
var HEREDOC = /<<-?([A-Za-z_]\w*)\s*$/;
|
|
207520
207543
|
var INLINE_PAIR = /(?:"([A-Za-z_][\w-]*)"|\b([A-Za-z_][\w-]*))\s*=(?!=)\s*("(?:[^"\\]|\\.)*")/g;
|
|
207521
|
-
function literalValue(raw2) {
|
|
207544
|
+
function literalValue(name, raw2) {
|
|
207522
207545
|
const value2 = stripTrailingComment(raw2).replace(/,$/, "").trim();
|
|
207523
|
-
|
|
207546
|
+
if (!isStringLiteral(value2)) return false;
|
|
207547
|
+
const inner = value2.slice(1, -1);
|
|
207548
|
+
if (isPlaceholder(inner) || isSecretReference(inner)) return false;
|
|
207549
|
+
return !(words(name).at(-1) === "auth" && /^[A-Z]+(?:_[A-Z]+)*$/.test(inner));
|
|
207550
|
+
}
|
|
207551
|
+
function variableName(holder) {
|
|
207552
|
+
return /^variable\s+"?([\w-]+)"?/.exec(holder)?.[1] ?? "";
|
|
207553
|
+
}
|
|
207554
|
+
function opensBlockComment(line) {
|
|
207555
|
+
for (let i = 0; i < line.length; i++) {
|
|
207556
|
+
const span = skipNonCode(line, i);
|
|
207557
|
+
if (!span) continue;
|
|
207558
|
+
if (line.startsWith("/*", i) && !line.includes("*/", i + 2)) return true;
|
|
207559
|
+
i = span.end;
|
|
207560
|
+
}
|
|
207561
|
+
return false;
|
|
207562
|
+
}
|
|
207563
|
+
function closesOnLine(rest) {
|
|
207564
|
+
let depth = 1;
|
|
207565
|
+
for (let i = 0; i < rest.length; i++) {
|
|
207566
|
+
const span = skipNonCode(rest, i);
|
|
207567
|
+
if (span) {
|
|
207568
|
+
i = span.end;
|
|
207569
|
+
continue;
|
|
207570
|
+
}
|
|
207571
|
+
if (rest[i] === "{") depth++;
|
|
207572
|
+
else if (rest[i] === "}" && --depth === 0) return true;
|
|
207573
|
+
}
|
|
207574
|
+
return false;
|
|
207524
207575
|
}
|
|
207525
207576
|
function findHardcodedSecrets(hcl2) {
|
|
207577
|
+
return findInLines(hcl2, null);
|
|
207578
|
+
}
|
|
207579
|
+
function findTfvarsSecrets(hcl2, path15) {
|
|
207580
|
+
return findInLines(hcl2, `tfvars input ${path15}`);
|
|
207581
|
+
}
|
|
207582
|
+
function findInLines(hcl2, fileHolder) {
|
|
207526
207583
|
const out = [];
|
|
207527
|
-
let holder =
|
|
207584
|
+
let holder = fileHolder;
|
|
207528
207585
|
let heredoc = null;
|
|
207529
207586
|
let inComment = false;
|
|
207530
207587
|
const lines = hcl2.split("\n");
|
|
@@ -207544,12 +207601,28 @@ function findHardcodedSecrets(hcl2) {
|
|
|
207544
207601
|
continue;
|
|
207545
207602
|
}
|
|
207546
207603
|
if (trimmed.startsWith("#") || trimmed.startsWith("//")) continue;
|
|
207547
|
-
|
|
207604
|
+
if (opensBlockComment(line)) inComment = true;
|
|
207605
|
+
const header = fileHolder === null ? HEADER.exec(line) : null;
|
|
207548
207606
|
if (header) {
|
|
207549
207607
|
holder = `${header[1]}${header[2].trimEnd() ? ` ${header[2].trim()}` : ""}`;
|
|
207608
|
+
const rest = header[3];
|
|
207609
|
+
const opens2 = HEREDOC.exec(rest);
|
|
207610
|
+
if (opens2) heredoc = opens2[1];
|
|
207611
|
+
if (!holder.startsWith("output ") && !holder.startsWith("terraform")) {
|
|
207612
|
+
for (const pair of rest.matchAll(INLINE_PAIR)) {
|
|
207613
|
+
const key = pair[1] ?? pair[2];
|
|
207614
|
+
const isVariable = holder.startsWith("variable ");
|
|
207615
|
+
if (isVariable && key !== "default") continue;
|
|
207616
|
+
const name2 = isVariable ? variableName(holder) : key;
|
|
207617
|
+
if (isSecretName(name2) && literalValue(name2, pair[3])) {
|
|
207618
|
+
out.push({ name: name2, holder, line: i + 1 });
|
|
207619
|
+
}
|
|
207620
|
+
}
|
|
207621
|
+
}
|
|
207622
|
+
if (closesOnLine(rest)) holder = null;
|
|
207550
207623
|
continue;
|
|
207551
207624
|
}
|
|
207552
|
-
if (line.startsWith("}")) {
|
|
207625
|
+
if (fileHolder === null && line.startsWith("}")) {
|
|
207553
207626
|
holder = null;
|
|
207554
207627
|
continue;
|
|
207555
207628
|
}
|
|
@@ -207561,30 +207634,34 @@ function findHardcodedSecrets(hcl2) {
|
|
|
207561
207634
|
const name = m[1] ?? m[2];
|
|
207562
207635
|
const value2 = m[3];
|
|
207563
207636
|
if (holder.startsWith("variable ")) {
|
|
207564
|
-
const variable =
|
|
207565
|
-
if (name === "default" && isSecretName(variable) && literalValue(value2)) {
|
|
207637
|
+
const variable = variableName(holder);
|
|
207638
|
+
if (name === "default" && isSecretName(variable) && literalValue(variable, value2)) {
|
|
207566
207639
|
out.push({ name: variable, holder, line: i + 1 });
|
|
207567
207640
|
}
|
|
207568
207641
|
continue;
|
|
207569
207642
|
}
|
|
207570
207643
|
if (holder.startsWith("output ") || holder.startsWith("terraform")) continue;
|
|
207571
|
-
if (isSecretName(name) && literalValue(value2)) {
|
|
207644
|
+
if (isSecretName(name) && literalValue(name, value2)) {
|
|
207572
207645
|
out.push({ name, holder, line: i + 1 });
|
|
207573
207646
|
continue;
|
|
207574
207647
|
}
|
|
207575
207648
|
for (const pair of value2.matchAll(INLINE_PAIR)) {
|
|
207576
207649
|
const key = pair[1] ?? pair[2];
|
|
207577
|
-
if (isSecretName(key) && literalValue(pair[3])) {
|
|
207650
|
+
if (isSecretName(key) && literalValue(key, pair[3])) {
|
|
207578
207651
|
out.push({ name: key, holder, line: i + 1 });
|
|
207579
207652
|
}
|
|
207580
207653
|
}
|
|
207581
207654
|
}
|
|
207582
207655
|
return out;
|
|
207583
207656
|
}
|
|
207584
|
-
function scanHardcodedSecrets(files) {
|
|
207657
|
+
function scanHardcodedSecrets(files, tfvarsFiles = []) {
|
|
207585
207658
|
const concerns = [];
|
|
207586
|
-
|
|
207587
|
-
|
|
207659
|
+
const hits = [
|
|
207660
|
+
...files.map((f) => ({ path: f.path, found: findHardcodedSecrets(f.hcl) })),
|
|
207661
|
+
...tfvarsFiles.map((f) => ({ path: f.path, found: findTfvarsSecrets(f.hcl, f.path) }))
|
|
207662
|
+
];
|
|
207663
|
+
for (const { path: path15, found } of hits) {
|
|
207664
|
+
for (const hit of found) {
|
|
207588
207665
|
concerns.push(
|
|
207589
207666
|
buildConcern({
|
|
207590
207667
|
source: NATIVE_SOURCE,
|
|
@@ -209587,7 +209664,8 @@ var NATIVE_RULE_SCANNERS = [
|
|
|
209587
209664
|
name: "hardcoded-secrets",
|
|
209588
209665
|
rules: [HARDCODED_SECRET_ARGUMENT],
|
|
209589
209666
|
// Per file: the argument's name and its literal are both on the line itself.
|
|
209590
|
-
|
|
209667
|
+
// The only rule that reads `.tfvars`: an input file holds values, not config.
|
|
209668
|
+
scan: (ctx) => ({ concerns: scanHardcodedSecrets(ctx.files, ctx.tfvarsFiles) })
|
|
209591
209669
|
},
|
|
209592
209670
|
{
|
|
209593
209671
|
name: "write-only",
|
|
@@ -209672,6 +209750,7 @@ function createRuleContext(input2) {
|
|
|
209672
209750
|
cwd: input2.cwd,
|
|
209673
209751
|
files: input2.files,
|
|
209674
209752
|
tofuFiles: input2.tofuFiles ?? [],
|
|
209753
|
+
tfvarsFiles: input2.tfvarsFiles ?? [],
|
|
209675
209754
|
truncated: input2.truncated ?? null,
|
|
209676
209755
|
repeatedLiteralThreshold: input2.repeatedLiteralThreshold
|
|
209677
209756
|
};
|
|
@@ -209723,6 +209802,9 @@ function readTfTree(cwd, limits) {
|
|
|
209723
209802
|
function readTofuTree(cwd, limits) {
|
|
209724
209803
|
return readTree(cwd, ".tofu", limits);
|
|
209725
209804
|
}
|
|
209805
|
+
function readTfvarsTree(cwd, limits) {
|
|
209806
|
+
return readTree(cwd, ".tfvars", limits);
|
|
209807
|
+
}
|
|
209726
209808
|
var OVERSIZE_NAMED = 5;
|
|
209727
209809
|
function describeOversize(paths) {
|
|
209728
209810
|
const named = paths.slice(0, OVERSIZE_NAMED).join(", ");
|
|
@@ -209751,6 +209833,9 @@ function scanNative(cwd, opts = {}) {
|
|
|
209751
209833
|
// walk over a suffix most repos do not use at all, and threading it through
|
|
209752
209834
|
// the context keeps the scanners uniform.
|
|
209753
209835
|
tofuFiles: readTofuTree(cwd).files,
|
|
209836
|
+
// likewise only for the hardcoded-secret rule: a value kept out of the `.tf`
|
|
209837
|
+
// source is most often committed here instead
|
|
209838
|
+
tfvarsFiles: readTfvarsTree(cwd).files,
|
|
209754
209839
|
truncated: tree.truncated,
|
|
209755
209840
|
repeatedLiteralThreshold: opts.repeatedLiteralThreshold ?? DEFAULT_REPEAT_THRESHOLD
|
|
209756
209841
|
});
|
|
@@ -214109,7 +214194,7 @@ function TerraformAssessTool(ctx) {
|
|
|
214109
214194
|
// src/mcp/localServer.ts
|
|
214110
214195
|
import { mkdtempSync as mkdtempSync4 } from "node:fs";
|
|
214111
214196
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
214112
|
-
import { join as
|
|
214197
|
+
import { join as join41 } from "node:path";
|
|
214113
214198
|
|
|
214114
214199
|
// node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
|
|
214115
214200
|
var external_exports = {};
|
|
@@ -271571,7 +271656,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
271571
271656
|
}
|
|
271572
271657
|
};
|
|
271573
271658
|
|
|
271574
|
-
// node_modules/.pnpm/@infraweaver-io+models@0.1.
|
|
271659
|
+
// node_modules/.pnpm/@infraweaver-io+models@0.1.7/node_modules/@infraweaver-io/models/dist/catalog.js
|
|
271575
271660
|
function provider(config3) {
|
|
271576
271661
|
return config3;
|
|
271577
271662
|
}
|
|
@@ -272932,12 +273017,47 @@ function readTfDir(cwd, dir) {
|
|
|
272932
273017
|
}
|
|
272933
273018
|
|
|
272934
273019
|
// src/mcp/terraform/refactorScope.ts
|
|
272935
|
-
import {
|
|
273020
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync12, statSync as statSync5 } from "node:fs";
|
|
272936
273021
|
import { join as join22 } from "node:path";
|
|
272937
273022
|
function isExamplePath(path15) {
|
|
272938
|
-
return /(?:^|\/)examples
|
|
273023
|
+
return /(?:^|\/)examples\/|^example\//i.test(path15.replace(/\\/g, "/"));
|
|
273024
|
+
}
|
|
273025
|
+
var PROVIDER_OR_BACKEND = new RegExp(
|
|
273026
|
+
String.raw`(?:^|\n)\s*(?:provider|backend)\s+${BLOCK_LABEL}\s*\{`
|
|
273027
|
+
);
|
|
273028
|
+
var CLOUD_BLOCK = /(?:^|\n)\s*cloud\s*\{/;
|
|
273029
|
+
function configuresDeployment(name, text) {
|
|
273030
|
+
if (name.endsWith(".tf.json")) {
|
|
273031
|
+
let doc;
|
|
273032
|
+
try {
|
|
273033
|
+
doc = JSON.parse(text);
|
|
273034
|
+
} catch {
|
|
273035
|
+
return false;
|
|
273036
|
+
}
|
|
273037
|
+
if (typeof doc !== "object" || doc === null) return false;
|
|
273038
|
+
const { provider: provider2, terraform } = doc;
|
|
273039
|
+
if (provider2 !== void 0) return true;
|
|
273040
|
+
return [terraform].flat().some((t) => typeof t === "object" && t !== null && ("backend" in t || "cloud" in t));
|
|
273041
|
+
}
|
|
273042
|
+
if (PROVIDER_OR_BACKEND.test(text)) return true;
|
|
273043
|
+
return parseBlocks(text, ["terraform"]).some((b) => CLOUD_BLOCK.test(b.body));
|
|
273044
|
+
}
|
|
273045
|
+
var isTerraformFile2 = (name) => name.endsWith(".tf") || name.endsWith(".tf.json");
|
|
273046
|
+
function deploysFrom(dir) {
|
|
273047
|
+
let names;
|
|
273048
|
+
try {
|
|
273049
|
+
names = readdirSync6(dir).filter(isTerraformFile2);
|
|
273050
|
+
} catch {
|
|
273051
|
+
return false;
|
|
273052
|
+
}
|
|
273053
|
+
return names.some((name) => {
|
|
273054
|
+
try {
|
|
273055
|
+
return configuresDeployment(name, readFileSync12(join22(dir, name), "utf8"));
|
|
273056
|
+
} catch {
|
|
273057
|
+
return false;
|
|
273058
|
+
}
|
|
273059
|
+
});
|
|
272939
273060
|
}
|
|
272940
|
-
var PROVIDER_OR_BACKEND = /^\s*(?:provider\s+"|backend\s+")/m;
|
|
272941
273061
|
function holdsTerraform(dir, depth) {
|
|
272942
273062
|
let entries;
|
|
272943
273063
|
try {
|
|
@@ -272955,26 +273075,35 @@ function holdsTerraform(dir, depth) {
|
|
|
272955
273075
|
return false;
|
|
272956
273076
|
}
|
|
272957
273077
|
function libraryRepoReason(cwd) {
|
|
272958
|
-
let
|
|
273078
|
+
let rootEntries;
|
|
272959
273079
|
try {
|
|
272960
|
-
|
|
273080
|
+
rootEntries = readdirSync6(cwd);
|
|
272961
273081
|
} catch {
|
|
272962
273082
|
return null;
|
|
272963
273083
|
}
|
|
272964
|
-
if (
|
|
272965
|
-
|
|
272966
|
-
let text;
|
|
272967
|
-
try {
|
|
272968
|
-
text = readFileSync12(join22(cwd, f), "utf8");
|
|
272969
|
-
} catch {
|
|
272970
|
-
continue;
|
|
272971
|
-
}
|
|
272972
|
-
if (PROVIDER_OR_BACKEND.test(text)) return null;
|
|
272973
|
-
}
|
|
272974
|
-
const examples = ["examples", "example"].find((d) => existsSync6(join22(cwd, d)));
|
|
273084
|
+
if (!rootEntries.some(isTerraformFile2) || deploysFrom(cwd)) return null;
|
|
273085
|
+
const examples = rootEntries.find((d) => /^examples?$/i.test(d));
|
|
272975
273086
|
if (examples === void 0 || !holdsTerraform(join22(cwd, examples), 2)) return null;
|
|
272976
273087
|
return `the repository root configures no provider and no backend, and ships \`${examples}/\`: it is a module other configurations call, so restructuring it is churn for every caller`;
|
|
272977
273088
|
}
|
|
273089
|
+
function libraryScope(cwd) {
|
|
273090
|
+
const reason = libraryRepoReason(cwd);
|
|
273091
|
+
if (reason === null) return () => null;
|
|
273092
|
+
const deploys = /* @__PURE__ */ new Map();
|
|
273093
|
+
return (file2) => {
|
|
273094
|
+
const dirs = file2.replace(/\\/g, "/").split("/").slice(0, -1);
|
|
273095
|
+
for (let i = dirs.length; i > 0; i--) {
|
|
273096
|
+
const dir = dirs.slice(0, i).join("/");
|
|
273097
|
+
let d = deploys.get(dir);
|
|
273098
|
+
if (d === void 0) {
|
|
273099
|
+
d = deploysFrom(join22(cwd, dir));
|
|
273100
|
+
deploys.set(dir, d);
|
|
273101
|
+
}
|
|
273102
|
+
if (d) return null;
|
|
273103
|
+
}
|
|
273104
|
+
return reason;
|
|
273105
|
+
};
|
|
273106
|
+
}
|
|
272978
273107
|
function reportOnly(reason) {
|
|
272979
273108
|
return reason === null ? {} : { report_only: true, report_only_reason: reason };
|
|
272980
273109
|
}
|
|
@@ -273332,12 +273461,12 @@ function ModuleExtractionCandidatesTool(ctx) {
|
|
|
273332
273461
|
parameters: ModuleExtractionCandidatesParams,
|
|
273333
273462
|
execute: execute(async () => {
|
|
273334
273463
|
const cwd = ctx.payload.cwd ?? process.cwd();
|
|
273464
|
+
const library = libraryScope(cwd);
|
|
273335
273465
|
const candidates = findExtractionCandidates(
|
|
273336
273466
|
cwd,
|
|
273337
273467
|
ctx.payload.moduleCatalogue,
|
|
273338
273468
|
ctx.toolState.orgModuleHcl
|
|
273339
|
-
).filter((c) => ctx.payload.refactorExamples || !isExamplePath(c.cluster.file));
|
|
273340
|
-
const library = libraryRepoReason(cwd);
|
|
273469
|
+
).filter((c) => ctx.payload.refactorExamples || !isExamplePath(c.cluster.file)).map((c) => ({ ...reportOnly(library(c.cluster.file)), ...c }));
|
|
273341
273470
|
const matched = candidates.filter((c) => c.candidates.length > 0);
|
|
273342
273471
|
const reasons = {};
|
|
273343
273472
|
for (const c of candidates)
|
|
@@ -273351,7 +273480,6 @@ function ModuleExtractionCandidatesTool(ctx) {
|
|
|
273351
273480
|
`\xBB module_extraction_candidates: ${candidates.length} cluster(s), ${matched.length} with a module match` + (partialInterfaces.length > 0 ? `, ${partialInterfaces.length} partial-interface block(s)` : "")
|
|
273352
273481
|
);
|
|
273353
273482
|
return toolOk({
|
|
273354
|
-
...reportOnly(library),
|
|
273355
273483
|
cluster_count: candidates.length,
|
|
273356
273484
|
matched_count: matched.length,
|
|
273357
273485
|
candidates,
|
|
@@ -273375,7 +273503,7 @@ function ModuleExtractionCandidatesTool(ctx) {
|
|
|
273375
273503
|
}
|
|
273376
273504
|
|
|
273377
273505
|
// src/mcp/moduleTests.ts
|
|
273378
|
-
import { existsSync as
|
|
273506
|
+
import { existsSync as existsSync6, readdirSync as readdirSync7, readFileSync as readFileSync14, statSync as statSync6 } from "node:fs";
|
|
273379
273507
|
import { join as join24 } from "node:path";
|
|
273380
273508
|
var MODULE_META_ARGS = /* @__PURE__ */ new Set([
|
|
273381
273509
|
"source",
|
|
@@ -273496,7 +273624,7 @@ function resolveSourceDir(fromDir, source) {
|
|
|
273496
273624
|
}
|
|
273497
273625
|
function isDir(p) {
|
|
273498
273626
|
try {
|
|
273499
|
-
return
|
|
273627
|
+
return existsSync6(p) && statSync6(p).isDirectory();
|
|
273500
273628
|
} catch {
|
|
273501
273629
|
return false;
|
|
273502
273630
|
}
|
|
@@ -273630,7 +273758,7 @@ function TerraformModuleTestsTool(ctx) {
|
|
|
273630
273758
|
}
|
|
273631
273759
|
|
|
273632
273760
|
// src/mcp/terraform/tools/advise.ts
|
|
273633
|
-
import { existsSync as
|
|
273761
|
+
import { existsSync as existsSync7, readFileSync as readFileSync16 } from "node:fs";
|
|
273634
273762
|
import { join as join26 } from "node:path";
|
|
273635
273763
|
|
|
273636
273764
|
// src/mcp/terraform/fixMemory.ts
|
|
@@ -273789,7 +273917,7 @@ function inlineWaivers(content, file2) {
|
|
|
273789
273917
|
}
|
|
273790
273918
|
function readLearnings(tmpdir6) {
|
|
273791
273919
|
const path15 = join26(tmpdir6, LEARNINGS_FILE);
|
|
273792
|
-
if (!
|
|
273920
|
+
if (!existsSync7(path15)) return [];
|
|
273793
273921
|
try {
|
|
273794
273922
|
return readFileSync16(path15, "utf-8").split("\n");
|
|
273795
273923
|
} catch {
|
|
@@ -275148,8 +275276,11 @@ function ConsolidationCandidatesTool(ctx) {
|
|
|
275148
275276
|
}
|
|
275149
275277
|
|
|
275150
275278
|
// src/mcp/terraform/tools/detectPlanDrift.ts
|
|
275151
|
-
import { readFileSync as
|
|
275152
|
-
import { join as
|
|
275279
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
275280
|
+
import { join as join28 } from "node:path";
|
|
275281
|
+
|
|
275282
|
+
// src/mcp/staleFix.ts
|
|
275283
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
275153
275284
|
|
|
275154
275285
|
// node_modules/.pnpm/@infraweaver-io+ci@0.1.8/node_modules/@infraweaver-io/ci/dist/progressComment.js
|
|
275155
275286
|
function parseProgressComment(raw2) {
|
|
@@ -276206,7 +276337,31 @@ function groupIdFromBranch(branch) {
|
|
|
276206
276337
|
}
|
|
276207
276338
|
function remediationBranchSuffix(base, defaultBranch) {
|
|
276208
276339
|
if (!base || !defaultBranch || base === defaultBranch) return "";
|
|
276209
|
-
|
|
276340
|
+
const slug2 = base.replace(/[^A-Za-z0-9._-]+/g, "-");
|
|
276341
|
+
if (slug2 === base) return `--${slug2}`;
|
|
276342
|
+
return `--${slug2}-${createHash6("sha1").update(base).digest("hex").slice(0, 8)}`;
|
|
276343
|
+
}
|
|
276344
|
+
function remediationBranchFor(id, base, defaultBranch, open3) {
|
|
276345
|
+
const computed = `remediate/${id}${remediationBranchSuffix(base, defaultBranch)}`;
|
|
276346
|
+
const heads = (open3 ?? []).filter((pr) => pr.base === base && groupIdFromBranch(pr.head) === id).map((pr) => pr.head).filter((head) => !(open3 ?? []).some((pr) => pr.head === head && pr.base !== base));
|
|
276347
|
+
return heads.includes(computed) ? computed : heads[0] ?? computed;
|
|
276348
|
+
}
|
|
276349
|
+
async function listOpenRemediationPrs(ctx) {
|
|
276350
|
+
const { octokit, repo } = ctx;
|
|
276351
|
+
if (ctx.toolState?.selectedMode !== "Remediate") return [];
|
|
276352
|
+
if (!octokit || !repo?.owner || !repo.name) return [];
|
|
276353
|
+
try {
|
|
276354
|
+
const open3 = await octokit.paginate(octokit.rest.pulls.list, {
|
|
276355
|
+
owner: repo.owner,
|
|
276356
|
+
repo: repo.name,
|
|
276357
|
+
state: "open",
|
|
276358
|
+
per_page: 100
|
|
276359
|
+
});
|
|
276360
|
+
return open3.filter((pr) => pr.head.repo?.id === pr.base.repo.id && groupIdFromBranch(pr.head.ref)).map((pr) => ({ head: pr.head.ref, base: pr.base.ref }));
|
|
276361
|
+
} catch (e) {
|
|
276362
|
+
log2.warning(`\xBB could not list open remediation PRs: ${errorMessage(e)}`);
|
|
276363
|
+
return [];
|
|
276364
|
+
}
|
|
276210
276365
|
}
|
|
276211
276366
|
function matchesBotIdentity(identity) {
|
|
276212
276367
|
const normalized = identity.replace(/\[bot\]$/i, "").toLowerCase();
|
|
@@ -276897,6 +277052,68 @@ function dedupeCrossScanner(concerns) {
|
|
|
276897
277052
|
return [...merged, ...passthrough];
|
|
276898
277053
|
}
|
|
276899
277054
|
|
|
277055
|
+
// src/mcp/terraform/verifySites.ts
|
|
277056
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
277057
|
+
import { join as join27 } from "node:path";
|
|
277058
|
+
function fileReader(cwd) {
|
|
277059
|
+
const cache3 = /* @__PURE__ */ new Map();
|
|
277060
|
+
return (file2) => {
|
|
277061
|
+
if (!cache3.has(file2)) {
|
|
277062
|
+
let text;
|
|
277063
|
+
try {
|
|
277064
|
+
text = readFileSync17(join27(cwd, file2), "utf8");
|
|
277065
|
+
} catch {
|
|
277066
|
+
text = null;
|
|
277067
|
+
}
|
|
277068
|
+
cache3.set(file2, text);
|
|
277069
|
+
}
|
|
277070
|
+
return cache3.get(file2) ?? null;
|
|
277071
|
+
};
|
|
277072
|
+
}
|
|
277073
|
+
function siteOf(c, read3) {
|
|
277074
|
+
const text = read3(c.location.file);
|
|
277075
|
+
return text === null ? null : resourceAddressAt(text, c.location.line);
|
|
277076
|
+
}
|
|
277077
|
+
function recordConcernSites(session, concerns, cwd, linesMatchTree) {
|
|
277078
|
+
const read3 = fileReader(cwd);
|
|
277079
|
+
session.siteById ??= /* @__PURE__ */ new Map();
|
|
277080
|
+
session.firstSitesByKey ??= /* @__PURE__ */ new Map();
|
|
277081
|
+
const first = session.firstSitesByKey;
|
|
277082
|
+
const fresh = /* @__PURE__ */ new Map();
|
|
277083
|
+
for (const c of concerns) {
|
|
277084
|
+
const site = linesMatchTree ? siteOf(c, read3) : null;
|
|
277085
|
+
const prior = session.siteById.get(c.id);
|
|
277086
|
+
session.siteById.set(c.id, prior === void 0 || prior === site ? site : null);
|
|
277087
|
+
if (!linesMatchTree) continue;
|
|
277088
|
+
const key = concernKeyOf(c);
|
|
277089
|
+
if (first.has(key)) continue;
|
|
277090
|
+
const sites = fresh.get(key) ?? /* @__PURE__ */ new Set();
|
|
277091
|
+
sites.add(site);
|
|
277092
|
+
fresh.set(key, sites);
|
|
277093
|
+
}
|
|
277094
|
+
for (const [key, sites] of fresh) first.set(key, sites);
|
|
277095
|
+
}
|
|
277096
|
+
function resolvedAtSite(params) {
|
|
277097
|
+
const firingByKey = /* @__PURE__ */ new Map();
|
|
277098
|
+
for (const c of params.current) {
|
|
277099
|
+
const list = firingByKey.get(c.key) ?? [];
|
|
277100
|
+
list.push(c.site);
|
|
277101
|
+
firingByKey.set(c.key, list);
|
|
277102
|
+
}
|
|
277103
|
+
const out = [];
|
|
277104
|
+
for (const r of params.requested) {
|
|
277105
|
+
if (r.site === null || r.file === void 0) continue;
|
|
277106
|
+
const firing = firingByKey.get(r.key) ?? [];
|
|
277107
|
+
const known = params.firstSites.get(r.key);
|
|
277108
|
+
if (known === void 0) continue;
|
|
277109
|
+
if (firing.some((s) => s === null || !known.has(s))) continue;
|
|
277110
|
+
if (firing.includes(r.site)) continue;
|
|
277111
|
+
if (!params.declared(r.file).has(r.site)) continue;
|
|
277112
|
+
out.push(r.id);
|
|
277113
|
+
}
|
|
277114
|
+
return out;
|
|
277115
|
+
}
|
|
277116
|
+
|
|
276900
277117
|
// src/mcp/terraform/concernResult.ts
|
|
276901
277118
|
function annotateConcerns(rawConcerns, opts) {
|
|
276902
277119
|
const inScope = opts.inScope ?? (() => true);
|
|
@@ -276923,6 +277140,7 @@ function buildConcernResult(ctx, rawConcerns, opts) {
|
|
|
276923
277140
|
fullBaseline.map((c) => concernKeyOf(c))
|
|
276924
277141
|
);
|
|
276925
277142
|
recordConcernKeys(session, fullBaseline);
|
|
277143
|
+
recordConcernSites(session, fullBaseline, opts.cwd, opts.linesMatchTree ?? false);
|
|
276926
277144
|
session.baselineFmtDriftFiles = union3(
|
|
276927
277145
|
session.baselineFmtDriftFiles,
|
|
276928
277146
|
fullBaseline.filter((c) => c.source === "terraform-fmt").map((c) => c.location.file)
|
|
@@ -276937,13 +277155,13 @@ function buildConcernResult(ctx, rawConcerns, opts) {
|
|
|
276937
277155
|
active,
|
|
276938
277156
|
opts.autonomyThreshold
|
|
276939
277157
|
);
|
|
276940
|
-
const
|
|
276941
|
-
|
|
276942
|
-
|
|
276943
|
-
);
|
|
276944
|
-
const groups2 = (opts.priority ? prioritizeGroups(annotatedGroups, active, opts.priority) : annotatedGroups).map((g) => ({ ...g, branch: `remediate/${g.id}${suffix2}` }));
|
|
277158
|
+
const base = remediationBaseOf(ctx);
|
|
277159
|
+
const defaultBranch = ctx.repo?.data.default_branch?.trim() || void 0;
|
|
277160
|
+
const branchFor = (id) => remediationBranchFor(id, base, defaultBranch, opts.openRemediationPrs);
|
|
277161
|
+
const groups2 = (opts.priority ? prioritizeGroups(annotatedGroups, active, opts.priority) : annotatedGroups).map((g) => ({ ...g, branch: branchFor(g.id) }));
|
|
276945
277162
|
const planned = planBatches(groups2);
|
|
276946
|
-
const
|
|
277163
|
+
const batchId = planned.batch_branch ? groupIdFromBranch(planned.batch_branch) : null;
|
|
277164
|
+
const batchPlan = batchId ? { ...planned, batch_branch: branchFor(batchId) } : planned;
|
|
276947
277165
|
const bySeverity = {};
|
|
276948
277166
|
for (const c of active) bySeverity[c.severity] = (bySeverity[c.severity] ?? 0) + 1;
|
|
276949
277167
|
return {
|
|
@@ -277373,7 +277591,7 @@ function readTfFiles(cwd) {
|
|
|
277373
277591
|
const out = [];
|
|
277374
277592
|
for (const file2 of walkTfFiles(cwd)) {
|
|
277375
277593
|
try {
|
|
277376
|
-
out.push({ file: file2, hcl:
|
|
277594
|
+
out.push({ file: file2, hcl: readFileSync18(join28(cwd, file2), "utf8") });
|
|
277377
277595
|
} catch {
|
|
277378
277596
|
}
|
|
277379
277597
|
}
|
|
@@ -277390,7 +277608,7 @@ function DetectPlanDriftTool(ctx) {
|
|
|
277390
277608
|
const planPath = path15 || !envPlanPath ? resolveWithinCwd(cwd, path15 ?? "plan.json") : envPlanPath;
|
|
277391
277609
|
let raw2;
|
|
277392
277610
|
try {
|
|
277393
|
-
raw2 =
|
|
277611
|
+
raw2 = readFileSync18(planPath, "utf8");
|
|
277394
277612
|
} catch {
|
|
277395
277613
|
return skipResult(
|
|
277396
277614
|
"plan_artifact_not_found",
|
|
@@ -277460,7 +277678,8 @@ function DetectPlanDriftTool(ctx) {
|
|
|
277460
277678
|
autonomyThreshold,
|
|
277461
277679
|
// drift is a narrow concern source — join any prior scan baseline so a
|
|
277462
277680
|
// later ✗→✓ verify doesn't read the whole workspace as regressions.
|
|
277463
|
-
baselineMode: "merge"
|
|
277681
|
+
baselineMode: "merge",
|
|
277682
|
+
openRemediationPrs: await listOpenRemediationPrs(ctx)
|
|
277464
277683
|
});
|
|
277465
277684
|
log2.info(
|
|
277466
277685
|
`\xBB detect_plan_drift: ${active.length} drifted resource(s) \u2265 ${threshold} from ${planPath}` + (noiseFiltered.length ? `, ${noiseFiltered.length} noise-filtered` : "") + (unlocated.length ? `, ${unlocated.length} unlocated` : "") + (statefulForgotten.length ? `, ${statefulForgotten.length} STATEFUL forget(s)` : "") + (suppressed.length ? ` (${suppressed.length} suppressed)` : "")
|
|
@@ -277522,22 +277741,22 @@ function DetectPlanDriftTool(ctx) {
|
|
|
277522
277741
|
}
|
|
277523
277742
|
|
|
277524
277743
|
// src/mcp/terraform/tools/emitCost.ts
|
|
277525
|
-
import { readFileSync as
|
|
277526
|
-
import { join as
|
|
277744
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync4 } from "node:fs";
|
|
277745
|
+
import { join as join30 } from "node:path";
|
|
277527
277746
|
|
|
277528
277747
|
// src/mcp/guardrails.ts
|
|
277529
277748
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
277530
|
-
import { readFileSync as
|
|
277531
|
-
import { join as
|
|
277749
|
+
import { readFileSync as readFileSync19, rmSync as rmSync2 } from "node:fs";
|
|
277750
|
+
import { join as join29 } from "node:path";
|
|
277532
277751
|
|
|
277533
277752
|
// src/mcp/terraform/emittedArtefacts.ts
|
|
277534
|
-
import { createHash as
|
|
277753
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
277535
277754
|
import { writeFileSync as writeFileSync3 } from "node:fs";
|
|
277536
277755
|
import { resolve as resolve5 } from "node:path";
|
|
277537
277756
|
var ARTEFACT_DIR = "compliance/";
|
|
277538
277757
|
function gitBlobId(bytes) {
|
|
277539
277758
|
const content = Buffer.from(bytes, "utf8");
|
|
277540
|
-
return
|
|
277759
|
+
return createHash7("sha1").update(`blob ${content.length}\0`).update(content).digest("hex");
|
|
277541
277760
|
}
|
|
277542
277761
|
function writeEmittedArtefact(toolState, path15, bytes) {
|
|
277543
277762
|
writeFileSync3(path15, bytes);
|
|
@@ -277830,7 +278049,7 @@ function parseGitleaksReport(json5) {
|
|
|
277830
278049
|
return hits;
|
|
277831
278050
|
}
|
|
277832
278051
|
function scanWithGitleaks(ctx, base) {
|
|
277833
|
-
const reportPath =
|
|
278052
|
+
const reportPath = join29(ctx.tmpdir, `gitleaks-report-${process.pid}.json`);
|
|
277834
278053
|
const cwd = ctx.payload.cwd ?? process.cwd();
|
|
277835
278054
|
const result = spawnSync5(
|
|
277836
278055
|
"gitleaks",
|
|
@@ -277864,7 +278083,7 @@ function scanWithGitleaks(ctx, base) {
|
|
|
277864
278083
|
return null;
|
|
277865
278084
|
}
|
|
277866
278085
|
try {
|
|
277867
|
-
const report2 =
|
|
278086
|
+
const report2 = readFileSync19(reportPath, "utf8");
|
|
277868
278087
|
return parseGitleaksReport(report2);
|
|
277869
278088
|
} catch {
|
|
277870
278089
|
return [];
|
|
@@ -277936,7 +278155,7 @@ function assertNoForeignDialectIntroduced(ctx) {
|
|
|
277936
278155
|
const file2 = rel.replace(/\\/g, "/");
|
|
277937
278156
|
if (changedSet.has(file2)) continue;
|
|
277938
278157
|
try {
|
|
277939
|
-
established.push(...findDialectMarkers(
|
|
278158
|
+
established.push(...findDialectMarkers(readFileSync19(join29(cwd, rel), "utf8"), file2));
|
|
277940
278159
|
} catch {
|
|
277941
278160
|
}
|
|
277942
278161
|
}
|
|
@@ -278310,7 +278529,7 @@ var OpenPrOverlapError = class extends Error {
|
|
|
278310
278529
|
// src/mcp/terraform/awsPrices.ts
|
|
278311
278530
|
var AWS_PRICE_REGION = "eu-west-2";
|
|
278312
278531
|
var AWS_PRICE_CURRENCY = "USD";
|
|
278313
|
-
var AWS_PRICE_FETCHED_AT = "2026-
|
|
278532
|
+
var AWS_PRICE_FETCHED_AT = "2026-10-03";
|
|
278314
278533
|
var AWS_HOURLY_PRICES = {
|
|
278315
278534
|
"eks-cluster-standard": 0.1,
|
|
278316
278535
|
"elb-application": 0.02646,
|
|
@@ -278328,30 +278547,30 @@ var AWS_PER_GB_PRICES = {
|
|
|
278328
278547
|
// src/mcp/terraform/azurePrices.ts
|
|
278329
278548
|
var AZURE_PRICE_REGION = "westeurope";
|
|
278330
278549
|
var AZURE_PRICE_CURRENCY = "EUR";
|
|
278331
|
-
var AZURE_PRICE_FETCHED_AT = "2026-
|
|
278550
|
+
var AZURE_PRICE_FETCHED_AT = "2026-10-03";
|
|
278332
278551
|
var AZURE_HOURLY_PRICES = {
|
|
278333
|
-
"app-service-p0v3": 0.
|
|
278334
|
-
"app-service-p1v3": 0.
|
|
278335
|
-
"app-service-p2v3": 0.
|
|
278336
|
-
"app-service-p3v3": 0.
|
|
278337
|
-
"bastion-basic": 0.
|
|
278338
|
-
"bastion-premium": 0.
|
|
278339
|
-
"bastion-standard": 0.
|
|
278340
|
-
"firewall-basic": 0.
|
|
278341
|
-
"firewall-premium": 1.
|
|
278342
|
-
"firewall-standard": 1.
|
|
278343
|
-
"redis-c0": 0.
|
|
278344
|
-
"redis-c1": 0.
|
|
278345
|
-
"redis-c2": 0.
|
|
278346
|
-
"redis-c3": 0.
|
|
278347
|
-
"redis-p1": 0.
|
|
278348
|
-
"redis-p2": 0.
|
|
278349
|
-
"redis-p3": 0.
|
|
278350
|
-
"vpn-gateway-vpngw1": 0.
|
|
278351
|
-
"vpn-gateway-vpngw2": 0.
|
|
278352
|
-
"vpn-gateway-vpngw3": 1.
|
|
278353
|
-
"vpn-gateway-vpngw4": 1.
|
|
278354
|
-
"vpn-gateway-vpngw5": 3.
|
|
278552
|
+
"app-service-p0v3": 0.0783,
|
|
278553
|
+
"app-service-p1v3": 0.1566,
|
|
278554
|
+
"app-service-p2v3": 0.3133,
|
|
278555
|
+
"app-service-p3v3": 0.6265,
|
|
278556
|
+
"bastion-basic": 0.1672,
|
|
278557
|
+
"bastion-premium": 0.396,
|
|
278558
|
+
"bastion-standard": 0.2552,
|
|
278559
|
+
"firewall-basic": 0.3476,
|
|
278560
|
+
"firewall-premium": 1.54,
|
|
278561
|
+
"firewall-standard": 1.1,
|
|
278562
|
+
"redis-c0": 0.0242,
|
|
278563
|
+
"redis-c1": 0.0607,
|
|
278564
|
+
"redis-c2": 0.0986,
|
|
278565
|
+
"redis-c3": 0.198,
|
|
278566
|
+
"redis-p1": 0.2438,
|
|
278567
|
+
"redis-p2": 0.4884,
|
|
278568
|
+
"redis-p3": 0.9759,
|
|
278569
|
+
"vpn-gateway-vpngw1": 0.1672,
|
|
278570
|
+
"vpn-gateway-vpngw2": 0.4312,
|
|
278571
|
+
"vpn-gateway-vpngw3": 1.1,
|
|
278572
|
+
"vpn-gateway-vpngw4": 1.8479,
|
|
278573
|
+
"vpn-gateway-vpngw5": 3.2119
|
|
278355
278574
|
};
|
|
278356
278575
|
|
|
278357
278576
|
// src/mcp/terraform/idleFloor.ts
|
|
@@ -278629,7 +278848,7 @@ function readTfFiles2(cwd) {
|
|
|
278629
278848
|
const out = [];
|
|
278630
278849
|
for (const file2 of walkTfFiles(cwd)) {
|
|
278631
278850
|
try {
|
|
278632
|
-
out.push({ file: file2, hcl:
|
|
278851
|
+
out.push({ file: file2, hcl: readFileSync20(join30(cwd, file2), "utf8") });
|
|
278633
278852
|
} catch {
|
|
278634
278853
|
}
|
|
278635
278854
|
}
|
|
@@ -278734,7 +278953,7 @@ function buildSuppressionSummary(waivers) {
|
|
|
278734
278953
|
}
|
|
278735
278954
|
|
|
278736
278955
|
// node_modules/.pnpm/@infraweaver-io+attest@0.1.7_supports-color@7.2.0/node_modules/@infraweaver-io/attest/dist/signing.js
|
|
278737
|
-
import { createHash as
|
|
278956
|
+
import { createHash as createHash8, createPrivateKey, createPublicKey, sign as cryptoSign, verify as cryptoVerify } from "node:crypto";
|
|
278738
278957
|
var SIGNATURE_ALGORITHM = "Ed25519";
|
|
278739
278958
|
var DEFAULT_KEY_LABEL = "the signing key";
|
|
278740
278959
|
function loadSigningKey(raw2, options) {
|
|
@@ -278761,7 +278980,7 @@ function loadSigningKey(raw2, options) {
|
|
|
278761
278980
|
return {
|
|
278762
278981
|
privateKey,
|
|
278763
278982
|
publicKeyPem,
|
|
278764
|
-
fingerprint:
|
|
278983
|
+
fingerprint: createHash8("sha256").update(spkiDer).digest("hex")
|
|
278765
278984
|
};
|
|
278766
278985
|
}
|
|
278767
278986
|
function signBytes(bytes, key) {
|
|
@@ -278782,7 +279001,7 @@ function publicKeyFingerprint(publicKeyPem) {
|
|
|
278782
279001
|
type: "spki",
|
|
278783
279002
|
format: "der"
|
|
278784
279003
|
});
|
|
278785
|
-
return
|
|
279004
|
+
return createHash8("sha256").update(der).digest("hex");
|
|
278786
279005
|
}
|
|
278787
279006
|
function signatureMetadata(key, sigFile) {
|
|
278788
279007
|
return {
|
|
@@ -279012,7 +279231,7 @@ function buildEvidenceBundle(args2) {
|
|
|
279012
279231
|
// node_modules/.pnpm/@infraweaver-io+attest@0.1.7_supports-color@7.2.0/node_modules/@infraweaver-io/attest/dist/keyless.js
|
|
279013
279232
|
var import_bundle = __toESM(require_dist6(), 1);
|
|
279014
279233
|
var import_sign = __toESM(require_dist9(), 1);
|
|
279015
|
-
import { createHash as
|
|
279234
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
279016
279235
|
|
|
279017
279236
|
// node_modules/.pnpm/@infraweaver-io+attest@0.1.7_supports-color@7.2.0/node_modules/@infraweaver-io/attest/dist/keylessOidc.js
|
|
279018
279237
|
var SIGSTORE_OIDC_AUDIENCE = "sigstore";
|
|
@@ -279041,7 +279260,7 @@ function keylessSigningPossible(env2, envName) {
|
|
|
279041
279260
|
}
|
|
279042
279261
|
function buildInTotoStatement(args2) {
|
|
279043
279262
|
const data = typeof args2.artifactBytes === "string" ? Buffer.from(args2.artifactBytes, "utf8") : args2.artifactBytes;
|
|
279044
|
-
const sha2562 =
|
|
279263
|
+
const sha2562 = createHash9("sha256").update(data).digest("hex");
|
|
279045
279264
|
return {
|
|
279046
279265
|
_type: "https://in-toto.io/Statement/v1",
|
|
279047
279266
|
subject: [{ name: args2.subjectName, digest: { sha256: sha2562 } }],
|
|
@@ -279251,12 +279470,12 @@ import { mkdirSync as mkdirSync4 } from "node:fs";
|
|
|
279251
279470
|
import { dirname as dirname6 } from "node:path";
|
|
279252
279471
|
|
|
279253
279472
|
// src/mcp/terraform/oscal.ts
|
|
279254
|
-
import { createHash as
|
|
279473
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
279255
279474
|
var OSCAL_VERSION = "1.1.2";
|
|
279256
279475
|
var INDICATIVE_REMARK = "Indicative, crosswalk-derived assessment from a deterministic starter rule-pack \u2014 NOT a formal OSCAL assessment against an authored assessment plan. Statuses are code-verified only; absence of a finding is not proof of compliance.";
|
|
279257
279476
|
var NS = "https://infraweaver.io/ns/oscal";
|
|
279258
279477
|
function deterministicUuid(seed) {
|
|
279259
|
-
const hex4 =
|
|
279478
|
+
const hex4 = createHash10("sha256").update(seed).digest("hex").slice(0, 32).split("");
|
|
279260
279479
|
hex4[12] = "5";
|
|
279261
279480
|
hex4[16] = (Number.parseInt(hex4[16] ?? "0", 16) & 3 | 8).toString(16);
|
|
279262
279481
|
const u = hex4.join("");
|
|
@@ -279395,20 +279614,20 @@ function TerraformEmitOscalTool(ctx) {
|
|
|
279395
279614
|
import { writeFileSync as writeFileSync5 } from "node:fs";
|
|
279396
279615
|
|
|
279397
279616
|
// src/mcp/terraform/lineage.ts
|
|
279398
|
-
import { createHash as
|
|
279399
|
-
import { readFileSync as
|
|
279400
|
-
import { join as
|
|
279617
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
279618
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
279619
|
+
import { join as join31 } from "node:path";
|
|
279401
279620
|
function repoFileReader(cwd) {
|
|
279402
279621
|
return (rel) => {
|
|
279403
279622
|
try {
|
|
279404
|
-
return
|
|
279623
|
+
return readFileSync21(join31(cwd, rel), "utf-8");
|
|
279405
279624
|
} catch {
|
|
279406
279625
|
return null;
|
|
279407
279626
|
}
|
|
279408
279627
|
};
|
|
279409
279628
|
}
|
|
279410
279629
|
function lineageKeyOf(c, address) {
|
|
279411
|
-
return
|
|
279630
|
+
return createHash11("sha1").update(`${c.source}|${bareRuleOf(c.source, c.rule_id)}|${c.location.file}|${address ?? ""}`).digest("hex").slice(0, 16);
|
|
279412
279631
|
}
|
|
279413
279632
|
function lineageResolver(read3) {
|
|
279414
279633
|
const files = /* @__PURE__ */ new Map();
|
|
@@ -279954,11 +280173,11 @@ function TerraformEmitVexTool(ctx) {
|
|
|
279954
280173
|
// src/mcp/terraform/tools/equivalenceCheck.ts
|
|
279955
280174
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync4 } from "node:fs";
|
|
279956
280175
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
279957
|
-
import { join as
|
|
280176
|
+
import { join as join33 } from "node:path";
|
|
279958
280177
|
|
|
279959
280178
|
// src/mcp/terraform/initArtefacts.ts
|
|
279960
280179
|
import { rmSync as rmSync3 } from "node:fs";
|
|
279961
|
-
import { join as
|
|
280180
|
+
import { join as join32, posix as posix9 } from "node:path";
|
|
279962
280181
|
var INIT_ARTEFACTS = /* @__PURE__ */ new Set([".terraform", ".terraform.lock.hcl"]);
|
|
279963
280182
|
function initArtefacts(cwd) {
|
|
279964
280183
|
const r = run("git", ["status", "--porcelain=v1", "-z", "--untracked-files=normal"], cwd);
|
|
@@ -279981,7 +280200,7 @@ function removeNewInitArtefacts(cwd, before, by) {
|
|
|
279981
280200
|
const created = [...after?.untracked ?? []].filter((p) => !before.untracked.has(p));
|
|
279982
280201
|
const changed = [...after?.modifiedLocks ?? []].filter((p) => !before.modifiedLocks.has(p));
|
|
279983
280202
|
if (!top || created.length + changed.length === 0) return;
|
|
279984
|
-
for (const p of created) rmSync3(
|
|
280203
|
+
for (const p of created) rmSync3(join32(top, p), { recursive: true, force: true });
|
|
279985
280204
|
if (changed.length > 0) run("git", ["checkout", "--", ...changed], top);
|
|
279986
280205
|
resetTerraformInitCache();
|
|
279987
280206
|
log2.info(
|
|
@@ -280450,16 +280669,32 @@ function uncoveredInstanceKeys(p) {
|
|
|
280450
280669
|
if (expected === null) return null;
|
|
280451
280670
|
const kind = level[0].kind;
|
|
280452
280671
|
const written = (k) => kind === "count" ? k : `"${k}"`;
|
|
280672
|
+
const fromAt = level[0].at;
|
|
280673
|
+
const toAt = p.after.multiplicity[0]?.at;
|
|
280674
|
+
if (fromAt === void 0 || toAt === void 0) return null;
|
|
280453
280675
|
const declared2 = /* @__PURE__ */ new Set();
|
|
280454
280676
|
for (const blk of p.blocks) {
|
|
280677
|
+
if (stripIndices(normaliseAddress(blk.from)) !== p.before.address || stripIndices(normaliseAddress(blk.to)) !== p.after.address)
|
|
280678
|
+
return null;
|
|
280455
280679
|
const from = instanceKeysOf(blk.from);
|
|
280456
280680
|
const to = instanceKeysOf(blk.to);
|
|
280457
280681
|
if (from.length > 1 || to.length > 1) return null;
|
|
280458
280682
|
if (from.length === 0 && to.length === 0) return null;
|
|
280459
|
-
if (from.length
|
|
280683
|
+
if (from.length !== 1 || to.length !== 1 || from[0] !== to[0]) continue;
|
|
280684
|
+
const fromPlaced = keyAtLevel(blk.from, fromAt);
|
|
280685
|
+
const toPlaced = keyAtLevel(blk.to, toAt);
|
|
280686
|
+
if (fromPlaced === false || toPlaced === false) continue;
|
|
280687
|
+
if (fromPlaced === null || toPlaced === null) return null;
|
|
280688
|
+
declared2.add(from[0]);
|
|
280460
280689
|
}
|
|
280461
280690
|
return expected.filter((k) => !declared2.has(written(k)));
|
|
280462
280691
|
}
|
|
280692
|
+
function keyAtLevel(address, at) {
|
|
280693
|
+
const onResource = instanceKeysOf(stripModuleHops(normaliseAddress(address))).length > 0;
|
|
280694
|
+
if (at === "resource") return onResource;
|
|
280695
|
+
if (onResource) return false;
|
|
280696
|
+
return moduleHops(address).length === 1 ? true : null;
|
|
280697
|
+
}
|
|
280463
280698
|
function computeEquivalence(before, after, movedBlocks, ambiguous = [], planPairs, opts = {}) {
|
|
280464
280699
|
const reasons = [];
|
|
280465
280700
|
const corr = correspond(before, after, movedBlocks);
|
|
@@ -281779,12 +282014,12 @@ async function baselineValidateErrors(cwd, base, env2, session) {
|
|
|
281779
282014
|
}
|
|
281780
282015
|
const prefix2 = run("git", ["rev-parse", "--show-prefix"], cwd);
|
|
281781
282016
|
if (prefix2.status !== 0) return null;
|
|
281782
|
-
const tree = mkdtempSync2(
|
|
282017
|
+
const tree = mkdtempSync2(join33(tmpdir2(), "iw-baseline-"));
|
|
281783
282018
|
try {
|
|
281784
282019
|
if (run("git", ["worktree", "add", "--detach", "--quiet", tree, base], cwd).status !== 0) {
|
|
281785
282020
|
return null;
|
|
281786
282021
|
}
|
|
281787
|
-
const outcome2 = await scanValidate(
|
|
282022
|
+
const outcome2 = await scanValidate(join33(tree, prefix2.stdout.trim()), env2);
|
|
281788
282023
|
if (!outcome2.ran || outcome2.unvalidated) return null;
|
|
281789
282024
|
const errors = outcome2.concerns.map(validateErrorKey);
|
|
281790
282025
|
session.baselineValidateErrors = { base, errors };
|
|
@@ -281885,7 +282120,7 @@ function TerraformGenerateMovedTool(ctx) {
|
|
|
281885
282120
|
|
|
281886
282121
|
// src/mcp/terraform/cost.ts
|
|
281887
282122
|
import { mkdtempSync as mkdtempSync3, rmSync as rmSync5 } from "node:fs";
|
|
281888
|
-
import { join as
|
|
282123
|
+
import { join as join34 } from "node:path";
|
|
281889
282124
|
function parseInfracostBreakdown(stdout) {
|
|
281890
282125
|
const parsed2 = parseScannerJson(InfracostBreakdownOutput, stdout, "infracost");
|
|
281891
282126
|
const raw2 = parsed2.totalMonthlyCost;
|
|
@@ -281967,15 +282202,15 @@ async function infracostBaseline(cwd, key, tmpdir6) {
|
|
|
281967
282202
|
if (!baseRef) return null;
|
|
281968
282203
|
const prefixResult = run("git", ["rev-parse", "--show-prefix"], cwd);
|
|
281969
282204
|
const prefix2 = prefixResult.status === 0 ? prefixResult.stdout.trim() : "";
|
|
281970
|
-
const baseDir = mkdtempSync3(
|
|
281971
|
-
const worktree =
|
|
282205
|
+
const baseDir = mkdtempSync3(join34(tmpdir6, "infracost-base-"));
|
|
282206
|
+
const worktree = join34(baseDir, "wt");
|
|
281972
282207
|
const add = run("git", ["worktree", "add", "--detach", worktree, baseRef], cwd);
|
|
281973
282208
|
if (add.status !== 0) {
|
|
281974
282209
|
rmSync5(baseDir, { recursive: true, force: true });
|
|
281975
282210
|
return null;
|
|
281976
282211
|
}
|
|
281977
282212
|
try {
|
|
281978
|
-
const scanCwd = prefix2 ?
|
|
282213
|
+
const scanCwd = prefix2 ? join34(worktree, prefix2) : worktree;
|
|
281979
282214
|
const r = await runInfracostBreakdown(scanCwd, key);
|
|
281980
282215
|
if (r.missing || r.status !== 0) return null;
|
|
281981
282216
|
return parseInfracostBreakdown(r.stdout);
|
|
@@ -282046,7 +282281,7 @@ function InfracostDiffTool(ctx) {
|
|
|
282046
282281
|
|
|
282047
282282
|
// src/mcp/terraform/tools/ingestExternalFindings.ts
|
|
282048
282283
|
import { statSync as statSync7 } from "node:fs";
|
|
282049
|
-
import { join as
|
|
282284
|
+
import { join as join35 } from "node:path";
|
|
282050
282285
|
|
|
282051
282286
|
// src/mcp/terraform/prowlerOcsf.ts
|
|
282052
282287
|
var DETECTION_FINDING_CREATE = 200401;
|
|
@@ -282272,7 +282507,7 @@ var MAX_FEED_BYTES = 100 * 1024 * 1024;
|
|
|
282272
282507
|
function readTfFiles3(cwd) {
|
|
282273
282508
|
const out = [];
|
|
282274
282509
|
for (const file2 of walkTfFiles(cwd)) {
|
|
282275
|
-
const hcl2 = readTextCapped(
|
|
282510
|
+
const hcl2 = readTextCapped(join35(cwd, file2));
|
|
282276
282511
|
if (hcl2 !== null) out.push({ file: file2, hcl: hcl2 });
|
|
282277
282512
|
}
|
|
282278
282513
|
return out;
|
|
@@ -282386,7 +282621,8 @@ function IngestExternalFindingsTool(ctx) {
|
|
|
282386
282621
|
// an external feed is a narrow concern source — join any prior scan
|
|
282387
282622
|
// baseline so a later ✗→✓ verify doesn't read the workspace as regressions.
|
|
282388
282623
|
baselineMode: "merge",
|
|
282389
|
-
seedCaps: seedCapsFrom(input2)
|
|
282624
|
+
seedCaps: seedCapsFrom(input2),
|
|
282625
|
+
openRemediationPrs: await listOpenRemediationPrs(ctx)
|
|
282390
282626
|
});
|
|
282391
282627
|
const cappedBlock = cappedSummary(capped);
|
|
282392
282628
|
log2.info(
|
|
@@ -282429,8 +282665,8 @@ function IngestExternalFindingsTool(ctx) {
|
|
|
282429
282665
|
}
|
|
282430
282666
|
|
|
282431
282667
|
// src/mcp/terraform/tools/moduleDocs.ts
|
|
282432
|
-
import { readFileSync as
|
|
282433
|
-
import { join as
|
|
282668
|
+
import { readFileSync as readFileSync22, writeFileSync as writeFileSync6 } from "node:fs";
|
|
282669
|
+
import { join as join36 } from "node:path";
|
|
282434
282670
|
|
|
282435
282671
|
// src/mcp/terraform/moduleDocs.ts
|
|
282436
282672
|
var VERDICT_CLAIM = {
|
|
@@ -282544,7 +282780,7 @@ function TerraformModuleDocsTool(ctx) {
|
|
|
282544
282780
|
);
|
|
282545
282781
|
}
|
|
282546
282782
|
const absDir = resolveWithinCwd(cwd, module_dir);
|
|
282547
|
-
const target =
|
|
282783
|
+
const target = join36(absDir, "README.md");
|
|
282548
282784
|
let gitHead = null;
|
|
282549
282785
|
try {
|
|
282550
282786
|
gitHead = $("git", ["rev-parse", "HEAD"], { cwd, log: false });
|
|
@@ -282552,7 +282788,7 @@ function TerraformModuleDocsTool(ctx) {
|
|
|
282552
282788
|
}
|
|
282553
282789
|
let existing = null;
|
|
282554
282790
|
try {
|
|
282555
|
-
existing =
|
|
282791
|
+
existing = readFileSync22(target, "utf8");
|
|
282556
282792
|
} catch {
|
|
282557
282793
|
}
|
|
282558
282794
|
const priorHead = readFooterGitHead(existing);
|
|
@@ -282856,15 +283092,13 @@ function NormalizationCandidatesTool(ctx) {
|
|
|
282856
283092
|
parameters: NormalizationCandidatesParams,
|
|
282857
283093
|
execute: execute(async () => {
|
|
282858
283094
|
const cwd = ctx.payload.cwd ?? process.cwd();
|
|
282859
|
-
const
|
|
282860
|
-
|
|
282861
|
-
);
|
|
283095
|
+
const library = libraryScope(cwd);
|
|
283096
|
+
const files = findNormalizationCandidates(cwd).filter((f) => ctx.payload.refactorExamples || !isExamplePath(f.file)).map((f) => ({ ...reportOnly(library(f.file)), ...f }));
|
|
282862
283097
|
const total = files.reduce((n, f) => n + f.count, 0);
|
|
282863
283098
|
log2.info(
|
|
282864
283099
|
`\xBB terraform_normalization_candidates: ${total} site(s) across ${files.length} file(s)`
|
|
282865
283100
|
);
|
|
282866
283101
|
return toolOk({
|
|
282867
|
-
...reportOnly(libraryRepoReason(cwd)),
|
|
282868
283102
|
file_count: files.length,
|
|
282869
283103
|
total,
|
|
282870
283104
|
files,
|
|
@@ -282876,7 +283110,7 @@ function NormalizationCandidatesTool(ctx) {
|
|
|
282876
283110
|
|
|
282877
283111
|
// src/mcp/terraform/tools/plan.ts
|
|
282878
283112
|
import { rmSync as rmSync6 } from "node:fs";
|
|
282879
|
-
import { join as
|
|
283113
|
+
import { join as join37 } from "node:path";
|
|
282880
283114
|
var PLAN_JSON_ARGS = ["plan", "-input=false", "-no-color", "-lock=false", "-json"];
|
|
282881
283115
|
var planFileSeq = 0;
|
|
282882
283116
|
async function capturePlanPairs(absDir, planFile, creds) {
|
|
@@ -282899,7 +283133,7 @@ async function planOneRoot(absDir, creds, tmpdir6) {
|
|
|
282899
283133
|
skipReason: `terraform init failed: ${init.stderr.trim().slice(0, 200) || "unknown error"}`
|
|
282900
283134
|
};
|
|
282901
283135
|
}
|
|
282902
|
-
const planFile = tmpdir6 ?
|
|
283136
|
+
const planFile = tmpdir6 ? join37(tmpdir6, `plan-${process.pid}-${planFileSeq++}.tfplan`) : void 0;
|
|
282903
283137
|
const plan = await runTfAsync(
|
|
282904
283138
|
planFile ? [...PLAN_JSON_ARGS, `-out=${planFile}`] : PLAN_JSON_ARGS,
|
|
282905
283139
|
absDir,
|
|
@@ -283269,8 +283503,8 @@ function TerraformProviderUpgradeTool(ctx) {
|
|
|
283269
283503
|
}
|
|
283270
283504
|
|
|
283271
283505
|
// src/mcp/terraform/tfquery.ts
|
|
283272
|
-
import { readFileSync as
|
|
283273
|
-
import { join as
|
|
283506
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
283507
|
+
import { join as join38 } from "node:path";
|
|
283274
283508
|
var TFQUERY_SUFFIX = ".tfquery.hcl";
|
|
283275
283509
|
function parseQueryFile(hcl2) {
|
|
283276
283510
|
return parseBlocks(hcl2, ["list"]).map((block) => {
|
|
@@ -283296,7 +283530,7 @@ function collectQueryInventory(cwd) {
|
|
|
283296
283530
|
for (const rel of walkFilesBySuffix(cwd, TFQUERY_SUFFIX)) {
|
|
283297
283531
|
let text;
|
|
283298
283532
|
try {
|
|
283299
|
-
text =
|
|
283533
|
+
text = readFileSync23(join38(cwd, rel), "utf8");
|
|
283300
283534
|
} catch {
|
|
283301
283535
|
continue;
|
|
283302
283536
|
}
|
|
@@ -283331,7 +283565,7 @@ function TerraformQueryInventoryTool(ctx) {
|
|
|
283331
283565
|
}
|
|
283332
283566
|
|
|
283333
283567
|
// src/mcp/terraform/tools/readFindings.ts
|
|
283334
|
-
import { readFileSync as
|
|
283568
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
283335
283569
|
var ReadFindingsParams = type({
|
|
283336
283570
|
"path?": type.string.describe(
|
|
283337
283571
|
"path to the Assessor's findings.json. Defaults to $INFRAWEAVER_FINDINGS_PATH, then ./findings.json in the workspace."
|
|
@@ -283356,7 +283590,7 @@ function ReadFindingsTool(ctx) {
|
|
|
283356
283590
|
const findingsPath = path15 || !envFindingsPath ? resolveWithinCwd(cwd, path15 ?? "findings.json") : envFindingsPath;
|
|
283357
283591
|
let raw2;
|
|
283358
283592
|
try {
|
|
283359
|
-
raw2 =
|
|
283593
|
+
raw2 = readFileSync24(findingsPath, "utf8");
|
|
283360
283594
|
} catch {
|
|
283361
283595
|
return skipResult(
|
|
283362
283596
|
"findings_not_found",
|
|
@@ -283399,7 +283633,8 @@ function ReadFindingsTool(ctx) {
|
|
|
283399
283633
|
minRank,
|
|
283400
283634
|
grouping,
|
|
283401
283635
|
autonomyThreshold,
|
|
283402
|
-
seedCaps: seedCapsFrom(input2)
|
|
283636
|
+
seedCaps: seedCapsFrom(input2),
|
|
283637
|
+
openRemediationPrs: await listOpenRemediationPrs(ctx)
|
|
283403
283638
|
});
|
|
283404
283639
|
const cappedBlock = cappedSummary(capped);
|
|
283405
283640
|
log2.info(
|
|
@@ -283578,23 +283813,54 @@ function computeScanDelta(input2) {
|
|
|
283578
283813
|
};
|
|
283579
283814
|
}
|
|
283580
283815
|
function markPossibleRenames(introduced, resolved, headAddresses) {
|
|
283581
|
-
const
|
|
283582
|
-
|
|
283583
|
-
|
|
283584
|
-
|
|
283816
|
+
const byResource = (findings) => {
|
|
283817
|
+
const out = /* @__PURE__ */ new Map();
|
|
283818
|
+
for (const f of [...findings].sort((a, b) => byLocation(a.concern, b.concern))) {
|
|
283819
|
+
if (f.address === null) continue;
|
|
283820
|
+
const dir = dirOf3(f.concern.location.file);
|
|
283821
|
+
const key = `${dir}|${f.address}`;
|
|
283822
|
+
const entry4 = out.get(key);
|
|
283823
|
+
if (entry4) entry4.findings.push(f);
|
|
283824
|
+
else out.set(key, { dir, address: f.address, findings: [f] });
|
|
283825
|
+
}
|
|
283826
|
+
return [...out.values()];
|
|
283827
|
+
};
|
|
283828
|
+
const vanished = byResource(resolved).filter((r) => !headAddresses(r.dir).has(r.address));
|
|
283829
|
+
const appeared = byResource(introduced);
|
|
283830
|
+
const shared = (from, to) => {
|
|
283831
|
+
const left = /* @__PURE__ */ new Map();
|
|
283832
|
+
for (const f of from.findings)
|
|
283833
|
+
left.set(ruleKey(f.concern), (left.get(ruleKey(f.concern)) ?? 0) + 1);
|
|
283834
|
+
return to.findings.filter((f) => {
|
|
283835
|
+
const n = left.get(ruleKey(f.concern)) ?? 0;
|
|
283836
|
+
if (n === 0) return false;
|
|
283837
|
+
left.set(ruleKey(f.concern), n - 1);
|
|
283838
|
+
return true;
|
|
283839
|
+
});
|
|
283840
|
+
};
|
|
283841
|
+
const order2 = (a, b) => a.dir.localeCompare(b.dir) || a.address.localeCompare(b.address);
|
|
283842
|
+
const candidates = vanished.flatMap(
|
|
283843
|
+
(from) => appeared.filter(
|
|
283844
|
+
(to) => (
|
|
283845
|
+
// a `moved` block cannot change a resource's type
|
|
283846
|
+
typeOf(from.address) === typeOf(to.address) && // renamed in place, or moved elsewhere under its own name
|
|
283847
|
+
from.dir === to.dir !== (from.address === to.address)
|
|
283848
|
+
)
|
|
283849
|
+
).map((to) => ({ from, to, findings: shared(from, to) })).filter((p) => p.findings.length > 0)
|
|
283850
|
+
);
|
|
283851
|
+
candidates.sort(
|
|
283852
|
+
(a, b) => b.findings.length - a.findings.length || order2(a.from, b.from) || order2(a.to, b.to)
|
|
283853
|
+
);
|
|
283585
283854
|
const used = /* @__PURE__ */ new Set();
|
|
283586
|
-
for (const
|
|
283587
|
-
if (
|
|
283588
|
-
|
|
283589
|
-
|
|
283590
|
-
|
|
283591
|
-
|
|
283592
|
-
|
|
283593
|
-
|
|
283594
|
-
|
|
283595
|
-
used.add(match5);
|
|
283596
|
-
finding.possiblyPreexisting = true;
|
|
283597
|
-
finding.renamedFrom = { address: match5.address, file: match5.concern.location.file };
|
|
283855
|
+
for (const { from, to, findings } of candidates) {
|
|
283856
|
+
if (used.has(from) || used.has(to)) continue;
|
|
283857
|
+
used.add(from);
|
|
283858
|
+
used.add(to);
|
|
283859
|
+
const file2 = from.findings[0]?.concern.location.file;
|
|
283860
|
+
for (const finding of findings) {
|
|
283861
|
+
finding.possiblyPreexisting = true;
|
|
283862
|
+
finding.renamedFrom = { address: from.address, file: file2 };
|
|
283863
|
+
}
|
|
283598
283864
|
}
|
|
283599
283865
|
}
|
|
283600
283866
|
function typeOf(address) {
|
|
@@ -283637,7 +283903,8 @@ function deltaVerdict(delta, requiredControls) {
|
|
|
283637
283903
|
return {
|
|
283638
283904
|
pass: gate.pass && required3.length === 0,
|
|
283639
283905
|
gating: gate.gating.length,
|
|
283640
|
-
required: required3.length
|
|
283906
|
+
required: required3.length,
|
|
283907
|
+
blocking: (/* @__PURE__ */ new Set([...gate.gating, ...required3])).size
|
|
283641
283908
|
};
|
|
283642
283909
|
}
|
|
283643
283910
|
function failsGate(finding, requiredControls) {
|
|
@@ -283755,8 +284022,8 @@ function describe3(f) {
|
|
|
283755
284022
|
}
|
|
283756
284023
|
|
|
283757
284024
|
// src/mcp/terraform/tools/scan.ts
|
|
283758
|
-
import { readFileSync as
|
|
283759
|
-
import { join as
|
|
284025
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
284026
|
+
import { join as join39 } from "node:path";
|
|
283760
284027
|
|
|
283761
284028
|
// src/mcp/terraform/noiseProfile.ts
|
|
283762
284029
|
var MIN_DISMISSAL_REPOS = 3;
|
|
@@ -283930,7 +284197,9 @@ async function runScan(ctx, {
|
|
|
283930
284197
|
grouping,
|
|
283931
284198
|
autonomyThreshold,
|
|
283932
284199
|
inScope,
|
|
283933
|
-
priority
|
|
284200
|
+
priority,
|
|
284201
|
+
openRemediationPrs: await listOpenRemediationPrs(ctx),
|
|
284202
|
+
linesMatchTree: true
|
|
283934
284203
|
}
|
|
283935
284204
|
);
|
|
283936
284205
|
const { active, suppressed, groups: groups2, batchPlan, bySeverity: by_severity } = result;
|
|
@@ -283942,7 +284211,7 @@ async function runScan(ctx, {
|
|
|
283942
284211
|
outcomes.flatMap((o) => o.concerns),
|
|
283943
284212
|
(rel) => {
|
|
283944
284213
|
try {
|
|
283945
|
-
return
|
|
284214
|
+
return readFileSync25(join39(cwd, rel), "utf-8");
|
|
283946
284215
|
} catch {
|
|
283947
284216
|
return null;
|
|
283948
284217
|
}
|
|
@@ -284459,9 +284728,9 @@ function TerraformStandardsReportTool(ctx) {
|
|
|
284459
284728
|
}
|
|
284460
284729
|
|
|
284461
284730
|
// src/mcp/terraform/tools/tag.ts
|
|
284462
|
-
import { createHash as
|
|
284463
|
-
import { existsSync as
|
|
284464
|
-
import { isAbsolute as isAbsolute3, join as
|
|
284731
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
284732
|
+
import { existsSync as existsSync8, readdirSync as readdirSync8, readFileSync as readFileSync26, realpathSync as realpathSync2, rmSync as rmSync7 } from "node:fs";
|
|
284733
|
+
import { isAbsolute as isAbsolute3, join as join40, relative as relative5, resolve as resolve6, sep as sep2 } from "node:path";
|
|
284465
284734
|
var TerraformTagParams = type({
|
|
284466
284735
|
tags: type({ "[string]": "string" }).describe(
|
|
284467
284736
|
'the tag set to apply, key \u2192 value (e.g. {"Owner":"platform","CostCentre":"1234"}); merged into every taggable resource\'s `tags`'
|
|
@@ -284482,24 +284751,24 @@ var TerraformTagParams = type({
|
|
|
284482
284751
|
var realRunners3 = { run };
|
|
284483
284752
|
function sha(path15) {
|
|
284484
284753
|
try {
|
|
284485
|
-
return
|
|
284754
|
+
return createHash12("sha256").update(readFileSync26(path15)).digest("hex");
|
|
284486
284755
|
} catch {
|
|
284487
284756
|
return null;
|
|
284488
284757
|
}
|
|
284489
284758
|
}
|
|
284490
284759
|
function snapshot2(cwd, files) {
|
|
284491
|
-
return new Map(files.map((f) => [f, sha(
|
|
284760
|
+
return new Map(files.map((f) => [f, sha(join40(cwd, f))]));
|
|
284492
284761
|
}
|
|
284493
284762
|
function toPosix(p) {
|
|
284494
284763
|
return p.split(sep2).join("/");
|
|
284495
284764
|
}
|
|
284496
284765
|
function terratagFiles(dir) {
|
|
284497
284766
|
const dirs = [dir];
|
|
284498
|
-
const manifest =
|
|
284499
|
-
if (
|
|
284767
|
+
const manifest = join40(dir, ".terraform", "modules", "modules.json");
|
|
284768
|
+
if (existsSync8(manifest)) {
|
|
284500
284769
|
let modules;
|
|
284501
284770
|
try {
|
|
284502
|
-
modules = JSON.parse(
|
|
284771
|
+
modules = JSON.parse(readFileSync26(manifest, "utf8")).Modules;
|
|
284503
284772
|
} catch {
|
|
284504
284773
|
throw new Error(`terraform_tag refused: cannot read ${manifest} (re-run terraform init)`);
|
|
284505
284774
|
}
|
|
@@ -284507,7 +284776,7 @@ function terratagFiles(dir) {
|
|
|
284507
284776
|
const moduleDir = m?.Dir;
|
|
284508
284777
|
if (typeof moduleDir !== "string") continue;
|
|
284509
284778
|
try {
|
|
284510
|
-
dirs.push(realpathSync2(
|
|
284779
|
+
dirs.push(realpathSync2(join40(dir, moduleDir)));
|
|
284511
284780
|
} catch {
|
|
284512
284781
|
}
|
|
284513
284782
|
}
|
|
@@ -284515,7 +284784,7 @@ function terratagFiles(dir) {
|
|
|
284515
284784
|
const files = /* @__PURE__ */ new Set();
|
|
284516
284785
|
for (const d of dirs) {
|
|
284517
284786
|
for (const name of readdirSync8(d)) {
|
|
284518
|
-
if (name.endsWith(".tf")) files.add(realpathSync2(
|
|
284787
|
+
if (name.endsWith(".tf")) files.add(realpathSync2(join40(d, name)));
|
|
284519
284788
|
}
|
|
284520
284789
|
}
|
|
284521
284790
|
return [...files];
|
|
@@ -284539,12 +284808,12 @@ function runTag(ctx, params, runners = realRunners3) {
|
|
|
284539
284808
|
return rel !== ".." && !rel.startsWith(`..${sep2}`) && !isAbsolute3(rel);
|
|
284540
284809
|
};
|
|
284541
284810
|
const requested = resolve6(cwd, params.dir ?? ".");
|
|
284542
|
-
const target =
|
|
284811
|
+
const target = existsSync8(requested) ? realpathSync2(requested) : requested;
|
|
284543
284812
|
if (!inside(target)) {
|
|
284544
284813
|
throw new Error(`terraform_tag: \`dir\` must stay inside the workspace (got ${params.dir})`);
|
|
284545
284814
|
}
|
|
284546
284815
|
const relDir = toPosix(relative5(cwd, target)) || ".";
|
|
284547
|
-
if (!
|
|
284816
|
+
if (!existsSync8(target)) {
|
|
284548
284817
|
return toolSkip("no_terraform_files", `no .tf files under ${relDir}`);
|
|
284549
284818
|
}
|
|
284550
284819
|
const absFiles = terratagFiles(target);
|
|
@@ -284582,7 +284851,7 @@ function runTag(ctx, params, runners = realRunners3) {
|
|
|
284582
284851
|
if (params.filter) args2.push(`-filter=${params.filter}`);
|
|
284583
284852
|
if (params.skip) args2.push(`-skip=${params.skip}`);
|
|
284584
284853
|
const before = snapshot2(cwd, files);
|
|
284585
|
-
const priorBackups = new Set(files.filter((f) =>
|
|
284854
|
+
const priorBackups = new Set(files.filter((f) => existsSync8(join40(cwd, `${f}.bak`))));
|
|
284586
284855
|
const r = runners.run("terratag", args2, cwd);
|
|
284587
284856
|
if (r.missing) {
|
|
284588
284857
|
return toolSkip(
|
|
@@ -284596,7 +284865,7 @@ function runTag(ctx, params, runners = realRunners3) {
|
|
|
284596
284865
|
${tail}` : ""}`);
|
|
284597
284866
|
}
|
|
284598
284867
|
for (const f of files) {
|
|
284599
|
-
if (!priorBackups.has(f)) rmSync7(
|
|
284868
|
+
if (!priorBackups.has(f)) rmSync7(join40(cwd, `${f}.bak`), { force: true });
|
|
284600
284869
|
}
|
|
284601
284870
|
const failed = [
|
|
284602
284871
|
...`${r.stderr}
|
|
@@ -284767,7 +285036,25 @@ async function runVerifyRemediation(ctx, { concern_ids, download_external_module
|
|
|
284767
285036
|
if (key !== void 0) keyed.push({ id, key });
|
|
284768
285037
|
else unkeyed.push(id);
|
|
284769
285038
|
}
|
|
284770
|
-
const
|
|
285039
|
+
const byKey = partitionByKey(keyed, currentKeys);
|
|
285040
|
+
const read3 = fileReader(cwd);
|
|
285041
|
+
const remainingKeyed = keyed.filter((k) => byKey.remaining.includes(k.id));
|
|
285042
|
+
const atSite = new Set(
|
|
285043
|
+
resolvedAtSite({
|
|
285044
|
+
requested: remainingKeyed.map((k) => ({
|
|
285045
|
+
...k,
|
|
285046
|
+
site: session.siteById?.get(k.id) ?? null,
|
|
285047
|
+
file: reported.get(k.id)?.location.file
|
|
285048
|
+
})),
|
|
285049
|
+
current: currentConcerns.map((c) => ({ key: concernKeyOf(c), site: siteOf(c, read3) })),
|
|
285050
|
+
firstSites: session.firstSitesByKey ?? /* @__PURE__ */ new Map(),
|
|
285051
|
+
declared: (file2) => new Set(declaredAddresses(read3(file2) ?? ""))
|
|
285052
|
+
})
|
|
285053
|
+
);
|
|
285054
|
+
const keyedVerdict = {
|
|
285055
|
+
resolved: [...byKey.resolved, ...byKey.remaining.filter((id) => atSite.has(id))],
|
|
285056
|
+
remaining: byKey.remaining.filter((id) => !atSite.has(id))
|
|
285057
|
+
};
|
|
284771
285058
|
const fallbackVerdict = computeRemediationVerdict(unkeyed, new Set(currentIds));
|
|
284772
285059
|
const resolved = [...keyedVerdict.resolved, ...fallbackVerdict.resolved];
|
|
284773
285060
|
const remaining = [...keyedVerdict.remaining, ...fallbackVerdict.remaining];
|
|
@@ -284987,10 +285274,10 @@ var DispatchRecorder = class {
|
|
|
284987
285274
|
* orchestrator counts as subagent — including a session the labeler could not
|
|
284988
285275
|
* name, because an unnamed session is by definition not the orchestrator's.
|
|
284989
285276
|
*/
|
|
284990
|
-
recordTokens(label,
|
|
284991
|
-
if (!Number.isFinite(
|
|
284992
|
-
if (label === ORCHESTRATOR_LABEL) this.#orchestratorTokens +=
|
|
284993
|
-
else this.#subagentTokens +=
|
|
285277
|
+
recordTokens(label, billableTokens) {
|
|
285278
|
+
if (!Number.isFinite(billableTokens) || billableTokens <= 0) return;
|
|
285279
|
+
if (label === ORCHESTRATOR_LABEL) this.#orchestratorTokens += billableTokens;
|
|
285280
|
+
else this.#subagentTokens += billableTokens;
|
|
284994
285281
|
}
|
|
284995
285282
|
tally() {
|
|
284996
285283
|
return {
|
|
@@ -285117,7 +285404,7 @@ function buildLocalContext(options) {
|
|
|
285117
285404
|
registryHost: options.registryHost
|
|
285118
285405
|
},
|
|
285119
285406
|
toolState: initToolState({ progressComment: void 0 }),
|
|
285120
|
-
tmpdir: mkdtempSync4(
|
|
285407
|
+
tmpdir: mkdtempSync4(join41(tmpdir3(), `${PRODUCT_SLUG}-mcp-`))
|
|
285121
285408
|
};
|
|
285122
285409
|
}
|
|
285123
285410
|
function buildLocalTools(ctx) {
|
|
@@ -285160,7 +285447,7 @@ function buildLocalTools(ctx) {
|
|
|
285160
285447
|
];
|
|
285161
285448
|
}
|
|
285162
285449
|
function cliVersion() {
|
|
285163
|
-
const raw2 = "0.3.
|
|
285450
|
+
const raw2 = "0.3.13";
|
|
285164
285451
|
if (raw2 !== void 0 && /^\d+\.\d+\.\d+$/.test(raw2)) {
|
|
285165
285452
|
return raw2;
|
|
285166
285453
|
}
|
|
@@ -285299,7 +285586,7 @@ async function runAssessCli(params) {
|
|
|
285299
285586
|
}
|
|
285300
285587
|
let cwd = process.cwd();
|
|
285301
285588
|
if (rawCwd) cwd = isAbsolute4(rawCwd) ? rawCwd : resolve7(process.cwd(), rawCwd);
|
|
285302
|
-
if (!
|
|
285589
|
+
if (!existsSync9(cwd) || !statSync8(cwd).isDirectory()) {
|
|
285303
285590
|
console.error(`assess: not a directory: ${cwd}`);
|
|
285304
285591
|
process.exit(ASSESS_EXIT.USAGE);
|
|
285305
285592
|
}
|
|
@@ -285391,15 +285678,15 @@ ${postureLine(scorecard.posture, scorecard.total)} \u2014 failing the gate (--fa
|
|
|
285391
285678
|
}
|
|
285392
285679
|
|
|
285393
285680
|
// src/commands/explain.ts
|
|
285394
|
-
import { readFileSync as
|
|
285395
|
-
import { join as
|
|
285681
|
+
import { readFileSync as readFileSync27 } from "node:fs";
|
|
285682
|
+
import { join as join42, relative as relative6, resolve as resolve8 } from "node:path";
|
|
285396
285683
|
var import_arg2 = __toESM(require_arg(), 1);
|
|
285397
285684
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
285398
285685
|
function readConfig(cwd) {
|
|
285399
285686
|
for (const name of INFRAWEAVER_CONFIG_FILENAMES) {
|
|
285400
285687
|
let raw2;
|
|
285401
285688
|
try {
|
|
285402
|
-
raw2 =
|
|
285689
|
+
raw2 = readFileSync27(join42(cwd, name), "utf-8");
|
|
285403
285690
|
} catch {
|
|
285404
285691
|
continue;
|
|
285405
285692
|
}
|
|
@@ -285573,8 +285860,8 @@ var import_arg3 = __toESM(require_arg(), 1);
|
|
|
285573
285860
|
|
|
285574
285861
|
// node_modules/.pnpm/@infraweaver-io+ci@0.1.8/node_modules/@infraweaver-io/ci/dist/gitAuth.js
|
|
285575
285862
|
import { execSync } from "node:child_process";
|
|
285576
|
-
import { createHash as
|
|
285577
|
-
import { readFileSync as
|
|
285863
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
285864
|
+
import { readFileSync as readFileSync28, realpathSync as realpathSync3, unlinkSync } from "node:fs";
|
|
285578
285865
|
|
|
285579
285866
|
// node_modules/.pnpm/@infraweaver-io+sandbox@0.1.8/node_modules/@infraweaver-io/sandbox/dist/subprocess.js
|
|
285580
285867
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
@@ -285900,7 +286187,7 @@ ${errMsg}` : errMsg;
|
|
|
285900
286187
|
// node_modules/.pnpm/@infraweaver-io+ci@0.1.8/node_modules/@infraweaver-io/ci/dist/gitAuth.js
|
|
285901
286188
|
var gitBinary;
|
|
285902
286189
|
function hashFile(path15) {
|
|
285903
|
-
return
|
|
286190
|
+
return createHash13("sha256").update(readFileSync28(path15)).digest("hex");
|
|
285904
286191
|
}
|
|
285905
286192
|
function resolveGit() {
|
|
285906
286193
|
const lookup3 = process.platform === "win32" ? "where git" : "which git";
|
|
@@ -286022,7 +286309,7 @@ async function $gitFetchWithDeepen(args2, options, label) {
|
|
|
286022
286309
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
286023
286310
|
import { writeFileSync as writeFileSync7 } from "node:fs";
|
|
286024
286311
|
import { createServer } from "node:http";
|
|
286025
|
-
import { join as
|
|
286312
|
+
import { join as join43 } from "node:path";
|
|
286026
286313
|
var REVOKED_TRAP_MS = 6e4;
|
|
286027
286314
|
function revokeGitHubToken(token, userAgent2) {
|
|
286028
286315
|
const apiBase = process.env.GITHUB_API_URL || "https://api.github.com";
|
|
@@ -286094,7 +286381,7 @@ async function startGitAuthServer(tmpdir6, options) {
|
|
|
286094
286381
|
function writeAskpassScript(code2) {
|
|
286095
286382
|
const scriptId = randomUUID3();
|
|
286096
286383
|
const scriptName = `askpass-${scriptId}.js`;
|
|
286097
|
-
const scriptPath =
|
|
286384
|
+
const scriptPath = join43(tmpdir6, scriptName);
|
|
286098
286385
|
const content = [
|
|
286099
286386
|
`#!/usr/bin/env node`,
|
|
286100
286387
|
`var a=process.argv[2]||"";`,
|
|
@@ -286273,9 +286560,9 @@ function TerraformChangeSummaryTool(ctx) {
|
|
|
286273
286560
|
}
|
|
286274
286561
|
|
|
286275
286562
|
// src/mcp/checkout.ts
|
|
286276
|
-
import { createHash as
|
|
286563
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
286277
286564
|
import { statSync as statSync9, unlinkSync as unlinkSync3, writeFileSync as writeFileSync13 } from "node:fs";
|
|
286278
|
-
import { join as
|
|
286565
|
+
import { join as join53 } from "node:path";
|
|
286279
286566
|
|
|
286280
286567
|
// node_modules/.pnpm/@infraweaver-io+ci@0.1.8/node_modules/@infraweaver-io/ci/dist/diffCoverage.js
|
|
286281
286568
|
import { isAbsolute as isAbsolute5, normalize as normalize4, resolve as resolve9 } from "node:path";
|
|
@@ -286571,7 +286858,7 @@ function readNumber(params) {
|
|
|
286571
286858
|
// src/mcp/git.ts
|
|
286572
286859
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
286573
286860
|
import { writeFileSync as writeFileSync9 } from "node:fs";
|
|
286574
|
-
import { join as
|
|
286861
|
+
import { join as join46 } from "node:path";
|
|
286575
286862
|
|
|
286576
286863
|
// src/modes/address-reviews.ts
|
|
286577
286864
|
function addressReviewsMode(t) {
|
|
@@ -287467,7 +287754,7 @@ This mode standardises STRUCTURE while preserving BEHAVIOUR \u2014 the equivalen
|
|
|
287467
287754
|
- \`${t("terraform_normalization_candidates")}\` \u2192 in-place idiomatic cleanups that change SYNTAX, not behaviour (redundant whole-string \`"\${expr}"\` interpolation; legacy HCL0.11 map-argument block syntax like \`vars {\` on a \`template_file\`). These relocate NOTHING \u2014 zero \`moved {}\` blocks \u2014 and are proven by the same equivalence check.
|
|
287468
287755
|
- \`${t("terraform_consolidation_candidates")}\` \u2192 the SAME resource shape declared in several root directories (\`env/dev\` + \`env/staging\` + \`env/prod\`), with the single parameterised module they could all call already derived: which attributes are identical (module content) and which differ (per-environment inputs). A member root of a group will ALSO show up as a zero-candidate cluster in \`${t("module_extraction_candidates")}\` \u2014 prefer the consolidation, which does that work once for every environment instead of once per environment. Its \`near_groups\` are the opposite case: roots recognisably the same stack that DIFFER (one carries a resource the other does not), where folding them together is a design decision this mode has no basis for. Do NOT extract a near-group root's shared resources into a module on its own either \u2014 a module one twin calls and the other does not widens exactly the drift the near-group reports. Leave those roots alone and name the near-group and its \`differences\` in your report.
|
|
287469
287756
|
|
|
287470
|
-
**A
|
|
287757
|
+
**A candidate marked \`report_only\` is an observation, not work.** It sits in the code of a module other configurations call (\`report_only_reason\` says why), and restructuring that is churn for every caller: name those candidates in your \`${t("report_progress")}\` summary and open no PR for them. \`examples/\` roots are left out of every candidate list unless the operator set \`refactor_examples\`.
|
|
287471
287758
|
|
|
287472
287759
|
**Before picking, check the interface.** \`${t("module_extraction_candidates")}\` reports \`unmapped_attributes\` per candidate and a top-level \`partial_interfaces\` list: arguments the raw resources SET that the target module does not. Adopting such a module DROPS them silently \u2014 and the equivalence check cannot catch it, because once the argument is gone it is absent from both sides. Two of these are unrecoverable rather than merely wrong (\`object_lock_enabled\` cannot be set after creation; \`force_destroy\` changes deletion semantics). So: **decline the candidate, or extend the module to expose the argument and say so in the PR body.** Deleting the argument to make the shapes match is never the fix. A candidate whose \`unmapped_attributes\` is \`null\` was NOT checked \u2014 the module is external and its code is not in this repo \u2014 which is not the same as clean.
|
|
287473
287760
|
|
|
@@ -287600,7 +287887,7 @@ function remediateMode(t) {
|
|
|
287600
287887
|
|
|
287601
287888
|
4. **for the chosen group**:
|
|
287602
287889
|
- **base branch**: this run's base branch is resolved deterministically \u2014 \`${t("create_pull_request")}\` targets the \`base_branch\` input if set, else the branch the run started on, else the repository's default branch (\`main\`, or \`master\`). You do not choose it; just **omit** the \`base\` argument when opening the PR (below) and it is filled in.
|
|
287603
|
-
- **idempotency**: the remediation branch is the group's \`branch\` (\`remediate/<group-id>\`, with a \`--<base>\` suffix when the PR targets a non-default branch) \u2014 use it exactly, never a name of your own. Before doing anything, check whether that branch or an open PR for it already exists (\`${t("git")}\` / \`${t("get_pull_request")}\`). If one exists, update it rather than opening a duplicate.
|
|
287890
|
+
- **idempotency**: the remediation branch is the group's \`branch\` (\`remediate/<group-id>\`, with a \`--<base>\` suffix when the PR targets a non-default branch, or the branch of the PR already open for this group) \u2014 use it exactly, never a name of your own. Before doing anything, check whether that branch or an open PR for it already exists (\`${t("git")}\` / \`${t("get_pull_request")}\`). If one exists, update it rather than opening a duplicate.
|
|
287604
287891
|
- **branch**: create the group's \`branch\` from the **current HEAD** (the checkout that was just scanned) via \`${t("git")}\` (\`git({ command: "checkout", args: ["-b", <branch>] })\`). Do NOT switch to a different base first \u2014 branching from the scanned checkout keeps the PR diff to exactly your fix.
|
|
287605
287892
|
- **honest refusal (decide BEFORE fixing)**: if the group's concerns appear in the scan's \`refusal_candidates\` (the fix needs a human decision \u2014 narrowing an IAM wildcard, a KMS key policy, a real ingress CIDR), do **not** guess a fix that could break the stack. Instead open a structured issue (\`${t("create_issue")}\`) describing the concern, why it isn't auto-fixed, and what a human should do, and skip the PR for that group. A proven fix or an honest refusal \u2014 never a guessed, unverifiable PR.
|
|
287606
287893
|
- **propose, then let me steer (when there's no single right fix)**: distinct from honest refusal (which refuses a fix a human must *decide*), this is for a finding with **2\u20133 genuinely distinct, defensible fixes** that differ in trade-offs, not correctness (e.g. encrypt with an AWS-managed key **vs** a customer-managed KMS key; a narrow security-group rule **vs** a prefix list **vs** a VPC endpoint). When such a fork exists **and the triggering comment did not already select a strategy**, do **not** silently pick for the reviewer: via \`${t("create_issue_comment")}\` post one short comment listing the options as **A / B / C** \u2014 each a single line (what it does + its trade-off) \u2014 and ask the reviewer to reply \`${COMMENT_COMMAND} fix #<concern-id> with strategy <A|B|C>\`. Then **skip the PR for this group** this run and note it in your final report (it resumes when the reviewer replies). When the comment **did** select one (\`fix #<id> with strategy B\`, or a bare \`strategy B\` reply on the proposal thread), apply **exactly** that strategy \u2014 don't second-guess it. Reserve this for real forks in the road; a fix with one obvious correct answer just gets made.
|
|
@@ -287661,7 +287948,7 @@ This mode composes the **Remediate** and **Refactor** verbs into a single run. I
|
|
|
287661
287948
|
- **commit the fix** (\`git add\` only the changed \`*.tf\`/\`*.tfvars\`, a \`fix(tf): \u2026\` message). Do NOT push yet. This committed state is the refactor's equivalence BASELINE.
|
|
287662
287949
|
|
|
287663
287950
|
3. **REFACTOR (phase 2) \u2014 modularise on top of the committed fix**: follow the **Refactor** mode's flow:
|
|
287664
|
-
- \`${t("module_extraction_candidates")}\` / \`${t("terraform_normalization_candidates")}\` \u2192 pick one behaviour-preserving refactor; a
|
|
287951
|
+
- \`${t("module_extraction_candidates")}\` / \`${t("terraform_normalization_candidates")}\` \u2192 pick one behaviour-preserving refactor; a candidate marked \`report_only\` (it sits in the code of a module others call) is named in the summary, never proposed. Respect a pinned \`refactor_source\` if one was supplied (it constrains which module source you may use; the behaviour-altering b.4 path is only available when the operator pinned \`third-party\`).
|
|
287665
287952
|
- resolve the module source, wire the \`module\` call against its real interface (\`${t("terraform_module_interface")}\` for a local module dir, \`${t("terraform_module_lookup")}\` for a registry-sourced one), and emit a \`moved {}\` block for EVERY relocated address (\`${t("terraform_generate_moved")}\`).
|
|
287666
287953
|
- \`terraform fmt\` + \`${t("terraform_validate")}\`, then \u2014 **with the refactor edits still UNCOMMITTED** \u2014 call \`${t("terraform_equivalence_check")}\`. In this mode it diffs the working tree against the COMMITTED fix (not the run-start commit), so it measures only the refactor. It must return \`equivalent: true\` (zero uncovered moves, resource set + arguments preserved, validate + fmt clean) before you proceed; \`${t("push_branch")}\` hard-blocks an unproven one \u2014 and, once this run has added a \`moved {}\` block, it also hard-blocks a push that never ran the check at all, so abandoning the refactor means REVERTING its edits rather than leaving them in with the fix. If it can't be proven equivalent, abandon the refactor and ship the fix alone.
|
|
287667
287954
|
- **document the module (only when the \`docs\` input is enabled)**: after the equivalence check passes, call \`${t("terraform_module_docs")}\` for the module you created/adopted (pass the relocated addresses as \`moves\`). Do not hand-write docs \u2014 the tool builds from the interface, moved blocks, and equivalence verdict.
|
|
@@ -288074,14 +288361,14 @@ import { spawn as spawn3, spawnSync as spawnSync6 } from "node:child_process";
|
|
|
288074
288361
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
288075
288362
|
import { closeSync as closeSync3, openSync as openSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
288076
288363
|
import { constants as osConstants, userInfo } from "node:os";
|
|
288077
|
-
import { join as
|
|
288364
|
+
import { join as join45 } from "node:path";
|
|
288078
288365
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
288079
288366
|
|
|
288080
288367
|
// node_modules/.pnpm/@infraweaver-io+core@0.1.5/node_modules/@infraweaver-io/core/dist/packageManager.js
|
|
288081
288368
|
var import_semver = __toESM(require_semver2(), 1);
|
|
288082
|
-
import { existsSync as
|
|
288369
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
288083
288370
|
import { mkdir as mkdir2, readFile } from "node:fs/promises";
|
|
288084
|
-
import { delimiter as delimiter2, join as
|
|
288371
|
+
import { delimiter as delimiter2, join as join44 } from "node:path";
|
|
288085
288372
|
var SUPPORTED_NAMES = ["npm", "pnpm", "yarn", "bun"];
|
|
288086
288373
|
var COREPACK_MANAGED = ["pnpm", "yarn"];
|
|
288087
288374
|
function isSupported(name) {
|
|
@@ -288121,8 +288408,8 @@ function parseDevEnginesField(field) {
|
|
|
288121
288408
|
};
|
|
288122
288409
|
}
|
|
288123
288410
|
async function resolvePackageManagerSpec(cwd) {
|
|
288124
|
-
const pkgPath =
|
|
288125
|
-
if (!
|
|
288411
|
+
const pkgPath = join44(cwd, "package.json");
|
|
288412
|
+
if (!existsSync10(pkgPath))
|
|
288126
288413
|
return null;
|
|
288127
288414
|
let pkg;
|
|
288128
288415
|
try {
|
|
@@ -288180,7 +288467,7 @@ async function currentVersion(run4, name) {
|
|
|
288180
288467
|
return result.stdout.trim();
|
|
288181
288468
|
}
|
|
288182
288469
|
function packageManagerBinDir(tmpdir6) {
|
|
288183
|
-
return
|
|
288470
|
+
return join44(tmpdir6, "pm-bin");
|
|
288184
288471
|
}
|
|
288185
288472
|
async function ensurePackageManager(params) {
|
|
288186
288473
|
const spec = params.spec;
|
|
@@ -288421,7 +288708,7 @@ async function killProcessGroup(proc) {
|
|
|
288421
288708
|
var MAX_OUTPUT_CHARS = 5e3;
|
|
288422
288709
|
function capOutput(output2) {
|
|
288423
288710
|
if (output2.length <= MAX_OUTPUT_CHARS) return output2;
|
|
288424
|
-
const fullPath =
|
|
288711
|
+
const fullPath = join45(getTempDir(), `shell-${randomUUID4().slice(0, 8)}.log`);
|
|
288425
288712
|
writeFileSync8(fullPath, output2);
|
|
288426
288713
|
const elided = output2.length - MAX_OUTPUT_CHARS;
|
|
288427
288714
|
return `... [${elided} chars truncated; output saved to ${fullPath}] ...
|
|
@@ -288487,8 +288774,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
|
|
|
288487
288774
|
if (params.background) {
|
|
288488
288775
|
const tempDir = getTempDir();
|
|
288489
288776
|
const handle = `bg-${randomUUID4().slice(0, 8)}`;
|
|
288490
|
-
const outputPath =
|
|
288491
|
-
const pidPath =
|
|
288777
|
+
const outputPath = join45(tempDir, `${handle}.log`);
|
|
288778
|
+
const pidPath = join45(tempDir, `${handle}.pid`);
|
|
288492
288779
|
const logFd = openSync3(outputPath, "a");
|
|
288493
288780
|
let proc;
|
|
288494
288781
|
try {
|
|
@@ -289193,7 +289480,7 @@ function countAhead(head, base) {
|
|
|
289193
289480
|
}
|
|
289194
289481
|
function spillGitOutput(params) {
|
|
289195
289482
|
const tempDir = getTempDir();
|
|
289196
|
-
const outputPath =
|
|
289483
|
+
const outputPath = join46(tempDir, `git-${params.command}-${randomUUID5().slice(0, 8)}.txt`);
|
|
289197
289484
|
writeFileSync9(outputPath, params.output);
|
|
289198
289485
|
const previewByLines = params.output.split("\n").slice(0, OVERFLOW_PREVIEW_LINES).join("\n");
|
|
289199
289486
|
const preview = previewByLines.length <= OVERFLOW_PREVIEW_MAX_CHARS ? previewByLines : `${previewByLines.slice(0, OVERFLOW_PREVIEW_MAX_CHARS)}\u2026`;
|
|
@@ -289214,15 +289501,52 @@ var Git = type({
|
|
|
289214
289501
|
args: type.string.array().describe("Additional arguments for the git command").optional()
|
|
289215
289502
|
});
|
|
289216
289503
|
function splitWords(line) {
|
|
289217
|
-
|
|
289504
|
+
const words2 = [];
|
|
289505
|
+
let word = "";
|
|
289506
|
+
let inWord = false;
|
|
289507
|
+
let quote;
|
|
289508
|
+
for (let i = 0; i < line.length; i++) {
|
|
289509
|
+
const ch = line.charAt(i);
|
|
289510
|
+
if (quote === "'") {
|
|
289511
|
+
if (ch === "'") quote = void 0;
|
|
289512
|
+
else word += ch;
|
|
289513
|
+
} else if (quote === '"') {
|
|
289514
|
+
if (ch === '"') quote = void 0;
|
|
289515
|
+
else if (ch === "\\" && i + 1 < line.length && '"\\$`\n'.includes(line.charAt(i + 1))) {
|
|
289516
|
+
i += 1;
|
|
289517
|
+
if (line.charAt(i) !== "\n") word += line.charAt(i);
|
|
289518
|
+
} else word += ch;
|
|
289519
|
+
} else if (ch === " " || ch === " ") {
|
|
289520
|
+
if (inWord) words2.push(word);
|
|
289521
|
+
word = "";
|
|
289522
|
+
inWord = false;
|
|
289523
|
+
} else if (ch === "\n") {
|
|
289524
|
+
throw new Error(
|
|
289525
|
+
"command holds an unquoted newline \u2014 pass one git command per call, and quote a multi-line message"
|
|
289526
|
+
);
|
|
289527
|
+
} else if (ch === "\\") {
|
|
289528
|
+
if (i + 1 >= line.length) throw new Error("command ends in a backslash that escapes nothing");
|
|
289529
|
+
i += 1;
|
|
289530
|
+
if (line.charAt(i) === "\n") continue;
|
|
289531
|
+
word += line.charAt(i);
|
|
289532
|
+
inWord = true;
|
|
289533
|
+
} else if (ch === "'" || ch === '"') {
|
|
289534
|
+
quote = ch;
|
|
289535
|
+
inWord = true;
|
|
289536
|
+
} else {
|
|
289537
|
+
word += ch;
|
|
289538
|
+
inWord = true;
|
|
289539
|
+
}
|
|
289540
|
+
}
|
|
289541
|
+
if (quote) throw new Error(`command has an unterminated ${quote} quote`);
|
|
289542
|
+
if (inWord) words2.push(word);
|
|
289543
|
+
return words2;
|
|
289218
289544
|
}
|
|
289219
289545
|
function normalizeGitCall(params) {
|
|
289220
|
-
|
|
289221
|
-
|
|
289222
|
-
|
|
289223
|
-
|
|
289224
|
-
else return { command: params.command, args: params.args ?? [] };
|
|
289225
|
-
const [command, ...args2] = words2[0] === "git" ? words2.slice(1) : words2;
|
|
289546
|
+
const words2 = params.command === void 0 ? [] : /^git\s/.test(params.command) ? splitWords(params.command) : [params.command];
|
|
289547
|
+
words2.push(...params.args ?? []);
|
|
289548
|
+
while (words2[0] === "git") words2.shift();
|
|
289549
|
+
const [command, ...args2] = words2;
|
|
289226
289550
|
if (command === void 0 || !/^[a-z][a-z0-9-]*$/.test(command)) {
|
|
289227
289551
|
throw new Error(
|
|
289228
289552
|
`command must be a Git subcommand such as 'status' or 'checkout' (was "${command ?? ""}")`
|
|
@@ -289408,7 +289732,7 @@ function PushTagsTool(ctx) {
|
|
|
289408
289732
|
}
|
|
289409
289733
|
|
|
289410
289734
|
// src/mcp/review.ts
|
|
289411
|
-
import { readFileSync as
|
|
289735
|
+
import { readFileSync as readFileSync33 } from "node:fs";
|
|
289412
289736
|
|
|
289413
289737
|
// src/mcp/findingAudit.ts
|
|
289414
289738
|
var COHERENCE_RULES = {
|
|
@@ -289658,7 +289982,7 @@ function claimsBlockingSeverity(body2) {
|
|
|
289658
289982
|
init_core();
|
|
289659
289983
|
import { isAbsolute as isAbsolute6, resolve as resolve10 } from "node:path";
|
|
289660
289984
|
|
|
289661
|
-
// node_modules/.pnpm/@infraweaver-io+models@0.1.
|
|
289985
|
+
// node_modules/.pnpm/@infraweaver-io+models@0.1.7/node_modules/@infraweaver-io/models/dist/monotonicQuota.js
|
|
289662
289986
|
function createMonotonicQuota(params) {
|
|
289663
289987
|
const { limit, unlimited, normalize: normalize5 } = params;
|
|
289664
289988
|
let used = 0;
|
|
@@ -289683,7 +290007,7 @@ function createMonotonicQuota(params) {
|
|
|
289683
290007
|
};
|
|
289684
290008
|
}
|
|
289685
290009
|
|
|
289686
|
-
// node_modules/.pnpm/@infraweaver-io+models@0.1.
|
|
290010
|
+
// node_modules/.pnpm/@infraweaver-io+models@0.1.7/node_modules/@infraweaver-io/models/dist/costQuota.js
|
|
289687
290011
|
var CostQuotaExceededError = class extends Error {
|
|
289688
290012
|
code = "COST_QUOTA_EXCEEDED";
|
|
289689
290013
|
constructor(message2) {
|
|
@@ -289730,7 +290054,7 @@ function resolveRunCostQuota(parsed2) {
|
|
|
289730
290054
|
return parsed2 === void 0 ? DEFAULT_RUN_COST_QUOTA_USD : parsed2;
|
|
289731
290055
|
}
|
|
289732
290056
|
|
|
289733
|
-
// node_modules/.pnpm/@infraweaver-io+models@0.1.
|
|
290057
|
+
// node_modules/.pnpm/@infraweaver-io+models@0.1.7/node_modules/@infraweaver-io/models/dist/tokenQuota.js
|
|
289734
290058
|
var TokenQuotaExceededError = class extends Error {
|
|
289735
290059
|
code = "TOKEN_QUOTA_EXCEEDED";
|
|
289736
290060
|
constructor(message2) {
|
|
@@ -289740,19 +290064,16 @@ var TokenQuotaExceededError = class extends Error {
|
|
|
289740
290064
|
};
|
|
289741
290065
|
var DEFAULT_RUN_TOKEN_QUOTA = 1e7;
|
|
289742
290066
|
var RUN_TOKEN_QUOTA_INPUT = "max_run_tokens";
|
|
289743
|
-
|
|
289744
|
-
|
|
289745
|
-
|
|
289746
|
-
|
|
289747
|
-
total += v;
|
|
289748
|
-
}
|
|
289749
|
-
return Math.floor(total);
|
|
290067
|
+
var CACHE_READ_WEIGHT = 0.1;
|
|
290068
|
+
function quotaTokens(t) {
|
|
290069
|
+
const part = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
|
|
290070
|
+
return Math.floor(part(t.input) + part(t.output) + part(t.cacheWrite) + part(t.cacheRead) * CACHE_READ_WEIGHT);
|
|
289750
290071
|
}
|
|
289751
290072
|
function normalizeTotal(total) {
|
|
289752
|
-
return typeof total === "number" ? Math.max(0, Math.floor(total)) :
|
|
290073
|
+
return typeof total === "number" ? Math.max(0, Math.floor(total)) : quotaTokens(total);
|
|
289753
290074
|
}
|
|
289754
290075
|
function tokenGap(used, ceiling) {
|
|
289755
|
-
return `run token quota exhausted: ${used.toLocaleString("en-GB")} of ${ceiling.toLocaleString("en-GB")}
|
|
290076
|
+
return `run token quota exhausted: ${used.toLocaleString("en-GB")} of ${ceiling.toLocaleString("en-GB")} tokens counted against the quota (a token read from the prompt cache counts as a tenth), so the run was stopped before it finished. Its results are INCOMPLETE and must not be read as a clean assessment \u2014 a finding that would have been raised after this point was never looked for. Raise \`${RUN_TOKEN_QUOTA_INPUT}\` if the run legitimately needs more budget, or set \`${RUN_TOKEN_QUOTA_INPUT}: 0\` to remove the bound entirely. A run that reaches this limit without finishing is more often a remediation loop that cannot converge (a fix that re-breaks its own check) than a genuinely large repository.`;
|
|
289756
290077
|
}
|
|
289757
290078
|
function unlimitedTokenQuota() {
|
|
289758
290079
|
return createMonotonicQuota({
|
|
@@ -289807,7 +290128,7 @@ function validateCompatibility(payloadVersion, actionVersion) {
|
|
|
289807
290128
|
}
|
|
289808
290129
|
|
|
289809
290130
|
// src/utils/github/prCommentEvent.ts
|
|
289810
|
-
import { readFileSync as
|
|
290131
|
+
import { readFileSync as readFileSync29 } from "node:fs";
|
|
289811
290132
|
var obj = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
|
|
289812
290133
|
function parsePrCommentEvent(eventName, raw2) {
|
|
289813
290134
|
if (eventName !== "issue_comment") return void 0;
|
|
@@ -289836,7 +290157,7 @@ function readPrCommentEvent(env2 = process.env) {
|
|
|
289836
290157
|
try {
|
|
289837
290158
|
return parsePrCommentEvent(
|
|
289838
290159
|
env2.GITHUB_EVENT_NAME,
|
|
289839
|
-
JSON.parse(
|
|
290160
|
+
JSON.parse(readFileSync29(env2.GITHUB_EVENT_PATH, "utf-8"))
|
|
289840
290161
|
);
|
|
289841
290162
|
} catch {
|
|
289842
290163
|
return void 0;
|
|
@@ -289844,7 +290165,7 @@ function readPrCommentEvent(env2 = process.env) {
|
|
|
289844
290165
|
}
|
|
289845
290166
|
|
|
289846
290167
|
// src/utils/github/pullRequestEvent.ts
|
|
289847
|
-
import { readFileSync as
|
|
290168
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
289848
290169
|
var obj2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
|
|
289849
290170
|
var str = (v) => typeof v === "string" && v ? v : void 0;
|
|
289850
290171
|
function parsePullRequestEvent(eventName, raw2) {
|
|
@@ -289904,7 +290225,7 @@ function readPullRequestEvent(env2 = process.env) {
|
|
|
289904
290225
|
if (env2.GITHUB_EVENT_NAME !== "pull_request" || !env2.GITHUB_EVENT_PATH) return void 0;
|
|
289905
290226
|
let raw2;
|
|
289906
290227
|
try {
|
|
289907
|
-
raw2 = JSON.parse(
|
|
290228
|
+
raw2 = JSON.parse(readFileSync30(env2.GITHUB_EVENT_PATH, "utf-8"));
|
|
289908
290229
|
} catch {
|
|
289909
290230
|
return void 0;
|
|
289910
290231
|
}
|
|
@@ -290895,6 +291216,12 @@ function parseCommentMarker(body2) {
|
|
|
290895
291216
|
return null;
|
|
290896
291217
|
}
|
|
290897
291218
|
}
|
|
291219
|
+
function findingKeysIn(body2) {
|
|
291220
|
+
return [...body2.matchAll(new RegExp(MARKER.source, "g"))].flatMap((m) => {
|
|
291221
|
+
const marker2 = parseCommentMarker(m[0]);
|
|
291222
|
+
return marker2?.kind === "finding" ? [marker2.key] : [];
|
|
291223
|
+
});
|
|
291224
|
+
}
|
|
290898
291225
|
var SUGGESTION = /```suggestion\r?\n([\s\S]*?)```/;
|
|
290899
291226
|
function suggestionText(body2) {
|
|
290900
291227
|
const m = SUGGESTION.exec(body2);
|
|
@@ -291144,44 +291471,120 @@ function formatDuplicateCommentsNote(duplicates) {
|
|
|
291144
291471
|
var MAX_DUPLICATE_COMMENT_LINES = 50;
|
|
291145
291472
|
|
|
291146
291473
|
// src/mcp/reviewCommentLimit.ts
|
|
291147
|
-
var
|
|
291474
|
+
var MAX_NOTE_CHARS = 3e4;
|
|
291475
|
+
var TRAILER_RESERVE = 400;
|
|
291148
291476
|
var PROVEN_MARK = "\u2705 **Proven by re-scan**";
|
|
291149
|
-
|
|
291477
|
+
var SEVERITY_LEVEL = {
|
|
291478
|
+
critical: 0,
|
|
291479
|
+
high: 1,
|
|
291480
|
+
medium: 2,
|
|
291481
|
+
low: 3,
|
|
291482
|
+
info: 4
|
|
291483
|
+
};
|
|
291484
|
+
var MARKER_LEVEL = { "\u{1F6A8}": 1, "\u26A0\uFE0F": 2, "\u26A0": 2, "\u2139\uFE0F": 3, \u2139: 3 };
|
|
291485
|
+
var UNMARKED_LEVEL = 2;
|
|
291486
|
+
function rank(c, severity) {
|
|
291150
291487
|
const body2 = c.body ?? "";
|
|
291151
|
-
const
|
|
291152
|
-
|
|
291153
|
-
return severity + (body2.includes(PROVEN_MARK) ? 0 : 1);
|
|
291488
|
+
const level = severity ? SEVERITY_LEVEL[severity] : MARKER_LEVEL[leadingMarker(body2) ?? ""] ?? UNMARKED_LEVEL;
|
|
291489
|
+
return level * 2 + (body2.includes(PROVEN_MARK) ? 0 : 1);
|
|
291154
291490
|
}
|
|
291155
|
-
function limitInlineComments(comments, limit) {
|
|
291491
|
+
function limitInlineComments(comments, limit, severityOf) {
|
|
291156
291492
|
if (!limit || comments.length <= limit) return { kept: [...comments], overflow: [] };
|
|
291157
291493
|
const keep = new Set(
|
|
291158
|
-
comments.map((c, i) => ({ i, r: rank(c) })).sort((a, b) => a.r - b.r || a.i - b.i).slice(0, limit).map(({ i }) => i)
|
|
291494
|
+
comments.map((c, i) => ({ i, r: rank(c, severityOf?.(c)) })).sort((a, b) => a.r - b.r || a.i - b.i).slice(0, limit).map(({ i }) => i)
|
|
291159
291495
|
);
|
|
291160
291496
|
return {
|
|
291161
291497
|
kept: comments.filter((_, i) => keep.has(i)),
|
|
291162
291498
|
overflow: comments.filter((_, i) => !keep.has(i))
|
|
291163
291499
|
};
|
|
291164
291500
|
}
|
|
291165
|
-
|
|
291501
|
+
var escapeHtml = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
291502
|
+
var whereOf = (c) => c.line ? `${c.path}:${c.line}` : c.path;
|
|
291503
|
+
function closesItself(body2) {
|
|
291504
|
+
const occurrences = (re) => body2.match(re)?.length ?? 0;
|
|
291505
|
+
const fences = body2.split("\n").filter((l) => /^\s*(```|~~~)/.test(l)).length;
|
|
291506
|
+
return fences % 2 === 0 && occurrences(/<details\b/gi) === occurrences(/<\/details\s*>/gi) && occurrences(/<!--/g) === occurrences(/-->/g);
|
|
291507
|
+
}
|
|
291508
|
+
function asText(body2) {
|
|
291509
|
+
const longest = Math.max(0, ...(body2.match(/`+/g) ?? []).map((run4) => run4.length));
|
|
291510
|
+
const fence = "`".repeat(Math.max(3, longest + 1));
|
|
291511
|
+
return `${fence}text
|
|
291512
|
+
${body2}
|
|
291513
|
+
${fence}`;
|
|
291514
|
+
}
|
|
291515
|
+
function renderWhole(c, linkOf) {
|
|
291516
|
+
const where4 = escapeHtml(whereOf(c));
|
|
291517
|
+
const gist = gistOf(c.body);
|
|
291518
|
+
const href = linkOf?.(c);
|
|
291519
|
+
const body2 = c.body ?? "";
|
|
291520
|
+
return [
|
|
291521
|
+
`<details><summary><code>${where4}</code>${gist ? ` \u2014 ${gist}` : ""}</summary>`,
|
|
291522
|
+
...href ? [`<a href="${escapeHtml(href)}">${where4}</a>`] : [],
|
|
291523
|
+
...body2 ? [closesItself(body2) ? body2 : asText(body2)] : [],
|
|
291524
|
+
"</details>"
|
|
291525
|
+
].join("\n\n");
|
|
291526
|
+
}
|
|
291527
|
+
function renderBrief(c) {
|
|
291528
|
+
const gist = gistOf(c.body);
|
|
291529
|
+
const markers = findingKeysIn(c.body ?? "").map(
|
|
291530
|
+
(key) => renderCommentMarker({ kind: "finding", key, proven: false })
|
|
291531
|
+
);
|
|
291532
|
+
return `- \`${whereOf(c).replace(/`/g, "'")}\`${gist ? ` \u2014 ${gist}` : ""}${markers.map((m) => ` ${m}`).join("")}`;
|
|
291533
|
+
}
|
|
291534
|
+
function formatOverflowNote(overflow, limit, linkOf) {
|
|
291166
291535
|
if (overflow.length === 0) return "";
|
|
291167
|
-
const
|
|
291168
|
-
const where4 = c.line ? `${c.path}:${c.line}` : c.path;
|
|
291169
|
-
const gist = gistOf(c.body);
|
|
291170
|
-
return `- \`${where4.replace(/`/g, "'")}\`${gist ? ` \u2014 ${gist}` : ""}`;
|
|
291171
|
-
});
|
|
291172
|
-
const rest = overflow.length - shown.length;
|
|
291173
|
-
if (rest > 0) shown.push(`- \u2026and ${rest} more not shown`);
|
|
291174
|
-
return `
|
|
291536
|
+
const header = `
|
|
291175
291537
|
|
|
291176
291538
|
---
|
|
291177
291539
|
|
|
291178
|
-
**Note:** this review posts at most ${limit} inline comments (\`review_comment_limit\`), so ${overflow.length} more ${overflow.length === 1 ? "is" : "are"} listed here instead
|
|
291179
|
-
|
|
291540
|
+
**Note:** this review posts at most ${limit} inline comments (\`review_comment_limit\`), so ${overflow.length} more ${overflow.length === 1 ? "is" : "are"} listed here instead:`;
|
|
291541
|
+
const SEP = 2;
|
|
291542
|
+
let room = MAX_NOTE_CHARS - TRAILER_RESERVE - header.length;
|
|
291543
|
+
const items = [];
|
|
291544
|
+
for (const c of overflow) {
|
|
291545
|
+
const brief2 = renderBrief(c);
|
|
291546
|
+
if (brief2.length + SEP > room) break;
|
|
291547
|
+
items.push(brief2);
|
|
291548
|
+
room -= brief2.length + SEP;
|
|
291549
|
+
}
|
|
291550
|
+
let brief = items.length;
|
|
291551
|
+
for (const [i, c] of overflow.slice(0, items.length).entries()) {
|
|
291552
|
+
const whole = renderWhole(c, linkOf);
|
|
291553
|
+
const extra = whole.length - items[i].length;
|
|
291554
|
+
if (extra > room) continue;
|
|
291555
|
+
items[i] = whole;
|
|
291556
|
+
room -= extra;
|
|
291557
|
+
brief--;
|
|
291558
|
+
}
|
|
291559
|
+
const omitted = overflow.length - items.length;
|
|
291560
|
+
if (omitted > 0) items.push(`- \u2026and ${omitted} more not shown`);
|
|
291561
|
+
const cut = [
|
|
291562
|
+
brief > 0 ? `${brief} of them ${brief === 1 ? "is" : "are"} shown by place and first line only` : "",
|
|
291563
|
+
omitted > 0 ? `${omitted} ${omitted === 1 ? "is" : "are"} not shown at all` : ""
|
|
291564
|
+
].filter(Boolean);
|
|
291565
|
+
if (cut.length > 0) {
|
|
291566
|
+
items.push(`${cut.join(" and ")}, to keep this review within GitHub's size limit.`);
|
|
291567
|
+
}
|
|
291568
|
+
return `${header}
|
|
291569
|
+
|
|
291570
|
+
${items.join("\n\n")}`;
|
|
291571
|
+
}
|
|
291572
|
+
function foldedFindingsStillIntroduced(input2) {
|
|
291573
|
+
const folded = new Set(
|
|
291574
|
+
input2.reviews.flatMap(
|
|
291575
|
+
(r) => r.body && isOwnReviewComment(r.user, r.body) ? findingKeysIn(r.body) : []
|
|
291576
|
+
)
|
|
291577
|
+
);
|
|
291578
|
+
if (folded.size === 0) return [];
|
|
291579
|
+
const dismissed = new Set(input2.dismissed.map((d) => d.finding_id));
|
|
291580
|
+
return input2.delta.introduced.filter(
|
|
291581
|
+
(f) => folded.has(findingKey(f)) && !dismissed.has(f.concern.id)
|
|
291582
|
+
);
|
|
291180
291583
|
}
|
|
291181
291584
|
|
|
291182
291585
|
// src/mcp/reviewComments.ts
|
|
291183
291586
|
import { writeFileSync as writeFileSync10 } from "node:fs";
|
|
291184
|
-
import { join as
|
|
291587
|
+
import { join as join47 } from "node:path";
|
|
291185
291588
|
|
|
291186
291589
|
// src/utils/github/body.ts
|
|
291187
291590
|
var import_turndown = __toESM(require_turndown_cjs(), 1);
|
|
@@ -291865,7 +292268,7 @@ function GetReviewCommentsTool(ctx) {
|
|
|
291865
292268
|
const { threadBlocks, reviewer, formatted, truncated } = result;
|
|
291866
292269
|
const tempDir = getTempDir();
|
|
291867
292270
|
const filename = `review-${params.review_id}-threads.md`;
|
|
291868
|
-
const commentsPath =
|
|
292271
|
+
const commentsPath = join47(tempDir, filename);
|
|
291869
292272
|
writeFileSync10(commentsPath, formatted.content);
|
|
291870
292273
|
log2.debug(`wrote ${threadBlocks.length} threads to ${commentsPath}`);
|
|
291871
292274
|
const truncationNote = truncated ? ` WARNING: this PR has more review threads/comments than a single fetch returns, so the set above is INCOMPLETE \u2014 some threads or comments are not included. Address what's here, but do not treat the list as exhaustive.` : "";
|
|
@@ -292056,7 +292459,7 @@ function where2(f) {
|
|
|
292056
292459
|
function renderReviewVerdict(input2) {
|
|
292057
292460
|
const { delta, verdict: verdict2 } = input2;
|
|
292058
292461
|
const introduced = delta.introduced.length;
|
|
292059
|
-
const blocking = verdict2
|
|
292462
|
+
const { blocking } = verdict2;
|
|
292060
292463
|
const renamedBlocking = delta.introduced.filter(
|
|
292061
292464
|
(f) => f.possiblyPreexisting && failsGate(f, [...input2.requiredControls ?? []])
|
|
292062
292465
|
).length;
|
|
@@ -292161,8 +292564,8 @@ function renderReviewSummarySection(input2) {
|
|
|
292161
292564
|
}
|
|
292162
292565
|
|
|
292163
292566
|
// src/mcp/suggestionProver.ts
|
|
292164
|
-
import { mkdtempSync as mkdtempSync5, readFileSync as
|
|
292165
|
-
import { join as
|
|
292567
|
+
import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync31, rmSync as rmSync8, writeFileSync as writeFileSync11 } from "node:fs";
|
|
292568
|
+
import { join as join48, posix as posix14 } from "node:path";
|
|
292166
292569
|
var MAX_SINGLE_PROOFS = 4;
|
|
292167
292570
|
async function proveSuggestions(input2, deps) {
|
|
292168
292571
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -292174,8 +292577,8 @@ async function proveSuggestions(input2, deps) {
|
|
|
292174
292577
|
else ready.push(c);
|
|
292175
292578
|
}
|
|
292176
292579
|
if (ready.length === 0) return input2.candidates.map((c) => out.get(c.index));
|
|
292177
|
-
const parent = mkdtempSync5(
|
|
292178
|
-
const worktree =
|
|
292580
|
+
const parent = mkdtempSync5(join48(input2.tmpdir, "suggestion-proof-"));
|
|
292581
|
+
const worktree = join48(parent, "wt");
|
|
292179
292582
|
if (run("git", ["worktree", "add", "--detach", worktree, "HEAD"], input2.repoCwd).status !== 0) {
|
|
292180
292583
|
rmSync8(parent, { recursive: true, force: true });
|
|
292181
292584
|
for (const c of ready) {
|
|
@@ -292187,7 +292590,7 @@ async function proveSuggestions(input2, deps) {
|
|
|
292187
292590
|
}
|
|
292188
292591
|
return input2.candidates.map((c) => out.get(c.index));
|
|
292189
292592
|
}
|
|
292190
|
-
const scanCwd = prefix2 ?
|
|
292593
|
+
const scanCwd = prefix2 ? join48(worktree, prefix2) : worktree;
|
|
292191
292594
|
const files = [...new Set(ready.map((c) => c.path.slice(prefix2.length)))];
|
|
292192
292595
|
try {
|
|
292193
292596
|
const before = await deps.scan(scanCwd, files);
|
|
@@ -292283,16 +292686,16 @@ function snapshot3(worktree, prefix2, cs) {
|
|
|
292283
292686
|
const m = /* @__PURE__ */ new Map();
|
|
292284
292687
|
for (const c of cs) {
|
|
292285
292688
|
const rel = c.path.slice(prefix2.length);
|
|
292286
|
-
if (!m.has(rel)) m.set(rel,
|
|
292689
|
+
if (!m.has(rel)) m.set(rel, readFileSync31(join48(worktree, c.path), "utf-8"));
|
|
292287
292690
|
}
|
|
292288
292691
|
return m;
|
|
292289
292692
|
}
|
|
292290
292693
|
function restore(worktree, prefix2, pristine) {
|
|
292291
|
-
for (const [rel, text] of pristine) writeFileSync11(
|
|
292694
|
+
for (const [rel, text] of pristine) writeFileSync11(join48(worktree, prefix2, rel), text);
|
|
292292
292695
|
}
|
|
292293
292696
|
function apply(worktree, path15, cs) {
|
|
292294
|
-
const file2 =
|
|
292295
|
-
const text =
|
|
292697
|
+
const file2 = join48(worktree, path15);
|
|
292698
|
+
const text = readFileSync31(file2, "utf-8");
|
|
292296
292699
|
const eol = text.includes("\r\n") ? "\r\n" : "\n";
|
|
292297
292700
|
const lines = text.split(/\r?\n/);
|
|
292298
292701
|
for (const c of [...cs].sort((a, b) => b.startLine - a.startLine)) {
|
|
@@ -292302,12 +292705,12 @@ function apply(worktree, path15, cs) {
|
|
|
292302
292705
|
}
|
|
292303
292706
|
|
|
292304
292707
|
// src/mcp/terraform/gateScan.ts
|
|
292305
|
-
import { existsSync as
|
|
292306
|
-
import { join as
|
|
292708
|
+
import { existsSync as existsSync11, mkdtempSync as mkdtempSync6, rmSync as rmSync10 } from "node:fs";
|
|
292709
|
+
import { join as join50, posix as posix15 } from "node:path";
|
|
292307
292710
|
|
|
292308
292711
|
// src/mcp/terraform/secretScan.ts
|
|
292309
|
-
import { readFileSync as
|
|
292310
|
-
import { join as
|
|
292712
|
+
import { readFileSync as readFileSync32, rmSync as rmSync9 } from "node:fs";
|
|
292713
|
+
import { join as join49 } from "node:path";
|
|
292311
292714
|
function parseBetterleaksReport(json5, prefix2 = "") {
|
|
292312
292715
|
const doc = JSON.parse(json5);
|
|
292313
292716
|
if (Array.isArray(doc) || !doc || typeof doc !== "object" || !("findings" in doc)) {
|
|
@@ -292341,7 +292744,7 @@ async function scanAddedSecrets(cwd, mergeBase, tmp) {
|
|
|
292341
292744
|
const top = run("git", ["rev-parse", "--show-toplevel"], cwd).stdout.trim();
|
|
292342
292745
|
const prefix2 = run("git", ["rev-parse", "--show-prefix"], cwd).stdout.trim();
|
|
292343
292746
|
if (!top) return { ran: false, reason: "not a git checkout", concerns: [] };
|
|
292344
|
-
const report2 =
|
|
292747
|
+
const report2 = join49(tmp, `betterleaks-${process.pid}.json`);
|
|
292345
292748
|
try {
|
|
292346
292749
|
const r = await runAsync(
|
|
292347
292750
|
"betterleaks",
|
|
@@ -292364,7 +292767,7 @@ async function scanAddedSecrets(cwd, mergeBase, tmp) {
|
|
|
292364
292767
|
const why = (r.stderr || r.stdout).trim().split("\n").pop() ?? "";
|
|
292365
292768
|
let parsed2;
|
|
292366
292769
|
try {
|
|
292367
|
-
parsed2 = parseBetterleaksReport(
|
|
292770
|
+
parsed2 = parseBetterleaksReport(readFileSync32(report2, "utf-8"), prefix2);
|
|
292368
292771
|
} catch (error63) {
|
|
292369
292772
|
const reason = r.status !== 0 ? `betterleaks exited ${r.status}: ${why}` : `${error63}`;
|
|
292370
292773
|
return { ran: false, reason, concerns: [] };
|
|
@@ -292414,8 +292817,8 @@ function checkOutBase(cwd, pr, tmp) {
|
|
|
292414
292817
|
}
|
|
292415
292818
|
const mergeBase = run("git", ["merge-base", pr.baseSha, "HEAD"], cwd).stdout.trim() || pr.baseSha;
|
|
292416
292819
|
const prefix2 = run("git", ["rev-parse", "--show-prefix"], cwd).stdout.trim();
|
|
292417
|
-
const parent = mkdtempSync6(
|
|
292418
|
-
const worktree =
|
|
292820
|
+
const parent = mkdtempSync6(join50(tmp, "scan-delta-base-"));
|
|
292821
|
+
const worktree = join50(parent, "wt");
|
|
292419
292822
|
if (run("git", ["worktree", "add", "--detach", worktree, mergeBase], cwd).status !== 0) {
|
|
292420
292823
|
rmSync10(parent, { recursive: true, force: true });
|
|
292421
292824
|
log2.warning("\xBB scan delta: could not check out the base \u2014 every finding is treated as new.");
|
|
@@ -292423,7 +292826,7 @@ function checkOutBase(cwd, pr, tmp) {
|
|
|
292423
292826
|
}
|
|
292424
292827
|
return {
|
|
292425
292828
|
mergeBase,
|
|
292426
|
-
cwd: prefix2 ?
|
|
292829
|
+
cwd: prefix2 ? join50(worktree, prefix2) : worktree,
|
|
292427
292830
|
close: () => {
|
|
292428
292831
|
run("git", ["worktree", "remove", "--force", worktree], cwd);
|
|
292429
292832
|
rmSync10(parent, { recursive: true, force: true });
|
|
@@ -292459,7 +292862,7 @@ async function reviewScans(ctx, pr, scanners) {
|
|
|
292459
292862
|
const changed = diffScope(ctx, cwd, scanners);
|
|
292460
292863
|
const scope2 = base ? reviewScope(ctx, cwd, base) : void 0;
|
|
292461
292864
|
const started = Date.now();
|
|
292462
|
-
const scanBase = async (b) =>
|
|
292865
|
+
const scanBase = async (b) => existsSync11(b.cwd) ? scanTree(ctx, b.cwd, changed, scanners, reviewedConcern, scope2) : [];
|
|
292463
292866
|
const [head, baseScan, secrets] = await Promise.allSettled([
|
|
292464
292867
|
scanTree(ctx, cwd, changed, scanners, reviewedConcern, scope2),
|
|
292465
292868
|
base ? scanBase(base) : Promise.resolve([]),
|
|
@@ -292891,6 +293294,22 @@ function CreatePullRequestReviewTool(ctx) {
|
|
|
292891
293294
|
`cannot approve: ${outstanding} unresolved ${PRODUCT_NAME} review thread(s) still open on this PR. approval requires every prior ${PRODUCT_NAME} finding to be resolved, not just the latest commits to be clean. inspect them with \`${listRef}\`; for each thread the current code genuinely addresses, reply then call \`${resolveRef2}\`, and retry this approval. if any thread is a real outstanding issue, do NOT approve \u2014 submit a non-approving review (omit \`approved\`, or set \`request_changes\` for a blocking one) that covers it instead.`
|
|
292892
293295
|
);
|
|
292893
293296
|
}
|
|
293297
|
+
if (delta) {
|
|
293298
|
+
const reviews = await ctx.octokit.paginate(ctx.octokit.rest.pulls.listReviews, {
|
|
293299
|
+
owner: ctx.repo.owner,
|
|
293300
|
+
repo: ctx.repo.name,
|
|
293301
|
+
pull_number,
|
|
293302
|
+
per_page: 100
|
|
293303
|
+
});
|
|
293304
|
+
const folded = foldedFindingsStillIntroduced({ reviews, delta, dismissed });
|
|
293305
|
+
if (folded.length > 0) {
|
|
293306
|
+
throw new Error(
|
|
293307
|
+
`cannot approve: ${folded.length} introduced finding(s) an earlier ${PRODUCT_NAME} review listed in its body (past \`review_comment_limit\`, so with no thread to resolve) are still introduced by this head: ` + folded.slice(0, 20).map(
|
|
293308
|
+
(f) => `${f.concern.id} (${f.concern.rule_id} at ${f.concern.location.file}:${f.concern.location.line ?? "?"})`
|
|
293309
|
+
).join(", ") + `. approval requires every prior ${PRODUCT_NAME} finding to be addressed. if one genuinely needs no change, list it in \`dismissed\` with the reason and retry; otherwise do NOT approve \u2014 submit a non-approving review that covers it.`
|
|
293310
|
+
);
|
|
293311
|
+
}
|
|
293312
|
+
}
|
|
292894
293313
|
}
|
|
292895
293314
|
const skip = reviewSkipDecision({
|
|
292896
293315
|
approved: approved ?? false,
|
|
@@ -292997,6 +293416,7 @@ ${formatReanchoredNote(reanchored.moved)}`
|
|
|
292997
293416
|
params.event = event;
|
|
292998
293417
|
}
|
|
292999
293418
|
const proofs = delta ? await proveReviewSuggestions(ctx, auditedComments) : /* @__PURE__ */ new Map();
|
|
293419
|
+
const findingSeverity = /* @__PURE__ */ new Map();
|
|
293000
293420
|
const reviewComments = auditedComments.map((comment, index) => {
|
|
293001
293421
|
let commentBody = fixDoubleEscapedString(comment.body || "");
|
|
293002
293422
|
if (comment.suggestion !== void 0) {
|
|
@@ -293038,6 +293458,9 @@ ${marker2}`;
|
|
|
293038
293458
|
reviewComment.start_line = comment.start_line;
|
|
293039
293459
|
reviewComment.start_side = side;
|
|
293040
293460
|
}
|
|
293461
|
+
if (comment.provenance?.kind === "scanner") {
|
|
293462
|
+
findingSeverity.set(reviewComment, comment.provenance.finding.concern.severity);
|
|
293463
|
+
}
|
|
293041
293464
|
return reviewComment;
|
|
293042
293465
|
});
|
|
293043
293466
|
let droppedComments = [];
|
|
@@ -293073,7 +293496,11 @@ ${marker2}`;
|
|
|
293073
293496
|
`withholding ${duplicateComments.length}/${reviewComments.length} inline comment(s) that duplicate open review threads`
|
|
293074
293497
|
);
|
|
293075
293498
|
}
|
|
293076
|
-
const limited = limitInlineComments(
|
|
293499
|
+
const limited = limitInlineComments(
|
|
293500
|
+
deduped.kept,
|
|
293501
|
+
ctx.payload.reviewCommentLimit,
|
|
293502
|
+
(c) => findingSeverity.get(c)
|
|
293503
|
+
);
|
|
293077
293504
|
overflowComments = limited.overflow;
|
|
293078
293505
|
if (overflowComments.length > 0) {
|
|
293079
293506
|
log2.info(
|
|
@@ -293105,7 +293532,13 @@ ${marker2}`;
|
|
|
293105
293532
|
body2 = body2 ? body2 + note : note.replace(/^\n\n/, "");
|
|
293106
293533
|
}
|
|
293107
293534
|
if (overflowComments.length > 0) {
|
|
293108
|
-
const
|
|
293535
|
+
const server = process.env.GITHUB_SERVER_URL || "https://github.com";
|
|
293536
|
+
const commit = params.commit_id;
|
|
293537
|
+
const note = formatOverflowNote(
|
|
293538
|
+
overflowComments,
|
|
293539
|
+
ctx.payload.reviewCommentLimit,
|
|
293540
|
+
commit ? (c) => `${server}/${ctx.repo.owner}/${ctx.repo.name}/blob/${commit}/${c.path.split("/").map(encodeURIComponent).join("/")}${c.line && c.side !== "LEFT" ? `#L${c.line}` : ""}` : void 0
|
|
293541
|
+
);
|
|
293109
293542
|
body2 = body2 ? body2 + note : note.replace(/^\n\n/, "");
|
|
293110
293543
|
}
|
|
293111
293544
|
let reproved = 0;
|
|
@@ -293358,7 +293791,7 @@ ${coverageState.lastBreakdown}`
|
|
|
293358
293791
|
}
|
|
293359
293792
|
function readReviewedFile(path15) {
|
|
293360
293793
|
try {
|
|
293361
|
-
return
|
|
293794
|
+
return readFileSync33(resolveWithinCwd(resolveRepoRoot(), path15), "utf-8");
|
|
293362
293795
|
} catch {
|
|
293363
293796
|
return null;
|
|
293364
293797
|
}
|
|
@@ -293673,7 +294106,7 @@ function fastForwardDiff(params, exec2) {
|
|
|
293673
294106
|
|
|
293674
294107
|
// src/utils/prompt/changeImpact.ts
|
|
293675
294108
|
import { writeFileSync as writeFileSync12 } from "node:fs";
|
|
293676
|
-
import { join as
|
|
294109
|
+
import { join as join51 } from "node:path";
|
|
293677
294110
|
var MAX_ATOMS = 20;
|
|
293678
294111
|
var MAX_REFS_PER_ATOM = 6;
|
|
293679
294112
|
var MAX_EXCERPT = 160;
|
|
@@ -293853,7 +294286,7 @@ function createChangeImpactArtifact(params) {
|
|
|
293853
294286
|
fileCount: params.files.length,
|
|
293854
294287
|
lookupError
|
|
293855
294288
|
});
|
|
293856
|
-
const path15 =
|
|
294289
|
+
const path15 = join51(
|
|
293857
294290
|
params.tmpdir,
|
|
293858
294291
|
`pr-${params.pullNumber}-${params.headSha.slice(0, 7)}-impact.md`
|
|
293859
294292
|
);
|
|
@@ -293873,7 +294306,7 @@ function createChangeImpactArtifact(params) {
|
|
|
293873
294306
|
import { execFileSync, execSync as execSync2 } from "node:child_process";
|
|
293874
294307
|
import { mkdtempSync as mkdtempSync7, readdirSync as readdirSync9, realpathSync as realpathSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
293875
294308
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
293876
|
-
import { join as
|
|
294309
|
+
import { join as join52 } from "node:path";
|
|
293877
294310
|
|
|
293878
294311
|
// src/utils/github/ghaCore.ts
|
|
293879
294312
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
@@ -293896,7 +294329,7 @@ var TEMP_DIR_STATE_KEY = "infraweaver_temp_dir";
|
|
|
293896
294329
|
|
|
293897
294330
|
// src/utils/setup/setup.ts
|
|
293898
294331
|
function createTempDirectory() {
|
|
293899
|
-
const sharedTempDir = mkdtempSync7(
|
|
294332
|
+
const sharedTempDir = mkdtempSync7(join52(tmpdir4(), `${PRODUCT_SLUG}-`));
|
|
293900
294333
|
process.env.INFRAWEAVER_TEMP_DIR = sharedTempDir;
|
|
293901
294334
|
saveState2(TEMP_DIR_STATE_KEY, sharedTempDir);
|
|
293902
294335
|
log2.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
@@ -293942,13 +294375,13 @@ function wipeRunnerLeakSurface() {
|
|
|
293942
294375
|
return [];
|
|
293943
294376
|
}
|
|
293944
294377
|
};
|
|
293945
|
-
const fileCommandsDir =
|
|
294378
|
+
const fileCommandsDir = join52(runnerTemp, "_runner_file_commands");
|
|
293946
294379
|
for (const entry4 of listDir(fileCommandsDir)) {
|
|
293947
|
-
tryUnlink(
|
|
294380
|
+
tryUnlink(join52(fileCommandsDir, entry4));
|
|
293948
294381
|
}
|
|
293949
294382
|
for (const entry4 of listDir(runnerTemp)) {
|
|
293950
294383
|
if (entry4.endsWith(".sh") || /^git-credentials-.*\.config$/.test(entry4)) {
|
|
293951
|
-
tryUnlink(
|
|
294384
|
+
tryUnlink(join52(runnerTemp, entry4));
|
|
293952
294385
|
}
|
|
293953
294386
|
}
|
|
293954
294387
|
if (wiped.length > 0) {
|
|
@@ -294117,7 +294550,7 @@ function formatFilesWithLineNumbers(files) {
|
|
|
294117
294550
|
}
|
|
294118
294551
|
const tocLines = [`## Files (${files.length})`];
|
|
294119
294552
|
for (const entry4 of tocEntries) {
|
|
294120
|
-
const anchor2 =
|
|
294553
|
+
const anchor2 = createHash14("sha256").update(entry4.filename).digest("hex");
|
|
294121
294554
|
tocLines.push(
|
|
294122
294555
|
`- ${entry4.filename} \u2192 lines ${entry4.startLine}-${entry4.endLine} \xB7 diff-${anchor2}`
|
|
294123
294556
|
);
|
|
@@ -294447,7 +294880,7 @@ function CheckoutPrTool(ctx) {
|
|
|
294447
294880
|
headSha: ctx.toolState.checkoutSha
|
|
294448
294881
|
});
|
|
294449
294882
|
if (incremental) {
|
|
294450
|
-
incrementalDiffPath =
|
|
294883
|
+
incrementalDiffPath = join53(
|
|
294451
294884
|
tempDir,
|
|
294452
294885
|
`pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
|
|
294453
294886
|
);
|
|
@@ -294461,7 +294894,7 @@ function CheckoutPrTool(ctx) {
|
|
|
294461
294894
|
const diffPreview = formatResult.content.split("\n").slice(0, 100).join("\n");
|
|
294462
294895
|
log2.debug(`formatted diff preview (first 100 lines):
|
|
294463
294896
|
${diffPreview}`);
|
|
294464
|
-
const diffPath =
|
|
294897
|
+
const diffPath = join53(tempDir, `pr-${pull_number}-${headShort}.diff`);
|
|
294465
294898
|
writeFileSync13(diffPath, formatResult.content);
|
|
294466
294899
|
log2.debug(`wrote diff to ${diffPath} (${formatResult.content.length} bytes)`);
|
|
294467
294900
|
ctx.toolState.diffCoverage = createDiffCoverageState({
|
|
@@ -294602,7 +295035,7 @@ ${dirty}`
|
|
|
294602
295035
|
|
|
294603
295036
|
// src/mcp/checkSuite.ts
|
|
294604
295037
|
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync14 } from "node:fs";
|
|
294605
|
-
import { join as
|
|
295038
|
+
import { join as join54 } from "node:path";
|
|
294606
295039
|
import { stripVTControlCharacters } from "node:util";
|
|
294607
295040
|
var GetCheckSuiteLogs = type({
|
|
294608
295041
|
check_suite_id: type.number.describe("the id from check_suite.id")
|
|
@@ -294697,7 +295130,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
294697
295130
|
};
|
|
294698
295131
|
}
|
|
294699
295132
|
const tempDir = getTempDir();
|
|
294700
|
-
const logsDir =
|
|
295133
|
+
const logsDir = join54(tempDir, "ci-logs");
|
|
294701
295134
|
mkdirSync6(logsDir, { recursive: true });
|
|
294702
295135
|
const jobLists = await mapWithConcurrency(
|
|
294703
295136
|
failedRuns,
|
|
@@ -294721,7 +295154,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
294721
295154
|
request: { signal: AbortSignal.timeout(1e4) }
|
|
294722
295155
|
});
|
|
294723
295156
|
const logsText = typeof data === "string" ? data : Buffer.from(data).toString("utf8");
|
|
294724
|
-
const logPath =
|
|
295157
|
+
const logPath = join54(logsDir, `job-${job.id}.log`);
|
|
294725
295158
|
writeFileSync14(logPath, logsText);
|
|
294726
295159
|
const analysis = analyzeLog(logsText, 80);
|
|
294727
295160
|
const failedSteps = job.steps?.filter((s) => s.conclusion === "failure").map((s) => `Step ${s.number}: ${s.name}`) ?? [];
|
|
@@ -294783,7 +295216,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
294783
295216
|
|
|
294784
295217
|
// src/mcp/commitInfo.ts
|
|
294785
295218
|
import { writeFileSync as writeFileSync15 } from "node:fs";
|
|
294786
|
-
import { join as
|
|
295219
|
+
import { join as join55 } from "node:path";
|
|
294787
295220
|
var CommitInfo = type({
|
|
294788
295221
|
sha: type.string.describe("the commit SHA (full or abbreviated) to fetch")
|
|
294789
295222
|
});
|
|
@@ -294802,7 +295235,7 @@ function CommitInfoTool(ctx) {
|
|
|
294802
295235
|
const files = data.files ?? [];
|
|
294803
295236
|
const formatResult = formatFilesWithLineNumbers(files);
|
|
294804
295237
|
const tempDir = getTempDir("get_commit_info");
|
|
294805
|
-
const diffFile =
|
|
295238
|
+
const diffFile = join55(tempDir, `commit-${sha2.slice(0, 7)}.diff`);
|
|
294806
295239
|
writeFileSync15(diffFile, formatResult.content);
|
|
294807
295240
|
log2.debug(`wrote commit diff to ${diffFile} (${formatResult.content.length} bytes)`);
|
|
294808
295241
|
return {
|
|
@@ -294963,8 +295396,8 @@ function UpsertRemediationDashboardTool(ctx) {
|
|
|
294963
295396
|
import { performance as performance3 } from "node:perf_hooks";
|
|
294964
295397
|
|
|
294965
295398
|
// src/prep/installNodeDependencies.ts
|
|
294966
|
-
import { existsSync as
|
|
294967
|
-
import { join as
|
|
295399
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
295400
|
+
import { join as join56 } from "node:path";
|
|
294968
295401
|
|
|
294969
295402
|
// node_modules/.pnpm/package-manager-detector@1.8.0/node_modules/package-manager-detector/dist/commands.mjs
|
|
294970
295403
|
function splitRunArgs(args2, valueFlags = []) {
|
|
@@ -295350,7 +295783,7 @@ async function installFallback(name, installSpec) {
|
|
|
295350
295783
|
return result.stderr || `failed to install ${name}`;
|
|
295351
295784
|
}
|
|
295352
295785
|
if (name === "deno") {
|
|
295353
|
-
const denoPath =
|
|
295786
|
+
const denoPath = join56(process.env.HOME || "", ".deno", "bin");
|
|
295354
295787
|
process.env.PATH = `${denoPath}:${process.env.PATH}`;
|
|
295355
295788
|
}
|
|
295356
295789
|
log2.info(`\xBB installed ${name}`);
|
|
@@ -295359,8 +295792,8 @@ async function installFallback(name, installSpec) {
|
|
|
295359
295792
|
var installNodeDependencies = {
|
|
295360
295793
|
name: "installNodeDependencies",
|
|
295361
295794
|
shouldRun: () => {
|
|
295362
|
-
const packageJsonPath =
|
|
295363
|
-
return
|
|
295795
|
+
const packageJsonPath = join56(process.cwd(), "package.json");
|
|
295796
|
+
return existsSync12(packageJsonPath);
|
|
295364
295797
|
},
|
|
295365
295798
|
run: async (options) => {
|
|
295366
295799
|
const declared2 = await resolvePackageManagerSpec(process.cwd());
|
|
@@ -295468,8 +295901,8 @@ ${errorMessage2}`]
|
|
|
295468
295901
|
};
|
|
295469
295902
|
|
|
295470
295903
|
// src/prep/installPythonDependencies.ts
|
|
295471
|
-
import { existsSync as
|
|
295472
|
-
import { join as
|
|
295904
|
+
import { existsSync as existsSync13, readFileSync as readFileSync34 } from "node:fs";
|
|
295905
|
+
import { join as join57 } from "node:path";
|
|
295473
295906
|
var PYTHON_CONFIGS = [
|
|
295474
295907
|
{
|
|
295475
295908
|
file: "requirements.txt",
|
|
@@ -295504,7 +295937,7 @@ var PYTHON_CONFIGS = [
|
|
|
295504
295937
|
];
|
|
295505
295938
|
function pyprojectDeclaresBuildSystem(cwd) {
|
|
295506
295939
|
try {
|
|
295507
|
-
const content =
|
|
295940
|
+
const content = readFileSync34(join57(cwd, "pyproject.toml"), "utf8");
|
|
295508
295941
|
return /^\s*\[build-system\]/m.test(content);
|
|
295509
295942
|
} catch {
|
|
295510
295943
|
return false;
|
|
@@ -295554,13 +295987,13 @@ var installPythonDependencies = {
|
|
|
295554
295987
|
}
|
|
295555
295988
|
const cwd = process.cwd();
|
|
295556
295989
|
return PYTHON_CONFIGS.some(
|
|
295557
|
-
(config3) =>
|
|
295990
|
+
(config3) => existsSync13(join57(cwd, config3.file)) && configApplies(config3, cwd)
|
|
295558
295991
|
);
|
|
295559
295992
|
},
|
|
295560
295993
|
run: async (options) => {
|
|
295561
295994
|
const cwd = process.cwd();
|
|
295562
295995
|
const config3 = PYTHON_CONFIGS.find(
|
|
295563
|
-
(c) =>
|
|
295996
|
+
(c) => existsSync13(join57(cwd, c.file)) && configApplies(c, cwd)
|
|
295564
295997
|
);
|
|
295565
295998
|
if (!config3) {
|
|
295566
295999
|
return {
|
|
@@ -296141,8 +296574,8 @@ function SetOutputTool(ctx, outputSchema) {
|
|
|
296141
296574
|
|
|
296142
296575
|
// src/mcp/policy.ts
|
|
296143
296576
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
296144
|
-
import { existsSync as
|
|
296145
|
-
import { join as
|
|
296577
|
+
import { existsSync as existsSync14, readFileSync as readFileSync35 } from "node:fs";
|
|
296578
|
+
import { join as join58 } from "node:path";
|
|
296146
296579
|
function parseConftestOutput(stdout) {
|
|
296147
296580
|
let parsed2;
|
|
296148
296581
|
try {
|
|
@@ -296176,7 +296609,7 @@ var CONFTEST_CONFIG = "conftest.toml";
|
|
|
296176
296609
|
function conftestSelectsNamespaces(conftestCwd) {
|
|
296177
296610
|
let raw2;
|
|
296178
296611
|
try {
|
|
296179
|
-
raw2 =
|
|
296612
|
+
raw2 = readFileSync35(join58(conftestCwd, CONFTEST_CONFIG), "utf-8");
|
|
296180
296613
|
} catch {
|
|
296181
296614
|
return false;
|
|
296182
296615
|
}
|
|
@@ -296192,8 +296625,8 @@ function namespaceArgs(conftestCwd) {
|
|
|
296192
296625
|
}
|
|
296193
296626
|
function findPlanJson(cwd) {
|
|
296194
296627
|
for (const candidate of PLAN_JSON_NAMES) {
|
|
296195
|
-
const abs =
|
|
296196
|
-
if (
|
|
296628
|
+
const abs = join58(cwd, candidate);
|
|
296629
|
+
if (existsSync14(abs)) return abs;
|
|
296197
296630
|
}
|
|
296198
296631
|
return null;
|
|
296199
296632
|
}
|
|
@@ -296234,11 +296667,11 @@ function resolvePolicyDir(cwd, explicit) {
|
|
|
296234
296667
|
} catch {
|
|
296235
296668
|
return null;
|
|
296236
296669
|
}
|
|
296237
|
-
return
|
|
296670
|
+
return existsSync14(abs) ? abs : null;
|
|
296238
296671
|
}
|
|
296239
296672
|
for (const d of DEFAULT_POLICY_DIRS) {
|
|
296240
|
-
const abs =
|
|
296241
|
-
if (
|
|
296673
|
+
const abs = join58(cwd, d);
|
|
296674
|
+
if (existsSync14(abs)) return abs;
|
|
296242
296675
|
}
|
|
296243
296676
|
return null;
|
|
296244
296677
|
}
|
|
@@ -296272,7 +296705,7 @@ function PolicyCheckTool(ctx) {
|
|
|
296272
296705
|
} catch {
|
|
296273
296706
|
abs = null;
|
|
296274
296707
|
}
|
|
296275
|
-
targetFile = abs &&
|
|
296708
|
+
targetFile = abs && existsSync14(abs) ? abs : null;
|
|
296276
296709
|
if (!targetFile) {
|
|
296277
296710
|
return toolSkip(
|
|
296278
296711
|
"target_not_found",
|
|
@@ -296545,9 +296978,9 @@ function PullRequestInfoTool(ctx) {
|
|
|
296545
296978
|
|
|
296546
296979
|
// node_modules/.pnpm/@infraweaver-io+sandbox@0.1.8/node_modules/@infraweaver-io/sandbox/dist/writePolicy.js
|
|
296547
296980
|
import { renameSync, writeFileSync as writeFileSync16 } from "node:fs";
|
|
296548
|
-
import { join as
|
|
296981
|
+
import { join as join59 } from "node:path";
|
|
296549
296982
|
function writePolicyPath(tmpdir6, filename) {
|
|
296550
|
-
return
|
|
296983
|
+
return join59(tmpdir6, filename);
|
|
296551
296984
|
}
|
|
296552
296985
|
function publishWritePolicy(params) {
|
|
296553
296986
|
try {
|
|
@@ -299863,15 +300296,15 @@ async function startMcpHttpServer(ctx, options) {
|
|
|
299863
300296
|
|
|
299864
300297
|
// src/mcp/terraform/policyGate.ts
|
|
299865
300298
|
import {
|
|
299866
|
-
existsSync as
|
|
300299
|
+
existsSync as existsSync15,
|
|
299867
300300
|
mkdirSync as mkdirSync7,
|
|
299868
300301
|
mkdtempSync as mkdtempSync8,
|
|
299869
300302
|
readdirSync as readdirSync10,
|
|
299870
|
-
readFileSync as
|
|
300303
|
+
readFileSync as readFileSync37,
|
|
299871
300304
|
writeFileSync as writeFileSync17
|
|
299872
300305
|
} from "node:fs";
|
|
299873
300306
|
import { tmpdir as osTmpdir } from "node:os";
|
|
299874
|
-
import { dirname as dirname8, isAbsolute as isAbsolute8, join as
|
|
300307
|
+
import { dirname as dirname8, isAbsolute as isAbsolute8, join as join61, relative as relative8, resolve as resolve11 } from "node:path";
|
|
299875
300308
|
function coercePolicyRules(raw2) {
|
|
299876
300309
|
const rules = [];
|
|
299877
300310
|
const rejected = [];
|
|
@@ -300123,7 +300556,7 @@ function evaluateRulesStatically(cwd, rules, scope2 = { kind: "all", reason: ""
|
|
|
300123
300556
|
const files = [];
|
|
300124
300557
|
for (const rel of walk.files) {
|
|
300125
300558
|
try {
|
|
300126
|
-
files.push({ rel, text:
|
|
300559
|
+
files.push({ rel, text: readFileSync37(join61(cwd, rel), "utf-8") });
|
|
300127
300560
|
} catch {
|
|
300128
300561
|
}
|
|
300129
300562
|
}
|
|
@@ -300238,16 +300671,16 @@ function cloudEmittedRego(rules) {
|
|
|
300238
300671
|
}
|
|
300239
300672
|
function readOrEmpty(path15) {
|
|
300240
300673
|
try {
|
|
300241
|
-
return
|
|
300674
|
+
return readFileSync37(path15, "utf-8");
|
|
300242
300675
|
} catch {
|
|
300243
300676
|
return "";
|
|
300244
300677
|
}
|
|
300245
300678
|
}
|
|
300246
300679
|
function regoDirIn(root, skip) {
|
|
300247
300680
|
for (const dir of DEFAULT_POLICY_DIRS) {
|
|
300248
|
-
const abs =
|
|
300249
|
-
if (
|
|
300250
|
-
(rel) => !skip(
|
|
300681
|
+
const abs = join61(root, dir);
|
|
300682
|
+
if (existsSync15(abs) && walkFilesBySuffix(abs, ".rego").some(
|
|
300683
|
+
(rel) => !skip(join61(dir, rel), readOrEmpty(join61(abs, rel)))
|
|
300251
300684
|
)) {
|
|
300252
300685
|
return dir;
|
|
300253
300686
|
}
|
|
@@ -300255,14 +300688,14 @@ function regoDirIn(root, skip) {
|
|
|
300255
300688
|
return null;
|
|
300256
300689
|
}
|
|
300257
300690
|
function withoutSkipped(root, dir, skip, tmpdir6) {
|
|
300258
|
-
const abs =
|
|
300259
|
-
const files = readdirSync10(abs, { recursive: true, withFileTypes: true }).filter((e) => e.isFile()).map((e) => relative8(abs,
|
|
300260
|
-
const kept = files.filter((rel) => !skip(
|
|
300691
|
+
const abs = join61(root, dir);
|
|
300692
|
+
const files = readdirSync10(abs, { recursive: true, withFileTypes: true }).filter((e) => e.isFile()).map((e) => relative8(abs, join61(e.parentPath, e.name)));
|
|
300693
|
+
const kept = files.filter((rel) => !skip(join61(dir, rel), readOrEmpty(join61(abs, rel))));
|
|
300261
300694
|
if (kept.length === files.length) return abs;
|
|
300262
|
-
const copy =
|
|
300695
|
+
const copy = join61(mkdtempSync8(join61(tmpdir6 ?? osTmpdir(), "policy-own-")), dir);
|
|
300263
300696
|
for (const rel of kept) {
|
|
300264
|
-
mkdirSync7(dirname8(
|
|
300265
|
-
writeFileSync17(
|
|
300697
|
+
mkdirSync7(dirname8(join61(copy, rel)), { recursive: true });
|
|
300698
|
+
writeFileSync17(join61(copy, rel), readFileSync37(join61(abs, rel)));
|
|
300266
300699
|
}
|
|
300267
300700
|
return copy;
|
|
300268
300701
|
}
|
|
@@ -300284,18 +300717,18 @@ function resolveRepoPolicy(cwd, baseRef, tmpdir6, notes, skip) {
|
|
|
300284
300717
|
}
|
|
300285
300718
|
const own2 = tree.files.filter((f) => !skip(f.path, f.raw));
|
|
300286
300719
|
if (!own2.some((f) => f.path.endsWith(".rego"))) continue;
|
|
300287
|
-
const root = mkdtempSync8(
|
|
300720
|
+
const root = mkdtempSync8(join61(tmpdir6 ?? osTmpdir(), "policy-base-"));
|
|
300288
300721
|
for (const f of own2) {
|
|
300289
|
-
mkdirSync7(dirname8(
|
|
300290
|
-
writeFileSync17(
|
|
300722
|
+
mkdirSync7(dirname8(join61(root, f.path)), { recursive: true });
|
|
300723
|
+
writeFileSync17(join61(root, f.path), f.raw);
|
|
300291
300724
|
}
|
|
300292
300725
|
const toml = readFileAtBaseRef(cwd, baseRef, CONFTEST_CONFIG);
|
|
300293
|
-
if (toml.kind === "file") writeFileSync17(
|
|
300294
|
-
const same = head === dir && readdirSync10(
|
|
300726
|
+
if (toml.kind === "file") writeFileSync17(join61(root, CONFTEST_CONFIG), toml.raw);
|
|
300727
|
+
const same = head === dir && readdirSync10(join61(cwd, dir), { recursive: true, withFileTypes: true }).filter(
|
|
300295
300728
|
(e) => e.isFile()
|
|
300296
300729
|
).length === tree.files.length && tree.files.every((f) => {
|
|
300297
300730
|
try {
|
|
300298
|
-
return
|
|
300731
|
+
return readFileSync37(join61(cwd, f.path), "utf-8") === f.raw;
|
|
300299
300732
|
} catch {
|
|
300300
300733
|
return false;
|
|
300301
300734
|
}
|
|
@@ -300305,7 +300738,7 @@ function resolveRepoPolicy(cwd, baseRef, tmpdir6, notes, skip) {
|
|
|
300305
300738
|
`the Rego policy differs from the base ref (${tree.ref}) \u2014 applying the BASE ${dir}/ so this change cannot relax the policy reviewing it. It takes effect once merged.`
|
|
300306
300739
|
);
|
|
300307
300740
|
}
|
|
300308
|
-
return { policyDir:
|
|
300741
|
+
return { policyDir: join61(root, dir), conftestCwd: root };
|
|
300309
300742
|
}
|
|
300310
300743
|
if (head) {
|
|
300311
300744
|
notes.push(
|
|
@@ -300315,7 +300748,7 @@ function resolveRepoPolicy(cwd, baseRef, tmpdir6, notes, skip) {
|
|
|
300315
300748
|
return null;
|
|
300316
300749
|
}
|
|
300317
300750
|
function findWorkflowPlanJson(cwd, notes) {
|
|
300318
|
-
const present = PLAN_JSON_NAMES.filter((name) =>
|
|
300751
|
+
const present = PLAN_JSON_NAMES.filter((name) => existsSync15(join61(cwd, name)));
|
|
300319
300752
|
if (present.length === 0) return null;
|
|
300320
300753
|
const listing = run("git", ["ls-files", "-z"], cwd);
|
|
300321
300754
|
if (listing.status !== 0) {
|
|
@@ -300332,7 +300765,7 @@ function findWorkflowPlanJson(cwd, notes) {
|
|
|
300332
300765
|
);
|
|
300333
300766
|
continue;
|
|
300334
300767
|
}
|
|
300335
|
-
return
|
|
300768
|
+
return join61(cwd, name);
|
|
300336
300769
|
}
|
|
300337
300770
|
return null;
|
|
300338
300771
|
}
|
|
@@ -300362,7 +300795,7 @@ function evaluatePolicyGate(cwd, rawRules, opts = {}) {
|
|
|
300362
300795
|
let plan;
|
|
300363
300796
|
if (planPath) {
|
|
300364
300797
|
try {
|
|
300365
|
-
plan = asPlan(JSON.parse(
|
|
300798
|
+
plan = asPlan(JSON.parse(readFileSync37(planPath, "utf-8")));
|
|
300366
300799
|
} catch {
|
|
300367
300800
|
}
|
|
300368
300801
|
if (!plan) notes.push(`${planPath} is not a Terraform plan JSON \u2014 ignored`);
|
|
@@ -300465,7 +300898,7 @@ function capturePolicyGate(ctx) {
|
|
|
300465
300898
|
if (!result) return;
|
|
300466
300899
|
const workspace = process.env.GITHUB_WORKSPACE ?? cwd;
|
|
300467
300900
|
for (const o of [...result.violations, ...result.inconclusive]) {
|
|
300468
|
-
if (o.file) o.file = posix16(relative8(workspace,
|
|
300901
|
+
if (o.file) o.file = posix16(relative8(workspace, join61(cwd, o.file)));
|
|
300469
300902
|
}
|
|
300470
300903
|
session.policyGate = result;
|
|
300471
300904
|
for (const n of result.notes) log2.warning(`\xBB policy gate: ${n}`);
|
|
@@ -300800,7 +301233,7 @@ var ThinkingTimer = class {
|
|
|
300800
301233
|
// src/agents/claude.ts
|
|
300801
301234
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
300802
301235
|
import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, writeFileSync as writeFileSync22 } from "node:fs";
|
|
300803
|
-
import { join as
|
|
301236
|
+
import { join as join70 } from "node:path";
|
|
300804
301237
|
import { performance as performance6 } from "node:perf_hooks";
|
|
300805
301238
|
import { setTimeout as sleep6 } from "node:timers/promises";
|
|
300806
301239
|
|
|
@@ -301160,7 +301593,7 @@ import { readFile as readFile2 } from "node:fs/promises";
|
|
|
301160
301593
|
|
|
301161
301594
|
// src/agents/shared.ts
|
|
301162
301595
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
301163
|
-
import { join as
|
|
301596
|
+
import { join as join62 } from "node:path";
|
|
301164
301597
|
var MAX_STDERR_LINES = 20;
|
|
301165
301598
|
var MAX_POST_RUN_RETRIES = 3;
|
|
301166
301599
|
function getGitStatus() {
|
|
@@ -301197,7 +301630,7 @@ var agent = (input2) => {
|
|
|
301197
301630
|
};
|
|
301198
301631
|
};
|
|
301199
301632
|
function agentHomeEnv(tmpdir6) {
|
|
301200
|
-
return { HOME: tmpdir6, XDG_CONFIG_HOME:
|
|
301633
|
+
return { HOME: tmpdir6, XDG_CONFIG_HOME: join62(tmpdir6, ".config") };
|
|
301201
301634
|
}
|
|
301202
301635
|
function baseAgentEnv(homeEnv, repoDir) {
|
|
301203
301636
|
return { ...process.env, ...homeEnv, PWD: repoDir };
|
|
@@ -301674,9 +302107,9 @@ function shouldRunGraceTurn(params) {
|
|
|
301674
302107
|
}
|
|
301675
302108
|
|
|
301676
302109
|
// src/agents/quotaTokens.ts
|
|
301677
|
-
var
|
|
301678
|
-
function
|
|
301679
|
-
return t.input + t.output + t.cacheWrite + t.cacheRead *
|
|
302110
|
+
var CACHE_READ_WEIGHT2 = 0.1;
|
|
302111
|
+
function quotaTokens2(t) {
|
|
302112
|
+
return t.input + t.output + (t.reasoning ?? 0) + t.cacheWrite + t.cacheRead * CACHE_READ_WEIGHT2;
|
|
301680
302113
|
}
|
|
301681
302114
|
|
|
301682
302115
|
// src/agents/toolPlaneWatch.ts
|
|
@@ -301905,7 +302338,7 @@ function matchesRouteSentinel(envVar, model) {
|
|
|
301905
302338
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
301906
302339
|
import { mkdirSync as mkdirSync8, rmSync as rmSync11, writeFileSync as writeFileSync18 } from "node:fs";
|
|
301907
302340
|
import { homedir } from "node:os";
|
|
301908
|
-
import { join as
|
|
302341
|
+
import { join as join63 } from "node:path";
|
|
301909
302342
|
var VERTEX_SERVICE_ACCOUNT_JSON_ENV = "VERTEX_SERVICE_ACCOUNT_JSON";
|
|
301910
302343
|
var GOOGLE_APPLICATION_CREDENTIALS_ENV = "GOOGLE_APPLICATION_CREDENTIALS";
|
|
301911
302344
|
var GOOGLE_CLOUD_PROJECT_ENV = "GOOGLE_CLOUD_PROJECT";
|
|
@@ -301929,7 +302362,7 @@ function readProjectIdFromVertexServiceAccountJson() {
|
|
|
301929
302362
|
}
|
|
301930
302363
|
function createSecretDir() {
|
|
301931
302364
|
const base = process.env.INFRAWEAVER_SECRET_HOME || process.env.HOME || homedir();
|
|
301932
|
-
const secretDir =
|
|
302365
|
+
const secretDir = join63(base, `.${PRODUCT_SLUG}`, "secrets", randomUUID9());
|
|
301933
302366
|
mkdirSync8(secretDir, { recursive: true, mode: 448 });
|
|
301934
302367
|
return secretDir;
|
|
301935
302368
|
}
|
|
@@ -301938,7 +302371,7 @@ function materializeVertexCredentials(params) {
|
|
|
301938
302371
|
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
301939
302372
|
if (!blob) return void 0;
|
|
301940
302373
|
const secretDir = createSecretDir();
|
|
301941
|
-
const credentialsPath =
|
|
302374
|
+
const credentialsPath = join63(secretDir, "vertex-sa.json");
|
|
301942
302375
|
writeFileSync18(credentialsPath, blob, { mode: 384 });
|
|
301943
302376
|
process.env[GOOGLE_APPLICATION_CREDENTIALS_ENV] = credentialsPath;
|
|
301944
302377
|
const projectId = readProjectIdFromVertexServiceAccountJson();
|
|
@@ -302074,29 +302507,29 @@ function createProcessOutputActivityTimeout(ctx) {
|
|
|
302074
302507
|
}
|
|
302075
302508
|
|
|
302076
302509
|
// src/utils/prompt/skills.ts
|
|
302077
|
-
import { existsSync as
|
|
302078
|
-
import { dirname as dirname9, join as
|
|
302510
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync38, writeFileSync as writeFileSync19 } from "node:fs";
|
|
302511
|
+
import { dirname as dirname9, join as join64 } from "node:path";
|
|
302079
302512
|
import { fileURLToPath } from "node:url";
|
|
302080
302513
|
var BUNDLED_SKILL_NAMES = ["terraform-best-practices"];
|
|
302081
302514
|
function resolveSkillPath(name) {
|
|
302082
302515
|
const here = dirname9(fileURLToPath(import.meta.url));
|
|
302083
302516
|
const candidates = [
|
|
302084
|
-
|
|
302085
|
-
|
|
302517
|
+
join64(here, "..", "..", "skills", name, "SKILL.md"),
|
|
302518
|
+
join64(here, "skills", name, "SKILL.md")
|
|
302086
302519
|
];
|
|
302087
302520
|
for (const candidate of candidates) {
|
|
302088
|
-
if (
|
|
302521
|
+
if (existsSync16(candidate)) return candidate;
|
|
302089
302522
|
}
|
|
302090
302523
|
throw new Error(`bundled skill not found: ${name} (looked in ${candidates.join(", ")})`);
|
|
302091
302524
|
}
|
|
302092
302525
|
var SKILL_TARGET_DIRS = [".opencode/skills", ".claude/skills", ".agents/skills"];
|
|
302093
302526
|
function installBundledSkills(params) {
|
|
302094
302527
|
for (const name of BUNDLED_SKILL_NAMES) {
|
|
302095
|
-
const content =
|
|
302528
|
+
const content = readFileSync38(resolveSkillPath(name), "utf8");
|
|
302096
302529
|
for (const targetDir of SKILL_TARGET_DIRS) {
|
|
302097
|
-
const skillDir =
|
|
302530
|
+
const skillDir = join64(params.home, targetDir, name);
|
|
302098
302531
|
mkdirSync9(skillDir, { recursive: true });
|
|
302099
|
-
writeFileSync19(
|
|
302532
|
+
writeFileSync19(join64(skillDir, "SKILL.md"), content);
|
|
302100
302533
|
}
|
|
302101
302534
|
}
|
|
302102
302535
|
log2.success(`installed bundled skills: ${BUNDLED_SKILL_NAMES.join(", ")}`);
|
|
@@ -302104,9 +302537,9 @@ function installBundledSkills(params) {
|
|
|
302104
302537
|
|
|
302105
302538
|
// src/utils/setup/install.ts
|
|
302106
302539
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
302107
|
-
import { createHash as
|
|
302108
|
-
import { chmodSync as chmodSync2, createWriteStream as createWriteStream2, existsSync as
|
|
302109
|
-
import { join as
|
|
302540
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
302541
|
+
import { chmodSync as chmodSync2, createWriteStream as createWriteStream2, existsSync as existsSync19, readFileSync as readFileSync39 } from "node:fs";
|
|
302542
|
+
import { join as join69 } from "node:path";
|
|
302110
302543
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
302111
302544
|
|
|
302112
302545
|
// src/utils/setup/tarballCache.ts
|
|
@@ -302161,7 +302594,7 @@ function verifyTarballIntegrity(tarballPath, dist, descriptor) {
|
|
|
302161
302594
|
`Refusing to install ${descriptor}: the registry published no integrity digest (neither dist.integrity nor dist.shasum), so the download cannot be verified.`
|
|
302162
302595
|
);
|
|
302163
302596
|
}
|
|
302164
|
-
const bytes =
|
|
302597
|
+
const bytes = readFileSync39(tarballPath);
|
|
302165
302598
|
if (integrity2) {
|
|
302166
302599
|
const candidates = integrity2.trim().split(/\s+/).filter(Boolean);
|
|
302167
302600
|
for (const candidate of candidates) {
|
|
@@ -302171,7 +302604,7 @@ function verifyTarballIntegrity(tarballPath, dist, descriptor) {
|
|
|
302171
302604
|
const expected = candidate.slice(separator2 + 1);
|
|
302172
302605
|
let actual;
|
|
302173
302606
|
try {
|
|
302174
|
-
actual =
|
|
302607
|
+
actual = createHash16(algorithm).update(bytes).digest("base64");
|
|
302175
302608
|
} catch {
|
|
302176
302609
|
continue;
|
|
302177
302610
|
}
|
|
@@ -302181,7 +302614,7 @@ function verifyTarballIntegrity(tarballPath, dist, descriptor) {
|
|
|
302181
302614
|
`Integrity check FAILED for ${descriptor}: the downloaded tarball does not match the registry's published digest (${integrity2}). Refusing to execute it.`
|
|
302182
302615
|
);
|
|
302183
302616
|
}
|
|
302184
|
-
const actualShasum =
|
|
302617
|
+
const actualShasum = createHash16("sha1").update(bytes).digest("hex");
|
|
302185
302618
|
if (actualShasum !== shasum) {
|
|
302186
302619
|
throw new Error(
|
|
302187
302620
|
`Integrity check FAILED for ${descriptor}: the downloaded tarball does not match the registry's published shasum (expected ${shasum}, got ${actualShasum}). Refusing to execute it.`
|
|
@@ -302190,9 +302623,9 @@ function verifyTarballIntegrity(tarballPath, dist, descriptor) {
|
|
|
302190
302623
|
}
|
|
302191
302624
|
async function installFromNpmTarball(params) {
|
|
302192
302625
|
const tempDir = getTempDir();
|
|
302193
|
-
const extractedDir =
|
|
302194
|
-
const cliPath =
|
|
302195
|
-
if (
|
|
302626
|
+
const extractedDir = join69(tempDir, "package");
|
|
302627
|
+
const cliPath = join69(extractedDir, params.executablePath);
|
|
302628
|
+
if (existsSync19(cliPath)) {
|
|
302196
302629
|
log2.debug(`\xBB using cached binary at ${cliPath}`);
|
|
302197
302630
|
return cliPath;
|
|
302198
302631
|
}
|
|
@@ -302243,7 +302676,7 @@ async function installFromNpmTarball(params) {
|
|
|
302243
302676
|
dist = (await manifestResponse.json()).dist;
|
|
302244
302677
|
}
|
|
302245
302678
|
log2.debug(`\xBB installing ${params.packageName}@${resolvedVersion}...`);
|
|
302246
|
-
const tarballPath =
|
|
302679
|
+
const tarballPath = join69(tempDir, "package.tgz");
|
|
302247
302680
|
const tarballFileName = params.packageName.startsWith("@") ? params.packageName.split("/")[1] : params.packageName;
|
|
302248
302681
|
const tarballUrl = `${npmRegistry}/${encodedName}/-/${tarballFileName}-${resolvedVersion}.tgz`;
|
|
302249
302682
|
const restored = await restoreTarball({
|
|
@@ -302283,7 +302716,7 @@ async function installFromNpmTarball(params) {
|
|
|
302283
302716
|
`Failed to extract tarball: ${extractResult.stderr || extractResult.stdout || "Unknown error"}`
|
|
302284
302717
|
);
|
|
302285
302718
|
}
|
|
302286
|
-
if (!
|
|
302719
|
+
if (!existsSync19(cliPath)) {
|
|
302287
302720
|
throw new Error(`Executable not found in extracted package at ${cliPath}`);
|
|
302288
302721
|
}
|
|
302289
302722
|
if (params.installDependencies) {
|
|
@@ -302394,9 +302827,9 @@ var CLAUDE_DISALLOWED_TOOLS = CLAUDE_EXEC_TOOL_DENY_RULES.join(",");
|
|
|
302394
302827
|
var INFRAWEAVER_MCP_AUTH_HEADER = `Bearer \${${MCP_SERVER_TOKEN_ENV}}`;
|
|
302395
302828
|
var CLAUDE_MAX_CONCURRENT_SUBAGENTS_DEFAULT = "4";
|
|
302396
302829
|
function writeMcpConfig(ctx) {
|
|
302397
|
-
const configDir =
|
|
302830
|
+
const configDir = join70(ctx.tmpdir, ".claude");
|
|
302398
302831
|
mkdirSync10(configDir, { recursive: true });
|
|
302399
|
-
const configPath =
|
|
302832
|
+
const configPath = join70(configDir, "mcp.json");
|
|
302400
302833
|
const terraformMcp = resolveTerraformMcp(ctx.payload);
|
|
302401
302834
|
if (terraformMcp.kind === "docker_missing") log2.info(`\xBB ${terraformMcp.note}`);
|
|
302402
302835
|
const opentofuMcp = resolveOpenTofuMcp(ctx.payload);
|
|
@@ -302428,13 +302861,13 @@ function writeMcpConfig(ctx) {
|
|
|
302428
302861
|
return configPath;
|
|
302429
302862
|
}
|
|
302430
302863
|
function writePretoolGateAssets(ctx, stopHookPath) {
|
|
302431
|
-
const scriptPath =
|
|
302864
|
+
const scriptPath = join70(ctx.tmpdir, CLAUDE_PRETOOL_GATE_FILENAME);
|
|
302432
302865
|
writeFileSync22(
|
|
302433
302866
|
scriptPath,
|
|
302434
302867
|
buildClaudePretoolGateSource(ctx.subagentDeniedTools, writePolicyPath2(ctx.tmpdir))
|
|
302435
302868
|
);
|
|
302436
302869
|
chmodSync3(scriptPath, 493);
|
|
302437
|
-
const settingsPath =
|
|
302870
|
+
const settingsPath = join70(ctx.tmpdir, "infraweaver-claude-settings.json");
|
|
302438
302871
|
const settings = buildClaudePretoolGateSettings(scriptPath, CLAUDE_EXEC_TOOL_DENY_RULES);
|
|
302439
302872
|
settings.permissions.deny.push(...harnessTmpdirWriteDenyClaude(ctx.tmpdir));
|
|
302440
302873
|
if (stopHookPath) {
|
|
@@ -302523,7 +302956,7 @@ function timerFor(state5, label) {
|
|
|
302523
302956
|
function chargeTokenQuota(state5) {
|
|
302524
302957
|
const quota = state5.params.tokenQuota;
|
|
302525
302958
|
if (!quota || state5.stopRun.signal.aborted) return;
|
|
302526
|
-
if (!quota.observe(state5.quotaSource,
|
|
302959
|
+
if (!quota.observe(state5.quotaSource, quotaTokens2(state5.accumulatedTokens))) return;
|
|
302527
302960
|
log2.info(`\xBB ${state5.params.label}: ${quota.gap()}`);
|
|
302528
302961
|
state5.stopRun.abort(new TokenQuotaExceededError(quota.gap()));
|
|
302529
302962
|
}
|
|
@@ -303059,11 +303492,11 @@ var claude = agent({
|
|
|
303059
303492
|
const onVertex = matchesRouteSentinel(VERTEX_MODEL_ID_ENV, specifier) && specifier !== void 0 && isVertexAnthropicId(specifier);
|
|
303060
303493
|
const model = !specifier ? void 0 : onBedrock ? specifier : onVertex ? void 0 : stripProviderPrefix(specifier);
|
|
303061
303494
|
const homeEnv = agentHomeEnv(ctx.tmpdir);
|
|
303062
|
-
mkdirSync10(
|
|
303495
|
+
mkdirSync10(join70(homeEnv.XDG_CONFIG_HOME, "claude"), { recursive: true });
|
|
303063
303496
|
installBundledSkills({ home: homeEnv.HOME });
|
|
303064
303497
|
const mcpConfigPath = writeMcpConfig(ctx);
|
|
303065
303498
|
const effort = resolveEffort(model);
|
|
303066
|
-
const stopHookPath =
|
|
303499
|
+
const stopHookPath = join70(ctx.tmpdir, "infraweaver-stop-hook.sh");
|
|
303067
303500
|
writeFileSync22(stopHookPath, buildStopHookScript(), { mode: 493 });
|
|
303068
303501
|
const pretoolGate = writePretoolGateAssets(ctx, stopHookPath);
|
|
303069
303502
|
installManagedSettings({
|
|
@@ -303229,7 +303662,7 @@ var claude = agent({
|
|
|
303229
303662
|
init_core();
|
|
303230
303663
|
import { spawn as nodeSpawn2 } from "node:child_process";
|
|
303231
303664
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync24 } from "node:fs";
|
|
303232
|
-
import { join as
|
|
303665
|
+
import { join as join72 } from "node:path";
|
|
303233
303666
|
import { performance as performance7 } from "node:perf_hooks";
|
|
303234
303667
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
303235
303668
|
import { setTimeout as sleep7 } from "node:timers/promises";
|
|
@@ -308912,7 +309345,7 @@ function autoSelectModel() {
|
|
|
308912
309345
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
308913
309346
|
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync23 } from "node:fs";
|
|
308914
309347
|
import { homedir as homedir3, userInfo as userInfo2 } from "node:os";
|
|
308915
|
-
import { join as
|
|
309348
|
+
import { join as join71 } from "node:path";
|
|
308916
309349
|
|
|
308917
309350
|
// src/utils/agent/codexOAuth.ts
|
|
308918
309351
|
init_webapi();
|
|
@@ -308966,8 +309399,8 @@ function installCodexAuth() {
|
|
|
308966
309399
|
}
|
|
308967
309400
|
const expiresMs = decodeJwtExpMs(body2.tokens.access_token) ?? 0;
|
|
308968
309401
|
const xdgDataHome = resolveDataHome();
|
|
308969
|
-
const opencodeDir =
|
|
308970
|
-
const authPath =
|
|
309402
|
+
const opencodeDir = join71(xdgDataHome, "opencode");
|
|
309403
|
+
const authPath = join71(opencodeDir, "auth.json");
|
|
308971
309404
|
const opencodeAuth = {
|
|
308972
309405
|
openai: {
|
|
308973
309406
|
type: "oauth",
|
|
@@ -308991,7 +309424,7 @@ function installCodexAuth() {
|
|
|
308991
309424
|
};
|
|
308992
309425
|
}
|
|
308993
309426
|
function resolveDataHome() {
|
|
308994
|
-
if (process.env.CI !== "true") return
|
|
309427
|
+
if (process.env.CI !== "true") return join71(homedir3(), ".local", "share");
|
|
308995
309428
|
bootstrapInfraweaverDataDir();
|
|
308996
309429
|
return INFRAWEAVER_DATA_DIR;
|
|
308997
309430
|
}
|
|
@@ -309255,7 +309688,7 @@ function newTurn() {
|
|
|
309255
309688
|
turnCounter += 1;
|
|
309256
309689
|
return {
|
|
309257
309690
|
finalText: "",
|
|
309258
|
-
tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
309691
|
+
tokens: { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0 },
|
|
309259
309692
|
costUsd: 0,
|
|
309260
309693
|
sessionError: null,
|
|
309261
309694
|
lastToolError: null,
|
|
@@ -309265,7 +309698,7 @@ function newTurn() {
|
|
|
309265
309698
|
function chargeTokenQuota2(ctx) {
|
|
309266
309699
|
const quota = ctx.tokenQuota;
|
|
309267
309700
|
if (!quota || !ctx.currentTurn || ctx.tokenQuotaExceeded) return;
|
|
309268
|
-
if (!quota.observe(ctx.currentTurn.quotaSource,
|
|
309701
|
+
if (!quota.observe(ctx.currentTurn.quotaSource, quotaTokens2(ctx.currentTurn.tokens))) return;
|
|
309269
309702
|
ctx.tokenQuotaExceeded = true;
|
|
309270
309703
|
log2.info(`\xBB ${ctx.label}: ${quota.gap()}`);
|
|
309271
309704
|
ctx.abortRun?.(new TokenQuotaExceededError(quota.gap()));
|
|
@@ -309374,6 +309807,7 @@ async function onPartUpdated(ctx, part) {
|
|
|
309374
309807
|
if (t) {
|
|
309375
309808
|
ctx.currentTurn.tokens.input += t.input || 0;
|
|
309376
309809
|
ctx.currentTurn.tokens.output += t.output || 0;
|
|
309810
|
+
ctx.currentTurn.tokens.reasoning += t.reasoning || 0;
|
|
309377
309811
|
ctx.currentTurn.tokens.cacheRead += t.cache?.read || 0;
|
|
309378
309812
|
ctx.currentTurn.tokens.cacheWrite += t.cache?.write || 0;
|
|
309379
309813
|
}
|
|
@@ -309732,10 +310166,10 @@ var opencode = agent({
|
|
|
309732
310166
|
const openAiCompatModel = resolveOpenAiCompatibleOpenCodeModel(rawModel);
|
|
309733
310167
|
const model = isBedrockRoute ? `amazon-bedrock/${rawModel}` : vertexModel ?? openAiCompatModel ?? rawModel;
|
|
309734
310168
|
const homeEnv = agentHomeEnv(ctx.tmpdir);
|
|
309735
|
-
const opencodePluginDir =
|
|
310169
|
+
const opencodePluginDir = join72(homeEnv.XDG_CONFIG_HOME, "opencode", "plugin");
|
|
309736
310170
|
mkdirSync12(opencodePluginDir, { recursive: true });
|
|
309737
310171
|
writeFileSync24(
|
|
309738
|
-
|
|
310172
|
+
join72(opencodePluginDir, INFRAWEAVER_OPENCODE_GATE_PLUGIN_FILENAME),
|
|
309739
310173
|
buildOpencodeSubagentGateSource(ctx.subagentDeniedTools, writePolicyPath2(ctx.tmpdir))
|
|
309740
310174
|
);
|
|
309741
310175
|
installBundledSkills({ home: homeEnv.HOME });
|
|
@@ -310671,7 +311105,7 @@ async function fetchRunContext(params) {
|
|
|
310671
311105
|
// src/utils/github/github.ts
|
|
310672
311106
|
init_core();
|
|
310673
311107
|
import { rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
|
|
310674
|
-
import { dirname as dirname12, join as
|
|
311108
|
+
import { dirname as dirname12, join as join73 } from "node:path";
|
|
310675
311109
|
|
|
310676
311110
|
// node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
|
|
310677
311111
|
function getUserAgent2() {
|
|
@@ -310770,8 +311204,8 @@ function addQueryParameters(url5, parameters) {
|
|
|
310770
311204
|
}).join("&");
|
|
310771
311205
|
}
|
|
310772
311206
|
var urlVariableRegex = /\{[^{}}]+\}/g;
|
|
310773
|
-
function removeNonChars(
|
|
310774
|
-
return
|
|
311207
|
+
function removeNonChars(variableName2) {
|
|
311208
|
+
return variableName2.replace(/(?:^\W+)|(?:(?<!\W)\W+$)/g, "").split(/,/);
|
|
310775
311209
|
}
|
|
310776
311210
|
function extractUrlVariableNames(url5) {
|
|
310777
311211
|
const matches2 = url5.match(urlVariableRegex);
|
|
@@ -316487,7 +316921,7 @@ function getGitHubUsageSummary() {
|
|
|
316487
316921
|
}
|
|
316488
316922
|
async function writeGitHubUsageSummaryToFile(path15) {
|
|
316489
316923
|
const summary2 = getGitHubUsageSummary();
|
|
316490
|
-
const tmpPath =
|
|
316924
|
+
const tmpPath = join73(dirname12(path15), `.usage-summary-${process.pid}.tmp`);
|
|
316491
316925
|
await writeFile2(tmpPath, JSON.stringify(summary2));
|
|
316492
316926
|
await rename2(tmpPath, path15);
|
|
316493
316927
|
}
|
|
@@ -317032,7 +317466,7 @@ async function resolveModelAndAuth(params) {
|
|
|
317032
317466
|
// src/utils/run/runLifecycle.ts
|
|
317033
317467
|
init_core();
|
|
317034
317468
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
317035
|
-
import { join as
|
|
317469
|
+
import { join as join76, resolve as resolve13 } from "node:path";
|
|
317036
317470
|
|
|
317037
317471
|
// src/utils/cloud/cloudReport.ts
|
|
317038
317472
|
init_core();
|
|
@@ -317426,7 +317860,7 @@ async function reportToCloud(input2) {
|
|
|
317426
317860
|
|
|
317427
317861
|
// src/utils/cloud/learnings.ts
|
|
317428
317862
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
317429
|
-
import { dirname as dirname13, join as
|
|
317863
|
+
import { dirname as dirname13, join as join74 } from "node:path";
|
|
317430
317864
|
|
|
317431
317865
|
// src/utils/cloud/learningsTruncate.ts
|
|
317432
317866
|
var MAX_LEARNINGS_LENGTH = 1e5;
|
|
@@ -317443,7 +317877,7 @@ function truncateAtLineBoundary(body2, cap2) {
|
|
|
317443
317877
|
// src/utils/cloud/learnings.ts
|
|
317444
317878
|
var LEARNINGS_FILE_NAME = LEARNINGS_FILE;
|
|
317445
317879
|
function learningsFilePath(tmpdir6) {
|
|
317446
|
-
return
|
|
317880
|
+
return join74(tmpdir6, LEARNINGS_FILE_NAME);
|
|
317447
317881
|
}
|
|
317448
317882
|
async function seedLearningsFile(params) {
|
|
317449
317883
|
const path15 = learningsFilePath(params.tmpdir);
|
|
@@ -317574,7 +318008,7 @@ ${ctx.error}` : ctx.error;
|
|
|
317574
318008
|
|
|
317575
318009
|
// src/utils/github/prSummary.ts
|
|
317576
318010
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
|
|
317577
|
-
import { dirname as dirname14, join as
|
|
318011
|
+
import { dirname as dirname14, join as join75 } from "node:path";
|
|
317578
318012
|
var SUMMARY_FILE_NAME = SUMMARY_FILE;
|
|
317579
318013
|
var SUMMARY_SCAFFOLD = `# PR summary
|
|
317580
318014
|
|
|
@@ -317584,7 +318018,7 @@ var SUMMARY_SCAFFOLD = `# PR summary
|
|
|
317584
318018
|
var MIN_SNAPSHOT_LENGTH = 60;
|
|
317585
318019
|
var MAX_SNAPSHOT_LENGTH = 32768;
|
|
317586
318020
|
function summaryFilePath(tmpdir6) {
|
|
317587
|
-
return
|
|
318021
|
+
return join75(tmpdir6, SUMMARY_FILE_NAME);
|
|
317588
318022
|
}
|
|
317589
318023
|
async function seedSummaryFile(params) {
|
|
317590
318024
|
const path15 = summaryFilePath(params.tmpdir);
|
|
@@ -318118,7 +318552,7 @@ async function emitFindingsOutputs(toolState, requiredControls) {
|
|
|
318118
318552
|
if (a.level === "error") error(a.message, props);
|
|
318119
318553
|
else warning(a.message, props);
|
|
318120
318554
|
}
|
|
318121
|
-
const sarifPath =
|
|
318555
|
+
const sarifPath = join76(workspace, SARIF_FILE);
|
|
318122
318556
|
if (session.emittedSarifPath && resolve13(session.emittedSarifPath) === resolve13(sarifPath)) {
|
|
318123
318557
|
log2.info(`\xBB findings output: replacing the agent-emitted ${SARIF_FILE} with the gate's`);
|
|
318124
318558
|
}
|
|
@@ -318450,7 +318884,7 @@ async function runAgentWithWatchdogs(params) {
|
|
|
318450
318884
|
const tokenQuota = reserved ? quotas.token : createTokenQuota(quotas.tokenLimit.full);
|
|
318451
318885
|
const costQuota = reserved ? quotas.cost : createCostQuota(quotas.costLimit.full);
|
|
318452
318886
|
log2.info(
|
|
318453
|
-
quotas.tokenLimit.full > 0 ? `\xBB run token quota: ${quotas.tokenLimit.full.toLocaleString("en-GB")}
|
|
318887
|
+
quotas.tokenLimit.full > 0 ? `\xBB run token quota: ${quotas.tokenLimit.full.toLocaleString("en-GB")} tokens` + (reserved ? ` (${tokenQuota.limit.toLocaleString("en-GB")} for the run, the rest reserved to deliver findings if it runs out)` : "") + "; a token read from the prompt cache counts as a tenth" : `\xBB run token quota: disabled (${RUN_TOKEN_QUOTA_INPUT}: 0)`
|
|
318454
318888
|
);
|
|
318455
318889
|
log2.info(
|
|
318456
318890
|
quotas.costLimit.full > 0 ? `\xBB run cost quota: $${quotas.costLimit.full.toFixed(2)}` + (reserved ? ` ($${costQuota.limit.toFixed(2)} for the run, the rest reserved to deliver findings if it runs out)` : "") : `\xBB run cost quota: disabled (${RUN_COST_QUOTA_INPUT}: 0)`
|
|
@@ -318548,9 +318982,9 @@ async function runAgentWithWatchdogs(params) {
|
|
|
318548
318982
|
}
|
|
318549
318983
|
|
|
318550
318984
|
// src/phases/startToolPlane.ts
|
|
318551
|
-
import { existsSync as
|
|
318985
|
+
import { existsSync as existsSync20, readdirSync as readdirSync11 } from "node:fs";
|
|
318552
318986
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
318553
|
-
import { join as
|
|
318987
|
+
import { join as join77 } from "node:path";
|
|
318554
318988
|
|
|
318555
318989
|
// src/utils/cloud/runTerminalStatus.ts
|
|
318556
318990
|
var TERMINAL_STATE_KEY = "run_terminal";
|
|
@@ -319378,8 +319812,8 @@ ${instructions.user}` : null,
|
|
|
319378
319812
|
log2.info(instructions.full);
|
|
319379
319813
|
});
|
|
319380
319814
|
if (toolContext.agentId === "opencode") {
|
|
319381
|
-
const pluginDir =
|
|
319382
|
-
const hasPlugins =
|
|
319815
|
+
const pluginDir = join77(process.cwd(), ".opencode", "plugin");
|
|
319816
|
+
const hasPlugins = existsSync20(pluginDir) && readdirSync11(pluginDir).some((f) => /\.[jt]sx?$/.test(f));
|
|
319383
319817
|
if (hasPlugins && toolState.dependencyInstallation?.promise) {
|
|
319384
319818
|
log2.info(
|
|
319385
319819
|
"\xBB .opencode/plugin/ detected \u2014 awaiting dependency installation before agent start"
|
|
@@ -319865,7 +320299,7 @@ async function run2(args2) {
|
|
|
319865
320299
|
}
|
|
319866
320300
|
|
|
319867
320301
|
// src/commands/mcp.ts
|
|
319868
|
-
import { existsSync as
|
|
320302
|
+
import { existsSync as existsSync21, statSync as statSync12 } from "node:fs";
|
|
319869
320303
|
import { isAbsolute as isAbsolute9, resolve as resolve14 } from "node:path";
|
|
319870
320304
|
var import_arg4 = __toESM(require_arg(), 1);
|
|
319871
320305
|
var SEVERITIES5 = ["critical", "high", "medium", "low", "info"];
|
|
@@ -319938,7 +320372,7 @@ async function runMcpCli(params) {
|
|
|
319938
320372
|
if (rawCwd) {
|
|
319939
320373
|
cwd = isAbsolute9(rawCwd) ? rawCwd : resolve14(process.cwd(), rawCwd);
|
|
319940
320374
|
}
|
|
319941
|
-
if (!
|
|
320375
|
+
if (!existsSync21(cwd) || !statSync12(cwd).isDirectory()) {
|
|
319942
320376
|
console.error(`--cwd is not a directory: ${cwd}`);
|
|
319943
320377
|
process.exit(1);
|
|
319944
320378
|
}
|
|
@@ -319971,7 +320405,7 @@ async function runMcpCli(params) {
|
|
|
319971
320405
|
}
|
|
319972
320406
|
|
|
319973
320407
|
// node_modules/.pnpm/@infraweaver-io+attest@0.1.7_supports-color@7.2.0/node_modules/@infraweaver-io/attest/dist/verifyEvidence.js
|
|
319974
|
-
import { readFileSync as
|
|
320408
|
+
import { readFileSync as readFileSync40 } from "node:fs";
|
|
319975
320409
|
function usageLine(params) {
|
|
319976
320410
|
const command = params.command ? `${params.command} ` : "";
|
|
319977
320411
|
return `usage: ${params.prog} ${command}<bundle> <sig> <pubkey>`;
|
|
@@ -319989,7 +320423,7 @@ function printUsage(params, stream2) {
|
|
|
319989
320423
|
}
|
|
319990
320424
|
function readFileOrExit(path15, what) {
|
|
319991
320425
|
try {
|
|
319992
|
-
return
|
|
320426
|
+
return readFileSync40(path15);
|
|
319993
320427
|
} catch (e) {
|
|
319994
320428
|
console.error(`could not read the ${what} at ${path15}: ${errorMessage(e)}`);
|
|
319995
320429
|
process.exit(1);
|
|
@@ -320037,7 +320471,7 @@ async function runVerifyEvidenceCli2(params) {
|
|
|
320037
320471
|
}
|
|
320038
320472
|
|
|
320039
320473
|
// src/cli.ts
|
|
320040
|
-
var VERSION14 = "0.3.
|
|
320474
|
+
var VERSION14 = "0.3.13";
|
|
320041
320475
|
var bin = basename9(process.argv[1] || "");
|
|
320042
320476
|
var PROG = bin === "pf" || bin === PRODUCT_SLUG ? bin : PRODUCT_SLUG;
|
|
320043
320477
|
var rawArgs = process.argv.slice(2);
|