fix(graph): stop the compat engine's flow particles at flowSpeed=0 - #178
fix(graph): stop the compat engine's flow particles at flowSpeed=0#178Coding-Dev-Tools wants to merge 2 commits into
Conversation
…laxy mode The Galactic gravity, Black hole mass, Local solar gravity, and Space damping sliders previously only fed the galaxy-mode integrator. In the default overview/communities/compact views a settled d3 layout had already cooled, so a force-only re-render was invisible and the user-facing effect of the sliders was "nothing happens when I drag it". This change wires each spacetime slider into the d3-force installation so the layout visibly responds in every non-galaxy mode: - gravitationalConstant (0..200) scales the charge (node repulsion) strength. Default 100 -> 1.0x; max 200 -> 2.0x; min 0 -> 0x. - blackHoleMass (0..500) scales the existing gravity-driven centering strength via the same multiplier used by the galaxy-mode integrator (linear above the 160 baseline, value/160 below). Default 160 -> 1.0x; 500 -> 7.8x; 80 -> 0.5x. - localGravitationalConstant (0..200) scales the link spring strength. The existing d3 path used 1/(min degree) as the base; we now multiply by the same scalar so the slider tightens or loosens the visible link force. - damping (1..15) maps to fg.velocityDecay. At 1 the layout is bouncy (decay 0.05); at 15 it settles quickly (decay 0.85). Bounded 0.05..0.85 so the extreme ends stay usable. Two small helpers (clamp, blackHoleMassMultiplier) are inlined next to the d3-force install path; the existing helper in ledger.js is unchanged. A new regression test test_spacetime_sliders_reach_d3_forces_in_non_galaxy_mode instruments fg.d3Force / fg.velocityDecay to confirm each spacetime setting lands on the d3 wire. Fixes the user-reported "Galactic gravity / Black hole mass / Local solar gravity / Space damping sliders STILL NOT WORKING CORRECTLY" complaint.
The Flow speed slider in the compat engine had a residual floor of 0.002 at flowSpeed=0, so the particles kept crawling even when the user dragged the slider to zero. The every-node engine already enforced this with a `moving = speed > 0` guard; the compat engine is brought into line: - `flowActive` is true iff `flowSpeed > 0`. When false, the `flowing` flag short-circuits, the per-link particle count drops to 0, and the per-link speed callback returns 0 (no motion at all). - The visible end-to-end range is now floor (0) to 0.01 (at flowSpeed=100), with no residual motion at the low end. A new regression test `test_flow_speed_zero_stops_particle_motion_in_compat_engine` confirms the compat engine installs both `linkDirectionalParticles` and `linkDirectionalParticleSpeed` closures after a flowSpeed=0 setSettings. Bench: 293 dashboard+graph tests pass.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:97bc724b12
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Coding-Dev-Tools
commented
Aug 28, 2026
Closing in favor of #180 (the canonical stop-at-zero + widened flow-speed range fix) and #177 (which already carries the four-spacetime-slider d3-force routing bundled in this branch via commit 434a94c). I confirmed before closing that no code is lost:
Net effect: nothing is lost and the wider flow-speed range lands in main. |
Two open codex review threads on the flow-speed work, both on engraphis-graph.js and ledger.js: P2 (PR #180, line 9345; same shape as PR #178 P2, line 9365) "Preserve the default speed when flowSpeed is unset": when a standalone caller (e.g. `EngraphisGraph.create()` + `setData()` without first supplying `flowSpeed`) leaves `state.settings.flowSpeed` undefined, `Number(undefined)` is NaN. The previous guard treated NaN as active and let the speed formula compute with NaN, so links got three particles at an unusable speed. Now the flowSpeed variable starts from `rawFlowSpeed` (Number.isFinite check) and falls back to the historical default of 45 before both the active check and the speed formula. NaN no longer leaks into either. P2 (PR #180, line 9333) "Stop flow only at the slider's visible zero endpoint": in the dashboard the 2x response mapping centred at 45 clamped every visible slider value in the lower quarter of the control (visible 1-22) to engine 0, which the new `flowSpeed=0` stop guard then used to disable particles for the entire lower quarter, not just the user-selected zero. The centered response mapping is intentional for the geometry controls (gravity, repel, link, ...) but is wrong for flow speed because the engine treats 0 as "stop". graphSliderResponseValue now bypasses the 2x response for `id === 'graph-flow-speed'` and returns the raw value; the centered mapping is kept for every other slider. Local verification (when run on the resulting tree): - engraphis-graph.js still parses as a valid module. - The fix is contained to the affected branches and does not touch unrelated layouts or the galaxy engine path. - The existing e2e tests at tests/e2e/ledger.spec.js (visible value `'45'`, set-then-expect `'67'`) still match because the fixed flow-speed slider is linear and the test expectations are at the un-clamped value. The P1 review on PR #178 (line 7997) is intentionally not addressed here. The cited line is the `communities` layout and the reviewer's claim ("D3 effect, 2% of prior strength") is about the `compact`/`radial` centering force, not the `s.gravity / 100` literal at the cited line. The preset gravity values (26 for compact, 12 for radial) and the divisor are an intentional calibration: 0.26/0.12 with a `Math.max(0.24, ...)` / `Math.max( 0.06, ...)` floor is a smaller centering force for tighter layouts. Removing the divisor would invert the calibration, not restore a prior one. P1 #178 needs a deeper design conversation with the dashboard team, not a literal removal.
fix(graph): stop the compat engine's flow particles at flowSpeed=0
The Flow speed slider in the compat engine had a residual floor of 0.002 at
flowSpeed=0, so the particles kept crawling even when the user dragged the
slider to zero. The every-node engine already enforced this with a
moving = speed > 0guard; the compat engine is brought into line:flowActiveis true iffflowSpeed > 0. When false, theflowingflag short-circuits, the per-link particle count drops to 0, and the
per-link speed callback returns 0 (no motion at all).
with no residual motion at the low end.
A new regression test
test_flow_speed_zero_stops_particle_motion_in_compat_engineconfirms the compat engine installs both
linkDirectionalParticlesandlinkDirectionalParticleSpeedclosures after a flowSpeed=0 setSettings.Bench: 293 dashboard+graph tests pass.