mason-context 0.16.1 → 0.16.2
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 +7 -0
- package/README.md +3 -0
- package/dist/mason-auto.js +61 -21
- package/dist/mason-auto.js.map +1 -1
- package/dist/mason-mcp.js +52 -24
- package/dist/mason-mcp.js.map +1 -1
- package/dist/mason.js +116 -71
- package/dist/mason.js.map +1 -1
- package/package.json +2 -1
package/dist/mason-mcp.js
CHANGED
|
@@ -3136,7 +3136,7 @@ var init_evidence = __esm({
|
|
|
3136
3136
|
init_dead_command();
|
|
3137
3137
|
init_storage();
|
|
3138
3138
|
exec11 = promisify12(execFile12);
|
|
3139
|
-
engineVersion = true ? "0.16.
|
|
3139
|
+
engineVersion = true ? "0.16.2" : "development";
|
|
3140
3140
|
hash = (value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex");
|
|
3141
3141
|
content = readAuditInput;
|
|
3142
3142
|
internal = (file) => file === ".mason" || file === ".mason/reports" || file.startsWith(".mason/reports/");
|
|
@@ -3246,9 +3246,29 @@ var runtime_exports = {};
|
|
|
3246
3246
|
__export(runtime_exports, {
|
|
3247
3247
|
automate: () => automate,
|
|
3248
3248
|
automationStatus: () => automationStatus,
|
|
3249
|
+
observeReadOnlyTool: () => observeReadOnlyTool,
|
|
3249
3250
|
summarize: () => summarize
|
|
3250
3251
|
});
|
|
3251
3252
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
3253
|
+
async function observeReadOnlyTool(dir, event) {
|
|
3254
|
+
const ws = await workspace(dir);
|
|
3255
|
+
await withLock(ws.root, ws.directory, async () => {
|
|
3256
|
+
const statePath = ws.directory + "/state.json";
|
|
3257
|
+
const raw = await readStoreJson(ws.root, statePath);
|
|
3258
|
+
if (raw === null) return;
|
|
3259
|
+
const state = parseState(raw);
|
|
3260
|
+
if (state.root !== ws.root || state.gitDir !== ws.gitDir || state.branch !== ws.branch) {
|
|
3261
|
+
throw new Error("Automation state belongs to another branch or worktree; original evidence was retained.");
|
|
3262
|
+
}
|
|
3263
|
+
const session = event.host && event.sessionId ? state.sessions[hash([event.host, event.sessionId])] : null;
|
|
3264
|
+
if (!session) return;
|
|
3265
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3266
|
+
session.lastUsed = now;
|
|
3267
|
+
session.events[event.event] = { at: now, count: (session.events[event.event]?.count ?? 0) + 1 };
|
|
3268
|
+
await writeStoreJson(ws.root, statePath, state);
|
|
3269
|
+
});
|
|
3270
|
+
return { root: ws.root, directory: ws.directory };
|
|
3271
|
+
}
|
|
3252
3272
|
function summarize(report) {
|
|
3253
3273
|
const open = report.findings.filter((f) => f.status !== "resolved");
|
|
3254
3274
|
return [
|
|
@@ -3472,8 +3492,15 @@ var init_runtime = __esm({
|
|
|
3472
3492
|
|
|
3473
3493
|
// src/automation/adapters.ts
|
|
3474
3494
|
import { z as z9 } from "zod";
|
|
3495
|
+
function managedHookCommand(host, platform = process.platform) {
|
|
3496
|
+
const command = `mason --setup-host ${host} auto hook --host ${host}`;
|
|
3497
|
+
return platform === "win32" ? `cmd.exe /d /s /c "where mason >nul 2>nul & if errorlevel 1 (exit /b 0) else (${command})"` : `if command -v mason >/dev/null 2>&1; then ${command}; fi`;
|
|
3498
|
+
}
|
|
3499
|
+
function knownManagedHookCommands(host) {
|
|
3500
|
+
return [managedHookCommand(host, "linux"), managedHookCommand(host, "win32"), `mason --setup-host ${host} auto hook --host ${host}`];
|
|
3501
|
+
}
|
|
3475
3502
|
function hookConfig(host, command = "npx --no-install --package mason-context mason-auto") {
|
|
3476
|
-
const handler = { type: "command", command: command + " hook --host " + host, timeout: 30 };
|
|
3503
|
+
const handler = { type: "command", command: command === `mason --setup-host ${host} auto` ? managedHookCommand(host) : command + " hook --host " + host, timeout: 30 };
|
|
3477
3504
|
return { hooks: Object.fromEntries(HOOK_EVENTS.map((name) => [
|
|
3478
3505
|
name,
|
|
3479
3506
|
[{ ...["PreToolUse", "PostToolUse"].includes(name) ? { matcher: ".*" } : {}, hooks: [{ ...handler }] }]
|
|
@@ -3602,7 +3629,7 @@ async function planAutomationInstall(root, host, command) {
|
|
|
3602
3629
|
const previous = record.hosts[host]?.command;
|
|
3603
3630
|
const ownershipText = await readText(root, OWNERSHIP_PATH);
|
|
3604
3631
|
const pending = ownershipText === null ? [] : ownershipSchema.parse(JSON.parse(ownershipText)).files[file]?.hookCommands ?? [];
|
|
3605
|
-
const owned = /* @__PURE__ */ new Set([previous, ...pending, newCommand]);
|
|
3632
|
+
const owned = /* @__PURE__ */ new Set([previous, ...pending, newCommand, ...knownManagedHookCommands(host)]);
|
|
3606
3633
|
const hooks = existing.hooks ?? {};
|
|
3607
3634
|
for (const event of HOOK_EVENTS) {
|
|
3608
3635
|
hooks[event] = (hooks[event] ?? []).map((group) => ({
|
|
@@ -3728,6 +3755,7 @@ var init_model = __esm({
|
|
|
3728
3755
|
// src/setup/launcher.ts
|
|
3729
3756
|
import { execFile as execFile13 } from "child_process";
|
|
3730
3757
|
import { promisify as promisify13 } from "util";
|
|
3758
|
+
import fs16 from "fs/promises";
|
|
3731
3759
|
function globalCommand(args, platform = process.platform) {
|
|
3732
3760
|
return platform === "win32" ? { command: "cmd.exe", args: ["/d", "/s", "/c", "mason", ...args] } : { command: "mason", args };
|
|
3733
3761
|
}
|
|
@@ -3752,7 +3780,7 @@ var init_launcher = __esm({
|
|
|
3752
3780
|
"use strict";
|
|
3753
3781
|
init_evidence();
|
|
3754
3782
|
init_model();
|
|
3755
|
-
executingVersion = () => true ? "0.16.
|
|
3783
|
+
executingVersion = () => true ? "0.16.2" : "development";
|
|
3756
3784
|
mcpCommand = (host) => globalCommand(["--setup-host", host, "mcp"]);
|
|
3757
3785
|
hookCommand = (host) => `mason --setup-host ${host} auto`;
|
|
3758
3786
|
}
|
|
@@ -4537,7 +4565,7 @@ var init_evidence2 = __esm({
|
|
|
4537
4565
|
});
|
|
4538
4566
|
|
|
4539
4567
|
// src/review/review.ts
|
|
4540
|
-
import
|
|
4568
|
+
import fs17 from "fs/promises";
|
|
4541
4569
|
import path22 from "path";
|
|
4542
4570
|
import { execFile as execFile15 } from "child_process";
|
|
4543
4571
|
import { promisify as promisify15 } from "util";
|
|
@@ -4617,7 +4645,7 @@ async function computeReview(rootDir, base, options = {}) {
|
|
|
4617
4645
|
analyzed,
|
|
4618
4646
|
async (relPath) => {
|
|
4619
4647
|
try {
|
|
4620
|
-
await
|
|
4648
|
+
await fs17.access(path22.join(resolvedRoot, relPath));
|
|
4621
4649
|
return true;
|
|
4622
4650
|
} catch {
|
|
4623
4651
|
return false;
|
|
@@ -5093,12 +5121,12 @@ __export(assemble_exports, {
|
|
|
5093
5121
|
assembleContext: () => assembleContext
|
|
5094
5122
|
});
|
|
5095
5123
|
import path25 from "path";
|
|
5096
|
-
import
|
|
5124
|
+
import fs18 from "fs/promises";
|
|
5097
5125
|
async function collectImpact(root, candidates) {
|
|
5098
5126
|
const targets = /* @__PURE__ */ new Set();
|
|
5099
5127
|
let sourceFiles;
|
|
5100
5128
|
for (const candidate of sanitizeRepoPaths(candidates)) {
|
|
5101
|
-
const stat = await
|
|
5129
|
+
const stat = await fs18.stat(path25.join(root, candidate)).catch(() => null);
|
|
5102
5130
|
if (stat?.isDirectory()) {
|
|
5103
5131
|
sourceFiles ??= await (await createFileAccess(root)).list();
|
|
5104
5132
|
for (const file of sourceFiles) {
|
|
@@ -5325,7 +5353,7 @@ __export(observations_exports, {
|
|
|
5325
5353
|
observeActivation: () => observeActivation,
|
|
5326
5354
|
readObservation: () => readObservation
|
|
5327
5355
|
});
|
|
5328
|
-
import
|
|
5356
|
+
import fs19 from "fs/promises";
|
|
5329
5357
|
import { z as z18 } from "zod";
|
|
5330
5358
|
function observationPath(directory, host, revision, version = executingVersion()) {
|
|
5331
5359
|
return `${directory}/activation/${host}-${revision}-${hash(version).slice(0, 12)}.json`;
|
|
@@ -5341,9 +5369,9 @@ async function observeActivation(dir, event, options = {}) {
|
|
|
5341
5369
|
const host = process.env.MASON_SETUP_HOST, revision = process.env.MASON_SETUP_REVISION;
|
|
5342
5370
|
if (host !== "codex" && host !== "claude" || !revision || !process.env.MASON_SETUP_ROOT) return null;
|
|
5343
5371
|
try {
|
|
5344
|
-
const capturedDirectory = options.reportPath?.match(/^(\.mason\/reports\/automation\/[a-f0-9]{24})\/checks\//)?.[1];
|
|
5345
|
-
const ws = capturedDirectory ? { root: await
|
|
5346
|
-
if (ws.root !== await
|
|
5372
|
+
const capturedDirectory = options.directory?.match(/^\.mason\/reports\/automation\/[a-f0-9]{24}$/)?.[0] ?? options.reportPath?.match(/^(\.mason\/reports\/automation\/[a-f0-9]{24})\/checks\//)?.[1];
|
|
5373
|
+
const ws = capturedDirectory ? { root: await fs19.realpath(dir), directory: capturedDirectory } : await workspace(dir);
|
|
5374
|
+
if (ws.root !== await fs19.realpath(process.env.MASON_SETUP_ROOT)) return null;
|
|
5347
5375
|
const setup = await loadSetup(ws.root);
|
|
5348
5376
|
if (setup?.hosts[host]?.revision !== revision) return "Mason setup changed; restart the assistant to observe the current integration.";
|
|
5349
5377
|
const directory = ws.directory + "/activation";
|
|
@@ -5429,7 +5457,7 @@ async function setupStatus(dir) {
|
|
|
5429
5457
|
version: 1,
|
|
5430
5458
|
status: pending.length ? "incomplete" : "not-configured",
|
|
5431
5459
|
hosts: {},
|
|
5432
|
-
next: pending.length ? "Setup did not finish. Rerun mason-auto setup --host " + pending[0] + " to resume using the retained original evidence." : "Run mason
|
|
5460
|
+
next: pending.length ? "Setup did not finish. Rerun mason-auto setup --host " + pending[0] + " to resume using the retained original evidence." : "Project hooks are inactive until local setup. Run mason setup --host codex or --host claude."
|
|
5433
5461
|
};
|
|
5434
5462
|
}
|
|
5435
5463
|
const hosts = {};
|
|
@@ -5759,7 +5787,7 @@ __export(config_exports2, {
|
|
|
5759
5787
|
saveConfluenceConfig: () => saveConfluenceConfig,
|
|
5760
5788
|
validateProvider: () => validateProvider
|
|
5761
5789
|
});
|
|
5762
|
-
import
|
|
5790
|
+
import fs20 from "fs/promises";
|
|
5763
5791
|
import path26 from "path";
|
|
5764
5792
|
import os3 from "os";
|
|
5765
5793
|
import { execFile as execFile17 } from "child_process";
|
|
@@ -5772,15 +5800,15 @@ function configFile() {
|
|
|
5772
5800
|
}
|
|
5773
5801
|
async function loadConfig() {
|
|
5774
5802
|
try {
|
|
5775
|
-
const raw = await
|
|
5803
|
+
const raw = await fs20.readFile(configFile(), "utf-8");
|
|
5776
5804
|
return JSON.parse(raw);
|
|
5777
5805
|
} catch {
|
|
5778
5806
|
return null;
|
|
5779
5807
|
}
|
|
5780
5808
|
}
|
|
5781
5809
|
async function saveConfig(config) {
|
|
5782
|
-
await
|
|
5783
|
-
await
|
|
5810
|
+
await fs20.mkdir(configDir(), { recursive: true });
|
|
5811
|
+
await fs20.writeFile(configFile(), JSON.stringify(config, null, 2), "utf-8");
|
|
5784
5812
|
}
|
|
5785
5813
|
function getDefaultModel(provider) {
|
|
5786
5814
|
return DEFAULT_MODELS[provider];
|
|
@@ -5940,7 +5968,7 @@ var init_renderer = __esm({
|
|
|
5940
5968
|
});
|
|
5941
5969
|
|
|
5942
5970
|
// src/confluence/diff.ts
|
|
5943
|
-
import
|
|
5971
|
+
import fs21 from "fs/promises";
|
|
5944
5972
|
import path27 from "path";
|
|
5945
5973
|
import { createHash as createHash5 } from "crypto";
|
|
5946
5974
|
function hashDescription(description) {
|
|
@@ -5954,7 +5982,7 @@ function syncStatePath(rootDir) {
|
|
|
5954
5982
|
}
|
|
5955
5983
|
async function loadSyncState(rootDir) {
|
|
5956
5984
|
try {
|
|
5957
|
-
const raw = await
|
|
5985
|
+
const raw = await fs21.readFile(syncStatePath(rootDir), "utf-8");
|
|
5958
5986
|
const parsed = JSON.parse(raw);
|
|
5959
5987
|
if (parsed.version !== 2) return null;
|
|
5960
5988
|
return parsed;
|
|
@@ -5963,8 +5991,8 @@ async function loadSyncState(rootDir) {
|
|
|
5963
5991
|
}
|
|
5964
5992
|
}
|
|
5965
5993
|
async function saveSyncState(rootDir, state) {
|
|
5966
|
-
await
|
|
5967
|
-
await
|
|
5994
|
+
await fs21.mkdir(syncStateDir(rootDir), { recursive: true });
|
|
5995
|
+
await fs21.writeFile(
|
|
5968
5996
|
syncStatePath(rootDir),
|
|
5969
5997
|
JSON.stringify(state, null, 2),
|
|
5970
5998
|
"utf-8"
|
|
@@ -6518,7 +6546,7 @@ import { z as z19 } from "zod";
|
|
|
6518
6546
|
|
|
6519
6547
|
// src/mcp/tools.ts
|
|
6520
6548
|
init_repair();
|
|
6521
|
-
import
|
|
6549
|
+
import fs22 from "fs/promises";
|
|
6522
6550
|
import path28 from "path";
|
|
6523
6551
|
import { execFile as execFile19 } from "child_process";
|
|
6524
6552
|
import { promisify as promisify19 } from "util";
|
|
@@ -7469,7 +7497,7 @@ async function detectProjectSnapshot(rootDir) {
|
|
|
7469
7497
|
const present = [];
|
|
7470
7498
|
for (const file of buildFiles) {
|
|
7471
7499
|
try {
|
|
7472
|
-
await
|
|
7500
|
+
await fs22.access(path28.join(rootDir, file));
|
|
7473
7501
|
present.push(file);
|
|
7474
7502
|
} catch {
|
|
7475
7503
|
}
|
|
@@ -8335,7 +8363,7 @@ function createMcpServer() {
|
|
|
8335
8363
|
const server = new McpServer(
|
|
8336
8364
|
{
|
|
8337
8365
|
name: "mason",
|
|
8338
|
-
version: "0.16.
|
|
8366
|
+
version: "0.16.2"
|
|
8339
8367
|
},
|
|
8340
8368
|
{
|
|
8341
8369
|
instructions: 'Mason retrieves recorded decisions, file impact, and optional feature/flow maps. Use get_context with the task and known files, and get_impact before editing. Save learned rationale and constraints with save_decision; review and commit the local records through the project workflow. These tools work without initialization or a concept map. Consult trust and diagnostics: changed or unknown freshness needs source inspection, failed verification needs correction, and proposals are suggestions and legacy records are unreviewed. Accepted decisions are recorded team constraints, still subject to freshness checks. Use review_decision to prepare code evidence and record only authorized acceptance, reaffirmation, or retirement. Never invent a reviewer or treat these recorded identities as authenticated approval. mason_init returns documentation audit and committed-diff review findings with a quickstart guide. Use mode: "map" only when a full architecture map is requested. A missing map is not a setup failure; use decisions and source evidence. get_snapshot provides architecture navigation when a map is available. The mason-audit and mason-review CLIs also work without setup.'
|