summaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md34
1 files changed, 33 insertions, 1 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 42dd8b2..babbd86 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -302,6 +302,35 @@ keypair bundle, or anything that looks like a user's public key.
reproduced the defect in one run. Model the environment, never the code under
test
+- **A hook cannot depend on one declared below it.** `const a = useCallback(fn,
+ [b])` evaluates `[b]` where it is written, so a `b` further down the component
+ is still in its temporal dead zone: `ReferenceError` on every render, before
+ anything the component does can run. The component simply does not appear —
+ clicking a video did nothing at all, with no error on screen and nothing in
+ the node's log because nothing was ever requested. It reached production.
+ `node --check` passes; the code is well-formed. Worse, the MSE harness
+ extracted the player functions in a list order of its own and therefore
+ *reordered* them, quietly repairing the one class of defect it was best placed
+ to catch — it now sorts by position in the file. `test_hook_ordering.py`
+ checks the whole SPA
+
+- **Flow-control accounting comes before every early return.** A segment that
+ arrived is no longer in flight, whatever is then done with it. Discarding one
+ before decrementing the in-flight window leaked a slot per discard, and
+ `reinitAt` is asynchronous, so a seek's whole window could arrive while it
+ was still awaiting its `updateend`s — the player then believed a full window
+ was in flight, granted no further credit, and the node waited for ever while
+ logging a stream it had fed perfectly. A race, so it worked twice and hung on
+ the third try; "it works now" is not evidence against a race, and
+ `tests/harness/window_leak.mjs` forces the worst case instead
+
+- **A new stream starts from a known state, and that list grows.** `appendingRef`
+ and `endedRef` were the first two; `awaitingInitRef` and `seekTargetRef`
+ repeated the same bug a session later, and worse — only `reinitAt` lowers
+ `awaitingInit`, and the next film never reaches it, so every one of its
+ segments would have been discarded. Reset at the *start* of the stream, never
+ in the teardown of the one before, which is skippable
+
- **`Cache-Control: no-cache` only binds a browser that asks.** One that cached
the SPA before that header existed applies heuristic freshness — a fraction of
the file's age, days for a file dated weeks ago — and does not ask at all. A
@@ -462,7 +491,10 @@ SFR residential Fedora 44 → meshbay.org OVH VPS:
| Asset versioning (hub) | `meshbay_hub.api.webapp` | `_asset_version()` — content hash; whole module graph served under `/a/<hash>/` so a cache cannot mix two builds |
| Stream capacity (node) | `meshbay_node.config` | `[node] max_concurrent_streams` (default 8) — a slot is held for the length of a film, so it counts simultaneous viewers |
| Stream diagnosis (node) | `webrtc_server.py` | `client_diag` at DEBUG — the player's own view (`ready`, `quota`, `ranges`, `err`) in the node's log. The only window into a phone |
-| Stream probe (no browser) | — | `QE/deploy/stream_probe.py` — pulls a real film over real MNP. Answers "is it the node or the browser" in one run (not versioned) |
+| Stream probe (no browser) | — | `QE/deploy/stream_probe.py` — pulls a real film over real MNP, `--start` to seek. Answers "is it the node or the browser" in one run (not versioned) |
+| Seeking (browser) | `static/app.js` | `requestSeek` → node restarts ffmpeg with `-ss`; `reinitAt` clears the buffer and sets `timestampOffset`. `-copyts` does *not* preserve position — measured — so the offset comes from the client |
+| Seeking (node) | `webrtc_server.py` | `start` on `stream_req`; `-ss` **before** `-i` (index seek, not decode-and-discard), clamped away from the end, echoed in `stream_init` |
+| Resume position | `static/app.js` | `readResumePosition` / `writeResumePosition` — localStorage, per file, per browser. No protocol, and nothing new learns what you watch |
## meshbay.org server (état cible)