world: fade landmark orbs after 60s idle (V5)
ci / gates (push) Successful in 6s
ci / rust (push) Failing after 10s
ci / frontend (push) Successful in 26s
ci / e2e (push) Has been skipped
ci / publish (push) Has been skipped

Turns out V5 wasn't a no-op — the SSE loop stops emitting a repo:<id>
node once its topic transitions to 'published' (the query filters on
processing/reviewing/publishing), but the client engine's idle-fade
only applied to service/event tiers. Repo and loop landmarks lingered
forever on the client until page reload.

Extends the fade rule to cover repo + loop tiers, with a longer window
(60s vs 22s for service/event) so a brief SSE hiccup doesn't wipe the
whole workspace's landmarks. When a topic reaches 'published', its
`lastSeen` stops advancing on the client; ~60s later the alpha ramps
down and the node is deleted from the map.

Same rule applies to loops that get `enabled=false` after being
turned off — their landmark quietly fades out instead of persisting
until reload.
This commit is contained in:
Omar Sobh
2026-07-09 15:52:01 -07:00
parent 959e766e36
commit 4831033910
+15 -3
View File
@@ -450,11 +450,23 @@ export class WorldEngine {
n.heat = Math.max(0, n.heat - dt * 0.5); n.heat = Math.max(0, n.heat - dt * 0.5);
} }
// world nodes fade out when idle (Gource file-idle), then are removed // world nodes fade out when idle (Gource file-idle), then are removed.
// - service/event: quick fade (22s) — tool calls and one-shot events
// shouldn't linger visually.
// - repo/loop landmarks: slow fade (60s) — a topic transitioning to
// 'published' stops emitting from the SSE loop; the landmark should
// quietly disappear rather than hang around forever. The longer
// window keeps a brief SSE hiccup from evicting the workspace.
for (const n of arr) { for (const n of arr) {
if (n.tier === "service" || n.tier === "event") { const shortLived = n.tier === "service" || n.tier === "event";
const landmark = n.tier === "repo" || n.tier === "loop";
if (shortLived || landmark) {
const idleAge = this.now - n.lastSeen; const idleAge = this.now - n.lastSeen;
n.alpha = idleAge > 22 ? Math.max(0, n.alpha - dt * 0.5) : Math.min(1, n.alpha + dt * 2); const window = landmark ? 60 : 22;
n.alpha =
idleAge > window
? Math.max(0, n.alpha - dt * 0.5)
: Math.min(1, n.alpha + dt * 2);
if (n.alpha <= 0.02) this.nodes.delete(n.id); if (n.alpha <= 0.02) this.nodes.delete(n.id);
} }
} }