Massu 1.5 → 1.6: Plan-Status Drift-Guard + Workspace Adapter Publish
Massu 1.5.0 went out on 2026-05-08; 36 hours later we were at 1.6.0 with five new framework adapter packages on npm. Two days after that, three patch releases and one minor cohesive-cleanup landed in quick succession (1.6.1 → 1.6.2 → 1.6.3 → 1.7.0). This post is a factual release log — what shipped, why, and how the audit gates kept it honest.
What's new on npm
npm view @massu/core dist-tags now reads:
{ latest: '1.7.0' }Six packages live as of 2026-05-11:
| Package | Version | First published |
|---|---|---|
@massu/core | 1.7.0 | (existing scope, version bumped from 1.6.0 → 1.7.0) |
@massu/adapter-rails | 1.0.0 | 🆕 first publish in 1.6.0 |
@massu/adapter-phoenix | 1.0.0 | 🆕 first publish in 1.6.0 |
@massu/adapter-aspnet | 1.0.0 | 🆕 first publish in 1.6.0 |
@massu/adapter-spring | 1.0.0 | 🆕 first publish in 1.6.0 |
@massu/adapter-go-chi | 1.0.0 | 🆕 first publish in 1.6.0 |
Adapters are workspace packages that core depends on directly. Installing @massu/core@1.7.0 automatically pulls in the five, so existing npx @massu/core init flows for Ruby/Rails, Elixir/Phoenix, ASP.NET, Java/Spring, and Go/Chi continue to work without code changes.
Why two minors in 36 hours
The 1.5.x series shipped one capability per patch — init end-to-end correctness for the six framework fixtures, AST adapter introspection piping, drift-guard tests, etc. Each patch was scoped to one structural defect. The 1.6.0 minor existed for one reason: to ship the five adapter packages as their own publishable units (Choice Z+II in the Phase 9b plan). That's a deliberate scope split — fixes go to 1.5.x, packaging-shape changes get a minor bump.
The story behind 1.5.8: structural drift-guard for plan-Status headers
By the morning of 2026-05-09, docs/plans/*.md had accumulated four stale Status: DRAFT headers despite the underlying code being shipped. The previous day's manual cleanup refreshed three of them; four hours later a new batch had drifted again.
Plan 1.5.8 closed this with three structural layers:
- Schema validator (
scripts/massu-plan-status-validator.sh) — every plan must declare aPlan Token:field plus aStatus:from the canonical 8-value enum:DRAFT,IN PROGRESS,SHIPPED,COMPLETE,IMPLEMENTED,APPROVED,SUPERSEDED,HISTORICAL DRAFT. - Commit-link drift scanner (
scripts/massu-plan-commit-drift.sh) — grepsgit logfor(feat|fix|chore|docs)(plan-<token>)references; fails if any referenced plan still reads DRAFT. Cross-repo plan tokens live in an explicit allowlist. - Drift-guard test (
packages/core/src/tests/plan-status-drift-guard.test.ts) — eight cases, one of them gates against the live corpus on every PR.
Wired at three enforcement points: GitHub Actions type-check job, local pre-push-light.sh, and the Claude Code pre-commit hook. The plan went through seven audit iterations before implementation (gap counts 16 → 9 → 8 → 2 → 2 → 1 → 0).
A new rule, CR-40 / VR-PLAN-STATUS, was added to .claude/CLAUDE.md to record the convention.
The story behind 1.6.0: workspace adapter publish (Phase 9b)
The five framework adapters (Rails, Phoenix, ASP.NET, Spring, Go-chi) used to live inside @massu/core's source tree. After 1.6.0 they're separately publishable workspace packages with their own version line.
Why split them: third-party adapter authors (the eventual goal) need a stable trust model. The signed adapter registry at https://registry.massu.ai/adapters/manifest.json (live since 2026-05-07) gates adapter loading by Ed25519 signature. Workspace publish makes the five reference adapters first-class consumers of the same registry shape that third-party adapters will use. <!-- leak-guard-allow: Ed25519 is a public crypto algorithm name, not a git SHA -->
The plan went through seven audit iterations as well. Highlights of what the audit caught before publish:
- A circular dependency in the original Choice Z+II direction — fixed with
peerDependencieson the core ↔ adapter boundary. - The
./adaptersubpath export pointing at raw.ts(Node ESM resolver can't execute that). Fixed by bundlingdist/adapter.js+ emittingdist/adapter.d.tsseparately viatsc --emitDeclarationOnly. - A missing 1.5.8 → 1.6.0 version-bump step. Without that the publish ceremony would have shipped 1.5.8-tagged tarballs as 1.6.0.
- Atomic-publish rollback: 6 packages publish; if package #3 fails, the registry is half-shipped. Added a dry-run gate and a documented rollback runbook (
72h-grace npm unpublishORbump-all-to-1.0.1 retry).
Soak verdict — what we mean by "the daemon is stable"
@massu/core ships a watch daemon (Plan 3a) that runs continuously in user repos to keep massu.config.yaml and the .claude/ directory in sync with code. Before the 1.6.0 publish we wanted evidence that the daemon code (unchanged across 1.5.0–1.5.8) was production-stable.
What we have:
- A formal soak-check sentinel writes
verdict: "PASS"after running seven gating criteria (sample count ≥ 100, alive percentage ≥ 99%, RSS p99 under budget, zero errors, RSS slope under leak threshold, and so on). git diff --stat v1.5.0..HEAD -- packages/core/src/watch/returns empty — the watcher source has not changed since the 1.5.0 release commit.- 561 continuous samples spanning 30.4 hours: 100% alive, zero errors, RSS averaging 196.6 MB against a 700 MB budget.
This is a deliberately narrow claim. We are not saying "production-grade for every workload"; we are saying "the criteria the project itself defined for the gate are satisfied with the data we have."
Patches since 1.6.0
The two days following 1.6.0 produced four more releases — three patches and one cohesive minor — each closing a structural drift class surfaced in operation:
@massu/core@1.6.1—plan-changelog-sot(2026-05-10). The website/changelogpage rendered a hardcodedChangelogEntry[]array stale by 5+ major releases (last entry0.6.3, mismatched0.xscheme vs npm's1.x). Replaced with build-time parser of the canonicalCHANGELOG.md; vitest drift-guard test asserts every## [X.Y.Z]heading produces exactly one rendered entry. Website-only patch; daemon code unchanged.
@massu/core@1.6.2—plan-1.6.2-server-lazy-db-deps(2026-05-10). Daemon-code patch eliminating the structural bug where every MCP tool/call eagerly opened both CodeGraph + Data SQLite DBs at the top-level dispatcher. In any repo without.codegraph/codegraph.db, all tools failed — even memory/audit/knowledge tools with no logical codegraph dependency. Bug class is now structurally impossible via a typed per-toolTOOL_DB_NEEDSmanifest + AST drift-guard + pattern-scanner Check 14.
@massu/core@1.6.3—plan-1.6.3-website-feature-discoverability(2026-05-11). Closed two structural drift classes surfaced when "where do these changelogs show up on the website?" produced an awkward answer: (a) the/changelogroute added in 1.6.1 had no nav link; (b) the parser fix from 1.6.1 + EXPECTED_COUNT bump from 1.6.2 had shipped to npm + git but never deployed to Vercel —massu.ai/changelogwas 33 days stale. Pattern Scanner Check 15 enforces nav-link coverage for every public page; pre-push-light step 8 enforces deploy-staleness lockstep; newCR-48mandates/massu-deployin Stage D of any plan touchingwebsite/.
@massu/core@1.7.0—plan-1.7.0-cohesive-cleanup(2026-05-11). Cohesive minor closing three structural-quality gaps simultaneously: (1) the Feb-2026plan-website-audit(never shipped) is revalidated and SUPERSEDED — stats values onmassu.ai/are now drift-guarded by a vitest test that asserts each stat equals a static derivation from its source-of-truth (packages/core/src/license.tsTOOL_TIER_MAPfor MCP Tools,.claude/commands/massu-*.mdfiles for Workflow Commands, etc.); the CLI Reference doc is expanded from 5 CLI commands to 5 CLI + 59 slash commands with a completeness drift-guard test; the team-tool surface gains a runtime cloud-gate via newisCloudFeatureAvailable()helper. (2)topLevelSrcSubdirsinpackages/core/src/detect/domain-inferrer.tsno longer hardcodesjoin(root, 'src')— it consumes the detected source-dir pipeline; newmonorepo-apps-no-root-srcfixture + 4 new test cases exercise both single-repo non-src/layouts and workspaces-driven monorepos; generalization-scanner Check 5 prevents recurrence. (3) The stalenext: 1.2.1npm dist-tag (4 minors behind, zero documented consumers) is removed; CLAUDE.md### npm dist-tags policysection codifies that onlylatestis maintained going forward; pre-push step 9 enforces.
Honest gaps
Three items remain open in the master plan as of this post:
- The synthetic leak-guard test caught its target on two of three guard variants (Source-of-Truth Discipline + Retro/Full-Tree) but the basic range-mode scanner returned PASS on the same trigger — a follow-up plan should investigate why range-mode missed it.
- The third-party adapter signing flow's last manifest-envelope deployment to
registry.massu.aiis operator-driven and remains pending (the round-trip CI gate is in place; only the live envelope content needs an operator-signed update). - Reference-repo install verification —
npx @massu/core@1.7.0 init --ciagainst six fixture shapes passed in CI, and a focused six-fixture test (Rails / Phoenix / ASP.NET / Spring / Go-chi / Glyphwise) all PASS as of 2026-05-11.
These are honest gaps documented in docs/plans/2026-05-07-massu-to-100-percent.md §6.
Try it
npx @massu/core@1.7.0 initOr in an existing repo:
npm install --save-dev @massu/core@1.7.0
npx massu init --ciFor a specific framework:
npm install @massu/adapter-rails@1.0.0@massu/core@1.7.0 engines field requires Node >=20 <26 — Node 26 is excluded because better-sqlite3@12.x doesn't support it yet (upstream issue, not ours).
Source
Both repos:
github.com/massu-ai/massu— public OSS package, tagsv1.6.0throughv1.7.0.npm:@massu/core@1.7.0— currentlatestdist-tag.
CHANGELOG entries: [1.5.8] and [1.6.0] through [1.7.0] in CHANGELOG.md.