@massu/core 1.7.0 → 1.9.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/README.md CHANGED
@@ -31,6 +31,95 @@ npx massu doctor
31
31
  npx massu validate-config
32
32
  ```
33
33
 
34
+ ### Permission Seeding
35
+
36
+ To skip the per-tool MCP permission dialog on a fresh install, `npx massu install-commands` automatically seeds the canonical glob `mcp__massu__*` into `.claude/settings.local.json`'s `permissions.allow` array. It also propagates the user-global `defaultMode` (from `~/.claude/settings.json`) into the project-local file (see "Permissions trap" below).
37
+
38
+ Three lifecycle subcommands for managing the allowlist:
39
+
40
+ ```bash
41
+ # Seed the canonical entry + propagate global defaultMode (idempotent)
42
+ npx massu permissions install
43
+
44
+ # Read-only check — exit 0 if all canonical entries present
45
+ npx massu permissions verify
46
+
47
+ # Extended diagnostic — surfaces 4 drift kinds with severity-mapped exit codes
48
+ npx massu permissions check-drift
49
+ ```
50
+
51
+ To opt out of automatic permission seeding during `install-commands` (e.g., when permissions are managed centrally by enterprise policy):
52
+
53
+ ```bash
54
+ npx massu install-commands --skip-permissions
55
+ ```
56
+
57
+ `defaultMode` validity reference (per [Claude Code docs](https://code.claude.com/docs/en/permission-modes)):
58
+
59
+ | Mode | Activatable from settings file alone | Requires launch flag |
60
+ |---|---|---|
61
+ | `default` | ✓ | — |
62
+ | `acceptEdits` | ✓ | — |
63
+ | `plan` | ✓ | — |
64
+ | `bypassPermissions` | — | `--permission-mode bypassPermissions` or `--dangerously-skip-permissions` |
65
+ | `auto` | — | `--permission-mode auto` (plus plan/admin/model preconditions) |
66
+ | `dontAsk` | — | `--permission-mode dontAsk` |
67
+
68
+ `permissions check-drift` warns when a launch-flag-required value is set in settings without the corresponding flag (these settings are silently inert without the launch flag).
69
+
70
+ ### Permissions trap (settings merge)
71
+
72
+ Empirically observed in Claude Code 2.1.x: a project-local `.claude/settings.local.json` that has a `permissions` object **without** a `defaultMode` key silently STRIPS the user-global `defaultMode` from `~/.claude/settings.json` during settings merge. The merge unit appears to be the entire `permissions` object's top-level keys, not individual keys within it — undocumented at `code.claude.com/docs/en/permissions`.
73
+
74
+ **Before** (trap state):
75
+ ```jsonc
76
+ // ~/.claude/settings.json (global)
77
+ { "permissions": { "defaultMode": "auto" } }
78
+
79
+ // .claude/settings.local.json (project)
80
+ { "permissions": { "allow": ["mcp__massu__*"] } }
81
+ // Effective defaultMode in this project: NONE (global "auto" silently stripped)
82
+ ```
83
+
84
+ **After** (correct state, what `massu permissions install` writes):
85
+ ```jsonc
86
+ // .claude/settings.local.json (project)
87
+ { "permissions": {
88
+ "allow": ["mcp__massu__*"],
89
+ "defaultMode": "auto"
90
+ } }
91
+ ```
92
+
93
+ The install writer:
94
+ 1. Reads global `~/.claude/settings.json`
95
+ 2. Reads project-local `.claude/settings.local.json`
96
+ 3. Computes merged state: `allow` = union with canonical entries; `defaultMode` = local override OR global value OR omit; `deny`/`ask` preserved from local
97
+ 4. Atomic-writes the complete merged block
98
+ 5. Post-write fail-loud assertion: re-reads disk and confirms the merge survived
99
+
100
+ To audit any project for the trap (or any other permission drift):
101
+ ```bash
102
+ npx massu permissions check-drift
103
+ # Exit 4 + stderr "drift[strips-global-defaultmode]: ..." if the trap is present
104
+ ```
105
+
106
+ ### Changelog Generation
107
+
108
+ Release-boundary CHANGELOG entries are auto-drafted by `npx massu changelog generate` (shipped 1.9.0+). The generator reads commit subjects since the last git tag, groups them by `(plan-<token>)` paren-notation (the same convention enforced by CR-40), and pulls each plan file's `## Changelog Summary` section verbatim into a Keep-a-Changelog 1.1.0-compliant entry. Goal: "fewer changelog entries, more meaningful" — one entry per release, structured by plan-token, instead of per-commit noise.
109
+
110
+ ```bash
111
+ # Auto-draft entry for commits since the last tag
112
+ npx massu changelog generate > /tmp/draft-entry.md
113
+
114
+ # Read-only verify that the latest CHANGELOG entry references every plan-token
115
+ # in the commit range since the last tag
116
+ npx massu changelog verify
117
+ ```
118
+
119
+ **Plan-file `## Changelog Summary` contract**: any plan whose Status is in the shipped subset (SHIPPED, IMPLEMENTED, COMPLETE, SUPERSEDED, APPROVED) MUST contain a `## Changelog Summary` section. The plan-status validator (`scripts/massu-plan-status-validator.sh`) enforces this — plans missing the section fail validation. The release generator reads this section to produce the CHANGELOG entry body, so plan authors describe shipped behavior once (in the plan file) and the generator propagates it.
120
+
121
+ **Pre-tag gate**: `scripts/pre-push-light.sh` step `[11/11] Plan-Token Changelog Currency` fires when `packages/core/package.json#version` drifts from the latest git tag (i.e., a release is in progress). The gate BLOCKS the push if CHANGELOG.md doesn't have a `## [X.Y.Z]` heading matching the new version AND doesn't reference every plan-token in the commit range since the last tag. The CI workflow at `.github/workflows/ci.yml` mirrors this check (3-layer enforcement: pre-push + CI + drift-guard vitest).
122
+
34
123
  ## Documentation
35
124
 
36
125
  Full documentation at [massu.ai](https://massu.ai).
@@ -179,7 +179,29 @@ fi
179
179
 
180
180
  ## STEP 3: CHANGELOG GENERATION
181
181
 
182
- ### 3.1 Parse Conventional Commits
182
+ ### 3.0 Auto-Generate Draft Entry (PREFERRED, plan-1.9.0+)
183
+
184
+ The `npx massu changelog generate` subcommand auto-drafts an entry by reading
185
+ commit subjects since the last tag, grouping by `(plan-<token>)` paren-notation,
186
+ and pulling the prose from each plan file's `## Changelog Summary` section. This
187
+ makes "fewer changelog entries, more meaningful" the default workflow.
188
+
189
+ ```bash
190
+ # Generate draft into a tmp file for operator review
191
+ npx massu changelog generate > /tmp/draft-changelog-entry.md
192
+ cat /tmp/draft-changelog-entry.md
193
+
194
+ # Operator reviews; edit inline if needed; then prepend to CHANGELOG.md.
195
+ # Stage D pre-tag gate (scripts/pre-push-light.sh step 11) BLOCKS the push
196
+ # if package.json#version drifts from the last tag but CHANGELOG.md does
197
+ # not have a matching `## [X.Y.Z]` heading AND references every plan-token
198
+ # in the commit range since the last tag.
199
+
200
+ # Sanity-check completeness post-edit
201
+ npx massu changelog verify # exit 0 = all plan-tokens referenced
202
+ ```
203
+
204
+ ### 3.1 Parse Conventional Commits (legacy / fallback when no plan-token paren-notation)
183
205
 
184
206
  ```bash
185
207
  LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")