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.
@@ -36,12 +36,69 @@ var init_paths = __esm({
36
36
  }
37
37
  });
38
38
 
39
+ // src/utils/profile.ts
40
+ import { AsyncLocalStorage } from "async_hooks";
41
+ async function profilePhase(label, run) {
42
+ const phases = profiles.getStore();
43
+ if (!phases) return run();
44
+ const start = performance.now();
45
+ try {
46
+ return await run();
47
+ } finally {
48
+ const timing = phases[label] ??= { calls: 0, totalMs: 0 };
49
+ timing.calls++;
50
+ timing.totalMs += performance.now() - start;
51
+ }
52
+ }
53
+ async function withProfile(run, emit) {
54
+ const phases = {};
55
+ const start = performance.now();
56
+ return profiles.run(phases, async () => {
57
+ try {
58
+ return await run();
59
+ } finally {
60
+ emit(JSON.stringify({ kind: "mason-profile", version: 1, totalMs: performance.now() - start, phases }));
61
+ }
62
+ });
63
+ }
64
+ var profiles;
65
+ var init_profile = __esm({
66
+ "src/utils/profile.ts"() {
67
+ "use strict";
68
+ profiles = new AsyncLocalStorage();
69
+ }
70
+ });
71
+
72
+ // src/utils/git-read.ts
73
+ import { execFile } from "child_process";
74
+ import { promisify } from "util";
75
+ function execGit(args, options) {
76
+ const command = args.find((arg) => !arg.startsWith("-")) ?? "other";
77
+ return profilePhase("git." + (commands.has(command) ? command : "other"), async () => {
78
+ const { input: input2, ...processOptions } = options;
79
+ const operation = execute("git", args, processOptions);
80
+ if (input2 !== void 0) {
81
+ operation.child.stdin.on("error", () => {
82
+ });
83
+ operation.child.stdin.end(input2);
84
+ }
85
+ return operation;
86
+ });
87
+ }
88
+ var execute, commands;
89
+ var init_git_read = __esm({
90
+ "src/utils/git-read.ts"() {
91
+ "use strict";
92
+ init_profile();
93
+ execute = promisify(execFile);
94
+ commands = /* @__PURE__ */ new Set(["rev-parse", "symbolic-ref", "for-each-ref", "ls-files", "check-ignore", "status", "log", "diff", "ls-tree", "show", "merge-base"]);
95
+ }
96
+ });
97
+
39
98
  // src/utils/files.ts
40
99
  import fs from "fs/promises";
41
100
  import { constants } from "fs";
42
101
  import path2 from "path";
43
- import { execFile } from "child_process";
44
- import { promisify } from "util";
45
102
  import fg from "fast-glob";
