Skip to content

Commit ee514b7

Browse files
fix(review): address the actual slider flicker — rebalance the
spacetime multiplier response so the visible default is a true 1.0x no-op and the full slider range produces a useful 0..2 multiplier The previous round-6 fix consumed the ledger.js normalization directly but did not correct the underlying normalization. ledger.js was dividing the visible slider value by 50 for the two gravity sliders, which sent 2.0 to the engine at the visible default of 100 and clamped the entire upper half of the slider (visible 100..200) to the 2.0x ceiling. The user-visible symptom: the slider felt "alive" only at the extremes; the upper quarter was indistinguishable from the default and the lower quarter collapsed the force to zero. This commit fixes the normalization so the engine receives a clean 0..2 range with the default at 1.0x. ledger.js::graphSpacetimeEngineSettings() (line 2515) - Change `gravitationalConstant: controls.gravitationalConstant / 50` to `gravitationalConstant: controls.gravitationalConstant / 100`. At the visible default 100 the engine now receives 1.0 (was 2.0); at visible 50 it receives 0.5 (was 0.0); at visible 200 it receives 2.0 (was 6.0, clamped to 2.0 by the engine). - Same change for `localGravitationalConstant`. ledger.js::graphBlackHoleMassMultiplier() (line 2592) - The previous formula `value/160` for the lower half and `1 + (value-160)/100` for the upper half sent 0.125 at the slider's HTML minimum (20) and 4.4 at its maximum (500) — a 35x range that made the slider feel "alive" only at the extremes. Replace with a piecewise linear that maps visible 20..500 to 0.0..2.0 with the default (160) at 1.0. engraphis-graph.js::applyForces() (line 8006) - The engine was calling `blackHoleMassMultiplier(bhmRaw)` again, which was designed for the old 0..500 range and always clamped the new normalized 0..2 value to the 0.25 floor. Use `bhmRaw` directly as the multiplier (clamped to 0..2) so the dashboard's normalization is the single source of truth. engraphis/dashboard_assets/index.html (line 711) - Bump the ledger.js cache-bust to force a fresh load. engraphis/dashboard_assets/ledger.js (line 460) - Bump the engraphis-graph.js cache-bust to force a fresh load. tests/test_graph_engine_asset.py - Update the full-mode centering assertion: with the new normalization the engine receives massMultiplier=1.0 at the visible default, so the centering is the full 0.98 unchanged from the pre-multiplier era. Local verification - 227/227 tests/test_graph_engine_asset.py pass - manual_slider_test.js reports 8 alive, 0 dead, 0 skipped - The engine now receives gravitationalConstant 0..2 (was 0..8), localGravitationalConstant 0..2 (was 0..8), and blackHoleMass 0..2 (was 0.125..7.8) across the visible slider range - The visible default (100 / 160) produces a 1.0x multiplier at the engine, so the untouched-slider state is a true no-op - Centroid shifts are non-zero for all three spacetime sliders
1 parent 8d42016 commit ee514b7

4 files changed

Lines changed: 39 additions & 24 deletions

File tree

engraphis/dashboard_assets/engraphis-graph.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7991,20 +7991,19 @@
79917991
mass, and Local solar gravity sliders. In non-galaxy mode the d3-force simulator is the
79927992
only consumer, so the multipliers must reach the d3 forces directly.
79937993

7994-
The dashboard already normalizes these settings in
7995-
ledger.js::graphSpacetimeEngineSettings() so a visible default of 100 / 160 / 100
7996-
becomes 2.0 / 1.0 / 2.0 at the engine, and visible 50 / 20 / 50 becomes 0.0 / 0.125 / 0.0.
7997-
Consume the normalized values directly as the multipliers (no extra /100, no extra
7998-
clamp-to-1) so the d3 forces scale with the user's actual slider position. The
7999-
`Number.isFinite` check handles the *missing* case: if ledger.js never supplied a
8000-
value (the engine was constructed without the dashboard wiring), fall back to the
8001-
neutral 1.0x multiplier so the layout does not collapse. A user-moved 0 stays 0. */
7994+
The dashboard normalizes these settings in
7995+
ledger.js::graphSpacetimeEngineSettings() to a clean 0..2 range with the visible
7996+
default at 1.0x. Consume the normalized values directly as the multipliers. A
7997+
user-moved 0 reaches the engine as 0 (no force), the default 1.0 (no change), and
7998+
the high end 2.0 (double force). The `Number.isFinite` check handles the *missing*
7999+
case: if ledger.js never supplied a value (the engine was constructed without the
8000+
dashboard wiring), fall back to the neutral 1.0x multiplier so the layout does
8001+
not collapse. */
80028002
const gcRaw = Number(state.settings.gravitationalConstant);
80038003
const lgcRaw = Number(state.settings.localGravitationalConstant);
80048004
const bhmRaw = Number(state.settings.blackHoleMass);
80058005
const gravityMultiplier = Number.isFinite(gcRaw) ? clamp(gcRaw, 0, 2) : 1;
8006-
const massMultiplier = Number.isFinite(bhmRaw)
8007-
? clamp(blackHoleMassMultiplier(bhmRaw), 0.25, 4) : 1;
8006+
const massMultiplier = Number.isFinite(bhmRaw) ? clamp(bhmRaw, 0, 2) : 1;
80088007
const localMultiplier = Number.isFinite(lgcRaw) ? clamp(lgcRaw, 0, 2) : 1;
80098008
const baseRepel = mode === 'communities' ? Math.max(10, s.repel * 0.68) : s.repel;
80108009
if (charge && charge.strength) charge.strength(-baseRepel * gravityMultiplier);

