feat: electric mode — spreading activation visualization#124
Open
nvandessel wants to merge 9 commits intomainfrom
Open
feat: electric mode — spreading activation visualization#124nvandessel wants to merge 9 commits intomainfrom
nvandessel wants to merge 9 commits intomainfrom
Conversation
Greptile SummaryThis PR adds electric mode visualization to the graph view, allowing users to click nodes and watch spreading activation propagate in real-time with animated particles and glow effects. The implementation is well-architected: the Go engine was cleanly refactored to expose step-by-step activation snapshots via Key changes:
Minor issues already noted in previous review threads:
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| internal/spreading/engine.go | Adds ActivateWithSteps() method and refactors core propagation logic into reusable propagateStep() and postProcess() helpers — clean extraction with proper synchronous updates |
| internal/spreading/engine_test.go | Adds 4 comprehensive tests for ActivateWithSteps() covering linear chains, snapshot independence, sigmoid application, and empty seeds edge case |
| internal/visualization/server.go | New HTTP server with cached HTML rendering and /api/activate endpoint — graceful shutdown implemented correctly, minor error handling issue noted in previous review |
| internal/visualization/server_test.go | Comprehensive test suite covering server startup, HTML serving, activation endpoint with valid/invalid seeds, and graceful shutdown |
| internal/visualization/dot.go | Adds RenderHTMLForServer() variant that embeds API base URL for electric mode — clean separation between static and server modes |
| internal/visualization/dot_test.go | Adds tests verifying electric mode markers appear in server HTML but not in static HTML exports |
| internal/visualization/templates/graph.html.tmpl | Adds ~250 lines of electric mode CSS and JavaScript including particle animation, glow effects, playback controls — no error handling on fetch call noted in previous review |
| cmd/floop/cmd_graph.go | Adds --serve flag with server lifecycle management and graceful shutdown — minor issue with flag validation for non-HTML formats noted in previous review |
Sequence Diagram
sequenceDiagram
participant Browser
participant Server as Go HTTP Server
participant Engine as Spreading Engine
participant Store as Graph Store
Browser->>Server: GET /
Server->>Store: GetNodes(), GetEdges()
Store-->>Server: Graph data
Server->>Server: RenderHTMLForServer(apiBaseURL)
Server-->>Browser: HTML + embedded graph JSON
Note over Browser: User clicks node "b42"
Browser->>Server: GET /api/activate?seed=b42
Server->>Store: GetNode(b42)
Store-->>Server: Node exists
Server->>Engine: ActivateWithSteps([{b42, 1.0}])
Engine->>Engine: Step 0: Initialize seed
loop For each propagation step
Engine->>Store: GetEdges(active nodes)
Store-->>Engine: Edge list
Engine->>Engine: propagateStep()
Engine->>Engine: Capture snapshot
end
Engine->>Engine: postProcess() - inhibition + sigmoid
Engine-->>Server: []StepSnapshot (JSON)
Server-->>Browser: Step-by-step activation data
Note over Browser: Animate particles, glow, playback controls
Last reviewed commit: 7e18797
Owner
Author
New commit: reduce spark size and improve edge visibilitySmaller sparks:
Better edge visibility:
All 18 visual tests pass. Ready for visual review — run |
54efba1 to
7e18797
Compare
… view Click a node in the HTML graph to see real spreading activation propagate through the behavior graph. The Go engine runs server-side on each click; JavaScript handles only animation and playback controls. - Add ActivateWithSteps() to spreading engine (per-step snapshots) - Add HTTP server (visualization/server.go) with /api/activate endpoint - cmd_graph.go: server mode by default, --output for static export - Electric mode JS: particles, glow, playback toolbar, test helpers - APIBaseURL in template data to toggle electric vs focus mode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- H1: Add --serve flag (opt-in server mode), keep temp-file as default - H2: Fix signal goroutine leak with defer signal.Stop - H3: Extract propagateStep/postProcess to eliminate duplication - H4: Use generic error messages in HTTP responses - M1: Restrict handlers to GET method only - M2: Pre-render and cache HTML at server startup - M3: Remove seed ID echo from 404 response - M5: Restore security comments in dot.go - M6: Remove duplicate onNodeClick/onBackgroundClick handlers - L3: Add null guard in linkDirectionalParticleWidth - L5: Fix shadowed ctx in TestServer_ActivateEndpoint - L8: Create engine once in NewServer, reuse per request - M4: Drain errCh in server tests via t.Cleanup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The spark rendering code (comet trails, glowing tips, ember particles) was never executing because force-graph v1.51.1's linkCanvasObject callback is never invoked despite the API existing. Migrated all spark rendering to onRenderFramePost which fires at 60fps. Also fixed nodeFirstStep threshold (0.01 → 0) so neighbor nodes with small activation values get tracked for spark timing, and added Playwright visual test infrastructure for electric mode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Eliminate all ctx.shadowBlur calls (3 sites) — replaced with gradient-only equivalents. Shadow compositing is the heaviest Canvas 2D operation. - Memoize getElectricProgress() per frame — eliminates ~970 redundant computations per frame via cached wrapper. - Cache getEdgeWaveEnergy() results per frame — reduces edge energy computations from 3E to E per frame. - Switch autoPauseRedraw default to true — zero CPU cost when idle. Electric mode toggles it on/off as needed. - Remove cooldownTime(Infinity) — let physics naturally settle. - Add FPS diagnostic counter with on-screen overlay (press F to toggle) and window.__getElectricFPS() test helper. Estimated combined impact: +18-33 FPS during electric mode animation. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ps (#133) - Replace edge wire illumination and comet trail LinearGradients with solid rgba() strokes — eliminates ~9,600 gradient object allocations per second during electric mode animation. - Merge electricUILoop rAF into onRenderFramePost — single animation loop instead of dual, reducing rAF overhead. - Capture Date.now() once per frame (_frameNow) for ripple phase, avoiding repeated syscalls inside the per-node rendering loop. - Reduce ember particles from 4 to 2 per edge — halves particle draw calls with minimal visual difference. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sparks were larger than nodes (up to 60px halo vs 5-16px nodes) — halved base radius and tightened halo/core multipliers. Edges were dropping to 10% opacity away from the wave front — raised fallback to 18%, added 0.06 energy floor, and increased residual glow factor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
07cf88d to
78c0393
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
floop graph --format html --serve): clicking a node runs the real Go spreading activation engine server-side and animates the results in the browser with flowing particles, node glow, and step-by-step playback controlsEngine.ActivateWithSteps()method captures per-step activation snapshots for animation timeline (initial seed → propagation steps → post-inhibition/sigmoid final)visualization.Server) serves the graph HTML and handles/api/activate?seed=<id>requests — zero JS algorithm duplication, no risk of divergence from the Go engineArchitecture
Changes
internal/spreading/engine.goActivateWithSteps(), extractedpropagateStep()/postProcess()shared methodsinternal/spreading/engine_test.gointernal/visualization/server.go/api/activateendpointinternal/visualization/server_test.gointernal/visualization/dot.goRenderHTMLForServer(),APIBaseURLin template datainternal/visualization/dot_test.gointernal/visualization/templates/graph.html.tmplcmd/floop/cmd_graph.go--serveflag, server lifecycle with graceful shutdownUsage
Test plan
go test ./internal/spreading/...— ActivateWithSteps tests passgo test ./internal/visualization/...— server + HTML marker tests passgo test ./...— all 29 packages pass, no regressionsfloop graph --format html --serve→ click node → particles flow, toolbar worksfloop graph --format html→ static file export still works (no server)🤖 Generated with Claude Code