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]>
The feed's per-card stream-health badges ran WebTorrent swarm probes at
PROBE_CONCURRENCY = 96, and each probe's torrent.add set no maxConns (WebTorrent
default 55 peers). Loading/scrolling the feed could therefore open
~96 x 55 simultaneous WebSocket/WebRTC connections, pegging the main thread
(freeze) and exhausting memory (tab crash); playing a video added the streaming
torrent on top and tipped it over. This also produced the MaxListenersExceeded
warnings and relay/connection storms.
- gridHealth: PROBE_CONCURRENCY 96 -> 4 (probes are real swarm joins, not pings).
- webtorrent probePeers add: maxConns: 4 (a probe only needs to see >=1 peer).
- webtorrent playback add: maxConns: 30 (caps the streaming handshake storm;
ample for playback bandwidth).
Pre-existing issue (not from the file-size refactor — verified). Confirmed
locally: feed scroll + playback no longer freeze/crash. grid-health +
webtorrent-regression tests pass; build green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Introduce `js/constants.js` with semantic time constants (e.g., `ONE_MINUTE_MS`, `STANDARD_TIMEOUT_MS`) and feature-specific TTLs.
- Export `KIND_MUTE_LIST` from `js/nostrEventSchemas.js` to standardize NIP-51 mute list kind usage.
- Refactor `js/state/cache.js`, `js/nostr/cachePolicies.js`, `js/channelProfile.js`, and various services to use centralized constants instead of hardcoded magic numbers.
- Update `js/nostr/relayConstants.js` to derive values from the shared time constants.
- Replace duplicate definitions of timeouts and retry delays across the codebase.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Extract `prioritizeEntries` logic to `js/gridHealthLogic.js` for testability
- Add comprehensive unit tests in `tests/grid-health.test.mjs`
- Improve `getIntersectionRect` to robustly handle invalid rects
- Ensure 0x0 rects are filtered out explicitly
Co-authored-by: PR0M3TH3AN <[email protected]>
- Create `docs/webtorrent-architecture.md` detailing the "Webseeds are Peers" strategy.
- Update `docs/video-availability-checks.md` with cross-reference.
- Add "CRITICAL" warning comments to `js/webtorrent.js` and `js/gridHealth.js` to prevent regressions.
- Enhance `tests/webtorrent-regression.test.mjs` to explicitly verify `urlList` passing in mocks.
Co-authored-by: PR0M3TH3AN <[email protected]>
Reverts `js/webtorrent.js` and `js/gridHealth.js` to a simplified implementation that correctly treats webseeds as peers. This ensures that videos with only webseeds (and 0 P2P peers) are considered healthy and playable, resolving an issue where such videos were marked as unhealthy or failed to stream.
- Updates `js/webtorrent.js` to use `client.add(url, { urlList: [...] })` for better webseed integration.
- Updates `js/gridHealth.js` to rely on `peers > 0` for health, removing complex `webseedOnly` logic.
- Updates `tests/webtorrent-regression.test.mjs` to verify that webseeds are counted as peers and result in a healthy state with reason "peer".
Co-authored-by: PR0M3TH3AN <[email protected]>
This change addresses two issues with WebTorrent webseed handling:
1. **Grid Availability Check:** Modified `js/gridHealth.js` to correctly classify torrents with only webseeds as "healthy" and report 1 peer (instead of 0) so the UI availability check passes.
2. **Video Player Bootstrap:** Modified `js/webtorrent.js` (`probePeers` and `streamVideo`) to explicitly append provided webseed URLs (`urlList`) to the magnet link as `&ws=` parameters. This forces the WebTorrent client to recognize and use these webseeds as initial peers for bootstrapping the swarm.
Tested via `tests/verification/verify_webseed_fix.mjs` (logic verification).
Co-authored-by: PR0M3TH3AN <[email protected]>
- Increased `PROBE_TIMEOUT_MS` in `js/gridHealth.js` to 20s to reduce false negatives in peer detection.
- Relaxed the peer check in `js/app.js` to allow forcing a switch to WebTorrent even if the liveliness checker reports 0 peers (showing a warning instead of an error).
- Added `tests/verify_app_switch.mjs` to validate the UI logic change.
- Add storage helpers for torrent probes and tracker health in `js/utils/storage.js`
- Update `js/gridHealth.js` to read/write torrent probes from localStorage
- Update `js/healthService.js` to read/write tracker health from localStorage
- Ensure TTLs (5m for probes, 2m for trackers) are respected across sessions
- Add verification test `tests/verify-storage-persistence.mjs` (removed before completion)