mason-context 0.17.3 → 0.17.4
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/CHANGELOG.md +11 -0
- package/dist/mason-audit.js +193 -156
- package/dist/mason-audit.js.map +1 -1
- package/dist/mason-auto.js +285 -244
- package/dist/mason-auto.js.map +1 -1
- package/dist/mason-drift.js +45 -18
- package/dist/mason-drift.js.map +1 -1
- package/dist/mason-hook.js +41 -13
- package/dist/mason-hook.js.map +1 -1
- package/dist/mason-mcp.js +421 -382
- package/dist/mason-mcp.js.map +1 -1
- package/dist/mason-review.js +53 -25
- package/dist/mason-review.js.map +1 -1
- package/dist/mason.js +318 -277
- package/dist/mason.js.map +1 -1
- package/package.json +1 -1
package/dist/mason-audit.js
CHANGED
|
@@ -31,6 +31,32 @@ var init_profile = __esm({
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
// src/utils/git-read.ts
|
|
35
|
+
import { execFile } from "child_process";
|
|
36
|
+
import { promisify } from "util";
|
|
37
|
+
function execGit(args, options) {
|
|
38
|
+
const command = args.find((arg) => !arg.startsWith("-")) ?? "other";
|
|
39
|
+
return profilePhase("git." + (commands.has(command) ? command : "other"), async () => {
|
|
40
|
+
const { input, ...processOptions } = options;
|
|
41
|
+
const operation = execute("git", args, processOptions);
|
|
42
|
+
if (input !== void 0) {
|
|
43
|
+
operation.child.stdin.on("error", () => {
|
|
44
|
+
});
|
|
45
|
+
operation.child.stdin.end(input);
|
|
46
|
+
}
|
|
47
|
+
return operation;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
var execute, commands;
|
|
51
|
+
var init_git_read = __esm({
|
|
52
|
+
"src/utils/git-read.ts"() {
|
|
53
|
+
"use strict";
|
|
54
|
+
init_profile();
|
|
55
|
+
execute = promisify(execFile);
|
|
56
|
+
commands = /* @__PURE__ */ new Set(["rev-parse", "symbolic-ref", "for-each-ref", "ls-files", "check-ignore", "status", "log", "diff", "ls-tree", "show", "merge-base"]);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
34
60
|
// src/utils/paths.ts
|
|
35
61
|
import path from "path";
|
|
36
62
|
function normalizeRepoPath(value) {
|
|
@@ -62,8 +88,6 @@ var init_paths = __esm({
|
|
|
62
88
|
import fs from "fs/promises";
|
|
63
89
|
import { constants } from "fs";
|
|
64
90
|
import path2 from "path";
|
|
65
|
-
import { execFile } from "child_process";
|
|
66
|
-
import { promisify } from "util";
|
|
67
91
|
import fg from "fast-glob";
|
|
68
92
|
async function readBoundedFile(file, maxBytes) {
|
|
69
93
|
const handle = await fs.open(file, constants.O_RDONLY | constants.O_NONBLOCK | constants.O_NOFOLLOW);
|
|
@@ -105,12 +129,12 @@ async function loadProjectConfig(root) {
|
|
|
105
129
|
throw new Error(`Cannot apply project file policy: ${error instanceof Error ? error.message : String(error)}`);
|
|
106
130
|
}
|
|
107
131
|
}
|
|
108
|
-
var
|
|
132
|
+
var SOURCE_EXTENSIONS, SOURCE_GLOB, SOURCE_IGNORE, MAX_SOURCE_BYTES;
|
|
109
133
|
var init_files = __esm({
|
|
110
134
|
"src/utils/files.ts"() {
|
|
111
135
|
"use strict";
|
|
136
|
+
init_git_read();
|
|
112
137
|
init_paths();
|
|
113
|
-
exec = promisify(execFile);
|
|
114
138
|
SOURCE_EXTENSIONS = ["ts", "tsx", "js", "jsx", "mts", "cts", "mjs", "cjs", "vue", "svelte", "kt", "kts", "java", "py", "go", "rs", "swift", "rb", "cs", "cpp", "c", "h", "hpp", "dart", "php"];
|
|
115
139
|
SOURCE_GLOB = `**/*.{${SOURCE_EXTENSIONS.join(",")}}`;
|
|
116
140
|
SOURCE_IGNORE = [
|
|
@@ -221,12 +245,10 @@ var init_test_map = __esm({
|
|
|
221
245
|
|
|
222
246
|
// src/snapshot/snapshot.ts
|
|
223
247
|
import path5 from "path";
|
|
224
|
-
import { execFile as execFile2 } from "child_process";
|
|
225
|
-
import { promisify as promisify2 } from "util";
|
|
226
248
|
import { z } from "zod";
|
|
227
249
|
async function getCurrentGitHash(rootDir) {
|
|
228
250
|
try {
|
|
229
|
-
const { stdout } = await
|
|
251
|
+
const { stdout } = await execGit(["rev-parse", "HEAD"], {
|
|
230
252
|
cwd: rootDir
|
|
231
253
|
});
|
|
232
254
|
return stdout.trim();
|
|
@@ -234,16 +256,16 @@ async function getCurrentGitHash(rootDir) {
|
|
|
234
256
|
return "unknown";
|
|
235
257
|
}
|
|
236
258
|
}
|
|
237
|
-
var
|
|
259
|
+
var repoPath, verificationFields, featureSchema, flowSchema, snapshotSchema;
|
|
238
260
|
var init_snapshot = __esm({
|
|
239
261
|
"src/snapshot/snapshot.ts"() {
|
|
240
262
|
"use strict";
|
|
263
|
+
init_git_read();
|
|
241
264
|
init_files();
|
|
242
265
|
init_files();
|
|
243
266
|
init_storage();
|
|
244
267
|
init_paths();
|
|
245
268
|
init_test_map();
|
|
246
|
-
exec2 = promisify2(execFile2);
|
|
247
269
|
repoPath = z.string().refine((value) => normalizeRepoPath(value) !== null, "Expected a relative repository path");
|
|
248
270
|
verificationFields = {
|
|
249
271
|
refreshedHash: z.string().optional(),
|
|
@@ -274,8 +296,6 @@ var init_snapshot = __esm({
|
|
|
274
296
|
// src/drift/drift.ts
|
|
275
297
|
import fs3 from "fs/promises";
|
|
276
298
|
import path6 from "path";
|
|
277
|
-
import { execFile as execFile3 } from "child_process";
|
|
278
|
-
import { promisify as promisify3 } from "util";
|
|
279
299
|
function parseChanges(output) {
|
|
280
300
|
const fields = output.split("\0");
|
|
281
301
|
const changes = [];
|
|
@@ -296,7 +316,7 @@ function touchedPaths(changes) {
|
|
|
296
316
|
async function getChangesWithStatus(resolvedRoot, fromHash, toHash = "HEAD") {
|
|
297
317
|
if (!fromHash || fromHash === "unknown" || fromHash.startsWith("-") || !toHash || toHash === "unknown" || toHash.startsWith("-")) return null;
|
|
298
318
|
try {
|
|
299
|
-
const { stdout } = await
|
|
319
|
+
const { stdout } = await execGit(["diff", "--name-status", "-z", "-M", fromHash, toHash, "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 });
|
|
300
320
|
return parseChanges(stdout);
|
|
301
321
|
} catch {
|
|
302
322
|
return null;
|
|
@@ -305,8 +325,8 @@ async function getChangesWithStatus(resolvedRoot, fromHash, toHash = "HEAD") {
|
|
|
305
325
|
async function getWorkingTree(resolvedRoot) {
|
|
306
326
|
try {
|
|
307
327
|
const [diff, untracked] = await Promise.all([
|
|
308
|
-
|
|
309
|
-
|
|
328
|
+
execGit(["diff", "--name-status", "-z", "-M", "HEAD", "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }),
|
|
329
|
+
execGit(["ls-files", "-z", "--others", "--exclude-standard"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 })
|
|
310
330
|
]);
|
|
311
331
|
const untrackedFiles = untracked.stdout.split("\0").filter((f) => f && !f.startsWith(".mason/"));
|
|
312
332
|
return { available: true, changedFiles: [.../* @__PURE__ */ new Set([...touchedPaths(parseChanges(diff.stdout)), ...untrackedFiles])].sort(), untrackedFiles };
|
|
@@ -314,13 +334,12 @@ async function getWorkingTree(resolvedRoot) {
|
|
|
314
334
|
return { available: false, changedFiles: [], untrackedFiles: [] };
|
|
315
335
|
}
|
|
316
336
|
}
|
|
317
|
-
var exec3;
|
|
318
337
|
var init_drift = __esm({
|
|
319
338
|
"src/drift/drift.ts"() {
|
|
320
339
|
"use strict";
|
|
340
|
+
init_git_read();
|
|
321
341
|
init_snapshot();
|
|
322
342
|
init_paths();
|
|
323
|
-
exec3 = promisify3(execFile3);
|
|
324
343
|
}
|
|
325
344
|
});
|
|
326
345
|
|
|
@@ -548,14 +567,14 @@ function extractClaims(content) {
|
|
|
548
567
|
const ignored = computeIgnoredLines(lines);
|
|
549
568
|
const paths = /* @__PURE__ */ new Map();
|
|
550
569
|
const counts = [];
|
|
551
|
-
const
|
|
570
|
+
const commands2 = /* @__PURE__ */ new Map();
|
|
552
571
|
const addPath = (claim) => {
|
|
553
572
|
const key = [claim.relativeTo ?? "scope", claim.path].join(":");
|
|
554
573
|
if (!paths.has(key)) paths.set(key, claim);
|
|
555
574
|
};
|
|
556
575
|
const addCommand = (claim) => {
|
|
557
576
|
const key = JSON.stringify([claim.scriptName, claim.directory, claim.scopeUnknown]);
|
|
558
|
-
if (!
|
|
577
|
+
if (!commands2.has(key)) commands2.set(key, claim);
|
|
559
578
|
};
|
|
560
579
|
const parsed = markdown.parse(lines.map((line, i) => ignored[i] ? "" : line).join("\n"), {});
|
|
561
580
|
for (const token of parsed) {
|
|
@@ -657,7 +676,7 @@ function extractClaims(content) {
|
|
|
657
676
|
return {
|
|
658
677
|
paths: [...paths.values()],
|
|
659
678
|
counts,
|
|
660
|
-
commands: [...
|
|
679
|
+
commands: [...commands2.values()]
|
|
661
680
|
};
|
|
662
681
|
}
|
|
663
682
|
var ROOT_FILE_NAMES, SHELL_FENCE_INFOS, markdown, COUNT_RE, COUNT_DENYLIST_RE, IGNORE_LINE, IGNORE_START, IGNORE_END;
|
|
@@ -707,9 +726,50 @@ var init_claims = __esm({
|
|
|
707
726
|
}
|
|
708
727
|
});
|
|
709
728
|
|
|
729
|
+
// src/audit/inspection.ts
|
|
730
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
731
|
+
import path8 from "path";
|
|
732
|
+
function inspectionRead(root, key, read) {
|
|
733
|
+
const inspection = inspections.getStore();
|
|
734
|
+
if (!inspection || inspection.root !== path8.resolve(root)) return read();
|
|
735
|
+
if (!inspection.reads.has(key)) {
|
|
736
|
+
const pending = read();
|
|
737
|
+
inspection.reads.set(key, pending);
|
|
738
|
+
void pending.catch(() => {
|
|
739
|
+
if (inspection.reads.get(key) === pending) inspection.reads.delete(key);
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
return inspection.reads.get(key);
|
|
743
|
+
}
|
|
744
|
+
function inspectionGit(args, options) {
|
|
745
|
+
return inspectionRead(options.cwd, "git:" + JSON.stringify([args, options]), () => execGit(args, options));
|
|
746
|
+
}
|
|
747
|
+
async function auditGitPaths(root, kind) {
|
|
748
|
+
const shared = inspections.getStore()?.root === path8.resolve(root);
|
|
749
|
+
const specs = shared ? [...docSpecs, ...sourceSpecs] : kind === "documents" ? docSpecs : sourceSpecs;
|
|
750
|
+
const limit = kind === "documents" ? 16 * 1024 * 1024 : 32 * 1024 * 1024;
|
|
751
|
+
const { stdout } = await inspectionGit(
|
|
752
|
+
["ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", ...specs],
|
|
753
|
+
{ cwd: root, maxBuffer: shared ? 48 * 1024 * 1024 : limit, timeout: 1e4 }
|
|
754
|
+
);
|
|
755
|
+
const paths = [...new Set(stdout.split("\0").filter(Boolean))].filter((file) => kind === "documents" ? /^(readme|agents|claude)\.md$/i.test(path8.posix.basename(file)) : sourceSuffixes.has(file.slice(file.lastIndexOf("."))));
|
|
756
|
+
if (Buffer.byteLength(paths.join("\0")) > limit) throw new Error("Git " + kind + " inventory exceeds its bounded read limit.");
|
|
757
|
+
return paths.sort();
|
|
758
|
+
}
|
|
759
|
+
var inspections, sourceSpecs, docSpecs, sourceSuffixes;
|
|
760
|
+
var init_inspection = __esm({
|
|
761
|
+
"src/audit/inspection.ts"() {
|
|
762
|
+
"use strict";
|
|
763
|
+
init_git_read();
|
|
764
|
+
init_files();
|
|
765
|
+
inspections = new AsyncLocalStorage2();
|
|
766
|
+
sourceSpecs = SOURCE_EXTENSIONS.map((extension) => `:(glob)**/*.${extension}`);
|
|
767
|
+
docSpecs = [":(icase,glob)**/readme.md", ":(icase,glob)**/agents.md", ":(icase,glob)**/claude.md"];
|
|
768
|
+
sourceSuffixes = new Set(SOURCE_EXTENSIONS.map((extension) => "." + extension));
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
|
|
710
772
|
// src/audit/git.ts
|
|
711
|
-
import { execFile as execFile4 } from "child_process";
|
|
712
|
-
import { promisify as promisify4 } from "util";
|
|
713
773
|
function parseCommitLine(line) {
|
|
714
774
|
const parts = line.split(" ");
|
|
715
775
|
if (parts.length < 3 || !parts[0]) return null;
|
|
@@ -717,8 +777,7 @@ function parseCommitLine(line) {
|
|
|
717
777
|
}
|
|
718
778
|
async function lastCommitOf(resolvedRoot, relPath) {
|
|
719
779
|
try {
|
|
720
|
-
const { stdout } = await
|
|
721
|
-
"git",
|
|
780
|
+
const { stdout } = await inspectionGit(
|
|
722
781
|
["log", "-1", `--format=${COMMIT_FORMAT}`, "--", `:(literal)${relPath}`],
|
|
723
782
|
{ cwd: resolvedRoot }
|
|
724
783
|
);
|
|
@@ -730,8 +789,7 @@ async function lastCommitOf(resolvedRoot, relPath) {
|
|
|
730
789
|
}
|
|
731
790
|
async function deletingCommitOf(resolvedRoot, relPath) {
|
|
732
791
|
try {
|
|
733
|
-
const { stdout } = await
|
|
734
|
-
"git",
|
|
792
|
+
const { stdout } = await inspectionGit(
|
|
735
793
|
[
|
|
736
794
|
"log",
|
|
737
795
|
"-1",
|
|
@@ -750,8 +808,7 @@ async function deletingCommitOf(resolvedRoot, relPath) {
|
|
|
750
808
|
}
|
|
751
809
|
async function firstCommitOf(resolvedRoot, relPath) {
|
|
752
810
|
try {
|
|
753
|
-
const { stdout } = await
|
|
754
|
-
"git",
|
|
811
|
+
const { stdout } = await inspectionGit(
|
|
755
812
|
["log", "--reverse", `--format=${COMMIT_FORMAT}`, "--", `:(literal)${relPath}`],
|
|
756
813
|
{ cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }
|
|
757
814
|
);
|
|
@@ -764,8 +821,7 @@ async function firstCommitOf(resolvedRoot, relPath) {
|
|
|
764
821
|
async function commitsTouchingSince(resolvedRoot, fromHash, pathspecs) {
|
|
765
822
|
if (!fromHash || fromHash === "unknown") return null;
|
|
766
823
|
try {
|
|
767
|
-
const { stdout } = await
|
|
768
|
-
"git",
|
|
824
|
+
const { stdout } = await inspectionGit(
|
|
769
825
|
[
|
|
770
826
|
"log",
|
|
771
827
|
`${fromHash}..HEAD`,
|
|
@@ -789,11 +845,11 @@ async function commitsTouchingSince(resolvedRoot, fromHash, pathspecs) {
|
|
|
789
845
|
return null;
|
|
790
846
|
}
|
|
791
847
|
}
|
|
792
|
-
var
|
|
848
|
+
var COMMIT_FORMAT;
|
|
793
849
|
var init_git = __esm({
|
|
794
850
|
"src/audit/git.ts"() {
|
|
795
851
|
"use strict";
|
|
796
|
-
|
|
852
|
+
init_inspection();
|
|
797
853
|
COMMIT_FORMAT = "%H%x09%cI%x09%s";
|
|
798
854
|
}
|
|
799
855
|
});
|
|
@@ -801,9 +857,7 @@ var init_git = __esm({
|
|
|
801
857
|
// src/audit/inputs.ts
|
|
802
858
|
import fs4 from "fs/promises";
|
|
803
859
|
import * as nativeFs from "fs";
|
|
804
|
-
import
|
|
805
|
-
import { execFile as execFile5 } from "child_process";
|
|
806
|
-
import { promisify as promisify5 } from "util";
|
|
860
|
+
import path9 from "path";
|
|
807
861
|
import fg2 from "fast-glob";
|
|
808
862
|
async function auditInputPath(root, file) {
|
|
809
863
|
if (file === ".") return fs4.realpath(root);
|
|
@@ -830,7 +884,7 @@ async function auditGlob(root, patterns, options) {
|
|
|
830
884
|
if (Array.isArray(patterns) && !patterns.length) return [];
|
|
831
885
|
const directories = /* @__PURE__ */ new Set();
|
|
832
886
|
const readdir2 = ((directory, opts, callback) => {
|
|
833
|
-
const relative =
|
|
887
|
+
const relative = path9.relative(root, directory).split(path9.sep).join("/") || ".";
|
|
834
888
|
directories.add(relative);
|
|
835
889
|
if (directories.size > MAX_INPUTS) {
|
|
836
890
|
callback(new Error(`${options.label} exceeds ${MAX_INPUTS.toLocaleString("en-US")} directories while inspecting ${relative}. Narrow this check's inputs.`));
|
|
@@ -841,7 +895,7 @@ async function auditGlob(root, patterns, options) {
|
|
|
841
895
|
}, callback);
|
|
842
896
|
});
|
|
843
897
|
const lstat2 = ((file, callback) => {
|
|
844
|
-
const relative =
|
|
898
|
+
const relative = path9.relative(root, file).split(path9.sep).join("/") || ".";
|
|
845
899
|
auditInputPath(root, relative).then(() => nativeFs.lstat(file, callback), callback);
|
|
846
900
|
});
|
|
847
901
|
const stream = fg2.stream(patterns, {
|
|
@@ -878,62 +932,48 @@ async function auditGlob(root, patterns, options) {
|
|
|
878
932
|
return matches.sort();
|
|
879
933
|
}
|
|
880
934
|
async function gitSourcePaths(root) {
|
|
881
|
-
|
|
882
|
-
"git",
|
|
883
|
-
[
|
|
884
|
-
"ls-files",
|
|
885
|
-
"-z",
|
|
886
|
-
"--cached",
|
|
887
|
-
"--others",
|
|
888
|
-
"--exclude-standard",
|
|
889
|
-
"--",
|
|
890
|
-
...SOURCE_EXTENSIONS.map((extension) => `:(glob)**/*.${extension}`)
|
|
891
|
-
],
|
|
892
|
-
{ cwd: root, maxBuffer: 32 * 1024 * 1024, timeout: 1e4 }
|
|
893
|
-
);
|
|
894
|
-
return [...new Set(stdout.split("\0").filter(Boolean))].sort();
|
|
935
|
+
return auditGitPaths(root, "sources");
|
|
895
936
|
}
|
|
896
937
|
async function gitIgnoredPaths(root, files) {
|
|
897
938
|
if (!files.length) return /* @__PURE__ */ new Set();
|
|
898
|
-
const
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
939
|
+
const ignored = /* @__PURE__ */ new Set();
|
|
940
|
+
for (let offset = 0; offset < files.length; offset += 1e3) {
|
|
941
|
+
try {
|
|
942
|
+
const { stdout } = await execGit(["check-ignore", "-z", "--stdin"], {
|
|
943
|
+
cwd: root,
|
|
944
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
945
|
+
timeout: 1e4,
|
|
946
|
+
input: files.slice(offset, offset + 1e3).join("\0") + "\0"
|
|
947
|
+
});
|
|
948
|
+
for (const file of stdout.split("\0").filter(Boolean)) ignored.add(file);
|
|
949
|
+
} catch (error) {
|
|
950
|
+
if (error.code !== 1) throw error;
|
|
951
|
+
}
|
|
911
952
|
}
|
|
953
|
+
return ignored;
|
|
912
954
|
}
|
|
913
|
-
var
|
|
955
|
+
var MAX_INPUTS;
|
|
914
956
|
var init_inputs = __esm({
|
|
915
957
|
"src/audit/inputs.ts"() {
|
|
916
958
|
"use strict";
|
|
917
959
|
init_files();
|
|
918
960
|
init_storage();
|
|
919
|
-
|
|
961
|
+
init_git_read();
|
|
962
|
+
init_inspection();
|
|
920
963
|
MAX_INPUTS = 1e5;
|
|
921
964
|
}
|
|
922
965
|
});
|
|
923
966
|
|
|
924
967
|
// src/audit/docs.ts
|
|
925
968
|
import fs5 from "fs/promises";
|
|
926
|
-
import
|
|
927
|
-
import { execFile as execFile6 } from "child_process";
|
|
928
|
-
import { promisify as promisify6 } from "util";
|
|
969
|
+
import path10 from "path";
|
|
929
970
|
import fg3 from "fast-glob";
|
|
930
971
|
async function dirtyDocs(resolvedRoot, files) {
|
|
931
972
|
if (!files.length) return /* @__PURE__ */ new Set();
|
|
932
973
|
try {
|
|
933
974
|
const dirty = /* @__PURE__ */ new Set();
|
|
934
975
|
for (let offset = 0; offset < files.length; offset += 256) {
|
|
935
|
-
const { stdout } = await
|
|
936
|
-
"git",
|
|
976
|
+
const { stdout } = await execGit(
|
|
937
977
|
["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", ...files.slice(offset, offset + 256).map((file) => `:(literal)${file}`)],
|
|
938
978
|
{ cwd: resolvedRoot, maxBuffer: 16 * 1024 * 1024, timeout: 1e4 }
|
|
939
979
|
);
|
|
@@ -953,25 +993,10 @@ async function dirtyDocs(resolvedRoot, files) {
|
|
|
953
993
|
async function discoverDocPaths(root) {
|
|
954
994
|
let candidates = [];
|
|
955
995
|
try {
|
|
956
|
-
|
|
957
|
-
"git",
|
|
958
|
-
[
|
|
959
|
-
"ls-files",
|
|
960
|
-
"-z",
|
|
961
|
-
"--cached",
|
|
962
|
-
"--others",
|
|
963
|
-
"--exclude-standard",
|
|
964
|
-
"--",
|
|
965
|
-
":(icase,glob)**/readme.md",
|
|
966
|
-
":(icase,glob)**/agents.md",
|
|
967
|
-
":(icase,glob)**/claude.md"
|
|
968
|
-
],
|
|
969
|
-
{ cwd: root, maxBuffer: 16 * 1024 * 1024, timeout: 1e4 }
|
|
970
|
-
);
|
|
971
|
-
candidates = stdout.split("\0").filter(Boolean);
|
|
996
|
+
candidates = await auditGitPaths(root, "documents");
|
|
972
997
|
} catch (error) {
|
|
973
998
|
try {
|
|
974
|
-
await
|
|
999
|
+
await execGit(["rev-parse", "--git-dir"], { cwd: root });
|
|
975
1000
|
} catch {
|
|
976
1001
|
return localDocPaths(root);
|
|
977
1002
|
}
|
|
@@ -1018,14 +1043,14 @@ async function localDocPaths(root) {
|
|
|
1018
1043
|
throw error;
|
|
1019
1044
|
}
|
|
1020
1045
|
for (const entry of entries) if (/^(?:agents|claude|readme)\.md$/i.test(entry.name)) {
|
|
1021
|
-
paths.push(
|
|
1046
|
+
paths.push(path10.posix.join(dir, entry.name));
|
|
1022
1047
|
}
|
|
1023
1048
|
}
|
|
1024
1049
|
return paths;
|
|
1025
1050
|
}
|
|
1026
1051
|
function documentScope(file) {
|
|
1027
|
-
const parent =
|
|
1028
|
-
return
|
|
1052
|
+
const parent = path10.posix.dirname(file);
|
|
1053
|
+
return path10.posix.basename(parent).toLowerCase() === ".claude" ? path10.posix.dirname(parent) : parent;
|
|
1029
1054
|
}
|
|
1030
1055
|
async function discoverDocs(resolvedRoot) {
|
|
1031
1056
|
return profilePhase("audit.documents", () => readDocs(resolvedRoot));
|
|
@@ -1045,7 +1070,7 @@ async function readDocs(resolvedRoot) {
|
|
|
1045
1070
|
path: candidate,
|
|
1046
1071
|
content,
|
|
1047
1072
|
scope: documentScope(candidate),
|
|
1048
|
-
kind: /^readme\.md$/i.test(
|
|
1073
|
+
kind: /^readme\.md$/i.test(path10.posix.basename(candidate)) ? "readme" : "instructions",
|
|
1049
1074
|
lineCount: content.split("\n").length,
|
|
1050
1075
|
lastCommit,
|
|
1051
1076
|
dirty: dirty.has(candidate),
|
|
@@ -1055,16 +1080,17 @@ async function readDocs(resolvedRoot) {
|
|
|
1055
1080
|
}
|
|
1056
1081
|
return docs;
|
|
1057
1082
|
}
|
|
1058
|
-
var
|
|
1083
|
+
var DOC_CANDIDATES;
|
|
1059
1084
|
var init_docs = __esm({
|
|
1060
1085
|
"src/audit/docs.ts"() {
|
|
1061
1086
|
"use strict";
|
|
1087
|
+
init_git_read();
|
|
1062
1088
|
init_profile();
|
|
1063
1089
|
init_claims();
|
|
1064
1090
|
init_git();
|
|
1065
1091
|
init_inputs();
|
|
1066
1092
|
init_files();
|
|
1067
|
-
|
|
1093
|
+
init_inspection();
|
|
1068
1094
|
DOC_CANDIDATES = [
|
|
1069
1095
|
"AGENTS.md",
|
|
1070
1096
|
"CLAUDE.md",
|
|
@@ -1091,14 +1117,14 @@ var init_types = __esm({
|
|
|
1091
1117
|
|
|
1092
1118
|
// src/audit/scope.ts
|
|
1093
1119
|
import fs6 from "fs/promises";
|
|
1094
|
-
import
|
|
1120
|
+
import path11 from "path";
|
|
1095
1121
|
function scopedPath(directory, value) {
|
|
1096
|
-
if (
|
|
1097
|
-
const resolved =
|
|
1122
|
+
if (path11.posix.isAbsolute(value) || value.includes("\\") || /[\x00-\x1f]/.test(value)) return null;
|
|
1123
|
+
const resolved = path11.posix.normalize(path11.posix.join(directory, value));
|
|
1098
1124
|
return resolved === ".." || resolved.startsWith("../") ? null : resolved;
|
|
1099
1125
|
}
|
|
1100
1126
|
function pathClaimScope(doc, claim) {
|
|
1101
|
-
const directory = claim.relativeTo === "document" ?
|
|
1127
|
+
const directory = claim.relativeTo === "document" ? path11.posix.dirname(doc) : documentScope(doc);
|
|
1102
1128
|
const local = scopedPath(directory, claim.path);
|
|
1103
1129
|
if (!local) return null;
|
|
1104
1130
|
const candidates = claim.relativeTo === "document" || directory === "." ? [local] : [...new Set([local, scopedPath(".", claim.path)].filter((p) => p !== null))];
|
|
@@ -1132,7 +1158,7 @@ var init_scope = __esm({
|
|
|
1132
1158
|
});
|
|
1133
1159
|
|
|
1134
1160
|
// src/audit/checks/deleted-reference.ts
|
|
1135
|
-
import
|
|
1161
|
+
import path12 from "path";
|
|
1136
1162
|
async function checkDeletedReferences(ctx) {
|
|
1137
1163
|
const result = emptyResult();
|
|
1138
1164
|
for (const doc of ctx.docs) {
|
|
@@ -1161,7 +1187,7 @@ async function checkDeletedReferences(ctx) {
|
|
|
1161
1187
|
const candidates = await Promise.all(scope.candidates.map(async (file) => ({
|
|
1162
1188
|
file,
|
|
1163
1189
|
tracked: await lastCommitOf(ctx.root, file),
|
|
1164
|
-
parent: await pathExists(ctx.root,
|
|
1190
|
+
parent: await pathExists(ctx.root, path12.posix.dirname(file))
|
|
1165
1191
|
})));
|
|
1166
1192
|
const candidate = candidates.find((c) => c.tracked || renames.has(c.file)) ?? candidates.find((c) => c.parent);
|
|
1167
1193
|
if (!candidate && claim.relativeTo !== "document") continue;
|
|
@@ -1201,7 +1227,7 @@ var init_deleted_reference = __esm({
|
|
|
1201
1227
|
// src/audit/checks/new-module.ts
|
|
1202
1228
|
import fg4 from "fast-glob";
|
|
1203
1229
|
import fs7 from "fs/promises";
|
|
1204
|
-
import
|
|
1230
|
+
import path13 from "path";
|
|
1205
1231
|
function escapeRegExp(text2) {
|
|
1206
1232
|
return text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1207
1233
|
}
|
|
@@ -1239,23 +1265,36 @@ async function checkNewModules(ctx) {
|
|
|
1239
1265
|
return result;
|
|
1240
1266
|
}
|
|
1241
1267
|
function moduleDocumentation(docs) {
|
|
1242
|
-
return docs.map((doc) => doc.content + "\n" + (
|
|
1268
|
+
return docs.map((doc) => doc.content + "\n" + (path13.posix.dirname(doc.path) === "." ? "" : path13.posix.dirname(doc.path) + "/")).join("\n");
|
|
1243
1269
|
}
|
|
1244
|
-
|
|
1270
|
+
function moduleCandidates(root, combinedDocs) {
|
|
1271
|
+
return inspectionRead(root, "modules:" + combinedDocs, () => collectModuleCandidates(root, combinedDocs));
|
|
1272
|
+
}
|
|
1273
|
+
async function collectModuleCandidates(root, combinedDocs) {
|
|
1245
1274
|
const [config, sourcePaths] = await Promise.all([loadProjectConfig(root), gitSourcePaths(root)]);
|
|
1246
1275
|
const ignore = [...SOURCE_IGNORE, ...config.ignore ?? []];
|
|
1247
1276
|
const sources = sourcePaths.filter((file) => !file.split("/").some((part) => part.startsWith(".")));
|
|
1248
|
-
const listSubdirs = async (
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1277
|
+
const listSubdirs = async (parents) => {
|
|
1278
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
1279
|
+
for (let offset = 0; offset < parents.length; offset += 16) {
|
|
1280
|
+
await Promise.all(parents.slice(offset, offset + 16).map(async (dir) => {
|
|
1281
|
+
const entries = await fs7.readdir(await auditInputPath(root, dir), { withFileTypes: true });
|
|
1282
|
+
const dirs = entries.filter((entry) => (entry.isDirectory() || entry.isSymbolicLink() && sources.some((file) => file.startsWith(path13.posix.join(dir, entry.name) + "/"))) && !entry.name.startsWith(".") && !DIR_DENYLIST.has(entry.name)).map((entry) => path13.posix.join(dir, entry.name));
|
|
1283
|
+
byParent.set(dir, dirs);
|
|
1284
|
+
}));
|
|
1285
|
+
}
|
|
1286
|
+
const ignored = await gitIgnoredPaths(root, [...byParent.values()].flat());
|
|
1287
|
+
const result = /* @__PURE__ */ new Map();
|
|
1288
|
+
for (const dir of parents) {
|
|
1289
|
+
const visible = new Set(byParent.get(dir).filter((candidate) => !ignored.has(candidate) || sources.some((file) => file.startsWith(candidate + "/"))));
|
|
1290
|
+
result.set(dir, (await auditGlob(root, dir === "." ? "*" : `${fg4.escapePath(dir)}/*`, {
|
|
1291
|
+
ignore,
|
|
1292
|
+
onlyDirectories: true,
|
|
1293
|
+
label: "Module directory discovery",
|
|
1294
|
+
select: (file) => visible.has(file)
|
|
1295
|
+
})).map((file) => path13.posix.basename(file)));
|
|
1296
|
+
}
|
|
1297
|
+
return result;
|
|
1259
1298
|
};
|
|
1260
1299
|
const countSourceFiles = async (dir) => {
|
|
1261
1300
|
const files = sources.filter((file) => file.startsWith(dir + "/"));
|
|
@@ -1271,14 +1310,16 @@ async function moduleCandidates(root, combinedDocs) {
|
|
|
1271
1310
|
return count3;
|
|
1272
1311
|
};
|
|
1273
1312
|
const candidates = [];
|
|
1274
|
-
|
|
1313
|
+
const topDirs = (await listSubdirs(["."])).get(".");
|
|
1314
|
+
const nested = await listSubdirs(topDirs.filter((dir) => isMentioned(combinedDocs, dir)));
|
|
1315
|
+
for (const topDir of topDirs) {
|
|
1275
1316
|
const topMentioned = isMentioned(combinedDocs, topDir);
|
|
1276
1317
|
if (!topMentioned) {
|
|
1277
1318
|
const count3 = await countSourceFiles(topDir);
|
|
1278
1319
|
if (count3 >= 1) candidates.push({ dir: topDir, sourceFileCount: count3 });
|
|
1279
1320
|
continue;
|
|
1280
1321
|
}
|
|
1281
|
-
const subdirs =
|
|
1322
|
+
const subdirs = nested.get(topDir);
|
|
1282
1323
|
const mentioned = subdirs.filter((s) => isMentioned(combinedDocs, s));
|
|
1283
1324
|
if (mentioned.length < ENUMERATION_THRESHOLD) continue;
|
|
1284
1325
|
for (const sub of subdirs) {
|
|
@@ -1295,6 +1336,7 @@ var DIR_DENYLIST, SECOND_LEVEL_MIN_SOURCE_FILES, ENUMERATION_THRESHOLD;
|
|
|
1295
1336
|
var init_new_module = __esm({
|
|
1296
1337
|
"src/audit/checks/new-module.ts"() {
|
|
1297
1338
|
"use strict";
|
|
1339
|
+
init_inspection();
|
|
1298
1340
|
init_files();
|
|
1299
1341
|
init_inputs();
|
|
1300
1342
|
init_git();
|
|
@@ -1324,7 +1366,7 @@ var init_new_module = __esm({
|
|
|
1324
1366
|
});
|
|
1325
1367
|
|
|
1326
1368
|
// src/audit/checks/stale-count.ts
|
|
1327
|
-
import
|
|
1369
|
+
import path14 from "path";
|
|
1328
1370
|
async function countGradleModules(root) {
|
|
1329
1371
|
for (const name of ["settings.gradle.kts", "settings.gradle"]) {
|
|
1330
1372
|
const content = await readAuditInput(root, name);
|
|
@@ -1358,7 +1400,7 @@ async function countNpmWorkspaces(root) {
|
|
|
1358
1400
|
return {
|
|
1359
1401
|
actual: matched.length,
|
|
1360
1402
|
countedFrom: "package.json workspaces",
|
|
1361
|
-
members: matched.map((m) =>
|
|
1403
|
+
members: matched.map((m) => path14.dirname(m)).sort()
|
|
1362
1404
|
};
|
|
1363
1405
|
}
|
|
1364
1406
|
}
|
|
@@ -1389,7 +1431,7 @@ async function countNpmWorkspaces(root) {
|
|
|
1389
1431
|
return {
|
|
1390
1432
|
actual: matched.length,
|
|
1391
1433
|
countedFrom: "pnpm-workspace.yaml",
|
|
1392
|
-
members: matched.map((m) =>
|
|
1434
|
+
members: matched.map((m) => path14.dirname(m)).sort()
|
|
1393
1435
|
};
|
|
1394
1436
|
}
|
|
1395
1437
|
}
|
|
@@ -1411,8 +1453,8 @@ async function countCargoCrates(root) {
|
|
|
1411
1453
|
ignore: ["**/target/**"],
|
|
1412
1454
|
label: "Cargo workspace discovery"
|
|
1413
1455
|
});
|
|
1414
|
-
for (const m of matched) members.add(
|
|
1415
|
-
} else if (await readAuditInput(root,
|
|
1456
|
+
for (const m of matched) members.add(path14.dirname(m));
|
|
1457
|
+
} else if (await readAuditInput(root, path14.posix.join(entry, "Cargo.toml")) !== null) {
|
|
1416
1458
|
members.add(entry);
|
|
1417
1459
|
}
|
|
1418
1460
|
}
|
|
@@ -1432,7 +1474,7 @@ async function resolveCountSource(root, claim) {
|
|
|
1432
1474
|
}
|
|
1433
1475
|
async function resolveDocCountSource(root, doc, claim) {
|
|
1434
1476
|
const scope = documentScope(doc);
|
|
1435
|
-
const source = await resolveCountSource(
|
|
1477
|
+
const source = await resolveCountSource(path14.join(root, scope), claim);
|
|
1436
1478
|
if (!source || scope === ".") return source;
|
|
1437
1479
|
return {
|
|
1438
1480
|
...source,
|
|
@@ -1484,7 +1526,7 @@ var init_stale_count = __esm({
|
|
|
1484
1526
|
});
|
|
1485
1527
|
|
|
1486
1528
|
// src/audit/checks/dead-command.ts
|
|
1487
|
-
import
|
|
1529
|
+
import path15 from "path";
|
|
1488
1530
|
function scriptsOf(raw) {
|
|
1489
1531
|
try {
|
|
1490
1532
|
const pkg = JSON.parse(raw);
|
|
@@ -1520,7 +1562,7 @@ async function commandInputs(root, docs) {
|
|
|
1520
1562
|
}
|
|
1521
1563
|
let cursor = directory;
|
|
1522
1564
|
while (true) {
|
|
1523
|
-
const manifest =
|
|
1565
|
+
const manifest = path15.posix.join(cursor, "package.json");
|
|
1524
1566
|
scope.candidates.push(manifest);
|
|
1525
1567
|
const raw = await read(manifest);
|
|
1526
1568
|
if (raw !== null) {
|
|
@@ -1531,7 +1573,7 @@ async function commandInputs(root, docs) {
|
|
|
1531
1573
|
break;
|
|
1532
1574
|
}
|
|
1533
1575
|
if (claim.directory !== void 0 || cursor === ".") break;
|
|
1534
|
-
cursor =
|
|
1576
|
+
cursor = path15.posix.dirname(cursor);
|
|
1535
1577
|
}
|
|
1536
1578
|
if (!resolution.manifest && !resolution.problem) {
|
|
1537
1579
|
resolution.problem = `No package.json for the command's scope (${directory}).`;
|
|
@@ -1594,10 +1636,8 @@ var init_dead_command = __esm({
|
|
|
1594
1636
|
});
|
|
1595
1637
|
|
|
1596
1638
|
// src/audit/release-metadata.ts
|
|
1597
|
-
import { execFile as execFile7 } from "child_process";
|
|
1598
|
-
import { promisify as promisify7 } from "util";
|
|
1599
1639
|
async function git(root, args) {
|
|
1600
|
-
return (await
|
|
1640
|
+
return (await execGit(args, { cwd: root, timeout: 1e4, maxBuffer: 2 * 1024 * 1024 })).stdout;
|
|
1601
1641
|
}
|
|
1602
1642
|
function withoutAndroidReleaseValues(text2) {
|
|
1603
1643
|
if (/\/\*|"""|'''/.test(text2) || !/id\s*\(?\s*["']com\.android\.(application|library)["']/.test(text2)) return null;
|
|
@@ -1643,11 +1683,10 @@ async function releaseMetadataOnly(root, commit) {
|
|
|
1643
1683
|
return false;
|
|
1644
1684
|
}
|
|
1645
1685
|
}
|
|
1646
|
-
var exec6;
|
|
1647
1686
|
var init_release_metadata = __esm({
|
|
1648
1687
|
"src/audit/release-metadata.ts"() {
|
|
1649
1688
|
"use strict";
|
|
1650
|
-
|
|
1689
|
+
init_git_read();
|
|
1651
1690
|
}
|
|
1652
1691
|
});
|
|
1653
1692
|
|
|
@@ -1743,7 +1782,7 @@ var init_deps_changed = __esm({
|
|
|
1743
1782
|
});
|
|
1744
1783
|
|
|
1745
1784
|
// src/context/lexical.ts
|
|
1746
|
-
import
|
|
1785
|
+
import path16 from "path";
|
|
1747
1786
|
var init_lexical = __esm({
|
|
1748
1787
|
"src/context/lexical.ts"() {
|
|
1749
1788
|
"use strict";
|
|
@@ -1904,7 +1943,7 @@ var init_provenance = __esm({
|
|
|
1904
1943
|
|
|
1905
1944
|
// src/decisions/decisions.ts
|
|
1906
1945
|
import fs8 from "fs/promises";
|
|
1907
|
-
import
|
|
1946
|
+
import path17 from "path";
|
|
1908
1947
|
import { createHash } from "crypto";
|
|
1909
1948
|
import { z as z3 } from "zod";
|
|
1910
1949
|
async function loadDecisionStore(rootDir) {
|
|
@@ -1955,9 +1994,9 @@ var init_decisions = __esm({
|
|
|
1955
1994
|
});
|
|
1956
1995
|
|
|
1957
1996
|
// src/decisions/drift.ts
|
|
1958
|
-
import
|
|
1997
|
+
import path18 from "path";
|
|
1959
1998
|
async function computeDecisionDrift(rootDir, decisions) {
|
|
1960
|
-
const resolvedRoot =
|
|
1999
|
+
const resolvedRoot = path18.resolve(rootDir);
|
|
1961
2000
|
const store = decisions ? { records: decisions, diagnostics: [] } : await loadDecisionStore(resolvedRoot);
|
|
1962
2001
|
const report = { historyAvailable: true, totalDecisions: store.records.length, staleDecisions: {}, freshness: {}, diagnostics: store.diagnostics };
|
|
1963
2002
|
const [head, workingTree] = await Promise.all([getCurrentGitHash(resolvedRoot), getWorkingTree(resolvedRoot)]);
|
|
@@ -2284,7 +2323,7 @@ __export(repair_exports, {
|
|
|
2284
2323
|
withRepairSession: () => withRepairSession
|
|
2285
2324
|
});
|
|
2286
2325
|
import fs10 from "fs/promises";
|
|
2287
|
-
import
|
|
2326
|
+
import path19 from "path";
|
|
2288
2327
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2289
2328
|
import { z as z6 } from "zod";
|
|
2290
2329
|
function recheckable(finding) {
|
|
@@ -2322,8 +2361,8 @@ async function readStableAudit(root, checks, options) {
|
|
|
2322
2361
|
async function prepareRepair(rootDir, checks = ALL_CHECKS, options = {}) {
|
|
2323
2362
|
return prepareOriginal(rootDir, checks, options);
|
|
2324
2363
|
}
|
|
2325
|
-
async function withRepairSession(root, options, run, cachedAudit) {
|
|
2326
|
-
const
|
|
2364
|
+
async function withRepairSession(root, options, run, validate, cachedAudit) {
|
|
2365
|
+
const head = await getCurrentGitHash(root);
|
|
2327
2366
|
const audits = /* @__PURE__ */ new Map();
|
|
2328
2367
|
const documents = /* @__PURE__ */ new Map();
|
|
2329
2368
|
const history = /* @__PURE__ */ new Map();
|
|
@@ -2334,9 +2373,9 @@ async function withRepairSession(root, options, run, cachedAudit) {
|
|
|
2334
2373
|
};
|
|
2335
2374
|
const session = {
|
|
2336
2375
|
audit: (checks) => memo(audits, [...checks].sort().join(","), async () => {
|
|
2337
|
-
if (cachedAudit && cachedAudit.headHash ===
|
|
2376
|
+
if (cachedAudit && cachedAudit.headHash === head && cachedAudit.root === root && digest([...checks].sort()) === digest([...cachedAudit.checksRun ?? []].sort())) {
|
|
2338
2377
|
const current = structuredClone(cachedAudit);
|
|
2339
|
-
const reviews = (await Promise.all(allFindings(current).map((f) => assessAdvisory(root, f,
|
|
2378
|
+
const reviews = (await Promise.all(allFindings(current).map((f) => assessAdvisory(root, f, head)))).filter((r) => r !== null);
|
|
2340
2379
|
delete current.advisoryReviews;
|
|
2341
2380
|
if (reviews.length) current.advisoryReviews = reviews;
|
|
2342
2381
|
return current;
|
|
@@ -2344,16 +2383,15 @@ async function withRepairSession(root, options, run, cachedAudit) {
|
|
|
2344
2383
|
return computeAudit(root, { ...options, checks });
|
|
2345
2384
|
}),
|
|
2346
2385
|
document: (file) => memo(documents, file, async () => readBoundedFile(await storePath(root, file), 10 * 1024 * 1024)),
|
|
2347
|
-
history: (
|
|
2348
|
-
assessment: (dir, finding,
|
|
2386
|
+
history: (head2) => memo(history, head2, () => getChangesWithStatus(root, head2)),
|
|
2387
|
+
assessment: (dir, finding, head2) => memo(assessments, digest([dir, finding, head2]), () => assessAdvisory(dir, finding, head2))
|
|
2349
2388
|
};
|
|
2350
2389
|
const result = await run({
|
|
2351
2390
|
prepare: () => prepareOriginal(root, ALL_CHECKS, options, session),
|
|
2352
2391
|
verify: (baseline) => profilePhase("repair.verify", () => verifyOriginal(root, baseline, options, session)),
|
|
2353
2392
|
currentAudit: () => session.audit(ALL_CHECKS)
|
|
2354
2393
|
});
|
|
2355
|
-
|
|
2356
|
-
if (digest(before) !== digest(after)) throw new Error("HEAD, context files or advisory review records changed during verification; retry against stable evidence.");
|
|
2394
|
+
await validate();
|
|
2357
2395
|
return result;
|
|
2358
2396
|
}
|
|
2359
2397
|
async function prepareOriginal(rootDir, checks, options, session) {
|
|
@@ -2375,8 +2413,8 @@ async function prepareOriginal(rootDir, checks, options, session) {
|
|
|
2375
2413
|
}
|
|
2376
2414
|
async function loadRepairBaseline(rootDir, baselinePath) {
|
|
2377
2415
|
const root = await fs10.realpath(rootDir);
|
|
2378
|
-
const declaredRoot =
|
|
2379
|
-
const relative =
|
|
2416
|
+
const declaredRoot = path19.resolve(rootDir);
|
|
2417
|
+
const relative = path19.isAbsolute(baselinePath) ? path19.relative(isWithinRoot(declaredRoot, baselinePath) ? declaredRoot : root, baselinePath) : baselinePath;
|
|
2380
2418
|
const stored = baselineSchema.parse(await readStoreJson(root, relative));
|
|
2381
2419
|
const { digest: savedDigest, ...payload } = stored;
|
|
2382
2420
|
if (digest(payload) !== savedDigest) throw new Error("Repair baseline was modified; use the original baseline.");
|
|
@@ -2551,8 +2589,6 @@ var init_repair = __esm({
|
|
|
2551
2589
|
|
|
2552
2590
|
// src/audit/advisory-review.ts
|
|
2553
2591
|
import fs11 from "fs/promises";
|
|
2554
|
-
import { execFile as execFile8 } from "child_process";
|
|
2555
|
-
import { promisify as promisify8 } from "util";
|
|
2556
2592
|
import { z as z7 } from "zod";
|
|
2557
2593
|
async function readRecord(root, id) {
|
|
2558
2594
|
const raw = await readStoreJson(root, recordPath(id));
|
|
@@ -2747,10 +2783,12 @@ async function reviewAdvisory(rootDir, input) {
|
|
|
2747
2783
|
};
|
|
2748
2784
|
});
|
|
2749
2785
|
}
|
|
2750
|
-
var
|
|
2786
|
+
var git2, hashSchema, commitSchema2, evidenceSchema2, eventSchema2, recordSchema, reviewSummarySchema, advisoryReviewRequest, recordPath;
|
|
2751
2787
|
var init_advisory_review = __esm({
|
|
2752
2788
|
"src/audit/advisory-review.ts"() {
|
|
2753
2789
|
"use strict";
|
|
2790
|
+
init_inspection();
|
|
2791
|
+
init_git_read();
|
|
2754
2792
|
init_findings();
|
|
2755
2793
|
init_deps_changed();
|
|
2756
2794
|
init_inputs();
|
|
@@ -2760,8 +2798,7 @@ var init_advisory_review = __esm({
|
|
|
2760
2798
|
init_store();
|
|
2761
2799
|
init_decisions();
|
|
2762
2800
|
init_drift2();
|
|
2763
|
-
|
|
2764
|
-
git2 = async (root, ...args) => (await execute2("git", args, { cwd: root, timeout: 1e4, maxBuffer: 8 * 1024 * 1024 })).stdout;
|
|
2801
|
+
git2 = async (root, ...args) => (await (["log", "ls-tree", "ls-files", "merge-base"].includes(args[0]) ? inspectionGit : execGit)(args, { cwd: root, timeout: 1e4, maxBuffer: 8 * 1024 * 1024 })).stdout;
|
|
2765
2802
|
hashSchema = z7.string().regex(/^[a-f0-9]{64}$/);
|
|
2766
2803
|
commitSchema2 = z7.string().regex(/^[a-f0-9]{40,64}$/);
|
|
2767
2804
|
evidenceSchema2 = z7.object({
|
|
@@ -2805,12 +2842,12 @@ var init_advisory_review = __esm({
|
|
|
2805
2842
|
|
|
2806
2843
|
// src/audit/audit.ts
|
|
2807
2844
|
import fs12 from "fs/promises";
|
|
2808
|
-
import
|
|
2845
|
+
import path20 from "path";
|
|
2809
2846
|
async function computeAudit(rootDir, options = {}) {
|
|
2810
2847
|
return profilePhase("audit.current", () => auditCurrent(rootDir, options));
|
|
2811
2848
|
}
|
|
2812
2849
|
async function auditCurrent(rootDir, options) {
|
|
2813
|
-
const resolvedRoot =
|
|
2850
|
+
const resolvedRoot = path20.resolve(rootDir);
|
|
2814
2851
|
const [docs, headHash] = await Promise.all([discoverDocs(resolvedRoot), getCurrentGitHash(resolvedRoot)]);
|
|
2815
2852
|
if (docs.length === 0) return null;
|
|
2816
2853
|
const report = {
|
|
@@ -2844,7 +2881,7 @@ async function auditCurrent(rootDir, options) {
|
|
|
2844
2881
|
}
|
|
2845
2882
|
let decisionsPresent = false;
|
|
2846
2883
|
try {
|
|
2847
|
-
await fs12.access(
|
|
2884
|
+
await fs12.access(path20.join(resolvedRoot, ".mason", "decisions"));
|
|
2848
2885
|
decisionsPresent = true;
|
|
2849
2886
|
} catch {
|
|
2850
2887
|
}
|
|
@@ -2889,11 +2926,11 @@ init_audit();
|
|
|
2889
2926
|
init_types();
|
|
2890
2927
|
init_repair();
|
|
2891
2928
|
init_findings();
|
|
2892
|
-
import
|
|
2929
|
+
import path22 from "path";
|
|
2893
2930
|
|
|
2894
2931
|
// src/audit/advisory-cli.ts
|
|
2895
2932
|
init_advisory_review();
|
|
2896
|
-
import
|
|
2933
|
+
import path21 from "path";
|
|
2897
2934
|
import { stripVTControlCharacters } from "util";
|
|
2898
2935
|
var USAGE = `Usage: mason audit review --baseline <path> --finding <id> [options]
|
|
2899
2936
|
|
|
@@ -2939,7 +2976,7 @@ async function runAdvisoryCli(args, io = { out: (text2) => console.log(text2), e
|
|
|
2939
2976
|
note: flags["--note"],
|
|
2940
2977
|
reviewToken: flags["--token"]
|
|
2941
2978
|
};
|
|
2942
|
-
const result = await reviewAdvisory(
|
|
2979
|
+
const result = await reviewAdvisory(path21.resolve(flags["--dir"] ?? process.cwd()), input);
|
|
2943
2980
|
if (json) io.out(JSON.stringify(result, null, 2));
|
|
2944
2981
|
else {
|
|
2945
2982
|
const lines = [`Advisory review: ${result.status}.`];
|
|
@@ -3172,7 +3209,7 @@ async function runAuditCli(argv, io = {
|
|
|
3172
3209
|
io.out(USAGE2);
|
|
3173
3210
|
return 0;
|
|
3174
3211
|
}
|
|
3175
|
-
const rootDir =
|
|
3212
|
+
const rootDir = path22.resolve(args.dir);
|
|
3176
3213
|
if (args.baseline || args.prepareRepair) {
|
|
3177
3214
|
try {
|
|
3178
3215
|
if (args.baseline) {
|