mason-context 0.11.0 → 0.12.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 +12 -0
- package/README.md +39 -1
- package/dist/mason-audit.js +13 -7
- package/dist/mason-audit.js.map +1 -1
- package/dist/mason-auto.js +2283 -0
- package/dist/mason-auto.js.map +1 -0
- package/dist/mason-mcp.js +3443 -2761
- package/dist/mason-mcp.js.map +1 -1
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.0 — 2026-09-06
|
|
4
|
+
|
|
5
|
+
Mason can now run documentation checks automatically through Claude Code and Codex hooks. It preserves findings before edits can hide them, resumes retained evidence across sessions, and verifies repairs against the final commit. Hook installation is opt-in.
|
|
6
|
+
|
|
7
|
+
- Add a shared documentation automation runtime with Claude Code and Codex lifecycle adapters, `mason-auto` installation/status/check commands, and the `mason_automation` MCP tool. Retain original and newly discovered findings across sessions, isolate branch/worktree state, verify after the final commit, and distinguish configured hooks from observed runtime events.
|
|
8
|
+
- Cache audit checks by their evidence dependencies, retry skipped checks, serialize concurrent captures, and keep full reports accessible behind concise notifications. Request at most one task-relevant continuation per session; never infer advisory approval or expand repair authorization.
|
|
9
|
+
- Add ordinary-request automation evaluations for module renames and unrelated edits, with baseline, instructions, and hooks arms. Offline lifecycle replay is separate from live agent performance evidence.
|
|
10
|
+
|
|
11
|
+
Upgrade with `npm install -D mason-context@0.12.0` in each project that will use the default hook command. Run `npx mason-auto install --host claude` or `npx mason-auto install --host codex`, then start a new assistant session; Codex also requires review/trust through `/hooks`. Keep the host configuration and `.mason/automation.json` together in version control, and ignore `.mason/reports/`. Update any separately pinned MCP server command, restart it, and refresh the Mason instructions through `mason_init`. No decision-store migration is required.
|
|
12
|
+
|
|
13
|
+
Validation includes 414 automated tests, live rename/control smoke tests in both hosts, and a Codex trial in an existing Kotlin Multiplatform/iOS project. These trials observed capture and final-commit verification without requiring forced continuation. The controlled live forced-repair continuation test remains deferred; broader mistake-rate, false-positive, and large-repository performance claims remain unproven. See the [recorded smoke results](https://github.com/adrianczuczka/mason/blob/v0.12.0/bench/harness/automation/SMOKE_RESULTS.md).
|
|
14
|
+
|
|
3
15
|
## 0.11.0 — 2026-09-05
|
|
4
16
|
|
|
5
17
|
Mason now keeps the original audit evidence visible while an assistant repairs documentation. A dependency warning suppressed by local edits stays unresolved, and a later documentation commit does not silently clear its review requirement.
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
### Give coding assistants the lessons your team already learned, the changes they might miss, and evidence of what is still current.
|
|
10
10
|
|
|
11
|
+
Project direction and remaining evidence gaps are recorded in [the roadmap](ROADMAP.md).
|
|
12
|
+
|
|
11
13
|
Start with useful checks in an existing Git repository — no setup, map build, or model calls:
|
|
12
14
|
|
|
13
15
|
```bash
|
|
@@ -131,6 +133,7 @@ Mason records assertions of review; it does not authenticate reviewer identity,
|
|
|
131
133
|
|---|---|
|
|
132
134
|
| `mason_init` | Read-only audit/review findings and quickstart guide; optional `base` for review, `evidence` for local CI manifests, `mode: "map"` for an architecture build. |
|
|
133
135
|
| `mason_repair` | Prepare an audit repair baseline; verify the same original findings after edits. Reports unresolved advisories and unavailable checks. |
|
|
136
|
+
| `mason_automation` | Inspect configured hooks and observed events, or capture/resume and verify retained repair evidence across sessions. |
|
|
134
137
|
| `mason_complete_init` | Records assistant instruction setup; preserves prior settings on repeated calls. |
|
|
135
138
|
| `generate_snapshot_batch` | Map step — returns one batch of files for the assistant to summarize. |
|
|
136
139
|
| `save_partial_snapshot` | Persists the partial map for one batch. |
|
|
@@ -314,6 +317,41 @@ jobs:
|
|
|
314
317
|
|
|
315
318
|
Omit `agent-command` for detect-only mode: no agent, no credentials — the job fails when the context files have drifted, which is a reasonable default for repos that want the signal before the automation. Two GitHub notes: the repo setting **"Allow GitHub Actions to create and approve pull requests"** (Settings → Actions → General) must be enabled for the PR step, and PRs created with the default `GITHUB_TOKEN` don't trigger the repo's own CI — run your agent with PAT-backed auth if you need that.
|
|
316
319
|
|
|
320
|
+
## Automatic documentation checks (mason-auto)
|
|
321
|
+
|
|
322
|
+
Mason can preserve documentation audit evidence and resume unfinished repairs through Claude Code or Codex lifecycle hooks. A shared engine owns the evidence, verification, and cache; each host adapter handles its event format. No concept map or model call is required for the checks.
|
|
323
|
+
|
|
324
|
+
Available from 0.12.0. Install or upgrade the package in each project where you want automatic checks:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
npm install -D mason-context@0.12.0
|
|
328
|
+
npx mason-auto install --host claude # Claude Code
|
|
329
|
+
npx mason-auto install --host codex # Codex; review/trust the hooks using /hooks
|
|
330
|
+
npx mason-auto status
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Install only the adapters you use. Installation merges the project's `.claude/settings.json` or `.codex/hooks.json`, preserves other hooks/settings, and records its own handler in `.mason/automation.json`. Repeating installation updates only those handlers. Keep the host configuration and `.mason/automation.json` together in version control; if you ignore all of `.mason/`, allow the installation record explicitly. Add `.mason/reports/` to your ignore rules. Start a new assistant session after installation. The default handler uses the locally installed package with `npx --no-install`; `--command` accepts an executable prefix for an existing installation.
|
|
334
|
+
|
|
335
|
+
When upgrading an existing MCP setup, update any separately pinned server command to `mason-context@0.12.0`, restart the server, and refresh the Mason instruction block through `mason_init`. Existing decisions and repair baselines need no migration. Upgrading the package alone does not install hooks.
|
|
336
|
+
|
|
337
|
+
`status` distinguishes configuration from observed events. Host versions, project trust, policy, and specialized tool paths can prevent hooks from running. Configuration alone is not evidence of automatic use. Codex requires review/trust of new or changed non-managed hooks. See the [Claude Code hook reference](https://code.claude.com/docs/en/hooks) and [Codex hook reference](https://learn.chatgpt.com/docs/hooks).
|
|
338
|
+
|
|
339
|
+
On session start, Mason recovers the current branch/worktree's evidence. Before and after tools, it checks for changed audit inputs and retains newly observed findings before another documentation edit can hide them. Shell and unknown tool calls are included because edits can happen outside a file-edit tool. At turn completion it verifies the retained findings. A relevant unresolved issue can request **one continuation per session**; advisories and unavailable checks never create a repair loop. Fixes remain the assistant's responsibility within the user's task scope.
|
|
340
|
+
|
|
341
|
+
Checks reuse cached results only when their dependencies match. Documentation and history, file inventory, manifests, and decision evidence have separate invalidation keys. Changes to a dirty manifest invalidate its checks even when Git's status text is unchanged. Skipped checks are retried. Cache corruption causes recomputation; invalid original baselines or active state remain errors. Concurrent events serialize writes, and interrupted local writers' locks are recovered only when their process is gone. New reports are written atomically. Unchanged tool events reuse the existing full report.
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
npx mason-auto check --json # Capture/resume the active evidence and verify it
|
|
345
|
+
# After any final documentation commit:
|
|
346
|
+
npx mason-auto check
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
The equivalent MCP operation is `mason_automation(action: "check")`. Its response is concise and links the full local report. `status` is read-only; `check` writes evidence. Exit codes are 0 for verified checks, 1 for unresolved issues, and 2 for incomplete/unavailable checks. Original `mason_repair` baselines remain separately verifiable by their paths. Hook errors are visible and advisory; the existing `mason-hook` decision injector keeps its previous behavior.
|
|
350
|
+
|
|
351
|
+
Evidence is local to the worktree and branch. Switching assistants in that worktree resumes the same repair; another worktree or branch has separate state. Detached-HEAD commits retain evidence; moving that checkout to a different history requires inspection. Hooks follow the Git worktree of the event's working directory. Reports are not automatically transferred to CI. CI can call `mason-auto check` on retained local artifacts, or `mason-audit --verify-repair <baseline>` after restoring the original artifacts at their recorded root. A fresh checkout cannot reconstruct missing pre-edit evidence. Audited instruction files remain limited to `AGENTS.md`, `CLAUDE.md`, and `.claude/CLAUDE.md`. Automation bounds inventory at 100,000 paths and retained baselines at 128; exceeding a bound reports unavailable evidence without evicting unresolved findings. Symbolic links in the inspected inventory require an explicit audit instead of cached automation. This is not proof of arbitrary repository scale or universal tool interception.
|
|
352
|
+
|
|
353
|
+
The [automation evaluation](bench/harness/automation/README.md) compares ordinary module-renaming requests and unrelated edits across hosts, with baseline, instructions, and hooks arms. Deterministic replay verifies the mechanism; live sessions measure actual activation.
|
|
354
|
+
|
|
317
355
|
## Decision injection (mason-hook)
|
|
318
356
|
|
|
319
357
|
Recorded knowledge only helps if it shows up. Retrieval tools depend on the model deciding to call them — and it often doesn't. `mason-hook` removes the gamble: it's a Claude Code `PostToolUse` hook that fires when a session reads or edits a file, looks up the decision records anchored to that file (exact path or directory prefix), and injects them into the model's context. Deterministic lookup, no LLM call, ~100ms, silent when nothing matches. Each decision is injected at most once per session, and records whose anchors drifted since verification carry a verify-before-relying marker.
|
|
@@ -508,7 +546,7 @@ If you used Mason before v0.4.0, the standalone `mason <command>` CLI has been r
|
|
|
508
546
|
| `mason impact File.kt` | Ask your assistant: *"what would changing File.kt affect?"* — it calls `get_impact`. |
|
|
509
547
|
| `mason snapshot --install-hook` | Removed. The map auto-refreshes when the assistant detects stale state. |
|
|
510
548
|
|
|
511
|
-
The package provides `mason-mcp`, `mason-drift`, `mason-audit`, `mason-hook`, and `mason-review`. Running `mason` directly prints a migration message and exits.
|
|
549
|
+
The package provides `mason-mcp`, `mason-drift`, `mason-audit`, `mason-auto`, `mason-hook`, and `mason-review`. Running `mason` directly prints a migration message and exits.
|
|
512
550
|
|
|
513
551
|
## License
|
|
514
552
|
|
package/dist/mason-audit.js
CHANGED
|
@@ -1428,7 +1428,7 @@ async function computeAudit(rootDir, options = {}) {
|
|
|
1428
1428
|
const selected = options.checks ?? ALL_CHECKS;
|
|
1429
1429
|
for (const name of ALL_CHECKS) {
|
|
1430
1430
|
if (!selected.includes(name)) continue;
|
|
1431
|
-
const { issues, advisories, suppressedAdvisories, skipped } = await CHECKS[name](ctx);
|
|
1431
|
+
const { issues, advisories, suppressedAdvisories, skipped } = await (options.runCheck ? options.runCheck(name, ctx) : CHECKS[name](ctx));
|
|
1432
1432
|
report.checksRun.push(name);
|
|
1433
1433
|
report.issues.push(...issues);
|
|
1434
1434
|
report.advisories.push(...advisories);
|
|
@@ -1500,6 +1500,12 @@ var issueSchema = findingSchema.extend({
|
|
|
1500
1500
|
confidence: z3.enum(["certain", "likely"])
|
|
1501
1501
|
});
|
|
1502
1502
|
var advisorySchema = findingSchema.extend({ type: z3.enum(["deps-changed", "decision-anchor-drift"]) });
|
|
1503
|
+
var checkResultSchema = z3.object({
|
|
1504
|
+
issues: z3.array(issueSchema),
|
|
1505
|
+
advisories: z3.array(advisorySchema),
|
|
1506
|
+
suppressedAdvisories: z3.array(advisorySchema).optional(),
|
|
1507
|
+
skipped: z3.array(z3.object({ check: z3.string(), reason: z3.string(), doc: z3.string().optional() }))
|
|
1508
|
+
});
|
|
1503
1509
|
var reportSchema = z3.object({
|
|
1504
1510
|
version: z3.literal(1),
|
|
1505
1511
|
root: z3.string(),
|
|
@@ -1569,19 +1575,19 @@ async function docState(root) {
|
|
|
1569
1575
|
}
|
|
1570
1576
|
return digest(docs);
|
|
1571
1577
|
}
|
|
1572
|
-
async function stableAudit(root, checks) {
|
|
1578
|
+
async function stableAudit(root, checks, options = {}) {
|
|
1573
1579
|
const head = await getCurrentGitHash(root);
|
|
1574
1580
|
const before = await docState(root);
|
|
1575
|
-
const report = await computeAudit(root, { checks });
|
|
1581
|
+
const report = await computeAudit(root, { ...options, checks });
|
|
1576
1582
|
if (head !== await getCurrentGitHash(root) || before !== await docState(root) || report && report.headHash !== head) {
|
|
1577
1583
|
throw new Error("HEAD or context files changed during the audit; retry against a stable checkout.");
|
|
1578
1584
|
}
|
|
1579
1585
|
return report;
|
|
1580
1586
|
}
|
|
1581
|
-
async function prepareRepair(rootDir, checks = ALL_CHECKS) {
|
|
1587
|
+
async function prepareRepair(rootDir, checks = ALL_CHECKS, options = {}) {
|
|
1582
1588
|
const root = await fs10.realpath(rootDir);
|
|
1583
1589
|
const selected = z3.array(checkSchema).nonempty().parse(checks);
|
|
1584
|
-
const report = await stableAudit(root, selected);
|
|
1590
|
+
const report = await stableAudit(root, selected, options);
|
|
1585
1591
|
if (!report) throw new Error("No context files found to prepare a repair.");
|
|
1586
1592
|
if (!report.gitAvailable) throw new Error("Readable Git history is required to prepare a repair.");
|
|
1587
1593
|
const storedReport = reportSchema.parse(report);
|
|
@@ -1595,7 +1601,7 @@ async function prepareRepair(rootDir, checks = ALL_CHECKS) {
|
|
|
1595
1601
|
await writeStoreJson(root, baselinePath, { ...payload, digest: digest(payload) });
|
|
1596
1602
|
return { version: 1, action: "prepare", baselinePath, report };
|
|
1597
1603
|
}
|
|
1598
|
-
async function verifyRepair(rootDir, baselinePath) {
|
|
1604
|
+
async function verifyRepair(rootDir, baselinePath, options = {}) {
|
|
1599
1605
|
const root = await fs10.realpath(rootDir);
|
|
1600
1606
|
const declaredRoot = path16.resolve(rootDir);
|
|
1601
1607
|
const relative = path16.isAbsolute(baselinePath) ? path16.relative(isWithinRoot(declaredRoot, baselinePath) ? declaredRoot : root, baselinePath) : baselinePath;
|
|
@@ -1607,7 +1613,7 @@ async function verifyRepair(rootDir, baselinePath) {
|
|
|
1607
1613
|
const diagnostics = [];
|
|
1608
1614
|
let current = null;
|
|
1609
1615
|
try {
|
|
1610
|
-
current = await stableAudit(root, original.checksRun);
|
|
1616
|
+
current = await stableAudit(root, original.checksRun, options);
|
|
1611
1617
|
if (!current) diagnostics.push("No context files remain available to audit.");
|
|
1612
1618
|
else if (!current.gitAvailable) diagnostics.push("Git history is unavailable.");
|
|
1613
1619
|
for (const doc of original.docs) {
|