chore(comments): drop epic, sprint and review-round ids from the code

The code cited its plan instead of saying why: `E28 review J4`, `(R6 S3b)`, `S1 justified…`,
`deep-review round 5`. That plan lives in the private ops repo, so for every reader of this one the
citation was noise, and a sentence whose subject was the plan step ("round 2 showed…") hid its
lesson behind an id. Each one is gone and the "why" kept: a bare citation is deleted, a sentence
carrying a lesson is reworded around it ("a later attempt showed…").

Measured (`scripts/audit_metrics.py`, product code): 652 lines in 270 files carried an epic code by
the definition the next commit holds (507 / 241 by the old, two-digit-only one) -> 0. Across all
code, tests, scripts and configs: ~1100 epic-code lines plus ~320 sprint/round ids.

Behaviour unchanged, checked mechanically: every changed .py file has the same AST once docstrings
are blanked; css/sh/toml/yml/json files are identical once comments are stripped; the only
non-comment changes in TS/JS are test titles, one description string in a contract table, and five
ESLint messages, whose text is all the gates snapshot diff holds. Not touched: Markdown (docs and
the changelog keep their history), Alembic migrations, TV episode notation (`S2 · E5`), DESIGN.md
ids (`C1`, `B4`, `S3h`), tracker ids (`SEC-16`, `DX-17`).

