mason-context 0.22.0 → 0.23.0
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 +10 -0
- package/dist/mason-audit.js +74 -26
- package/dist/mason-audit.js.map +1 -1
- package/dist/mason-drift.js +42 -19
- package/dist/mason-drift.js.map +1 -1
- package/dist/mason-hook.js +41 -19
- package/dist/mason-hook.js.map +1 -1
- package/dist/mason-mcp.js +699 -173
- package/dist/mason-mcp.js.map +1 -1
- package/dist/mason-review.js +54 -29
- package/dist/mason-review.js.map +1 -1
- package/dist/mason-runtime.js +12 -6
- package/dist/mason-runtime.js.map +1 -1
- package/dist/mason.js +722 -148
- package/dist/mason.js.map +1 -1
- package/package.json +1 -1
package/dist/mason-hook.js
CHANGED
|
@@ -421,6 +421,7 @@ async function storePath(root, relative, createParents = false) {
|
|
|
421
421
|
}
|
|
422
422
|
return current;
|
|
423
423
|
}
|
|
424
|
+
var STORE_MAX_BYTES = 10 * 1024 * 1024;
|
|
424
425
|
|
|
425
426
|
// src/decisions/anchors.ts
|
|
426
427
|
var repoPath = z.string().refine((p) => normalizeRepoPath(p) === p);
|
|
@@ -443,7 +444,12 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
443
444
|
);
|
|
444
445
|
const inventory = access.inventory();
|
|
445
446
|
if (!inventory) throw new Error("Git anchor inventory unavailable");
|
|
446
|
-
const
|
|
447
|
+
const visible = indexMatchingPaths(
|
|
448
|
+
union.map((anchor) => [anchor]),
|
|
449
|
+
inventory
|
|
450
|
+
);
|
|
451
|
+
const hidden = new Set(union.filter((_, index) => !visible[index].length));
|
|
452
|
+
const ignored = hidden.size ? (await inspectionGit(
|
|
447
453
|
[
|
|
448
454
|
"ls-files",
|
|
449
455
|
"-z",
|
|
@@ -451,13 +457,11 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
451
457
|
"--ignored",
|
|
452
458
|
"--exclude-standard",
|
|
453
459
|
"--",
|
|
454
|
-
...
|
|
460
|
+
...[...hidden].map((anchor) => `:(literal)${anchor}`)
|
|
455
461
|
],
|
|
456
462
|
{ cwd: root, maxBuffer: 8 * 1024 * 1024 }
|
|
457
|
-
);
|
|
458
|
-
const files = [
|
|
459
|
-
.../* @__PURE__ */ new Set([...inventory, ...ignored.stdout.split("\0").filter(Boolean)])
|
|
460
|
-
].sort();
|
|
463
|
+
)).stdout.split("\0").filter(Boolean) : [];
|
|
464
|
+
const files = [.../* @__PURE__ */ new Set([...inventory, ...ignored])].sort();
|
|
461
465
|
const patterns = await Promise.all(
|
|
462
466
|
union.map(async (anchor) => {
|
|
463
467
|
const literal = fg3.escapePath(anchor);
|
|
@@ -473,7 +477,7 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
473
477
|
const filesByScope = new Map(
|
|
474
478
|
scopes.map((scope, index) => [JSON.stringify([...new Set(scope)].sort()), indexed[index]])
|
|
475
479
|
);
|
|
476
|
-
return { filesByScope, eligible };
|
|
480
|
+
return { filesByScope, eligible, hidden, ignored: new Set(ignored) };
|
|
477
481
|
};
|
|
478
482
|
return Promise.all(
|
|
479
483
|
scopes.map((scope) => {
|
|
@@ -485,8 +489,10 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
485
489
|
const capture = { anchors, files: {}, complete: true };
|
|
486
490
|
if (!anchors.length) return capture;
|
|
487
491
|
try {
|
|
488
|
-
const { eligible, filesByScope } = await (context ??= prepareContext());
|
|
489
|
-
const files = filesByScope.get(JSON.stringify(anchors))
|
|
492
|
+
const { eligible, filesByScope, hidden, ignored } = await (context ??= prepareContext());
|
|
493
|
+
const files = filesByScope.get(JSON.stringify(anchors)).filter(
|
|
494
|
+
(file) => !ignored.has(file) || anchors.some((anchor) => hidden.has(anchor) && anchorMatches(anchor, file))
|
|
495
|
+
);
|
|
490
496
|
if (files.length > 2e3) return { ...capture, complete: false };
|
|
491
497
|
for (const file of files) {
|
|
492
498
|
const evidence = await inspectionRead(
|
|
@@ -960,7 +966,7 @@ async function loadDecisionStore(rootDir) {
|
|
|
960
966
|
}
|
|
961
967
|
|
|
962
968
|
// src/hook/hook.ts
|
|
963
|
-
import { createHash as
|
|
969
|
+
import { createHash as createHash5 } from "crypto";
|
|
964
970
|
|
|
965
971
|
// src/decisions/drift.ts
|
|
966
972
|
import path8 from "path";
|
|
@@ -1026,6 +1032,26 @@ async function getWorkingTree(resolvedRoot) {
|
|
|
1026
1032
|
}
|
|
1027
1033
|
}
|
|
1028
1034
|
|
|
1035
|
+
// src/decisions/excerpts.ts
|
|
1036
|
+
import { createHash as createHash4 } from "crypto";
|
|
1037
|
+
import { execFile as execFile2 } from "child_process";
|
|
1038
|
+
import { promisify as promisify2 } from "util";
|
|
1039
|
+
var exec = promisify2(execFile2);
|
|
1040
|
+
function driftBaseline(record) {
|
|
1041
|
+
const effective = effectiveDecision(record);
|
|
1042
|
+
const inspection = latestDecisionInspection(
|
|
1043
|
+
record,
|
|
1044
|
+
decisionApproval(effective) === "accepted" ? "operative" : "all"
|
|
1045
|
+
);
|
|
1046
|
+
return {
|
|
1047
|
+
record: effective,
|
|
1048
|
+
capture: inspection?.capture ?? (effective.version === 2 ? effective.capture : void 0),
|
|
1049
|
+
commits: [inspection?.headHash, effective.refreshedHash].filter(
|
|
1050
|
+
(hash) => !!hash && /^[a-f0-9]{40,64}$/.test(hash)
|
|
1051
|
+
)
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1029
1055
|
// src/decisions/drift.ts
|
|
1030
1056
|
async function computeDecisionDrift(rootDir, decisions) {
|
|
1031
1057
|
const resolvedRoot = path8.resolve(rootDir);
|
|
@@ -1089,15 +1115,11 @@ async function computeDecisionDrift(rootDir, decisions) {
|
|
|
1089
1115
|
};
|
|
1090
1116
|
for (const record of store.records) {
|
|
1091
1117
|
if (record.status !== "active") continue;
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1094
|
-
record,
|
|
1095
|
-
decisionApproval(effective) === "accepted" ? "operative" : "all"
|
|
1096
|
-
);
|
|
1097
|
-
const state = await inspect(effective, inspection?.capture);
|
|
1118
|
+
const baseline = driftBaseline(record);
|
|
1119
|
+
const state = await inspect(baseline.record, baseline.capture);
|
|
1098
1120
|
report.freshness[record.id] = state.freshness;
|
|
1099
1121
|
if (state.changedFiles.length) report.staleDecisions[record.id] = state.changedFiles;
|
|
1100
|
-
if (
|
|
1122
|
+
if (baseline.record !== record)
|
|
1101
1123
|
(report.pendingProposals ??= {})[record.id] = await inspect(
|
|
1102
1124
|
record,
|
|
1103
1125
|
latestDecisionInspection(record)?.capture
|
|
@@ -1209,10 +1231,10 @@ async function runHook(stdinText, env = {}) {
|
|
|
1209
1231
|
const stateDir = env.stateDir ?? os2.tmpdir();
|
|
1210
1232
|
const stateFile = path9.join(
|
|
1211
1233
|
stateDir,
|
|
1212
|
-
`mason-hook-${
|
|
1234
|
+
`mason-hook-${createHash5("sha256").update(root).digest("hex").slice(0, 12)}-${stateKey(input)}.json`
|
|
1213
1235
|
);
|
|
1214
1236
|
const injected = await loadInjected(stateFile);
|
|
1215
|
-
const recordKey = (record) => `${record.id}:${
|
|
1237
|
+
const recordKey = (record) => `${record.id}:${createHash5("sha256").update(JSON.stringify(record)).digest("hex")}`;
|
|
1216
1238
|
const previouslyInjected = (record) => [...injected].some((key) => key === record.id || key.startsWith(`${record.id}:`));
|
|
1217
1239
|
const fresh = records.filter(
|
|
1218
1240
|
(r) => !injected.has(recordKey(r)) && (previouslyInjected(r) || r.status === "active" && anchorsCover(r, relPath))
|