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 viagit rev-parse --show-toplevelinstead of hardcoded/Users/<user>/paths — works for any operator regardless of$USER. Closeswave2-pattern:F4.scripts/kb-staleness-audit.sh(P-E-002) incident-count parser now uses awk-based context-aware count of### Incident #Nentries under the## Incidentssection, properly handles empty-template case. Closeswave2-pattern:F5.scripts/massu-pattern-scanner.sh(P-E-003) addsgawkshim + 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 oninit.ts:655yaml-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. Closeswave1-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')→ ESMimport { 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.jsonpin present,dist/in tarball.packages/core/package.json(P-E-007 + P-E-012 + P-E-015 + P-E-017):mainnow points to./dist/cli.js(was./src/server.ts— pre-modern toolchains failed);exports[\".\"]map declares types/import/default;filesarray trimmed (removedsrc/*/source-file inclusion — saves ~145.tsfiles in tarball; addedCHANGELOG.md+ excludedcommands/README.md);prepublishOnlycopies rootCHANGELOG.mdto 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/activateroute.website/src/lib/logger.ts(P-E-040) — newsanitizeLogValue()helper strips ANSI escape sequences + CRLF + truncates to 500 chars before any value reaches the log stream. Wired into everylogger.warn/error/info/debugcall. Closes log-injection class (wave2-security:F-SEC-019).website/src/lib/og-image.tsx+ 3 newopengraph-image.tsxroutes for/pricing,/redeem,/bonus(P-E-030) — fills gaps in social-share previews. (/activateand/forgot-passwordskipped — 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. Closeswave3-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 = 90exported for session-start hook. Eliminates unbounded-growth class fortool_cost_eventstable.CONTRIBUTING.md(P-E-047) — new "Local Development Troubleshooting" section documents thebetter-sqlite3rebuild recipe (closeswave2-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. Closeswave2-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 underscripts/. 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/ratelimitand@upstash/redismust be exact-pinned (no^/~/range) inwebsite/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.8→2.0.8(exact);@upstash/redis^1.36.2→1.36.2. Security-critical packages now resist silent patch updates.packages/core/src/tests/integration/helpers/supabase-mocks.ts(P-E-005) — 8anytypes →unknownto clear@typescript-eslint/no-explicit-anyESLint 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-importsESLint error.website/src/app/dashboard/layout.tsx+website/src/app/dashboard/settings/billing/page.tsx(P-E-005) —react-hooks/puritydisables 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-effectdisables 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 ineslint.config.mjs). Budget P-E-045 lowered from 90 to 0. - P-E-009
initdetection 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.tsdefersrunDetection+computeFingerprintimports via dynamicawait 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.mddocuments why the pre-1.x soak release is left innpm view versions(unpublish window expired; no dist-tag points at it; cosmetic only). - P-E-018
post-tool-use.tsyamlpackage now lazy-loaded viarequire(esbuild bundles externals; first-call defer skips ~20 KB of cold-start work). - P-E-019 Consolidated PreToolUse gate —
pre-tool-use-gate.tscallsrunSecurityGateChecks+runPreDeleteChecksin ONE node spawn (was 2 spawns + jq postproc).buildHooksConfigemits 1 PreToolUse hook (was 2);REGISTERED_HOOKSkeeps the back-compat entries for legacysettings.local.json. Cuts ~200ms cold-start latency per tool call. - P-E-020 MEMORY.md integrity-check uses structural regex (
# Memory Index+- titlelink lines) instead of brittle fixed-heading list — false positives on operator reorganization eliminated. - P-E-021 Single source of truth for hook timeouts —
lib/hook-timeouts.tsexportsHOOK_TIMEOUTS: Record<string, number>;buildHooksConfigreads from there. Drift-guardhook-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.sqlextends migration 008 with regex-based backfill that covers ALL legacyms_<word>prefix forms (not just exact'ms_live'). Idempotent + verification block. - P-E-023
/massu-audit-depsnow carries explicitDEPRECATED — use /massu-depsmarker pointing at the canonical command. 1-release grace before deletion in 1.13.0. Drift-guarddeprecated-command-warning-present.test.ts(4 cases) pins the deprecation marker. - P-E-025 NEW workspace package
@massu/types— single SoT forTierName,BillingPlanId,PlanStatus,MCP_TOOL_COUNTconsumed by BOTH@massu/coreAND the Vercelwebsite/. Closes DUP-001.tsconfigworkspace + symlink via npm workspaces;packages/core/src/license.tsre-exportsToolTierasTierNamealias for back-compat. Drift-guardmassu-types-consistency.test.ts(3 cases) assertsMCP_TOOL_COUNTmatches between@massu/typesandwebsite/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>withdisablednow omitshref+ addsaria-disabled="true"+role="link"+tabIndex={-1}+onClick preventDefault. Drift-guardbutton-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", othersvariant="secondary". Clear primary action emphasis. - P-E-036 Retry-timer live countdown —
nextRetryAtdeadline 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/activateresponse now includesemail_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 canonicalPlan Token:withplan-prefix; renamedCOMPLETE→SHIPPED. - P-E-044
stripe.ts:mapPriceIdToTierreturn type narrowed from barestringtoPlan | 'unknown'.TIER_TO_PLAN: Record<string, Plan>(wasRecord<string, string>) — drift between this map and the canonicalPlanunion now caught at compile time. - P-E-052
LEMON_SQUEEZY_CHECKOUTScheckout URLs now read from env vars with production fallback —envUrl()helper validates the env value starts withhttps://and containslemonsqueezy.combefore honoring the override. Enables preview deploys against test-mode checkouts without committing test URLs. - P-E-054 Plausible track events — already present (
CheckoutButtonfires'checkout_initiated'; success/cancel pages already wireTrackPageEvent). Audit gap closed by verification. - P-E-055 Contact form honeypot — hidden
websitefield added toContactFields(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.tsextension (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-024Google/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/redeemand/activateconsolidation 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. Incident9e262f2confirmed naive hash approach breaks hydration.docs/deferred-ideas/2026-05-17-knowledge-tools-3db-call.md(P-E-056) —wave1-schema-sync:F-0153-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/typesshared 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.tmpfrom 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).