Pre-push ↔ CI parity (plan-2026-05-18-pre-push-ci-parity). Closes the structural drift class surfaced 2026-05-18 when SHA b26fbb1 passed pre-push-light locally but failed CI on 4 distinct gates spread across 3 separate workflow YAMLs (@massu/types/dist missing → ci.yml, eslint-rules/ missing from PUBLIC_DIRS → sync-check.yml, diff-commands-vs-docs.sh hardcoded path → sync-check.yml, Tarball E2E adapter list stale → ci.yml). The two operator-pushed fix attempts 8c6b843 + d3164f7 fixed the specific instances but left the bug class wide open. This release closes the CLASS via three-layer enforcement.
Added
- CR-50 / VR-CI-PARITY — structural pre-push ↔ CI parity drift-guard. Every multi-line shell block (>5 lines) in ANY
.github/workflows/.yml(excluding.public.ymlmirrors + 6 INFRASTRUCTURE/SECURITY workflows inWORKFLOW_FILE_EXCLUSIONS) lives inscripts/ci-<name>.sh; every such script is called fromscripts/pre-push-light.shOR carries# CI-ONLY:opt-out + entry inCI_ONLY_SCRIPTSallowlist. Three-layer enforcement: vitest drift-guardpackages/core/src/tests/ci-prepush-parity.test.ts(7 cases, including byte-equivalence mirror-enforcement between TS test sets and bash scanner arrays) + pattern-scanner Check 26 + workspace-build-freshness step[12/15]. scripts/ci-tarball-e2e.sh— extracted Tarball E2E adapter-pack verification. Adapter list filesystem-derived (find packages/adapter-*); supports--quickmode for pre-push-light.scripts/ci-sync-check.sh— extracted public-mirror sync verification withmktemp -d+trap cleanup EXIT INT TERMsafety contract; called from bothsync-check.ymland pre-push-light step[13/15]. Secrets scan extended to cover ALL file types (not just.ts+.md) AND addedrk_test_/rk_live_restricted-key +whsec_webhook-secret regex variants.scripts/ci-fresh-install.sh(CI-ONLY) —init --cifixture runner withlocal+publishedmodes via$2. Fixture-name validated against^[a-z][a-z0-9_-]*$regex to prevent path traversal.scripts/ci-config-drift.sh(CI-ONLY) — workspace-shadow-avoiding scratch-dir setup formassu config check-drift.scripts/lib/mtime-helper.sh— cross-platform BSD/GNUstatshim with python3 fallback. Sourced bypre-push-light.shstep[12/15]Workspace Build Freshness.scripts/test-ci-parity-regression.sh— AC-PARITY-REGRESSION automated test (ephemeralgit clone --no-local+git revert 8c6b843 d3164f7+npm ci+ pre-push-light exit-code assertion). Cited markers:PARITY-REGRESSION-TEST: PASS|FAIL|ABORT.- 5 new
pre-push-light.shsteps:[0/15]Clean-state simulation (opt-in viaMASSU_PREPUSH_CLEAN=1),[12/15]Workspace Build Freshness,[13/15]Sync Check (auto-gated onpackages/+scripts/+CHANGELOG.md+...),[14/15]Tarball E2E quick,[15/15]Config Drift. - 4 bypass env-vars threaded with audit-trail stderr markers mirroring CR-48 precedent:
MASSU_PREPUSH_CLEAN,MASSU_SKIP_NEW_STEPS,MASSU_PREPUSH_SYNC_CHECK,MASSU_SYNC_PUBLIC_CHECK_ONLY.
Changed
scripts/pre-push-light.shrenumbered fromN/11toN/15label scheme (16 total labels — Plan-Token Changelog Currency REMOVED per P2-006 iter-5 resolution; absorbed bychangelog-parse.test.tsEXPECTED_COUNT drift-guard running via[6/15] Tests).[9/15] Deploy Stalenessparser fixed to scan for firstPASS:|SKIP:|WARN:line rather than first log line (pre-existing minor bug masked by stderr/stdout merging — pre-push-light now correctly shows SKIP underMASSU_SKIP_DEPLOY_STALENESS_CHECK=1).scripts/sync-public.shaddscheck_public_dirs_completeness()drift-guard catching futurePUBLIC_DIRSomissions structurally (greps cross-package test imports). NewMASSU_SYNC_PUBLIC_CHECK_ONLY=1env-var runs drift-guard then exits 0 with no filesystem side-effects (AC-12 contract)..github/workflows/{ci,sync-check,fresh-install-matrix,massu-config-drift}.yml— 4 in-scope workflows now delegate toscripts/ci-*.sh(thin orchestration); 7 excluded workflows remain inline with per-entry justification comments inWORKFLOW_FILE_EXCLUSIONS.scripts/massu-pattern-scanner.shadds Check 26 (Pre-push ↔ CI parity). Awk regex covers all YAML block-scalar variants (|,|-,|+,>,>-,>+) — prior|only would silently bypass..claude/CLAUDE.mdadds CR-50 row + VR-CI-PARITY row + inline### CR-50: Pre-Push Must Mirror CIblock.website/CHANGELOG.mdsynced to root CHANGELOG.md byte-equal (drift-guardwebsite-changelog-matches-root.test.ts).website/src/tests/changelog-parse.test.ts:EXPECTED_COUNTbumped 39 → 40.
Fixed
- Closes the 2026-05-18 incident class (4 CI-only failure modes on SHAs
b26fbb1,8c6b843,d3164f7). scripts/pre-push-light.shstep[9/15]deploy-staleness status parser pre-existing bug — first log line was the stderr audit-trail marker, not the stdout PASS/SKIP line (CR-9 fix surfaced during multi-perspective review).