Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c837de5
feat(viz): scaffold Vite + Three.js web app
Enreign Mar 15, 2026
13d920c
chore: add node_modules to .gitignore and untrack viz/node_modules
Enreign Mar 15, 2026
6da1869
chore(viz): create viz/public/ directory for data.json output
Enreign Mar 15, 2026
1619338
feat(viz): rewrite viz.py to output data.json for web app
Enreign Mar 15, 2026
4ff5acf
fix(viz): dedup struct edges, remove dead ownership multiplier in ris…
Enreign Mar 15, 2026
f815b39
feat(viz): treemap layout engine with d3-hierarchy
Enreign Mar 16, 2026
9851f15
fix(viz): skip root node in regions, fix root-level file colors, remo…
Enreign Mar 16, 2026
46ccf87
feat(viz): Three.js renderer with region planes and bloom
Enreign Mar 16, 2026
6e43f53
fix(viz): sprite Y overflow, portrait viewport clipping, remove dead …
Enreign Mar 16, 2026
a947f7d
feat(viz): instanced file nodes with architecture mode coloring
Enreign Mar 16, 2026
412c7ae
fix(viz): restore blast node scale, move blastColors outside loop
Enreign Mar 16, 2026
2e1ee2f
feat(viz): structural edges with hierarchical Bezier bundling
Enreign Mar 16, 2026
626e8bb
feat(viz): zoom/pan, GPU picking, blast radius selection
Enreign Mar 16, 2026
6700efc
fix(viz): sync camInitial on resize, remove dead imports
Enreign Mar 16, 2026
11f6127
feat(viz): modes, UI panels, search, selection detail
Enreign Mar 16, 2026
782fcd0
fix(viz): escape HTML in UI to prevent XSS from repo data
Enreign Mar 16, 2026
4ce8a4b
feat(viz): complete Phase 1 — WebGL treemap visualization
Enreign Mar 16, 2026
0c1080b
fix(viz): preserve blast radius highlight during mode switch
Enreign Mar 16, 2026
cd36a39
feat(viz): export commits temporal data for time scrubber
Enreign Mar 16, 2026
afcb2b1
fix(viz): test_commits imports build_commits from viz.py directly
Enreign Mar 16, 2026
9c418b4
feat(viz): conditional animation loop and updateRegionColors
Enreign Mar 16, 2026
9fe9b89
feat(viz): extend color palette to 16, add ownerColor for ownership mode
Enreign Mar 16, 2026
7321399
feat(viz): animated blast radius ripple/pulse replaces static highlight
Enreign Mar 16, 2026
e7659f4
chore(viz): remove dead highlightIds variable in selectNode
Enreign Mar 16, 2026
8139e2a
feat(viz): export computeArcPoints helper from edges.js
Enreign Mar 16, 2026
f8e8669
feat(viz): co-change particle flow on node selection
Enreign Mar 16, 2026
cbb888b
feat(viz): ownership mode with region coloring and legend
Enreign Mar 16, 2026
42422aa
fix(viz): show legend-ownership as flex so gap applies correctly
Enreign Mar 16, 2026
2797699
feat(viz): time scrubber with activity overlay
Enreign Mar 16, 2026
9bf5be4
feat(viz): guided tour with 5-step onboarding and ? replay button
Enreign Mar 16, 2026
64d2882
feat(viz): complete Phase 2 — particles, ripple, ownership, scrubber,…
Enreign Mar 16, 2026
a04390a
fix(viz): cancel stale tour timers on skip/restart
Enreign Mar 16, 2026
5b5d1f1
fix(viz): tick snapshot iteration, arc confidence index, id invariant…
Enreign Mar 16, 2026
b9b995a
feat(filters): add _filterMask + setFilterMask to nodes.js
Enreign Mar 16, 2026
e8361e9
feat(filters): pre-compute 3-hop blast counts in interaction.js
Enreign Mar 16, 2026
7da25e8
feat(filters): create filters.js — unified filter state module
Enreign Mar 16, 2026
7dbf707
feat(filters): wire filter UI in ui.js — chips, risk legend, connecti…
Enreign Mar 16, 2026
6928bca
fix(filters): legend-risk flex display, hide empty chip section
Enreign Mar 16, 2026
4a2cf18
feat(filters): wire initFilters and slider maxes in main.js
Enreign Mar 16, 2026
c68a805
fix(filters): store blastCounts once in main.js
Enreign Mar 16, 2026
ad5278a
fix(filters): safe reachable slider max, normalize setOwnerFilter emp…
Enreign Mar 16, 2026
66568a8
fix: search Enter key, scrubber zero-range, and co-change timestamps
Enreign Mar 16, 2026
a6d6e5c
chore(viz): regenerate data.json with real co-change timestamps
Enreign Mar 16, 2026
c6c4a3a
chore(viz): regenerate data.json from openclaw (real multi-month hist…
Enreign Mar 16, 2026
b8aa5fe
feat(index): add --max-commits flag, raise default to 50k
Enreign Mar 16, 2026
5ccf746
chore(viz): regenerate data.json from full openclaw history (19k comm…
Enreign Mar 17, 2026
a997b05
feat(historian): rename tracking for complete co-change history
Enreign Mar 17, 2026
29d9784
fix(viz): use all co-change edges for scrubber, not just threshold-fi…
Enreign Mar 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@ dist/
.env
.env.*

# Superpowers working docs (specs, plans, research)
docs/superpowers/

# Node
node_modules/
viz/dist/

# macOS
.DS_Store

# IDE
.idea/
.vscode/
*.iml
*.iml
viz/node_modules/
viz/public/data.json
45 changes: 45 additions & 0 deletions scripts/test_commits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python3
"""Test build_commits temporal data export."""
import sqlite3
import tempfile
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from scripts.viz import build_commits


# Tests
def test_build_commits_basic():
files_sorted = [{"id": 10, "path": "a.ts"}, {"id": 20, "path": "b.ts"}]
file_idx = {10: 0, 20: 1}
edges = [
{"from_id": 10, "to_id": 20, "last_evidence": "2023-01-15 10:00:00"},
{"from_id": 10, "to_id": 20, "last_evidence": "2023-03-05 10:00:00"},
]
result = build_commits(files_sorted, file_idx, edges)
assert result is not None, "Should return data"
assert result["first"] < result["last"], "first < last"
assert len(result["buckets"]) == 2, f"Expected 2 months, got {len(result['buckets'])}"
jan_bucket = result["buckets"][0]
assert 0 in jan_bucket["files"], "file idx 0 in Jan"
assert 1 in jan_bucket["files"], "file idx 1 in Jan"
print("test_build_commits_basic PASSED")

def test_build_commits_empty():
result = build_commits([], {}, [])
assert result is None, "Empty input returns None"
print("test_build_commits_empty PASSED")

def test_build_commits_no_evidence():
files_sorted = [{"id": 1, "path": "a.ts"}]
file_idx = {1: 0}
edges = [{"from_id": 1, "to_id": 2, "last_evidence": None}]
result = build_commits(files_sorted, file_idx, edges)
assert result is None, "None timestamps returns None"
print("test_build_commits_no_evidence PASSED")

test_build_commits_basic()
test_build_commits_empty()
test_build_commits_no_evidence()
print("All tests passed.")
Loading
Loading