feat(liveness): config-driven card visibility policy + probe prefetch (#5)

Makes the card liveness-visibility behavior switchable so it can be A/B
feel-tested, and probes ahead of the scroll for a snappier result.

- CARD_LIVENESS_POLICY (config/instance-config.js): "show-pending" (default,
  unchanged) | "hide-foreign" (foreign/ingested cards hidden until a source
  verifies; native cards stay show-pending) | "hide-all". Owner's own cards are
  always visible. Flip live for testing without a rebuild:
  window.__BITVID_CARD_LIVENESS_POLICY__ = "hide-foreign" then refresh/scroll.
  Implemented via a data-foreign provenance flag on the card +
  getCardLivenessPolicy() in cardSourceVisibility.js.
- LIVENESS_PROBE_PREFETCH_MARGIN (default 600px): both liveness probes were
  already viewport-gated (IntersectionObserver, on-screen-first, WebTorrent
  priority-queued + concurrency-capped); this expands their rootMargin so cards
  just below the fold verify before the user reaches them.
- Tests: three policy scenarios in tests/video-card-source-visibility.test.mjs;
  also un-broke 3 pre-existing VideoCard tests by adding the missing
  IntersectionObserver JSDOM stub.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-25 09:13:52 -04:00
1 parent df99bdb65f
commit ccbe8d9bb2
10 files changed
+236 -16

No files matched your search

+18 -5
View File
@@ -1,3 +1,5 @@
import { getCardLivenessPolicy } from "../constants.js";
function resolveCardElement(cardLike) {
if (!cardLike) {
return null;
@@ -65,11 +67,22 @@ export function updateVideoCardSourceVisibility(cardLike) {
const cdnHealthy = cdnState === "healthy";
const streamHealthy = streamState === "healthy";
const shouldHide =
!cdnHealthy &&
!streamHealthy &&
!cdnPending &&
!streamPending;
// Liveness visibility policy (config/instance-config.js → CARD_LIVENESS_POLICY):
// show-pending : show now, hide only once every source is confirmed dead.
// hide-foreign : foreign/ingested cards stay hidden until a source is proven
// playable; native cards keep show-pending.
// hide-all : every non-owner card stays hidden until proven playable.
const policy = getCardLivenessPolicy();
const isForeign = card.dataset.foreign === "true";
const hideUntilVerified =
policy === "hide-all" || (policy === "hide-foreign" && isForeign);
const shouldHide = hideUntilVerified
? // Hidden until at least one source proves playable (covers the pending
// window too, so a dead foreign stranger never flashes in).
!cdnHealthy && !streamHealthy
: // Default: only hide once every source has come back dead.
!cdnHealthy && !streamHealthy && !cdnPending && !streamPending;
if (shouldHide) {
if (!card.hidden) {