Skip to content

Commit d5b819b

Browse files
fix(dashboard): harden Galaxy operating bounds (#209)
Merge reviewed Galaxy operating-bound, black-hole exclusion, asset cache-busting, and migration hardening changes.
1 parent 8a5181f commit d5b819b

11 files changed

Lines changed: 351 additions & 69 deletions

File tree

‎engraphis/classic_assets/dashboard.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎engraphis/classic_assets/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,6 @@
349349
graph view. dashboard.js fetches both on demand from graphRender(); see loadForceGraph()
350350
and loadGraphEngine(). scripts/externalize_dashboard_assets.py enforces both halves:
351351
they stay out of this file, and the lazy references still have to resolve. -->
352-
<script src="/classic-assets/dashboard.js?v=20260905-processing-review-1"></script>
352+
<script src="/classic-assets/dashboard.js?v=20260906-galaxy-boundaries-1"></script>
353353
</body>
354354
</html>

‎engraphis/dashboard_assets/engraphis-graph.js‎

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,6 @@
319319
const GALAXY_ORBITAL_SPEED_RESPONSE_GAIN = 0.5;
320320
const GALAXY_ORBITAL_SPEED_MAXIMUM = 4.6;
321321
const GALAXY_ORBITAL_RADIUS_MAXIMUM = 1.06;
322-
const GALAXY_BASE_ORBITAL_SPEED_BOOST = 1.625;
323322
function galaxyOrbitalSpeedMultiplier(setting) {
324323
const raw = Number(setting);
325324
const value = Number.isFinite(raw)
@@ -746,10 +745,9 @@
746745
const circularSpeed = Math.sqrt(Math.max(0, acceleration * localRadius));
747746
const multiplier = Math.max(0, Number(orbitalSpeed) || 0);
748747
return kinematicCap
749-
? Math.min(circularSpeed * GALAXY_BASE_ORBITAL_SPEED_BOOST * multiplier,
748+
? Math.min(circularSpeed * multiplier,
750749
GALAXY_LOCAL_RELATIVE_SPEED_LIMIT * multiplier)
751-
: Math.min(GALAXY_LOCAL_RELATIVE_SPEED_LIMIT, circularSpeed)
752-
* GALAXY_BASE_ORBITAL_SPEED_BOOST * multiplier;
750+
: Math.min(GALAXY_LOCAL_RELATIVE_SPEED_LIMIT, circularSpeed) * multiplier;
753751
}
754752

755753
/* The classic renderer's *dense* signal (`GPERF.dense`, `links>1500` in dashboard.js). Past
@@ -1230,7 +1228,7 @@
12301228
|| ((seededHash(opts.layoutSeed, 'system:' + String(parent.id)) & 1) ? 1 : -1);
12311229
const targetTangent = galaxyRelativeSpeedBudget(parent, absoluteSpeedLimit,
12321230
Math.min(GALAXY_LOCAL_RELATIVE_SPEED_LIMIT,
1233-
Math.sqrt(Math.max(0, acceleration * radius)) * GALAXY_BASE_ORBITAL_SPEED_BOOST * orbitalSpeed),
1231+
Math.sqrt(Math.max(0, acceleration * radius)) * orbitalSpeed),
12341232
tangentX * sign, tangentY * sign);
12351233
const parentId = String(parent.id);
12361234
const previousParent = typeof node.__galaxyOrbitAnchorId === 'string'
@@ -3428,12 +3426,13 @@
34283426
const globalSpeed = omega * orbit.radius;
34293427
const globalVx = -Math.sin(orbit.angle) * globalSpeed * direction;
34303428
const globalVy = Math.cos(orbit.angle) * globalSpeed * direction;
3431-
moveNode(star, targetX, targetY, globalVx, globalVy);
3429+
// Initialize local phases against the old parent frame before moving the carrier.
34323430
const localMotion = advanceGalaxyKinematicLocalMembers(members, star, {
34333431
x: targetX, y: targetY, vx: globalVx, vy: globalVy,
34343432
}, item.core ? Object.assign({}, opts, {
34353433
localOrbitCache: '__galaxyKinematicCoreLocalOrbit',
34363434
}) : opts);
3435+
moveNode(star, targetX, targetY, globalVx, globalVy);
34373436
satellites += localMotion.satellites;
34383437
speedCapped = speedCapped || localMotion.speedCapped;
34393438
const carrierContact = nodeRadius(anchor) + nodeRadius(star)
@@ -4551,8 +4550,20 @@
45514550
const maximumExtents = new Map(systems.map(system => [
45524551
system, galaxySystemMaximumEnvelopeRadius(system, opts),
45534552
]));
4554-
systems.sort((left, right) => maximumExtents.get(right) - maximumExtents.get(left)
4553+
/* Rigid translations and rotations introduce a few ulps in otherwise equal envelopes.
4554+
Use stable precision only for ordering, so numerical noise cannot move a system to a
4555+
different ring. Keep exact extents for every safety reservation below. */
4556+
const extentOrder = new Map(systems.map(system => [
4557+
system, Number(maximumExtents.get(system).toPrecision(12)),
4558+
]));
4559+
systems.sort((left, right) => extentOrder.get(right) - extentOrder.get(left)
45554560
|| String(left.id).localeCompare(String(right.id)));
4561+
const remainingExtents = new Array(systems.length);
4562+
let maximumRemainingExtent = 0;
4563+
for (let index = systems.length - 1; index >= 0; index--) {
4564+
maximumRemainingExtent = Math.max(maximumRemainingExtent, maximumExtents.get(systems[index]));
4565+
remainingExtents[index] = maximumRemainingExtent;
4566+
}
45564567
const blackHoleBodyRadius = finitePositive(anchor.radius,
45574568
evidenceNodeRadius(anchor, 3), 160);
45584569
/* Runtime horizon projection paints the explicit global anchor at twice its body radius.
@@ -4567,7 +4578,7 @@
45674578
/* Reserve the maximum nested local envelope, then keep a small independent lane margin.
45684579
This remains collision-free when the orbital-speed control reaches its maximum. */
45694580
const laneSlack = GALAXY_CARRIER_LANE_SLACK;
4570-
const laneExtent = maximumExtents.get(systems[cursor]) * laneSlack;
4581+
const laneExtent = remainingExtents[cursor] * laneSlack;
45714582
let laneRadius = Math.max(coreRadius + laneExtent + gap
45724583
+ GALAXY_BLACK_HOLE_EXCLUSION_PADDING,
45734584
previousLaneRadius + previousLaneExtent + laneExtent + gap);
@@ -4588,8 +4599,7 @@
45884599
'carrier-ring:' + String(laneIndex)) / 0x100000000 * Math.PI * 2;
45894600
for (let slot = 0; slot < count; slot++) {
45904601
const system = systems[cursor + slot];
4591-
/* Re-evaluate with the largest member of the next lane only; sorting makes every
4592-
remaining extent no larger than this ring's conservative laneExtent. */
4602+
// The exact remaining maximum also covers larger members within an ordering tie.
45934603
const angle = phaseOffset + slot * Math.PI * 2 / count;
45944604
const unitX = Math.cos(angle), unitY = Math.sin(angle);
45954605
const shiftX = anchor.x + unitX * laneRadius - system.x;
@@ -6475,19 +6485,9 @@
64756485
phase.angle += phase.direction * angularSpeed * timestep;
64766486
const unitX = Math.cos(phase.angle), unitY = Math.sin(phase.angle);
64776487
const tangentX = -unitY * phase.direction, tangentY = unitX * phase.direction;
6478-
let targetX = parent.x + unitX * targetRadius;
6479-
let targetY = parent.y + unitY * targetRadius;
6480-
if (globalAnchor && parent !== globalAnchor) {
6481-
const minBhDist = (finitePositive(globalAnchor.radius, evidenceNodeRadius(globalAnchor, 3), 160) * GALAXY_BLACK_HOLE_PAINT_SCALE)
6482-
+ nodeRadius + GALAXY_BLACK_HOLE_EXCLUSION_PADDING;
6483-
const bhDx = targetX - globalAnchor.x;
6484-
const bhDy = targetY - globalAnchor.y;
6485-
const bhDist = Math.hypot(bhDx, bhDy);
6486-
if (bhDist < minBhDist && bhDist > 1e-9) {
6487-
targetX = globalAnchor.x + (bhDx / bhDist) * minBhDist;
6488-
targetY = globalAnchor.y + (bhDy / bhDist) * minBhDist;
6489-
}
6490-
}
6488+
// The final black-hole exclusion pass translates the complete system together.
6489+
const targetX = parent.x + unitX * targetRadius;
6490+
const targetY = parent.y + unitY * targetRadius;
64916491
const targetVx = (Number.isFinite(parent.vx) ? parent.vx : 0)
64926492
+ tangentX * phaseSpeed;
64936493
const targetVy = (Number.isFinite(parent.vy) ? parent.vy : 0)

‎engraphis/dashboard_assets/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,6 @@ <h2 id="graph-connections-title">Connected nodes</h2>
823823
<script src="/v2-assets/memory-history.js?v=20260906-workflow-1"></script>
824824
<script src="/v2-assets/ask-requests.js?v=20260906-ask-home-1"></script>
825825
<script src="/v2-assets/graph-lifecycle.js?v=20260906-lifecycle-1"></script>
826-
<script src="/v2-assets/ledger.js?v=20260906-lifecycle-1"></script>
826+
<script src="/v2-assets/ledger.js?v=20260906-galaxy-boundaries-1"></script>
827827
</body>
828828
</html>

‎engraphis/dashboard_assets/ledger.js‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@
500500
graphAssetSource('/v2-assets/vendor/force-graph.min.js?v=20260727-final'),
501501
'ForceGraph', controller.signal,
502502
)).then(() => loadScript(
503-
graphAssetSource('/v2-assets/engraphis-graph.js?v=20260903-rotation-balance-1'),
503+
graphAssetSource('/v2-assets/engraphis-graph.js?v=20260906-galaxy-boundaries-1'),
504504
'EngraphisGraph', controller.signal,
505505
)).then(() => loadScript(
506506
graphAssetSource('/v2-assets/engraphis-spacetime.js?v=20260812-stable-orbit-lanes-7'),
@@ -3129,9 +3129,11 @@
31293129
const savedTuning = graphPreference('tuning', {});
31303130
const savedPhysicsVersion = Number(graphPreference('physicsVersion', 0));
31313131
const sourcePhysicsVersion = Number.isFinite(savedPhysicsVersion) ? savedPhysicsVersion : 0;
3132-
const legacyPhysics = hasSavedPreferences && sourcePhysicsVersion < GRAPH_PHYSICS_VERSION;
3133-
const needsPhysicsV3Migration = hasSavedPreferences && sourcePhysicsVersion < 3;
3134-
const needsPhysicsV4Migration = hasSavedPreferences && sourcePhysicsVersion < 4;
3132+
const needsPhysicsMigration = version => hasSavedPreferences
3133+
&& sourcePhysicsVersion < version;
3134+
const legacyPhysics = needsPhysicsMigration(GRAPH_PHYSICS_VERSION);
3135+
const needsPhysicsV3Migration = needsPhysicsMigration(3);
3136+
const needsPhysicsV4Migration = needsPhysicsMigration(4);
31353137
const effectiveTuning = savedTuning && typeof savedTuning === 'object'
31363138
? { ...savedTuning } : {};
31373139
const savedSpacetimeTuning = graphPreference('spacetimeTuning', {});
@@ -3159,7 +3161,7 @@
31593161
}
31603162
/* Physics v5 makes 120 the Galaxy gravity default. Migrate only the exact retired default;
31613163
a saved 96 in an already-versioned v5 snapshot remains an intentional user choice. */
3162-
if (legacyPhysics && preset === 'galaxy' && Number(effectiveTuning.gravity) === 96) {
3164+
if (needsPhysicsMigration(5) && preset === 'galaxy' && Number(effectiveTuning.gravity) === 96) {
31633165
effectiveTuning.gravity = 120;
31643166
}
31653167
syncGraphTuning({

‎engraphis/static/dashboard.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎engraphis/static/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,6 @@
349349
graph view. dashboard.js fetches both on demand from graphRender(); see loadForceGraph()
350350
and loadGraphEngine(). scripts/externalize_dashboard_assets.py enforces both halves:
351351
they stay out of this file, and the lazy references still have to resolve. -->
352-
<script src="/static/dashboard.js?v=20260905-processing-review-1"></script>
352+
<script src="/static/dashboard.js?v=20260906-galaxy-boundaries-1"></script>
353353
</body>
354354
</html>

0 commit comments

Comments
 (0)