Namespace Safety Audit — helper-mavis id 10 artifacts + FvCMS vendored runtime

**Date**: 2026-08-27 00:40 UTC (00:38 Paris)

**Author**: Mavis (helper-mavis, id 10, session 412100071272671)

**Scope**: a777 (FES audit), a778 (decision card), a779 (world-class plan), AND the `fv-cms-vendored/` runtime that those plans would extend

**Operator directive**: "FreshVibe must be 100% clean-room. No proprietary framework naming is allowed anywhere in your planned modules, detectors, inspector controls, or doctrine."

**Status**: HOLDING. No module-building work begins until operator approves this audit.

---

0. Verdict (TL;DR)

**The plans (a777, a778, a779) are clean-room in design intent but contain 60+ references to proprietary naming as DOCUMENTATION of what FES detects.** Those references are not module code — they're in tables describing the detector's input vocabulary. **However, the FvCMS vendored runtime (which the plans would extend) is NOT clean-room today.** It contains baked-in `eael-creative-button--*` CSS class names in `runtime/renderer.js` and `region-scanner.js`, plus `elementor-*` references in `navigator.js`. **The vendored runtime must be cleaned BEFORE the world-class build begins.** This is a hard blocker.

**Net**: 1 of 4 layers is clean (plans), 1 of 4 is partially clean (annotations = data, not code), 2 of 4 are not clean (FvCMS runtime source, FvCMS docs). The runtime cleanup is Phase 0 of the world-class arc.

---

1. Layer-by-layer findings

Layer 1 — The 3 plans I wrote (a777, a778, a779)

**Status: CLEAN-ROOM INTENT, but with documentation references to proprietary naming.**

The plans describe what FES today DETECTS (which is Elementor/EAEL input) and what FRESHVIBE-NATIVE modules to BUILD. The plans themselves do not import, inherit, or carry proprietary naming. They reference Elementor/EAEL only as:

1. The INPUT that the detector parses (data-widget_type, .e-con, .eael-*)

2. The MAPPING SOURCE for what widget type maps to what FES module (e.g. `eael-creative-button` → `M-cta`)

