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.
- package/CHANGELOG.md +15 -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-drift.js
CHANGED
|
@@ -384,11 +384,13 @@ async function storePath(root, relative, createParents = false) {
|
|
|
384
384
|
}
|
|
385
385
|
return current;
|
|
386
386
|
}
|
|
387
|
-
|
|
387
|
+
var STORE_MAX_BYTES = 10 * 1024 * 1024;
|
|
388
|
+
async function readStoreJson(root, relative, maxBytes = STORE_MAX_BYTES) {
|
|
388
389
|
try {
|
|
389
390
|
const file = await storePath(root, relative);
|
|
390
|
-
const raw = await readBoundedFile(file,
|
|
391
|
-
if (raw === null)
|
|
391
|
+
const raw = await readBoundedFile(file, maxBytes);
|
|
392
|
+
if (raw === null)
|
|
393
|
+
throw new Error(`file is not regular or exceeds ${maxBytes / 1024 / 1024} MiB`);
|
|
392
394
|
const parsed = JSON.parse(raw);
|
|
393
395
|
if (parsed === null) throw new Error("expected a JSON object, received null");
|
|
394
396
|
return parsed;
|
|
@@ -712,7 +714,12 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
712
714
|
);
|
|
713
715
|
const inventory = access.inventory();
|
|
714
716
|
if (!inventory) throw new Error("Git anchor inventory unavailable");
|
|
715
|
-
const
|
|
717
|
+
const visible = indexMatchingPaths(
|
|
718
|
+
union.map((anchor) => [anchor]),
|
|
719
|
+
inventory
|
|
720
|
+
);
|
|
721
|
+
const hidden = new Set(union.filter((_, index) => !visible[index].length));
|
|
722
|
+
const ignored = hidden.size ? (await inspectionGit(
|
|
716
723
|
[
|
|
717
724
|
"ls-files",
|
|
718
725
|
"-z",
|
|
@@ -720,13 +727,11 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
720
727
|
"--ignored",
|
|
721
728
|
"--exclude-standard",
|
|
722
729
|
"--",
|
|
723
|
-
...
|
|
730
|
+
...[...hidden].map((anchor) => `:(literal)${anchor}`)
|
|
724
731
|
],
|
|
725
732
|
{ cwd: root, maxBuffer: 8 * 1024 * 1024 }
|
|
726
|
-
);
|
|
727
|
-
const files = [
|
|
728
|
-
.../* @__PURE__ */ new Set([...inventory, ...ignored.stdout.split("\0").filter(Boolean)])
|
|
729
|
-
].sort();
|
|
733
|
+
)).stdout.split("\0").filter(Boolean) : [];
|
|
734
|
+
const files = [.../* @__PURE__ */ new Set([...inventory, ...ignored])].sort();
|
|
730
735
|
const patterns = await Promise.all(
|
|
731
736
|
union.map(async (anchor) => {
|
|
732
737
|
const literal = fg3.escapePath(anchor);
|
|
@@ -742,7 +747,7 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
742
747
|
const filesByScope = new Map(
|
|
743
748
|
scopes.map((scope, index) => [JSON.stringify([...new Set(scope)].sort()), indexed[index]])
|
|
744
749
|
);
|
|
745
|
-
return { filesByScope, eligible };
|
|
750
|
+
return { filesByScope, eligible, hidden, ignored: new Set(ignored) };
|
|
746
751
|
};
|
|
747
752
|
return Promise.all(
|
|
748
753
|
scopes.map((scope) => {
|
|
@@ -754,8 +759,10 @@ async function captureAnchorScopes(root, scopes) {
|
|
|
754
759
|
const capture = { anchors, files: {}, complete: true };
|
|
755
760
|
if (!anchors.length) return capture;
|
|
756
761
|
try {
|
|
757
|
-
const { eligible, filesByScope } = await (context ??= prepareContext());
|
|
758
|
-
const files = filesByScope.get(JSON.stringify(anchors))
|
|
762
|
+
const { eligible, filesByScope, hidden, ignored } = await (context ??= prepareContext());
|
|
763
|
+
const files = filesByScope.get(JSON.stringify(anchors)).filter(
|
|
764
|
+
(file) => !ignored.has(file) || anchors.some((anchor) => hidden.has(anchor) && anchorMatches(anchor, file))
|
|
765
|
+
);
|
|
759
766
|
if (files.length > 2e3) return { ...capture, complete: false };
|
|
760
767
|
for (const file of files) {
|
|
761
768
|
const evidence = await inspectionRead(
|
|
@@ -1092,6 +1099,26 @@ async function loadDecisionStore(rootDir) {
|
|
|
1092
1099
|
);
|
|
1093
1100
|
}
|
|
1094
1101
|
|
|
1102
|
+
// src/decisions/excerpts.ts
|
|
1103
|
+
import { createHash as createHash4 } from "crypto";
|
|
1104
|
+
import { execFile as execFile2 } from "child_process";
|
|
1105
|
+
import { promisify as promisify2 } from "util";
|
|
1106
|
+
var exec = promisify2(execFile2);
|
|
1107
|
+
function driftBaseline(record) {
|
|
1108
|
+
const effective = effectiveDecision(record);
|
|
1109
|
+
const inspection = latestDecisionInspection(
|
|
1110
|
+
record,
|
|
1111
|
+
decisionApproval(effective) === "accepted" ? "operative" : "all"
|
|
1112
|
+
);
|
|
1113
|
+
return {
|
|
1114
|
+
record: effective,
|
|
1115
|
+
capture: inspection?.capture ?? (effective.version === 2 ? effective.capture : void 0),
|
|
1116
|
+
commits: [inspection?.headHash, effective.refreshedHash].filter(
|
|
1117
|
+
(hash) => !!hash && /^[a-f0-9]{40,64}$/.test(hash)
|
|
1118
|
+
)
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1095
1122
|
// src/decisions/drift.ts
|
|
1096
1123
|
async function computeDecisionDrift(rootDir, decisions) {
|
|
1097
1124
|
const resolvedRoot = path8.resolve(rootDir);
|
|
@@ -1155,15 +1182,11 @@ async function computeDecisionDrift(rootDir, decisions) {
|
|
|
1155
1182
|
};
|
|
1156
1183
|
for (const record of store.records) {
|
|
1157
1184
|
if (record.status !== "active") continue;
|
|
1158
|
-
const
|
|
1159
|
-
const
|
|
1160
|
-
record,
|
|
1161
|
-
decisionApproval(effective) === "accepted" ? "operative" : "all"
|
|
1162
|
-
);
|
|
1163
|
-
const state = await inspect(effective, inspection?.capture);
|
|
1185
|
+
const baseline = driftBaseline(record);
|
|
1186
|
+
const state = await inspect(baseline.record, baseline.capture);
|
|
1164
1187
|
report.freshness[record.id] = state.freshness;
|
|
1165
1188
|
if (state.changedFiles.length) report.staleDecisions[record.id] = state.changedFiles;
|
|
1166
|
-
if (
|
|
1189
|
+
if (baseline.record !== record)
|
|
1167
1190
|
(report.pendingProposals ??= {})[record.id] = await inspect(
|
|
1168
1191
|
record,
|
|
1169
1192
|
latestDecisionInspection(record)?.capture
|