# FvW Alignment Audit — Phase 4 — Gap Analysis (Forward-Only Framing) **Date:** 2026-09-14 **Audit lane:** id 9 (vibecoder-standalone-mavis) **Code HEAD:** a2062aa (post b2994 drift guard) **Doctrine HEAD:** c6ae6f7f (post b30XX ratification of v8.6.0) **Predecessors:** Phase 1 = b2998, Phase 2 = b2999, Phase 3 = b3001 --- ## Phase 0 — Verification - **STATUS: PASSED.** - `git pull --ff-only origin main` in `/workspace/fv-module-gallery`: HEAD advanced c8fba08 → c6ae6f7f. 3 new commits. Ratification commit `2bde2b0 b30XX: ratify FvW v8.6.0 as forward-only` by id 8 (fv-gallery-mavis), 2026-09-14. - `VERSION`: `8.5.0` → **`8.6.0`** ✓ - `validator-v8.json` `fvw_version`: `8.6.0-proposed` → **`8.6.0`** ✓ - §00.12.11 forward-only clause **PRESENT** (after §00.12.8 in document order, but correctly titled and complete) - Amendment pack `2026-09-12-fvw-v8-6-0/` STATUS: `PROPOSED` → **`RATIFIED`** - G40 (gate) defined 10× in validator-v8.json; G41 defined 1× ✓ - **Forward-only clause text:** > "This standard applies to all modules created or substantially modified after the ratification date. Modules existing at ratification are exempt from retroactive compliance. They are brought into compliance incrementally, as part of normal work. … No module is 'non-compliant.' Only 'not yet migrated.'" Verbatim — module statuses are now exactly three: **COMPLIANT / MIGRATING / LEGACY**. The audit reuses these terms. --- ## Migration map (Phase 3 §00.12 debt → forward-only) | P | Phase 3 verdict | Phase 4 refactor | Migration effort when touched | |---|---|---|---| | 1. Units (px usage) | NON-COMPLIANT (4,113 px lines) | **LEGACY** | HIGH (multi-week; convert layout primitives to rem/vw, keep px for icon/border/shadow per §00.12 exception) | | 2. Typography (rem) | NON-COMPLIANT (99% px) | **LEGACY** | HIGH (coupled with P1) | | 3. Contrast WCAG AA | UNMEASURABLE (no tooling) | **LEGACY** (and unmeasurable) | UNKNOWN until axe-core wired; migrate as surfaces touched | | 4. Motion (prefers-reduced-motion) | NON-COMPLIANT (248 anim, 0 wrappers) | **LEGACY** | HIGH (wrapper rule + audit 248 declarations when any touched) | | 5. ARIA / keyboard | PARTIAL (138 ARIA, 4 keyDown) | **MIGRATING** | HIGH per-component (per surface, low overall) | | 6. Responsive 320–4K | PARTIAL (480–900px band) | **MIGRATING** | LOW when breakpoint logic added | | 7. CWV | UNMEASURABLE (no tooling) | **LEGACY** | UNKNOWN until web-vitals wired | | 8. Empty/error states | PARTIAL (26 fallbacks) | **MIGRATING** | LOW per-component | | 9. No legacy patterns | COMPLIANT (0 deprecated) | **COMPLIANT** | NONE (already there) | | 10. By-construction (CI gates) | NON-COMPLIANT (no CI) | **LEGACY** (and unmeasurable today) | HIGH (build gate infrastructure required) | | FVRE clause (§00.12.4) | NOT WIRED | **LEGACY** | HIGH (FVRE subprocess per FvW §26) | **Cumulative picture:** 1 principle (P9) is COMPLIANT today. The remaining 10 are LEGACY (6) or MIGRATING (3), with no NEW compliance work required for existing code until a "substantial modification" lands on the touch surface. NEW work must comply from creation. --- ## Section A — Critical (correctness, security, blockers) Items that block production readiness independent of doctrine: 1. **Pact guard recursion / cyclic loading** — `app-pact/loaders/*.ts` includes sovereign, autonomous, offline, communication, module-map, sandbox, gallery, cross-app — 8 loaders. Verify no cyclic import; verify each loader is idempotent under repeated `init()` calls. (Source: Phase 2 finding — pact is REAL and read by 10 bridge loaders.) 2. **Bridge server.cjs monolith risk** — 5,317 lines, 183 routes in a single CJS module. Any unhandled exception in one route can kill the process. Refactor is critical infrastructure hygiene, not doctrine-driven. 3. **CJS dynamic-import guard in `.js` mount fns** — known trap (see `oscarweb` topic). Audit any host-boot mount fn for `await import('./X.tsx')` and `await import('react-dom/client')` patterns and refactor to static imports. 4. **Trace atlas non-conformant field naming** — current atlas uses camelCase while §04.3 ratifies snake_case. Worst case: a downstream consumer validates against the schema and rejects. Decision before any regeneration: keep camelCase (legacy holder), or migrate mid-flight. 5. **Consolidated layout single source of intent** — `app-recipe/manifest.json` is the ONLY document explaining the 8→14-dir consolidation. If corrupted, the design intent is lost. Duplicate to `app-shell/README.md` or `docs/architecture/vibecoder-profile.md`. **Count: 5 critical items.** None retroactive on doctrine. All structural / process. --- ## Section B — Structural (tooling, generators, CI) The three structural gaps Phase 3 identified. Forward-only — these tools exist to validate NEW work and to verify that touched modules migrate. 1. **Trace atlas generator** — currently absent. Author `tools/generate-trace-atlas.cjs` that walks src/, app-surfaces/, app-behaviours/, app-modules/ and emits `app-trace-atlas/atlas.json` in snake_case (§04.3). Hand-walk first generation; automate thereafter. **Stays per-feature: regenerate only when touched, not on a schedule.** 2. **PACT index generator** — currently absent (5 indexes: surface/lifecycle/host/naming/contradiction-docket). Author `tools/generate-pact-indexes.cjs` that reads registry/source graph and emits the 5 markdown files. **Same constraint: regenerate as features touch, not nightly.** 3. **CI wiring (build gates)** — no `.github/workflows/`, no `.gitlab-ci.yml`. Add `.github/workflows/verify.yml` that runs (a) `vitest run app-vp` to execute the 5 VP test files Phase 3 found, (b) the planned trace-atlas generator in dry-run mode against current code (diffs must be empty for untouched code, non-empty + intentional for touched code). **For NEW modules only, backward test legacy to prove no regression.** 4. **§00.12 tooling** — install `axe-core` and `web-vitals` as devDependencies. Wire to a `tools/check-uistd.cjs` script. **Apply to NEW components + any legacy component being substantially modified.** A test passes once written and need not retroactively scan untouched components. **Count: 4 structural items.** Each pays forward; none retroactively assess. --- ## Section C — Forward-only migration enablers These make NEW work compliant by default; touched LEGACY work migrates as it touches. 1. **ESLint / TypeScript rule enforcing §00.12 units** — add `no-restricted-syntax` rule in `.eslintrc` forbidding CSS `px` literals (except the §00.12 exceptions: icon sizes via `1rem`/`2rem`, borders `1px`, shadow blur values). Apply to NEW files + touched files. The rule does NOT scan unchanged files. 2. **pre-commit hook for §00.12 sanity** — Husky + lint-staged. On commit, runs: `tools/check-uistd.cjs --changed-only` against staged files. Forward-only by design. 3. **Shared `prefers-reduced-motion` wrapper component** — `` / `` React components in `src/components/motion-safe/`. NEW components import this by default. Existing components migrated when touched (search-replace `transition`/`animation` props with ``). 4. **ARIA build-time check** — script `tools/check-aria.cjs` walks `.tsx` files (changed-only mode by default), validates that interactive components have `aria-label`, `aria-controls`, or are wrapped in semantic `