46
103
  function isSensitiveFile(file) {
47
104
  return file.split(/[\\/]/).some(
@@ -95,12 +152,12 @@ async function createFileAccess(rootDir) {
95
152
  const ignore = [...SOURCE_IGNORE, ...config.ignore ?? []];
96
153
  let gitFiles = null;
97
154
  try {
98
- const { stdout } = await exec("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], { cwd: root, maxBuffer: 50 * 1024 * 1024 });
155
+ const { stdout } = await execGit(["ls-files", "-z", "--cached", "--others", "--exclude-standard"], { cwd: root, maxBuffer: 50 * 1024 * 1024 });
99
156
  gitFiles = new Set(stdout.split("\0").filter(Boolean));
100
157
  } catch {
101
158
  let inGit = false;
102
159
  try {
103
- await exec("git", ["rev-parse", "--git-dir"], { cwd: root });
160
+ await execGit(["rev-parse", "--git-dir"], { cwd: root });
104
161
  inGit = true;
105
162
  } catch {
106
163
  }
@@ -143,12 +200,12 @@ async function createFileAccess(rootDir) {
143
200
  }
144
201
  return { root, config, list, read };
145
202
  }
146
- var exec, SOURCE_EXTENSIONS, SOURCE_GLOB, SOURCE_IGNORE, MAX_SOURCE_BYTES;
203
+ var SOURCE_EXTENSIONS, SOURCE_GLOB, SOURCE_IGNORE, MAX_SOURCE_BYTES;
147
204
  var init_files = __esm({
148
205
  "src/utils/files.ts"() {
149
206
  "use strict";
207
+ init_git_read();
150
208
  init_paths();
151
- exec = promisify(execFile);
152
209
  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"];
153
210
  SOURCE_GLOB = `**/*.{${SOURCE_EXTENSIONS.join(",")}}`;
154
211
  SOURCE_IGNORE = [
@@ -346,39 +403,6 @@ var init_store = __esm({
346
403
  }
347
404
  });
348
405
 
349
- // src/utils/profile.ts
350
- import { AsyncLocalStorage } from "async_hooks";
351
- async function profilePhase(label, run) {
352
- const phases = profiles.getStore();
353
- if (!phases) return run();
354
- const start = performance.now();
355
- try {
356
- return await run();
357
- } finally {
358
- const timing = phases[label] ??= { calls: 0, totalMs: 0 };
359
- timing.calls++;
360
- timing.totalMs += performance.now() - start;
361
- }
362
- }
363
- async function withProfile(run, emit) {
364
- const phases = {};
365
- const start = performance.now();
366
- return profiles.run(phases, async () => {
367
- try {
368
- return await run();
369
- } finally {
370
- emit(JSON.stringify({ kind: "mason-profile", version: 1, totalMs: performance.now() - start, phases }));
371
- }
372
- });
373
- }
374
- var profiles;
375
- var init_profile = __esm({
376
- "src/utils/profile.ts"() {
377
- "use strict";
378
- profiles = new AsyncLocalStorage();
379
- }
380
- });
381
-
382
406
  // src/audit/commands.ts
383
407
  import path4 from "path";
384
408
  function splitCommands(line) {
@@ -603,14 +627,14 @@ function extractClaims(content2) {
603
627
  const ignored = computeIgnoredLines(lines);
604
628
  const paths = /* @__PURE__ */ new Map();
605
629
  const counts = [];
606
- const commands = /* @__PURE__ */ new Map();
630
+ const commands2 = /* @__PURE__ */ new Map();
607
631
  const addPath = (claim) => {
608
632
  const key = [claim.relativeTo ?? "scope", claim.path].join(":");
609
633
  if (!paths.has(key)) paths.set(key, claim);
610
634
  };
611
635
  const addCommand = (claim) => {
612
636
  const key = JSON.stringify([claim.scriptName, claim.directory, claim.scopeUnknown]);
613
- if (!commands.has(key)) commands.set(key, claim);
637
+ if (!commands2.has(key)) commands2.set(key, claim);
614
638
  };
615
639
  const parsed = markdown.parse(lines.map((line, i) => ignored[i] ? "" : line).join("\n"), {});
616
640
  for (const token of parsed) {
@@ -712,7 +736,7 @@ function extractClaims(content2) {
712
736
  return {
713
737
  paths: [...paths.values()],
714
738
  counts,
715
- commands: [...commands.values()]
739
+ commands: [...commands2.values()]
716
740
  };
717
741
  }
718
742
  var ROOT_FILE_NAMES, SHELL_FENCE_INFOS, markdown, COUNT_RE, COUNT_DENYLIST_RE, IGNORE_LINE, IGNORE_START, IGNORE_END;
@@ -762,9 +786,53 @@ var init_claims = __esm({
762
786
  }
763
787
  });
764
788
 
789
+ // src/audit/inspection.ts
790
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
791
+ import path5 from "path";
792
+ function withRepositoryInspection(root, run) {
793
+ return inspections.run({ root: path5.resolve(root), reads: /* @__PURE__ */ new Map() }, run);
794
+ }
795
+ function inspectionRead(root, key, read) {
796
+ const inspection = inspections.getStore();
797
+ if (!inspection || inspection.root !== path5.resolve(root)) return read();
798
+ if (!inspection.reads.has(key)) {
799
+ const pending = read();
800
+ inspection.reads.set(key, pending);
801
+ void pending.catch(() => {
802
+ if (inspection.reads.get(key) === pending) inspection.reads.delete(key);
803
+ });
804
+ }
805
+ return inspection.reads.get(key);
806
+ }
807
+ function inspectionGit(args, options) {
808
+ return inspectionRead(options.cwd, "git:" + JSON.stringify([args, options]), () => execGit(args, options));
809
+ }
810
+ async function auditGitPaths(root, kind) {
811
+ const shared = inspections.getStore()?.root === path5.resolve(root);
812
+ const specs = shared ? [...docSpecs, ...sourceSpecs] : kind === "documents" ? docSpecs : sourceSpecs;
813
+ const limit = kind === "documents" ? 16 * 1024 * 1024 : 32 * 1024 * 1024;
814
+ const { stdout } = await inspectionGit(
815
+ ["ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", ...specs],
816
+ { cwd: root, maxBuffer: shared ? 48 * 1024 * 1024 : limit, timeout: 1e4 }
817
+ );
818
+ const paths = [...new Set(stdout.split("\0").filter(Boolean))].filter((file) => kind === "documents" ? /^(readme|agents|claude)\.md$/i.test(path5.posix.basename(file)) : sourceSuffixes.has(file.slice(file.lastIndexOf("."))));
819
+ if (Buffer.byteLength(paths.join("\0")) > limit) throw new Error("Git " + kind + " inventory exceeds its bounded read limit.");
820
+ return paths.sort();
821
+ }
822
+ var inspections, sourceSpecs, docSpecs, sourceSuffixes;
823
+ var init_inspection = __esm({
824
+ "src/audit/inspection.ts"() {
825
+ "use strict";
826
+ init_git_read();
827
+ init_files();
828
+ inspections = new AsyncLocalStorage2();
829
+ sourceSpecs = SOURCE_EXTENSIONS.map((extension) => `:(glob)**/*.${extension}`);
830
+ docSpecs = [":(icase,glob)**/readme.md", ":(icase,glob)**/agents.md", ":(icase,glob)**/claude.md"];
831
+ sourceSuffixes = new Set(SOURCE_EXTENSIONS.map((extension) => "." + extension));
832
+ }
833
+ });
834
+
765
835
  // src/audit/git.ts
766
- import { execFile as execFile2 } from "child_process";
767
- import { promisify as promisify2 } from "util";
768
836
  function parseCommitLine(line) {
769
837
  const parts = line.split(" ");
770
838
  if (parts.length < 3 || !parts[0]) return null;
@@ -772,8 +840,7 @@ function parseCommitLine(line) {
772
840
  }
773
841
  async function lastCommitOf(resolvedRoot, relPath) {
774
842
  try {
775
- const { stdout } = await exec2(
776
- "git",
843
+ const { stdout } = await inspectionGit(
777
844
  ["log", "-1", `--format=${COMMIT_FORMAT}`, "--", `:(literal)${relPath}`],
778
845
  { cwd: resolvedRoot }
779
846
  );
@@ -785,8 +852,7 @@ async function lastCommitOf(resolvedRoot, relPath) {
785
852
  }
786
853
  async function deletingCommitOf(resolvedRoot, relPath) {
787
854
  try {
788
- const { stdout } = await exec2(
789
- "git",
855
+ const { stdout } = await inspectionGit(
790
856
  [
791
857
  "log",
792
858
  "-1",
@@ -805,8 +871,7 @@ async function deletingCommitOf(resolvedRoot, relPath) {
805
871
  }
806
872
  async function firstCommitOf(resolvedRoot, relPath) {
807
873
  try {
808
- const { stdout } = await exec2(
809
- "git",
874
+ const { stdout } = await inspectionGit(
810
875
  ["log", "--reverse", `--format=${COMMIT_FORMAT}`, "--", `:(literal)${relPath}`],
811
876
  { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }
812
877
  );
@@ -819,8 +884,7 @@ async function firstCommitOf(resolvedRoot, relPath) {
819
884
  async function commitsTouchingSince(resolvedRoot, fromHash, pathspecs) {
820
885
  if (!fromHash || fromHash === "unknown") return null;
821
886
  try {
822
- const { stdout } = await exec2(
823
- "git",
887
+ const { stdout } = await inspectionGit(
824
888
  [
825
889
  "log",
826
890
  `${fromHash}..HEAD`,
@@ -844,11 +908,11 @@ async function commitsTouchingSince(resolvedRoot, fromHash, pathspecs) {
844
908
  return null;
845
909
  }
846
910
  }
847
- var exec2, COMMIT_FORMAT;
911
+ var COMMIT_FORMAT;
848
912
  var init_git = __esm({
849
913
  "src/audit/git.ts"() {
850
914
  "use strict";
851
- exec2 = promisify2(execFile2);
915
+ init_inspection();
852
916
  COMMIT_FORMAT = "%H%x09%cI%x09%s";
853
917
  }
854
918
  });
@@ -856,9 +920,7 @@ var init_git = __esm({
856
920
  // src/audit/inputs.ts
857
921
  import fs4 from "fs/promises";
858
922
  import * as nativeFs from "fs";
859
- import path5 from "path";
860
- import { execFile as execFile3 } from "child_process";
861
- import { promisify as promisify3 } from "util";
923
+ import path6 from "path";
862
924
  import fg2 from "fast-glob";
863
925
  async function auditInputPath(root, file) {
864
926
  if (file === ".") return fs4.realpath(root);
@@ -885,7 +947,7 @@ async function auditGlob(root, patterns, options) {
885
947
  if (Array.isArray(patterns) && !patterns.length) return [];
886
948
  const directories = /* @__PURE__ */ new Set();
887
949
  const readdir2 = ((directory, opts, callback) => {
888
- const relative = path5.relative(root, directory).split(path5.sep).join("/") || ".";
950
+ const relative = path6.relative(root, directory).split(path6.sep).join("/") || ".";
889
951
  directories.add(relative);
890
952
  if (directories.size > MAX_INPUTS) {
891
953
  callback(new Error(`${options.label} exceeds ${MAX_INPUTS.toLocaleString("en-US")} directories while inspecting ${relative}. Narrow this check's inputs.`));
@@ -896,7 +958,7 @@ async function auditGlob(root, patterns, options) {
896
958
  }, callback);
897
959
  });
898
960
  const lstat2 = ((file, callback) => {
899
- const relative = path5.relative(root, file).split(path5.sep).join("/") || ".";
961
+ const relative = path6.relative(root, file).split(path6.sep).join("/") || ".";
900
962
  auditInputPath(root, relative).then(() => nativeFs.lstat(file, callback), callback);
901
963
  });
902
964
  const stream = fg2.stream(patterns, {
@@ -933,62 +995,48 @@ async function auditGlob(root, patterns, options) {
933
995
  return matches.sort();
934
996
  }
935
997
  async function gitSourcePaths(root) {
936
- const { stdout } = await execute(
937
- "git",
938
- [
939
- "ls-files",
940
- "-z",
941
- "--cached",
942
- "--others",
943
- "--exclude-standard",
944
- "--",
945
- ...SOURCE_EXTENSIONS.map((extension) => `:(glob)**/*.${extension}`)
946
- ],
947
- { cwd: root, maxBuffer: 32 * 1024 * 1024, timeout: 1e4 }
948
- );
949
- return [...new Set(stdout.split("\0").filter(Boolean))].sort();
998
+ return auditGitPaths(root, "sources");
950
999
  }
951
1000
  async function gitIgnoredPaths(root, files) {
952
1001
  if (!files.length) return /* @__PURE__ */ new Set();
953
- const operation = execute(
954
- "git",
955
- ["check-ignore", "-z", "--stdin"],
956
- { cwd: root, maxBuffer: 4 * 1024 * 1024, timeout: 1e4 }
957
- );
958
- operation.child.stdin.on("error", () => {
959
- });
960
- operation.child.stdin.end(files.join("\0") + "\0");
961
- try {
962
- return new Set((await operation).stdout.split("\0").filter(Boolean));
963
- } catch (error) {
964
- if (error.code === 1) return /* @__PURE__ */ new Set();
965
- throw error;
1002
+ const ignored = /* @__PURE__ */ new Set();
1003
+ for (let offset = 0; offset < files.length; offset += 1e3) {
1004
+ try {
1005
+ const { stdout } = await execGit(["check-ignore", "-z", "--stdin"], {
1006
+ cwd: root,
1007
+ maxBuffer: 4 * 1024 * 1024,
1008
+ timeout: 1e4,
1009
+ input: files.slice(offset, offset + 1e3).join("\0") + "\0"
1010
+ });
1011
+ for (const file of stdout.split("\0").filter(Boolean)) ignored.add(file);
1012
+ } catch (error) {
1013
+ if (error.code !== 1) throw error;
1014
+ }
966
1015
  }
1016
+ return ignored;
967
1017
  }
968
- var execute, MAX_INPUTS;
1018
+ var MAX_INPUTS;
969
1019
  var init_inputs = __esm({
970
1020
  "src/audit/inputs.ts"() {
971
1021
  "use strict";
972
1022
  init_files();
973
1023
  init_storage();
974
- execute = promisify3(execFile3);
1024
+ init_git_read();
1025
+ init_inspection();
975
1026
  MAX_INPUTS = 1e5;
976
1027
  }
977
1028
  });
978
1029
 
979
1030
  // src/audit/docs.ts
980
1031
  import fs5 from "fs/promises";
981
- import path6 from "path";
982
- import { execFile as execFile4 } from "child_process";
983
- import { promisify as promisify4 } from "util";
1032
+ import path7 from "path";
984
1033
  import fg3 from "fast-glob";
985
1034
  async function dirtyDocs(resolvedRoot, files) {
986
1035
  if (!files.length) return /* @__PURE__ */ new Set();
987
1036
  try {
988
1037
  const dirty = /* @__PURE__ */ new Set();
989
1038
  for (let offset = 0; offset < files.length; offset += 256) {
990
- const { stdout } = await exec3(
991
- "git",
1039
+ const { stdout } = await execGit(
992
1040
  ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", ...files.slice(offset, offset + 256).map((file) => `:(literal)${file}`)],
993
1041
  { cwd: resolvedRoot, maxBuffer: 16 * 1024 * 1024, timeout: 1e4 }
994
1042
  );
@@ -1008,25 +1056,10 @@ async function dirtyDocs(resolvedRoot, files) {
1008
1056
  async function discoverDocPaths(root) {
1009
1057
  let candidates = [];
1010
1058
  try {
1011
- const { stdout } = await exec3(
1012
- "git",
1013
- [
1014
- "ls-files",
1015
- "-z",
1016
- "--cached",
1017
- "--others",
1018
- "--exclude-standard",
1019
- "--",
1020
- ":(icase,glob)**/readme.md",
1021
- ":(icase,glob)**/agents.md",
1022
- ":(icase,glob)**/claude.md"
1023
- ],
1024
- { cwd: root, maxBuffer: 16 * 1024 * 1024, timeout: 1e4 }
1025
- );
1026
- candidates = stdout.split("\0").filter(Boolean);
1059
+ candidates = await auditGitPaths(root, "documents");
1027
1060
  } catch (error) {
1028
1061
  try {
1029
- await exec3("git", ["rev-parse", "--git-dir"], { cwd: root });
1062
+ await execGit(["rev-parse", "--git-dir"], { cwd: root });
1030
1063
  } catch {
1031
1064
  return localDocPaths(root);
1032
1065
  }
@@ -1073,14 +1106,14 @@ async function localDocPaths(root) {
1073
1106
  throw error;
1074
1107
  }
1075
1108
  for (const entry of entries) if (/^(?:agents|claude|readme)\.md$/i.test(entry.name)) {
1076
- paths.push(path6.posix.join(dir, entry.name));
1109
+ paths.push(path7.posix.join(dir, entry.name));
1077
1110
  }
1078
1111
  }
1079
1112
  return paths;
1080
1113
  }
1081
1114
  function documentScope(file) {
1082
- const parent = path6.posix.dirname(file);
1083
- return path6.posix.basename(parent).toLowerCase() === ".claude" ? path6.posix.dirname(parent) : parent;
1115
+ const parent = path7.posix.dirname(file);
1116
+ return path7.posix.basename(parent).toLowerCase() === ".claude" ? path7.posix.dirname(parent) : parent;
1084
1117
  }
1085
1118
  async function discoverDocs(resolvedRoot) {
1086
1119
  return profilePhase("audit.documents", () => readDocs(resolvedRoot));
@@ -1100,7 +1133,7 @@ async function readDocs(resolvedRoot) {
1100
1133
  path: candidate,
1101
1134
  content: content2,
1102
1135
  scope: documentScope(candidate),
1103
- kind: /^readme\.md$/i.test(path6.posix.basename(candidate)) ? "readme" : "instructions",
1136
+ kind: /^readme\.md$/i.test(path7.posix.basename(candidate)) ? "readme" : "instructions",
1104
1137
  lineCount: content2.split("\n").length,
1105
1138
  lastCommit,
1106
1139
  dirty: dirty.has(candidate),
@@ -1110,16 +1143,17 @@ async function readDocs(resolvedRoot) {
1110
1143
  }
1111
1144
  return docs;
1112
1145
  }
1113
- var exec3, DOC_CANDIDATES;
1146
+ var DOC_CANDIDATES;
1114
1147
  var init_docs = __esm({
1115
1148
  "src/audit/docs.ts"() {
1116
1149
  "use strict";
1150
+ init_git_read();
1117
1151
  init_profile();
1118
1152
  init_claims();
1119
1153
  init_git();
1120
1154
  init_inputs();
1121
1155
  init_files();
1122
- exec3 = promisify4(execFile4);
1156
+ init_inspection();
1123
1157
  DOC_CANDIDATES = [
1124
1158
  "AGENTS.md",
1125
1159
  "CLAUDE.md",
@@ -1130,14 +1164,14 @@ var init_docs = __esm({
1130
1164
 
1131
1165
  // src/audit/scope.ts
1132
1166
  import fs6 from "fs/promises";
1133
- import path7 from "path";
1167
+ import path8 from "path";
1134
1168
  function scopedPath(directory, value) {
1135
- if (path7.posix.isAbsolute(value) || value.includes("\\") || /[\x00-\x1f]/.test(value)) return null;
1136
- const resolved = path7.posix.normalize(path7.posix.join(directory, value));
1169
+ if (path8.posix.isAbsolute(value) || value.includes("\\") || /[\x00-\x1f]/.test(value)) return null;
1170
+ const resolved = path8.posix.normalize(path8.posix.join(directory, value));
1137
1171
  return resolved === ".." || resolved.startsWith("../") ? null : resolved;
1138
1172
  }
1139
1173
  function pathClaimScope(doc, claim) {
1140
- const directory = claim.relativeTo === "document" ? path7.posix.dirname(doc) : documentScope(doc);
1174
+ const directory = claim.relativeTo === "document" ? path8.posix.dirname(doc) : documentScope(doc);
1141
1175
  const local = scopedPath(directory, claim.path);
1142
1176
  if (!local) return null;
1143
1177
  const candidates = claim.relativeTo === "document" || directory === "." ? [local] : [...new Set([local, scopedPath(".", claim.path)].filter((p) => p !== null))];
@@ -1171,9 +1205,9 @@ var init_scope = __esm({
1171
1205
  });
1172
1206
 
1173
1207
  // src/test-map.ts
1174
- import path8 from "path";
1208
+ import path9 from "path";
1175
1209
  async function buildTestMap(dir) {
1176
- const rootDir = path8.resolve(dir);
1210
+ const rootDir = path9.resolve(dir);
1177
1211
  const access = await createFileAccess(rootDir);
1178
1212
  const testPatterns = [
1179
1213
  "**/*.test.*",
@@ -1194,7 +1228,7 @@ async function buildTestMap(dir) {
1194
1228
  const sourceByBaseName = /* @__PURE__ */ new Map();
1195
1229
  for (const file of sourceFiles) {
1196
1230
  if (testFiles.includes(file)) continue;
1197
- const baseName = path8.basename(file).replace(/\.[^.]+$/, "");
1231
+ const baseName = path9.basename(file).replace(/\.[^.]+$/, "");
1198
1232
  const existing = sourceByBaseName.get(baseName) ?? [];
1199
1233
  existing.push(file);
1200
1234
  sourceByBaseName.set(baseName, existing);
@@ -1202,7 +1236,7 @@ async function buildTestMap(dir) {
1202
1236
  const paired = [];
1203
1237
  const unmatched = [];
1204
1238
  for (const testFile of testFiles) {
1205
- const testBaseName = path8.basename(testFile).replace(/\.[^.]+$/, "");
1239
+ const testBaseName = path9.basename(testFile).replace(/\.[^.]+$/, "");
1206
1240
  const sourceName = testBaseName.replace(/Test$|Tests$|Spec$|\.test$|\.spec$/, "").replace(/^test_|_test$/, "");
1207
1241
  if (!sourceName) {
1208
1242
  unmatched.push(testFile);
@@ -1210,10 +1244,10 @@ async function buildTestMap(dir) {
1210
1244
  }
1211
1245
  const candidates = sourceByBaseName.get(sourceName);
1212
1246
  if (candidates && candidates.length > 0) {
1213
- const testDir = path8.dirname(testFile);
1247
+ const testDir = path9.dirname(testFile);
1214
1248
  const bestMatch = candidates.reduce((best, candidate) => {
1215
- const candidateDir = path8.dirname(candidate);
1216
- const bestDir = path8.dirname(best);
1249
+ const candidateDir = path9.dirname(candidate);
1250
+ const bestDir = path9.dirname(best);
1217
1251
  const candidateOverlap = commonSegments(testDir, candidateDir);
1218
1252
  const bestOverlap = commonSegments(testDir, bestDir);
1219
1253
  return candidateOverlap > bestOverlap ? candidate : best;
@@ -1247,9 +1281,7 @@ var init_test_map = __esm({
1247
1281
  });
1248
1282
 
1249
1283
  // src/snapshot/snapshot.ts
1250
- import path9 from "path";
1251
- import { execFile as execFile5 } from "child_process";
1252
- import { promisify as promisify5 } from "util";
1284
+ import path10 from "path";
1253
1285
  import { z as z2 } from "zod";
1254
1286
  async function inspectSnapshot(rootDir) {
1255
1287
  try {
@@ -1265,7 +1297,7 @@ async function inspectSnapshot(rootDir) {
1265
1297
  }
1266
1298
  async function getCurrentGitHash(rootDir) {
1267
1299
  try {
1268
- const { stdout } = await exec4("git", ["rev-parse", "HEAD"], {
1300
+ const { stdout } = await execGit(["rev-parse", "HEAD"], {
1269
1301
  cwd: rootDir
1270
1302
  });
1271
1303
  return stdout.trim();
@@ -1273,16 +1305,16 @@ async function getCurrentGitHash(rootDir) {
1273
1305
  return "unknown";
1274
1306
  }
1275
1307
  }
1276
- var exec4, repoPath, verificationFields, featureSchema, flowSchema, snapshotSchema;
1308
+ var repoPath, verificationFields, featureSchema, flowSchema, snapshotSchema;
1277
1309
  var init_snapshot = __esm({
1278
1310
  "src/snapshot/snapshot.ts"() {
1279
1311
  "use strict";
1312
+ init_git_read();
1280
1313
  init_files();
1281
1314
  init_files();
1282
1315
  init_storage();
1283
1316
  init_paths();
1284
1317
  init_test_map();
1285
- exec4 = promisify5(execFile5);
1286
1318
  repoPath = z2.string().refine((value) => normalizeRepoPath(value) !== null, "Expected a relative repository path");
1287
1319
  verificationFields = {
1288
1320
  refreshedHash: z2.string().optional(),
@@ -1312,9 +1344,7 @@ var init_snapshot = __esm({
1312
1344
 
1313
1345
  // src/drift/drift.ts
1314
1346
  import fs7 from "fs/promises";
1315
- import path10 from "path";
1316
- import { execFile as execFile6 } from "child_process";
1317
- import { promisify as promisify6 } from "util";
1347
+ import path11 from "path";
1318
1348
  function parseChanges(output) {
1319
1349
  const fields = output.split("\0");
1320
1350
  const changes = [];
@@ -1335,7 +1365,7 @@ function touchedPaths(changes) {
1335
1365
  async function getChangesWithStatus(resolvedRoot, fromHash, toHash = "HEAD") {
1336
1366
  if (!fromHash || fromHash === "unknown" || fromHash.startsWith("-") || !toHash || toHash === "unknown" || toHash.startsWith("-")) return null;
1337
1367
  try {
1338
- const { stdout } = await exec5("git", ["diff", "--name-status", "-z", "-M", fromHash, toHash, "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 });
1368
+ const { stdout } = await execGit(["diff", "--name-status", "-z", "-M", fromHash, toHash, "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 });
1339
1369
  return parseChanges(stdout);
1340
1370
  } catch {
1341
1371
  return null;
@@ -1344,8 +1374,8 @@ async function getChangesWithStatus(resolvedRoot, fromHash, toHash = "HEAD") {
1344
1374
  async function getWorkingTree(resolvedRoot) {
1345
1375
  try {
1346
1376
  const [diff, untracked] = await Promise.all([
1347
- exec5("git", ["diff", "--name-status", "-z", "-M", "HEAD", "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }),
1348
- exec5("git", ["ls-files", "-z", "--others", "--exclude-standard"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 })
1377
+ execGit(["diff", "--name-status", "-z", "-M", "HEAD", "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }),
1378
+ execGit(["ls-files", "-z", "--others", "--exclude-standard"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 })
1349
1379
  ]);
1350
1380
  const untrackedFiles = untracked.stdout.split("\0").filter((f) => f && !f.startsWith(".mason/"));
1351
1381
  return { available: true, changedFiles: [.../* @__PURE__ */ new Set([...touchedPaths(parseChanges(diff.stdout)), ...untrackedFiles])].sort(), untrackedFiles };
@@ -1353,13 +1383,12 @@ async function getWorkingTree(resolvedRoot) {
1353
1383
  return { available: false, changedFiles: [], untrackedFiles: [] };
1354
1384
  }
1355
1385
  }
1356
- var exec5;
1357
1386
  var init_drift = __esm({
1358
1387
  "src/drift/drift.ts"() {
1359
1388
  "use strict";
1389
+ init_git_read();
1360
1390
  init_snapshot();
1361
1391
  init_paths();
1362
- exec5 = promisify6(execFile6);
1363
1392
  }
1364
1393
  });
1365
1394
 
@@ -1380,7 +1409,7 @@ var init_types = __esm({
1380
1409
  });
1381
1410
 
1382
1411
  // src/audit/checks/deleted-reference.ts
1383
- import path11 from "path";
1412
+ import path12 from "path";
1384
1413
  async function checkDeletedReferences(ctx) {
1385
1414
  const result = emptyResult();
1386
1415
  for (const doc of ctx.docs) {
@@ -1409,7 +1438,7 @@ async function checkDeletedReferences(ctx) {
1409
1438
  const candidates = await Promise.all(scope.candidates.map(async (file) => ({
1410
1439
  file,
1411
1440
  tracked: await lastCommitOf(ctx.root, file),
1412
- parent: await pathExists(ctx.root, path11.posix.dirname(file))
1441
+ parent: await pathExists(ctx.root, path12.posix.dirname(file))
1413
1442
  })));
1414
1443
  const candidate = candidates.find((c) => c.tracked || renames.has(c.file)) ?? candidates.find((c) => c.parent);
1415
1444
  if (!candidate && claim.relativeTo !== "document") continue;
@@ -1449,7 +1478,7 @@ var init_deleted_reference = __esm({
1449
1478
  // src/audit/checks/new-module.ts
1450
1479
  import fg4 from "fast-glob";
1451
1480
  import fs8 from "fs/promises";
1452
- import path12 from "path";
1481
+ import path13 from "path";
1453
1482
  function escapeRegExp(text2) {
1454
1483
  return text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1455
1484
  }
@@ -1487,23 +1516,36 @@ async function checkNewModules(ctx) {
1487
1516
  return result;
1488
1517
  }
1489
1518
  function moduleDocumentation(docs) {
1490
- return docs.map((doc) => doc.content + "\n" + (path12.posix.dirname(doc.path) === "." ? "" : path12.posix.dirname(doc.path) + "/")).join("\n");
1519
+ return docs.map((doc) => doc.content + "\n" + (path13.posix.dirname(doc.path) === "." ? "" : path13.posix.dirname(doc.path) + "/")).join("\n");
1491
1520
  }
1492
- async function moduleCandidates(root, combinedDocs) {
1521
+ function moduleCandidates(root, combinedDocs) {
1522
+ return inspectionRead(root, "modules:" + combinedDocs, () => collectModuleCandidates(root, combinedDocs));
1523
+ }
1524
+ async function collectModuleCandidates(root, combinedDocs) {
1493
1525
  const [config, sourcePaths] = await Promise.all([loadProjectConfig(root), gitSourcePaths(root)]);
1494
1526
  const ignore = [...SOURCE_IGNORE, ...config.ignore ?? []];
1495
1527
  const sources = sourcePaths.filter((file) => !file.split("/").some((part) => part.startsWith(".")));
1496
- const listSubdirs = async (dir) => {
1497
- const entries = await fs8.readdir(await auditInputPath(root, dir), { withFileTypes: true });
1498
- const dirs = entries.filter((entry) => (entry.isDirectory() || entry.isSymbolicLink() && sources.some((file) => file.startsWith(path12.posix.join(dir, entry.name) + "/"))) && !entry.name.startsWith(".") && !DIR_DENYLIST.has(entry.name)).map((entry) => path12.posix.join(dir, entry.name));
1499
- const ignored = await gitIgnoredPaths(root, dirs);
1500
- const visible = new Set(dirs.filter((dir2) => !ignored.has(dir2) || sources.some((file) => file.startsWith(dir2 + "/"))));
1501
- return (await auditGlob(root, dir === "." ? "*" : `${fg4.escapePath(dir)}/*`, {
1502
- ignore,
1503
- onlyDirectories: true,
1504
- label: "Module directory discovery",
1505
- select: (file) => visible.has(file)
1506
- })).map((file) => path12.posix.basename(file));
1528
+ const listSubdirs = async (parents) => {
1529
+ const byParent = /* @__PURE__ */ new Map();
1530
+ for (let offset = 0; offset < parents.length; offset += 16) {
1531
+ await Promise.all(parents.slice(offset, offset + 16).map(async (dir) => {
1532
+ const entries = await fs8.readdir(await auditInputPath(root, dir), { withFileTypes: true });
1533
+ 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));
1534
+ byParent.set(dir, dirs);
1535
+ }));
1536
+ }
1537
+ const ignored = await gitIgnoredPaths(root, [...byParent.values()].flat());
1538
+ const result = /* @__PURE__ */ new Map();
1539
+ for (const dir of parents) {
1540
+ const visible = new Set(byParent.get(dir).filter((candidate) => !ignored.has(candidate) || sources.some((file) => file.startsWith(candidate + "/"))));
1541
+ result.set(dir, (await auditGlob(root, dir === "." ? "*" : `${fg4.escapePath(dir)}/*`, {
1542
+ ignore,
1543
+ onlyDirectories: true,
1544
+ label: "Module directory discovery",
1545
+ select: (file) => visible.has(file)
1546
+ })).map((file) => path13.posix.basename(file)));
1547
+ }
1548
+ return result;
1507
1549
  };
1508
1550
  const countSourceFiles = async (dir) => {
1509
1551
  const files = sources.filter((file) => file.startsWith(dir + "/"));
@@ -1519,14 +1561,16 @@ async function moduleCandidates(root, combinedDocs) {
1519
1561
  return count4;
1520
1562
  };
1521
1563
  const candidates = [];
1522
- for (const topDir of await listSubdirs(".")) {
1564
+ const topDirs = (await listSubdirs(["."])).get(".");
1565
+ const nested = await listSubdirs(topDirs.filter((dir) => isMentioned(combinedDocs, dir)));
1566
+ for (const topDir of topDirs) {
1523
1567
  const topMentioned = isMentioned(combinedDocs, topDir);
1524
1568
  if (!topMentioned) {
1525
1569
  const count4 = await countSourceFiles(topDir);
1526
1570
  if (count4 >= 1) candidates.push({ dir: topDir, sourceFileCount: count4 });
1527
1571
  continue;
1528
1572
  }
1529
- const subdirs = await listSubdirs(topDir);
1573
+ const subdirs = nested.get(topDir);
1530
1574
  const mentioned = subdirs.filter((s) => isMentioned(combinedDocs, s));
1531
1575
  if (mentioned.length < ENUMERATION_THRESHOLD) continue;
1532
1576
  for (const sub of subdirs) {
@@ -1543,6 +1587,7 @@ var DIR_DENYLIST, SECOND_LEVEL_MIN_SOURCE_FILES, ENUMERATION_THRESHOLD;
1543
1587
  var init_new_module = __esm({
1544
1588
  "src/audit/checks/new-module.ts"() {
1545
1589
  "use strict";
1590
+ init_inspection();
1546
1591
  init_files();
1547
1592
  init_inputs();
1548
1593
  init_git();
@@ -1572,7 +1617,7 @@ var init_new_module = __esm({
1572
1617
  });
1573
1618
 
1574
1619
  // src/audit/checks/stale-count.ts
1575
- import path13 from "path";
1620
+ import path14 from "path";
1576
1621
  async function countGradleModules(root) {
1577
1622
  for (const name of ["settings.gradle.kts", "settings.gradle"]) {
1578
1623
  const content2 = await readAuditInput(root, name);
@@ -1606,7 +1651,7 @@ async function countNpmWorkspaces(root) {
1606
1651
  return {
1607
1652
  actual: matched.length,
1608
1653
  countedFrom: "package.json workspaces",
1609
- members: matched.map((m) => path13.dirname(m)).sort()
1654
+ members: matched.map((m) => path14.dirname(m)).sort()
1610
1655
  };
1611
1656
  }
1612
1657
  }
@@ -1637,7 +1682,7 @@ async function countNpmWorkspaces(root) {
1637
1682
  return {
1638
1683
  actual: matched.length,
1639
1684
  countedFrom: "pnpm-workspace.yaml",
1640
- members: matched.map((m) => path13.dirname(m)).sort()
1685
+ members: matched.map((m) => path14.dirname(m)).sort()
1641
1686
  };
1642
1687
  }
1643
1688
  }
@@ -1659,8 +1704,8 @@ async function countCargoCrates(root) {
1659
1704
  ignore: ["**/target/**"],
1660
1705
  label: "Cargo workspace discovery"
1661
1706
  });
1662
- for (const m of matched) members.add(path13.dirname(m));
1663
- } else if (await readAuditInput(root, path13.posix.join(entry, "Cargo.toml")) !== null) {
1707
+ for (const m of matched) members.add(path14.dirname(m));
1708
+ } else if (await readAuditInput(root, path14.posix.join(entry, "Cargo.toml")) !== null) {
1664
1709
  members.add(entry);
1665
1710
  }
1666
1711
  }
@@ -1680,7 +1725,7 @@ async function resolveCountSource(root, claim) {
1680
1725
  }
1681
1726
  async function resolveDocCountSource(root, doc, claim) {
1682
1727
  const scope = documentScope(doc);
1683
- const source = await resolveCountSource(path13.join(root, scope), claim);
1728
+ const source = await resolveCountSource(path14.join(root, scope), claim);
1684
1729
  if (!source || scope === ".") return source;
1685
1730
  return {
1686
1731
  ...source,
@@ -1732,7 +1777,7 @@ var init_stale_count = __esm({
1732
1777
  });
1733
1778
 
1734
1779
  // src/audit/checks/dead-command.ts
1735
- import path14 from "path";
1780
+ import path15 from "path";
1736
1781
  function scriptsOf(raw) {
1737
1782
  try {
1738
1783
  const pkg = JSON.parse(raw);
@@ -1768,7 +1813,7 @@ async function commandInputs(root, docs) {
1768
1813
  }
1769
1814
  let cursor = directory;
1770
1815
  while (true) {
1771
- const manifest = path14.posix.join(cursor, "package.json");
1816
+ const manifest = path15.posix.join(cursor, "package.json");
1772
1817
  scope.candidates.push(manifest);
1773
1818
  const raw = await read(manifest);
1774
1819
  if (raw !== null) {
@@ -1779,7 +1824,7 @@ async function commandInputs(root, docs) {
1779
1824
  break;
1780
1825
  }
1781
1826
  if (claim.directory !== void 0 || cursor === ".") break;
1782
- cursor = path14.posix.dirname(cursor);
1827
+ cursor = path15.posix.dirname(cursor);
1783
1828
  }
1784
1829
  if (!resolution.manifest && !resolution.problem) {
1785
1830
  resolution.problem = `No package.json for the command's scope (${directory}).`;
@@ -1842,10 +1887,8 @@ var init_dead_command = __esm({
1842
1887
  });
1843
1888
 
1844
1889
  // src/audit/release-metadata.ts
1845
- import { execFile as execFile7 } from "child_process";
1846
- import { promisify as promisify7 } from "util";
1847
1890
  async function git(root, args) {
1848
- return (await exec6("git", args, { cwd: root, timeout: 1e4, maxBuffer: 2 * 1024 * 1024 })).stdout;
1891
+ return (await execGit(args, { cwd: root, timeout: 1e4, maxBuffer: 2 * 1024 * 1024 })).stdout;
1849
1892
  }
1850
1893
  function withoutAndroidReleaseValues(text2) {
1851
1894
  if (/\/\*|"""|'''/.test(text2) || !/id\s*\(?\s*["']com\.android\.(application|library)["']/.test(text2)) return null;
@@ -1891,11 +1934,10 @@ async function releaseMetadataOnly(root, commit) {
1891
1934
  return false;
1892
1935
  }
1893
1936
  }
1894
- var exec6;
1895
1937
  var init_release_metadata = __esm({
1896
1938
  "src/audit/release-metadata.ts"() {
1897
1939
  "use strict";
1898
- exec6 = promisify7(execFile7);
1940
+ init_git_read();
1899
1941
  }
1900
1942
  });
1901
1943
 
@@ -1991,7 +2033,7 @@ var init_deps_changed = __esm({
1991
2033
  });
1992
2034
 
1993
2035
  // src/context/lexical.ts
1994
- import path15 from "path";
2036
+ import path16 from "path";
1995
2037
  var init_lexical = __esm({
1996
2038
  "src/context/lexical.ts"() {
1997
2039
  "use strict";
@@ -2175,7 +2217,7 @@ var init_provenance = __esm({
2175
2217
 
2176
2218
  // src/decisions/decisions.ts
2177
2219
  import fs9 from "fs/promises";
2178
- import path16 from "path";
2220
+ import path17 from "path";
2179
2221
  import { createHash } from "crypto";
2180
2222
  import { z as z4 } from "zod";
2181
2223
  async function loadDecisionStore(rootDir) {
@@ -2226,9 +2268,9 @@ var init_decisions = __esm({
2226
2268
  });
2227
2269
 
2228
2270
  // src/decisions/drift.ts
2229
- import path17 from "path";
2271
+ import path18 from "path";
2230
2272
  async function computeDecisionDrift(rootDir, decisions) {
2231
- const resolvedRoot = path17.resolve(rootDir);
2273
+ const resolvedRoot = path18.resolve(rootDir);
2232
2274
  const store = decisions ? { records: decisions, diagnostics: [] } : await loadDecisionStore(resolvedRoot);
2233
2275
  const report = { historyAvailable: true, totalDecisions: store.records.length, staleDecisions: {}, freshness: {}, diagnostics: store.diagnostics };
2234
2276
  const [head, workingTree] = await Promise.all([getCurrentGitHash(resolvedRoot), getWorkingTree(resolvedRoot)]);
@@ -2452,8 +2494,6 @@ var init_findings = __esm({
2452
2494
 
2453
2495
  // src/audit/advisory-review.ts
2454
2496
  import fs10 from "fs/promises";
2455
- import { execFile as execFile8 } from "child_process";
2456
- import { promisify as promisify8 } from "util";
2457
2497
  import { z as z6 } from "zod";
2458
2498
  async function readRecord(root, id) {
2459
2499
  const raw = await readStoreJson(root, recordPath(id));
@@ -2580,10 +2620,12 @@ async function advisoryReviewInventory(root) {
2580
2620
  if (names.length > 5e3) throw new Error("Advisory review inventory exceeds 5,000 records.");
2581
2621
  return Promise.all(names.filter((name) => name.endsWith(".json")).sort().map(async (name) => [name, await readAuditInput(root, ".mason/reviews/advisories/" + name)]));
2582
2622
  }
2583
- var execute2, git2, hashSchema, commitSchema2, evidenceSchema2, eventSchema2, recordSchema, reviewSummarySchema, advisoryReviewRequest, recordPath;
2623
+ var git2, hashSchema, commitSchema2, evidenceSchema2, eventSchema2, recordSchema, reviewSummarySchema, advisoryReviewRequest, recordPath;
2584
2624
  var init_advisory_review = __esm({
2585
2625
  "src/audit/advisory-review.ts"() {
2586
2626
  "use strict";
2627
+ init_inspection();
2628
+ init_git_read();
2587
2629
  init_findings();
2588
2630
  init_deps_changed();
2589
2631
  init_inputs();
@@ -2593,8 +2635,7 @@ var init_advisory_review = __esm({
2593
2635
  init_store();
2594
2636
  init_decisions();
2595
2637
  init_drift2();
2596
- execute2 = promisify8(execFile8);
2597
- git2 = async (root, ...args) => (await execute2("git", args, { cwd: root, timeout: 1e4, maxBuffer: 8 * 1024 * 1024 })).stdout;
2638
+ 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;
2598
2639
  hashSchema = z6.string().regex(/^[a-f0-9]{64}$/);
2599
2640
  commitSchema2 = z6.string().regex(/^[a-f0-9]{40,64}$/);
2600
2641
  evidenceSchema2 = z6.object({
@@ -2638,12 +2679,12 @@ var init_advisory_review = __esm({
2638
2679
 
2639
2680
  // src/audit/audit.ts
2640
2681
  import fs11 from "fs/promises";
2641
- import path18 from "path";
2682
+ import path19 from "path";
2642
2683
  async function computeAudit(rootDir, options = {}) {
2643
2684
  return profilePhase("audit.current", () => auditCurrent(rootDir, options));
2644
2685
  }
2645
2686
  async function auditCurrent(rootDir, options) {
2646
- const resolvedRoot = path18.resolve(rootDir);
2687
+ const resolvedRoot = path19.resolve(rootDir);
2647
2688
  const [docs, headHash] = await Promise.all([discoverDocs(resolvedRoot), getCurrentGitHash(resolvedRoot)]);
2648
2689
  if (docs.length === 0) return null;
2649
2690
  const report = {
@@ -2677,7 +2718,7 @@ async function auditCurrent(rootDir, options) {
2677
2718
  }
2678
2719
  let decisionsPresent = false;
2679
2720
  try {
2680
- await fs11.access(path18.join(resolvedRoot, ".mason", "decisions"));
2721
+ await fs11.access(path19.join(resolvedRoot, ".mason", "decisions"));
2681
2722
  decisionsPresent = true;
2682
2723
  } catch {
2683
2724
  }
@@ -2719,7 +2760,7 @@ var init_audit = __esm({
2719
2760
 
2720
2761
  // src/audit/repair.ts
2721
2762
  import fs12 from "fs/promises";
2722
- import path19 from "path";
2763
+ import path20 from "path";
2723
2764
  import { randomUUID as randomUUID2 } from "crypto";
2724
2765
  import { z as z7 } from "zod";
2725
2766
  function recheckable(finding) {
@@ -2754,8 +2795,8 @@ async function readStableAudit(root, checks, options) {
2754
2795
  }
2755
2796
  return report;
2756
2797
  }
2757
- async function withRepairSession(root, options, run, cachedAudit) {
2758
- const before = await Promise.all([getCurrentGitHash(root), docState(root), advisoryReviewInventory(root).then(digest)]);
2798
+ async function withRepairSession(root, options, run, validate, cachedAudit) {
2799
+ const head = await getCurrentGitHash(root);
2759
2800
  const audits = /* @__PURE__ */ new Map();
2760
2801
  const documents = /* @__PURE__ */ new Map();
2761
2802
  const history = /* @__PURE__ */ new Map();
@@ -2766,9 +2807,9 @@ async function withRepairSession(root, options, run, cachedAudit) {
2766
2807
  };
2767
2808
  const session = {
2768
2809
  audit: (checks) => memo(audits, [...checks].sort().join(","), async () => {
2769
- if (cachedAudit && cachedAudit.headHash === before[0] && cachedAudit.root === root && digest([...checks].sort()) === digest([...cachedAudit.checksRun ?? []].sort())) {
2810
+ if (cachedAudit && cachedAudit.headHash === head && cachedAudit.root === root && digest([...checks].sort()) === digest([...cachedAudit.checksRun ?? []].sort())) {
2770
2811
  const current = structuredClone(cachedAudit);
2771
- const reviews = (await Promise.all(allFindings(current).map((f) => assessAdvisory(root, f, before[0])))).filter((r) => r !== null);
2812
+ const reviews = (await Promise.all(allFindings(current).map((f) => assessAdvisory(root, f, head)))).filter((r) => r !== null);
2772
2813
  delete current.advisoryReviews;
2773
2814
  if (reviews.length) current.advisoryReviews = reviews;
2774
2815
  return current;
@@ -2776,16 +2817,15 @@ async function withRepairSession(root, options, run, cachedAudit) {
2776
2817
  return computeAudit(root, { ...options, checks });
2777
2818
  }),
2778
2819
  document: (file) => memo(documents, file, async () => readBoundedFile(await storePath(root, file), 10 * 1024 * 1024)),
2779
- history: (head) => memo(history, head, () => getChangesWithStatus(root, head)),
2780
- assessment: (dir, finding, head) => memo(assessments, digest([dir, finding, head]), () => assessAdvisory(dir, finding, head))
2820
+ history: (head2) => memo(history, head2, () => getChangesWithStatus(root, head2)),
2821
+ assessment: (dir, finding, head2) => memo(assessments, digest([dir, finding, head2]), () => assessAdvisory(dir, finding, head2))
2781
2822
  };
2782
2823
  const result = await run({
2783
2824
  prepare: () => prepareOriginal(root, ALL_CHECKS, options, session),
2784
2825
  verify: (baseline) => profilePhase("repair.verify", () => verifyOriginal(root, baseline, options, session)),
2785
2826
  currentAudit: () => session.audit(ALL_CHECKS)
2786
2827
  });
2787
- const after = await Promise.all([getCurrentGitHash(root), docState(root), advisoryReviewInventory(root).then(digest)]);
2788
- if (digest(before) !== digest(after)) throw new Error("HEAD, context files or advisory review records changed during verification; retry against stable evidence.");
2828
+ await validate();
2789
2829
  return result;
2790
2830
  }
2791
2831
  async function prepareOriginal(rootDir, checks, options, session) {
@@ -2807,8 +2847,8 @@ async function prepareOriginal(rootDir, checks, options, session) {
2807
2847
  }
2808
2848
  async function loadRepairBaseline(rootDir, baselinePath) {
2809
2849
  const root = await fs12.realpath(rootDir);
2810
- const declaredRoot = path19.resolve(rootDir);
2811
- const relative = path19.isAbsolute(baselinePath) ? path19.relative(isWithinRoot(declaredRoot, baselinePath) ? declaredRoot : root, baselinePath) : baselinePath;
2850
+ const declaredRoot = path20.resolve(rootDir);
2851
+ const relative = path20.isAbsolute(baselinePath) ? path20.relative(isWithinRoot(declaredRoot, baselinePath) ? declaredRoot : root, baselinePath) : baselinePath;
2812
2852
  const stored = baselineSchema.parse(await readStoreJson(root, relative));
2813
2853
  const { digest: savedDigest, ...payload } = stored;
2814
2854
  if (digest(payload) !== savedDigest) throw new Error("Repair baseline was modified; use the original baseline.");
@@ -2967,14 +3007,12 @@ var init_repair = __esm({
2967
3007
 
2968
3008
  // src/automation/evidence.ts
2969
3009
  import fs13 from "fs/promises";
2970
- import path20 from "path";
3010
+ import path21 from "path";
2971
3011
  import { createHash as createHash3 } from "crypto";
2972
- import { execFile as execFile9 } from "child_process";
2973
- import { promisify as promisify9 } from "util";
2974
3012
  import fg5 from "fast-glob";
2975
3013
  import { z as z8 } from "zod";
2976
3014
  async function git3(root, ...args) {
2977
- return profilePhase("automation.git", async () => (await exec7("git", args, { cwd: root, maxBuffer: 16 * 1024 * 1024, timeout: 1e4 })).stdout);
3015
+ return profilePhase("automation.git", async () => (await execGit(args, { cwd: root, maxBuffer: 16 * 1024 * 1024, timeout: 1e4 })).stdout);
2978
3016
  }
2979
3017
  async function workspace(dir) {
2980
3018
  const root = await fs13.realpath((await git3(dir, "rev-parse", "--show-toplevel")).trim());
@@ -2998,7 +3036,7 @@ async function collectInputs(root) {
2998
3036
  const head = headText.trim();
2999
3037
  let shallow = null;
3000
3038
  try {
3001
- shallow = await fs13.readFile(path20.resolve(root, shallowPath.trim()), "utf8");
3039
+ shallow = await fs13.readFile(path21.resolve(root, shallowPath.trim()), "utf8");
3002
3040
  } catch (error) {
3003
3041
  if (error.code !== "ENOENT") throw error;
3004
3042
  }
@@ -3022,7 +3060,7 @@ async function collectInputs(root) {
3022
3060
  if (scope?.candidates.some(gitMetadataPath)) continue;
3023
3061
  for (const candidate of scope?.candidates ?? []) {
3024
3062
  if (optionalMasonPath(candidate)) continue;
3025
- const [filePresent, parentPresent] = await Promise.all([exists(candidate), exists(path20.posix.dirname(candidate))]);
3063
+ const [filePresent, parentPresent] = await Promise.all([exists(candidate), exists(path21.posix.dirname(candidate))]);
3026
3064
  claims.push([candidate, filePresent, parentPresent]);
3027
3065
  }
3028
3066
  }
@@ -3034,7 +3072,7 @@ async function collectInputs(root) {
3034
3072
  if (error.code === "ENOENT") return "absent";
3035
3073
  throw error;
3036
3074
  });
3037
- const [modules, counts, commands, decisionFiles] = await Promise.all([
3075
+ const [modules, counts, commands2, decisionFiles] = await Promise.all([
3038
3076
  combinedDocs ? moduleCandidates(root, combinedDocs) : [],
3039
3077
  Promise.all(countClaims.map(({ doc, claim }) => resolveDocCountSource(root, doc, claim))),
3040
3078
  commandInputs(root, parsedDocs),
@@ -3053,7 +3091,7 @@ async function collectInputs(root) {
3053
3091
  "deleted-reference": hash([common, claims, docStatus]),
3054
3092
  "new-module": hash([common, modules]),
3055
3093
  "stale-count": hash([common, counts]),
3056
- "dead-command": hash([common, commands]),
3094
+ "dead-command": hash([common, commands2]),
3057
3095
  "deps-changed": hash([common, docStatus]),
3058
3096
  "decision-anchor-drift": hash([common, decisionPresence, decisions, status, index2])
3059
3097
  };
@@ -3091,10 +3129,11 @@ function checkCache(raw, inputs) {
3091
3129
  }
3092
3130
  };
3093
3131
  }
3094
- var exec7, engineVersion, hash, content, cacheSchema;
3132
+ var engineVersion, hash, content, cacheSchema;
3095
3133
  var init_evidence = __esm({
3096
3134
  "src/automation/evidence.ts"() {
3097
3135
  "use strict";
3136
+ init_git_read();
3098
3137
  init_profile();
3099
3138
  init_docs();
3100
3139
  init_scope();
@@ -3107,8 +3146,7 @@ var init_evidence = __esm({
3107
3146
  init_dead_command();
3108
3147
  init_storage();
3109
3148
  init_advisory_review();
3110
- exec7 = promisify9(execFile9);
3111
- engineVersion = true ? "0.17.3" : "development";
3149
+ engineVersion = true ? "0.17.4" : "development";
3112
3150
  hash = (value) => createHash3("sha256").update(JSON.stringify(value)).digest("hex");
3113
3151
  content = readAuditInput;
3114
3152
  cacheSchema = z8.object({ version: z8.literal(1), entries: z8.record(z8.object({ key: z8.string(), result: checkResultSchema })), digest: z8.string() });
@@ -3376,12 +3414,12 @@ async function matchingAnalysis(ws, state, inputs) {
3376
3414
  return { analysis: a };
3377
3415
  }
3378
3416
  async function verifyInputs(ws, inputs) {
3379
- return profilePhase("automation.revalidate", async () => {
3417
+ return profilePhase("automation.revalidate", () => withRepositoryInspection(ws.root, async () => {
3380
3418
  const [after, currentWs] = await Promise.all([readInputs(ws.root), workspace(ws.root)]);
3381
3419
  if (after.fingerprint !== inputs.fingerprint || currentWs.directory !== ws.directory) {
3382
3420
  throw new Error("Repository inputs or branch changed during automation; no current verification was recorded. Retry on a stable checkout.");
3383
3421
  }
3384
- });
3422
+ }));
3385
3423
  }
3386
3424
  async function computeAnalysis(ws, state, inputs, event, previousAudit, cacheDiagnostic) {
3387
3425
  const baselines = [...state.baselines];
@@ -3401,7 +3439,10 @@ async function computeAnalysis(ws, state, inputs, event, previousAudit, cacheDia
3401
3439
  capture: "unknown",
3402
3440
  scope: SCOPE
3403
3441
  };
3404
- if (!baselines.length && Object.values(inputs.docs).every((value) => value === null)) return { baselines, report: empty, cache: null };
3442
+ if (!baselines.length && Object.values(inputs.docs).every((value) => value === null)) {
3443
+ await verifyInputs(ws, inputs);
3444
+ return { baselines, report: empty, cache: null };
3445
+ }
3405
3446
  if (ws.branch === "detached" && state.latest) {
3406
3447
  const previous = await readStoreJson(ws.root, state.latest);
3407
3448
  if (!previous?.head || !/^[a-f0-9]{40,64}$/.test(previous.head)) throw new Error("The previous detached checkout evidence is unavailable.");
@@ -3439,7 +3480,7 @@ async function computeAnalysis(ws, state, inputs, event, previousAudit, cacheDia
3439
3480
  }
3440
3481
  currentAudit = await repairs.currentAudit();
3441
3482
  return verifications2;
3442
- }, cachedAudit);
3483
+ }, () => verifyInputs(ws, inputs), cachedAudit);
3443
3484
  const merged = /* @__PURE__ */ new Map();
3444
3485
  for (const verification of verifications) {
3445
3486
  for (const finding of verification.findings) {
@@ -3474,7 +3515,6 @@ async function analyze(ws, inputs, event, startedAt) {
3474
3515
  if (previous && previous.completedAt >= startedAt) return { analysis: previous, shared: true };
3475
3516
  const originalDigest = await baselineDigest(ws, before);
3476
3517
  const computed = await computeAnalysis(ws, before, inputs, event, previous?.currentAudit, diagnostic);
3477
- await verifyInputs(ws, inputs);
3478
3518
  if (originalDigest !== await baselineDigest(ws, before)) throw new Error("Repair baseline was modified during automation; original evidence must be inspected.");
3479
3519
  const id = randomUUID4();
3480
3520
  const analysis = analysisSchema.parse({
@@ -3503,7 +3543,7 @@ async function analyze(ws, inputs, event, startedAt) {
3503
3543
  async function automate(dir, event) {
3504
3544
  const startedAt = Date.now();
3505
3545
  const ws = await profilePhase("automation.workspace", () => workspace(dir));
3506
- return recordExecution(ws.root, ws.directory, event.event, async () => {
3546
+ return recordExecution(ws.root, ws.directory, event.event, () => withRepositoryInspection(ws.root, async () => {
3507
3547
  const inputs = await readInputs(ws.root);
3508
3548
  const result = await profilePhase("automation.analysis", () => analyze(ws, inputs, event, startedAt));
3509
3549
  if (result.shared) {
@@ -3576,7 +3616,7 @@ async function automate(dir, event) {
3576
3616
  await writeStoreJson(ws.root, ws.directory + "/state.json", state);
3577
3617
  return { report, message: notify ? summarize(report) : null, continueOnce };
3578
3618
  }));
3579
- });
3619
+ }));
3580
3620
  }
3581
3621
  async function automationStatus(dir) {
3582
3622
  const ws = await profilePhase("automation.workspace", () => workspace(dir));
@@ -3614,6 +3654,7 @@ var init_runtime = __esm({
3614
3654
  "src/automation/runtime.ts"() {
3615
3655
  "use strict";
3616
3656
  init_profile();
3657
+ init_inspection();
3617
3658
  init_execution();
3618
3659
  init_repair();
3619
3660
  init_types();
@@ -3659,9 +3700,9 @@ var init_runtime = __esm({
3659
3700
 
3660
3701
  // src/automation/hook-root.ts
3661
3702
  import fs15 from "fs/promises";
3662
- import path21 from "path";
3703
+ import path22 from "path";
3663
3704
  async function repositoryRoot(dir) {
3664
- if (!path21.isAbsolute(dir)) throw new Error("Hook input working directory must be absolute.");
3705
+ if (!path22.isAbsolute(dir)) throw new Error("Hook input working directory must be absolute.");
3665
3706
  try {
3666
3707
  return await fs15.realpath((await git3(dir, "rev-parse", "--show-toplevel")).trim());
3667
3708
  } catch (error) {
@@ -3745,8 +3786,8 @@ __export(launcher_exports, {
3745
3786
  mcpCommand: () => mcpCommand,
3746
3787
  prepareLaunch: () => prepareLaunch
3747
3788
  });
3748
- import { execFile as execFile10 } from "child_process";
3749
- import { promisify as promisify10 } from "util";
3789
+ import { execFile as execFile2 } from "child_process";
3790
+ import { promisify as promisify2 } from "util";
3750
3791
  import fs16 from "fs/promises";
3751
3792
  function globalCommand(args, platform = process.platform) {
3752
3793
  return platform === "win32" ? { command: "cmd.exe", args: ["/d", "/s", "/c", "mason", ...args] } : { command: "mason", args };
@@ -3754,7 +3795,7 @@ function globalCommand(args, platform = process.platform) {
3754
3795
  async function installedCommand() {
3755
3796
  const invocation = globalCommand(["internal-integration-version"]);
3756
3797
  try {
3757
- const { stdout } = await promisify10(execFile10)(
3798
+ const { stdout } = await promisify2(execFile2)(
3758
3799
  invocation.command,
3759
3800
  invocation.args,
3760
3801
  { timeout: 5e3, maxBuffer: 8192, windowsHide: true }
@@ -3790,7 +3831,7 @@ var init_launcher = __esm({
3790
3831
  "use strict";
3791
3832
  init_evidence();
3792
3833
  init_model();
3793
- executingVersion = () => true ? "0.17.3" : "development";
3834
+ executingVersion = () => true ? "0.17.4" : "development";
3794
3835
  mcpCommand = (host) => globalCommand(["--setup-host", host, "mcp"]);
3795
3836
  hookCommand = (host) => `mason --setup-host ${host} auto`;
3796
3837
  }
@@ -4006,7 +4047,7 @@ __export(files_exports, {
4006
4047
  readText: () => readText
4007
4048
  });
4008
4049
  import fs18 from "fs/promises";
4009
- import path22 from "path";
4050
+ import path23 from "path";
4010
4051
  import { randomUUID as randomUUID5 } from "crypto";
4011
4052
  async function readText(root, file) {
4012
4053
  try {
@@ -4039,7 +4080,7 @@ async function applyEdit(root, edit) {
4039
4080
  return true;
4040
4081
  }
4041
4082
  const file = await storePath(root, edit.path, true);
4042
- const temporary = path22.join(path22.dirname(file), ".mason-setup-" + randomUUID5() + ".tmp");
4083
+ const temporary = path23.join(path23.dirname(file), ".mason-setup-" + randomUUID5() + ".tmp");
4043
4084
  try {
4044
4085
  const mode = await fs18.stat(file).then((s) => s.mode & 511, () => 384);
4045
4086
  const handle = await fs18.open(temporary, "wx", mode);
@@ -4484,14 +4525,14 @@ async function planTeardown(root, selected) {
4484
4525
  const setup = setupBefore === null ? null : setupSchema.parse(JSON.parse(setupBefore));
4485
4526
  const automationBefore = await read(AUTOMATION_PATH);
4486
4527
  const automation = automationBefore === null ? null : recordSchema2.parse(JSON.parse(automationBefore));
4487
- const commands = (host) => new Set([
4528
+ const commands2 = (host) => new Set([
4488
4529
  automation?.hosts[host]?.command,
4489
4530
  ...ownership.files[configPath(host)]?.hookCommands ?? [],
4490
4531
  ...knownManagedHookCommands(host),
4491
4532
  hookConfig(host, hookCommand(host)).hooks.SessionStart[0].hooks[0].command,
4492
4533
  hookConfig(host).hooks.SessionStart[0].hooks[0].command
4493
4534
  ].filter((command) => !!command));
4494
- const possibleHook = (command, host) => commands(host).has(command) || /\bmason(?:-auto|-hook)?\b/.test(command);
4535
+ const possibleHook = (command, host) => commands2(host).has(command) || /\bmason(?:-auto|-hook)?\b/.test(command);
4495
4536
  const add = (file, before, after, empty) => {
4496
4537
  edits.push({ path: file, before, after: ownership.files[file]?.created && (empty || ownership.files[file].initialHash === hash(before)) ? null : after });
4497
4538
  };
@@ -4555,12 +4596,12 @@ async function planTeardown(root, selected) {
4555
4596
  for (const [event, groups] of Object.entries(config.hooks ?? {})) {
4556
4597
  const known = ownership.files[hookFile]?.hooks?.[event];
4557
4598
  const handlers = groups.flatMap((group) => group.hooks);
4558
- if (known && !handlers.some((handler) => handler.type === "command" && handler.command && commands(host).has(handler.command)) && handlers.some((handler) => !known.includes(hash(handler)))) {
4599
+ if (known && !handlers.some((handler) => handler.type === "command" && handler.command && commands2(host).has(handler.command)) && handlers.some((handler) => !known.includes(hash(handler)))) {
4559
4600
  diagnostics.push({ path: hookFile, message: "A recorded Mason hook is missing beside a new or edited handler (" + event + "); inspect ownership manually." });
4560
4601
  }
4561
4602
  const kept = groups.flatMap((group) => {
4562
4603
  const handlers2 = group.hooks.filter((handler) => {
4563
- if (handler.type === "command" && handler.command && commands(host).has(handler.command)) {
4604
+ if (handler.type === "command" && handler.command && commands2(host).has(handler.command)) {
4564
4605
  changed = true;
4565
4606
  return false;
4566
4607
  }
@@ -4692,13 +4733,13 @@ var init_teardown = __esm({
4692
4733
  });
4693
4734
 
4694
4735
  // src/review/cochange.ts
4695
- import { execFile as execFile11 } from "child_process";
4696
- import { promisify as promisify11 } from "util";
4736
+ import { execFile as execFile3 } from "child_process";
4737
+ import { promisify as promisify3 } from "util";
4697
4738
  async function buildMatrix(resolvedRoot) {
4698
4739
  try {
4699
- const { stdout: shallow } = await exec8("git", ["rev-parse", "--is-shallow-repository"], { cwd: resolvedRoot });
4740
+ const { stdout: shallow } = await exec("git", ["rev-parse", "--is-shallow-repository"], { cwd: resolvedRoot });
4700
4741
  if (shallow.trim() === "true") return null;
4701
- const { stdout } = await exec8(
4742
+ const { stdout } = await exec(
4702
4743
  "git",
4703
4744
  ["log", `-n${HISTORY_COMMITS}`, "--format=%x01", "--name-only", "-M"],
4704
4745
  { cwd: resolvedRoot, maxBuffer: 100 * 1024 * 1024 }
@@ -4754,11 +4795,11 @@ async function findMissingPartners(resolvedRoot, changedFiles, existsOnDisk, all
4754
4795
  findings.sort((a, b) => b.rate - a.rate || b.sharedCommits - a.sharedCommits);
4755
4796
  return findings;
4756
4797
  }
4757
- var exec8, HISTORY_COMMITS, MIN_FILE_COMMITS, MIN_SHARED_COMMITS, MIN_COCHANGE_RATE, MAX_COMMIT_FILES;
4798
+ var exec, HISTORY_COMMITS, MIN_FILE_COMMITS, MIN_SHARED_COMMITS, MIN_COCHANGE_RATE, MAX_COMMIT_FILES;
4758
4799
  var init_cochange = __esm({
4759
4800
  "src/review/cochange.ts"() {
4760
4801
  "use strict";
4761
- exec8 = promisify11(execFile11);
4802
+ exec = promisify3(execFile3);
4762
4803
  HISTORY_COMMITS = 1500;
4763
4804
  MIN_FILE_COMMITS = 5;
4764
4805
  MIN_SHARED_COMMITS = 4;
@@ -5066,10 +5107,10 @@ var init_check = __esm({
5066
5107
  });
5067
5108
 
5068
5109
  // src/review/evidence.ts
5069
- import path23 from "path";
5110
+ import path24 from "path";
5070
5111
  import { z as z22 } from "zod";
5071
5112
  function relativeArtifact(root, file) {
5072
- const relative = path23.isAbsolute(file) ? path23.relative(root, file) : file;
5113
+ const relative = path24.isAbsolute(file) ? path24.relative(root, file) : file;
5073
5114
  const normalized = normalizeRepoPath(relative);
5074
5115
  if (!normalized) throw new Error(`Evidence artifact must be inside the repository: ${file}`);
5075
5116
  return normalized;
@@ -5166,7 +5207,7 @@ async function collectReviewEvidence(root, manifests, changedFiles, decisions, d
5166
5207
  const report = await readStoreJson(root, file);
5167
5208
  if (report === null) throw new Error(`Report artifact is missing: ${file}`);
5168
5209
  const sourceRoot = check.sourceRoot ?? root;
5169
- if (!path23.posix.isAbsolute(sourceRoot) && !/^[A-Za-z]:[\\/]/.test(sourceRoot)) throw new Error("sourceRoot must identify the absolute checkout root on the check runner.");
5210
+ if (!path24.posix.isAbsolute(sourceRoot) && !/^[A-Za-z]:[\\/]/.test(sourceRoot)) throw new Error("sourceRoot must identify the absolute checkout root on the check runner.");
5170
5211
  const parsed = check.report.format === "vitest-json" ? parseVitest(report, sourceRoot) : check.report.format === "mason-check-json" ? parseCheck(report, sourceRoot) : parseSarif(report, sourceRoot);
5171
5212
  result.outcome = parsed.outcome;
5172
5213
  result.counts = parsed.counts;
@@ -5288,12 +5329,12 @@ var init_evidence2 = __esm({
5288
5329
 
5289
5330
  // src/review/review.ts
5290
5331
  import fs19 from "fs/promises";
5291
- import path24 from "path";
5292
- import { execFile as execFile12 } from "child_process";
5293
- import { promisify as promisify12 } from "util";
5332
+ import path25 from "path";
5333
+ import { execFile as execFile4 } from "child_process";
5334
+ import { promisify as promisify4 } from "util";
5294
5335
  async function resolveMergeBase(resolvedRoot, base, head) {
5295
5336
  try {
5296
- const { stdout } = await exec9("git", ["merge-base", base, head], {
5337
+ const { stdout } = await exec2("git", ["merge-base", base, head], {
5297
5338
  cwd: resolvedRoot
5298
5339
  });
5299
5340
  return stdout.trim() || null;
@@ -5304,7 +5345,7 @@ async function resolveMergeBase(resolvedRoot, base, head) {
5304
5345
  async function defaultBase(resolvedRoot) {
5305
5346
  for (const ref of ["origin/HEAD", "origin/main", "origin/master", "main"]) {
5306
5347
  try {
5307
- await exec9("git", ["rev-parse", "--verify", "--quiet", ref], {
5348
+ await exec2("git", ["rev-parse", "--verify", "--quiet", ref], {
5308
5349
  cwd: resolvedRoot
5309
5350
  });
5310
5351
  return ref;
@@ -5317,7 +5358,7 @@ function anchorsTouched(record, changedFiles) {
5317
5358
  return matchingPaths(record.files, changedFiles);
5318
5359
  }
5319
5360
  async function computeReview(rootDir, base, options = {}) {
5320
- const resolvedRoot = path24.resolve(rootDir);
5361
+ const resolvedRoot = path25.resolve(rootDir);
5321
5362
  const head = await getCurrentGitHash(resolvedRoot);
5322
5363
  if (head === "unknown") return null;
5323
5364
  const mergeBase = await resolveMergeBase(resolvedRoot, base, head);
@@ -5367,7 +5408,7 @@ async function computeReview(rootDir, base, options = {}) {
5367
5408
  analyzed,
5368
5409
  async (relPath) => {
5369
5410
  try {
5370
- await fs19.access(path24.join(resolvedRoot, relPath));
5411
+ await fs19.access(path25.join(resolvedRoot, relPath));
5371
5412
  return true;
5372
5413
  } catch {
5373
5414
  return false;
@@ -5400,7 +5441,7 @@ async function computeReview(rootDir, base, options = {}) {
5400
5441
  }
5401
5442
  return finalize();
5402
5443
  }
5403
- var exec9, MAX_ANALYZED_FILES;
5444
+ var exec2, MAX_ANALYZED_FILES;
5404
5445
  var init_review = __esm({
5405
5446
  "src/review/review.ts"() {
5406
5447
  "use strict";
@@ -5412,7 +5453,7 @@ var init_review = __esm({
5412
5453
  init_cochange();
5413
5454
  init_evidence2();
5414
5455
  init_snapshot();
5415
- exec9 = promisify12(execFile12);
5456
+ exec2 = promisify4(execFile4);
5416
5457
  MAX_ANALYZED_FILES = 50;
5417
5458
  }
5418
5459
  });