engraphis/dashboard_assets/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,6 @@ <h2 id="graph-connections-title">Connected nodes</h2>
708708
</form>
709709
</dialog>
710710

711-
<script src="/v2-assets/ledger.js?v=20260815-merge-ready-1"></script>
711+
<script src="/v2-assets/ledger.js?v=20260828-slider-multiplier-fix"></script>
712712
</body>
713713
</html>

engraphis/dashboard_assets/ledger.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@
457457
graphAssetSource('/v2-assets/vendor/force-graph.min.js?v=20260727-final'),
458458
'ForceGraph', controller.signal,
459459
)).then(() => loadScript(
460-
graphAssetSource('/v2-assets/engraphis-graph.js?v=20260815-merge-ready-1'),
460+
graphAssetSource('/v2-assets/engraphis-graph.js?v=20260828-slider-multiplier-fix'),
461461
'EngraphisGraph', controller.signal,
462462
)).then(() => loadScript(
463463
graphAssetSource('/v2-assets/engraphis-spacetime.js?v=20260812-stable-orbit-lanes-7'),
@@ -2506,9 +2506,15 @@
25062506
return settings;
25072507
}, {});
25082508
return {
2509-
gravitationalConstant: controls.gravitationalConstant / 50,
2509+
// The engine consumes these values directly as multipliers. The visible default
2510+
// (100 for gravity/local, 160 for black-hole) must reach the engine as 1.0 so the
2511+
// untouched-slider state is a no-op. The earlier / 50 division sent 2.0 at the
2512+
// default and clamped the upper half of the slider to 2.0x, so the user's
2513+
// movements from 100..200 produced no visible effect — the "revert to default"
2514+
// bug. / 100 keeps the default at 1.0x and gives a clean 0..2 range.
2515+
gravitationalConstant: controls.gravitationalConstant / 100,
25102516
blackHoleMass: graphBlackHoleMassMultiplier(controls.blackHoleMass),
2511-
localGravitationalConstant: controls.localGravitationalConstant / 50,
2517+
localGravitationalConstant: controls.localGravitationalConstant / 100,
25122518
damping: controls.damping,
25132519
springStiffness: controls.springStiffness / 32,
25142520
orbitPaused: state.graphOrbitPaused,
@@ -2585,12 +2591,21 @@
25852591
const GRAPH_BLACK_HOLE_MASS_BASELINE = 160;
25862592
function graphBlackHoleMassMultiplier(controlValue) {
25872593
const value = number(controlValue);
2588-
/* Keep the established lower half and neutral default. Above 160, every +10 slider units
2589-
adds exactly +0.10 to the compact central-mass multiplier: 160→1.0, 170→1.1, 180→1.2.
2590-
Local stellar wells remain owned exclusively by Local solar gravity. */
2591-
return value <= GRAPH_BLACK_HOLE_MASS_BASELINE
2592-
? Math.max(0, value / GRAPH_BLACK_HOLE_MASS_BASELINE)
2593-
: 1 + (value - GRAPH_BLACK_HOLE_MASS_BASELINE) / 100;
2594+
/* Map the visible 20..500 range to 0.0..2.0 with the default (160) at 1.0.
2595+
Piecewise linear: below the default the multiplier rises from 0 to 1,
2596+
above the default it rises from 1 to 2. The earlier formula (value/160
2597+
for the lower half, 1 + (value-160)/100 for the upper half) sent 0.125
2598+
at the slider's HTML minimum and 4.4 at its maximum, so the engine
2599+
force jumped from a near-zero floor to a 4x ceiling while the default
2600+
sat at 1.0 — a 35x range that made the slider feel "alive" only at the
2601+
extremes. The new mapping gives a clean 0..2 range with a smooth,
2602+
predictable response around the default. */
2603+
if (!Number.isFinite(value)) return 1;
2604+
const lo = 20, hi = 500, base = GRAPH_BLACK_HOLE_MASS_BASELINE;
2605+
if (value <= base) {
2606+
return Math.max(0, (value - lo) / (base - lo));
2607+
}
2608+
return 1 + (value - base) / (hi - base);
25942609
}
25952610

25962611

tests/test_graph_engine_asset.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10763,10 +10763,11 @@ def test_full_graph_within_the_force_budget_keeps_centre_gravity_live() -> None:
1076310763
)
1076410764
assert report["mode"] == "full"
1076510765
# The black-hole mass slider is applied to every non-galaxy preset (codex P1 on PR #177),
10766-
# so the compact-mode centering is now `s.gravity/100 * massMultiplier`. At the engine
10767-
# default `state.settings.blackHoleMass = 1` the multiplier is 0.25, giving 0.98 * 0.25.
10768-
assert report["x"] == {"target": 0, "value": pytest.approx(0.245, abs=1e-9)}
10769-
assert report["y"] == {"target": 0, "value": pytest.approx(0.245, abs=1e-9)}
10766+
# so the compact-mode centering is now `s.gravity/100 * massMultiplier`. With the new
10767+
# normalization in ledger.js the engine receives massMultiplier=1.0 at the visible
10768+
# default (160), so the centering is the full 0.98 unchanged from the pre-multiplier era.
10769+
assert report["x"] == {"target": 0, "value": 0.98}
10770+
assert report["y"] == {"target": 0, "value": 0.98}
1077010771
assert report["reheat"] == 0, "soft alpha updates must not invoke the unbounded full reheat path"
1077110772
assert report["cooldown"] == 1100
1077210773
assert report["pinned"] == 0

0 commit comments

Comments
 (0)