Skip to content

Session handover — 2026-07-12 pt5

The ADR-0010 build landed — slices A (Wix media client) and B (video migration via the API) — and the hero video now renders (ADR-0009 Slice 5b), closing the "getting an asset ≠ rendering it" gap ADR-0010 named. Then an asset reconciliation (new, slice E) measured what we've pulled against what the site actually shows, and reclassified a "cosmetic" known-issue into the next slice.

What shipped (code + data; one worker redeploy, two surgical D1 writes)

  1. Wix media client — ADR-0010 slice A. Committed apps/cms/scripts/wix-api.mjs: auth (wix-site-id only), cursor paging, by-id index, pure parseMediaRef/pickVideoUrl/originalNameOf, 22-check network-free --selftest. The site id is derived, not hand-entered — every rendered Wix page carries metaSiteId=<uuid>, so it comes from the crawl and is committed to sites/<site>.jsonc (see ADR-0010 §"Site id"). The by-id match is a straight stem comparison: the API's file id is the id in our scraped basename.

  2. Hero video acquired — slice B. transform-seed-images.mjs gained a video branch (scrape id → API MP4 → R2), retiring the Slice 5b URL reconstruction. WCP's hero → r2:…/vid-20251205-wa0007-73c39f8f.mp4 (video/mp4, 3.96 MB, x-amz-meta-original-name: VID-20251205-WA0007.mp4); the key stem is the API's real filename, so provenance is sourced, not derived. asset-migration-gaps 1 → 0. Idempotent.

  3. Hero video RENDERS — ADR-0009 Slice 5b (known-patterns "A Wix hero carousel's VIDEO slide is captured as its POSTER"). Measured live first: the video IS slide 8 of the 8-frame carousel (Wix paints a video slide as its poster still until the player mounts — which is why our capture enumerated it as an image). So the video's ref replaces its own poster at its own index; no new field, 8 slides stay 8. hero-4 renders a video-extension slide as <video>, held for its own duration (a 23s clip in a 4.5s image slot was its own bug). Poster↔video joined by media id via the API's posters[], through the same lossy normaliseStem that built the R2 keys. WCP home plays the video live (worker 48441217, surgical D1 slideshowUrls patch — never a reseed). garvanbay renders hero-4 with zero slide-branch usage → provably inert.

  4. Asset reconciliation — slice E. New apps/cms/scripts/asset-reconcile.mjs joins Wix pool → R2 → seed → deployed HTML and buckets every asset. Findings in known-issues; the headline is that "pulled but not rendered" is 1 object (the poster we deliberately replaced) — but the deployed-HTML scan found 276 loud-fail placeholders across all 24 WCP pages.

Wiki changes

  • ADR-0010 — slices A/B/E marked Done; amendment: listFiles is ROOT-FOLDER-scoped (WCP root 94 vs true library 392) → the pool is searchFiles; new §"Site id".
  • ADR-0009 — Slice 5 tracker: hero video done, acquisition and render (append-mostly).
  • known-patterns.md — three new entries: the carousel video slide (captured as its poster); listFiles returns one folder; a reconciliation is only as honest as its join key.
  • known-issues.md — hero-video entry deleted (fixed); the WCP logo? "cosmetic" note reclassified into "276 loud-fail placeholders"
  • a new asset-reconciliation entry; an unexplained R2-throughput data point added to the existing deferred throughput issue.

Three numbers I got wrong before reporting them

Recorded because the process is the lesson (known-patterns "join key"): the reconciliation first said 91-of-94 library files were "never pulled" (wrong join key — display name vs media id), then still lied because the pool was root-only, then reported 349 "empty image slots" that included every legitimate absence (a hero with no video). Each was audited in both directions and corrected before it reached the report. The trustworthy answer to "what is broken on the page" came from measuring the deployed HTML (ui-missing-*), not from the seed.

State

Committed to master this session-end: apps/cms/scripts/wix-api.mjs (new), apps/cms/scripts/asset-reconcile.mjs (new), transform-seed-images.mjs (video branch + linkVideoSlide), upload-image.mjs (video content-types + uploadAsset with a provenance override — image keys byte-identical, proven over 190 corpus filenames and against live R2), packages/components-v3/…/hero-4.astro (video slide + per-slide dwell), apps/cms/seed/waterfordcountypainters.json, apps/cms/sites/waterfordcountypainters.jsonc (wix_site_id), the wiki + this handover. Live writes: WCP worker redeployed (48441217); WCP D1 patched twice, surgically (hero videoUrl, then slideshowUrls) — 12 blocks preserved each time, no reseed (a reseed would revert the capture-invisible SERVICE AREAS CTA); 1 MP4 uploaded to R2. No garvanbay change (worker untouched). Side effect worth knowing: upload-image.validate.mjs does live PUTs — running it uploaded 30 wfpainters objects genuinely missing from R2 (benign; immutable keys).

Next session (priority order)

  1. LogoStrip src capture gap — user-directed next slice. 237 fcr.logo-strip items carry an item count and no src, painting 276 placeholders across all 24 WCP pages. The logos are real and on live (Terra Spirits, Portarlington RFC, Hennessy Feeds, Coffey Engineering, Dairy Direct, Enterprise Ireland…) — so they are unfilled, not phantom, and this is a capture-plane gap (likely JS-rendered, invisible to the static matcher — same class as the topbar email/location miss). One fix clears all 276. Fold in the dead fcr.business.imageUrl logo (/assets/logos/… → R2; breaks og:image + JSON-LD). Re-run asset-reconcile.mjs after, and re-read at-source-never-pulled (298) — the residual is a capture-coverage signal.
  2. ADR-0010 slice C — image provenance enrichment (API filenames/dimensions/alt replacing derived basenames), now that searchFiles gives the true pool.
  3. garvanbay wix_site_id — absent (crawl inputs live only on EC2), so the reconciliation skips its Wix pool. One line in sites/garvanbay.jsonc.
  4. Section-style density dimension + Slice 6 calibration (fit lib/calibration.json; promote hero-variant/scrim/textTone to scored dims).