# fix\(web\): paused sidebar videos keep their place during commands · PR \#23127 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/23127)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: open

Source repository: pingdotgg/t3code

Source branch: fix/issue-23089

Target branch: main

Head commit: d8d674784e4279e847b450e5908dc29db17a6be0

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/23127)

[Commits](https://git.cafe/pingdotgg/t3code/pull/23127/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/23127/diffs?format=markdown)

## Description

---

## Problem

A local MP4 paused in the sidebar reloads when unrelated read-only agent commands complete. A video paused at five seconds resets to the first-frame preview even though its bytes have not changed.

## Change

Return an optional revision from the media file's existing open-file stats and use it for the sidebar video's revision. Keep the loaded video source across unchanged revisions and URL re-signing, while retaining real-file updates, active-playback deferral, retry, and stale-source recovery. Older servers retain the existing workspace-change fallback. HTML, PDF, audio, and image refresh behavior is unchanged.

## Scope and approval

Fixes #23089
GitCafe: https://git.cafe/pingdotgg/t3code/issues/23089
Triaged bug via the automated issue flow. Reproduced in the real web app on Linux using a fake provider that executes two actual read-only shell commands. The fix changes media refresh state and optional result metadata; signing claims and authorization are unchanged.

## Verification

- Red-first Chromium regression failed on main: a new URL for unchanged paused media replaced its loaded source. It passes on the fixed head, including stale-source fallback and changed revisions.
- Whole focused files: `AssetAccess.test.ts` (25), client-runtime `assets.test.ts` (1), `FilePreviewPanel.test.ts` (13), and `MediaVideoPlayer.browser.test.tsx` (1): **40 tests pass**.
- Scoped typechecks: contracts, client-runtime, server, web: pass.
- Targeted lint: pass with one pre-existing `no-inline-schema-compile` warning outside the changed test. Scoped Knip exports check and `git diff --check`: pass.
- Two independent code reviews: Codex GPT-6.1-Sol and Claude Opus 5.5 returned `MERGE`; evidence is checked separately below.

Independent proof audit: **SUFFICIENT** against the [six-row matrix](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/00dad552e107af06/matrix.md). [Full evidence index](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/cb9691be2afd2e44/evidence.md). Before is merge-base `968dd51704441138559a3fe9c348719f2b11e0c6`; after is `d8d674784e4279e847b450e5908dc29db17a6be0`. Real Linux web app, Chrome154, DPR2, 1440×900 and390×844, light and dark. Separate worktrees and isolated state; same MP4 and scripted commands.

Core result: unchanged paused video remains at5s with zero emptied/loadstart events after four read-only turns; baseline resets to0.1s. Real edits and atomic replacements update the preview; active playback defers the update until pause.

Limitations: desktop/Electron and native mobile were not run. Signed/direct PR video callers, ended release, true signed-token expiry/retry, older-server no-revision fallback and remote/tunnel propagation are runtime-unverified. R5 has focused object-URL test coverage; R6 has no dedicated compatibility test. Caller desktop-light frames differ despite equal paused2s event state; no decoded-frame equality is claimed. These gaps were disclosed to the proof auditor.

### R1–R3 recordings and full-viewport milestone sheets

Every row below covers R1, R2 and R3 as chapters in the same recording. SHA under Before is `968dd51704441138559a3fe9c348719f2b11e0c6`; under After is `d8d674784e4279e847b450e5908dc29db17a6be0`. The sheets stack four whole frames: initialized, after unchanged paused5 commands, changed-file refresh, active-play edit. They supplement the recordings; a still cannot prove reload absence.

| Settings / R1–R3 | Before | After | Diff |
|---|---|---|---|
| 1440×900 light | [before-1440-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d9dde654ec0c94c5/before-1440-light.mp4)<br>![before-1440-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b172984370ba5c20/before-1440-light-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [after-1440-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c8d2a39a80678aa2/after-1440-light.mp4)<br>![after-1440-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4da27da255e66f37/after-1440-light-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![core-1440-light-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d32bce289358806e/core-1440-light-diff0.png)<br>![core-1440-light-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ee4f4b552eb32cc6/core-1440-light-diff16.png) |
| 1440×900 dark | [before-1440-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f1c05e9b80e4d20e/before-1440-dark.mp4)<br>![before-1440-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3c1db97b14e6761c/before-1440-dark-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [after-1440-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1d355c3ed12d37ab/after-1440-dark.mp4)<br>![after-1440-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/9436799906e9f8ed/after-1440-dark-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![core-1440-dark-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5f406922c95221c4/core-1440-dark-diff0.png)<br>![core-1440-dark-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7dceeebee0bd3350/core-1440-dark-diff16.png) |
| 390×844 light | [before-390-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/40c443c6d153ff02/before-390-light.mp4)<br>![before-390-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1c16869553e37daf/before-390-light-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [after-390-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c98c0c9ff6d52472/after-390-light.mp4)<br>![after-390-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7c92199fd2cd91ea/after-390-light-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![core-390-light-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/05160e5172e05d26/core-390-light-diff0.png)<br>![core-390-light-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e18cbad9d8b23d92/core-390-light-diff16.png) |
| 390×844 dark | [before-390-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a4e31cb4c633725f/before-390-dark.mp4)<br>![before-390-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fb77ee1ace4cb958/before-390-dark-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [after-390-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0c2d211c3807bd7d/after-390-dark.mp4)<br>![after-390-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f4ebdbf99d61f4e0/after-390-dark-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![core-390-dark-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/06263c4f2c0089d3/core-390-dark-diff0.png)<br>![core-390-dark-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5a1f077e485b9127/core-390-dark-diff16.png) |

Actual unchanged-stage event counts (after initial load, four read-only turns):

| Settings | Before emptied / loadstart | After emptied / loadstart | Paused position before → after |
|---|---|---|---|
| 1440-light | 16 / 10 | 0 / 0 | 0.1s → 5s |
| 1440-dark | 16 / 8 | 0 / 0 | 0.1s → 5s |
| 390-light | 16 / 8 | 0 / 0 | 0.1s → 5s |
| 390-dark | 16 / 8 | 0 / 0 | 0.1s → 5s |

The baseline event totals include intermediate source churn and canceled/coalesced loads from completed commands and checkpoints. They are observations from these runs, not a claim of exactly two loads per command. All final after traces retain source-1 through R1; actual changes adopt sources2/3/4, and source4 persists throughout active playback until pause releases it to source5. Stat hashes remain original across the unchanged stage.

### R4 caller recordings

| Settings / R4 | Before | After | Diff |
|---|---|---|---|
| 1440-light | [callers-before-1440-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ab0bc0792a5aace5/callers-before-1440-light.mp4)<br>![callers-before-1440-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1a3642e4a6363ceb/callers-before-1440-light-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [callers-after-1440-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/33a7a58809154364/callers-after-1440-light.mp4)<br>![callers-after-1440-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8aa9934aea57f679/callers-after-1440-light-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![callers-1440-light-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f69962ae6d2f24cb/callers-1440-light-diff0.png)<br>![callers-1440-light-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4457244313e1a5db/callers-1440-light-diff16.png) |
| 1440-dark | [callers-before-1440-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8f328ff6d4562976/callers-before-1440-dark.mp4)<br>![callers-before-1440-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b88a827ef15e1df1/callers-before-1440-dark-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [callers-after-1440-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/72e7510d2e3a7ff7/callers-after-1440-dark.mp4)<br>![callers-after-1440-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6b83dbebb67a8b56/callers-after-1440-dark-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![callers-1440-dark-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bbc30e0665d52112/callers-1440-dark-diff0.png)<br>![callers-1440-dark-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e8b4d4869d33c640/callers-1440-dark-diff16.png) |
| 390-light | [callers-before-390-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/749712682c77f916/callers-before-390-light.mp4)<br>![callers-before-390-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5384ffd288d545cc/callers-before-390-light-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [callers-after-390-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f9208809d45780de/callers-after-390-light.mp4)<br>![callers-after-390-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/67ad626c4b9a7c1c/callers-after-390-light-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![callers-390-light-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ba00d4190cf9dca3/callers-390-light-diff0.png)<br>![callers-390-light-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/10596fba3fa0fb3c/callers-390-light-diff16.png) |
| 390-dark | [callers-before-390-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fec41f8ebb152f5a/callers-before-390-dark.mp4)<br>![callers-before-390-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0609eda08a5e9231/callers-before-390-dark-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [callers-after-390-dark.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/624cb6f412be9467/callers-after-390-dark.mp4)<br>![callers-after-390-dark-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/57cb8ba60c9466da/callers-after-390-dark-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![callers-390-dark-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f5919097da3f130a/callers-390-dark-diff0.png)<br>![callers-390-dark-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/19b1e314d74b4535/callers-390-dark-diff16.png) |
| Draft absolute file / 1440-light | [draft-before-1440-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/28dddf6011507498/draft-before-1440-light.mp4)<br>![draft-before-1440-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d61ca1854babaf3a/draft-before-1440-light-sheet.png)<br>`968dd51704441138559a3fe9c348719f2b11e0c6` | [draft-after-1440-light.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4af0ecf6d6fe474a/draft-after-1440-light.mp4)<br>![draft-after-1440-light-sheet.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a7f9ddb1b2db5cca/draft-after-1440-light-sheet.png)<br>`d8d674784e4279e847b450e5908dc29db17a6be0` | ![draft-1440-light-diff0.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/01d4aa60b6ac1dbe/draft-1440-light-diff0.png)<br>![draft-1440-light-diff16.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a75712f1d090b76c/draft-1440-light-diff16.png) |

R4 sweeps start before the user upload/send, then local and remote markdown playback/seek2/pause, attachment offscreen→visible, expanded autoplay/seek2/pause/close/reopen. The attachment remains muted, controls=false, preload=metadata; markdown players controls=true. Draft recording opens Files→`.t3/fixture.mp4` in an unsent draft and seeks/pauses2s. Draft smoke is one equivalent layout at1440/light as the matrix permits. PR container variants cannot be certified by these chat callers.

### Core chapter index (visible caption clock)

| Recording | paused0 commands | seek5 / paused5 commands | in-place / atomic edit | active edit / pause |
|---|---|---|---|---|
| after-1440-dark | 2.4s, 7.5s | 12.39s, 12.64s, 17.05s | 21.61s, 34.01s | 39.3s, 44.43s |
| after-1440-light | 2.09s, 6.71s | 11.35s, 11.62s, 16.2s | 20.77s, 30.86s | 35.97s, 41.13s |
| after-390-dark | 2.24s, 6.95s | 11.35s, 11.56s, 16.01s | 20.67s, 30.25s | 35.32s, 39.83s |
| after-390-light | 2.17s, 6.67s | 11.13s, 11.32s, 16.25s | 20.76s, 31.48s | 36.43s, 41.34s |
| before-1440-dark | 2.13s, 7.02s | 11.94s, 12.23s, 16.95s | 21.74s, 32.18s | 37.35s, 42.39s |
| before-1440-light | 2.46s, 7.16s | 11.94s, 12.2s, 16.98s | 21.89s, 32.72s | 37.89s, 42.75s |
| before-390-dark | 2.15s, 7.09s | 11.59s, 11.81s, 16.28s | 20.77s, 30.43s | 35.7s, 40.22s |
| before-390-light | 2.22s, 6.65s | 11.28s, 11.67s, 16.83s | 21.79s, 32.2s | 37.14s, 42.29s |

Full caller and draft chapter timestamps: [chapters.md](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3ab9c4cf3e23ac7e/chapters.md).
### What else changed

Diff algorithm: per pixel maximum absolute R/G/B channel difference; bright magenta if >0 or >16 **8-bit levels (16/255)**, black otherwise. No alignment, masking, crop, or subthreshold-equality claim. SHA headers themselves differ and are included. Exact sampled times, native frame sizes and differing-pixel counts are in the linked manifest/bundle.

- Intended R1 difference: baseline transient blank/loading frames and resets to first preview frame; after stays on the selected flower frame at5s. Source IDs differ after baseline churn. This changes video contents/playhead/controls timing, not panel styling. See each core recording’s R1 captions and first two sheet frames.
- R2: both replace flower with Sintel and duration5.055→52.208333; reset/loading moments vary. The scene near Sintel’s opening is dark; black or spinner stills are transient refresh samples, not proof of failed decoding. Confirm loadedmetadata/ready4 in the event logs and later playback chapter.
- R3: both retain the long clip while playing, then return to flower on pause. Exact animated frames differ because playback/command completion timing is not frozen. The `ended` route was not exercised.
- Sandbox UI: before breadcrumb/project is `issue-23089-before`; after is `issue-23089`. Detached baseline versus fix branch labels and sandbox change counts can differ when their panels are visible. Main sidebar is hidden for core/draft. Caller sweeps may show sandbox file/change sidebar; after contains the seven-file +138/−5 fix while baseline has0. No maintainer projects/private threads are seeded.
- R4 desktop-light: local signed markdown has currentTime2/ready4 in both logs, but the sampled after image resembles the initial flower frame while before shows the2s frame. Native controls differ too. The cause (rendering/capture timing versus player behavior) is not established; do not certify frame equality from these captures.
- Time labels, relative ages, worked durations, step elapsed captions, source-ID counts, focus/cursor/hover and native control visibility differ. Browser recording start/stream lag differs slightly. Chat scroll follows the same steps but small content/timing differences shift lines. R4 local/remote videos can show briefly loading at different encoded frames. These are unmasked in both diffs.
- The capture-only bottom caption and SHA headers are added identically but contain different elapsed times/SHAs/source observations. They can cover the lower composer edge. These are not shipped UI changes.
- No new product labels, colors, layout, typography or controls are introduced by the fix. This statement is based on the seven-file diff; unmasked image deltas are not all attributable to the feature. Non-feature differences above mean strict frozen-clock evidence equality was not achieved and requires PASS2 judgment.

### Rebuildable public data and checks

Original: [23089-original.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3626b0c6c8e09083/23089-original.mp4) — SHA256 `0cd83d944a6ca7822b4a8306cecc60a36e859b041f6702c6a1ad9ead78924451`,5.055s. Changed: [23089-changed.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/27af8dd50f7671e9/23089-changed.mp4) — SHA256 `b670602fa00934ca27c4351bb0efe7ea7a07fae57284e44226025eeed7c51254`,52.208333s. Original is MDN flower; changed is W3 Sintel trailer.

[public-evidence-bundle.zip](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b45709b5d76d30cd/public-evidence-bundle.zip) contains public-safe provider adaptations, capture scripts, file-operation/stat/hash transcripts, media events with source IDs only, persisted read-only-command outputs, chapter timestamps, rendering manifest, test outputs and SHA256 inventory. [chapters.md](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3ab9c4cf3e23ac7e/chapters.md) provides every narrated step/time. [sheets-manifest.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0997ce34d4b7b619/sheets-manifest.json) lists every extracted frame/time/diff count. No raw signed URLs, credentials, private thread content, databases or server logs are included.

Focused commands (after checkout’s own vp, Vitest5.0.5): `cd apps/server && ../../node_modules/.bin/vp test run src/assets/AssetAccess.test.ts` (25 pass); `cd apps/web && ../../node_modules/.bin/vp test run src/components/media/MediaVideoPlayer.browser.test.tsx` (1 pass); `cd apps/web && ../../node_modules/.bin/vp test run src/components/files/FilePreviewPanel.test.ts` (13 pass). No repo-wide checks. The player test uses generated WebM/object URLs and asserts source retention, revision replacement, revoked-held-URL fallback src/no alert. It does not establish live signed-URL recovery/decoding.


Implemented by Claude Opus 5.5 through Claude Agent SDK; triage, verification and independent review by GPT-6.1-Sol through Codex.


<!-- gc2-pull-create:ce3b7198f74911bea097bfca494882b596ea6cf39300ae960d0c1fb0f4105455 -->
