mason-context 0.22.0 → 0.23.1

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.
@@ -37,8 +37,8 @@ import { stripVTControlCharacters } from "util";
37
37
  // src/review/review.ts
38
38
  import fs7 from "fs/promises";
39
39
  import path11 from "path";
40
- import { execFile as execFile3 } from "child_process";
41
- import { promisify as promisify3 } from "util";
40
+ import { execFile as execFile4 } from "child_process";
41
+ import { promisify as promisify4 } from "util";
42
42
 
43
43
  // src/utils/git-read.ts
44
44
  import { execFile } from "child_process";
@@ -391,11 +391,13 @@ async function storePath(root, relative, createParents = false) {
391
391
  }
392
392
  return current;
393
393
  }
394
- async function readStoreJson(root, relative) {
394
+ var STORE_MAX_BYTES = 10 * 1024 * 1024;
395
+ async function readStoreJson(root, relative, maxBytes = STORE_MAX_BYTES) {
395
396
  try {
396
397
  const file = await storePath(root, relative);
397
- const raw = await readBoundedFile(file, 10 * 1024 * 1024);
398
- if (raw === null) throw new Error("file is not regular or exceeds 10 MiB");
398
+ const raw = await readBoundedFile(file, maxBytes);
399
+ if (raw === null)
400
+ throw new Error(`file is not regular or exceeds ${maxBytes / 1024 / 1024} MiB`);
399
401
  const parsed = JSON.parse(raw);
400
402
  if (parsed === null) throw new Error("expected a JSON object, received null");
401
403
  return parsed;
@@ -572,7 +574,12 @@ async function captureAnchorScopes(root, scopes) {
572
574
  );
573
575
  const inventory = access.inventory();
574
576
  if (!inventory) throw new Error("Git anchor inventory unavailable");
575
- const ignored = await inspectionGit(
577
+ const visible = indexMatchingPaths(
578
+ union.map((anchor) => [anchor]),
579
+ inventory
580
+ );
581
+ const hidden = new Set(union.filter((_, index2) => !visible[index2].length));
582
+ const ignored = hidden.size ? (await inspectionGit(
576
583
  [
577
584
  "ls-files",
578
585
  "-z",
@@ -580,13 +587,11 @@ async function captureAnchorScopes(root, scopes) {
580
587
  "--ignored",
581
588
  "--exclude-standard",
582
589
  "--",
583
- ...union.map((anchor) => `:(literal)${anchor}`)
590
+ ...[...hidden].map((anchor) => `:(literal)${anchor}`)
584
591
  ],
585
592
  { cwd: root, maxBuffer: 8 * 1024 * 1024 }
586
- );
587
- const files = [
588
- .../* @__PURE__ */ new Set([...inventory, ...ignored.stdout.split("\0").filter(Boolean)])
589
- ].sort();
593
+ )).stdout.split("\0").filter(Boolean) : [];
594
+ const files = [.../* @__PURE__ */ new Set([...inventory, ...ignored])].sort();
590
595
  const patterns = await Promise.all(
591
596
  union.map(async (anchor) => {
592
597
  const literal = fg3.escapePath(anchor);
@@ -602,7 +607,7 @@ async function captureAnchorScopes(root, scopes) {
602
607
  const filesByScope = new Map(
603
608
  scopes.map((scope, index2) => [JSON.stringify([...new Set(scope)].sort()), indexed[index2]])
604
609
  );
605
- return { filesByScope, eligible };
610
+ return { filesByScope, eligible, hidden, ignored: new Set(ignored) };
606
611
  };
607
612
  return Promise.all(
608
613
  scopes.map((scope) => {
@@ -614,8 +619,10 @@ async function captureAnchorScopes(root, scopes) {
614
619
  const capture = { anchors, files: {}, complete: true };
615
620
  if (!anchors.length) return capture;
616
621
  try {
617
- const { eligible, filesByScope } = await (context ??= prepareContext());
618
- const files = filesByScope.get(JSON.stringify(anchors));
622
+ const { eligible, filesByScope, hidden, ignored } = await (context ??= prepareContext());
623
+ const files = filesByScope.get(JSON.stringify(anchors)).filter(
624
+ (file) => !ignored.has(file) || anchors.some((anchor) => hidden.has(anchor) && anchorMatches(anchor, file))
625
+ );
619
626
  if (files.length > 2e3) return { ...capture, complete: false };
620
627
  for (const file of files) {
621
628
  const evidence = await inspectionRead(
@@ -1036,6 +1043,28 @@ async function loadDecisionStore(rootDir) {
1036
1043
 
1037
1044
  // src/decisions/drift.ts
1038
1045
  import path8 from "path";
1046
+
1047
+ // src/decisions/excerpts.ts
1048
+ import { createHash as createHash4 } from "crypto";
1049
+ import { execFile as execFile2 } from "child_process";
1050
+ import { promisify as promisify2 } from "util";
1051
+ var exec = promisify2(execFile2);
1052
+ function driftBaseline(record) {
1053
+ const effective = effectiveDecision(record);
1054
+ const inspection = latestDecisionInspection(
1055
+ record,
1056
+ decisionApproval(effective) === "accepted" ? "operative" : "all"
1057
+ );
1058
+ return {
1059
+ record: effective,
1060
+ capture: inspection?.capture ?? (effective.version === 2 ? effective.capture : void 0),
1061
+ commits: [inspection?.headHash, effective.refreshedHash].filter(
1062
+ (hash) => !!hash && /^[a-f0-9]{40,64}$/.test(hash)
1063
+ )
1064
+ };
1065
+ }
1066
+
1067
+ // src/decisions/drift.ts
1039
1068
  async function computeDecisionDrift(rootDir, decisions) {
1040
1069
  const resolvedRoot = path8.resolve(rootDir);
1041
1070
  const store = decisions ? { records: decisions, diagnostics: [] } : await loadDecisionStore(resolvedRoot);
@@ -1098,15 +1127,11 @@ async function computeDecisionDrift(rootDir, decisions) {
1098
1127
  };
1099
1128
  for (const record of store.records) {
1100
1129
  if (record.status !== "active") continue;
1101
- const effective = effectiveDecision(record);
1102
- const inspection = latestDecisionInspection(
1103
- record,
1104
- decisionApproval(effective) === "accepted" ? "operative" : "all"
1105
- );
1106
- const state = await inspect(effective, inspection?.capture);
1130
+ const baseline = driftBaseline(record);
1131
+ const state = await inspect(baseline.record, baseline.capture);
1107
1132
  report.freshness[record.id] = state.freshness;
1108
1133
  if (state.changedFiles.length) report.staleDecisions[record.id] = state.changedFiles;
1109
- if (effective !== record)
1134
+ if (baseline.record !== record)
1110
1135
  (report.pendingProposals ??= {})[record.id] = await inspect(
1111
1136
  record,
1112
1137
  latestDecisionInspection(record)?.capture
@@ -1116,9 +1141,9 @@ async function computeDecisionDrift(rootDir, decisions) {
1116
1141
  }
1117
1142
 
1118
1143
  // src/review/cochange.ts
1119
- import { execFile as execFile2 } from "child_process";
1120
- import { promisify as promisify2 } from "util";
1121
- var exec = promisify2(execFile2);
1144
+ import { execFile as execFile3 } from "child_process";
1145
+ import { promisify as promisify3 } from "util";
1146
+ var exec2 = promisify3(execFile3);
1122
1147
  var HISTORY_COMMITS = 1500;
1123
1148
  var MIN_FILE_COMMITS = 5;
1124
1149
  var MIN_SHARED_COMMITS = 4;
@@ -1126,11 +1151,11 @@ var MIN_COCHANGE_RATE = 0.6;
1126
1151
  var MAX_COMMIT_FILES = 30;
1127
1152
  async function buildMatrix(resolvedRoot) {
1128
1153
  try {
1129
- const { stdout: shallow } = await exec("git", ["rev-parse", "--is-shallow-repository"], {
1154
+ const { stdout: shallow } = await exec2("git", ["rev-parse", "--is-shallow-repository"], {
1130
1155
  cwd: resolvedRoot
1131
1156
  });
1132
1157
  if (shallow.trim() === "true") return null;
1133
- const { stdout } = await exec(
1158
+ const { stdout } = await exec2(
1134
1159
  "git",
1135
1160
  ["log", `-n${HISTORY_COMMITS}`, "--format=%x01", "--name-only", "-M"],
1136
1161
  { cwd: resolvedRoot, maxBuffer: 100 * 1024 * 1024 }
@@ -1858,11 +1883,11 @@ async function collectReviewEvidence(root, manifests, changedFiles, decisions, d
1858
1883
  }
1859
1884
 
1860
1885
  // src/review/review.ts
1861
- var exec2 = promisify3(execFile3);
1886
+ var exec3 = promisify4(execFile4);
1862
1887
  var MAX_ANALYZED_FILES = 50;
1863
1888
  async function resolveMergeBase(resolvedRoot, base, head) {
1864
1889
  try {
1865
- const { stdout } = await exec2("git", ["merge-base", base, head], {
1890
+ const { stdout } = await exec3("git", ["merge-base", base, head], {
1866
1891
  cwd: resolvedRoot
1867
1892
  });
1868
1893
  return stdout.trim() || null;
@@ -1873,7 +1898,7 @@ async function resolveMergeBase(resolvedRoot, base, head) {
1873
1898
  async function defaultBase(resolvedRoot) {
1874
1899
  for (const ref of ["origin/HEAD", "origin/main", "origin/master", "main"]) {
1875
1900
  try {
1876
- await exec2("git", ["rev-parse", "--verify", "--quiet", ref], {
1901
+ await exec3("git", ["rev-parse", "--verify", "--quiet", ref], {
1877
1902
  cwd: resolvedRoot
1878
1903
  });
1879
1904
  return ref;