mason-context 0.17.4 → 0.18.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 +112 -67
- package/dist/mason-audit.js.map +1 -1
- package/dist/mason-auto.js +56 -11
- package/dist/mason-auto.js.map +1 -1
- package/dist/mason-drift.js +9 -4
- package/dist/mason-drift.js.map +1 -1
- package/dist/mason-hook.js +14 -9
- package/dist/mason-hook.js.map +1 -1
- package/dist/mason-mcp.js +416 -227
- package/dist/mason-mcp.js.map +1 -1
- package/dist/mason-review.js +10 -5
- package/dist/mason-review.js.map +1 -1
- package/dist/mason.js +59 -14
- package/dist/mason.js.map +1 -1
- package/package.json +1 -1
package/dist/mason-auto.js
CHANGED
|
@@ -305,18 +305,34 @@ var init_storage = __esm({
|
|
|
305
305
|
}
|
|
306
306
|
});
|
|
307
307
|
|
|
308
|
-
// src/
|
|
308
|
+
// src/utils/store-lock.ts
|
|
309
309
|
import fs3 from "fs/promises";
|
|
310
310
|
import os from "os";
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
async function lockDiagnostic(file) {
|
|
312
|
+
let reason2;
|
|
313
313
|
try {
|
|
314
|
-
|
|
314
|
+
const owner = JSON.parse(await fs3.readFile(file, "utf8"));
|
|
315
|
+
if (!owner || typeof owner.host !== "string" || !Number.isInteger(owner.pid) || owner.pid <= 0) {
|
|
316
|
+
reason2 = "Lock owner data is incomplete or malformed.";
|
|
317
|
+
} else if (owner.host !== os.hostname()) {
|
|
318
|
+
reason2 = "The lock belongs to another host; its process cannot be checked locally.";
|
|
319
|
+
} else {
|
|
320
|
+
try {
|
|
321
|
+
process.kill(owner.pid, 0);
|
|
322
|
+
reason2 = `Local owner PID ${owner.pid} is still running.`;
|
|
323
|
+
} catch (error) {
|
|
324
|
+
reason2 = error.code === "ESRCH" ? `Local owner PID ${owner.pid} has exited, but lock recovery has not completed.` : `Local owner PID ${owner.pid} could not be checked.`;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
315
327
|
} catch (error) {
|
|
316
|
-
|
|
328
|
+
reason2 = error instanceof SyntaxError ? "Lock owner data is incomplete or malformed." : "Lock owner data could not be read; the lock may have changed.";
|
|
317
329
|
}
|
|
330
|
+
if (await fs3.lstat(file + ".reclaim").then(() => true, () => false)) {
|
|
331
|
+
reason2 += " A recovery guard also needs inspection: " + file + ".reclaim.";
|
|
332
|
+
}
|
|
333
|
+
return reason2 + " Retry if a writer is active. For manual recovery, stop all Mason writers for this checkout, confirm they have exited (including other hosts), then remove only confirmed abandoned lock and lock.reclaim files. See docs/reference.md#snapshot-repairs-and-verification.";
|
|
318
334
|
}
|
|
319
|
-
async function
|
|
335
|
+
async function withStoreLock(root, directory, run, waitMs = 5e3, label = "Mason store") {
|
|
320
336
|
const file = await storePath(root, directory + "/lock", true);
|
|
321
337
|
const deadline = Date.now() + waitMs;
|
|
322
338
|
let handle;
|
|
@@ -359,7 +375,7 @@ async function withLock(root, directory, run, waitMs = 5e3) {
|
|
|
359
375
|
}
|
|
360
376
|
} catch {
|
|
361
377
|
}
|
|
362
|
-
if (Date.now() >= deadline) throw new Error("
|
|
378
|
+
if (Date.now() >= deadline) throw new Error(label + " is busy or its lock needs inspection: " + file + ". " + await lockDiagnostic(file));
|
|
363
379
|
await new Promise((resolve) => setTimeout(resolve, 40));
|
|
364
380
|
}
|
|
365
381
|
}
|
|
@@ -370,11 +386,30 @@ async function withLock(root, directory, run, waitMs = 5e3) {
|
|
|
370
386
|
await fs3.unlink(file);
|
|
371
387
|
}
|
|
372
388
|
}
|
|
389
|
+
var init_store_lock = __esm({
|
|
390
|
+
"src/utils/store-lock.ts"() {
|
|
391
|
+
"use strict";
|
|
392
|
+
init_storage();
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// src/automation/store.ts
|
|
397
|
+
import { z } from "zod";
|
|
398
|
+
function parseState(raw) {
|
|
399
|
+
try {
|
|
400
|
+
return stateSchema.parse(raw);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
throw new Error("Invalid automation state; original evidence was retained.", { cause: error });
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function withLock(root, directory, run, waitMs = 5e3) {
|
|
406
|
+
return withStoreLock(root, directory, run, waitMs, "Automation");
|
|
407
|
+
}
|
|
373
408
|
var hostSchema, events, stateSchema;
|
|
374
409
|
var init_store = __esm({
|
|
375
410
|
"src/automation/store.ts"() {
|
|
376
411
|
"use strict";
|
|
377
|
-
|
|
412
|
+
init_store_lock();
|
|
378
413
|
hostSchema = z.enum(["claude", "codex"]);
|
|
379
414
|
events = ["session_start", "turn_start", "before_tool", "after_tool", "task_end"];
|
|
380
415
|
stateSchema = z.object({
|
|
@@ -1204,6 +1239,14 @@ var init_scope = __esm({
|
|
|
1204
1239
|
}
|
|
1205
1240
|
});
|
|
1206
1241
|
|
|
1242
|
+
// src/snapshot/lock.ts
|
|
1243
|
+
var init_lock = __esm({
|
|
1244
|
+
"src/snapshot/lock.ts"() {
|
|
1245
|
+
"use strict";
|
|
1246
|
+
init_store_lock();
|
|
1247
|
+
}
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1207
1250
|
// src/test-map.ts
|
|
1208
1251
|
import path9 from "path";
|
|
1209
1252
|
async function buildTestMap(dir) {
|
|
@@ -1313,6 +1356,7 @@ var init_snapshot = __esm({
|
|
|
1313
1356
|
init_files();
|
|
1314
1357
|
init_files();
|
|
1315
1358
|
init_storage();
|
|
1359
|
+
init_lock();
|
|
1316
1360
|
init_paths();
|
|
1317
1361
|
init_test_map();
|
|
1318
1362
|
repoPath = z2.string().refine((value) => normalizeRepoPath(value) !== null, "Expected a relative repository path");
|
|
@@ -1320,6 +1364,7 @@ var init_snapshot = __esm({
|
|
|
1320
1364
|
refreshedHash: z2.string().optional(),
|
|
1321
1365
|
verifiedAt: z2.string().optional(),
|
|
1322
1366
|
verifiedHash: z2.string().optional(),
|
|
1367
|
+
verificationToken: z2.string().optional(),
|
|
1323
1368
|
verificationFailed: z2.boolean().optional(),
|
|
1324
1369
|
verificationNote: z2.string().optional()
|
|
1325
1370
|
};
|
|
@@ -3146,7 +3191,7 @@ var init_evidence = __esm({
|
|
|
3146
3191
|
init_dead_command();
|
|
3147
3192
|
init_storage();
|
|
3148
3193
|
init_advisory_review();
|
|
3149
|
-
engineVersion = true ? "0.
|
|
3194
|
+
engineVersion = true ? "0.18.0" : "development";
|
|
3150
3195
|
hash = (value) => createHash3("sha256").update(JSON.stringify(value)).digest("hex");
|
|
3151
3196
|
content = readAuditInput;
|
|
3152
3197
|
cacheSchema = z8.object({ version: z8.literal(1), entries: z8.record(z8.object({ key: z8.string(), result: checkResultSchema })), digest: z8.string() });
|
|
@@ -3831,7 +3876,7 @@ var init_launcher = __esm({
|
|
|
3831
3876
|
"use strict";
|
|
3832
3877
|
init_evidence();
|
|
3833
3878
|
init_model();
|
|
3834
|
-
executingVersion = () => true ? "0.
|
|
3879
|
+
executingVersion = () => true ? "0.18.0" : "development";
|
|
3835
3880
|
mcpCommand = (host) => globalCommand(["--setup-host", host, "mcp"]);
|
|
3836
3881
|
hookCommand = (host) => `mason --setup-host ${host} auto`;
|
|
3837
3882
|
}
|
|
@@ -4200,7 +4245,7 @@ Mason provides recorded decisions and file impact over MCP. A concept map is opt
|
|
|
4200
4245
|
- Before editing a file \u2192 \`get_impact\` to check references, tests, and historical change partners.
|
|
4201
4246
|
- Investigation or correction reveals a reusable project lesson \u2192 \`save_decision\` before finishing. Capture only the lasting constraint and reason, with anchors and known sources, owner, and recorder. This creates a proposal; never infer approval. Preserve uncertain causes and unknown attribution. Route project lessons here; keep personal preferences in agent memory. Skip code summaries, current checkout status, temporary task permissions, session trivia, and secrets. No qualifying lesson means no record.
|
|
4202
4247
|
- Before saving, compare the lesson with matching \`get_context\` records and any pending proposal. If new evidence changes the same lesson's assumptions, scope, or recommended action, revise it with \`save_decision(id: existingId)\`, including when it is accepted. Preserve supported rationale and sources, replace obsolete instructions, and add the new evidence. Create a separate record for a genuinely distinct lesson; skip unchanged restatements. Revision preserves history and leaves the accepted version operative until authorized review.
|
|
4203
|
-
- Consult trust metadata before relying on entries: unknown or changed freshness requires inspection, and failed
|
|
4248
|
+
- Consult trust metadata before relying on entries: unknown or changed freshness requires inspection, stale or unknown map verification requires a fresh evidence review, and a recorded failed verdict means the description must be corrected. Check approval too: proposals are suggestions, legacy records are unreviewed, and accepted decisions are recorded constraints subject to freshness checks. An accepted revision remains operative while a pending proposal is reviewed; keep both versions and their freshness distinct.
|
|
4204
4249
|
- Asked to review or re-verify a decision \u2192 \`review_decision\` first to inspect content, sources, history, and code changes. Record acceptance, reaffirmation, or retirement only when authorized by the user or a cited team review, with the actual reviewer and reason. Never infer approval from unchanged code. Review and commit the local record through the normal project workflow.
|
|
4205
4250
|
- For an architectural overview, use \`get_snapshot\` if a map is available. If \`map.status\` is missing or invalid, use available decisions and source evidence; do not start building a map unless requested.
|
|
4206
4251
|
- \`mason_init\` returns documentation audit and committed-diff review results, plus a short setup guide. Pass \`evidence\` with local CI manifest paths to include test and analysis results; the CLI equivalent is \`mason-review --evidence <manifest>\`. State skipped, unavailable, stale, or unknown checks explicitly. Related accepted decisions identify review context, not proven violations.
|