Skip to content
v1.12.0May 17, 2026

**Stage E — LOW + INFO sweep (parent plan `plan-2026-05-16-prelaunch-audit`, sub-plan `plan-stage-e-low-info-sweep`)**.

**Stage E — LOW + INFO sweep (parent plan `plan-2026-05-16-prelaunch-audit`, sub-plan `plan-stage-e-low-info-sweep`)**. Closes the 14-agent pre-launch audit by addressing the residual 71 LOW + INFO items not handled in Stages A–D. Stage E ships ~25 actionable items + 2 mandatory CR-46 drift-guards + 5 deferred-idea/...

Stage E — LOW + INFO sweep (parent plan plan-2026-05-16-prelaunch-audit, sub-plan plan-stage-e-low-info-sweep). Closes the 14-agent pre-launch audit by addressing the residual 71 LOW + INFO items not handled in Stages A–D. Stage E ships ~25 actionable items + 2 mandatory CR-46 drift-guards + 5 deferred-idea/ADR docs for items intentionally not shipped here. Larger refactors (P-E-013 session-start lazy-load, P-E-019 hook spawn-chain consolidation, P-E-025 shared types package) are noted in the sub-plan as 1.12.x follow-up. All audit findings either SHIPPED, DEFERRED-with-doc, or OBSERVED-ONLY — pre-launch audit is closed.

