mason-context 0.19.1 → 0.20.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 +25 -0
- package/dist/mason-audit.js +115 -88
- package/dist/mason-audit.js.map +1 -1
- package/dist/mason-drift.js.map +1 -1
- package/dist/mason-hook.js.map +1 -1
- package/dist/mason-mcp.js +939 -577
- package/dist/mason-mcp.js.map +1 -1
- package/dist/mason-review.js.map +1 -1
- package/dist/mason-runtime.js +173 -64
- package/dist/mason-runtime.js.map +1 -1
- package/dist/mason.js +1264 -758
- package/dist/mason.js.map +1 -1
- package/package.json +2 -2
- package/dist/mason-auto.js +0 -6281
- package/dist/mason-auto.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.20.1 — 2026-09-30
|
|
6
|
+
|
|
7
|
+
- Retry temporary Windows lock access failures during concurrent snapshot writes, preserving the acquisition timeout and persistent permission errors.
|
|
8
|
+
- Includes the stats and CLI changes below; 0.20.0 was tagged but not published after its Windows release check failed.
|
|
9
|
+
|
|
10
|
+
## 0.20.0 — not published
|
|
11
|
+
|
|
12
|
+
- Keep optional stats failures from blocking setup, allow disabling with damaged stats storage, and preserve newer audit outcomes when delivery observations arrive late.
|
|
13
|
+
- Remove the `mason-auto` executable. Use `mason setup`, `mason status`, `mason check`, and `mason stats`; hook configuration and execution use `mason auto`.
|
|
14
|
+
- Enable local stats during setup, preserving explicit opt-outs, with summaries for hook finding delivery, observed resolution, returned decision IDs, automation timing, and supplied feedback ratings. Keep uncertain outcomes explicit; no prompts or source contents are stored or uploaded.
|
|
15
|
+
|
|
16
|
+
- Add a controlled agent-behavior benchmark with matched conditions, independent grading, and retained hook evidence. Pilot results establish delivery, not improved outcomes.
|
|
17
|
+
|
|
18
|
+
## 0.19.2 — 2026-09-29
|
|
19
|
+
|
|
20
|
+
- Use operating-system trusted certificates in standalone Mason, preserving bundled and extra certificates, so company TLS certificates work for upgrades and other requests. Report GitHub release lookup failures with their underlying error code and certificate or network guidance.
|
|
21
|
+
|
|
22
|
+
- Capture supported lessons immediately as proposals, keeping unimplemented remedies tentative and acceptance subject to explicit review.
|
|
23
|
+
- Give assistants new or worsened audit findings during the task and show remaining findings at response completion. Keep the existing backlog quiet; explicit checks still report it in full.
|
|
24
|
+
- Preserve notification history across restarts, ignore report-only changes, and retain overflow for later notices. Notices never force another agent turn.
|
|
25
|
+
- Recover notification tracking from unreadable upgrade reports while preserving repair evidence. Deduplicate verification warnings per session.
|
|
26
|
+
- Show uncommitted decision records and pending proposals in explicit status, with paths, ages, and oldest proposals first.
|
|
27
|
+
|
|
3
28
|
## 0.19.1 — 2026-09-25
|
|
4
29
|
|
|
5
30
|
- Match supported dependency changes to named document passages; retain unmatched manifest recency as information without a review obligation. Preserve specific findings, original baselines and prior assessments, and label historical evidence explicitly.
|
package/dist/mason-audit.js
CHANGED
|
@@ -489,17 +489,12 @@ async function withStoreLock(root, directory, run, waitMs = 5e3, label = "Mason
|
|
|
489
489
|
while (!handle) {
|
|
490
490
|
try {
|
|
491
491
|
handle = await fs4.open(file, "wx", 384);
|
|
492
|
-
try {
|
|
493
|
-
await handle.writeFile(JSON.stringify({ pid: process.pid, host: os.hostname() }));
|
|
494
|
-
} catch (error) {
|
|
495
|
-
await handle.close().catch(() => {
|
|
496
|
-
});
|
|
497
|
-
handle = void 0;
|
|
498
|
-
await fs4.rm(file, { force: true }).catch(() => {
|
|
499
|
-
});
|
|
500
|
-
throw error;
|
|
501
|
-
}
|
|
502
492
|
} catch (error) {
|
|
493
|
+
if (process.platform === "win32" && error.code === "EPERM") {
|
|
494
|
+
if (Date.now() >= deadline) throw error;
|
|
495
|
+
await new Promise((resolve) => setTimeout(resolve, 40));
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
503
498
|
if (error.code !== "EEXIST") throw error;
|
|
504
499
|
try {
|
|
505
500
|
const owner = JSON.parse(await fs4.readFile(file, "utf8"));
|
|
@@ -528,6 +523,17 @@ async function withStoreLock(root, directory, run, waitMs = 5e3, label = "Mason
|
|
|
528
523
|
if (Date.now() >= deadline) throw new Error(label + " is busy or its lock needs inspection: " + file + ". " + await lockDiagnostic(file));
|
|
529
524
|
await new Promise((resolve) => setTimeout(resolve, 40));
|
|
530
525
|
}
|
|
526
|
+
if (handle) {
|
|
527
|
+
try {
|
|
528
|
+
await handle.writeFile(JSON.stringify({ pid: process.pid, host: os.hostname() }));
|
|
529
|
+
} catch (error) {
|
|
530
|
+
await handle.close().catch(() => {
|
|
531
|
+
});
|
|
532
|
+
await fs4.rm(file, { force: true }).catch(() => {
|
|
533
|
+
});
|
|
534
|
+
throw error;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
531
537
|
}
|
|
532
538
|
try {
|
|
533
539
|
return await run();
|
|
@@ -2479,8 +2485,30 @@ var init_findings = __esm({
|
|
|
2479
2485
|
}
|
|
2480
2486
|
});
|
|
2481
2487
|
|
|
2482
|
-
// src/automation/
|
|
2488
|
+
// src/automation/notifications.ts
|
|
2483
2489
|
import { z as z5 } from "zod";
|
|
2490
|
+
var conditionSchema, notificationStateSchema;
|
|
2491
|
+
var init_notifications = __esm({
|
|
2492
|
+
"src/automation/notifications.ts"() {
|
|
2493
|
+
"use strict";
|
|
2494
|
+
init_findings();
|
|
2495
|
+
conditionSchema = z5.object({
|
|
2496
|
+
level: z5.number(),
|
|
2497
|
+
facts: z5.array(z5.string()),
|
|
2498
|
+
magnitude: z5.number().optional()
|
|
2499
|
+
});
|
|
2500
|
+
notificationStateSchema = z5.object({
|
|
2501
|
+
version: z5.literal(1),
|
|
2502
|
+
baselineHead: z5.string(),
|
|
2503
|
+
baseline: z5.record(conditionSchema),
|
|
2504
|
+
delivered: z5.record(conditionSchema),
|
|
2505
|
+
cleared: z5.array(z5.string())
|
|
2506
|
+
});
|
|
2507
|
+
}
|
|
2508
|
+
});
|
|
2509
|
+
|
|
2510
|
+
// src/automation/store.ts
|
|
2511
|
+
import { z as z6 } from "zod";
|
|
2484
2512
|
function withLock(root, directory, run, waitMs = 5e3) {
|
|
2485
2513
|
return withStoreLock(root, directory, run, waitMs, "Automation");
|
|
2486
2514
|
}
|
|
@@ -2489,29 +2517,28 @@ var init_store = __esm({
|
|
|
2489
2517
|
"src/automation/store.ts"() {
|
|
2490
2518
|
"use strict";
|
|
2491
2519
|
init_store_lock();
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2520
|
+
init_notifications();
|
|
2521
|
+
hostSchema = z6.enum(["claude", "codex"]);
|
|
2522
|
+
stateSchema = z6.object({
|
|
2523
|
+
version: z6.literal(1),
|
|
2524
|
+
root: z6.string(),
|
|
2525
|
+
gitDir: z6.string(),
|
|
2526
|
+
branch: z6.string(),
|
|
2527
|
+
baselines: z6.array(z6.object({ path: z6.string(), at: z6.string(), event: z6.string(), fingerprint: z6.string() })).max(128),
|
|
2528
|
+
sessions: z6.record(z6.object({
|
|
2500
2529
|
host: hostSchema,
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
mutationObserved: z5.boolean(),
|
|
2507
|
-
pending: z5.record(z5.string()),
|
|
2508
|
-
coverageGaps: z5.array(z5.string()),
|
|
2509
|
-
events: z5.record(z5.object({ at: z5.string(), count: z5.number().int().positive() }))
|
|
2530
|
+
lastUsed: z6.string(),
|
|
2531
|
+
notifiedDiagnostics: z6.array(z6.string()).default([]),
|
|
2532
|
+
pending: z6.record(z6.string()),
|
|
2533
|
+
coverageGaps: z6.array(z6.string()),
|
|
2534
|
+
events: z6.record(z6.object({ at: z6.string(), count: z6.number().int().positive() }))
|
|
2510
2535
|
})),
|
|
2511
|
-
updatedAt:
|
|
2512
|
-
fingerprint:
|
|
2513
|
-
latest:
|
|
2514
|
-
|
|
2536
|
+
updatedAt: z6.string(),
|
|
2537
|
+
fingerprint: z6.string().nullable(),
|
|
2538
|
+
latest: z6.string().nullable(),
|
|
2539
|
+
notifications: notificationStateSchema.optional(),
|
|
2540
|
+
agentNotifications: notificationStateSchema.optional(),
|
|
2541
|
+
analysis: z6.object({ id: z6.string(), fingerprint: z6.string(), completedAt: z6.number(), path: z6.string() }).optional()
|
|
2515
2542
|
});
|
|
2516
2543
|
}
|
|
2517
2544
|
});
|
|
@@ -2533,7 +2560,7 @@ __export(repair_exports, {
|
|
|
2533
2560
|
import fs10 from "fs/promises";
|
|
2534
2561
|
import path20 from "path";
|
|
2535
2562
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2536
|
-
import { z as
|
|
2563
|
+
import { z as z7 } from "zod";
|
|
2537
2564
|
function recheckable(finding) {
|
|
2538
2565
|
return !("confidence" in finding) && finding.resolution === "recheck" && ["deleted-reference", "dead-command", "new-module"].includes(finding.type) && ["missing-path", "missing-script", "unmentioned-dir"].includes(finding.evidence.kind);
|
|
2539
2566
|
}
|
|
@@ -2604,7 +2631,7 @@ async function withRepairSession(root, options, run, validate, cachedAudit) {
|
|
|
2604
2631
|
}
|
|
2605
2632
|
async function prepareOriginal(rootDir, checks, options, session) {
|
|
2606
2633
|
const root = await fs10.realpath(rootDir);
|
|
2607
|
-
const selected =
|
|
2634
|
+
const selected = z7.array(checkSchema).nonempty().parse(checks);
|
|
2608
2635
|
const report = await (session ? session.audit(selected) : stableAudit(root, selected, options));
|
|
2609
2636
|
if (!report) throw new Error("No context files found to prepare a repair.");
|
|
2610
2637
|
if (!report.gitAvailable) throw new Error("Readable Git history is required to prepare a repair.");
|
|
@@ -2761,42 +2788,42 @@ var init_repair = __esm({
|
|
|
2761
2788
|
init_findings();
|
|
2762
2789
|
init_advisory_review();
|
|
2763
2790
|
init_findings();
|
|
2764
|
-
count2 =
|
|
2765
|
-
reportSchema =
|
|
2766
|
-
version:
|
|
2767
|
-
root:
|
|
2768
|
-
gitAvailable:
|
|
2791
|
+
count2 = z7.number().int().nonnegative();
|
|
2792
|
+
reportSchema = z7.object({
|
|
2793
|
+
version: z7.literal(1),
|
|
2794
|
+
root: z7.string(),
|
|
2795
|
+
gitAvailable: z7.literal(true),
|
|
2769
2796
|
headHash: commitSchema.shape.hash,
|
|
2770
|
-
checksRun:
|
|
2771
|
-
docs:
|
|
2772
|
-
path:
|
|
2773
|
-
scope:
|
|
2774
|
-
kind:
|
|
2797
|
+
checksRun: z7.array(checkSchema).nonempty(),
|
|
2798
|
+
docs: z7.array(z7.object({
|
|
2799
|
+
path: z7.string().refine((value) => normalizeRepoPath(value) === value),
|
|
2800
|
+
scope: z7.string().optional(),
|
|
2801
|
+
kind: z7.enum(["instructions", "readme", "guide"]).optional(),
|
|
2775
2802
|
lastCommit: commitSchema.nullable(),
|
|
2776
|
-
dirty:
|
|
2803
|
+
dirty: z7.boolean(),
|
|
2777
2804
|
lineCount: count2
|
|
2778
2805
|
})).nonempty(),
|
|
2779
|
-
decisionsChecked:
|
|
2780
|
-
clean:
|
|
2781
|
-
excludedChecks:
|
|
2782
|
-
issues:
|
|
2783
|
-
advisories:
|
|
2784
|
-
suppressedAdvisories:
|
|
2785
|
-
skippedChecks:
|
|
2806
|
+
decisionsChecked: z7.boolean(),
|
|
2807
|
+
clean: z7.boolean(),
|
|
2808
|
+
excludedChecks: z7.array(z7.object({ check: checkSchema, doc: z7.string() })).optional(),
|
|
2809
|
+
issues: z7.array(issueSchema),
|
|
2810
|
+
advisories: z7.array(advisorySchema),
|
|
2811
|
+
suppressedAdvisories: z7.array(advisorySchema).optional(),
|
|
2812
|
+
skippedChecks: z7.array(z7.object({ check: z7.string(), reason: z7.string(), doc: z7.string().optional() }))
|
|
2786
2813
|
});
|
|
2787
|
-
baselineSchema =
|
|
2788
|
-
kind:
|
|
2789
|
-
version:
|
|
2790
|
-
createdAt:
|
|
2814
|
+
baselineSchema = z7.object({
|
|
2815
|
+
kind: z7.literal("mason-audit-repair"),
|
|
2816
|
+
version: z7.literal(1),
|
|
2817
|
+
createdAt: z7.string().datetime(),
|
|
2791
2818
|
report: reportSchema,
|
|
2792
|
-
digest:
|
|
2819
|
+
digest: z7.string().regex(/^[a-f0-9]{64}$/)
|
|
2793
2820
|
});
|
|
2794
|
-
repairFindingSchema =
|
|
2795
|
-
id:
|
|
2796
|
-
original:
|
|
2797
|
-
status:
|
|
2798
|
-
reason:
|
|
2799
|
-
current:
|
|
2821
|
+
repairFindingSchema = z7.object({
|
|
2822
|
+
id: z7.string(),
|
|
2823
|
+
original: z7.union([issueSchema, advisorySchema]),
|
|
2824
|
+
status: z7.enum(["resolved", "unresolved", "review-required", "unverified"]),
|
|
2825
|
+
reason: z7.string(),
|
|
2826
|
+
current: z7.union([issueSchema, advisorySchema]).optional(),
|
|
2800
2827
|
review: reviewSummarySchema.optional()
|
|
2801
2828
|
});
|
|
2802
2829
|
}
|
|
@@ -2804,7 +2831,7 @@ var init_repair = __esm({
|
|
|
2804
2831
|
|
|
2805
2832
|
// src/audit/advisory-review.ts
|
|
2806
2833
|
import fs11 from "fs/promises";
|
|
2807
|
-
import { z as
|
|
2834
|
+
import { z as z8 } from "zod";
|
|
2808
2835
|
async function readRecord(root, id) {
|
|
2809
2836
|
const raw = await readStoreJson(root, recordPath(id));
|
|
2810
2837
|
if (raw === null) return null;
|
|
@@ -3023,41 +3050,41 @@ var init_advisory_review = __esm({
|
|
|
3023
3050
|
init_decisions();
|
|
3024
3051
|
init_drift2();
|
|
3025
3052
|
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;
|
|
3026
|
-
hashSchema =
|
|
3027
|
-
commitSchema2 =
|
|
3028
|
-
evidenceSchema2 =
|
|
3053
|
+
hashSchema = z8.string().regex(/^[a-f0-9]{64}$/);
|
|
3054
|
+
commitSchema2 = z8.string().regex(/^[a-f0-9]{40,64}$/);
|
|
3055
|
+
evidenceSchema2 = z8.object({
|
|
3029
3056
|
head: commitSchema2,
|
|
3030
3057
|
fingerprint: hashSchema,
|
|
3031
|
-
scope:
|
|
3032
|
-
tree:
|
|
3058
|
+
scope: z8.array(z8.string()).min(1).max(1e3),
|
|
3059
|
+
tree: z8.string().max(2 * 1024 * 1024),
|
|
3033
3060
|
lastScopeCommit: commitSchema2,
|
|
3034
|
-
paths:
|
|
3061
|
+
paths: z8.array(z8.object({ path: z8.string(), exists: z8.boolean() })).max(1e3)
|
|
3035
3062
|
});
|
|
3036
|
-
dismissalReasonSchema =
|
|
3037
|
-
eventSchema2 =
|
|
3038
|
-
at:
|
|
3039
|
-
reviewer:
|
|
3040
|
-
note:
|
|
3041
|
-
outcome:
|
|
3063
|
+
dismissalReasonSchema = z8.enum(["no-dependency-claims", "unrelated-manifest-change"]);
|
|
3064
|
+
eventSchema2 = z8.object({
|
|
3065
|
+
at: z8.string().datetime(),
|
|
3066
|
+
reviewer: z8.string().trim().min(1).max(200).optional(),
|
|
3067
|
+
note: z8.string().trim().min(1).max(2500),
|
|
3068
|
+
outcome: z8.enum(["addressed", "inapplicable", "deferred", "dismissed"]),
|
|
3042
3069
|
reasonCode: dismissalReasonSchema.optional(),
|
|
3043
3070
|
finding: advisorySchema.refine((finding) => finding.evidence.kind !== "decision-anchor", "Decision findings use decision reviews"),
|
|
3044
3071
|
evidence: evidenceSchema2
|
|
3045
3072
|
});
|
|
3046
|
-
recordSchema =
|
|
3047
|
-
reviewSummarySchema =
|
|
3073
|
+
recordSchema = z8.object({ version: z8.literal(1), id: hashSchema, events: z8.array(eventSchema2).min(1).max(200), digest: hashSchema });
|
|
3074
|
+
reviewSummarySchema = z8.object({
|
|
3048
3075
|
id: hashSchema,
|
|
3049
|
-
status:
|
|
3050
|
-
reason:
|
|
3051
|
-
recordPath:
|
|
3052
|
-
reviewer:
|
|
3053
|
-
note:
|
|
3054
|
-
outcome:
|
|
3055
|
-
reviewedHead:
|
|
3076
|
+
status: z8.enum(["current", "reopened", "deferred", "unverified"]),
|
|
3077
|
+
reason: z8.string(),
|
|
3078
|
+
recordPath: z8.string().optional(),
|
|
3079
|
+
reviewer: z8.string().optional(),
|
|
3080
|
+
note: z8.string().optional(),
|
|
3081
|
+
outcome: z8.enum(["addressed", "inapplicable", "deferred", "accepted", "reaffirmed", "retired", "dismissed"]).optional(),
|
|
3082
|
+
reviewedHead: z8.string().optional()
|
|
3056
3083
|
});
|
|
3057
|
-
advisoryReviewRequest =
|
|
3058
|
-
baselinePath:
|
|
3084
|
+
advisoryReviewRequest = z8.object({
|
|
3085
|
+
baselinePath: z8.string().min(1),
|
|
3059
3086
|
findingId: hashSchema,
|
|
3060
|
-
action:
|
|
3087
|
+
action: z8.enum(["prepare", "addressed", "inapplicable", "deferred", "dismiss"]).default("prepare"),
|
|
3061
3088
|
reasonCode: dismissalReasonSchema.optional(),
|
|
3062
3089
|
reviewer: eventSchema2.shape.reviewer.optional(),
|
|
3063
3090
|
note: eventSchema2.shape.note.optional(),
|