Read PR #39's own gate log rather than the tick (CLAUDE.md §2b). Every stage
this branch could affect is green: decisions-log, lint, l0, render-golden, l1,
and approval-policy (which evaluated for real on the pull_request event and
passed — no sensitive path touched). The one failure is `gitea-settings`:
required_approvals: DECLARED 1 but LIVE is 0
Gitea has DRIFTED from infra/gitea/expected-branch-protection.json
Every other declared setting matched, and one runner is online. So live `main`
currently requires ZERO approvals while the declaration says 1, and because
.gitea/workflows/gate.yml sets REQUIRE_GITEA_SETTINGS=true, that drift blocks
EVERY PR in the repo, not only this one. The check that would notice approvals
are unenforced is the check that is failing.
Not touched here: infra/gitea/** is a sensitive path (non-author approval
required) and outside this branch's documentation-only scope. Re-asserting the
protection or changing the declaration is an operator decision in its own PR;
local branch fix/admin-approval-override (616a497) looks like that work in
flight.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Hardware transcoding is confirmed working on prod (2026-10-02): VAAPI for both
decode and encode on /dev/dri/renderD128, with zero-copy, measured in
`Plex Media Server.log` in the running pod. The device-plugin mechanism from #37
works end to end.
`runbooks/plex-quicksync.md` said the Plex dashboard showing `Transcode (hw)` was
"the *only* proof available, and nothing else will ever tell you". That is false:
Dashboard -> Activity showed nothing while the feature was fully working, so the
page's authoritative check was silent on a healthy system and sent the operator
hunting a fault that did not exist.
Three inference errors corrected, two kept as named false leads:
1. The LOG is the primary check, not the dashboard. The grep ships in its
REDACTING form -- that log carries API URLs with `X-Plex-Token` (CLAUDE.md §6).
Also recorded: `Plex Transcoder Statistics.log` is the WRONG file (XML
<Variant/> records, no ffmpeg output), and why `grep -a` is required. The
dashboard is kept but demoted to best-effort, with its silence stated to prove
nothing.
2. An fd snapshot is not evidence. A /proc/*/fd sweep found no holder of
renderD128 while hardware transcoding was active -- sessions are short and the
scan landed in a gap. The reliable process-level check is the transcoder's
argv (-hwaccel, -hwaccel_device, vaapi, renderD128).
3. A missing preference key means nothing. `HardwareAcceleratedCodecs` was absent
from all 27 attributes with the toggle on and working, while
`HardwareDevicePath` was written and the log said "hardware transcoding:
enabled". Only `="0"` is conclusive; the log settles it.
Also stale and now fixed: GID 992 is a hostPath-era number. Under the plugin the
injected device is root:root, so the image's hook resolves GID 0 and adds `plex`
to the root group (`Groups: 0 100 1000`, `groups=1000(plex),0(root),100(users)`).
Marked as an inherent property of the plugin's DeviceSpec, not a defect, and
explicitly not a reason to reintroduce supplementalGroups (still a no-op --
s6-setuidgid rebuilds the group list from /etc/group). Added a per-title fallback
entry (UHD 630 has no AV1 decode), labelled a HYPOTHESIS: the title that fell
back was never checked. `runbooks/README.md`'s index entry was stale the same two
ways and is corrected.
Unchanged on purpose: the "STOP HERE IF PLEX IS Pending" section, the escape
hatch, and the no-alert-is-possible reasoning (no metricsEndpoint, no
ServiceMonitor, nothing a rule could evaluate).
Documentation only -- no catalog/, schemas/, apps/ or platform/ change.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>