One stale claim fixed on the way: test_hls_reaper's docstring said the player checkpoints "every
10 s whether or not it is playing", which plex/stream.py calls wrong; it now says what the code does.
This commit is contained in:
2026-10-05 00:19:39 +02:00
parent c73d8be094
commit 4aaaaa7860
669 changed files with 1831 additions and 1904 deletions
+14 -14
View File
@@ -32,7 +32,7 @@ import { PLEX_SCALE, normalizeVolumeIn, stepVolumeIn } from "./playerVolume";
// watched, clears the position and scrobbles to Plex — re-performing the very write that was just
// refused, i.e. exactly the defect this constant was introduced to close. So the invariant is
// one-directional and it is PINNED, not described: `plexFinishMargin.contract.test.ts` reads the
// Python and fails if this value ever drops below it (round 7).
// Python and fails if this value ever drops below it.
const FINISH_MARGIN_S = 30;
// A live wall clock for the top bar, re-rendered every 15s (minute resolution is enough for the
@@ -71,11 +71,11 @@ export function useFullscreen(wrapRef: RefObject<HTMLElement | null>): {
// closure rebuild: barAutoHide (per-user "never auto-hide" setting), whether a menu is open (keep the
// bar up so it can't vanish mid-choice), and the <video> paused state (a paused video keeps the bar).
// `holdOnHover` is the pointer resting on the chrome: the bar stays while it is there (as on YouTube
// and Plex Web — E28 F22, it used to fade out from under a mouse parked on Next), and leaving it
// starts a fresh 3 s. `holdOnFocus` is the same for a KEYBOARD focus in the chrome (E28 review E6): the
// and Plex Web — it used to fade out from under a mouse parked on Next), and leaving it
// starts a fresh 3 s. `holdOnFocus` is the same for a KEYBOARD focus in the chrome: the
// bar must not fade from under the control a key user is on — but only for a while after the last
// key (FOCUS_HOLD_MS). The focus never leaves the bands on its own (Escape hands it back to the ⋯), so
// a hold without an end kept them over the whole film (round 2, P4); any key wakes them again.
// a hold without an end kept them over the whole film; any key wakes them again.
//
// On touch (C3) nothing moves a mouse, so the timer is also armed by PLAYBACK starting — before, the
// bar stayed up until the first tap however long the video played — and a tap on the picture only
@@ -155,7 +155,7 @@ export function useControlsVisibility(opts: {
focused.current = on;
// Only a hold that ENDS restarts the timer. A tap moving the focus out of the bands (a finger
// never holds: its focus is not :focus-visible) re-showed them on its way to the picture, whose
// own toggle then hid them again — the tap did nothing on Android (round 2, P3).
// own toggle then hid them again — the tap did nothing on Android.
if (was && !on) wake();
},
[wake],
@@ -209,8 +209,8 @@ export function usePlexProgress(opts: {
// and the backend reads a position within `_FINISH_MARGIN_S` of the duration as a finish. So the
// branch named "take the finish back" marked the item watched, cleared the position and
// scrobbled to Plex within ten seconds — the refused write performed through a third route,
// under an error toast saying it had failed. Round 6 closed only the explicit rollback write;
// this closes the other three (deep-review round 7). What the refusal does take back is the
// under an error toast saying it had failed. An earlier fix closed only the explicit rollback
// write; this closes the other three. What the refusal does take back is the
// CLAIM: the cache must not say watched, and `settle` must not re-assert it on the way out.
let finishRefused = false;
// `final` = a settled checkpoint (pause / page-hide / leaving the player) vs. the periodic tick.
@@ -232,14 +232,14 @@ export function usePlexProgress(opts: {
// watch twice — and where Plex's reported duration runs more than the finish margin past the
// real media, the checkpoint was not near-end either, so it wrote a resume position AFTER the
// scrobble. That race is what `finish` exists to prevent; on a natural play-through it was
// raised a beat too late (deep-review round 5).
// raised a beat too late.
const onPauseFlush = () => {
if (videoRef.current?.ended) return;
flush(true);
};
const video = videoRef.current;
video?.addEventListener("pause", onPauseFlush);
// A seek is a settled position too (S2: Plex is the source of truth, so it must see the new spot
// A seek is a settled position too (Plex is the source of truth, so it must see the new spot
// right away, not up to 10s later). Debounced so scrubbing — many `seeked` events in a row — pushes
// just ONCE, once the user lands. `final=true` bypasses the backend's ≥10s push-throttle, which is
// exactly why the debounce lives here: it bounds a scrub to one immediate Plex timeline call.
@@ -270,7 +270,7 @@ export function usePlexProgress(opts: {
// that is when the position is final. Reading the LATEST abs/duration is the whole point of the
// checkpoint (the resume point when leaving).
const settle = () => {
// Match the language-keyed detail query (E5 S6) so the optimistic resume patch lands.
// Match the language-keyed detail query so the optimistic resume patch lands.
const key = qk.plexItem(id, plexLang(i18n.language));
if (finished) {
// A refused finish claims nothing: the server has the item unwatched at the position the
@@ -297,7 +297,7 @@ export function usePlexProgress(opts: {
// `finishRefused`): the cached detail said watched / position 0 while the server still had
// the item unwatched at the last checkpoint, and the once-per-id start guard meant the
// corrected detail arriving later was never used — the episode reopened at 0:00 with a
// Watched badge the server disagreed with (round 5).
// Watched badge the server disagreed with.
const pos = Math.floor(absRef.current);
const dur = durationRef.current;
// The media's own end, not Plex's reported duration: a file shorter than its metadata (a
@@ -311,7 +311,7 @@ export function usePlexProgress(opts: {
// position within `_FINISH_MARGIN_S` of the duration as a finish: it would set watched,
// clear the position and scrobble to Plex. So the branch named "take the finish back"
// performed, through a second route, exactly the write that had just been refused — while
// the caller's error toast was already on screen saying it had failed (round 6). The
// the caller's error toast was already on screen saying it had failed. The
// credits-skip caller captures a mid-episode position and is unaffected.
if (!ended && pos > 0 && dur > 0 && pos <= dur - FINISH_MARGIN_S)
api.plexProgress(id, pos, dur, true).catch(() => {});
@@ -347,7 +347,7 @@ export function usePlexProgress(opts: {
* loading, or a resumed one that has stayed paused) it reads 0 while the film is minutes in, so the
* answer is where the session was ASKED to start. Anything that restarts the session "here" — an
* audio switch, an A/V offset, a keyboard seek — must use this: reading `abs` restarted a resume at
* 20:00 from 0:00, and the next checkpoint saved that (deep-review round 4). */
* 20:00 from 0:00, and the next checkpoint saved that. */
export function playhead(absRef: RefObject<number>, loadStartRef: RefObject<number>): number {
return absRef.current > 0 ? absRef.current : loadStartRef.current;
}
@@ -485,7 +485,7 @@ export function useAutoSkip(opts: {
// (the current id, captured here — not the reactive id, which go() is about to change). The
// write is handed to go() so a refusal takes the finish back: this path has no near-end
// checkpoint to corroborate it, so one failed request used to leave the cache claiming
// watched / position 0 while the server still had the credits position (round 5).
// watched / position 0 while the server still had the credits position.
const watchedWrite = api.plexSetState(id, "watched");
watchedWrite.catch(reportWatchedErrorRef.current);
go(nextId, watchedWrite);