Phase 06 · v1.0 · Shipped 2026-05-20

Cutover to exact matching.

After Phase 5's dry-run gate was reviewed and approved (gate resolved: playerplayer_start, rerun shows 0 flips on the blesk fixture), exact matching becomes the default validation path and the old substring behavior is removed. Mechanical single-swap.

Milestonev1.0 ScopeVAL-05 Depends onPhase 5 (gate resolved) ModeMechanical single-swap
Phase boundary

No new design — just the cutover Phase 5 designed.

Scope so tight that no smart-discuss table is needed. Replace three lines in validateEvents; remove the old substring path.

The swap
Before · substring

src/utils/eventUtils.ts:111-113

const hasDataLayer = eventSources.DataLayer.events.some(e => e.includes(eventSources.DataLayer.expected));
const hasGA4       = eventSources.GA4.events.some(e       => e.includes(eventSources.GA4.expected));
const hasGemius    = eventSources.Gemius.events.some(e    => e.includes(eventSources.Gemius.expected));
After · exact + alias

via the Phase 5 helper

const hasDataLayer = matchExpectedEvent(eventSources.DataLayer.events, eventSources.DataLayer.expected, aliasMap[functionName].dataLayer);
const hasGA4       = matchExpectedEvent(eventSources.GA4.events,       eventSources.GA4.expected,       aliasMap[functionName].ga4);
const hasGemius    = matchExpectedEvent(eventSources.Gemius.events,    eventSources.Gemius.expected,    aliasMap[functionName].gemius);

Add imports: matchExpectedEvent from ./eventMatching, aliasMap from ../lib/Types.

Success criteria
  1. Production validateEvents uses exact + alias matching only; no substring fallback in any code path.
  2. All Phase 1–5 tests pass byte-for-byte (lock-test gate).
  3. Old substring helper removed from the codebase; grep returns zero.
  4. Full run against the blesk fixture produces exactly the verdicts Phase 5's dry-run predicted.
Files
modsrc/utils/eventUtils.tsthree-line swap + imports
delold substring helper (if any)
← PreviousPhase 5 · Dry-run gate Next →Phase 7 · Failure taxonomy