Skip to content

Helm session recovery: unshipped fixes, unconfirmed root causes, and cleanup items (2026-08-19) #9513

Description

@tanflem

Summary

Recovered from ~28 old helm/* session transcripts (worktrees auto-deleted, session logs survived under ~/.claude/projects/). A peer session (help-me-get-a-tight-list-of-what-i-need-to-do-to) had already done most of this recovery ~23h earlier and opened PRs #9502#9506 from it. This issue captures what's left: things still unticketed, a likely-duplicate PR, and one open architecture decision.

Needs a decision

Confirmed root causes, not yet fixed

  • Ama / bcp47-less-language 404 on jesusfilm.org/watch (whole bug class, not Ama-specific) — root cause confirmed in the forge repo, not core. The watch-page language picker (apps/web/src/lib/content.ts in forge) lists any published+hls language, but the route gate rejects any slug missing from a generated corpus (packages/watch-url-policy/src/public-watch-language-slugs.ts in forge) built from Language.bcp47. ~39 admin-added Language rows (including Ama, id 20118, bcp47 nyi) have no bcp47 set and are skipped by the corpus generator, so classify() returns unknown and notFound() fires before any GraphQL lookup runs. Every published dub in one of those ~39 languages 404s identically. Three fix options identified: backfill bcp47 for the 39 rows, key the corpus generator on Language.slug instead, or filter the picker to match the corpus. Write-up is in core PR docs(solutions): add investigation notes for the Ama watch-page bug #9506 (docs only) — the actual fix needs to happen in forge.
  • hasVideos never set true on the Mux-upload pathcreateOrUpdateVideoVariant (apis/api-media/src/schema/videoVariantUpload/service.ts) never calls ensureLanguageHasVideosTrue, unlike the GraphQL-mutation path. Fix already written and committed locally on an unpushed branch (08-05-TF-fix-language-has-videos-upload-path, commit 950eee08e), needs a rebase onto current main; overlaps with PR feat(api-media): activate video variant reconciliation (QA-554) #9386's reconciliation work.
  • Darkroom Faith replacement episodes not playing on Watch — root cause found via a live diagnosis session (14/24 variants affected, deterministic repro): production Watch reads from a separate coreId-keyed content mirror that isn't in this monorepo — same shape as the Ama bug above. A full ranked-hypothesis handoff doc exists only at /tmp/handoff-darkroom-faith-watch-20260812/HANDOFF.md in an ephemeral container and will be lost if not rescued.
  • Possible cache cross-contamination between clientsapis/api-media/src/yoga.ts keys anonymous-request cache entries on null session instead of clientName, so an anonymous journeys response could theoretically be served to a watch request. Means the shipped restrictViewPlatforms feature could already be leaking in prod via cache cross-contamination. (Already privately tracked as issue add first-draft journey graph design #6 in a personal core-issues repo — flagging here too since it's a real prod-facing risk.)
  • Prod Redis/Arclight languageIds bug — some caller passes a BCP-47 tag (en) into Arclight's languageIds param (which expects numeric IDs), producing and caching an empty result for English media-components. One stale cache key was deleted live as a stopgap (media-components:1:4999:languageIds:en). The actual caller sending the malformed request was never identified.
  • Arclight download URLs hardcoded to a ≤720p tierapps/arclight/src/lib/downloadHelpers.ts's findDownloadWithFallback only ever looks up VideoVariantDownloadQuality.low/.high rows, never fhd/qhd/uhd/highest. Every video's download-URL API field is capped regardless of actual encode quality. HLS streaming through Arclight is unaffected — only the download-URL field.
  • api-languages response cache has no TTL and no invalidation path for importer-written data — could cause indefinitely stale language lists after an import.
  • LanguageAutocomplete.tsx:71 silently drops languages whose name array is empty, with no warning surfaced anywhere.
  • forge issue chore: upgrade to node 18 #1831 ("public resolvers don't filter DRAFT/unpublished status") — still open, surfaced while diagnosing and fixing the 2_ElCamImpulsesVert restricted-video leak (that fix itself shipped, forge PRs fix: make journeys published by default #1829/fix: journeys variant language #1830/feat: ui elements improvements #1838/fix: permission error #1839, all merged).

GitHub issue triage conclusions still current (from an old /triage pass)

At risk of being lost (git-gc pruning)

  • A 293-line regression runbook (docs/qa/regression-runbook-2026-08-11.md, covering 28 merged PRs) and an already-written VideoList.tsx row-click bugfix (URL built from pathname instead of a fixed path, broken by PR feat(videos-admin): add status pipeline tab #9361 moving the component) both live only in a dangling, unreferenced commit (a24436b0e in the main repo's object store) — not on any branch, so eligible for git gc pruning. The runbook is also still live as a Claude Artifact (https://claude.ai/code/artifact/f9f55fd3-d1aa-4a5c-93ab-8e03908d7b69) as a backup, but the bugfix commit has no other copy.
  • A prod resync script (resync-restrict-view-watch.ts, already run successfully against prod — 46/46 videos updated, this part is done) is recoverable from a stash (stash@{0} in the main repo, "wip before checking out PR 9430 for testing", commit 9dffcf0a8) if the tooling itself is worth keeping around for reuse.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Choreready-for-humanHand this PR back to a human — Mergetron skips it

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions