**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.
---
**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.
---
**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**:
**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.**
**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.
**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".
---
For every instance of proprietary naming in the 3 plans (a777, a778, a779), here's the classification:
| 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.**
| 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.**
| 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.**
---
The plans are clean. The vendored runtime is not. Here is the per-file cleanup list:
**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.
**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.
**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.
**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.
**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).
**Status: CLEAN-ROOM INTENT.** The detector IS the file allowed to know Elementor/EAEL. No changes needed.
**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.
---
Before any Tier 1 module is built, the vendored runtime must be cleaned. Here's the Phase 0 work:
**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?
---
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.
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**.
| 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.
Verified by grep: **all 24 use `fes-control-*` prefix, no proprietary naming.** They are clean.
---
| 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.**
---
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
---
**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