Setting CARD_LIVENESS_POLICY=hide-foreign made all foreign/NIP-71 content
disappear: a hide-until-verified card starts display:none, which has no layout
box, so the IntersectionObserver never fires for it — its liveness probe never
runs, it never gets a healthy verdict, and it stays hidden forever (deadlock).
Fix: cardNeedsEagerLivenessProbe() identifies cards governed by a
hide-until-verified policy (foreign under hide-foreign; all non-owner under
hide-all). Both health observers now kick the probe for those cards from
onCardRegister — which fires for every card regardless of visibility — instead of
waiting for an intersection that a hidden card can never produce. The URL probe is
deferred one microtask so attachUrlHealthBadges has wired state.onCheck after
observe(). Probes stay concurrency-capped + priority-ordered; show-pending is
unchanged (no eager probing).
Tests: cardNeedsEagerLivenessProbe predicate coverage in
tests/video-card-source-visibility.test.mjs.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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]>
- `refreshUrlHealthBadges` from `js/urlHealthObserver.js`
- `parseVideoEventPayload` from `js/videoEventUtils.js`
- `buildDirectMessageSnapshotPayload` from `js/directMessagesStore.js`
- Unexported `ingestLocalReaction` in `js/reactionCounter.js` (still used internally)
I verified there are no references in the codebase or tests.
Tests run: `npm run format`, `npm run lint`, `npm run test:unit`.
(Note: `test:unit` results were truncated in the log, but I confirmed no usage in tests.)
Artifacts: `artifacts/depcheck.json` was not included as no dependencies were removed.