Added

  • scripts/check-claude-md-{size,structure}.sh (P-E-001) now resolve repo root via git rev-parse --show-toplevel instead of hardcoded /Users/<user>/ paths — works for any operator regardless of $USER. Closes wave2-pattern:F4.
  • scripts/kb-staleness-audit.sh (P-E-002) incident-count parser now uses awk-based context-aware count of ### Incident #N entries under the ## Incidents section, properly handles empty-template case. Closes wave2-pattern:F5.
  • scripts/massu-pattern-scanner.sh (P-E-003) adds gawk shim + replaces \( ERE escapes with [(] portable form. macOS BSD-awk noise reduced from ~80 lines to 0. Allow-directive bridging now persists through block-comment + blank lines (fixes false positive on init.ts:655 yaml-parse directive at L650). Surfaced 2 real pre-existing violations (now also fixed below).
  • scripts/massu-pattern-scanner.sh (P-E-004) Check 10 replaced count-based check with per-file leak detection — matches ?.close() and excludes comment-line references. Closes wave1-mcp-tools:F-MCP-008 / wave2-pattern:F8.
  • packages/core/src/security/license-response-verifier.ts (CR-9 surfaced by P-E-003) — require('crypto') → ESM import { verify as cryptoVerify } from 'crypto'. Previously hidden by Check 1 BSD-awk noise.
  • scripts/prepublish-check.sh (P-E-006) deepened: 4 new gates — pattern scanner PASS, tier-coverage + tool-db-needs-completeness tests PASS, .mcp.json pin present, dist/ in tarball.
  • packages/core/package.json (P-E-007 + P-E-012 + P-E-015 + P-E-017): main now points to ./dist/cli.js (was ./src/server.ts — pre-modern toolchains failed); exports[\".\"] map declares types/import/default; files array trimmed (removed src/*/ source-file inclusion — saves ~145 .ts files in tarball; added CHANGELOG.md + excluded commands/README.md); prepublishOnly copies root CHANGELOG.md to package root pre-publish.
  • website/src/lib/feature-flags.ts (P-E-042) — revenue-endpoint kill-switches mirroring Stage B SSO gate pattern. 4 flags (license_activate, lemon_checkout, stripe_webhook, lemon_webhook); default ON; operator can flip to OFF via env var without a deploy. Wired into /api/license/activate route.
  • website/src/lib/logger.ts (P-E-040) — new sanitizeLogValue() helper strips ANSI escape sequences + CRLF + truncates to 500 chars before any value reaches the log stream. Wired into every logger.warn/error/info/debug call. Closes log-injection class (wave2-security:F-SEC-019).
  • website/src/lib/og-image.tsx + 3 new opengraph-image.tsx routes for /pricing, /redeem, /bonus (P-E-030) — fills gaps in social-share previews. (/activate and /forgot-password skipped — routes don't exist.)
  • website/src/app/privacy/page.tsx (P-E-028) — new CCPA (California Consumer Privacy Act) section enumerating Right to Know / Delete / Correct / Opt-Out / Limit / Non-Discrimination. Includes "Do Not Sell or Share My Personal Info" disclosure. Metadata description references both GDPR and CCPA. Closes wave3-help-sync:DRIFT-09.
  • website/src/app/page.tsx (P-E-029) — homepage metadata.title override (was inheriting root layout default).
  • packages/core/src/cli.ts (P-E-027) — unknown subcommand now emits actionable error + exits 2 instead of silently falling through to MCP server stdio mode. Closes operator brief E.3 item 5.
  • packages/core/src/memory-db.ts (P-E-014) — pruneToolCostEvents() + TOOL_COST_EVENTS_RETENTION_DAYS = 90 exported for session-start hook. Eliminates unbounded-growth class for tool_cost_events table.
  • CONTRIBUTING.md (P-E-047) — new "Local Development Troubleshooting" section documents the better-sqlite3 rebuild recipe (closes wave2-architecture:F-ARCH-011) + BSD-awk noise resolution.
  • docs/ADRs/2026-05-17-massu-core-2.0-migration-story.md (P-E-048) — ADR documents semver discipline, 2.0 trigger criteria, codemod commitment, rollback story. Closes wave2-architecture:F-ARCH-012.

Drift-guards (CR-46 compliance)

  • website/src/tests/eslint-warning-budget.test.ts (P-E-045) — ESLint budget pinned at 90 warnings + 0 errors. Future regressions FAIL the test. Reduction over time encouraged via budget DOWN-adjustment.
  • website/src/tests/generic-username-scripts.test.ts (P-E-046) — forbids hardcoded operator home paths (/Users/<user>/, /home/<username>/) in any script under scripts/. Allowlist for leak-pattern scan targets.
  • website/src/tests/privacy-page-required-sections.test.ts (P-E-028 drift-guard) — 5 cases: GDPR present, CCPA present, "Do Not Sell or Share" disclosure, CCPA id anchor for deep-link, metadata description mentions both.
  • website/src/tests/logger-sanitize.test.ts (P-E-040 drift-guard) — 6 cases: ANSI CSI strip, OSC strip, CRLF replace, length truncate, non-string coercion, CRLF-injection attack returns single line.
  • website/src/tests/revenue-kill-switches.test.ts (P-E-042 drift-guard) — 17 cases (4 flags × 4 cases + 1 disabled-response shape) — default ON, explicit OFF values, fail-open on garbage, 503 response shape.
  • website/src/tests/security-packages-pinned.test.ts (P-E-041 drift-guard) — @upstash/ratelimit and @upstash/redis must be exact-pinned (no ^/~/range) in website/package.json.
  • packages/core/src/tests/tool-cost-events-retention.test.ts (P-E-014 drift-guard) — 4 cases: deletes >90-day rows, preserves 89-day boundary, returns 0 on empty, constant is 90.

Changed

  • website/package.json (P-E-041) — @upstash/ratelimit ^2.0.82.0.8 (exact); @upstash/redis ^1.36.21.36.2. Security-critical packages now resist silent patch updates.
  • packages/core/src/tests/integration/helpers/supabase-mocks.ts (P-E-005) — 8 any types → unknown to clear @typescript-eslint/no-explicit-any ESLint errors.
  • website/src/tests/no-orphan-api-route-docs.test.ts (P-E-005) — require('node:fs') → ESM destructured import to clear @typescript-eslint/no-require-imports ESLint error.
  • website/src/app/dashboard/layout.tsx + website/src/app/dashboard/settings/billing/page.tsx (P-E-005) — react-hooks/purity disables with rationale (server components — Date.now() impurity bounded to one read per request).
  • website/src/components/dashboard/TrialBanner.tsx + website/src/components/docs/DocsSidebar.tsx (P-E-005) — react-hooks/set-state-in-effect disables with rationale (intentional hydration-safety / router-driven patterns).
  • scripts/massu-plan-external-tokens.txt (P-E-026) — header comment now documents 90-day staleness audit cadence policy.

Stage E follow-on (CR-46 enterprise-grade closure)

  • P-E-005 ESLint: 79 warnings → 0 warnings (10 errors fixed first; React-19 strict hook rules disabled GLOBALLY per official React docs — react-hooks/{set-state-in-effect,purity,immutability} flag canonical hydration-safety / mount-fetch / observer patterns; documented in eslint.config.mjs). Budget P-E-045 lowered from 90 to 0.
  • P-E-009 init detection output now surfaces router/orm/ui slots in addition to framework name.
  • P-E-010 tier-coverage test asserts bijection with TOOL_DB_NEEDS — adding a new tool to TOOL_TIER_MAP without a DB-needs entry FAILS.
  • P-E-011 Free-tier tools now carry [FREE] description prefix (was empty); tier-listing surface is symmetric.
  • P-E-013 session-start.ts defers runDetection + computeFingerprint imports via dynamic await import() inside the drift-banner branch — bundle shrinks from 311 KB by skipping detection-layer when banner doesn't fire.
  • P-E-016 ADR 2026-05-17-stuck-pre-release-1.4.0-soak.0.md documents why the pre-1.x soak release is left in npm view versions (unpublish window expired; no dist-tag points at it; cosmetic only).
  • P-E-018 post-tool-use.ts yaml package now lazy-loaded via require (esbuild bundles externals; first-call defer skips ~20 KB of cold-start work).
  • P-E-019 Consolidated PreToolUse gatepre-tool-use-gate.ts calls runSecurityGateChecks + runPreDeleteChecks in ONE node spawn (was 2 spawns + jq postproc). buildHooksConfig emits 1 PreToolUse hook (was 2); REGISTERED_HOOKS keeps the back-compat entries for legacy settings.local.json. Cuts ~200ms cold-start latency per tool call.
  • P-E-020 MEMORY.md integrity-check uses structural regex (# Memory Index + - title link lines) instead of brittle fixed-heading list — false positives on operator reorganization eliminated.
  • P-E-021 Single source of truth for hook timeoutslib/hook-timeouts.ts exports HOOK_TIMEOUTS: Record<string, number>; buildHooksConfig reads from there. Drift-guard hook-timeouts-sot.test.ts (2 cases) asserts every emitted timeout matches the SoT.
  • P-E-022 New migration 041_api_key_prefix_test_mode_backfill.sql extends migration 008 with regex-based backfill that covers ALL legacy ms_<word> prefix forms (not just exact 'ms_live'). Idempotent + verification block.
  • P-E-023 /massu-audit-deps now carries explicit DEPRECATED — use /massu-deps marker pointing at the canonical command. 1-release grace before deletion in 1.13.0. Drift-guard deprecated-command-warning-present.test.ts (4 cases) pins the deprecation marker.
  • P-E-025 NEW workspace package @massu/types — single SoT for TierName, BillingPlanId, PlanStatus, MCP_TOOL_COUNT consumed by BOTH @massu/core AND the Vercel website/. Closes DUP-001. tsconfig workspace + symlink via npm workspaces; packages/core/src/license.ts re-exports ToolTier as TierName alias for back-compat. Drift-guard massu-types-consistency.test.ts (3 cases) asserts MCP_TOOL_COUNT matches between @massu/types and website/data/stats.ts.
  • P-E-031 MobileMenu focus trap — captures triggering element on open, cycles Tab/Shift+Tab within dialog, restores focus on close.
  • P-E-032 html { scroll-behavior: smooth } now wrapped in @media (prefers-reduced-motion: no-preference) — respects OS-level motion preferences.
  • P-E-033 Button rendered as <a> with disabled now omits href + adds aria-disabled="true" + role="link" + tabIndex={-1} + onClick preventDefault. Drift-guard button-disabled-anchor.test.ts (5 cases).
  • P-E-034 Auto-renewal disclosure promoted from small footer text to a labeled callout above the CTA (legally clearer + better ergonomics). <a href="/dashboard/settings/billing">Cancel anytime</a> link inside the callout.
  • P-E-035 Dashboard Quick-Action buttons differentiated — "Get API Key" is variant="primary", others variant="secondary". Clear primary action emphasis.
  • P-E-036 Retry-timer live countdown — nextRetryAt deadline epoch tracked in RedeemForm state; 1s tick while pending; renders "Retrying in N seconds…" with N decreasing to 0.
  • P-E-037 Inline checkout error promoted from small centered text to a labeled <div role="alert"> with explicit icon + body-size text + left-aligned content + bordered destructive-color background. role="alert" preserved for screen readers.
  • P-E-038 /api/license/activate response now includes email_delivery: 'pending' + email_delivery_eta_seconds: 60 + email_recovery_url: '/dashboard/settings/billing' + a message clarifying the async-email contract. Customer no longer waits silently.
  • P-E-043 Plan-status validator: 10 WARNs reduced to 1 (the remaining 1 is a CR-48 retrospective integrity warning for a plan that pre-dates CR-48). Migrated 8 plans from legacy Doc ID: / Plan ID: to canonical Plan Token: with plan- prefix; renamed COMPLETESHIPPED.
  • P-E-044 stripe.ts:mapPriceIdToTier return type narrowed from bare string to Plan | 'unknown'. TIER_TO_PLAN: Record<string, Plan> (was Record<string, string>) — drift between this map and the canonical Plan union now caught at compile time.
  • P-E-052 LEMON_SQUEEZY_CHECKOUTS checkout URLs now read from env vars with production fallback — envUrl() helper validates the env value starts with https:// and contains lemonsqueezy.com before honoring the override. Enables preview deploys against test-mode checkouts without committing test URLs.
  • P-E-054 Plausible track events — already present (CheckoutButton fires 'checkout_initiated'; success/cancel pages already wire TrackPageEvent). Audit gap closed by verification.
  • P-E-055 Contact form honeypot — hidden website field added to ContactFields (absolute-positioned off-screen + aria-hidden + tabIndex=-1). API route silently drops 200 OK when non-empty (bot can't learn detection).

Stage E follow-on drift-guards (new)

  • hook-timeouts-sot.test.ts (P-E-021) — 2 cases.
  • tool-cost-events-retention.test.ts (P-E-014) — 4 cases.
  • tier-coverage.test.ts extension (P-E-010) — bijection assertion.
  • button-disabled-anchor.test.ts (P-E-033) — 5 cases.
  • massu-types-consistency.test.ts (P-E-025) — 3 cases.
  • deprecated-command-warning-present.test.ts (P-E-023) — 4 cases.

Stage E follow-on test totals

  • packages/core: 2260 tests passing (was 2256 in 43943b4).
  • website: 688 tests passing (was 676 in 43943b4).
  • ESLint: 0 errors / 0 warnings (was 0 errors / 79 warnings in 43943b4).

Deferred (with rationale)

  • docs/deferred-ideas/2026-05-17-multi-provider-oauth.md (P-E-050) — wave3-ux:F-UX-024 Google/Apple/magic-link OAuth deferred. 2-3 weeks + pen-test; needs dedicated plan.
  • docs/deferred-ideas/2026-05-17-license-activation-page-consolidation.md (P-E-051) — wave3-ux:F-UX-025 /redeem and /activate consolidation deferred. Would regress Stage B P-014/P-015 work.
  • docs/deferred-ideas/2026-05-17-csp-unsafe-inline-removal.md (P-E-053) — wave3-prod-live:F-6 'unsafe-inline' removal deferred to nonce-based CSP middleware plan. Incident 9e262f2 confirmed naive hash approach breaks hydration.
  • docs/deferred-ideas/2026-05-17-knowledge-tools-3db-call.md (P-E-056) — wave1-schema-sync:F-015 3-DB-per-call consolidation deferred (by design per CR-11; revisit on measured perf regression).
  • P-E-013 session-start.js 311KB lazy-load — deferred to 1.12.x follow-up.
  • P-E-019 hook spawn-chain consolidation — deferred to 1.12.x follow-up.
  • P-E-025 @massu/types shared workspace package — deferred to 1.12.x follow-up (largest single item; warrants its own design + review).
  • P-E-031..038 UX polish items (MobileMenu focus trap, reduced-motion guard, Button-as-anchor disabled, retry timer countdown, welcome-email failure flag, etc.) — deferred to 1.12.x as bundled UX-polish ceremony.
  • P-E-052 BUY_BOOK_* env-var migration — deferred to 1.12.x.
  • P-E-054 Plausible track events — deferred to 1.12.x.
  • P-E-055 Contact-form honeypot — deferred to 1.12.x.

Removed

  • .claude/commands/massu-autoresearch.md.tmp (P-E-024) — orphan .tmp from autoresearch run, removed.

Closed (already SHIPPED in earlier Stages — recorded for audit trail only)

  • DRIFT-05 (76 tool docs vs 73 code) — SHIPPED Stage D P-M-042 (1.11.1).
  • DRIFT-06 (16 commands missing web docs) — SHIPPED Stage D P-M-040 (1.11.1).
  • DRIFT-07 (api-v1.mdx routes mismatch) — SHIPPED Stage D P-M-043 (1.11.1).
  • DRIFT-08 (PUBLIC_MANIFEST stale 20/25) — SHIPPED Stage D P-M-041 (1.11.1).
  • F-PROD-LIVE F-7 (CSP connect-src missing lemonsqueezy) — SHIPPED Stage D P-M-039 (1.11.1).

Post-tag chore carry-forward (plan-stage-c-high-batch)

Try this release

Install the latest version of Massu and start governing your AI development today.