test: reproduce #15577 and #15581 on the ECS branch - #15592
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
🎭 Playwright: 🕵🏻 0 passed, 0 failed📊 Browser Reports
🎨 Storybook: ✅ Built — View Storybook📦 Bundle Size
⚡ Performance Report
Absolute values
Raw data{
"timestamp": "2026-08-22T05:42:52.423Z",
"gitSha": "423ca41768cf58b930cdc829565ce7ff25f74abc",
"branch": "cb__repro-15577-15581",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2036.8299999999806,
"styleRecalcs": 8,
"styleRecalcDurationMs": 6.984000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 478.87499999999994,
"heapDeltaBytes": -2113960,
"heapUsedBytes": 67050132,
"domNodes": -281,
"jsHeapTotalBytes": 4972544,
"scriptDurationMs": 7.610000000000002,
"eventListeners": -185,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2051.315999999929,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.212,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 478.279,
"heapDeltaBytes": -353852,
"heapUsedBytes": 68808352,
"domNodes": -284,
"jsHeapTotalBytes": 4972544,
"scriptDurationMs": 8.504000000000001,
"eventListeners": -185,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2318.4699999999907,
"styleRecalcs": 80,
"styleRecalcDurationMs": 42.617000000000004,
"layouts": 12,
"layoutDurationMs": 3.821,
"taskDurationMs": 1390.587,
"heapDeltaBytes": -7342988,
"heapUsedBytes": 62462124,
"domNodes": -281,
"jsHeapTotalBytes": 6545408,
"scriptDurationMs": 181.517,
"eventListeners": -185,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2158.02599999995,
"styleRecalcs": 79,
"styleRecalcDurationMs": 40.163000000000004,
"layouts": 12,
"layoutDurationMs": 3.4259999999999997,
"taskDurationMs": 1173.2600000000002,
"heapDeltaBytes": -8597928,
"heapUsedBytes": 60641424,
"domNodes": -280,
"jsHeapTotalBytes": 5496832,
"scriptDurationMs": 155.79999999999998,
"eventListeners": -185,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1737.6760000000218,
"styleRecalcs": 32,
"styleRecalcDurationMs": 16.275,
"layouts": 6,
"layoutDurationMs": 0.616,
"taskDurationMs": 337.06399999999996,
"heapDeltaBytes": 3750736,
"heapUsedBytes": 72729600,
"domNodes": 76,
"jsHeapTotalBytes": 5505024,
"scriptDurationMs": 9.914000000000001,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1722.264999999993,
"styleRecalcs": 32,
"styleRecalcDurationMs": 15.135,
"layouts": 6,
"layoutDurationMs": 0.528,
"taskDurationMs": 340.034,
"heapDeltaBytes": 4060240,
"heapUsedBytes": 73673056,
"domNodes": 76,
"jsHeapTotalBytes": 4980736,
"scriptDurationMs": 10.245,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 745.900000000006,
"styleRecalcs": 10,
"styleRecalcDurationMs": 7.018,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 427.859,
"heapDeltaBytes": -5842824,
"heapUsedBytes": 63752664,
"domNodes": 16,
"jsHeapTotalBytes": 5505024,
"scriptDurationMs": 32.336999999999996,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 703.9380000001074,
"styleRecalcs": 11,
"styleRecalcDurationMs": 7.341,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 422.30799999999994,
"heapDeltaBytes": -6859288,
"heapUsedBytes": 62337220,
"domNodes": 18,
"jsHeapTotalBytes": 5505024,
"scriptDurationMs": 32.179,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2055.282000000034,
"styleRecalcs": 6,
"styleRecalcDurationMs": 5.497,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 555.182,
"heapDeltaBytes": -21993480,
"heapUsedBytes": 68546728,
"domNodes": -275,
"jsHeapTotalBytes": 3665920,
"scriptDurationMs": 32.409000000000006,
"eventListeners": -185,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2073.1969999999365,
"styleRecalcs": 6,
"styleRecalcDurationMs": 5.489000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 560.6510000000001,
"heapDeltaBytes": -21611672,
"heapUsedBytes": 68496088,
"domNodes": -282,
"jsHeapTotalBytes": 3928064,
"scriptDurationMs": 36.457,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 3295.5269999999928,
"styleRecalcs": 65,
"styleRecalcDurationMs": 10.225000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 2598.5719999999997,
"heapDeltaBytes": -5399056,
"heapUsedBytes": 86032128,
"domNodes": -274,
"jsHeapTotalBytes": -40960,
"scriptDurationMs": 933.09,
"eventListeners": -151,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 3292.3920000000635,
"styleRecalcs": 66,
"styleRecalcDurationMs": 10.623000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 2654.2180000000003,
"heapDeltaBytes": -13651472,
"heapUsedBytes": 77429304,
"domNodes": -280,
"jsHeapTotalBytes": 1007616,
"scriptDurationMs": 987.6229999999999,
"eventListeners": -151,
"totalBlockingTimeMs": 29,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 4384.21599999998,
"styleRecalcs": 66,
"styleRecalcDurationMs": 10.652999999999999,
"layouts": 60,
"layoutDurationMs": 7.295000000000001,
"taskDurationMs": 2563.671,
"heapDeltaBytes": 11465860,
"heapUsedBytes": 80919744,
"domNodes": 24,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 918.726,
"eventListeners": 12,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.80000000000109
},
{
"name": "large-graph-zoom",
"durationMs": 4390.350000000012,
"styleRecalcs": 66,
"styleRecalcDurationMs": 10.461000000000002,
"layouts": 60,
"layoutDurationMs": 6.745,
"taskDurationMs": 2528.5800000000004,
"heapDeltaBytes": -27555832,
"heapUsedBytes": 68381704,
"domNodes": -234,
"jsHeapTotalBytes": 2355200,
"scriptDurationMs": 884.7429999999999,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "legacy-node-drag",
"durationMs": 3155.1419999999553,
"styleRecalcs": 41,
"styleRecalcDurationMs": 5.19,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 2023.679,
"heapDeltaBytes": 13542568,
"heapUsedBytes": 80418180,
"domNodes": 0,
"jsHeapTotalBytes": 679936,
"scriptDurationMs": 202.84400000000002,
"eventListeners": 188,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "legacy-node-drag",
"durationMs": 3160.109000000034,
"styleRecalcs": 41,
"styleRecalcDurationMs": 5.115999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 2027.234,
"heapDeltaBytes": 13641960,
"heapUsedBytes": 80968332,
"domNodes": 0,
"jsHeapTotalBytes": 1204224,
"scriptDurationMs": 209.61899999999997,
"eventListeners": 188,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2032.594999999958,
"styleRecalcs": 4,
"styleRecalcDurationMs": 3.842999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 528.0339999999999,
"heapDeltaBytes": -19257424,
"heapUsedBytes": 73189560,
"domNodes": -272,
"jsHeapTotalBytes": -1576960,
"scriptDurationMs": 34.57900000000001,
"eventListeners": -155,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2029.9289999999246,
"styleRecalcs": 3,
"styleRecalcDurationMs": 8.474000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 555.395,
"heapDeltaBytes": -21893644,
"heapUsedBytes": 70811468,
"domNodes": -277,
"jsHeapTotalBytes": 3141632,
"scriptDurationMs": 33.452000000000005,
"eventListeners": -185,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 699.0749999999935,
"styleRecalcs": 45,
"styleRecalcDurationMs": 8.443,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 490.95,
"heapDeltaBytes": 17582084,
"heapUsedBytes": 87725700,
"domNodes": 16,
"jsHeapTotalBytes": 5505024,
"scriptDurationMs": 132.287,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 692.5260000000435,
"styleRecalcs": 45,
"styleRecalcDurationMs": 9.14,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 496.27500000000003,
"heapDeltaBytes": 17202888,
"heapUsedBytes": 80042100,
"domNodes": 16,
"jsHeapTotalBytes": 4980736,
"scriptDurationMs": 133.98,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 1990.4599999999846,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.247000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 465.973,
"heapDeltaBytes": -13426312,
"heapUsedBytes": 56352192,
"domNodes": -296,
"jsHeapTotalBytes": 5496832,
"scriptDurationMs": 6.517,
"eventListeners": -201,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2017.4630000000207,
"styleRecalcs": 9,
"styleRecalcDurationMs": 6.983999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 463.494,
"heapDeltaBytes": 9672324,
"heapUsedBytes": 72535384,
"domNodes": -297,
"jsHeapTotalBytes": 4710400,
"scriptDurationMs": 6.803,
"eventListeners": -231,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1823.6190000000079,
"styleRecalcs": 75,
"styleRecalcDurationMs": 34.166999999999994,
"layouts": 16,
"layoutDurationMs": 4.108,
"taskDurationMs": 1097.9130000000002,
"heapDeltaBytes": -3380940,
"heapUsedBytes": 66981508,
"domNodes": -298,
"jsHeapTotalBytes": 6545408,
"scriptDurationMs": 114.48700000000001,
"eventListeners": -201,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1824.4320000000016,
"styleRecalcs": 75,
"styleRecalcDurationMs": 35.589,
"layouts": 16,
"layoutDurationMs": 4.056000000000001,
"taskDurationMs": 1084.13,
"heapDeltaBytes": 12769340,
"heapUsedBytes": 76634580,
"domNodes": -297,
"jsHeapTotalBytes": 4972544,
"scriptDurationMs": 114.454,
"eventListeners": -233,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-transition-enter",
"durationMs": 1406.466000000023,
"styleRecalcs": 19,
"styleRecalcDurationMs": 31.251,
"layouts": 14,
"layoutDurationMs": 14.355999999999998,
"taskDurationMs": 899.093,
"heapDeltaBytes": -7393952,
"heapUsedBytes": 85350088,
"domNodes": 13671,
"jsHeapTotalBytes": 11010048,
"scriptDurationMs": 28.869000000000007,
"eventListeners": 2381,
"totalBlockingTimeMs": 129,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 12349.46100000002,
"styleRecalcs": 246,
"styleRecalcDurationMs": 34.433,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 9099.823,
"heapDeltaBytes": 10778964,
"heapUsedBytes": 101753048,
"domNodes": -276,
"jsHeapTotalBytes": 3334144,
"scriptDurationMs": 3187.147,
"eventListeners": -129,
"totalBlockingTimeMs": 12,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 12416.345999999976,
"styleRecalcs": 246,
"styleRecalcDurationMs": 33.065000000000005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 9013.043,
"heapDeltaBytes": 8188932,
"heapUsedBytes": 98845972,
"domNodes": -282,
"jsHeapTotalBytes": 4382720,
"scriptDurationMs": 3215.5,
"eventListeners": -129,
"totalBlockingTimeMs": 19,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 16677.279,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15872.428,
"heapDeltaBytes": -34534632,
"heapUsedBytes": 177257436,
"domNodes": -6548,
"jsHeapTotalBytes": -4657152,
"scriptDurationMs": 300.716,
"eventListeners": -7475,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.780000000000047,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 16587.821000000076,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15771.782000000001,
"heapDeltaBytes": -35379972,
"heapUsedBytes": 176461964,
"domNodes": -6548,
"jsHeapTotalBytes": 1560576,
"scriptDurationMs": 306.077,
"eventListeners": -7473,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.779999999999927,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 20805.406000000006,
"styleRecalcs": 176,
"styleRecalcDurationMs": 16.451000000000022,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 20335.411,
"heapDeltaBytes": -26959520,
"heapUsedBytes": 177212092,
"domNodes": -6548,
"jsHeapTotalBytes": 2871296,
"scriptDurationMs": 888.064,
"eventListeners": -7471,
"totalBlockingTimeMs": 65,
"frameDurationMs": 17.776666666666763,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 20584.369999999923,
"styleRecalcs": 173,
"styleRecalcDurationMs": 17.018000000000004,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 20160.957,
"heapDeltaBytes": -21352432,
"heapUsedBytes": 185205404,
"domNodes": -6548,
"jsHeapTotalBytes": -1343488,
"scriptDurationMs": 895.3130000000001,
"eventListeners": -7471,
"totalBlockingTimeMs": 39,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 140.21900000000187,
"styleRecalcs": 10,
"styleRecalcDurationMs": 18.256,
"layouts": 3,
"layoutDurationMs": 1.525,
"taskDurationMs": 104.868,
"heapDeltaBytes": 3830888,
"heapUsedBytes": 70454024,
"domNodes": 137,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 6.459000000000001,
"eventListeners": 49,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 502.7109999999766,
"styleRecalcs": 19,
"styleRecalcDurationMs": 22.772000000000002,
"layouts": 3,
"layoutDurationMs": 1.078,
"taskDurationMs": 135.879,
"heapDeltaBytes": 5741928,
"heapUsedBytes": 68631068,
"domNodes": 145,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 8.103,
"eventListeners": 97,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## feature/ecs-migration #15592 +/- ##
========================================================
Coverage ? 82.29%
========================================================
Files ? 1900
Lines ? 107660
Branches ? 34065
========================================================
Hits ? 88600
Misses ? 18722
Partials ? 338
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Seven it.fails assertions covering both configure-time link defects, plus controls that keep them honest. #15577: normalizeConfiguredTopology keys duplicates on target_id:target_slot and keeps data.links[first] rather than the link input.link names, so a workflow with two links into one input comes up wired to the wrong upstream node. conflictingOriginLinksRoot is byte-for-byte what main serializes after a pack creates a link through the legacy slot mirrors alone. #15581: a serialized input whose name has no live counterpart keeps its stale target_slot, the resulting occupied-target rejection breaks the loop, and every remaining move for that node is abandoned. Covers the dropped-input, renamed- input and directly-rejected-batch cases.
20039d9 to
14bb542
Compare
Both #15577 and #15581 reproduce on this branch, and #15577 is reachable through files today's shipping frontend already saves. Seven
it.failsassertions state the wanted behaviour; ten controls keep them from passing for the wrong reason.#15577 — reachable, and it re-wires the node
normalizeConfiguredTopologykeys duplicates ontarget_id:target_slotand keepsdata.links[first]rather than the linkinput.linknames. With two links into one input from different origins, the node comes up fed by a different upstream node than the file names, and nothing is logged.Reachability, measured rather than argued. Driving rgthree
link_fixer's mirror-only creation idiom (output.links.push(id)+input.link = id, noconnect()) onmainat32d0b6e202and serializing produces:That is
conflictingOriginLinksRootbyte for byte. The shape is not hypothetical and it persists across every save onmain.Same fixture, both branches:
main32d0b6e2029f6ab9addagetInputLink(0).origin_idinput.linknames3:0Dropping to one link is correct, the store enforces one link per input. Which one survives is the regression.
This branch closes the producer: the
input.linksetter ignores id assignment and theoutput.linksview discards additions, so the same idiom now serializes one link. Pinned bydiscards a link written only through the legacy slot mirrors. Forward-safe, but files saved before the branch ships still load wrong.Mutation: preferring the
input.link-referenced survivor and warning on the drop flips bothit.failsto pass, controls unchanged.The negative control
test-cases.mdspecified does not exist. Re-narrowing the key to the 4-tuple was predicted to leave two links registered and fail the degeneracy control. It does not: the store rejects the second link downstream and the terminal graph state is identical, link count and all. The 4-tuple key and the 2-tuple key are indistinguishable by any assertion on the resulting graph for this fixture. The control that remains proves the fixture is non-degenerate, which is what it is for.#15581 — reproduces, and the issue's suggested fallback does not fix it
A serialized input whose name has no live counterpart is skipped, keeps its stale
target_slot, and the resultingoccupied-targetrejectionbreaks the loop, abandoning every remaining move for that node.Three cases in
LGraph.inputSlotRealign.test.ts:configuredrops an input,configurerenames one, andrealignInputLinkSlotscalled directly on a pre-seeded incumbent. Net effect in cases 1 and 2 is thatin_areportsin_c's link andin_breportsin_a's. Nohas_errors,console.erroronly.Two mutations, and they disagree:
it.failsflippedupdateEndpoints'sremovalsThe per-link fallback fails because the collision cascades: link 3 squats slot 0, so link 1 cannot move off slot 1, so link 2 cannot move onto it. Retrying one at a time hits the same wall. Only evicting the stale incumbent clears it. Worth deciding before anyone implements the issue's first suggestion.
Counts
17 tests across the two files: 10 pass, 7 expected fail. The eight pre-existing
#3348tests stay green under both mutations, which is the negative control that the fix does not break what #3348 was filed for.oxfmtandoxlint --type-awareclean.vue-tsc --noEmitclean for the three files in this diff; the repo-wide count is not meaningful from this worktree, see below.On typecheck, because it will bite the next person working in a worktree with a borrowed
node_modules. The first two pushes carried 10 real type errors thatvitest,oxfmtandoxlint --type-awareall passed: nine branded-id mismatches (TS2339,TS2322onLinkId) and one wrong import path (TS2459). Fixed in4651215809and20039d9e42.They got through because my local typecheck was lying, in two different ways:
vue-tscOOMs at the 2GB default heap —FATAL ERROR: Ineffective mark-compacts near heap limit, exit 134, after 18 lines. Filtered for errors that reads as zero. Silence from a dead process is indistinguishable from a pass.TS2688. WithNODE_OPTIONS=--max-old-space-size=8192the run completes at exit 2 with 1418TS2688plus 68TS7006/TS7031/TS7053implicit-any errors in.vueand.stories.ts— downstream fallout of the broken type roots, not real.Working recipe: larger heap, confirm exit 2 rather than 134, then grep for your own changed files. Zero for all three files here.
Wider class, filed separately
All three
updateEndpointscall sites on this branch swallow rejection intoconsole.errorand degrade silently, none markshas_errors, none uses the repo's unifiedreportError.slotLinks.ts:192is the worst of them: on rejection it returns[]beforenode.inputs.splice, so the node keeps its old input layout and the empty return is indistinguishable from "nothing to replace". Follow-ups tracked in the workspace todo.