Section: Creative Director preview follow-ups (#2702)
A federated video poster never un-sticks from "Syncing".
peerSyncAssets.js#doPullOneAsset regenerates a pulled video's thumbnail locally but emits asset-arrived only for the *.mp4 — never for the .jpg — so MediaImage's exact-filename listener (now used for the CD card posters in ProjectPreview.jsx) never fires, and the card sits on the placeholder until a remount. Confirmed in server/services/sharing/peerSyncAssets.js:845-907 (doPullOneAsset): the peerSyncEvents.emit('asset-arrived', …) call at line 881 fires once, before the video branch; the video-thumbnail regeneration at lines 902-906 (await generateThumbnail(videoPath, jobId).catch(() => null)) has no matching emit afterward.
Worse for a stitched final: the regenerated name is derived from the VIDEO filename (const jobId = safeName.replace(/\.[a-z0-9]+$/i, ''), line 903) — but a CD project's stitched final is rendered by the video-timeline service, which names its file timeline-<projectId-slice>-<ts>.mp4 while minting an independent randomUUID() as the history-row id (server/services/videoTimeline/local.js:358-359: const jobId = randomUUID(); const filename = \timeline-${projectId.slice(0, 8)}-${Date.now()}.mp4`;). So for a stitched final, doPullOneAsset's derived "jobId" is actually the timeline-...filename stem, not the real history id — while every poster URL in the UI is built from the real.jpg(the history row'sid/thumbnail` field). The regenerated thumbnail lands under the wrong name entirely, not just un-eventfully.
Fix server-side: emit an asset-arrived for the regenerated thumbnail, and key its name off the synced history row's thumbnail field rather than the mp4 basename.
Flagged by codex review on PR #2719.
Migrated from PLAN.md by /do:replan --issues.
Section: Creative Director preview follow-ups (#2702)
A federated video poster never un-sticks from "Syncing".
peerSyncAssets.js#doPullOneAssetregenerates a pulled video's thumbnail locally but emitsasset-arrivedonly for the*.mp4— never for the.jpg— soMediaImage's exact-filename listener (now used for the CD card posters inProjectPreview.jsx) never fires, and the card sits on the placeholder until a remount. Confirmed inserver/services/sharing/peerSyncAssets.js:845-907(doPullOneAsset): thepeerSyncEvents.emit('asset-arrived', …)call at line 881 fires once, before the video branch; the video-thumbnail regeneration at lines 902-906 (await generateThumbnail(videoPath, jobId).catch(() => null)) has no matching emit afterward.Worse for a stitched final: the regenerated name is derived from the VIDEO filename (
const jobId = safeName.replace(/\.[a-z0-9]+$/i, ''), line 903) — but a CD project's stitched final is rendered by the video-timeline service, which names its filetimeline-<projectId-slice>-<ts>.mp4while minting an independentrandomUUID()as the history-row id (server/services/videoTimeline/local.js:358-359:const jobId = randomUUID(); const filename = \timeline-${projectId.slice(0, 8)}-${Date.now()}.mp4`;). So for a stitched final,doPullOneAsset's derived "jobId" is actually thetimeline-...filename stem, not the real history id — while every poster URL in the UI is built from the real.jpg(the history row'sid/thumbnail` field). The regenerated thumbnail lands under the wrong name entirely, not just un-eventfully.Fix server-side: emit an
asset-arrivedfor the regenerated thumbnail, and key its name off the synced history row'sthumbnailfield rather than the mp4 basename.Flagged by codex review on PR #2719.
Migrated from PLAN.md by /do:replan --issues.