mason-context 0.9.0 → 0.10.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 +25 -0
- package/README.md +167 -37
- package/dist/mason-audit.js +368 -149
- package/dist/mason-audit.js.map +1 -1
- package/dist/mason-drift.js +479 -209
- package/dist/mason-drift.js.map +1 -1
- package/dist/mason-hook.js +337 -123
- package/dist/mason-hook.js.map +1 -1
- package/dist/mason-mcp.js +3459 -1451
- package/dist/mason-mcp.js.map +1 -1
- package/dist/mason-review.js +988 -97
- package/dist/mason-review.js.map +1 -1
- package/package.json +7 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.10.0 — 2026-09-05
|
|
4
|
+
|
|
5
|
+
Mason now provides useful project checks and decision capture without building an architecture map. This release strengthens the trust evidence around stored knowledge and brings existing test and analysis results into the same review.
|
|
6
|
+
|
|
7
|
+
### Added and improved
|
|
8
|
+
|
|
9
|
+
- **Trust and storage:** preserve unknown freshness, invalid-store diagnostics, and failed verification throughout retrieval and review. Use shared file-access policy and bounded reads, store metadata atomically, and distinguish committed drift from local edits. Refreshes stay current through the final metadata commit.
|
|
10
|
+
- **Faster onboarding:** `mason_init` returns documentation audit and committed-diff review findings with a short setup guide. Decision capture, context, and file impact work immediately; architecture mapping is optional.
|
|
11
|
+
- **Decision provenance:** new records start as proposals with optional owner, source, and recorder information. `review_decision` prepares source and history evidence before recording acceptance, reaffirmation, or retirement with a named reviewer and reason. Revisions and prior reviews remain in the record history.
|
|
12
|
+
- **Combined review evidence:** `mason-review --evidence <manifest>` and the `mason_init` evidence input import Vitest JSON and SARIF 2.1.0 artifacts. Findings associate changed files with accepted decisions. Check outcomes and commit freshness remain separate, including skipped, unavailable, stale, and unknown states. `--require-evidence` opts into a CI gate.
|
|
13
|
+
- **Patch evaluations:** an offline-verifiable benchmark grades actual patches and missed companion updates, supports configurable agent adapters, and preserves artifacts for review. The initial ten-task live comparison tied at 10/10 for both arms; fewer coding mistakes and an acceptable false-positive rate are not established by this release.
|
|
14
|
+
- **CI:** run tests with recorded exit status and checkout provenance, review their artifacts, and check types before publishing. Empty-project tests create their own temporary directories so fresh checkouts reproduce local results.
|
|
15
|
+
- **Packaging fixes:** hook help and configuration commands return immediately even when stdin is an open pipe. Update compatible locked runtime dependencies to resolve the six advisories found during release preparation, including the [fast-uri](https://github.com/advisories/GHSA-f65p-4m7j-42xc), [ip-address](https://github.com/advisories/GHSA-mwp4-54f8-5fhr), and [Hono](https://github.com/advisories/GHSA-88fw-hqm2-52qc) advisories. The production dependency audit reports zero known vulnerabilities for the release lockfile.
|
|
16
|
+
|
|
17
|
+
### Upgrading from 0.9.0
|
|
18
|
+
|
|
19
|
+
1. Update the `mason-context` package in all clients that share a decision store, then restart those clients. For a pinned MCP command, use `npx -p mason-context@0.10.0 mason-mcp`. Existing version 1 decision files remain readable and are not automatically rewritten. Their first edit or review upgrades them to version 2; older clients must be updated before using those records.
|
|
20
|
+
2. Re-run `mason_init` and refresh the Mason block in the project's existing assistant instructions. It now defaults to a quickstart audit/review. Automation that needs the previous full architecture build must pass `mode: "map"`. Existing maps remain usable, and initialization markers are no longer a prerequisite for decision capture, context, or impact.
|
|
21
|
+
3. Treat new decisions as **proposed** and legacy records as **unreviewed**. Acceptance needs an owner, source, named reviewer, reason, and committed anchor evidence. Use `review_decision` to prepare and record authorized verdicts. These are recorded assertions for review, not authenticated approvals.
|
|
22
|
+
4. Replace workflows that re-verify a decision by saving identical content. An unchanged `save_decision` is now a no-op; use `review_decision` with `action: "reaffirm"` for accepted records. Content or attribution changes create a new proposed revision. A proposal cannot supersede an accepted record; review the replacement and retire the original separately.
|
|
23
|
+
5. Audit, drift, and review JSON contracts remain additive. Review evidence is optional and advisory for default exit codes. With `--require-evidence`, current failures exit 1; incomplete, missing, skipped, stale, or unknown evidence exits 2. A current failure takes precedence over incomplete evidence. The existing missing-partner check still drives exit 1.
|
|
24
|
+
|
|
25
|
+
Imported commands are never executed. Check provenance applies to its recorded commit and clean checkout, not local edits or complete test coverage. File associations identify relevant knowledge without claiming that a decision was violated. See [CI evidence usage](README.md#combine-ci-evidence-with-project-knowledge) for manifests and supported formats.
|
package/README.md
CHANGED
|
@@ -6,21 +6,32 @@
|
|
|
6
6
|
[](https://github.com/adrianczuczka/mason/blob/main/LICENSE)
|
|
7
7
|
[](https://github.com/adrianczuczka/mason/issues)
|
|
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
|
-
|
|
11
|
+
Start with useful checks in an existing Git repository — no setup, map build, or model calls:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx -p mason-context mason-audit --dir .
|
|
15
|
+
npx -p mason-context mason-review --dir . --base origin/main
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The audit checks claims in `AGENTS.md` and `CLAUDE.md` against the repository. The review checks committed changes from the merge base to HEAD for missing historical change partners and touched decisions. Choose the base branch you normally review against. Missing context files, unavailable history, and skipped checks are reported explicitly; these commands do not certify a patch's correctness.
|
|
19
|
+
|
|
20
|
+
To capture and retrieve lessons while coding, connect Mason to your assistant:
|
|
12
21
|
|
|
13
22
|
```bash
|
|
14
23
|
claude mcp add mason --scope user -- npx -p mason-context mason-mcp
|
|
15
24
|
```
|
|
16
25
|
|
|
17
|
-
Restart Claude Code, then ask: *"
|
|
26
|
+
Restart Claude Code, then ask: *"Use Mason to check this project and set up decision capture."* `mason_init` returns the audit and review findings plus a short guide for adding Mason instructions to the project's existing `AGENTS.md` or `CLAUDE.md`. It does not build a map by default.
|
|
27
|
+
|
|
28
|
+
After resolving a real incident or settling a constraint, ask your assistant to record the reason with `save_decision`. On the next related task, `get_context` retrieves it as a proposal with file impact, tests, and trust evidence. Use `review_decision` when you are ready to record acceptance. Both work immediately, even without running setup.
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
For architecture navigation, ask: *"Build a Mason concept map."* The assistant calls `mason_init` with `mode: "map"` for the full Map-Reduce workflow.
|
|
20
31
|
|
|
21
|
-
> **0.
|
|
32
|
+
> **Upgrading to 0.10.0:** Update Mason in every client that shares decision records, then re-run `mason_init` and refresh the marker-delimited assistant instructions. New decisions are version 2 proposals; legacy records stay explicitly unreviewed until reviewed. Use `review_decision` for acceptance or reaffirmation; saving unchanged content no longer refreshes evidence. Map builds now require `mode: "map"`. See the [migration notes](CHANGELOG.md#upgrading-from-090).
|
|
22
33
|
|
|
23
|
-
> **0.4.0 note:**
|
|
34
|
+
> **0.4.0 note:** The previous `mason <command>` CLI was removed in v0.4.0. Setup and map editing use MCP; dedicated drift, audit, hook, and review binaries support automation. See [0.4.0 migration](#040-migration) below if you used the old CLI.
|
|
24
35
|
|
|
25
36
|
---
|
|
26
37
|
|
|
@@ -34,13 +45,13 @@ Agentic search keeps getting better at re-deriving what's *in* the code — but
|
|
|
34
45
|
|
|
35
46
|
## The fix
|
|
36
47
|
|
|
37
|
-
Mason is an MCP server that
|
|
48
|
+
Mason is an MCP server that assembles repository knowledge per task and checks it against source and Git evidence:
|
|
38
49
|
|
|
39
|
-
- **
|
|
40
|
-
- **
|
|
41
|
-
- **Drift engine** — LLM-free
|
|
50
|
+
- **Decision records** (`.mason/decisions/`) — lessons and constraints captured by `save_decision`, ready for normal code review and commit
|
|
51
|
+
- **Optional concept map** (`.mason/snapshot.json`) — features and flows → files, built by your assistant, spot-checked by `verify_snapshot`
|
|
52
|
+
- **Drift engine** — LLM-free evidence of what changed, per entry, with a self-maintaining refresh loop for CI
|
|
42
53
|
|
|
43
|
-
|
|
54
|
+
One `get_context` call retrieves matching decisions with their full rationale and trust evidence. Known file paths or matched decision anchors provide tests and impact; an available map adds relevant features and flows. An optional map looks like:
|
|
44
55
|
|
|
45
56
|
```json
|
|
46
57
|
{
|
|
@@ -59,12 +70,14 @@ Ask your assistant to do a task and one `get_context` call returns the relevant
|
|
|
59
70
|
|
|
60
71
|
The assistant jumps straight to the relevant files instead of exploring.
|
|
61
72
|
|
|
62
|
-
**Where the map comes from:** Mason doesn't parse your code. Your assistant reads the project through Mason's analysis tools and writes the map itself — capturing architectural intent, not just symbols and call edges. Setup
|
|
73
|
+
**Where the map comes from:** Mason doesn't parse your code. Your assistant reads the project through Mason's analysis tools and writes the map itself — capturing architectural intent, not just symbols and call edges. Setup adds a short section to your project's assistant instructions so future sessions consult the available knowledge.
|
|
63
74
|
|
|
64
75
|
## What the numbers say
|
|
65
76
|
|
|
66
77
|
Measured with real headless agent sessions in A/B arms (baseline always has a populated CLAUDE.md — beating a context-free agent is not a result). Full harness, pinned commits, and losses included: [bench/harness/](bench/harness/).
|
|
67
78
|
|
|
79
|
+
These measurements concern read-only answers. The new [patch benchmark](bench/harness/patches/README.md) grades actual code changes, companion updates, and constraint preservation. Its offline checks validate the harness; improved patch outcomes and an acceptable false-positive rate have not yet been established.
|
|
80
|
+
|
|
68
81
|
- **Where Mason wins — knowledge that isn't in the code.** On tasks whose correct answer hinges on a recorded engineering decision (seeded fairly: the baseline had the same facts in a discoverable doc), Mason averaged **9.0/10 vs 7.0/10**. The baseline missed the constraint entirely half the time, and needed ~3× the turns when it found it; Mason surfaced it in one `get_context` call, every time.
|
|
69
82
|
- **Stale-map safety.** Against a deliberately stale map, the drift flag + changed-file previews led the agent to verify and answer current-code truth — the "confidently wrong from a stale cache" failure did not occur.
|
|
70
83
|
- **Where it's a wash — and we say so.** On questions agents can answer by reading code, quality is parity across hono (186 files), vuejs/core (483), and nestjs/nest (1676): 8.7–8.8 both arms, with Mason slightly *behind* on nest (8.5 vs 8.8). If your only questions are "how does X work", modern agents don't need a map.
|
|
@@ -72,28 +85,58 @@ Measured with real headless agent sessions in A/B arms (baseline always has a po
|
|
|
72
85
|
|
|
73
86
|
## Decision records
|
|
74
87
|
|
|
75
|
-
|
|
88
|
+
Capture a lesson with `save_decision`: what happened, why it matters, and the files or directories it applies to. Add `owner`, `sources`, and `actor` when known. None are required to capture a proposal, and missing attribution stays explicit.
|
|
76
89
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
| Approval | How assistants should use it |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `proposed` | A suggestion that needs review; the default for new records. |
|
|
93
|
+
| `accepted` | A recorded team constraint, still subject to freshness checks. |
|
|
94
|
+
| `unreviewed` | Legacy knowledge with no recorded acceptance. Check its source before treating it as adopted. |
|
|
95
|
+
|
|
96
|
+
Acceptance is separate from lifecycle: retired and superseded records remain in history but leave active retrieval. `get_context`, `get_snapshot`, hooks, and `mason-review` expose approval and provenance alongside freshness. A hook session also receives changes in approval and withdrawals of records it previously saw.
|
|
97
|
+
|
|
98
|
+
For example, an assistant can call `save_decision` with:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"dir": "/path/to/project",
|
|
103
|
+
"title": "Delivery retries require an idempotency key",
|
|
104
|
+
"body": "Unkeyed retries duplicated customer orders during incident 42. Retry only when the request carries an idempotency key.",
|
|
105
|
+
"category": "gotcha",
|
|
106
|
+
"files": ["src/delivery.ts"],
|
|
107
|
+
"owner": "Delivery team",
|
|
108
|
+
"sources": [{ "kind": "incident", "reference": "incidents/42" }]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then ask your assistant to **review that decision**. `review_decision` with its `id` returns the full record, revision and review history, changes since its evidence baseline, local edits, and bounded source/diff previews. Source references are citations to inspect; Mason does not fetch or validate their contents. Supported source kinds are `pull_request`, `issue`, `incident`, `discussion`, `document`, and `other`.
|
|
113
|
+
|
|
114
|
+
After the user or cited team review authorizes a verdict, call `review_decision` again with `action: "accept"`, the actual `reviewer`, a `note` explaining the reason, and the returned `reviewToken`. Acceptance needs an owner, at least one source, readable Git HEAD, and no uncommitted changes to the anchors. Unrelated local work can remain. If the decision or code revision changed since preparation, prepare and inspect it again.
|
|
115
|
+
|
|
116
|
+
When anchored code changes later, use the same preparation flow and `action: "reaffirm"` to record that the accepted decision still holds, or `action: "retire"` to withdraw it. Retirement preserves history and can be recorded when Git history is unavailable. A reviewer may establish a new acceptance baseline when old history is unreachable; that gap stays recorded in the review event. Anchorless knowledge retains unknown code freshness even after acceptance.
|
|
117
|
+
|
|
118
|
+
Tools preserve earlier content and review events in each `.mason/decisions/<id>.json` file. Reviews record the reviewer, reason, timestamp, revision, and code baseline. Editing content, anchors, owner, or sources creates a new proposed revision and retains the earlier accepted version in history. Saving identical content is a no-op: it does not silently reaffirm or refresh the decision. A proposal cannot supersede an accepted constraint; review the replacement, then explicitly retire the original.
|
|
119
|
+
|
|
120
|
+
**Existing records:** Version 1 records remain readable and explicitly unreviewed, without automatic file rewrites or invented attribution. Their first revision or review upgrades them to version 2 with an import event marking the missing earlier history. Old clients that only understand version 1 must be upgraded before consuming new records. Use the tools to revise records; inconsistent content/history is reported as invalid.
|
|
121
|
+
|
|
122
|
+
Mason records assertions of review; it does not authenticate reviewer identity, verify approval in linked systems, or commit files. Review and commit these records through your normal PR process. The history is a review trail, not a tamper-proof approval service.
|
|
81
123
|
|
|
82
124
|
## MCP tools
|
|
83
125
|
|
|
84
126
|
| Tool | Purpose |
|
|
85
127
|
|---|---|
|
|
86
|
-
| `mason_init` |
|
|
87
|
-
| `mason_complete_init` |
|
|
128
|
+
| `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. |
|
|
129
|
+
| `mason_complete_init` | Records assistant instruction setup; preserves prior settings on repeated calls. |
|
|
88
130
|
| `generate_snapshot_batch` | Map step — returns one batch of files for the assistant to summarize. |
|
|
89
131
|
| `save_partial_snapshot` | Persists the partial map for one batch. |
|
|
90
132
|
| `reduce_snapshot` | Reduce step — returns every partial + instructions to merge into a unified map. |
|
|
91
133
|
| `save_snapshot` | Persist the final unified map. Clears partials. |
|
|
92
134
|
| `mason_set_confluence` | Configure Confluence credentials — two-step: list spaces, then persist. |
|
|
93
135
|
| `export_to_confluence` | Sync the concept map to Confluence as PM-readable wiki pages. |
|
|
94
|
-
| `get_snapshot` |
|
|
95
|
-
| `get_context` |
|
|
96
|
-
| `save_decision` |
|
|
136
|
+
| `get_snapshot` | Architecture navigation when a map is available. Loads the concept map — feature → file lookup — in one LLM-free call. |
|
|
137
|
+
| `get_context` | Decisions with approval, provenance, file impact, tests, and trust for a task; adds features/flows when a map exists. No setup required. |
|
|
138
|
+
| `save_decision` | Capture or revise proposals with rationale, anchors, owner, sources, and revision history. No setup required. |
|
|
139
|
+
| `review_decision` | Prepare record/code evidence, then record authorized acceptance, reaffirmation, or retirement against that revision. |
|
|
97
140
|
| `mason_check_drift` | Feature-level staleness report — what changed since the snapshot, and whether to refresh incrementally or rebuild. |
|
|
98
141
|
| `verify_snapshot` | Spot-check map correctness — sampled entries + file skeletons for the assistant to judge, least-recently-verified first. |
|
|
99
142
|
| `save_verification` | Record verification verdicts — failures flag entries for re-mapping until fixed. |
|
|
@@ -102,9 +145,9 @@ The store that makes Mason more than a map. When your assistant learns something
|
|
|
102
145
|
| `full_analysis` | One-shot orientation for unmapped projects: structure + samples + tests + git. |
|
|
103
146
|
| `get_code_samples` | Smart file previews selected by architectural role. |
|
|
104
147
|
|
|
105
|
-
|
|
148
|
+
Tools operate on the data they need; none require the initialization marker. Decision capture and impact need no concept map. Map verification and drift require a map; Confluence export requires credentials and a map.
|
|
106
149
|
|
|
107
|
-
Setup
|
|
150
|
+
Setup installs a short marker-delimited section in the existing `AGENTS.md`, otherwise `CLAUDE.md` or `.claude/CLAUDE.md`; if none exists, it creates `AGENTS.md`. It routes assistants to decisions and impact, with map navigation when available.
|
|
108
151
|
|
|
109
152
|
### How the concept map is built
|
|
110
153
|
|
|
@@ -114,7 +157,7 @@ To stay accurate on codebases of any size, Mason uses a **Map-Reduce** pattern i
|
|
|
114
157
|
- **Reduce**: `reduce_snapshot` returns all the partials plus instructions to merge them into one product-shaped catalog — combining platform variants ("home Android" + "home iOS" → "home screen"), deduplicating, and ensuring no file is dropped.
|
|
115
158
|
- **Save**: `save_snapshot` persists the unified map and cleans up the partials.
|
|
116
159
|
|
|
117
|
-
The
|
|
160
|
+
The goal is complete source coverage. Drift checking reports eligible committed source files omitted from the snapshot, including omissions from a map saved at HEAD. A 200-file project takes ~5 batches; a 1000-file monorepo takes ~20.
|
|
118
161
|
|
|
119
162
|
## Change impact
|
|
120
163
|
|
|
@@ -130,12 +173,31 @@ Ask your assistant *"what would be affected if I changed WeatherRepository?"* an
|
|
|
130
173
|
|
|
131
174
|
A concept map that silently goes stale is worse than no map — your assistant confidently jumps to files that no longer do what the map says. `mason_check_drift` compares the map against HEAD (pure git + filesystem, no LLM call) and reports drift at the **feature level**: which features are stale and which files changed under them, new source files not yet mapped, ghost files the map still references, and renames. It ends with a recommendation — `up-to-date`, `incremental` (re-map just the stale entries), or `full-rebuild` (re-run the Map-Reduce playbook).
|
|
132
175
|
|
|
133
|
-
Ask your assistant *"is the concept map still fresh?"* — and if it isn't, the same report tells it exactly which entries to regenerate. `get_snapshot` includes the same drift report whenever it detects a stale map, so
|
|
176
|
+
Ask your assistant *"is the concept map still fresh?"* — and if it isn't, the same report tells it exactly which entries to regenerate. `get_snapshot` includes the same drift report whenever it detects a stale map, so the assistant can inspect and refresh affected entries.
|
|
134
177
|
|
|
135
178
|
Incremental refreshes are safe against partial updates: every entry a refresh touches is stamped with the commit it was verified against, so entries skipped in one refresh keep reporting as stale instead of silently riding along on the map's new hash. Features that disappear from the codebase can be deleted from the map with `save_snapshot`'s `removeFeatures`/`removeFlows` — renames stop leaving zombie entries behind.
|
|
136
179
|
|
|
137
180
|
When a lot of files drifted at once, the assistant runs a **scoped refresh** instead of a full rebuild: `generate_snapshot_batch` accepts a `files` list, so the Map-Reduce loop walks only the drifted files and the reduce step merges the result into the existing map. 60 drifted files in a 1000-file monorepo means ~2 batches, not 20.
|
|
138
181
|
|
|
182
|
+
### Reading trust signals
|
|
183
|
+
|
|
184
|
+
`get_context` reports `map.status` as `available`, `missing`, or `invalid`. The legacy `exists` field indicates usable map availability only: `exists: false` can still include decisions, impact, and tests. Without a usable map, map freshness is `null`, and an invalid map produces diagnostics while valid decisions remain retrievable. An empty decision match is not a clean audit. Impact covers up to three unique targets, expanding directory anchors to eligible source files; use `get_impact` for a larger explicit file list.
|
|
185
|
+
|
|
186
|
+
Freshness and correctness are separate. `get_context` returns a `trust` object for each matched entry; `get_snapshot` includes a trust index for features, flows, and decisions.
|
|
187
|
+
|
|
188
|
+
| Field | Meaning |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `freshness: current` | No changes detected in the inspected anchors. This does not prove the description is correct. |
|
|
191
|
+
| `freshness: changed` | Anchored files changed, including edits in the working tree. Inspect the current code. |
|
|
192
|
+
| `freshness: unknown` | Evidence is unavailable, such as missing history or an anchorless decision. Verify before relying on it. |
|
|
193
|
+
| `verification: unverified` | No correctness verdict has been recorded. |
|
|
194
|
+
| `verification: passed` | An assistant recorded a passing verdict; check its freshness and verification point before reuse. |
|
|
195
|
+
| `verification: failed` | A known incorrect entry. The failure and its reason remain visible until corrected. |
|
|
196
|
+
|
|
197
|
+
Git commit distance is informational: unrelated commits and committing the refreshed map do not make the map stale. `mason-drift` exit codes still describe **committed map drift**; working-tree changes, decision warnings, and verification results are reported separately. A clean drift exit is not a correctness approval.
|
|
198
|
+
|
|
199
|
+
Snapshot, decision, and partial stores are validated on load and replaced atomically on save. Invalid snapshots produce errors. Invalid decision records appear in diagnostics while valid records remain available; repair the invalid records before writing more decisions.
|
|
200
|
+
|
|
139
201
|
### Drift checks in CI
|
|
140
202
|
|
|
141
203
|
Because the check is deterministic, it also ships as a tiny standalone binary — read-only and LLM-free:
|
|
@@ -164,7 +226,7 @@ codex exec --full-auto "$(mason-drift --refresh-prompt)"
|
|
|
164
226
|
gemini --yolo -p "$(mason-drift --refresh-prompt)"
|
|
165
227
|
```
|
|
166
228
|
|
|
167
|
-
To close the loop in CI, this repo ships a reusable GitHub Actions workflow — detect on every push, refresh with your agent of choice, commit the updated map
|
|
229
|
+
To close the loop in CI, this repo ships a reusable GitHub Actions workflow — detect on every push, refresh with your agent of choice, verify that only the snapshot changed, commit it, check freshness again, and push the updated map:
|
|
168
230
|
|
|
169
231
|
```yaml
|
|
170
232
|
jobs:
|
|
@@ -233,7 +295,7 @@ Recorded knowledge only helps if it shows up. Retrieval tools depend on the mode
|
|
|
233
295
|
npx -p mason-context mason-hook --print-config # the settings block to add
|
|
234
296
|
```
|
|
235
297
|
|
|
236
|
-
Add the printed block to `.claude/settings.json` — the *committed* project settings, so every teammate's sessions get the same rail. The loop this closes: someone
|
|
298
|
+
Add the printed block to `.claude/settings.json` — the *committed* project settings, so every teammate's sessions get the same rail. The loop this closes: someone captures a proposal with `save_decision` and records acceptance with `review_decision` ("this screen has a v1 and v2 — new work goes in v2 behind flag X"), and from then on any session that touches those files gets told, whether or not it thought to ask.
|
|
237
299
|
|
|
238
300
|
For faster fires than `npx` resolution allows, install the package (`npm i -D mason-context`) and point the command at `node_modules/.bin/mason-hook`.
|
|
239
301
|
|
|
@@ -246,15 +308,83 @@ npx -p mason-context mason-review --base origin/main
|
|
|
246
308
|
```
|
|
247
309
|
|
|
248
310
|
- **Missing co-change partners** — files that changed together with a changed file in ≥60% of its commits (≥4 shared, 1500-commit window) but are absent from this diff. Evidence-based but heuristic-grade: a missing partner is a question to ask the diff, not proof of a bug. These drive exit 1.
|
|
249
|
-
- **Touched decisions** — decision records whose
|
|
311
|
+
- **Touched decisions** — decision records whose file or directory anchors the diff touches, including deleted paths and both sides of renames, listed with approval, owner, sources, last review, and freshness. Proposals and legacy records are distinguished from accepted constraints. Informational; never affect the exit code.
|
|
312
|
+
|
|
313
|
+
Deterministic, no LLM, one pass over git history. Run it locally before pushing, or wire it into CI as an advisory check (`mason-review || true` if you want the signal without the gate).
|
|
314
|
+
|
|
315
|
+
### Combine CI evidence with project knowledge
|
|
316
|
+
|
|
317
|
+
Import existing check results into the same review:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
npx -p mason-context mason-review --base origin/main \
|
|
321
|
+
--evidence .mason/reports/evidence.json
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The review shows each check's outcome, command, source, and tested commit. Findings link to changed files and relevant **accepted, active decisions**, including their owner and freshness. Failing tests can also link through Mason's test-to-source pairs, with the pairing confidence shown. These associations give reviewers context; they do not establish that a decision was violated. Proposed and legacy decisions remain visible separately in the touched-decision list.
|
|
325
|
+
|
|
326
|
+
Supported artifacts are [Vitest JSON reporter output](https://vitest.dev/guide/reporters#json-reporter) for tests and [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html) for static analysis, security, complexity, or duplication findings. Mason imports results from those tools; it does not run their commands or infer a score for checks you have not supplied. JUnit and tool-specific non-SARIF analysis formats are not yet supported.
|
|
327
|
+
|
|
328
|
+
Create a manifest beside your artifacts. Replace the example commit and checkout path with values captured **when the check ran**, and record its actual exit code:
|
|
329
|
+
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"version": 1,
|
|
333
|
+
"checks": [
|
|
334
|
+
{
|
|
335
|
+
"id": "unit-tests",
|
|
336
|
+
"kind": "tests",
|
|
337
|
+
"tool": "vitest",
|
|
338
|
+
"command": "npm test -- --reporter=json --outputFile=.mason/reports/vitest.json",
|
|
339
|
+
"commit": "0123456789abcdef0123456789abcdef01234567",
|
|
340
|
+
"workingTreeClean": true,
|
|
341
|
+
"sourceRoot": "/runner/work/project",
|
|
342
|
+
"source": "https://ci.example.com/runs/42",
|
|
343
|
+
"exitCode": 0,
|
|
344
|
+
"report": { "format": "vitest-json", "path": ".mason/reports/vitest.json" }
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"id": "security",
|
|
348
|
+
"kind": "security",
|
|
349
|
+
"tool": "your-security-scanner",
|
|
350
|
+
"command": "your scanner command",
|
|
351
|
+
"status": "skipped",
|
|
352
|
+
"reason": "Security scanning is not configured in this job."
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
For a completed analysis check, use `report.format: "sarif"`, its report path, and the same run provenance fields. Give every expected check a unique `id`; use `status: "skipped"` or `"unavailable"` with a reason when it did not run. Omitted checks cannot be detected. `status` defaults to `"completed"`. A successful SARIF invocation can supply completion evidence when an exit code is absent; Vitest imports require a recorded exit code for complete evidence.
|
|
359
|
+
|
|
360
|
+
Manifest and report paths are relative to the repository root, even when the manifest lives in a subdirectory. Absolute paths inside that root also work. `sourceRoot` maps file locations from the CI checkout to this checkout; it defaults to the local repository root. `source` is an optional CI run link or description. Artifacts must be regular files inside the repository, without symlinks, and at most 10 MiB each. Commands and links are displayed as imported provenance, never executed or fetched, and are not authenticated attestations.
|
|
361
|
+
|
|
362
|
+
Outcome and freshness are separate. A full tested commit matching the reviewed HEAD and `workingTreeClean: true` establish **current** commit evidence; a different commit is **stale**, while missing commit or dirty/unrecorded checkout state is **unknown**. Record cleanliness before and after the run, and invalidate attribution if HEAD changes during execution. A passing report for another commit cannot establish a pass for this one. Local uncommitted edits remain outside the review's committed scope.
|
|
363
|
+
|
|
364
|
+
Empty or entirely skipped test runs do not pass; partially skipped runs are incomplete. Malformed or missing artifacts stay unavailable. SARIF active `fail` results count as failures at every severity; explicitly accepted suppressions and results marked absent are retained separately. Failed analysis invocations and omitted results stay unavailable. Open/review results, unresolved locations, and unresolved suppression states preserve uncertainty. The JSON report retains overall counts even when findings are abbreviated (10 manifests, 50 checks, 200 findings per check, 5 related decisions per finding); MCP and text summaries have smaller previews and flag truncation.
|
|
365
|
+
|
|
366
|
+
Imports are advisory under the existing exit-code contract. Opt into a gate with:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
npx -p mason-context mason-review --base origin/main \
|
|
370
|
+
--evidence .mason/reports/evidence.json --require-evidence --json
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
| Exit | With `--require-evidence` |
|
|
374
|
+
| --- | --- |
|
|
375
|
+
| 0 | All declared checks are current, complete, and passing; no missing co-change partners. |
|
|
376
|
+
| 1 | A current check failed, or co-change partners are missing. |
|
|
377
|
+
| 2 | Evidence is missing, skipped, stale, unknown, or incomplete, or the review cannot run. Current failures take precedence over incomplete evidence. |
|
|
378
|
+
|
|
379
|
+
Through MCP, pass `evidence: [".mason/reports/evidence.json"]` to `mason_init`. No map or initialization is required. A passing import only describes the supplied checks, not complete coverage or overall correctness.
|
|
250
380
|
|
|
251
|
-
|
|
381
|
+
Mason's own checkout produces real test artifacts with `npm run test:evidence`, using [scripts/test-evidence.mjs](scripts/test-evidence.mjs). It records the observed exit code and checkout state and invalidates previous evidence before starting a fresh run. After `npm run build`, inspect them with `node dist/mason-review.js --base HEAD --evidence .mason/reports/evidence.json`. A local run with uncommitted edits correctly has unknown commit attribution. The repository CI uses this producer and posts the combined review to its job summary. Add `.mason/reports/` to your ignore file when using that output directory; keep the decisions and map tracked.
|
|
252
382
|
|
|
253
383
|
## Confluence sync
|
|
254
384
|
|
|
255
385
|
Keep a Confluence wiki in sync with the concept map, in plain product language that PMs and designers can read. Each sync rewrites the snapshot through your assistant into PM-friendly descriptions, pushes one page per feature, and posts a "what changed since last sync" entry to a changelog page. Mason owns these pages and overwrites each one on every sync, so edit the code, not the page — manual edits to a page body are replaced. Re-running a sync with no code change is a no-op: it makes no Confluence edits at all.
|
|
256
386
|
|
|
257
|
-
|
|
387
|
+
Configure this separately by asking your assistant *"set up Confluence for this project."* The assistant walks you through the Atlassian site URL, your account email, and an API token from id.atlassian.com, then lets you pick which space to use. To sync, ask *"sync the wiki to Confluence."*
|
|
258
388
|
|
|
259
389
|
> ⚠️ **Token in chat history.** The API token is pasted into your assistant chat, not a terminal. It will appear in your chat history. If that's not acceptable, skip Confluence sync.
|
|
260
390
|
|
|
@@ -333,10 +463,10 @@ Language-agnostic. Mason works from file naming patterns and git history rather
|
|
|
333
463
|
|
|
334
464
|
## Security
|
|
335
465
|
|
|
336
|
-
- **The snapshot
|
|
337
|
-
- **
|
|
338
|
-
- **Path
|
|
339
|
-
- **
|
|
466
|
+
- **The snapshot stores:** assistant-authored feature names, relative file paths, descriptions, and verification metadata. Review that prose before committing it; do not record secrets.
|
|
467
|
+
- **Shared file policy:** mapping, sampling, verification, impact analysis, and test discovery respect Git ignores and `.mason/config.json` exclusions. Sensitive filenames are denied, and source reads are limited to 1 MiB.
|
|
468
|
+
- **Path protection:** source reads check canonical paths and reject symlinks escaping the project root. Metadata paths reject symlinks, including parent directories.
|
|
469
|
+
- **Mapping is local:** source previews go to the connected assistant through MCP. Mason itself makes no model API calls for mapping. Optional Confluence sync uses network access and can call a configured model provider.
|
|
340
470
|
|
|
341
471
|
## 0.4.0 migration
|
|
342
472
|
|
|
@@ -345,13 +475,13 @@ If you used Mason before v0.4.0, the standalone `mason <command>` CLI has been r
|
|
|
345
475
|
| Old CLI | New flow |
|
|
346
476
|
|---|---|
|
|
347
477
|
| `mason set-llm <provider>` | Not needed — your assistant *is* the LLM. |
|
|
348
|
-
| `mason snapshot` | Ask your assistant: *"
|
|
478
|
+
| `mason snapshot` | Ask your assistant: *"build a Mason concept map"* → `mason_init` with `mode: "map"` → the Map-Reduce workflow. |
|
|
349
479
|
| `mason generate` (CLAUDE.md) | Removed. Use your assistant directly. |
|
|
350
480
|
| `mason analyze` | Ask your assistant: *"give me git stats for this repo"* — it calls `analyze_project`. |
|
|
351
481
|
| `mason impact File.kt` | Ask your assistant: *"what would changing File.kt affect?"* — it calls `get_impact`. |
|
|
352
482
|
| `mason snapshot --install-hook` | Removed. The map auto-refreshes when the assistant detects stale state. |
|
|
353
483
|
|
|
354
|
-
The
|
|
484
|
+
The package provides `mason-mcp`, `mason-drift`, `mason-audit`, `mason-hook`, and `mason-review`. Running `mason` directly prints a migration message and exits.
|
|
355
485
|
|
|
356
486
|
## License
|
|
357
487
|
|