BOLT-1193: brush slide-jump residue — pre-claim transform key from CONSTRAINED matrix
failedAgent: richie-engineer
Priority: 0
Follow-up to 94fcd2be82 (suppress no-drag brush click commit + zoom-transform feedback loop). Richie's 2026-06-09 12:30 UTC GIF (Slack ts 1781008207.494869) shows the slide-jump symptom is partially live: late frames have move-cursor at ~38% of slider track while the brush rectangle has snapped forward to ~45-58%, and the chart x-axis tracks the brushed position not the cursor.
ROOT CAUSE: The previous fix pre-claims lastTransformRef in syncTransformToDomain using the RAW computed scaleX/translateX. But visx Zoom pipes every transform through its constrain callback before storing it (we clamp translateX to [chartWidth*(1-scaleX), 0]). Near the brush's right-edge saturation, the constrained translateX differs from our raw value by floating-point drift or a hard clamp. The Zoom render-prop then computes transformKey from the CONSTRAINED matrix, key mismatches our pre-claim, setTimeout(handleZoomTransform) schedules, and during a fast drag that deferred round-trip fires after a newer brush emission and clobbers it with the stale constrained-derived domain. Net effect: brush snaps forward by ~constrain-clamp distance whenever motion accumulates near saturation.
FIX:
1. Extract the inline `constrain` arrow (currently in <Zoom constrain={...}>) into a useCallback `constrainTransform(matrix)` returning the constrained matrix. Same logic, just hoisted.
2. <Zoom constrain={constrainTransform}> uses it directly.
3. In syncTransformToDomain: compute raw {scaleX,translateX}, call constrainTransform to get the matrix visx will actually store, derive the pre-claim key from the CONSTRAINED matrix, then setTransformMatrix with the constrained values.
4. Same treatment in handleResetZoom — pre-claim key '1.0000-0.00' is fine for the identity matrix (it survives constrain unchanged since scaleX=1, translateX=0 is within bounds), but use constrainTransform for parity.
FILE: packages/edges/src/components/charts/ChartContainer/ChartContainer.tsx
BRANCH: winston/bolt-1193-brush-zoom-auto-densify (existing PR #11790)
WORKDIR: /home/agent/agents/richie-engineer/mono (already on the correct branch)
TEST PLAN:
- Existing ChartBrush.test.tsx + ChartContainer.test.tsx + SiteEnergyCharts.test.tsx all still pass (`yarn workspace @texturehq/edges test ChartContainer ChartBrush`, `yarn workspace dashboard test SiteEnergyCharts`).
- Add a new SiteEnergyCharts test that simulates a fast sequence of brush onChange emissions near the right-edge saturation and asserts onZoomChange is called with each emitted domain — i.e. no stale-domain clobber.
ACCEPTANCE: Push to existing branch, CI green, ping Richie with a sentence describing what changed and ask him to re-test the GIF scenario in the preview deploy.
Event Timeline
created
subagent_spawned
spawn claim: bolt-1193-constrained-key-preclaim
status_change
queued → in_progress
failed
lease expired — re-queued for retry
in_progress → queued
subagent_completed
subagent done: constrained-matrix pre-claim shipped — commits 80ace108ed + fb8b4d9e3e, CI substantive green
status_change
queued → blocked
status_change
blocked → failed