Skip to content

fix(teched): render both directions of Devtoberfest↔TechEd cross-links (#2312) - #2423

Merged
jung-thomas merged 1 commit into
DEVfrom
fix/teched-dtf-crosslink-render
Sep 18, 2026
Merged

jung-thomas merged 1 commit into
DEVfrom
fix/teched-dtf-crosslink-render

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

Problem

#2312 shipped the Devtoberfest↔TechEd concept cross-links, but on PROD neither direction rendered despite the concept-link tables being populated and warm (verified: /build/teched carries 215/349 sessions with matches). Two independent defects:

1. Forward (Devtoberfest → TechEd) — feed always empty

/api/devtoberfest/schedule returned relatedTechEdSessions: [] for every session. The forward map was keyed by the KG DevtoberfestSessions.ID (a freshly-minted uuid from the fetch job) but devtoberfest-feed.js attached by the planner-facade Session.ID — two distinct UUID namespaces, so every lookup missed.

Fix: re-key both sides on SESSIONCODE, the one identifier copied verbatim into the KG row. Shared dtfSessionKey() normalizer (trim + uppercase). The reverse direction already keyed on the shared slug, which is why only forward was broken.

2. Reverse (TechEd → Devtoberfest) — block never rendered on /teched/

The teched-sessions-grid island preferred the baked #teched-data blob over the live /build/teched feed. relatedDevtoberfestSessions is computed per request, so it's always empty in the bake — the page shipped stale-empty related arrays.

Fix: loadFeed() now fetches the live feed first; the baked blob is a fallback used only when the fetch fails (offline / CAP down). Durable — no rebuild needed, and it can't go stale again.

Why tests missed it

The existing unit test hardcoded the crosslink map key equal to the session ID ('s1' == sessions[0].ID), forcing the two namespaces equal so the mismatch couldn't surface. Added:

  • A seam-crossing assembleFeed test with a facade ID distinct from SESSIONCODE.
  • A regression guard asserting a facade-ID-keyed map yields [] (the old keying can't sneak back).
  • Rewrote the island load tests for the fetch-first contract (prefers live feed; falls back to blob on fetch failure; "null" blob safe).

Verification

  • Backend unit: 13/13 (test/unit/teched-devtoberfest-crosslink.test.js)
  • Island: 90/90 (hugo-apps/src/teched-sessions-grid/)

Follow-up (not in this PR)

hugo-apps/package.json does not declare @vue/test-utils — it resolves from a parent node_modules, which crashes the island suite in a fresh worktree. Worth a devDep declaration.

Deploy note

Both directions are gated by TECHED_DEVTOBERFEST_CROSSLINK_ENABLED (already ON on PROD) + the KG session-link jobs (already warm). Once merged to DEV and promoted, the forward feed lights up immediately; the reverse /teched/ cards render on next load (fetch-first, no rebuild).

Generated with Claude Code

…nks (#2312)

Two defects left the #2312 cross-links invisible on PROD despite the
concept links being populated:

1. Forward (Devtoberfest -> TechEd) feed was always empty. The forward
   map was keyed by the KG DevtoberfestSessions.ID (a freshly-minted
   uuid) but the feed attached by the planner-facade Session.ID — two
   distinct UUID namespaces, so every lookup missed and every
   relatedTechEdSessions came back []. Re-key both sides on SESSIONCODE,
   the one identifier copied verbatim into the KG row (shared dtfSessionKey
   normalizer). Reverse (TechEd -> DTF) already keyed on the shared slug,
   which is why only the forward direction was broken.

2. Reverse (TechEd -> DTF) block never rendered on /teched/. The island
   preferred the baked #teched-data blob over the live /build/teched feed,
   and relatedDevtoberfestSessions is a request-time field that is always
   empty in the bake. Flip loadFeed to fetch-first; the blob is now a
   fallback used only when the fetch fails (offline / CAP down).

Tests: added a seam-crossing assembleFeed test (distinct facade ID vs
sessionCode key) + a regression guard that a facade-ID-keyed map yields []
— the existing unit test masked the bug by hardcoding map key == session ID.
Rewrote the island load tests for the fetch-first contract (prefers live
feed, falls back to blob on fetch failure). Backend 13/13, island 90/90.

Note: hugo-apps does not declare @vue/test-utils; it resolves from a parent
node_modules, which crashes the suite in a fresh worktree. Not fixed here
(out of scope) but worth a follow-up devDep declaration.

Generated with Claude Code
@jung-thomas
jung-thomas merged commit 4fbcd23 into DEV Sep 18, 2026
6 checks passed
@jung-thomas
jung-thomas deleted the fix/teched-dtf-crosslink-render branch September 18, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant