fix: resolve cloud output video missing-media false positives#13507
Conversation
🎨 Storybook: ✅ Built — View Storybook📦 Bundle: 7.78 MB gzip 🔴 +316 BDetailsSummary
Category Glance App Entry Points — 47.8 kB (baseline 47.8 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.27 MB (baseline 1.27 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 98 kB (baseline 98 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 9 added / 9 removed / 3 unchanged Panels & Settings — 546 kB (baseline 546 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 16 unchanged User & Accounts — 29.1 kB (baseline 29.1 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 7 added / 7 removed / 3 unchanged Editors & Dialogs — 117 kB (baseline 117 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 4 added / 4 removed / 1 unchanged UI Components — 57.5 kB (baseline 57.5 kB) • ⚪ 0 BReusable component library chunks
Status: 5 added / 5 removed / 8 unchanged Data & Services — 270 kB (baseline 270 kB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 13 added / 13 removed / 3 unchanged Utilities & Hooks — 3.39 MB (baseline 3.38 MB) • 🔴 +2.1 kBHelpers, composables, and utility bundles
Status: 16 added / 16 removed / 17 unchanged Vendor & Third-Party — 15.3 MB (baseline 15.3 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 11.7 MB (baseline 11.7 MB) • ⚪ 0 BBundles that do not match a named category
Status: 67 added / 67 removed / 98 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-08T19:04:57.533Z",
"gitSha": "f8597bb537a5fa836dc2ace8c971e27f227aa7ae",
"branch": "codex/fix-cloud-output-video-missing-media",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2040.1709999999866,
"styleRecalcs": 7,
"styleRecalcDurationMs": 6.790999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 408.257,
"heapDeltaBytes": -8017892,
"heapUsedBytes": 45206608,
"domNodes": -292,
"jsHeapTotalBytes": 16642048,
"scriptDurationMs": 17.01,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2046.0100000000239,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.053999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 400.183,
"heapDeltaBytes": -1322836,
"heapUsedBytes": 50800816,
"domNodes": -292,
"jsHeapTotalBytes": 16904192,
"scriptDurationMs": 16.845,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2003.120000000024,
"styleRecalcs": 78,
"styleRecalcDurationMs": 53.06799999999999,
"layouts": 12,
"layoutDurationMs": 4.025,
"taskDurationMs": 946.311,
"heapDeltaBytes": -12494032,
"heapUsedBytes": 57089588,
"domNodes": -238,
"jsHeapTotalBytes": 20074496,
"scriptDurationMs": 123.38000000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1841.876999999954,
"styleRecalcs": 73,
"styleRecalcDurationMs": 37.346000000000004,
"layouts": 12,
"layoutDurationMs": 3.903,
"taskDurationMs": 780.375,
"heapDeltaBytes": -13282284,
"heapUsedBytes": 56262400,
"domNodes": -244,
"jsHeapTotalBytes": 20336640,
"scriptDurationMs": 112.321,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1773.032999999998,
"styleRecalcs": 31,
"styleRecalcDurationMs": 18.938,
"layouts": 6,
"layoutDurationMs": 0.7670000000000001,
"taskDurationMs": 370.02599999999995,
"heapDeltaBytes": -3674840,
"heapUsedBytes": 65803280,
"domNodes": -225,
"jsHeapTotalBytes": 12996608,
"scriptDurationMs": 22.409,
"eventListeners": -184,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1724.6870000000172,
"styleRecalcs": 30,
"styleRecalcDurationMs": 16.632,
"layouts": 6,
"layoutDurationMs": 0.5910000000000002,
"taskDurationMs": 328.893,
"heapDeltaBytes": -3938224,
"heapUsedBytes": 49131232,
"domNodes": -242,
"jsHeapTotalBytes": 10088448,
"scriptDurationMs": 18.112999999999996,
"eventListeners": -186,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "dom-widget-clipping",
"durationMs": 577.7920000000449,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.316000000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 345.605,
"heapDeltaBytes": 8595076,
"heapUsedBytes": 66371148,
"domNodes": 20,
"jsHeapTotalBytes": 16252928,
"scriptDurationMs": 56.313,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 613.9460000000554,
"styleRecalcs": 11,
"styleRecalcDurationMs": 7.807000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 384.48799999999994,
"heapDeltaBytes": -23528704,
"heapUsedBytes": 45995048,
"domNodes": -281,
"jsHeapTotalBytes": 5656576,
"scriptDurationMs": 55.703,
"eventListeners": -201,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66666666666665,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2061.4249999999856,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.580999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 586.995,
"heapDeltaBytes": -997460,
"heapUsedBytes": 59244500,
"domNodes": -276,
"jsHeapTotalBytes": -565248,
"scriptDurationMs": 92.587,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2039.131999999995,
"styleRecalcs": 8,
"styleRecalcDurationMs": 6.749999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 544.84,
"heapDeltaBytes": -9446452,
"heapUsedBytes": 57926504,
"domNodes": -273,
"jsHeapTotalBytes": -1843200,
"scriptDurationMs": 82.96300000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2070.19600000001,
"styleRecalcs": 66,
"styleRecalcDurationMs": 16.018,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 976.3420000000001,
"heapDeltaBytes": 27694872,
"heapUsedBytes": 81348408,
"domNodes": 8,
"jsHeapTotalBytes": 729088,
"scriptDurationMs": 352.21899999999994,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2108.573999999976,
"styleRecalcs": 68,
"styleRecalcDurationMs": 17.282,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1091.623,
"heapDeltaBytes": 13480832,
"heapUsedBytes": 82201436,
"domNodes": -276,
"jsHeapTotalBytes": -1638400,
"scriptDurationMs": 410.16,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3083.432000000016,
"styleRecalcs": 63,
"styleRecalcDurationMs": 18.323,
"layouts": 60,
"layoutDurationMs": 8.049000000000001,
"taskDurationMs": 1255.744,
"heapDeltaBytes": 12691312,
"heapUsedBytes": 66911864,
"domNodes": -281,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 470.444,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3104.575999999952,
"styleRecalcs": 63,
"styleRecalcDurationMs": 16.325,
"layouts": 60,
"layoutDurationMs": 7.804,
"taskDurationMs": 1245.661,
"heapDeltaBytes": 13253768,
"heapUsedBytes": 66916148,
"domNodes": -284,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 464.8,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2042.4770000000194,
"styleRecalcs": 7,
"styleRecalcDurationMs": 7.1850000000000005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 612.1289999999999,
"heapDeltaBytes": -2456488,
"heapUsedBytes": 59377728,
"domNodes": -274,
"jsHeapTotalBytes": -565248,
"scriptDurationMs": 103.80899999999998,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2040.5070000000478,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.289000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 529.4649999999999,
"heapDeltaBytes": -10288632,
"heapUsedBytes": 58571104,
"domNodes": -273,
"jsHeapTotalBytes": -1056768,
"scriptDurationMs": 84.269,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 595.9170000000427,
"styleRecalcs": 46,
"styleRecalcDurationMs": 11.24,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 407.15599999999995,
"heapDeltaBytes": -22095312,
"heapUsedBytes": 47528640,
"domNodes": -280,
"jsHeapTotalBytes": 6180864,
"scriptDurationMs": 128.092,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 606.6349999999829,
"styleRecalcs": 49,
"styleRecalcDurationMs": 13.404,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 401.037,
"heapDeltaBytes": -22120124,
"heapUsedBytes": 47530244,
"domNodes": -272,
"jsHeapTotalBytes": 5656576,
"scriptDurationMs": 123.919,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-idle",
"durationMs": 2061.0149999999976,
"styleRecalcs": 10,
"styleRecalcDurationMs": 10.154,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 464.47799999999995,
"heapDeltaBytes": -8449396,
"heapUsedBytes": 61222956,
"domNodes": -279,
"jsHeapTotalBytes": 18763776,
"scriptDurationMs": 19.936999999999998,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-idle",
"durationMs": 2039.2050000000381,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.549000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 407.4530000000001,
"heapDeltaBytes": -2740692,
"heapUsedBytes": 49693132,
"domNodes": -290,
"jsHeapTotalBytes": 16904192,
"scriptDurationMs": 15.538,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1756.744000000026,
"styleRecalcs": 77,
"styleRecalcDurationMs": 41.732000000000006,
"layouts": 16,
"layoutDurationMs": 4.512,
"taskDurationMs": 755.463,
"heapDeltaBytes": -17031488,
"heapUsedBytes": 52690620,
"domNodes": -233,
"jsHeapTotalBytes": 19025920,
"scriptDurationMs": 97.229,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1751.8019999999979,
"styleRecalcs": 77,
"styleRecalcDurationMs": 39.32299999999999,
"layouts": 16,
"layoutDurationMs": 4.36,
"taskDurationMs": 718.9920000000001,
"heapDeltaBytes": -16881216,
"heapUsedBytes": 52675812,
"domNodes": -239,
"jsHeapTotalBytes": 19550208,
"scriptDurationMs": 89.60300000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 931.577999999945,
"styleRecalcs": 18,
"styleRecalcDurationMs": 31.343999999999998,
"layouts": 14,
"layoutDurationMs": 14.841999999999997,
"taskDurationMs": 744.8300000000002,
"heapDeltaBytes": 31732240,
"heapUsedBytes": 98600344,
"domNodes": 13673,
"jsHeapTotalBytes": 13107200,
"scriptDurationMs": 26.478,
"eventListeners": 2533,
"totalBlockingTimeMs": 132,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "viewport-pan-sweep",
"durationMs": 8137.079999999969,
"styleRecalcs": 249,
"styleRecalcDurationMs": 58.765,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3887.0900000000006,
"heapDeltaBytes": 14679608,
"heapUsedBytes": 74780748,
"domNodes": -275,
"jsHeapTotalBytes": 5931008,
"scriptDurationMs": 1354.2889999999998,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8204.834000000006,
"styleRecalcs": 250,
"styleRecalcDurationMs": 59.807,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3554.7180000000003,
"heapDeltaBytes": 6007992,
"heapUsedBytes": 65963836,
"domNodes": -274,
"jsHeapTotalBytes": 688128,
"scriptDurationMs": 1157.928,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.80000000000109
},
{
"name": "vue-large-graph-idle",
"durationMs": 13766.255999999998,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13737.482,
"heapDeltaBytes": -30626116,
"heapUsedBytes": 170918660,
"domNodes": -3302,
"jsHeapTotalBytes": 21467136,
"scriptDurationMs": 487.393,
"eventListeners": -16374,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 13057.23999999998,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13041.594,
"heapDeltaBytes": -38504712,
"heapUsedBytes": 170604384,
"domNodes": -3300,
"jsHeapTotalBytes": 233472,
"scriptDurationMs": 503.996,
"eventListeners": -16378,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 16898.98900000003,
"styleRecalcs": 110,
"styleRecalcDurationMs": 24.13500000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16876.542999999998,
"heapDeltaBytes": -28140184,
"heapUsedBytes": 153996564,
"domNodes": -3302,
"jsHeapTotalBytes": 16224256,
"scriptDurationMs": 792.112,
"eventListeners": -16370,
"totalBlockingTimeMs": 14,
"frameDurationMs": 17.220000000000073,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 16885.68499999997,
"styleRecalcs": 115,
"styleRecalcDurationMs": 22.51299999999995,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16861.197,
"heapDeltaBytes": -22035356,
"heapUsedBytes": 167312740,
"domNodes": -3302,
"jsHeapTotalBytes": 17797120,
"scriptDurationMs": 783.021,
"eventListeners": -16370,
"totalBlockingTimeMs": 10,
"frameDurationMs": 18.33666666666674,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 478.78899999989244,
"styleRecalcs": 17,
"styleRecalcDurationMs": 25.118000000000002,
"layouts": 4,
"layoutDurationMs": 1.1409999999999998,
"taskDurationMs": 221.536,
"heapDeltaBytes": -22174220,
"heapUsedBytes": 48704360,
"domNodes": -165,
"jsHeapTotalBytes": 4345856,
"scriptDurationMs": 17.535000000000004,
"eventListeners": -134,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "workflow-execution",
"durationMs": 483.7870000000066,
"styleRecalcs": 17,
"styleRecalcDurationMs": 29.976000000000003,
"layouts": 4,
"layoutDurationMs": 1.0909999999999997,
"taskDurationMs": 225.083,
"heapDeltaBytes": -22036192,
"heapUsedBytes": 48722616,
"domNodes": -175,
"jsHeapTotalBytes": 4870144,
"scriptDurationMs": 17.503,
"eventListeners": -132,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
}
]
}🎭 Playwright: ✅ 1692 passed, 0 failed · 2 flaky📊 Browser Reports
|
🎭 Playwright: ⏳ Running... |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughCloud output missing-media handling now resolves subfoldered output video candidates through hash-derived identifiers, with matching resolver logic, browser runtime checks, and unit tests updated to cover the new flow. ChangesCloud output media hash matching
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewersSuggested reviewers: 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/platform/missingMedia/missingMediaAssetResolver.ts (1)
252-276: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: extract shared loop pattern to reduce duplication.
rememberResolvedTargetNamesandrememberResolvedCloudTargetNamesshare the samefor...of+targetNames.has+foundTargetNames.addloop, differing only in the detection-name source. A small shared helper could reduce duplication, though the current clarity is acceptable given the distinct matching semantics.♻️ Optional refactor: extract shared matching loop
function rememberResolvedTargetNames( asset: AssetItem, targetNames: ReadonlySet<string>, foundTargetNames: Set<string>, options: MediaPathDetectionOptions ) { if (targetNames.size === 0) return - for (const name of getAssetDetectionNames(asset, options)) { - if (targetNames.has(name)) foundTargetNames.add(name) - } + matchTargetNames(getAssetDetectionNames(asset, options), targetNames, foundTargetNames) } function rememberResolvedCloudTargetNames( asset: AssetItem, targetNames: ReadonlySet<string>, foundTargetNames: Set<string>, options: MediaPathDetectionOptions ) { if (targetNames.size === 0 || !asset.hash) return - for (const name of getMediaPathDetectionNames(asset.hash, options)) { - if (targetNames.has(name)) foundTargetNames.add(name) - } + matchTargetNames(getMediaPathDetectionNames(asset.hash, options), targetNames, foundTargetNames) +} + +function matchTargetNames( + names: Iterable<string>, + targetNames: ReadonlySet<string>, + foundTargetNames: Set<string> +) { + for (const name of names) { + if (targetNames.has(name)) foundTargetNames.add(name) + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/platform/missingMedia/missingMediaAssetResolver.ts` around lines 252 - 276, Both rememberResolvedTargetNames and rememberResolvedCloudTargetNames duplicate the same matching loop over detection names. Extract the shared “iterate names, check targetNames.has, add to foundTargetNames” logic into a small helper in missingMediaAssetResolver.ts, and keep each function focused on supplying its own source of names via getAssetDetectionNames or getMediaPathDetectionNames while preserving the existing early-return checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/platform/missingMedia/missingMediaAssetResolver.ts`:
- Around line 252-276: Both rememberResolvedTargetNames and
rememberResolvedCloudTargetNames duplicate the same matching loop over detection
names. Extract the shared “iterate names, check targetNames.has, add to
foundTargetNames” logic into a small helper in missingMediaAssetResolver.ts, and
keep each function focused on supplying its own source of names via
getAssetDetectionNames or getMediaPathDetectionNames while preserving the
existing early-return checks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0a442a53-6312-46f0-8900-19ba6f8abc0b
📒 Files selected for processing (6)
browser_tests/assets/missing/missing_media_cloud_output_video_subfolder.jsonbrowser_tests/tests/propertiesPanel/errorsTabMissingMediaRuntime.spec.tssrc/platform/missingMedia/missingMediaAssetResolver.test.tssrc/platform/missingMedia/missingMediaAssetResolver.tssrc/platform/missingMedia/missingMediaScan.test.tssrc/platform/missingMedia/missingMediaScan.ts
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #13507 +/- ##
==========================================
+ Coverage 77.76% 77.91% +0.15%
==========================================
Files 1650 1650
Lines 92458 93625 +1167
Branches 31998 32835 +837
==========================================
+ Hits 71902 72950 +1048
- Misses 19888 20007 +119
Partials 668 668
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 87 files with indirect coverage changes 🚀 New features to boost your workflow:
|
benceruleanlu
left a comment
There was a problem hiding this comment.
Work really needs to get put into this part of the codebase, too bad it's not a priority.
| } | ||
| } | ||
|
|
||
| function rememberResolvedCloudTargetNames( |
There was a problem hiding this comment.
Matching only asset.hash here means candidates that resolve by asset name (or subfolder metadata) no longer stop pagination — every workflow load pages through the full output-asset list. Only subfoldered candidates need the hash-only strictness; flat ones could still early-exit on a name match.
There was a problem hiding this comment.
Good catch, thank you. I pushed a small follow-up in 4333ba1 so the hash-only requirement is limited to basename fallbacks from subfoldered Cloud output candidates. Flat output targets can now still resolve and stop pagination through the normal asset detection names, and I added a unit test for that early-exit case so it does not regress.
4333ba1
Summary
Fix Cloud missing-media false positives for output videos inserted as loader nodes when the widget value includes a subfoldered output path such as
video/<hash>.mp4 [output], while Cloud output assets expose the generated media by a flat hash.Changes
asset.namedoes not stop loading before the hash match appears.LoadVideowithvideo/cloud-video-hash.mp4 [output].Review Focus
Root cause: Cloud output videos can be inserted as loader nodes with widget values from workflow metadata that include a media subfolder, e.g.
video/<hash>.mp4 [output]. The Cloud output asset list resolves generated media by a flat hash. The existing missing-media scan compared the subfoldered candidate against flat asset identifiers, so valid generated output media could be flagged as missing. Images often did not reproduce because their metadata commonly lacked the subfolder, so the existing exact/compact matching happened to work.Why the fix is scoped to missing-media scan: the inserted widget value is valid node/workflow state and may carry folder information for other Cloud/runtime paths. Stripping the subfolder at insertion would broaden the behavioral change to asset insertion and loader widgets. Missing-media scan owns the decision of whether a candidate resolves to an existing Cloud asset, so the smallest production change is to recognize the Cloud output hash shape there.
Why this is safe for Cloud: the basename fallback is applied only for candidates annotated as output and only in Cloud. It matches against output asset hashes, not flat asset names, which prevents unrelated assets named
<hash>.mp4from masking a real miss. Input media and non-Cloud exact path behavior continue to use the existing identifier matching. Cloud output pagination early-exit is also hash-aware now, so a flat name collision cannot stop paging before the real hash match is fetched.Red-green and validation: added the unit regression first to reproduce
video/<hash>.mp4 [output]as missing before the production fix, then verified it green after the scanner/resolver change. Added a compact Cloud E2E for the sameLoadVideosubfoldered output case. Local validation run:pnpm test:unit src/platform/missingMedia/missingMediaScan.test.ts src/platform/missingMedia/missingMediaAssetResolver.test.ts- 59 passedPLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://localhost:5175 PLAYWRIGHT_SETUP_API_URL=http://localhost:8188 pnpm exec playwright test browser_tests/tests/propertiesPanel/errorsTabMissingMediaRuntime.spec.ts --project=cloud --grep "subfoldered output video" --repeat-each=5 --reporter=line- 5 passedPLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://localhost:5175 PLAYWRIGHT_SETUP_API_URL=http://localhost:8188 pnpm exec playwright test browser_tests/tests/propertiesPanel/errorsTabMissingMediaRuntime.spec.ts --project=cloud --grep "resolves compact annotated output media|resolves subfoldered output video" --reporter=line- 2 passedpnpm typecheckpnpm typecheck:browserpnpm knippnpm lintScreenshots (if applicable)
Before
2026-07-08.3.15.34.mov
After
2026-07-08.3.16.35.mov