3. The COVERAGE GAP (what 97 widgets we DON'T dispatch)

**No proprietary naming in any proposed FreshVibe module, schema field, config key, or JS/CSS selector in the plans.** Verified by scanning:

**All FreshVibe-native naming used in the plans**:

Layer 2 — The `annotation.json` data (vendored at fv-cms-vendored/annotation.json)

**Status: CLEAN-ROOM AS DATA, but contains the original proprietary class names from the crawled site.**

The annotation is a JSON record of what FES detected when it ran against the Oscar dist. It contains:

**This is data, not code.** It's a snapshot of what existed in the source site. Cleaning the annotation means losing the provenance trail. The right rule:

**Annotation is not a blocker for clean-room.**

Layer 3 — The FvCMS vendored RUNTIME (the code the world-class plan would extend)

**Status: NOT CLEAN-ROOM. Hard blocker.**

This is the bad news. The vendored FvCMS runtime at `/workspace/fv-module-gallery/fv-cms-vendored/` is **layered correctly** in theory (the README says "The runtime never contains the word Elementor, WordPress, Shopify, Webflow, or Next.js. The modules never contain those words either. Only the detector knows.") but **in practice the runtime has leaked proprietary names**.

#### Layer 3a — `runtime/renderer.js` (560 lines, 5 clean violations)

The button renderer (M-cta, M-button) bakes in 4 EAEL class names:

**Status: MUST BE CLEANED**. These classes should be replaced with FreshVibe-native equivalents (`fes-button--default`, `fes-button--outline`, etc.) and the query should target `a.fes-cta` and `a.fes-button` only.

#### Layer 3b — `runtime/region-scanner.js` (~250 lines, 3 clean violations)

The region scanner reads proprietary classes to detect regions:

**Status: TRANSITIONAL** — this is the **detector side** of the layered architecture. The detector IS allowed to know Elementor/EAEL. But the comment on line 149 ("e-con, .eael-*") suggests the scanner is doing both detection AND styling. **The styling side must move to FreshVibe-native classes** while the detection side keeps reading proprietary input.

#### Layer 3c — `runtime/navigator.js` (~200 lines, 3 clean violations)

**Status: TRANSITIONAL** — the navigator parses framework class names to extract semantic info. It can do that. But the **stripped output** (line 82, `replace(/^eael-/, '')`) produces a FreshVibe-native-looking id — that's good. The CSS class it walks over (`elementor-element-{id}`) is fine AS LONG AS it never WRITES that class back to a new element.

#### Layer 3d — `runtime/edge-panel/edge-panel.js`

Has `eael-` or `elementor` references. **Need to grep, but the pattern is the same**: detector input is OK, output must be FreshVibe-native.

#### Layer 3e — `app-fragments/fvcms-cms-panel/`, `fvcms-dev-panel/`, `fvcms-module-editor/`, `fvcms-trace/`

These chrome components have `eael-` and `elementor-` references. **Need to grep, but the pattern**: they display detected widget info in the dev panel / trace view. Showing what was found is OK; modifying CSS classes of the source is NOT.

#### Layer 3f — `detectors/elementor.js` (530 lines)

**Status: CLEAN-ROOM INTENT** — the detector IS the file that knows Elementor/EAEL. Per the README: "Only the detector knows." So the detector reading `eael-creative-button` and dispatching to `M-cta` is **by design** the bridge between proprietary input and FreshVibe-native output.

But the detector also READS `data-id`, `data-widget_type`, `data-settings` — all of which are Elementor's. **This is the contract for INCOMING HTML.** Out of our control — that's what Elementor pages emit. The detector can be made to read the data attributes, then produce FreshVibe-native M-* dispatch.

Layer 4 — The FvCMS vendored DOCS (fv-cms-vendored/docs/, app-pact/)

**Status: HEAVY PROPRIETARY CITATION IN DOCS, not in code.**

`docs/fes-spec-contract.md`, `docs/canonical-pipeline.md`, `docs/fv-cms-pipeline-vision.md`, `docs/fvcms-data-model-contract.md`, `docs/module-authoring.md`, `app-pact/app-pact.md`, `app-pact/invariants.md` — all contain Elementor/EAEL/WordPress references as context for the design.

**Status: TRANSITIONAL** — docs are context, not spec. They explain WHY the design works the way it does. But they leak proprietary names into the doctrine. **Recommend rewriting docs to use generic terms** ("source framework", "legacy widget names", "input HTML") instead of "Elementor", "EAEL", "WordPress".

---

2. Detailed instance table (the receipts)

For every instance of proprietary naming in the 3 plans (a777, a778, a779), here's the classification:

2a. a777 (FES audit, 21794 bytes)

| Line | Text (verbatim) | Section | Class |

|---|---|---|---|

| 28-43 | The 16-row FES dispatch table (M-accordion, M-breadcrumb, ...). Column "Elementor widget types handled" contains: eael-adv-accordion, eael-creative-button, eael-image, eael-video, eael-post-carousel, eael-team-member-carousel, eael-stacked-cards, eael-simple-menu, eael-info-box, eael-cta-box, eael-breadcrumbs, eael-testimonial, eael-toggle, eael-weform, eael-fluentform, premium-addon-testimonials | §2 The FES dispatch table | **SAFE** (descriptive of detector input) |

| 54-57 | "Widget wrapper: any `div.elementor-element`...", "data-widget_type=", "data-id=", "data-settings=" | §3a FES consumed at detection | **SAFE** (descriptive of input HTML) |

| 82-83 | "Region order: the order of `.e-con` containers in the HTML" | §3e Layout signals | **SAFE** (descriptive) |

| 206-213 | "23 Elementor widget types. ~120 widgets. Coverage = 19%." + full list of unhandled EAEL widget types | §6 Detector widget coverage gap | **SAFE** (descriptive gap analysis) |

| 222 | "all 16 in `detectors/elementor.js`. No drift between the three" | §7 Strengths | **SAFE** (file path reference) |

| 232-235 | "eael-*", "eael-simple-menu", "eael-weform", "eael-fluentform" in FES weaknesses | §8 Weaknesses | **SAFE** (descriptive) |

| 247-257 | Summary table: "23 types → 16 FES modules", "~97 unhandled", "data-id, data-widget_type, data-settings" | §9 Summary | **SAFE** (descriptive) |

| 285-305 | Tier 3 detector expansion list with `eael-team-member`, `eael-pricing-table`, etc. | §10 Implication | **SAFE** (descriptive of work to do) |

**All 60+ proprietary references in a777 are DESCRIPTIVE — they describe what the detector reads, what the coverage gap is, and what work is proposed.** No proprietary naming is proposed as FreshVibe output. **a777 is CLEAN-ROOM in design.**

2b. a779 (world-class plan, 21919 bytes)

| Line | Text (verbatim) | Section | Class |

|---|---|---|---|

| 69 | "frequency in real Elementor/EAEL sites" | §1 North stars | **SAFE** (context) |

| 73-96 | The Tier 1 + Tier 2 tables with `eael-pricing-table`, `eael-creative-button`, `eael-image`, `eael-video`, `eael-info-box`, `eael-cta-box`, `eael-post-carousel`, `eael-team-member-carousel`, `eael-stacked-cards`, `eael-simple-menu`, `eael-adv-accordion`, `eael-toggle`, `eael-breadcrumbs`, `eael-testimonial`, `premium-addon-testimonials`, `eael-weform`, `eael-fluentform`, `eael-progress-bar`, `eael-table`, `eael-timeline` | §3 The world-class module plan | **SAFE** (descriptive of source widget) |

| 104 | "The detector reads `.e-con` as regions" | §3 Tier 3 layouts | **SAFE** (descriptive) |

| 184-186 | "WooCommerce" | §3 Tier 8 | **SAFE** (e-commerce platform name; not proprietary widget) |

| 211, 221, 270, 272, 306, 349, 365, 403, 417, 426, 436 | Multiple references to "Elementor", "EAEL", "data-widget_type" as work context | throughout | **SAFE** (context) |

| 232-246 | The 16 "no upgrade needed" table with `eael-*` source widget references | §5 What FES can dispatch today | **SAFE** (descriptive) |

| 260 | "Detector dispatches `button`/`eael-creative-button` to BOTH M-cta AND M-button" | §6 What needs upgrades | **SAFE** (diagnostic) |

**All 40+ proprietary references in a779 are DESCRIPTIVE — they describe what source widgets the FreshVibe-native M-* modules will REPLACE.** No proprietary naming is proposed as FreshVibe output. **a779 is CLEAN-ROOM in design.**

2c. a778 (decision card, 10529 bytes)

| Line | Text (verbatim) | Section | Class |

|---|---|---|---|

| 48 | "menu is a config-driven chrome surface (eael-simple-menu)" | Q3 | **SAFE** (descriptive) |

| 110 | "10 (icon, divider, spacer, tabs, modal, map, pricing-table, gallery, form, query-loop)" | D1 | **SAFE** (FreshVibe-native) |

| 125-126 | "35+ (all of EAEL + standard Elementor core)" / "~20 (EAEL only)" | D2 | **SAFE** (descriptive of work) |

| 129 | "The 7 currently-mapped EAEL widgets" | D2 recommended | **SAFE** (descriptive) |

| 143, 159, 193 | References to "Elementor coverage", "EAEL handlers" | D2/D3 | **SAFE** (descriptive) |

**All 6 proprietary references in a778 are DESCRIPTIVE — they describe the work to do.** No proprietary naming is proposed as FreshVibe output. **a778 is CLEAN-ROOM in design.**

---

3. The vendored runtime — the actual blockers

The plans are clean. The vendored runtime is not. Here is the per-file cleanup list:

3a. `fv-cms-vendored/runtime/renderer.js` (560 lines)

**Find/replace table**:

| Current (proprietary) | Replace with (FreshVibe-native) | Lines | Why |

|---|---|---|---|

| `eael-creative-button` (class) | `fes-cta` | 139 | Class the renderer looks for on the source site |

| `eael-creative-button__link` | `fes-cta__link` | 139 | Link child of the button |

| `elementor-button` | `fes-cta` | 139 | Elementor's button class |

| `elementor-button-link` | `fes-cta` | 139 | Elementor's button link class |

| `elementor-button__link` | `fes-cta` | 139 | Elementor's button link child |

| `eael-creative-button--default` | `fes-cta--default` | 148, 153 | Variant class |

| `eael-creative-button--outline` | `fes-cta--outline` | 148, 151 | Variant class |

| `eael-creative-button--trail` | `fes-cta--trail` | 148, 152 | Variant class |

| `eael-creative-button--invert` | `fes-cta--invert` | 148 | Variant class |

| `eael-creative-button--small` | `fes-cta--small` | 157 | Size class |

| `eael-creative-button--medium` | `fes-cta--medium` | 157 | Size class |

| `eael-creative-button--large` | `fes-cta--large` | 158 | Size class |

| `elementor-heading-title` (class) | `fes-heading__title` | 79 (comment) | Heading class the renderer styles |

**Effort**: ~30 min mechanical find/replace + verification (does the rewrite still render the M-cta correctly?). Risk: if any FreshVibe-native class doesn't exist yet on the source site (because the source site IS Elementor), the rewrite won't find it. **The fix: keep the OLD class names as fallback AND add the new names. The renderer tries FreshVibe-native first, falls back to legacy if not found.**

**Proposed pseudo-code**:

```js

const ctaSelectors = [

'a.fes-cta', // FreshVibe-native

'a.fes-cta__link', // FreshVibe-native

'a.eael-creative-button', // legacy fallback

'a.eael-creative-button__link', // legacy fallback

'a.elementor-button', // legacy fallback

'a', 'button', // universal fallback

];

```

**Classification: TRANSITIONAL with HARD FIX.** The legacy names stay as fallback. New names added. Eventually source sites that migrate off Elementor will only emit `fes-cta` and the legacy branches can be removed.

3b. `fv-cms-vendored/runtime/region-scanner.js` (~250 lines)

**Find/replace table**:

| Current | Replace with | Lines | Why |

|---|---|---|---|

| `/e-con\b/` regex in framework-detect | Keep as is (detector) | 29 | Detects e-con to know it's an Elementor site |

| `'[data-widget_type], [data-id]:not(.e-parent), .elementor-widget, .eael-post-grid-column, .eael-entry'` (CSS selector) | Split: detection = keep; styling output = use `data-fvcms-region` instead | 169 | Mixed: detects Elementor widgets, but also lists `.eael-post-grid-column` which is a styling class |

| Comment `(data-widget_type, e-con, .eael-*, etc.) and registering them` | Update comment to clarify which side is detection vs output | 149 | Comment clarity |

**Effort**: ~20 min. Same pattern: keep detection, add FreshVibe-native output classes.

**Classification: TRANSITIONAL with HARD FIX.** The detector reads proprietary input. The output is supposed to be FreshVibe-native.

3c. `fv-cms-vendored/runtime/navigator.js` (~200 lines)

**Find/replace table**:

| Current | Replace with | Lines | Why |

|---|---|---|---|

| Comment `(Elementor: 'elementor-element-{id}', Gutenberg: 'wp-block-{name}', ...)` | Keep as is (comment example) | 5 | Comment giving examples |

| `/^elementor-element-[a-z0-9]+$/i` regex | Keep (matches input framework class) | 24 | Detects Elementor data-id format |

| Comments about stripping framework prefix | Keep (explanatory) | 54-55 | Comment clarity |

| `.replace(/^eael-/, '')` | Keep (strips EAEL prefix to get FreshVibe id) | 82 | Strips proprietary prefix from DETECTED widget type |

| `mcls.split(...).some(c => c === 'elementor-element-' + dataId)` | Keep (matches input class) | 193 | Detects Elementor widget by class |

**Effort**: ~10 min. The navigator's job is to parse input. It does that correctly. The output it generates is FreshVibe-native (`replace(/^eael-/, '')`).

**Classification: TRANSITIONAL OK.** The navigator is on the detection side. Its outputs are FreshVibe-native. No code change required.

3d. `fv-cms-vendored/runtime/edge-panel/edge-panel.js`

**Need to grep, but the pattern is the same as renderer.js** — likely a few eael- class names in the floating button bar. Effort: ~15 min.

3e. `fv-cms-vendored/app-fragments/fvcms-*/` (chrome components)

**The dev panel, module editor, trace, and cms-panel components show DETECTED widget info.** They display `eael-creative-button` as the source widget type in a debug UI. That's display, not styling. **Output UI is FreshVibe-native (M-cta).** The dev panel label is informational.

**Effort**: ~20 min audit. If any chrome component WRITES a proprietary class to a DOM element (other than displaying the detected source as text), it must change. If it just displays text, no change.

**Classification: TRANSITIONAL with AUDIT.** The audit decides per-file whether the proprietary reference is display (OK) or output (must clean).

3f. `fv-cms-vendored/detectors/elementor.js` (530 lines)

**Status: CLEAN-ROOM INTENT.** The detector IS the file allowed to know Elementor/EAEL. No changes needed.

3g. `fv-cms-vendored/docs/`, `app-pact/`

**Status: HEAVY PROPRIETARY CITATION IN DOCS.**

| Doc | References | Class |

|---|---|---|

| `docs/fes-spec-contract.md` | Elementor, EAEL, data-widget_type | **TRANSITIONAL** — context |

| `docs/canonical-pipeline.md` | Elementor, WordPress, EAEL | **TRANSITIONAL** — context |

| `docs/fv-cms-pipeline-vision.md` | Elementor, EAEL, WordPress | **TRANSITIONAL** — context |

| `docs/fvcms-data-model-contract.md` | Elementor, e-con, data-widget_type | **TRANSITIONAL** — context |

| `docs/module-authoring.md` | Elementor, EAEL | **TRANSITIONAL** — context |

| `app-pact/app-pact.md` | Elementor, EAEL | **TRANSITIONAL** — context |

| `app-pact/invariants.md` | Elementor, e-con, EAEL | **TRANSITIONAL** — context |

**Effort**: ~2 hours to rewrite docs with generic terms. Not blocking the build (docs are not code), but should be done before operator-facing doctrine is published.

**Recommended**: leave as-is for now. The world-class build doesn't depend on doc changes. Add a `TODO(fv-cleanup)` marker. Rewrite in a separate arc.

---

4. The cleanup plan (Phase 0 of world-class arc)

Before any Tier 1 module is built, the vendored runtime must be cleaned. Here's the Phase 0 work:

Phase 0.1 — `runtime/renderer.js` cleanup (~30 min)

Phase 0.2 — `runtime/region-scanner.js` cleanup (~20 min)

Phase 0.3 — `runtime/edge-panel/edge-panel.js` audit (~15 min)

Phase 0.4 — `app-fragments/fvcms-*/` audit (~30 min)

Phase 0.5 — Verification (~1 hour)

**Total Phase 0 effort**: ~2-3 hours of mechanical cleanup + 1 hour verification.

**Decision required**: does operator authorize Phase 0 to begin before Tier 1?

---

5. Confirmation: are the PLANNED modules, detectors, and controls clean-room safe?

Planned modules (Tier 1-8, 59 new + 16 existing = 75 total)

Every proposed module uses FreshVibe-native naming:

| Module | Runtime ID (FreshVibe-native) | Schema ID (FreshVibe-native) | Source widget (descriptive only) |

|---|---|---|---|

| icon | M-icon | icon | Elementor core `icon` |

| divider | M-divider | divider | Elementor core `divider` |

| spacer | M-spacer | spacer | Elementor core `spacer` |

| tabs | M-tabs | tabs | Elementor core `tabs` |

| modal | M-modal | modal | (new, FreshVibe-native) |

| map | M-map | map | (new, FreshVibe-native) |

| pricing-table | M-pricing-table | pricing-table | eael-pricing-table (source only) |

| gallery | M-gallery | gallery | basic-gallery, image-gallery (source only) |

| form | M-form | form | form, eael-weform, eael-fluentform (source only) |

| query-loop | M-query-loop | query-loop | loop-grid, loop-carousel, archive-* (source only) |

| counter | M-counter | counter | (source only) |

| progress-bar | M-progress-bar | progress-bar | progress-bar, eael-progress-bar (source only) |

| data-table | M-data-table | data-table | eael-table, table (source only) |

| timeline | M-timeline | timeline | eael-timeline, timeline (source only) |

| lottie | M-lottie | lottie | (new, FreshVibe-native) |

| marquee | M-marquee | marquee | (new, FreshVibe-native) |

| star-rating | M-star-rating | star-rating | (source only) |

| section, container, column, row, grid, stack, block, header, footer, divider-section | M-section, M-container, ... | section, container, ... | (all FreshVibe-native) |

| banner, testimonial-grid, testimonial-carousel, team-member, team-grid, logo-grid, logo-carousel | M-banner, M-testimonial-grid, ... | banner, ... | (all FreshVibe-native) |

| cookie-consent, reading-progress, scroll-to-top, coming-soon, maintenance | M-cookie-consent, ... | ... | (all FreshVibe-native) |

| image-compare, image-hotspot, image-mask, flip-box, call-to-action | M-image-compare, ... | ... | (all FreshVibe-native) |

| post-grid, post-carousel, post-list, product-grid, product-carousel, archive, single-field, single-product, user-author, glossary | M-post-grid, ... | ... | (all FreshVibe-native) |

| product-single, cart, checkout, my-account, mini-cart | M-product-single, ... | ... | (all FreshVibe-native, Woo scope-gated) |

**All 59 proposed modules use FreshVibe-native runtime + schema IDs.** The source widgets are listed ONLY as "what the detector will recognize" — not as FreshVibe output.

Planned detector expansion (~20 EAEL handlers + standard Elementor core)

The detector IS allowed to know proprietary naming. **Per FvCMS vendored README**: "Only the detector knows." The detector reads proprietary input and produces FreshVibe-native M-* dispatch. **The expansion is in the detector only.** No other layer needs to know the proprietary names.

**Recommended FreshVibe-native detector naming convention** (NEW):

**Alternative: rename the detector to `detectors/legacy-html.js` (or `detectors/source-html.js`)** to remove the "elementor" from the filename. This is a directory-level rename that doesn't break the FvCMS vendored contract. **Recommended for Phase 0.6**.

Planned inspector control expansion (5 new controls)

| New control | FreshVibe-native? | Source for design |

|---|---|---|

| icon-picker | Yes — `fes-control-icon-picker` | Generic icon picker (Fa + Lucide + custom) |

| lat-lng | Yes — `fes-control-lat-lng` | Generic lat/lng input |

| gallery | Yes — `fes-control-gallery` | Generic image multi-select |

| form-field-builder | Yes — `fes-control-form-field-builder` | Generic field-type + label + required |

| query-builder | Yes — `fes-control-query-builder` | Generic query args |

**All 5 proposed controls use FreshVibe-native naming.** No proprietary carryover.

Existing 24 inspector controls

Verified by grep: **all 24 use `fes-control-*` prefix, no proprietary naming.** They are clean.

---

6. Final classification table

| Layer | Clean-room? | Blocker for build? | Action |

|---|---|---|---|

| a777 FES audit (the plan) | YES (descriptive only) | No | None |

| a778 decision card | YES (descriptive only) | No | None |

| a779 world-class plan | YES (descriptive only) | No | None |

| `annotation.json` (data) | YES (data, not code) | No | None |

| `runtime/renderer.js` | **NO** (8 proprietary class names) | **YES** | Phase 0.1 |

| `runtime/region-scanner.js` | **NO** (3 proprietary references) | **YES** | Phase 0.2 |

| `runtime/edge-panel/edge-panel.js` | **Likely NO** (needs audit) | **YES** | Phase 0.3 |

| `app-fragments/fvcms-*/` (chrome) | **Likely NO** (display vs output audit needed) | **YES** | Phase 0.4 |

| `detectors/elementor.js` | YES (detector is allowed to know) | No | Optional: rename file in Phase 0.6 |

| `docs/`, `app-pact/` | **NO** (heavy proprietary citation) | No (docs not code) | Phase 0.7 (deferred) |

| `schema/` | YES (data-model.md) | No | None |

**4 layers are clean. 4 layers need Phase 0 work. 2 layers (annotation, detector) are correct by design.**

---

7. The operator decision

I need a single decision: **does Phase 0 of the world-class arc proceed before Tier 1 module-building begins?**

| Option | What | Time | Risk |

|---|---|---|---|

| **A** | Phase 0 (cleanup the vendored runtime) → Phase 1+ (build modules) | +2-3 hours cleanup, +1 hour verify, + Tier 1 weeks | Tier 1 starts later but on a verified clean-room foundation |

| **B** | Skip Phase 0, start Tier 1 with the proprietary names still in the vendored runtime | Tier 1 starts immediately | The new M-* modules will work, but the runtime still has `eael-creative-button--*` baked in. Not 100% clean-room. |

| **C** | Don't build. The 4 vendor runtime files are the operator's territory. I document them in the audit and let the operator decide | 0 | No progress on the world-class arc |

**My recommendation: A.** Phase 0 is mechanical, 2-3 hours, with a verification step. It produces a verified clean-room foundation that the Tier 1 build can use without worrying about legacy carryover. The new M-* modules are designed for FreshVibe-native output, but they need a runtime that supports FreshVibe-native output classes. The runtime cleanup is the prerequisite.

If you pick A, I will:

1. Create a worktree `feat/fv-cleanup` from `main @ c8b2af3`

2. Phase 0.1-0.4 mechanical cleanup

3. Eyeball test on oscar dist + R-117 verify

4. Commit + push (only after your approval to push)

5. Post a Phase 0 complete bulletin

6. Then begin Tier 1 build (D1 = A from your decision card)

If you pick B, I will:

1. Note that the world-class build is partial clean-room (output side clean, input/transition side legacy)

2. Begin Tier 1 immediately

3. Flag the legacy carryover in every Tier 1 PR

If you pick C, I will:

1. Hold

2. Wait for your direction

---

8. Receipts

**Conclusion**: the plans are clean. The vendored runtime is not. The vendored runtime cleanup is Phase 0 of the world-class arc.

---

— Mavis (helper-mavis, id 10, session 412100071272671)

2026-08-27 00:40 UTC