@hybridlabor-api/bdb-synapse 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,7 +26,7 @@ func TestFreshScanPicksUpCodexTitleIndexChange(t *testing.T) {
26
26
  }
27
27
  writeIndex("Title One")
28
28
 
29
- s := New(Config{ClaudeDir: filepath.Join(t.TempDir(), "claude"), CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi")})
29
+ s := New(Config{ClaudeDir: filepath.Join(t.TempDir(), "claude"), CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
30
30
  initial := requestSessions(t, s, "/api/sessions")
31
31
  if len(initial) != 1 || initial[0].Title != "Title One" {
32
32
  t.Fatalf("initial sessions = %#v", initial)
@@ -26,6 +26,7 @@ import (
26
26
  "github.com/hybridlabor-api/bdb-synapse/internal/adapter/claudecode"
27
27
  "github.com/hybridlabor-api/bdb-synapse/internal/adapter/codex"
28
28
  "github.com/hybridlabor-api/bdb-synapse/internal/adapter/agy"
29
+ "github.com/hybridlabor-api/bdb-synapse/internal/adapter/opencode"
29
30
  "github.com/hybridlabor-api/bdb-synapse/internal/adapter/pi"
30
31
  "github.com/hybridlabor-api/bdb-synapse/internal/citymap"
31
32
  "github.com/hybridlabor-api/bdb-synapse/internal/judge"
@@ -41,6 +42,7 @@ type Config struct {
41
42
  CodexDir string
42
43
  PiDir string
43
44
  AgyDir string
45
+ OpencodeDir string
44
46
  OpenSession string
45
47
  Dev bool
46
48
  RepoRoot string
@@ -122,7 +124,7 @@ const (
122
124
  func New(cfg Config) *Server {
123
125
  s := &Server{
124
126
  cfg: cfg,
125
- adapters: []adapter.Source{claudecode.Adapter{Dir: cfg.ClaudeDir}, codex.Adapter{Dir: cfg.CodexDir}, pi.Adapter{Dir: cfg.PiDir}, agy.Adapter{Dir: cfg.AgyDir}},
127
+ adapters: []adapter.Source{claudecode.Adapter{Dir: cfg.ClaudeDir}, codex.Adapter{Dir: cfg.CodexDir}, pi.Adapter{Dir: cfg.PiDir}, agy.Adapter{Dir: cfg.AgyDir}, opencode.Adapter{Dir: cfg.OpencodeDir}},
126
128
  agentGraphs: map[string]agentGraphCacheEntry{},
127
129
  agentGraphLoads: map[string]*inflightAgentGraph{},
128
130
  summaries: map[string]summaryCacheEntry{},
@@ -540,7 +542,14 @@ func (s *Server) scanSessions() ([]model.SessionMeta, error) {
540
542
  }
541
543
  seen := map[string]bool{}
542
544
  var files []sessionFile
545
+ var directSessions []model.SessionMeta
543
546
  for _, source := range s.adapters {
547
+ if source.Harness() == "opencode" {
548
+ if list, err := source.ListSessions(); err == nil {
549
+ directSessions = append(directSessions, list...)
550
+ }
551
+ continue
552
+ }
544
553
  dir := source.SessionDir()
545
554
  if dir == "" {
546
555
  continue
@@ -558,6 +567,11 @@ func (s *Server) scanSessions() ([]model.SessionMeta, error) {
558
567
  if filepath.Ext(path) != ".jsonl" {
559
568
  return nil
560
569
  }
570
+ if source.Harness() == "agy" {
571
+ if filepath.Base(path) != "transcript.jsonl" || strings.Contains(path, "/chunks/") {
572
+ return nil
573
+ }
574
+ }
561
575
  info, err := entry.Info()
562
576
  if err != nil {
563
577
  return nil
@@ -605,8 +619,8 @@ func (s *Server) scanSessions() ([]model.SessionMeta, error) {
605
619
  }
606
620
  }
607
621
 
608
- catalog := make(map[string]model.SessionMeta, len(files))
609
- sessions := make([]model.SessionMeta, 0, len(files))
622
+ catalog := make(map[string]model.SessionMeta, len(files)+len(directSessions))
623
+ sessions := make([]model.SessionMeta, 0, len(files)+len(directSessions))
610
624
  for _, meta := range results {
611
625
  if meta == nil {
612
626
  continue
@@ -616,6 +630,15 @@ func (s *Server) scanSessions() ([]model.SessionMeta, error) {
616
630
  sessions = append(sessions, *meta)
617
631
  }
618
632
  }
633
+ for _, meta := range directSessions {
634
+ catalog[meta.Key] = meta
635
+ if !meta.Auxiliary {
636
+ sessions = append(sessions, meta)
637
+ }
638
+ }
639
+ sort.Slice(sessions, func(i, j int) bool {
640
+ return sessions[i].EndedAt > sessions[j].EndedAt
641
+ })
619
642
  s.mu.Lock()
620
643
  s.sessionCatalog = catalog
621
644
  s.mu.Unlock()
@@ -967,6 +990,9 @@ func (s *Server) findSession(selector string) (model.SessionMeta, error) {
967
990
  func fingerprintFile(path string) (fileFingerprint, error) {
968
991
  info, err := os.Stat(path)
969
992
  if err != nil {
993
+ if dbInfo, dbErr := os.Stat(filepath.Join(filepath.Dir(path), "opencode.db")); dbErr == nil {
994
+ return fileFingerprint{size: dbInfo.Size(), modTime: dbInfo.ModTime()}, nil
995
+ }
970
996
  return fileFingerprint{}, err
971
997
  }
972
998
  return fileFingerprint{size: info.Size(), modTime: info.ModTime()}, nil
@@ -28,7 +28,7 @@ func TestTraceStillLoadsWhenSessionCwdIsMissing(t *testing.T) {
28
28
  `{"type":"user","timestamp":"2026-07-09T00:00:02Z","sessionId":"missingcwd","cwd":`+quoteJSON(missingRoot)+`,"message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"r1","content":"ok","is_error":false}]}}`,
29
29
  )
30
30
 
31
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi")})
31
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
32
32
  traceResp := httptest.NewRecorder()
33
33
  s.handleSessionResource(traceResp, httptest.NewRequest(http.MethodGet, "/api/sessions/missingcwd/trace", nil))
34
34
  if traceResp.Code != http.StatusOK {
@@ -79,7 +79,7 @@ func TestOpenSessionUsesUniqueKeyAndFindSessionAcceptsBasename(t *testing.T) {
79
79
  `{"type":"user","timestamp":"2026-07-09T00:00:00Z","sessionId":"internal-id","cwd":"/tmp","message":{"role":"user","content":"hello"}}`,
80
80
  )
81
81
 
82
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), OpenSession: session})
82
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode"), OpenSession: session})
83
83
  wantKey := adapter.SessionKey("claude-code", session)
84
84
  if got := s.openSessionKey(); got != wantKey {
85
85
  t.Fatalf("openSessionKey = %q, want %q", got, wantKey)
@@ -110,7 +110,7 @@ func TestDuplicateSessionIDsUseDistinctKeysAndCaches(t *testing.T) {
110
110
  })
111
111
  }
112
112
 
113
- s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi")})
113
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
114
114
  sessions, err := s.listSessions()
115
115
  if err != nil {
116
116
  t.Fatal(err)
@@ -158,7 +158,7 @@ func TestTraceCacheReloadsWhenActiveSessionGrows(t *testing.T) {
158
158
  `{"type":"user","timestamp":"2026-07-09T00:00:02Z","sessionId":"growing","cwd":`+quoteJSON(repoRoot)+`,"message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"r1","content":"ok","is_error":false}]}}`,
159
159
  )
160
160
 
161
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi")})
161
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
162
162
  firstTrace, firstCity, err := s.traceAndMap("growing")
163
163
  if err != nil {
164
164
  t.Fatal(err)
@@ -192,7 +192,7 @@ func TestSessionsFreshBypassesListTTL(t *testing.T) {
192
192
  writeServerSession(t, filepath.Join(claudeDir, "first.jsonl"),
193
193
  `{"type":"user","timestamp":"2026-07-09T00:00:00Z","sessionId":"first","cwd":"/tmp","message":{"role":"user","content":"hello"}}`,
194
194
  )
195
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi")})
195
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
196
196
 
197
197
  initial := requestSessions(t, s, "/api/sessions")
198
198
  if len(initial) != 1 {
@@ -217,7 +217,7 @@ func TestConcurrentFreshGenerationReusesCompletedScan(t *testing.T) {
217
217
  writeServerSession(t, filepath.Join(claudeDir, "session.jsonl"),
218
218
  `{"type":"user","timestamp":"2026-07-09T00:00:00Z","sessionId":"session","cwd":"/tmp","message":{"role":"user","content":"hello"}}`,
219
219
  )
220
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi")})
220
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
221
221
 
222
222
  // Two fresh callers that enter before either scan completes observe the
223
223
  // same generation. The second must reuse the first completed scan.
@@ -389,7 +389,7 @@ func TestServerLoadsCodexSessions(t *testing.T) {
389
389
  },
390
390
  )
391
391
 
392
- s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi")})
392
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
393
393
  sessionsResp := httptest.NewRecorder()
394
394
  s.handleSessions(sessionsResp, httptest.NewRequest(http.MethodGet, "/api/sessions", nil))
395
395
  if sessionsResp.Code != http.StatusOK {
@@ -478,7 +478,7 @@ func TestCodexAgentAPIsDoNotDeriveChildAcrossDuplicateRootIDs(t *testing.T) {
478
478
  },
479
479
  })
480
480
 
481
- s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi")})
481
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
482
482
  sessions := requestSessions(t, s, "/api/sessions")
483
483
  if len(sessions) != 2 {
484
484
  t.Fatalf("visible sessions = %#v, want duplicate-ID roots only", sessions)
@@ -537,7 +537,7 @@ func TestServerRetainsClaudeSubagentInCatalog(t *testing.T) {
537
537
  `{"type":"user","timestamp":"2026-07-09T00:00:01Z","sessionId":"root-id","agentId":"child","isSidechain":true,"cwd":"/tmp","message":{"role":"user","content":"internal"}}`,
538
538
  )
539
539
 
540
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi")})
540
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
541
541
  sessions := requestSessions(t, s, "/api/sessions")
542
542
  if len(sessions) != 1 || sessions[0].ID != "root-id" {
543
543
  t.Fatalf("sessions = %#v", sessions)
@@ -857,7 +857,7 @@ func TestFreshScanReloadsClaudeSidecarMetadata(t *testing.T) {
857
857
  `{"type":"user","timestamp":"2026-07-09T00:00:01Z","sessionId":"root-id","agentId":"child","isSidechain":true,"cwd":"/tmp","message":{"role":"user","content":"internal"}}`,
858
858
  )
859
859
 
860
- s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi")})
860
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
861
861
  requestSessions(t, s, "/api/sessions")
862
862
  childKey := adapter.SessionKey("claude-code", child)
863
863
  if got := s.sessionCatalog[childKey].Agent.Role; got != "" {
@@ -914,7 +914,7 @@ func TestServerSkipsCodexSubagentSessions(t *testing.T) {
914
914
  },
915
915
  )
916
916
 
917
- s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi")})
917
+ s := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
918
918
  sessions, err := s.scanSessions()
919
919
  if err != nil {
920
920
  t.Fatal(err)
@@ -925,7 +925,7 @@ func TestServerSkipsCodexSubagentSessions(t *testing.T) {
925
925
 
926
926
  // Explicitly opening an auxiliary rollout keeps it available internally
927
927
  // without leaking it into the visible session list.
928
- explicit := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), OpenSession: subagentSession})
928
+ explicit := New(Config{ClaudeDir: claudeDir, CodexDir: codexDir, PiDir: filepath.Join(t.TempDir(), "pi"), AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode"), OpenSession: subagentSession})
929
929
  explicitSessions, err := explicit.listSessions()
930
930
  if err != nil {
931
931
  t.Fatal(err)
@@ -1362,7 +1362,7 @@ func TestSessionAgentsForSourceWithoutGraphSupport(t *testing.T) {
1362
1362
  t.Fatal(err)
1363
1363
  }
1364
1364
 
1365
- s := New(Config{ClaudeDir: filepath.Join(t.TempDir(), "claude"), CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: piRoot})
1365
+ s := New(Config{ClaudeDir: filepath.Join(t.TempDir(), "claude"), CodexDir: filepath.Join(t.TempDir(), "codex"), PiDir: piRoot, AgyDir: filepath.Join(t.TempDir(), "agy"), OpencodeDir: filepath.Join(t.TempDir(), "opencode")})
1366
1366
  if sessions := requestSessions(t, s, "/api/sessions"); len(sessions) != 1 {
1367
1367
  t.Fatalf("sessions = %#v", sessions)
1368
1368
  }
@@ -0,0 +1,3 @@
1
+ import{r,j as t,a as rs,R as Qe,c as as}from"./react-gcHzaSmV.js";import{C as jt,V as te,Q as ze,S as ct,a as Mt,M as kt,b as me,c as We,L as os,d as is,B as nn,e as rt,D as Pt,f as sn,A as at,g as rn,h as an,P as on,W as cn,O as ln,H as dn,i as un,R as cs,j as _e,G as hn,F as fn,k as wt,l as nt,m as pn,n as bt,I as qe,o as Be,p as st,q as mn,r as ls,E as ds,s as us,t as It,u as hs,v as fs,w as ps}from"./three-DnGjZfD1.js";(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))a(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const f of l.addedNodes)f.tagName==="LINK"&&f.rel==="modulepreload"&&a(f)}).observe(document,{childList:!0,subtree:!0});function s(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function a(o){if(o.ep)return;o.ep=!0;const l=s(o);fetch(o.href,l)}})();const ms=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),gs=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(n,s,a)=>a?a.toUpperCase():s.toLowerCase()),zt=e=>{const n=gs(e);return n.charAt(0).toUpperCase()+n.slice(1)},gn=(...e)=>e.filter((n,s,a)=>!!n&&n.trim()!==""&&a.indexOf(n)===s).join(" ").trim(),xs=e=>{for(const n in e)if(n.startsWith("aria-")||n==="role"||n==="title")return!0};var vs={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};const ys=r.forwardRef(({color:e="currentColor",size:n=24,strokeWidth:s=2,absoluteStrokeWidth:a,className:o="",children:l,iconNode:f,...m},v)=>r.createElement("svg",{ref:v,...vs,width:n,height:n,stroke:e,strokeWidth:a?Number(s)*24/Number(n):s,className:gn("lucide",o),...!l&&!xs(m)&&{"aria-hidden":"true"},...m},[...f.map(([d,b])=>r.createElement(d,b)),...Array.isArray(l)?l:[l]]));const oe=(e,n)=>{const s=r.forwardRef(({className:a,...o},l)=>r.createElement(ys,{ref:l,iconNode:n,className:gn(`lucide-${ms(zt(e))}`,`lucide-${e}`,a),...o}));return s.displayName=zt(e),s};const ws=[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]],bs=oe("bot",ws);const js=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],Ms=oe("circle",js);const ks=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12",key:"l9bcsi"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12",key:"13hhkx"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2",key:"10w3f3"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18",key:"15g9kq"}]],Ns=oe("crosshair",ks);const Cs=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]],Es=oe("ellipsis",Cs);const Rs=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],Ss=oe("eye-off",Rs);const $s=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],As=oe("eye",$s);const Ls=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]],Tt=oe("folder-open",Ls);const Ps=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],Is=oe("info",Ps);const zs=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],Nt=oe("loader",zs);const Ts=[["path",{d:"m8 3 4 8 5-5 5 15H2L8 3z",key:"otkl63"}]],xn=oe("mountain",Ts);const Fs=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m16 15-3-3 3-3",key:"14y99z"}]],Bs=oe("panel-left-close",Fs);const _s=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m14 9 3 3-3 3",key:"8010ee"}]],qs=oe("panel-left-open",_s);const Ds=[["rect",{x:"14",y:"3",width:"5",height:"18",rx:"1",key:"kaeet6"}],["rect",{x:"5",y:"3",width:"5",height:"18",rx:"1",key:"1wsw3u"}]],Os=oe("pause",Ds);const Hs=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],Us=oe("play",Hs);const Vs=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],ot=oe("refresh-cw",Vs);const Gs=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Ks=oe("rotate-ccw",Gs);const Ws=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],Ys=oe("search",Ws);const Xs=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],vn=oe("sparkles",Xs);const Js=[["path",{d:"M13.971 4.285A2 2 0 0 1 17 6v12a2 2 0 0 1-3.029 1.715l-9.997-5.998a2 2 0 0 1-.003-3.432z",key:"19qhus"}],["path",{d:"M21 20V4",key:"cb8qj8"}]],Zs=oe("step-back",Js);const Qs=[["path",{d:"M10.029 4.285A2 2 0 0 0 7 6v12a2 2 0 0 0 3.029 1.715l9.997-5.998a2 2 0 0 0 .003-3.432z",key:"1ystz2"}],["path",{d:"M3 4v16",key:"1ph11n"}]],er=oe("step-forward",Qs);const tr=[["path",{d:"m17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14h-.3a1 1 0 0 1-.7-1.7L9 9h-.2A1 1 0 0 1 8 7.3L12 3l4 4.3a1 1 0 0 1-.8 1.7H15l3 3.3a1 1 0 0 1-.7 1.7H17Z",key:"cpyugq"}],["path",{d:"M12 22v-3",key:"kmzjlo"}]],yn=oe("tree-pine",tr);const nr=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],Ct=oe("triangle-alert",nr);const sr=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]],rr=oe("users",sr);const ar=[["path",{d:"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5",key:"ftymec"}],["rect",{x:"2",y:"6",width:"14",height:"12",rx:"2",key:"158x01"}]],or=oe("video",ar);const ir=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],Ye=oe("x",ir);async function De(e){const n=await fetch(e);if(!n.ok){const s=(await n.text()).trim();throw new Error(s||`${n.status} ${n.statusText}`)}return n.json()}function Ae(e,n){if(e instanceof TypeError)return`Can't reach the Synapse server while ${n} — is it still running?`;const s=(e instanceof Error?e.message:String(e)).trim();return s?`Couldn't finish ${n}: ${s}`:`Couldn't finish ${n}`}function Ft(e=!1){return De(e?"/api/sessions?fresh=1":"/api/sessions")}function cr(e){return De(`/api/sessions/${encodeURIComponent(e)}/snapshot`)}function lr(e){return De(`/api/sessions/${encodeURIComponent(e)}/agents`)}function dr(e,n){return De(`/api/sessions/${encodeURIComponent(e)}/agents/${encodeURIComponent(n)}/trace`)}function ur(e){return De(`/api/sessions/${encodeURIComponent(e)}/report`)}async function hr(e,n){const s=await fetch(`/api/sessions/${encodeURIComponent(e)}/analyze`,{method:"POST",headers:n?{"Content-Type":"application/json"}:void 0,body:n?JSON.stringify(n):void 0});if(!s.ok){const a=(await s.text()).trim();throw new Error(a||`${s.status} ${s.statusText}`)}return s.json()}function fr(e){const n=e?`/api/repomap?repo=${encodeURIComponent(e)}`:"/api/repomap";return De(n)}function pr({panels:e,openSheet:n,openPop:s,onToggle:a,onClosePop:o}){const l=r.useRef(null),f=r.useRef(null),m=e.find(c=>c.id===n&&c.presentation==="sheet"),v=e.find(c=>c.id===s&&c.presentation==="pop"),b=["scene","session"].map(c=>({section:c,items:e.filter(S=>S.section===c)})).filter(c=>c.items.length>0);return r.useEffect(()=>{if(!v)return;const c=w=>{const I=w.target;l.current?.contains(I)||f.current?.contains(I)||o()},S=w=>{w.key==="Escape"&&o()};return document.addEventListener("pointerdown",c),document.addEventListener("keydown",S),()=>{document.removeEventListener("pointerdown",c),document.removeEventListener("keydown",S)}},[v,o]),t.jsxs("div",{className:"dock",children:[v?t.jsx("div",{className:"dock-pop",ref:l,children:v.render()}):null,m?t.jsx("aside",{className:"dock-panel",children:m.render()}):null,t.jsx("div",{className:"dock-side",ref:f,children:t.jsx("div",{className:"dock-strip",role:"group","aria-label":"Stage panels",children:b.map((c,S)=>t.jsxs("div",{className:"dock-strip-group",children:[S>0?t.jsx("div",{className:"dock-strip-divider","aria-hidden":!0}):null,c.items.map(w=>{const I=w.id===n||w.id===s,O=w.icon;return t.jsxs("button",{"aria-pressed":I,className:I?"active":"",onClick:()=>a(w),"data-hint":w.hint,"aria-label":w.hint,children:[t.jsx(O,{size:15}),w.badge?t.jsx("span",{className:`dock-dot dock-dot-${w.badge}`}):null]},w.id)})]},c.section))})})]})}function mr({graph:e,current:n,loading:s,loadingAgentID:a,locked:o=!1,error:l,retryAgentID:f,onSelect:m,onRetry:v,onClose:d}){const b=e?.agents.filter(p=>p.kind!=="main")??[],c=e?.agents.find(p=>p.kind==="main"),S=l&&f===null?l:void 0,[w,I]=r.useState(null),O=e?.agents.find(p=>p.id===w?.agentID);r.useEffect(()=>{w&&e&&!O&&I(null)},[w,O,e]);const T=()=>{I(null),d()};return t.jsxs("div",{className:"dock-body agents-panel","aria-label":"Agent lenses",children:[t.jsxs("div",{className:"inspector-head",children:[t.jsxs("div",{children:[t.jsx("div",{className:"inspector-path",children:"Agents"}),t.jsx("div",{className:"agents-head-note",children:"Choose one trace at a time"})]}),t.jsx("button",{className:"icon-btn",onClick:T,title:"Close","aria-label":"Close agents",children:t.jsx(Ye,{size:15})})]}),S?t.jsx(Bt,{error:S,locked:o,onRetry:v}):null,t.jsxs("div",{className:"agent-list","aria-busy":s||a!==void 0,children:[t.jsxs("button",{className:n===null?"agent-row agent-row-select active":"agent-row agent-row-select","aria-pressed":n===null,disabled:o,onClick:()=>m(null),children:[t.jsx("span",{className:"agent-row-icon","aria-hidden":!0,children:t.jsx(Ms,{size:12})}),t.jsxs("span",{className:"agent-row-copy",children:[t.jsxs("span",{className:"agent-row-primary",children:[t.jsxs("span",{className:"agent-row-title",children:["Main",n===null?t.jsx("span",{className:"agent-current",children:"current"}):null]}),t.jsx("span",{className:"agent-row-count",children:wn(c?.traceEventCount??0)})]}),t.jsx("span",{className:"agent-row-secondary",children:"Root trace"})]})]}),b.map(p=>{const j=l&&f===p.id?l:void 0;return t.jsxs(r.Fragment,{children:[t.jsx(gr,{agent:p,current:n===p.id,loading:a===p.id,locked:o,onSelect:m,detailMode:w?.agentID===p.id?w.mode:void 0,onPreview:$=>I(C=>C?.mode==="pinned"?C:{agentID:p.id,mode:"preview",anchor:$}),onPreviewEnd:$=>I(C=>C?.agentID===$&&C.mode==="preview"?null:C),onToggleDetails:$=>I(C=>C?.agentID===p.id&&C.mode==="pinned"?null:{agentID:p.id,mode:"pinned",anchor:$})}),j?t.jsx(Bt,{error:j,locked:o,onRetry:v,rowLocal:!0}):null]},p.id)}),e&&b.length===0?t.jsx("p",{className:"agents-empty",children:"No child agents found."}):null,!e&&s?t.jsxs("p",{className:"agents-state","aria-live":"polite",children:[t.jsx(Nt,{size:13,className:"spin","aria-hidden":!0}),"Loading agents…"]}):null]}),w&&O?t.jsx(xr,{agent:O,state:w,onClose:()=>I(null)}):null]})}function Bt({error:e,locked:n,onRetry:s,rowLocal:a=!1}){return t.jsxs("div",{className:a?"agents-error row-local":"agents-error",role:"alert",children:[t.jsxs("span",{children:[t.jsx(Ct,{size:14,"aria-hidden":!0}),e]}),t.jsxs("button",{className:"agents-retry",onClick:s,disabled:n,children:[t.jsx(ot,{size:13,"aria-hidden":!0}),"Retry"]})]})}function gr({agent:e,current:n,loading:s,locked:a,onSelect:o,detailMode:l,onPreview:f,onPreviewEnd:m,onToggleDetails:v}){const d=e.traceAvailability==="available",b=vr(e,s),c=[e.role,e.instructionPreview].filter(Boolean).join(" · "),S=!d||a;return t.jsxs("div",{className:["agent-row",n?"active":"",S?"disabled":""].filter(Boolean).join(" "),onMouseEnter:w=>f(w.currentTarget),onMouseLeave:()=>m(e.id),onFocus:w=>f(w.currentTarget),onBlur:w=>{w.currentTarget.contains(w.relatedTarget)||m(e.id)},children:[t.jsxs("button",{className:"agent-row-select",style:{paddingLeft:`${12+Math.min(e.depth,4)*14}px`},"aria-pressed":n,disabled:S,onClick:()=>o(e.id),"aria-label":`${e.label}, ${b}`,children:[t.jsx("span",{className:"agent-row-icon","aria-hidden":!0,children:s?t.jsx(Nt,{size:13,className:"spin"}):t.jsx(bs,{size:13})}),t.jsxs("span",{className:"agent-row-copy",children:[t.jsxs("span",{className:"agent-row-primary",children:[t.jsxs("span",{className:"agent-row-title",children:[e.label,n?t.jsx("span",{className:"agent-current",children:"current"}):null]}),t.jsx("span",{className:`agent-row-count agent-status-${e.traceAvailability}`,children:b})]}),t.jsx("span",{className:"agent-row-secondary",children:c||"No launch details"})]})]}),t.jsx("button",{className:"agent-row-detail-trigger","aria-label":`${l==="pinned"?"Unpin":"Pin"} details for ${e.label}`,"aria-pressed":l==="pinned",onClick:w=>{w.stopPropagation(),v(w.currentTarget.closest(".agent-row"))},children:t.jsx(Is,{size:12,"aria-hidden":!0})})]})}function xr({agent:e,state:n,onClose:s}){const o=r.useRef(null),[l,f]=r.useState({left:12,top:12,width:Math.min(520,window.innerWidth-24),maxHeight:window.innerHeight-24});return r.useLayoutEffect(()=>{const m=()=>{const b=Math.min(520,window.innerWidth-24),c=n.anchor.getBoundingClientRect(),S=c.left-b-12,w=c.right+12,I=S>=12?S:w+b<=window.innerWidth-12?w:Math.min(Math.max(c.left,12),window.innerWidth-b-12),O=window.innerHeight-24,T=Math.min(o.current?.offsetHeight??O,O),p=Math.min(Math.max(c.top,12),window.innerHeight-T-12);f({left:I,top:p,width:b,maxHeight:O})},v=n.anchor.closest(".dock-panel");return m(),window.addEventListener("resize",m),window.addEventListener("scroll",m,!0),v?.addEventListener("animationend",m),()=>{window.removeEventListener("resize",m),window.removeEventListener("scroll",m,!0),v?.removeEventListener("animationend",m)}},[n.anchor]),r.useEffect(()=>{if(n.mode!=="pinned")return;const m=d=>{d.key==="Escape"&&s()},v=d=>{const b=d.target;o.current?.contains(b)||n.anchor.contains(b)||s()};return document.addEventListener("keydown",m),document.addEventListener("pointerdown",v),()=>{document.removeEventListener("keydown",m),document.removeEventListener("pointerdown",v)}},[s,n.anchor,n.mode]),rs.createPortal(t.jsxs("div",{ref:o,className:`agent-detail-popover ${n.mode}`,role:n.mode==="preview"?"tooltip":"dialog","aria-label":`${e.label} details`,style:l,children:[t.jsxs("div",{className:"agent-detail-head",children:[t.jsxs("span",{children:[t.jsx("strong",{children:e.label}),e.role?t.jsx("span",{children:e.role}):null]}),n.mode==="pinned"?t.jsx("button",{className:"agent-detail-close",onClick:s,"aria-label":"Close details",children:t.jsx(Ye,{size:14,"aria-hidden":!0})}):null]}),e.instructionPreview?t.jsx("div",{className:"agent-detail-instruction",children:e.instructionPreview}):null,t.jsx("div",{className:"agent-detail-meta",children:yr(e)})]}),document.body)}function vr(e,n){return n?"Loading trace…":e.traceAvailability==="missing"?"Trace missing":e.status==="failed"?"Launch failed · no trace":e.traceAvailability==="unavailable"?"Trace unavailable":wn(e.traceEventCount)}function wn(e){return`${e} event${e===1?"":"s"}`}function yr(e){return`Launch: ${e.status} · Trace: ${e.traceAvailability} · Correlation: ${e.linkQuality} via ${e.linkMethod}`}const wr={exploration:{title:"Exploration",hint:"Did the agent build enough understanding before editing?"},scope:{title:"Scope",hint:"Does the footprint match what the task needed?"},wandering:{title:"Wandering",hint:"Purposeful path, or circles and dead ends?"},verification:{title:"Verification",hint:"Were edits verified, and errors followed up?"}},bn={claude:[{value:"",label:"default model"},{value:"sonnet",label:"sonnet"},{value:"opus",label:"opus"},{value:"fable",label:"fable"}],codex:[{value:"",label:"default model"},{value:"gpt-5.6-sol",label:"gpt-5.6 sol"},{value:"gpt-5.6-terra",label:"gpt-5.6 terra"}]},jn="mindwalk:judge-choice";function br(){try{const e=localStorage.getItem(jn);if(e){const n=JSON.parse(e);return{cli:typeof n.cli=="string"?n.cli:"",model:typeof n.model=="string"?n.model:""}}}catch{}return{cli:"",model:""}}function jr(e,n){const s=n.includes(e.cli)?e.cli:n[0]??"",o=(bn[s]??[]).some(l=>l.value===e.model)?e.model:"";return{cli:s,model:o}}function Mr({status:e,analyzing:n,locked:s,onAnalyze:a,onClose:o,onJumpTo:l}){const[f,m]=r.useState(br),v=e?.judgeClis??(e?.judgeCli?[e.judgeCli]:[]),d=jr(f,v),b=r.useCallback(S=>{m(S);try{localStorage.setItem(jn,JSON.stringify(S))}catch{}},[]),c=r.useCallback(()=>a(d),[a,d]);return t.jsxs("div",{className:"dock-body","aria-label":"Session evaluation",children:[t.jsxs("div",{className:"inspector-head",children:[t.jsxs("div",{children:[t.jsx("div",{className:"inspector-path",children:"Evaluation"}),e?.report?t.jsxs("div",{className:"report-meta",children:["judged by ",e.report.judge.cli,e.report.judge.model?` · ${e.report.judge.model}`:""," ·"," ",Ar(e.report.judge.generatedAt)]}):null]}),t.jsx("button",{className:"icon-btn",onClick:o,title:"Close","aria-label":"Close evaluation",children:t.jsx(Ye,{size:15})})]}),t.jsx(Nr,{status:e,analyzing:n,locked:s,analyze:c,onJumpTo:l,picker:v.length>0?t.jsx(kr,{clis:v,choice:d,onChange:b}):null})]})}function kr({clis:e,choice:n,onChange:s}){const a=bn[n.cli]??[{value:"",label:"default model"}];return t.jsxs("div",{className:"report-picker",children:[t.jsx("select",{value:n.cli,onChange:o=>s({cli:o.target.value,model:""}),"aria-label":"Judge agent",title:"Which agent CLI judges this session",children:e.map(o=>t.jsx("option",{value:o,children:o},o))}),t.jsx("select",{value:n.model,onChange:o=>s({...n,model:o.target.value}),"aria-label":"Judge model",title:"Which model the judge runs on",children:a.map(o=>t.jsx("option",{value:o.value,children:o.label},o.value))})]})}function Nr({status:e,analyzing:n,locked:s,analyze:a,onJumpTo:o,picker:l}){if(!e)return t.jsx("p",{className:"report-note",children:"Checking for an existing report…"});if(e.state==="running"||n)return t.jsxs("div",{className:"report-note",children:[t.jsx("p",{className:"report-running",children:"Judging the trajectory…"}),t.jsx("p",{children:"The judge first drafts task-specific criteria from your request, then scores the session against them plus four process dimensions. Usually a minute or two; you can keep exploring meanwhile."})]});if(e.state==="failed")return t.jsxs("div",{className:"report-note",children:[t.jsxs("p",{className:"report-error",children:[t.jsx(Ct,{size:13})," Evaluation failed"]}),t.jsx("p",{className:"report-error-detail",children:e.error}),l,t.jsxs("button",{className:"report-run",onClick:a,children:[t.jsx(ot,{size:13}),"Retry"]})]});if(e.state==="none"||!e.report)return e.judgeAvailable?t.jsxs("div",{className:"report-note",children:[t.jsx("p",{children:"Ask an agent to evaluate this session: how it explored, whether the footprint matched the task, where it wandered, and how it verified its work. Every finding links back to the timeline."}),l,t.jsxs("button",{className:"report-run",onClick:a,children:[t.jsx(vn,{size:13}),"Evaluate session"]}),t.jsx("p",{className:"report-cost",children:"Runs the selected CLI under your own account and sends it a summary of this session — task wording, file paths, event digests — for the model to read. About a minute."})]}):t.jsxs("p",{className:"report-note",children:["Evaluation needs a local agent CLI as judge. Install ",t.jsx("code",{children:"claude"})," or ",t.jsx("code",{children:"codex"})," and make it available on PATH."]});const f=e.report;return t.jsxs("div",{className:"report-body",children:[t.jsxs("div",{className:"report-controls",children:[e.stale?t.jsxs("p",{className:"report-stale-note",children:["Based on ",f.session.eventCount," events — the session has grown since."]}):null,t.jsxs("div",{className:"report-stale-actions",children:[l,t.jsxs("button",{className:"report-rerun",onClick:a,title:e.stale?"Re-evaluate with the current trace":"Run a fresh evaluation of this session",children:[t.jsx(ot,{size:12}),"Re-evaluate"]})]})]}),t.jsx("p",{className:"report-task",children:f.taskSummary}),t.jsx("p",{className:"report-narrative",children:f.narrative}),t.jsx(Cr,{rubric:f.rubric,locked:s,onJumpTo:o}),t.jsx("p",{className:"report-chapter",children:"Process"}),f.dimensions.map(m=>t.jsx(Sr,{dimension:m,locked:s,onJumpTo:o},m.name)),f.notableMoments?.length?t.jsxs("section",{className:"report-section",children:[t.jsx("p",{className:"eyebrow",children:"Moments"}),f.notableMoments.map(m=>t.jsxs("button",{className:"report-moment",onClick:()=>o(m.seq),disabled:s,title:`Jump to step ${m.seq+1}`,children:[t.jsxs("strong",{children:["#",m.seq+1]}),t.jsx("span",{children:m.note})]},m.seq))]}):null]})}function Cr({rubric:e,locked:n,onJumpTo:s}){if(!e)return t.jsx("p",{className:"report-rubric-note",children:"This report has no task rubric — re-evaluate to add one."});if(e.status!=="scored"||!e.tasks?.length){const v=e.reason==="generation-failed"?"Task rubric unavailable this run — showing process dimensions only.":e.reason==="no-events"?"No tool events to evidence a rubric.":"Not enough task text to build a rubric from.";return t.jsx("p",{className:"report-rubric-note",children:v})}const a=e.tasks,o=a.flatMap(v=>v.criteria),l=o.filter(v=>v.coverage&&v.coverage!=="sufficient"),f=o.length>0&&l.length/o.length>.4,m=a.length>1;return t.jsxs("div",{className:"report-rubric",children:[t.jsx("p",{className:"report-chapter",children:"Tasks"}),f?t.jsxs("p",{className:"report-rubric-hint",children:[l.length," of ",o.length," criteria had thin evidence — the log may not show enough to judge them."]}):null,a.map((v,d)=>t.jsx(Er,{task:v,multi:m,locked:n,onJumpTo:s},v.anchorSeqs?.[0]??`task-${d}`)),e.note?t.jsxs("div",{className:"report-rubric-footnote",children:[t.jsx("p",{className:"eyebrow",children:"Rubric note"}),t.jsx("p",{children:e.note})]}):null]})}function Er({task:e,multi:n,locked:s,onJumpTo:a}){const o=e.anchorSeqs?.[0];return t.jsxs("section",{className:"report-rubric-task",children:[n?t.jsx("button",{className:"rubric-task-head",onClick:()=>{o!==void 0&&a(o)},disabled:s||o===void 0,title:o!==void 0?`Jump to this task's start (step ${o+1})`:void 0,children:t.jsxs("span",{className:"rubric-task-title",children:[e.title,e.type?t.jsx("span",{className:"rubric-task-type",children:e.type}):null]})}):null,e.criteria.map(l=>t.jsx(Rr,{criterion:l,locked:s,onJumpTo:a},l.id))]})}function Rr({criterion:e,locked:n,onJumpTo:s}){const a=[e.why,e.good?`good: ${e.good}`:"",e.bad?`bad: ${e.bad}`:""].filter(Boolean).join(`
2
+ `);return t.jsxs("section",{className:"report-dimension report-criterion",children:[t.jsxs("div",{className:"report-dimension-head",children:[t.jsx("span",{className:"report-criterion-name",title:a||void 0,children:e.title}),t.jsxs("span",{className:"report-criterion-badges",children:[e.coverage==="partial"?t.jsx("span",{className:"coverage-badge",children:"partial evidence"}):null,t.jsx("span",{className:`verdict verdict-${e.verdict}`,title:e.coverage==="none"?"The log cannot evidence this criterion either way":void 0,children:kn(e.verdict)})]})]}),e.findings.map(o=>t.jsx(Mn,{finding:o,locked:n,onJumpTo:s},`${o.severity}|${o.evidenceSeqs?.join(",")}|${o.claim}`))]})}function Mn({finding:e,locked:n,onJumpTo:s}){return t.jsxs("button",{className:"report-finding",onClick:()=>{const a=e.evidenceSeqs?.[0];a!==void 0&&s(a)},disabled:n||!e.evidenceSeqs?.length,title:e.evidenceSeqs?.length?`Jump to step ${e.evidenceSeqs[0]+1} — evidence: ${e.evidenceSeqs.map(a=>`#${a+1}`).join(" ")}`:void 0,children:[t.jsx("span",{className:`severity-dot ${$r(e.severity)}`}),t.jsx("span",{className:"report-claim",children:e.claim})]})}function Sr({dimension:e,locked:n,onJumpTo:s}){const a=wr[e.name]??{title:e.name,hint:""};return t.jsxs("section",{className:"report-dimension",children:[t.jsxs("div",{className:"report-dimension-head","data-hint":a.hint,children:[t.jsx("span",{className:"report-dimension-name",children:a.title}),t.jsx("span",{className:`verdict verdict-${e.verdict}`,children:kn(e.verdict)})]}),e.findings.map(o=>t.jsx(Mn,{finding:o,locked:n,onJumpTo:s},`${o.severity}|${o.evidenceSeqs?.join(",")}|${o.claim}`))]})}function kn(e){return e==="insufficient-data"?"no signal":e}function $r(e){return`sev-${e}`}function Ar(e){const n=new Date(e);return Number.isNaN(n.getTime())?"":n.toISOString().slice(0,10)}function Lr({view:e,onViewChange:n,note:s,locked:a=!1}){return t.jsxs("div",{className:"view-pop",role:"group","aria-label":"Scene view",children:[t.jsxs("button",{"aria-pressed":e==="tree",className:e==="tree"?"view-row active":"view-row",onClick:()=>n("tree"),disabled:a,children:[t.jsx(yn,{size:14}),t.jsx("span",{children:"Tree"})]}),t.jsxs("button",{"aria-pressed":e==="terrain",className:e==="terrain"?"view-row active":"view-row",onClick:()=>n("terrain"),disabled:a,children:[t.jsx(xn,{size:14}),t.jsx("span",{children:"Terrain"})]}),t.jsxs("p",{className:"view-note",children:[s,t.jsx("span",{className:"view-key",children:"V"})]})]})}const et={hit:1,read:2,edit:3},Pr=12;class Ir{events;idByPath=new Map;cursor=-1;touchByFile=new Map;touchByPath=new Map;visitsByFile=new Map;historyByPath=new Map;recentTargets=[];constructor(n,s){this.events=n?.events??[];for(const a of s?.files??[])this.idByPath.set(a.path,a.id)}snapshotAt(n){const s=Math.min(n,this.events.length-1);s<this.cursor&&this.reset();for(let a=this.cursor+1;a<=s;a++)this.apply(this.events[a]);return this.cursor=Math.max(this.cursor,s),{touchByFile:this.touchByFile,touchByPath:this.touchByPath,visitsByFile:this.visitsByFile,historyByPath:this.historyByPath,recentTargets:this.recentTargets}}reset(){this.cursor=-1,this.touchByFile.clear(),this.touchByPath.clear(),this.visitsByFile.clear(),this.historyByPath.clear(),this.recentTargets.length=0}apply(n){for(const s of n.targets){const a=this.touchByPath.get(s.path);(!a||et[s.touch]>et[a])&&this.touchByPath.set(s.path,s.touch);const o=s.fileId??this.idByPath.get(s.path);if(o!==void 0){const f=this.touchByFile.get(o);(!f||et[s.touch]>et[f])&&this.touchByFile.set(o,s.touch),this.visitsByFile.set(o,(this.visitsByFile.get(o)??0)+1)}const l=this.historyByPath.get(s.path);l?l.push(n):this.historyByPath.set(s.path,[n])}if(n.targets.length>0){const s=n.targets.find(a=>!a.weak)??n.targets[0];this.recentTargets.push({...s,fileId:s.fileId??this.idByPath.get(s.path)}),this.recentTargets.length>Pr&&this.recentTargets.shift()}}}function zr(e){const s=e.split(";")[0].trim().toLowerCase().split("/")[1]??"";return s.includes("webm")?"webm":s.includes("mp4")?"mp4":s.includes("x-matroska")||s.includes("matroska")?"mkv":s.includes("ogg")?"ogv":s||"webm"}const Tr=30,Fr=3e4,Br=120;function _r(){const e=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm"];for(const n of e)if(typeof MediaRecorder<"u"&&MediaRecorder.isTypeSupported(n))return n}function Nn(){return typeof MediaRecorder<"u"&&typeof HTMLCanvasElement<"u"&&typeof HTMLCanvasElement.prototype.captureStream=="function"}function qr(e){const{canvas:n,total:s,setSeq:a,onProgress:o,signal:l}=e,f=e.fps??Tr;if(!Nn())return Promise.reject(new Error("This browser can't record the canvas (MediaRecorder unavailable)."));if(s<=0)return Promise.reject(new Error("Nothing to record — load a session first."));const m=e.durationMs??Math.min(Fr,Math.max(1e3,s*Br)),v=_r(),d=n.captureStream(f),b=v?new MediaRecorder(d,{mimeType:v}):new MediaRecorder(d),c=[];return new Promise((S,w)=>{let I=0,O=0,T=!1;const p=()=>{I&&cancelAnimationFrame(I),d.getTracks().forEach(P=>P.stop()),l?.removeEventListener("abort",C)},j=()=>{if(T)return;T=!0,p();const P=b.mimeType||v||"video/webm";S({blob:new Blob(c,{type:P}),extension:zr(P)})},$=P=>{if(!T){T=!0,p();try{b.state!=="inactive"&&b.stop()}catch{}w(P)}},C=()=>$(new Error("Recording cancelled."));if(b.ondataavailable=P=>{P.data&&P.data.size>0&&c.push(P.data)},b.onerror=()=>$(new Error("Recording failed.")),b.onstop=j,l){if(l.aborted){$(new Error("Recording cancelled."));return}l.addEventListener("abort",C)}const L=P=>{if(T)return;O||(O=P);const ne=Math.min(1,(P-O)/m),K=Math.min(s-1,Math.floor(ne*(s-1)));if(a(K),o?.(ne),ne>=1){I=requestAnimationFrame(()=>{b.state!=="inactive"&&b.stop()});return}I=requestAnimationFrame(L)};a(0),b.start(),I=requestAnimationFrame(L)})}function Dr(e,n){const s=URL.createObjectURL(e),a=document.createElement("a");a.href=s,a.download=n,document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(s),1e3)}function Xe(e){switch(e){case"hit":return"seen";case"read":return"read";case"edit":return"edited";default:return"unvisited"}}let He=null;function Cn(){if(He)return He;const e=64,n=document.createElement("canvas");n.width=e,n.height=e;const s=n.getContext("2d"),a=s.createRadialGradient(e/2,e/2,0,e/2,e/2,e/2);return a.addColorStop(0,"rgba(255,255,255,1)"),a.addColorStop(.25,"rgba(255,210,160,0.55)"),a.addColorStop(1,"rgba(255,158,94,0)"),s.fillStyle=a,s.fillRect(0,0,e,e),He=new jt(n),He.userData.shared=!0,He}let Ue=null;function Or(){if(Ue)return Ue;const e=128,n=document.createElement("canvas");n.width=e,n.height=e;const s=n.getContext("2d"),a=s.createRadialGradient(e/2,e/2,0,e/2,e/2,e/2);return a.addColorStop(0,"rgba(255,255,255,0.9)"),a.addColorStop(.4,"rgba(255,255,255,0.28)"),a.addColorStop(1,"rgba(255,255,255,0)"),s.fillStyle=a,s.fillRect(0,0,e,e),Ue=new jt(n),Ue.userData.shared=!0,Ue}function Hr(e){const n='500 30px "Schibsted Grotesk Variable", "PingFang SC", sans-serif',s=document.createElement("canvas").getContext("2d");s.font=n;const a=Math.ceil(s.measureText(e).width)+24,o=44,l=document.createElement("canvas");l.width=a*2,l.height=o*2;const f=l.getContext("2d");f.scale(2,2),f.font=n,f.textBaseline="middle",f.textAlign="center",f.fillStyle="rgba(197, 205, 222, 0.95)",f.fillText(e,a/2,o/2+1);const m=new jt(l);return m.anisotropy=4,{texture:m,aspect:a/o}}const Ur=60,Vr=120;class En{labels=[];y;dirty=!0;lastCamPos=new te(1/0,1/0,1/0);lastCamQuat=new ze(0,0,0,0);lastViewW=0;lastViewH=0;point=new te;constructor(n,s,a,o=!1){this.y=a;const l=[...n].sort((f,m)=>m.fileCount-f.fileCount).slice(0,Vr);for(const f of l){const{texture:m,aspect:v}=Hr(f.name),d=new ct(new Mt({map:m,transparent:!0,opacity:0,depthWrite:!1,depthTest:!o,toneMapped:!1,fog:!1}));o&&(d.renderOrder=20),d.visible=!1,d.position.set(f.x,a,f.z),d.raycast=()=>{},s.add(d),this.labels.push({sprite:d,entry:f,aspect:v,target:0})}}markDirty(){this.dirty=!0}updateTargets(n,s,a){if(this.labels.length===0||s===0||a===0||!(this.dirty||!n.position.equals(this.lastCamPos)||!n.quaternion.equals(this.lastCamQuat)||s!==this.lastViewW||a!==this.lastViewH))return;this.dirty=!1,this.lastCamPos.copy(n.position),this.lastCamQuat.copy(n.quaternion),this.lastViewW=s,this.lastViewH=a;const l=Math.tan(kt.degToRad(n.fov)/2),f=Math.max(s,a),m=[];for(const d of this.labels){this.point.set(d.entry.x,this.y,d.entry.z);const b=this.point.distanceTo(n.position),c=a/(2*b*l),S=d.entry.radius*c;this.point.project(n);const w=(this.point.x+1)/2*s,I=(1-this.point.y)/2*a;if(!(this.point.z<1&&w>-60&&w<s+60&&I>-40&&I<a+40)||S<Ur||S>f*1.6){d.target=0;continue}const T=d.entry.depth<=1?15:13,p=T/c;d.sprite.scale.set(p*d.aspect,p,1),m.push({label:d,sx:w,sy:I,pw:T*d.aspect,ph:T})}m.sort((d,b)=>b.label.entry.fileCount-d.label.entry.fileCount);const v=[];for(const d of m){const b=v.some(c=>Math.abs(c.sx-d.sx)<(c.pw+d.pw)/2+14&&Math.abs(c.sy-d.sy)<(c.ph+d.ph)/2+10);d.label.target=b?0:1,b||v.push(d)}}ease(n){for(const s of this.labels){const a=s.sprite.material,o=s.target-a.opacity;Math.abs(o)>.02?a.opacity=n?s.target:a.opacity+o*.16:a.opacity!==s.target&&(a.opacity=s.target),s.sprite.visible=a.opacity>.02}}}const it=new me("#12151c"),Rn=new me("#ff9e5e"),Sn={hit:new me("#8fb45f"),read:new me("#a5c8f1"),edit:new me("#f0ad5a"),selected:new me("#f6ead2")};function $n(e,n,s){if(!Number.isFinite(e.aspect)||e.aspect<=0)return null;const a=n.clone().negate(),o=new te().crossVectors(a,new te(0,1,0)).normalize(),l=new te().crossVectors(o,a),f=Math.tan(kt.degToRad(e.fov)/2),m=f*e.aspect;let v=0;for(const d of s){const b=d.dot(a);v=Math.max(v,Math.abs(d.dot(o))/m-b,Math.abs(d.dot(l))/f-b)}return v}function An(e,n,s,a,o,l){if(a===0||o===0)return;const f=e.getWorldDirection(new te),m=s.clone().sub(e.position).dot(f);if(m<=0)return;const v=s.clone().project(e),d=(v.x+1)/2*a,b=(1-v.y)/2*o,c=48,S=Math.max(c+60,a-l-48),w=120,I=o-100,O=Math.min(Math.max(d,c),S),T=Math.min(Math.max(b,w),I);if(O===d&&T===b)return;const p=Math.tan(kt.degToRad(e.fov)/2),j=p*e.aspect,$=new te().crossVectors(f,new te(0,1,0)).normalize(),C=new te().crossVectors($,f),L=$.multiplyScalar((d-O)*2*m*j/a).addScaledVector(C,(T-b)*2*m*p/o);e.position.add(L),n.target.add(L),n.update()}class Ln{constructor(n){this.host=n,this.el=document.createElement("div"),this.el.className="scene-tip",this.pathEl=document.createElement("span"),this.metaEl=document.createElement("span"),this.metaEl.className="dim",this.el.append(this.pathEl,this.metaEl),n.appendChild(this.el)}host;el;pathEl;metaEl;show(n,s,a,o){this.pathEl.textContent=n,this.metaEl.textContent=` · ${s}`,this.el.style.display="block";const l=this.host.getBoundingClientRect(),f=a-l.left,m=o-l.top,v=Math.min(f+14,Math.max(0,l.width-this.el.offsetWidth-8)),d=Math.min(m+16,Math.max(0,l.height-this.el.offsetHeight-8));this.el.style.left=`${v}px`,this.el.style.top=`${d}px`}hide(){this.el.style.display="none"}dispose(){this.el.remove()}}const Pn=()=>typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches;function In(e){e.traverse(n=>{if(n instanceof We||n instanceof os||n instanceof ct){n.geometry?.dispose();const s=n.material;Array.isArray(s)?s.forEach(_t):s&&_t(s)}})}function _t(e){const n=e.map;n&&!n.userData.shared&&n.dispose(),e.dispose()}const Ve=14,qt=11;class zn{object;positions;colors;lift;arcPoints=Array.from({length:Ve+1},()=>new te);mid=new te;curve=new is;color=new me;constructor(n){this.lift=n;const s=qt*Ve*2,a=new nn;this.positions=new rt(new Float32Array(s*3),3),this.positions.setUsage(Pt),this.colors=new rt(new Float32Array(s*3),3),this.colors.setUsage(Pt),a.setAttribute("position",this.positions),a.setAttribute("color",this.colors),a.setDrawRange(0,0);const o=new sn({vertexColors:!0,transparent:!0,blending:at,depthWrite:!1,fog:!1});this.object=new rn(a,o),this.object.frustumCulled=!1}update(n){const s=Math.min(Math.max(n.length-1,0),qt);if(s===0){this.object.geometry.setDrawRange(0,0);return}const a=n.length-1-s;let o=0;for(let l=1;l<=s;l++){const f=n[a+l-1],m=n[a+l];this.mid.copy(f).lerp(m,.5),this.mid.y=Math.max(f.y,m.y)+f.distanceTo(m)*.22+this.lift,this.curve.v0.copy(f),this.curve.v1.copy(this.mid),this.curve.v2.copy(m);for(let d=0;d<=Ve;d++)this.curve.getPoint(d/Ve,this.arcPoints[d]);const v=l/s;this.color.copy(Rn).multiplyScalar(.05+.95*v*v);for(let d=0;d<Ve;d++){const b=this.arcPoints[d],c=this.arcPoints[d+1];this.positions.setXYZ(o,b.x,b.y,b.z),this.colors.setXYZ(o,this.color.r,this.color.g,this.color.b),o++,this.positions.setXYZ(o,c.x,c.y,c.z),this.colors.setXYZ(o,this.color.r,this.color.g,this.color.b),o++}}this.object.geometry.setDrawRange(0,o),this.positions.needsUpdate=!0,this.colors.needsUpdate=!0}}const Ce={unvisited:new me("#5b6372"),ghost:new me("#404551"),...Sn},Ge=.14,Gr=2.4,Kr=348;function Dt(e,n){return(e==="edit"?7.2:e==="read"?4.2:1.6)*(1+.35*Math.log2(Math.max(n,1)))}const Ot=.3,Wr=16,Yr=2.2;function Xr(e,n){return n<=0?0:Math.min(1,Math.log2(Math.max(e,1))/n)}function Jr(e){return Ot+Math.pow(e,Yr)*(Wr-Ot)}const Fe=[{at:0,color:new me("#5b6372")},{at:.35,color:new me("#e0894f")},{at:.7,color:new me("#9a6bd8")},{at:1,color:new me("#e0524f")}];function Zr(e){for(let n=1;n<Fe.length;n++)if(e<=Fe[n].at){const s=Fe[n-1],a=Fe[n],o=a.at-s.at,l=o>0?(e-s.at)/o:0;return s.color.clone().lerp(a.color,l)}return Fe[Fe.length-1].color.clone()}function Qr({city:e,playback:n,selectedPath:s,onSelect:a,onCanvasReady:o,locHeights:l}){const f=r.useRef(null),m=r.useRef(null),v=r.useRef(null),d=r.useRef([]),b=r.useRef([]),c=r.useRef(new Map),S=r.useRef(null),w=r.useRef(null),I=r.useRef(null),O=r.useRef(null),T=r.useRef(null),p=r.useRef(null),j=r.useRef(null),$=r.useRef(null),C=r.useRef(null),L=r.useRef(!1),P=r.useRef({cx:0,cz:0,size:120}),ne=r.useRef(n);ne.current=n;const K=r.useRef(null),G=r.useMemo(()=>{if(!e||e.files.length===0)return{cx:0,cz:0,size:120,halfW:60,halfD:60};let A=1/0,x=-1/0,k=1/0,E=-1/0;for(const i of e.files)A=Math.min(A,i.rect.x),x=Math.max(x,i.rect.x+i.rect.w),k=Math.min(k,i.rect.z),E=Math.max(E,i.rect.z+i.rect.d);return{cx:(A+x)/2,cz:(k+E)/2,size:Math.max(x-A,E-k,60),halfW:(x-A)/2,halfD:(E-k)/2}},[e]);return r.useEffect(()=>{const A=f.current;if(!A)return;const x=Pn();L.current=x;const k=new an;k.background=it,O.current=k;const E=new on(38,A.clientWidth/A.clientHeight||1,.1,2400);E.position.set(70,130,100),w.current=E;const i=new cn({antialias:!0});i.setPixelRatio(Math.min(window.devicePixelRatio,2)),i.setSize(A.clientWidth,A.clientHeight),S.current=i,A.appendChild(i.domElement),o?.(i.domElement);const h=new ln(E,i.domElement);h.enableDamping=!x,h.dampingFactor=.08,h.maxPolarAngle=Math.PI*.44,h.autoRotate=!x,h.autoRotateSpeed=-.5;const g=new Ln(A);h.addEventListener("start",()=>{h.autoRotate=!1,g.hide()}),I.current=h;const y=new dn("#66779b","#161922",1.7);k.add(y);const R=new un("#b6c5de",1.1);R.position.set(-60,120,-40),k.add(R);const q=new cs,U=new ls,de=X=>{if(!w.current||!S.current)return;const J=S.current.domElement.getBoundingClientRect();U.x=(X.clientX-J.left)/J.width*2-1,U.y=-((X.clientY-J.top)/J.height)*2+1,q.setFromCamera(U,w.current);const he=[v.current,m.current].filter(Boolean),ie=q.intersectObjects(he,!1)[0];if(!(!ie||ie.instanceId===void 0)){if(ie.object===v.current){const H=b.current[ie.instanceId];return H?d.current[H.fileId]:void 0}return d.current[ie.instanceId]}};let ae=null;const le=X=>{ae={x:X.clientX,y:X.clientY}},F=X=>{if(!ae)return;const J=Math.hypot(X.clientX-ae.x,X.clientY-ae.y);ae=null,!(J>5)&&a(de(X)?.path)};let z=0;const D=X=>{if(ae){g.hide();return}z||(z=requestAnimationFrame(()=>{z=0;const J=de(X);if(i.domElement.style.cursor=J?"pointer":"",!J){g.hide();return}const he=ne.current,ie=he.touchByPath.get(J.path),H=he.visitsByFile.get(J.id)??0,N=ie?`${Xe(ie)} · ${H} visit${H===1?"":"s"}`:Xe(void 0);g.show(J.path,J.ghost?`${N} · ghost`:N,X.clientX,X.clientY)}))},Y=()=>{g.hide(),i.domElement.style.cursor=""};i.domElement.addEventListener("pointerdown",le),i.domElement.addEventListener("pointerup",F),i.domElement.addEventListener("pointermove",D),i.domElement.addEventListener("pointerleave",Y);const re=()=>{if(!f.current)return;const X=f.current.clientWidth,J=f.current.clientHeight;X===0||J===0||(i.setSize(X,J),E.aspect=X/J,E.updateProjectionMatrix(),K.current?.()&&(K.current=null))},W=new ResizeObserver(re);W.observe(A);const ue=new mn,se=new _e,xe=new ze,je=()=>{h.update(),$.current?.updateTargets(E,i.domElement.clientWidth,i.domElement.clientHeight),$.current?.ease(L.current);const X=v.current,J=b.current,he=c.current;if(X&&J.length>0){let H=!1;for(let N=0;N<J.length;N++){const _=J[N],V=d.current[_.fileId];if(!V)continue;let ee=he.get(_.fileId)??0;const ce=_.target-ee;Math.abs(ce)>.015?(ee=L.current?_.target:ee+ce*.13,he.set(_.fileId,ee),H=!0):ee!==_.target&&(he.set(_.fileId,_.target),ee=_.target,H=!0);const fe=Math.max(V.rect.w,.45)+.04,Z=Math.max(V.rect.d,.45)+.04;se.compose(new te(V.rect.x+V.rect.w/2-P.current.cx,Math.max(ee,.02)/2+Ge,V.rect.z+V.rect.d/2-P.current.cz),xe,new te(fe,Math.max(ee,.02),Z)),X.setMatrixAt(N,se)}H&&(X.instanceMatrix.needsUpdate=!0)}const ie=j.current;if(ie?.visible){const H=ue.getElapsedTime(),N=ie.userData.baseScale,_=L.current?1:1+.1*Math.sin(H*2.4);ie.scale.setScalar(N*_)}i.render(k,E),C.current=requestAnimationFrame(je)};return je(),()=>{C.current&&cancelAnimationFrame(C.current),z&&cancelAnimationFrame(z),i.domElement.removeEventListener("pointerdown",le),i.domElement.removeEventListener("pointerup",F),i.domElement.removeEventListener("pointermove",D),i.domElement.removeEventListener("pointerleave",Y),g.dispose(),W.disconnect(),h.dispose(),i.dispose(),A.removeChild(i.domElement),k.clear(),o?.(null)}},[a,o]),r.useEffect(()=>{const A=O.current;if(!A||(d.current=e?.files??[],b.current=[],c.current=new Map,P.current=G,!e||e.files.length===0))return;const x=new hn,k=G.size;A.fog=new fn(it,k*2.1,k*4.2);const E=new We(new wt(k*6,k*6),new nt({color:"#14171e",roughness:1}));E.rotation.x=-Math.PI/2,E.position.y=-.32,x.add(E);const i=new pn(k*2.8,46,"#20242e","#1a1e27");i.material.transparent=!0,i.material.opacity=.5,i.position.y=-.3,x.add(i);const h=e.dirs.filter(F=>F.depth<=3&&F.rect.w>0&&F.rect.d>0);if(h.length>0){const F=new bt(1,1,1),z=new nt({roughness:.95,metalness:0}),D=new qe(F,z,h.length),Y=new _e,re=new me;h.forEach((W,ue)=>{const se=-.2+Math.min(W.depth,3)*.06,xe=se+.3;Y.compose(new te(W.rect.x+W.rect.w/2-G.cx,se-xe/2,W.rect.z+W.rect.d/2-G.cz),new ze,new te(W.rect.w,xe,W.rect.d)),D.setMatrixAt(ue,Y),re.set("#1a1f29").lerp(new me("#252b37"),Math.min(W.depth,3)/3),D.setColorAt(ue,re)}),D.instanceMatrix.needsUpdate=!0,D.instanceColor&&(D.instanceColor.needsUpdate=!0),x.add(D)}const g=new bt(1,1,1),y=new nt({roughness:.85,metalness:0}),R=new qe(g,y,e.files.length),q=new _e;for(const F of e.files){const z=Math.max(F.rect.w,.45),D=Math.max(F.rect.d,.45),Y=F.rect.x+F.rect.w/2-G.cx,re=F.rect.z+F.rect.d/2-G.cz;q.compose(new te(Y,Ge/2,re),new ze,new te(z,Ge,D)),R.setMatrixAt(F.id,q),R.setColorAt(F.id,Ht(F))}R.instanceMatrix.needsUpdate=!0,R.instanceColor&&(R.instanceColor.needsUpdate=!0),m.current=R,x.add(R);const U=new qe(ea(),new Be({toneMapped:!1,vertexColors:!0}),e.files.length);U.instanceColor=new st(new Float32Array(e.files.length*3),3),U.count=0,U.frustumCulled=!1,v.current=U,x.add(U),$.current=new En(e.dirs.filter(F=>F.depth>=1&&F.fileCount>0&&F.rect.w>0&&F.rect.d>0).map(F=>({name:ta(F.path),x:F.rect.x+F.rect.w/2-G.cx,z:F.rect.z+F.rect.d/2-G.cz,radius:Math.hypot(F.rect.w,F.rect.d)/2,fileCount:F.fileCount,depth:F.depth})),x,Gr,!0);const de=new ct(new Mt({map:Cn(),color:Rn,blending:at,depthWrite:!1,transparent:!0}));de.userData.baseScale=Math.max(k*.028,2.2),de.visible=!1,j.current=de,x.add(de);const ae=new zn(1.4);p.current=ae,x.add(ae.object),T.current=x,A.add(x);const le=()=>{const F=w.current,z=I.current;if(!F||!z)return!0;const D=new te(.46,1.08,.72).normalize(),Y=[];for(const ue of[-1,1])for(const se of[-1,1])Y.push(new te(ue*G.halfW,0,se*G.halfD));const re=$n(F,D,Y);if(re===null)return!1;const W=Math.max(re*1.12,k*.6);return F.position.copy(D).multiplyScalar(W),z.target.set(0,0,0),z.minDistance=k*.18,z.maxDistance=Math.max(k*2.6,W*1.2),z.update(),!0};return K.current=le()?null:le,()=>{K.current=null,In(x),A.remove(x),T.current=null,m.current=null,v.current=null,p.current=null,j.current=null,$.current=null}},[e,G]),r.useEffect(()=>{const A=v.current,x=m.current;if(!A||!x||!e)return;const k=c.current,E=[],i=new Set,h=l?Math.log2(Math.max(1,e.files.reduce((g,y)=>Math.max(g,y.lines),1))):0;for(const g of e.files){const y=n.touchByFile.get(g.id),R=g.path===s;if(x.setColorAt(g.id,R?Ce.selected:Ht(g)),y){const q=n.visitsByFile.get(g.id)??1;let U=Ce[y];g.ghost&&(U=U.clone().lerp(Ce.ghost,.45)),R&&(U=Ce.selected),E.push({fileId:g.id,target:Dt(y,q),color:U}),i.add(g.id)}else if(l){const q=Xr(g.lines,h);let U=Zr(q);g.ghost&&(U=U.lerp(Ce.ghost,.45)),R&&(U=Ce.selected),E.push({fileId:g.id,target:Jr(q),color:U}),i.add(g.id)}}for(const[g,y]of k)y>.04&&!i.has(g)?E.push({fileId:g,target:0,color:Ce.unvisited}):y<=.04&&!i.has(g)&&k.delete(g);E.forEach((g,y)=>A.setColorAt(y,g.color)),A.count=E.length,A.instanceColor&&(A.instanceColor.needsUpdate=!0),x.instanceColor&&(x.instanceColor.needsUpdate=!0),b.current=E},[e,n,s,l]),r.useEffect(()=>{if(!e||!s)return;const A=e.files.find(g=>g.path===s),x=w.current,k=I.current,E=S.current?.domElement;if(!A||!x||!k||!E)return;k.autoRotate=!1;const i=c.current.get(A.id)??Ge,h=vt(A,G);h.y=i,An(x,k,h,E.clientWidth,E.clientHeight,Kr)},[e,G,s]),r.useEffect(()=>{const A=p.current;if(!A||!e)return;const x=n.recentTargets.map(i=>i.fileId!==void 0?e.files[i.fileId]:void 0).filter(i=>!!i),k=i=>{const h=n.touchByFile.get(i.id),g=n.visitsByFile.get(i.id)??1;return h?Dt(h,g):Ge},E=j.current;if(E){const i=x[x.length-1];if(i){const h=vt(i,G);E.position.set(h.x,k(i)+1.6,h.z),E.visible=!0}else E.visible=!1}A.update(x.map(i=>{const h=vt(i,G);return h.y=k(i)+.4,h}))},[e,n,G]),t.jsx("div",{className:"city-scene",ref:f,"aria-label":"Attention terrain"})}function ea(){const e=new bt(1,1,1),n=e.getAttribute("position"),s=e.getAttribute("normal"),a=new Float32Array(n.count*3);for(let o=0;o<n.count;o++){const l=n.getY(o)+.5,f=s.getY(o)===1?.82:.34+.66*l*l;a.fill(f,o*3,o*3+3)}return e.setAttribute("color",new rt(a,3)),e}function Ht(e){if(e.ghost)return Ce.ghost;let n=2166136261;for(let a=0;a<e.path.length;a++)n=Math.imul(n^e.path.charCodeAt(a),16777619);const s=(n>>>0)%1e3/1e3-.5;return Ce.unvisited.clone().offsetHSL(0,0,s*.05)}function vt(e,n){return new te(e.rect.x+e.rect.w/2-n.cx,0,e.rect.z+e.rect.d/2-n.cz)}function ta(e){return e.slice(e.lastIndexOf("/")+1)||e}function na(e){const n={name:"",path:"",depth:0,children:new Map,files:[],leafCount:0,angle:0},s=[...e].sort((p,j)=>p.path<j.path?-1:1);for(const p of s){const j=p.path.split("/").filter(Boolean);let $=n;for(const C of j.slice(0,-1)){let L=$.children.get(C);L||(L={name:C,path:$.path?`${$.path}/${C}`:C,depth:$.depth+1,children:new Map,files:[],leafCount:0,angle:0},$.children.set(C,L)),$=L}$.files.push(p)}let a=1;const o=p=>{p.leafCount=p.files.length,p.files.length>0&&(a=Math.max(a,p.depth+1));for(const j of p.children.values())p.leafCount+=o(j);return p.leafCount};o(n);const l=Math.max(n.leafCount,1),f=Math.max(55,Math.sqrt(l)*4),m=f/Math.max(a,1),v=Math.PI*2/l,d={radius:f,leaf:new Map,dirs:[],edges:[]},b=(p,j)=>({x:p*Math.cos(j),z:p*Math.sin(j)}),c=(p,j,$,C)=>{const L=p<1e-6?C:j;let P=C-L;for(;P>Math.PI;)P-=Math.PI*2;for(;P<-Math.PI;)P+=Math.PI*2;const ne=[],K=8;for(let G=0;G<=K;G++){const A=G/K,x=A*A*(3-2*A);ne.push(b(p+($-p)*A,L+P*x))}return ne};let S=0;const w=p=>{p.angle=(S+p.leafCount/2)*v;const j=[...p.children.values()].sort((C,L)=>C.name<L.name?-1:1),$=[...p.files].sort((C,L)=>C.path<L.path?-1:1);for(const C of j)w(C);for(const C of $){const L=(S+.5)*v;S+=1;const P=b((p.depth+1)*m,L);d.leaf.set(C.id,P),d.edges.push({childFileId:C.id,points:c(p.depth*m,p.angle,(p.depth+1)*m,L)})}if(p.path!==""){const C=b(p.depth*m,p.angle);d.dirs.push({path:p.path,name:p.name,x:C.x,z:C.z,depth:p.depth,fileCount:p.leafCount,radius:0})}};w(n);const I=new Map,O=p=>{I.set(p.path,p);for(const j of p.children.values())O(j)};O(n);for(const p of d.dirs){const j=I.get(p.path),$=p.path.includes("/")?p.path.slice(0,p.path.lastIndexOf("/")):"",C=I.get($);d.edges.push({childPath:p.path,points:c(C.depth*m,C.angle,j.depth*m,j.angle)})}const T=new Map(d.dirs.map(p=>[p.path,p]));for(const p of e){const j=d.leaf.get(p.id);if(!j)continue;const $=p.path.split("/").filter(Boolean);let C="";for(let L=0;L<$.length-1;L++){C=C?`${C}/${$[L]}`:$[L];const P=T.get(C);P&&(P.radius=Math.max(P.radius,Math.hypot(j.x-P.x,j.z-P.z)))}}return d}const Ne={unvisited:new me("#5a6375"),ghost:new me("#4d5464"),...Sn},sa=new me("#3c424f"),ra=new me("#7d8496"),aa=new me("#ffeeda"),Le=.7;function oa(e){return Math.min(1.8*(1+.45*Math.log2(Math.max(e,1))),4.8)}const ia=1.8,ca=348;function la({city:e,playback:n,selectedPath:s,onSelect:a,onCanvasReady:o}){const l=r.useRef(null),f=r.useRef(null),m=r.useRef(null),v=r.useRef(new Map),d=r.useRef(null),b=r.useRef(null),c=r.useRef(null),S=r.useRef([]),w=r.useRef([]),I=r.useRef(null),O=r.useRef([]),T=r.useRef(new Map),p=r.useRef(null),j=r.useRef(null),$=r.useRef(null),C=r.useRef(null),L=r.useRef(null),P=r.useRef(null),ne=r.useRef(null),K=r.useRef(null),G=r.useRef(null),A=r.useRef(!1),x=r.useRef(n);x.current=n;const k=r.useRef(null),E=r.useMemo(()=>e&&e.files.length>0?na(e.files):null,[e]);return r.useEffect(()=>{const i=l.current;if(!i)return;const h=Pn();A.current=h;const g=new an;g.background=it,C.current=g;const y=new on(38,i.clientWidth/i.clientHeight||1,.1,2400);y.position.set(60,110,90),j.current=y;const R=new cn({antialias:!0});R.setPixelRatio(Math.min(window.devicePixelRatio,2)),R.setSize(i.clientWidth,i.clientHeight),p.current=R,i.appendChild(R.domElement),o?.(R.domElement);const q=new ln(y,R.domElement);q.enableDamping=!h,q.dampingFactor=.08,q.maxPolarAngle=Math.PI*.44,q.autoRotate=!h,q.autoRotateSpeed=-.5;const U=new Ln(i);q.addEventListener("start",()=>{q.autoRotate=!1,U.hide()}),$.current=q;const de=new dn("#66779b","#161922",1.7);g.add(de);const ae=new un("#b6c5de",1.1);ae.position.set(-60,120,-40),g.add(ae);const le=18,F=new te,z=H=>{const N=I.current;if(!N||!j.current||!p.current)return;const _=p.current.domElement.getBoundingClientRect(),V=H.clientX-_.left,ee=H.clientY-_.top;let ce,fe=le*le;for(const Z of w.current){const ke=N.leaf.get(Z.id);if(!ke||(F.set(ke.x,Le,ke.z).project(j.current),F.z>1))continue;const ge=(F.x+1)/2*_.width,Me=(1-F.y)/2*_.height,Re=(ge-V)*(ge-V)+(Me-ee)*(Me-ee);Re<fe&&(fe=Re,ce=Z)}return ce};let D=null;const Y=H=>{D={x:H.clientX,y:H.clientY}},re=H=>{if(!D)return;const N=Math.hypot(H.clientX-D.x,H.clientY-D.y);D=null,!(N>5)&&a(z(H)?.path)};let W=0;const ue=H=>{if(D){U.hide();return}W||(W=requestAnimationFrame(()=>{W=0;const N=z(H);if(R.domElement.style.cursor=N?"pointer":"",!N){U.hide();return}const _=x.current,V=_.touchByPath.get(N.path),ee=_.visitsByFile.get(N.id)??0,ce=V?`${Xe(V)} · ${ee} visit${ee===1?"":"s"}`:Xe(void 0);U.show(N.path,N.ghost?`${ce} · ghost`:ce,H.clientX,H.clientY)}))},se=()=>{U.hide(),R.domElement.style.cursor=""};R.domElement.addEventListener("pointerdown",Y),R.domElement.addEventListener("pointerup",re),R.domElement.addEventListener("pointermove",ue),R.domElement.addEventListener("pointerleave",se);const xe=()=>{if(!l.current)return;const H=l.current.clientWidth,N=l.current.clientHeight;H===0||N===0||(R.setSize(H,N),y.aspect=H/N,y.updateProjectionMatrix(),k.current?.()&&(k.current=null))},je=new ResizeObserver(xe);je.observe(i);const X=new mn,J=new _e,he=new ze().setFromEuler(new ds(-Math.PI/2,0,0)),ie=()=>{q.update(),K.current?.updateTargets(y,R.domElement.clientWidth,R.domElement.clientHeight),K.current?.ease(A.current);const H=b.current,N=O.current,_=T.current,V=I.current;if(H&&V&&N.length>0){let ce=!1;for(let fe=0;fe<N.length;fe++){const Z=N[fe],ke=V.leaf.get(Z.fileId);if(!ke)continue;let ge=_.get(Z.fileId)??0;const Me=Z.target-ge;Math.abs(Me)>.015?(ge=A.current?Z.target:ge+Me*.12,_.set(Z.fileId,ge),ce=!0):ge!==Z.target&&(_.set(Z.fileId,Z.target),ge=Z.target,ce=!0),J.compose(new te(ke.x,.06,ke.z),he,new te(Math.max(ge,.01)*2,Math.max(ge,.01)*2,1)),H.setMatrixAt(fe,J)}ce&&(H.instanceMatrix.needsUpdate=!0)}const ee=ne.current;if(ee?.visible){const ce=X.getElapsedTime(),fe=ee.userData.baseScale,Z=A.current?1:1+.1*Math.sin(ce*2.4);ee.scale.setScalar(fe*Z)}R.render(g,y),G.current=requestAnimationFrame(ie)};return ie(),()=>{G.current&&cancelAnimationFrame(G.current),W&&cancelAnimationFrame(W),R.domElement.removeEventListener("pointerdown",Y),R.domElement.removeEventListener("pointerup",re),R.domElement.removeEventListener("pointermove",ue),R.domElement.removeEventListener("pointerleave",se),U.dispose(),je.disconnect(),q.dispose(),R.dispose(),i.removeChild(R.domElement),g.clear(),o?.(null)}},[a,o]),r.useEffect(()=>{const i=C.current;if(!i||(w.current=e?.files??[],I.current=E,O.current=[],T.current=new Map,!e||!E))return;const h=new hn,g=E.radius*2.3;i.fog=new fn(it,g*2.1,g*4.2);const y=new We(new wt(g*6,g*6),new nt({color:"#14171e",roughness:1}));y.rotation.x=-Math.PI/2,y.position.y=-.25,h.add(y);const R=new pn(g*2.4,40,"#1d222c","#181c25");R.material.transparent=!0,R.material.opacity=.4,R.position.y=-.24,h.add(R);const q=[],U=[];for(const N of E.edges){let _=0;for(let V=0;V<N.points.length-1;V++)q.push(N.points[V].x,.12,N.points[V].z),q.push(N.points[V+1].x,.12,N.points[V+1].z),_+=2;U.push({childPath:N.childPath,childFileId:N.childFileId,vertexCount:_})}const de=new nn;de.setAttribute("position",new us(q,3));const ae=new Float32Array(q.length);de.setAttribute("color",new rt(ae,3));const le=new rn(de,new sn({vertexColors:!0,transparent:!0,opacity:.9}));c.current=le,S.current=U,h.add(le);const F=new It(.5,10,8),z=new Be({toneMapped:!1,fog:!1}),D=new qe(F,z,e.files.length);D.instanceColor=new st(new Float32Array(e.files.length*3),3);const Y=e.files.filter(N=>N.ghost),re=new Map;Y.forEach((N,_)=>re.set(N.id,_)),v.current=re;const W=new _e,ue=new _e().makeScale(0,0,0);for(const N of e.files){const _=E.leaf.get(N.id);if(!_)continue;if(N.ghost){D.setMatrixAt(N.id,ue);continue}const V=Math.min(.24+Math.sqrt(Math.max(N.lines,1))*.045,1.05);W.compose(new te(_.x,Le,_.z),new ze,new te(V,V,V)),D.setMatrixAt(N.id,W),D.setColorAt(N.id,Ne.unvisited)}D.instanceMatrix.needsUpdate=!0,D.instanceColor&&(D.instanceColor.needsUpdate=!0),f.current=D,h.add(D);let se=null;if(Y.length>0){se=new qe(new It(.55,8,5),new Be({wireframe:!0,transparent:!0,opacity:.85,toneMapped:!1,fog:!1}),Y.length),se.instanceColor=new st(new Float32Array(Y.length*3),3);for(const N of Y){const _=E.leaf.get(N.id),V=re.get(N.id);if(!_){se.setMatrixAt(V,ue);continue}const ee=Math.min(.24+Math.sqrt(Math.max(N.lines,1))*.045,1.05)*.8;W.compose(new te(_.x,Le,_.z),new ze,new te(ee,ee,ee)),se.setMatrixAt(V,W),se.setColorAt(V,Ne.ghost)}se.instanceMatrix.needsUpdate=!0,se.instanceColor&&(se.instanceColor.needsUpdate=!0),se.raycast=()=>{},h.add(se)}m.current=se;const xe=new qe(new wt(1,1),new Be({map:Or(),transparent:!0,opacity:.55,depthWrite:!1,toneMapped:!1,fog:!1}),e.files.length);xe.instanceColor=new st(new Float32Array(e.files.length*3),3),xe.count=0,xe.frustumCulled=!1,xe.raycast=()=>{},b.current=xe,h.add(xe),K.current=new En(E.dirs,h,ia);const je=new ct(new Mt({map:Cn(),color:aa,blending:at,depthWrite:!1,transparent:!0,fog:!1}));je.userData.baseScale=Math.max(g*.026,2.2),je.visible=!1,ne.current=je,h.add(je);const X=new Be({color:Ne.selected,transparent:!0,opacity:.9,side:hs,depthWrite:!1,toneMapped:!1,fog:!1}),J=new We(new fs(1.2,1.5,48),X);J.rotation.x=-Math.PI/2,J.visible=!1,J.raycast=()=>{},h.add(J);const he=new We(new ps(.05,.05,6,6,1,!0),new Be({color:Ne.selected,transparent:!0,opacity:.32,blending:at,depthWrite:!1,toneMapped:!1,fog:!1}));he.visible=!1,he.raycast=()=>{},h.add(he),d.current={ring:J,beam:he};const ie=new zn(1.6);P.current=ie,h.add(ie.object),L.current=h,i.add(h);const H=()=>{const N=j.current,_=$.current;if(!N||!_)return!0;const V=new te(.3,.66,.47).normalize(),ee=[...E.leaf.values()].map(Z=>new te(Z.x,Le,Z.z)),ce=$n(N,V,ee);if(ce===null)return!1;const fe=ce*1.12;return N.position.copy(V).multiplyScalar(fe),_.target.set(0,0,0),_.minDistance=g*.15,_.maxDistance=Math.max(g*2.4,fe*1.2),_.update(),!0};return k.current=H()?null:H,()=>{k.current=null,In(h),i.remove(h),L.current=null,f.current=null,m.current=null,v.current=new Map,d.current=null,b.current=null,c.current=null,P.current=null,ne.current=null,K.current=null}},[e,E]),r.useEffect(()=>{const i=f.current,h=m.current,g=v.current,y=b.current,R=c.current;if(!i||!y||!R||!e||!E)return;const q=T.current,U=[],de=new Set,ae=new Set;for(const z of e.files){const D=n.touchByFile.get(z.id);let Y=z.ghost?Ne.ghost:Ne.unvisited;if(D){Y=Ne[D];const re=n.visitsByFile.get(z.id)??1;U.push({fileId:z.id,target:oa(re),color:Ne[D]}),de.add(z.id);const W=z.path.split("/");let ue="";for(let se=0;se<W.length-1;se++)ue=ue?`${ue}/${W[se]}`:W[se],ae.add(ue)}if(z.ghost){const re=g.get(z.id);h&&re!==void 0&&h.setColorAt(re,Y)}else i.setColorAt(z.id,Y)}for(const[z,D]of q)D>.04&&!de.has(z)?U.push({fileId:z,target:0,color:Ne.unvisited}):D<=.04&&!de.has(z)&&q.delete(z);U.forEach((z,D)=>y.setColorAt(D,z.color)),y.count=U.length,y.instanceColor&&(y.instanceColor.needsUpdate=!0),i.instanceColor&&(i.instanceColor.needsUpdate=!0),h?.instanceColor&&(h.instanceColor.needsUpdate=!0),O.current=U;const le=R.geometry.getAttribute("color");let F=0;for(const z of S.current){let D=!1;z.childFileId!==void 0?D=n.touchByFile.has(z.childFileId):z.childPath&&(D=ae.has(z.childPath));const Y=D?ra:sa;for(let re=0;re<z.vertexCount;re++)le.setXYZ(F++,Y.r,Y.g,Y.b)}le.needsUpdate=!0},[e,E,n]),r.useEffect(()=>{const i=d.current;if(!i||!e||!E)return;const h=s?e.files.find(y=>y.path===s):void 0,g=h?E.leaf.get(h.id):void 0;if(g){i.ring.position.set(g.x,.1,g.z),i.beam.position.set(g.x,3,g.z),i.ring.visible=!0,i.beam.visible=!0;const y=j.current,R=$.current,q=p.current?.domElement;y&&R&&q&&(R.autoRotate=!1,An(y,R,new te(g.x,Le,g.z),q.clientWidth,q.clientHeight,ca))}else i.ring.visible=!1,i.beam.visible=!1},[e,E,s]),r.useEffect(()=>{const i=P.current;if(!i||!e||!E)return;const h=n.recentTargets.map(y=>y.fileId!==void 0?e.files[y.fileId]:void 0).filter(y=>!!(y&&E.leaf.get(y.id))),g=ne.current;if(g){const y=h[h.length-1];if(y){const R=E.leaf.get(y.id);g.position.set(R.x,Le+1.7,R.z),g.visible=!0}else g.visible=!1}i.update(h.map(y=>{const R=E.leaf.get(y.id);return new te(R.x,Le+.3,R.z)}))},[e,E,n]),t.jsx("div",{className:"city-scene",ref:l,"aria-label":"Firefly tree"})}const Tn="mindwalk.sessionFilters";function Fn(e,n,s){return!(n.harness&&e.harness!==n.harness||n.hideEmpty&&e.eventCount===0&&e.key!==s)}function da(){try{const e=localStorage.getItem(Tn);if(e){const n=JSON.parse(e);return{hideEmpty:n.hideEmpty!==!1,harness:typeof n.harness=="string"?n.harness:void 0}}}catch{}return{hideEmpty:!0}}function Ut(e){try{localStorage.setItem(Tn,JSON.stringify(e))}catch{}}const Vt=e=>{let n;const s=new Set,a=(d,b)=>{const c=typeof d=="function"?d(n):d;if(!Object.is(c,n)){const S=n;n=b??(typeof c!="object"||c===null)?c:Object.assign({},n,c),s.forEach(w=>w(n,S))}},o=()=>n,m={setState:a,getState:o,getInitialState:()=>v,subscribe:d=>(s.add(d),()=>s.delete(d))},v=n=e(a,o,m);return m},ua=(e=>e?Vt(e):Vt),ha=e=>e;function fa(e,n=ha){const s=Qe.useSyncExternalStore(e.subscribe,Qe.useCallback(()=>n(e.getState()),[e,n]),Qe.useCallback(()=>n(e.getInitialState()),[e,n]));return Qe.useDebugValue(s),s}const Gt=e=>{const n=ua(e),s=a=>fa(n,a);return Object.assign(s,n),s},pa=(e=>e?Gt(e):Gt),Kt=da(),Bn="mindwalk.railCollapsed";function ma(){try{return localStorage.getItem(Bn)==="1"}catch{return!1}}const Pe=pa((e,n)=>({sessions:[],currentSeq:0,view:"terrain",loading:!1,hideEmpty:Kt.hideEmpty,harnessFilter:Kt.harness,railCollapsed:ma(),mapOnly:!1,setView:s=>e({view:s}),setSessions:s=>e({sessions:s}),setActiveSession:s=>e({activeSessionKey:s,trace:void 0,city:void 0,currentSeq:0,selectedPath:void 0}),setData:(s,a)=>e({trace:s,city:a,currentSeq:Math.max(0,s.events.length-1)}),setCityOnly:s=>e({city:s,trace:void 0,currentSeq:0,selectedPath:void 0,mapOnly:!0}),setCurrentSeq:s=>e({currentSeq:s}),setSelectedPath:s=>e({selectedPath:s}),setLoading:s=>e({loading:s}),setError:s=>e({error:s}),setHideEmpty:s=>{e({hideEmpty:s}),Ut({hideEmpty:s,harness:n().harnessFilter})},setHarnessFilter:s=>{e({harnessFilter:s}),Ut({hideEmpty:n().hideEmpty,harness:s})},setRailCollapsed:s=>{e({railCollapsed:s});try{localStorage.setItem(Bn,s?"1":"0")}catch{}}})),yt=8,ga=r.memo(function({trace:n,city:s,agentLabel:a,editedNow:o,readNow:l,seenNow:f,churn:m,onSelectFile:v,onOpenAgents:d,locked:b=!1}){const c=n?.stats,S=c?c.fovea-c.edited:0,w=c?Math.max(0,c.filesInRepo-o-l-f):0,I=c?Math.max(0,c.filesInRepo-c.fovea-c.parafovea):0,O=s?s.files.reduce((P,ne)=>P+(ne.ghost?1:0),0):0,T=c?Xt(c.errors):0,p=c?T>0||c.churnFiles>0||c.actions.edit>0:!1,[j,$]=r.useState(!1),C=r.useRef(null),L=r.useRef(null);return r.useEffect(()=>$(!1),[n]),r.useEffect(()=>{if(!j)return;const P=K=>{const G=K.target;C.current?.contains(G)||L.current?.contains(G)||$(!1)},ne=K=>{K.key==="Escape"&&$(!1)};return document.addEventListener("pointerdown",P),document.addEventListener("keydown",ne),()=>{document.removeEventListener("pointerdown",P),document.removeEventListener("keydown",ne)}},[j]),t.jsx("div",{className:"hud","aria-hidden":!s,children:t.jsxs("div",{className:"hud-left",children:[t.jsxs("div",{className:"hud-title-line",children:[t.jsx("div",{className:"hud-repo",children:s?ba(s.repo.root):""}),n&&a?t.jsxs("button",{className:"hud-lens",onClick:d,disabled:!d||b,"aria-label":`Open Agent lenses, current ${a}`,children:[t.jsx("span",{children:"Lens"}),a]}):null]}),s?t.jsxs("div",{className:"hud-commit",children:[t.jsx("span",{children:s.repo.commit||"worktree"}),s.repo.dirty?t.jsx("span",{className:"dirty",children:"● dirty"}):null,n?.session.model?t.jsx("span",{children:n.session.model}):null,c?t.jsxs("span",{"data-hint":"Files in the repository map — the denominator of the coverage spectrum below",children:[c.filesInRepo," files"]}):null,s.repo.truncated?t.jsx("span",{"data-hint":"The tree holds more files than the map shows — scanning stopped at the budget",children:"partial map"}):null]}):null,c?t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"spectrum",children:[t.jsx(Ke,{kind:"edit",label:"edited",now:o,final:c.edited,hint:"Files the agent changed"}),t.jsx(Ke,{kind:"read",label:"read",now:l,final:S,hint:"Files the agent opened and read, but never changed"}),t.jsx(Ke,{kind:"hit",label:"seen",now:f,final:c.parafovea,hint:"Files that only appeared in search results, never opened"}),t.jsx(Ke,{kind:"unvisited",label:"unvisited",now:w,final:I,hint:"Files in the map the agent never touched"}),O>0?t.jsx(Ke,{kind:"ghost",label:"ghost",now:O,final:O,hint:"Files the session touched that are gone from the repository — drawn hollow in the scene"}):null]}),t.jsxs("div",{className:"hud-quiet",children:[t.jsxs("span",{"data-hint":`Tool calls — ${Jt(c.actions)}`,children:[Xt(c.actions)," calls"]}),t.jsxs("span",{"data-hint":"User messages — each one starts a turn of agent work",children:[c.userTurns," turns"]}),c.subagents>0?t.jsxs("button",{className:"hud-agent-link","data-hint":"Subagent launches (Task/Agent) — open Agent lenses",onClick:d,disabled:!d||b,"aria-label":`Open ${c.subagents} subagent${c.subagents===1?"":"s"} in Agent lenses`,children:[c.subagents," subagent",c.subagents===1?"":"s"]}):null,c.compactions>0?t.jsxs("span",{"data-hint":"Context compactions — the conversation was summarized to free memory",children:[c.compactions," compaction",c.compactions===1?"":"s"]}):null,t.jsxs("span",{"data-hint":"Tool output the agent consumed over the session",children:[wa(c.resultBytes)," output"]}),t.jsx("span",{"data-hint":va(c.observability.reads),children:c.observability.reads==="unavailable"?"re-reads n/a":`re-reads ${Wt(c.observability.reads)}${xa(c.regressionRate)}`})]}),p?t.jsxs("div",{className:"hud-review",children:[t.jsx("span",{className:"review-label",children:"review"}),T>0?t.jsxs("span",{className:"warn","data-hint":`${Jt(c.errors)} — press X to jump to the next one${ya(c.observability.errors)}`,children:[Wt(c.observability.errors),T," error",T===1?"":"s"]}):null,c.churnFiles>0?t.jsxs("button",{ref:L,className:j?"warn churn-toggle open":"warn churn-toggle","aria-expanded":j,onClick:()=>$(P=>!P),"data-hint":`Files edited in three or more separate events — the most-edited file changed ${c.maxEditsPerFile} times. Click to list them.`,children:[c.churnFiles," file",c.churnFiles===1?"":"s"," edited 3+ times"]}):null,c.actions.edit>0?c.actions.verify===0?t.jsx("span",{className:"warn","data-hint":"The session edited files but no build or test commands were recognized (go test, make test, npm run build, …)",children:"never verified"}):c.editsAfterLastVerify>0?t.jsxs("span",{className:"warn","data-hint":`Edit events after the session's last build or test run — ${Yt(c.actions.verify)} total; pass/fail is not tracked`,children:[c.editsAfterLastVerify," edit",c.editsAfterLastVerify===1?"":"s"," after last verify"]}):t.jsx("span",{className:"ok","data-hint":`The last edit was followed by a build or test run — ${Yt(c.actions.verify)} total; pass/fail is not tracked`,children:"verified after final edit"}):null]}):null,j?t.jsxs("div",{className:"churn-panel",ref:C,children:[m.slice(0,yt).map(P=>t.jsxs("button",{className:"churn-row",onClick:()=>{v(P.path),$(!1)},children:[t.jsx("span",{className:"churn-path",children:P.path}),t.jsxs("span",{className:"churn-count",children:[P.edits," edit",P.edits===1?"":"s"]})]},P.path)),m.length>yt?t.jsxs("p",{className:"churn-more",children:["…and ",m.length-yt," more"]}):null]}):null]}):null]})})});function Ke({kind:e,label:n,now:s,final:a,hint:o}){return t.jsxs("div",{className:"spectrum-stat","data-hint":o,children:[t.jsx("span",{className:`legend-dot ${e}`}),t.jsx("span",{className:"spectrum-label",children:n}),t.jsx("strong",{children:s===a?a:`${s} → ${a}`})]})}function xa(e){return`${Math.round(e*100)}%`}function Wt(e){return e==="estimated"?"~":""}function Yt(e){return`${e} verify run${e===1?"":"s"}`}function va(e){switch(e){case"unavailable":return"No file reads observed — this session reads files through commands Synapse could not recognize";case"estimated":return"Reads that re-read a file unchanged since its last read — inferred from shell commands, so the rate is approximate";default:return"Reads that re-read a file unchanged since its last read"}}function ya(e){return e==="estimated"?" — inferred from command output; failures inside scripted calls may be missed":""}const _n=["search","read","edit","exec","verify","other"];function Xt(e){return _n.reduce((n,s)=>n+e[s],0)}function Jt(e){const n=_n.filter(s=>e[s]>0).map(s=>`${e[s]} ${s}`);return n.length?n.join(" · "):"none"}function wa(e){const n=e/1024;return n<1?`${e} B`:n<1e3?`${Math.round(n)} KB`:`${(n/1024).toFixed(1)} MB`}function ba(e){const n=e.replace(/\/+$/,"");return n.slice(n.lastIndexOf("/")+1)}function ja({file:e,touch:n,history:s,onClose:a,onJumpTo:o,locked:l=!1}){if(!e)return t.jsxs("div",{className:"dock-body","aria-label":"File inspector",children:[t.jsxs("div",{className:"inspector-head",children:[t.jsx("div",{className:"inspector-path",children:"Inspect"}),t.jsx("button",{className:"icon-btn",onClick:a,title:"Close","aria-label":"Close inspector",children:t.jsx(Ye,{size:15})})]}),t.jsx("p",{className:"dock-note",children:"Click a building in the scene to inspect a file — its touch state, size, and every visit the agent paid it."})]});const f=e.path.lastIndexOf("/"),m=f>=0?e.path.slice(0,f+1):"",v=f>=0?e.path.slice(f+1):e.path;return t.jsxs("div",{className:"dock-body","aria-label":`File ${e.path}`,children:[t.jsxs("div",{className:"inspector-head",children:[t.jsxs("div",{children:[t.jsxs("div",{className:"inspector-path",children:[t.jsx("span",{className:"dir",children:m}),v]}),e.ghost?t.jsx("span",{className:"ghost-badge",children:"ghost — not in this tree"}):null]}),t.jsx("button",{className:"icon-btn",onClick:a,title:"Close","aria-label":"Close inspector",children:t.jsx(Ye,{size:15})})]}),t.jsxs("dl",{className:"inspector-facts",children:[t.jsxs("div",{children:[t.jsx("dt",{children:"Touch"}),t.jsx("dd",{className:n?`touch-${n}`:void 0,children:Xe(n)})]}),t.jsxs("div",{children:[t.jsx("dt",{children:"Lang"}),t.jsx("dd",{children:e.lang||"text"})]}),t.jsxs("div",{children:[t.jsx("dt",{children:"Lines"}),t.jsx("dd",{children:e.lines.toLocaleString()})]}),t.jsxs("div",{children:[t.jsx("dt",{children:"Bytes"}),t.jsx("dd",{children:e.bytes.toLocaleString()})]})]}),t.jsxs("section",{className:"inspector-history",children:[t.jsxs("p",{className:"eyebrow",children:["Visits · ",s.length]}),t.jsxs("div",{className:"history-list",children:[s.slice(-14).reverse().map(d=>t.jsxs("button",{className:"history-row",onClick:()=>o(d.seq),disabled:l,title:`Jump to step ${d.seq+1} — ${d.summary}`,children:[t.jsx("span",{className:`action-dot ${d.action}`}),t.jsxs("strong",{children:["#",d.seq+1]}),t.jsx("span",{children:d.tool}),t.jsx("span",{className:"history-time",children:d.ts?Ma(d.ts):""}),d.isError?t.jsx(Ct,{className:"history-err",size:13}):t.jsx("span",{})]},d.seq)),s.length===0?t.jsx("p",{className:"muted",children:"Not visited yet at this point of the walk. Scrub the timeline forward."}):null]})]})]})}function Ma(e){const n=new Date(e);return Number.isNaN(n.getTime())?"":[n.getHours(),n.getMinutes(),n.getSeconds()].map(s=>String(s).padStart(2,"0")).join(":")}function ka({size:e=22}){return t.jsxs("svg",{viewBox:"0 0 64 64",width:e,height:e,"aria-hidden":!0,focusable:"false",children:[t.jsx("defs",{children:t.jsxs("radialGradient",{id:"logo-halo",children:[t.jsx("stop",{offset:"0%",stopColor:"#f1aa57",stopOpacity:"0.55"}),t.jsx("stop",{offset:"100%",stopColor:"#f1aa57",stopOpacity:"0"})]})}),t.jsx("rect",{width:"64",height:"64",rx:"14",fill:"#0f141b"}),t.jsx("circle",{cx:"20",cy:"15",r:"1.6",fill:"#3b4047"}),t.jsx("circle",{cx:"11",cy:"27",r:"1.4",fill:"#3b4047"}),t.jsx("circle",{cx:"51",cy:"40",r:"1.6",fill:"#3b4047"}),t.jsx("circle",{cx:"34",cy:"53",r:"1.4",fill:"#3b4047"}),t.jsxs("g",{fill:"#f1aa57",children:[t.jsx("circle",{cx:"18.6",cy:"47.9",r:"1.15",opacity:"0.35"}),t.jsx("circle",{cx:"22.7",cy:"45.2",r:"1.25",opacity:"0.42"}),t.jsx("circle",{cx:"25.9",cy:"42",r:"1.35",opacity:"0.49"}),t.jsx("circle",{cx:"28.2",cy:"38.1",r:"1.45",opacity:"0.56"}),t.jsx("circle",{cx:"30.9",cy:"29.3",r:"1.55",opacity:"0.64"}),t.jsx("circle",{cx:"33",cy:"25.4",r:"1.65",opacity:"0.72"}),t.jsx("circle",{cx:"36",cy:"22.1",r:"1.75",opacity:"0.8"}),t.jsx("circle",{cx:"38",cy:"20.4",r:"1.85",opacity:"0.88"})]}),t.jsx("circle",{cx:"13",cy:"50",r:"4.5",fill:"#9fc67b",opacity:"0.16"}),t.jsx("circle",{cx:"13",cy:"50",r:"2.4",fill:"#9fc67b"}),t.jsx("circle",{cx:"29.5",cy:"34",r:"5",fill:"#b6daf1",opacity:"0.16"}),t.jsx("circle",{cx:"29.5",cy:"34",r:"2.7",fill:"#b6daf1"}),t.jsx("circle",{cx:"44",cy:"17.5",r:"9.5",fill:"url(#logo-halo)"}),t.jsx("circle",{cx:"44",cy:"17.5",r:"3.4",fill:"#f1aa57"}),t.jsx("circle",{cx:"44",cy:"17.5",r:"1.7",fill:"#ffe0b0"})]})}const Na=typeof navigator<"u"&&/Mac|iPhone|iPad/.test(navigator.platform),qn=Na?"⌘B":"Ctrl+B",Ca=r.memo(function({sessions:n,activeKey:s,loading:a,hideEmpty:o,harnessFilter:l,collapsed:f,onSelect:m,onRefresh:v,onHideEmptyChange:d,onHarnessFilterChange:b,onCollapse:c,onOpenMap:S,activeRepo:w,locked:I=!1,activeReportState:O}){const[T,p]=r.useState(""),[j,$]=r.useState(""),[C,L]=r.useState(!1),P=r.useRef(null);r.useEffect(()=>{if(!C)return;const x=E=>{P.current?.contains(E.target)||L(!1)},k=E=>{E.key==="Escape"&&L(!1)};return document.addEventListener("pointerdown",x),document.addEventListener("keydown",k),()=>{document.removeEventListener("pointerdown",x),document.removeEventListener("keydown",k)}},[C]);const ne=r.useMemo(()=>[...new Set(n.map(x=>x.harness))].sort(),[n]),K=r.useMemo(()=>n.filter(x=>x.eventCount===0).length,[n]),G=l&&ne.includes(l)?l:void 0,A=r.useMemo(()=>{const x=T.trim().toLowerCase();return n.filter(k=>Fn(k,{hideEmpty:o,harness:G},s)?x?`${k.title??""} ${k.id} ${k.gitBranch??""} ${k.harness}`.toLowerCase().includes(x):!0:!1)},[n,T,o,G,s]);return t.jsxs("aside",{className:f?"session-rail collapsed":"session-rail",children:[t.jsxs("div",{className:"rail-head",children:[t.jsxs("h1",{className:"wordmark",children:[t.jsx(ka,{}),t.jsxs("span",{children:["Synapse",t.jsx("span",{className:"spark",children:"."})]})]}),t.jsxs("div",{className:"rail-head-actions",children:[t.jsxs("div",{className:"rail-map",ref:P,children:[t.jsx("button",{className:"icon-btn",onClick:()=>L(x=>!x),"aria-expanded":C,title:"Open a repository map","aria-label":"Open a repository map",children:t.jsx(Tt,{size:15})}),C?t.jsxs("div",{className:"rail-map-pop",children:[w?t.jsxs("button",{className:"rail-map-primary",onClick:()=>{S(w),L(!1)},title:`Open the map of ${w}`,children:[t.jsx(Tt,{size:14,"aria-hidden":!0}),t.jsxs("span",{className:"rail-map-primary-text",children:[t.jsx("span",{className:"rail-map-primary-name",children:Ea(w)}),t.jsx("span",{className:"rail-map-primary-path",children:"‎"+w})]})]}):null,w?t.jsx("div",{className:"rail-map-divider","aria-hidden":!0,children:t.jsx("span",{children:"or open any repository"})}):t.jsx("p",{className:"rail-map-label",children:"Open a repository map"}),t.jsxs("form",{className:"rail-map-form",onSubmit:x=>{x.preventDefault();const k=j.trim();k&&(S(k),L(!1))},children:[t.jsx("input",{type:"text",className:"rail-map-input",placeholder:"/path/to/repo",value:j,onChange:x=>$(x.currentTarget.value),spellCheck:!1}),t.jsx("button",{type:"submit",className:"rail-map-go",disabled:j.trim()==="",children:"Open"})]})]}):null]}),t.jsx("button",{className:"icon-btn",onClick:v,disabled:I,title:"Rescan sessions","aria-label":"Rescan sessions",children:t.jsx(ot,{size:15})}),t.jsx("button",{className:"icon-btn",onClick:c,title:`Hide sidebar (${qn})`,"aria-label":"Hide session sidebar",children:t.jsx(Bs,{size:15})})]})]}),t.jsxs("div",{className:"rail-controls",children:[t.jsxs("label",{className:"rail-filter",children:[t.jsx(Ys,{size:14,"aria-hidden":!0}),t.jsx("input",{type:"search",placeholder:"Filter sessions",value:T,onChange:x=>p(x.currentTarget.value),"aria-label":"Filter sessions"})]}),ne.length>1||K>0?t.jsxs("div",{className:"rail-chips",role:"group","aria-label":"Session filters",children:[ne.length>1?t.jsxs(t.Fragment,{children:[t.jsx("button",{className:G===void 0?"chip active":"chip",onClick:()=>b(void 0),children:"all"}),ne.map(x=>t.jsx("button",{className:G===x?"chip active":"chip",onClick:()=>b(x),children:Qt(x)},x))]}):null,K>0?t.jsx("button",{className:o?"eye-toggle":"eye-toggle showing",onClick:()=>d(!o),"aria-pressed":!o,title:o?`Show ${K} empty sessions`:`Hide ${K} empty sessions`,"aria-label":o?`Show ${K} empty sessions`:`Hide ${K} empty sessions`,children:o?t.jsx(Ss,{size:13,"aria-hidden":!0}):t.jsx(As,{size:13,"aria-hidden":!0})}):null]}):null]}),t.jsxs("div",{className:"session-list","aria-busy":a,children:[A.map(x=>t.jsxs("button",{className:x.key===s?"session-row active":"session-row",onClick:()=>m(x.key),disabled:I,children:[t.jsx("span",{className:"session-title",children:x.title||x.id}),t.jsxs("span",{className:"session-meta",children:[t.jsxs("span",{className:"session-meta-text",children:[Qt(x.harness)," · ",x.eventCount," ",x.eventCount===1?"call":"calls",x.gitBranch?` · ${x.gitBranch}`:"",x.endedAt?` · ${Ra(x.endedAt)}`:""]}),(()=>{const k=x.key===s&&O!==void 0?O:x.reportState;return k?t.jsx("span",{className:`rail-eval rail-eval-${k}`,title:Zt(k),"aria-label":Zt(k),children:k==="running"?"evaluating":""}):null})()]})]},x.key)),A.length===0?t.jsx("p",{className:"muted",style:{padding:"10px 8px"},children:a&&n.length===0?"Scanning sessions…":"No matching sessions."}):null]}),t.jsx("div",{className:"rail-foot",children:A.length===n.length?`${n.length} session${n.length===1?"":"s"}`:`${A.length} of ${n.length} sessions`})]})});function Ea(e){const n=e.replace(/\/+$/,"");return n.slice(n.lastIndexOf("/")+1)||n}function Zt(e){switch(e){case"running":return"Evaluation in progress";case"done":return"Evaluation ready";case"stale":return"Evaluation ready, but the session has grown since";case"failed":return"Last evaluation failed"}}function Qt(e){return e==="claude-code"?"claude":e}function Ra(e){const n=new Date(e);if(Number.isNaN(n.getTime()))return"";const s=new Date,a=n.getFullYear()===s.getFullYear(),o=`${String(n.getMonth()+1).padStart(2,"0")}-${String(n.getDate()).padStart(2,"0")}`,l=`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`;return a?`${o} ${l}`:`${n.getFullYear()}-${o}`}const Sa=160,en=340,tt=[1,4,16],$a=220,tn={compaction:"context compaction","user-message":"user message",subagent:"subagent"},Aa=["search","read","edit","verify","exec"];function La({trace:e,currentSeq:n,onChange:s,onSubagentMark:a,onExport:o,exporting:l=!1}){const[f,m]=r.useState(!1),[v,d]=r.useState(1),[b,c]=r.useState(!1),S=r.useRef(null),w=e?.events.length??0,I=Math.max(0,w-1),O=Math.min(n,I),T=e?.events[O];r.useEffect(()=>{m(!1)},[e]),r.useEffect(()=>{l&&m(!1)},[l]);const p=r.useRef(O),j=r.useRef(I),$=r.useRef(f);p.current=O,j.current=I,$.current=f,r.useEffect(()=>{if(!f||w===0||l)return;const i=Math.max(85,en/v),h=Math.max(1,Math.round(v*i/en)),g=window.setInterval(()=>{if(p.current>=j.current){m(!1);return}s(Math.min(p.current+h,j.current))},i);return()=>window.clearInterval(g)},[f,v,w,s,l]);const C=r.useCallback(()=>{!$.current&&p.current>=j.current&&s(0),m(i=>!i)},[s]),L=r.useCallback(()=>{d(i=>tt[(tt.indexOf(i)+1)%tt.length])},[]),P=r.useCallback(i=>{s(Math.min(j.current,Math.max(0,p.current+i)))},[s]),ne=r.useCallback((i,h)=>{if(e){for(let g=p.current+i;g>=0&&g<e.events.length;g+=i)if(h(e.events[g])){s(g);return}}},[e,s]),K=r.useMemo(()=>{const i=(e?.marks??[]).map(h=>Math.min(h.seq,Math.max(0,(e?.events.length??1)-1)));return[...new Set(i)].sort((h,g)=>h-g)},[e]),G=r.useCallback(i=>{const h=p.current,g=i===1?K.find(y=>y>h):[...K].reverse().find(y=>y<h);g!==void 0&&s(g)},[K,s]);r.useEffect(()=>{if(!e||l)return;const i=h=>{if(!(h.metaKey||h.ctrlKey||h.altKey||h.target?.closest("input, textarea, select, button, [contenteditable]"))){switch(h.key){case" ":h.preventDefault(),C();return;case"ArrowLeft":h.preventDefault(),P(h.shiftKey?-10:-1);return;case"ArrowRight":h.preventDefault(),P(h.shiftKey?10:1);return;case"Home":h.preventDefault(),s(0);return;case"End":h.preventDefault(),s(j.current);return}switch(h.key.toLowerCase()){case"s":L();return;case"e":ne(h.shiftKey?-1:1,y=>y.action==="edit");return;case"x":ne(h.shiftKey?-1:1,y=>y.isError);return;case"m":G(h.shiftKey?-1:1);return}}};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[e,l,C,P,s,L,ne,G]);const A=w===0||l;r.useEffect(()=>{A&&c(!1)},[A]),r.useEffect(()=>{if(!b)return;const i=g=>{S.current?.contains(g.target)||c(!1)},h=g=>{g.key==="Escape"&&c(!1)};return window.addEventListener("pointerdown",i),window.addEventListener("keydown",h),()=>{window.removeEventListener("pointerdown",i),window.removeEventListener("keydown",h)}},[b]);const x=r.useMemo(()=>{if(!e||w===0)return[];const i=Math.min(Sa,w),h=[];for(let g=0;g<i;g++){const y=Math.floor(g*w/i),R=Math.floor((g+1)*w/i),q=new Map;for(let le=y;le<R;le++){const F=e.events[le].action;q.set(F,(q.get(F)??0)+1)}let U="other",de=-1;const ae=["edit","verify","read","search","exec","other"];for(const le of ae){const F=q.get(le)??0;F>de&&(de=F,U=le)}h.push({count:R-y,dominant:U})}return h},[e,w]),k=r.useMemo(()=>x.reduce((i,h)=>Math.max(i,h.count),1),[x]),E=r.useMemo(()=>{if(!e)return[];const i=new Map;for(const h of e.marks){const g=Math.min(h.seq,I),y=I>0?g/I:0,R=`${h.type}:${Math.round(y*$a)}`,q=i.get(R);q?(q.count++,q.seq=Math.min(q.seq,g)):i.set(R,{type:h.type,seq:g,pos:y,count:1,note:h.note})}return[...i.values()]},[e,I]);return t.jsxs("footer",{className:"deck",children:[t.jsxs("div",{className:"deck-main",children:[t.jsxs("div",{className:"strip",children:[t.jsx("div",{className:"strip-marks",children:E.map((i,h)=>t.jsx("button",{type:"button",className:`strip-mark ${i.type}`,style:{left:`${i.pos*100}%`},disabled:A,title:`${i.note||tn[i.type]}${i.count>1?` ×${i.count}`:""}`,"aria-label":`Jump to ${i.note||tn[i.type]} at event ${i.seq+1}${i.count>1?`, ${i.count} marks`:""}`,onClick:()=>i.type==="subagent"&&a?a(i.seq):s(i.seq)},`${i.type}-${i.seq}-${h}`))}),t.jsx("div",{className:"strip-bars","aria-hidden":!0,children:x.map((i,h)=>t.jsx("span",{className:`strip-bar ${i.dominant}`,style:{height:`${18+i.count/k*82}%`}},h))}),w>0?t.jsx("div",{className:"strip-playhead",style:{left:`${O/Math.max(I,1)*100}%`},"aria-hidden":!0}):null,t.jsx("input",{className:"strip-input",type:"range",min:0,max:I,value:O,disabled:A,onChange:i=>s(Number(i.currentTarget.value)),"aria-label":"Playback position","aria-valuetext":T?`event ${T.seq}: ${T.tool}`:"empty"})]}),t.jsxs("div",{className:"deck-pos",children:[t.jsx("span",{className:"deck-pos-count",style:{minWidth:`${String(Math.max(w,1)).length*2+3}ch`},children:w>0?`${O+1} / ${w}`:"0 / 0"}),t.jsx("span",{className:"deck-pos-clock",children:T?.ts?Pa(T.ts):"—"})]}),t.jsxs("div",{className:"transport",children:[t.jsx("button",{className:"icon-btn",onClick:()=>P(-1),disabled:A,title:"Step back (←)","aria-label":"Step back one event",children:t.jsx(Zs,{size:15})}),t.jsx("button",{className:"play-btn",onClick:C,disabled:A,title:f?"Pause (Space)":"Play (Space)","aria-label":f?"Pause playback":"Play playback",children:f?t.jsx(Os,{size:16}):t.jsx(Us,{size:16,className:"play-glyph"})}),t.jsx("button",{className:"icon-btn",onClick:()=>P(1),disabled:A,title:"Step forward (→)","aria-label":"Step forward one event",children:t.jsx(er,{size:15})}),t.jsxs("div",{className:"transport-more",ref:S,children:[t.jsx("button",{className:`icon-btn${l?" recording":""}${b?" open":""}`,onClick:()=>c(i=>!i),disabled:A,"aria-haspopup":"true","aria-expanded":b,title:"More controls","aria-label":"More playback controls",children:l?t.jsx(Nt,{size:15,className:"spin"}):v!==1?t.jsxs("span",{className:"more-speed",children:[v,"×"]}):t.jsx(Es,{size:15})}),b?t.jsxs("div",{className:"transport-pop",children:[t.jsxs("div",{className:"pop-speed",children:[t.jsx("span",{className:"pop-speed-label",children:"Speed"}),t.jsx("div",{className:"pop-speed-chips",title:"Cycle with S",children:tt.map(i=>t.jsxs("button",{className:i===v?"pop-chip engaged":"pop-chip",onClick:()=>d(i),"aria-pressed":i===v,children:[i,"×"]},i))})]}),t.jsxs("button",{className:"pop-item",onClick:()=>{s(0),c(!1)},children:[t.jsx(Ks,{size:14}),t.jsx("span",{children:"Restart"}),t.jsx("kbd",{children:"Home"})]}),o?t.jsxs("button",{className:"pop-item",onClick:()=>{c(!1),o()},children:[t.jsx(or,{size:14}),t.jsx("span",{children:"Export video"})]}):null]}):null]})]})]}),t.jsxs("div",{className:"deck-foot",children:[t.jsx("div",{className:"readout-now",children:T?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:`action-dot ${T.action}`}),t.jsx("span",{className:"readout-tool",children:T.tool}),T.isError?t.jsx("span",{className:"err",children:"error"}):null,t.jsx("span",{className:"readout-summary",title:T.summary,children:T.summary})]}):t.jsx("span",{className:"readout-summary",children:e?"No recorded activity for this agent.":"Select a session to start the walk."})}),t.jsxs("div",{className:"deck-legend","aria-hidden":!0,children:[t.jsx("span",{className:"legend-group",children:Aa.map(i=>t.jsxs("span",{className:"legend-item",children:[t.jsx("span",{className:`action-dot ${i}`}),i]},i))}),t.jsxs("span",{className:"legend-group",children:[t.jsxs("span",{className:"legend-item",children:[t.jsx("span",{className:"legend-glyph compaction"}),"compaction"]}),t.jsxs("span",{className:"legend-item",children:[t.jsx("span",{className:"legend-glyph subagent"}),"subagent"]}),t.jsxs("span",{className:"legend-item",children:[t.jsx("span",{className:"legend-glyph user-message"}),"user turn"]})]})]})]})]})}function Pa(e){const n=new Date(e);return Number.isNaN(n.getTime())?"":[n.getHours(),n.getMinutes(),n.getSeconds()].map(s=>String(s).padStart(2,"0")).join(":")}function Ia(e){switch(e){case"running":return"The judge is reading the trace — about a minute";case"done":return"Evaluation ready";case"stale":return"Evaluation ready, but the session has grown since";case"failed":return"The last evaluation failed — open to retry";default:return"Evaluate this session with your local agent CLI"}}const Ie="__main__";function za(){const{sessions:e,activeSessionKey:n,trace:s,city:a,currentSeq:o,selectedPath:l,view:f,loading:m,error:v,hideEmpty:d,harnessFilter:b,railCollapsed:c,mapOnly:S,setView:w,setSessions:I,setActiveSession:O,setData:T,setCityOnly:p,setCurrentSeq:j,setSelectedPath:$,setLoading:C,setError:L,setHideEmpty:P,setHarnessFilter:ne,setRailCollapsed:K}=Pe(),G=r.useRef(!1),A=r.useRef(0),x=r.useRef(0),k=r.useRef(0),E=r.useRef(0),i=r.useRef(0),h=r.useRef(!1),g=r.useRef(0),y=r.useRef(n);y.current=n;const R=r.useRef(null),[q,U]=r.useState(!1),[de,ae]=r.useState(null),[le,F]=r.useState(null),[z,D]=r.useState(),[Y,re]=r.useState(),[W,ue]=r.useState(null),[se,xe]=r.useState(!1),[je,X]=r.useState(),[J,he]=r.useState(),[ie,H]=r.useState(),N=r.useRef(null),_=r.useRef(void 0),V=r.useRef(void 0),ee=r.useRef(void 0),ce=r.useRef(new Map),fe=r.useRef(new Map),Z=r.useRef(!1);Z.current=q;const ke=r.useCallback(u=>{R.current=u},[]),ge=r.useCallback(()=>{g.current++,C(!0)},[C]),Me=r.useCallback(()=>{g.current=Math.max(0,g.current-1),g.current===0&&C(!1)},[C]),Re=r.useCallback(()=>{const u=++k.current;return E.current++,i.current++,N.current=null,_.current=void 0,V.current=void 0,ee.current=void 0,ce.current.clear(),fe.current.clear(),re(void 0),ue(null),xe(!1),X(void 0),he(void 0),H(void 0),u},[]),Se=r.useCallback(async(u,M=k.current)=>{const B=++E.current;xe(!0),he(void 0),H(void 0);try{const Q=await lr(u);if(M!==k.current||B!==E.current||y.current!==u)return;re(Q)}catch(Q){M===k.current&&B===E.current&&y.current===u&&(he(Ae(Q,"loading agents")),H(null))}finally{M===k.current&&B===E.current&&y.current===u&&xe(!1)}},[]),Je=r.useCallback(async u=>{const M=++x.current,B=k.current;ge(),L(void 0);try{const{trace:Q,city:ve}=await cr(u);if(M!==x.current||B!==k.current||y.current!==u)return;V.current=Q,ee.current=ve,ce.current.set(Ie,Q);const ye=N.current;if(ye===null){T(Q,ve);const we=fe.current.get(Ie);we!==void 0&&j(Math.min(we,Math.max(0,Q.events.length-1))),$(void 0)}else{const we=ce.current.get(ye);if(we){const pe=Pe.getState().currentSeq;T(we,ve),j(Math.min(pe,Math.max(0,we.events.length-1)))}}}catch(Q){M===x.current&&y.current===u&&L(Ae(Q,"loading the session"))}finally{Me()}},[ge,Me,j,T,L,$]),Et=r.useCallback(()=>{const u=N.current;fe.current.set(u??Ie,Pe.getState().currentSeq),i.current++,_.current=void 0,ce.current.clear(),N.current=null,ue(null),X(void 0),he(void 0),H(void 0);const M=V.current,B=ee.current;if(M&&B){T(M,B);const Q=fe.current.get(Ie);Q!==void 0&&j(Math.min(Q,Math.max(0,M.events.length-1))),$(void 0)}},[j,T,$]),lt=r.useCallback(async u=>{const M=++A.current;ge(),L(void 0);try{const B=await Ft(u);if(M!==A.current)return;I(B);let Q;if(!G.current){G.current=!0;const be=new URL(window.location.href).searchParams.get("session")??void 0,At=be?B.find(xt=>xt.key===be):void 0,gt=be&&!At?B.filter(xt=>xt.id===be):[],Lt=At?.key??(gt.length===1?gt[0].key:void 0);Lt?Q=Lt:gt.length>1?console.warn(`session id "${be}" is ambiguous; falling back to the latest session`):be&&console.warn(`session "${be}" not found; falling back to the latest session`)}const ve=y.current,ye=ve!==void 0&&B.some(be=>be.key===ve),we=(B.find(be=>Fn(be,{hideEmpty:d,harness:b}))??B[0])?.key,pe=Q??(ye?ve:we);if(pe!==ve){const be=Re();y.current=pe,pe||x.current++,O(pe),pe&&Se(pe,be)}else u&&pe&&(Et(),Se(pe));pe&&await Je(pe)}catch(B){M===A.current&&L(Ae(B,"scanning sessions"))}finally{Me()}},[ge,Me,b,d,Et,Se,Je,Re,O,L,I]),Dn=r.useCallback(async u=>{ge(),L(void 0);try{const M=await fr(u);p(M)}catch(M){L(Ae(M,"loading the repository map"))}finally{Me()}},[ge,Me,p,L]),On=r.useCallback(u=>{const M=u?`/?map=1&repo=${encodeURIComponent(u)}`:"/?map=1";window.open(M,"_blank","noopener")},[]),Hn=r.useCallback(u=>{if(y.current===u)return;const M=Re();y.current=u,O(u),Se(u,M),Je(u)},[Se,Je,Re,O]),Ze=r.useCallback(()=>{const u=N.current??Ie;fe.current.set(u,Pe.getState().currentSeq)},[]),dt=r.useCallback((u,M,B)=>{Ze(),N.current=u,ue(u),T(M,B);const Q=fe.current.get(u??Ie);Q!==void 0&&j(Math.min(Q,Math.max(0,M.events.length-1))),$(void 0)},[Ze,j,T,$]),ut=r.useCallback(async u=>{if(Z.current)return;const M=y.current,B=ee.current;if(!M||!B)return;const Q=++i.current;if(_.current=void 0,X(void 0),he(void 0),H(void 0),N.current===u)return;const ve=u===null?V.current:ce.current.get(u);if(ve){dt(u,ve,B);return}if(u===null)return;const ye=Y?.agents.find(pe=>pe.id===u);if(!ye||ye.traceAvailability!=="available")return;const we=k.current;_.current=u,X(u);try{const pe=await dr(M,u);if(we!==k.current||Q!==i.current||_.current!==u||y.current!==M||Z.current)return;ce.current.set(u,pe),dt(u,pe,ee.current??B)}catch(pe){we===k.current&&Q===i.current&&_.current===u&&y.current===M&&(he(Ae(pe,`loading the ${ye.label} trace`)),H(u))}finally{we===k.current&&Q===i.current&&_.current===u&&y.current===M&&(_.current=void 0,X(void 0))}},[Y,dt]),Un=r.useCallback(()=>{const u=y.current;Z.current||!u||ie===void 0||(ie===null?Se(u):ut(ie))},[ie,Se,ut]),Vn=r.useCallback(async()=>{const u=R.current,M=s?.events.length??0;if(!u||M===0||Z.current)return;const B=y.current,Q=N.current,ve=Pe.getState().currentSeq;i.current++,_.current=void 0,X(void 0),Z.current=!0,U(!0),L(void 0);try{const{blob:ye,extension:we}=await qr({canvas:u,total:M,setSeq:j}),pe=s?.session.id||B||"session";Dr(ye,`mindwalk-${pe}.${we}`)}catch(ye){L(Ae(ye,"exporting the video"))}finally{y.current===B&&N.current===Q&&j(ve),Z.current=!1,U(!1)}},[s,q,j,L]),Gn=r.useCallback(()=>K(!0),[K]),Kn=r.useCallback(()=>K(!1),[K]),Ee=r.useCallback(async u=>{try{const M=await ur(u);y.current===u&&D(M)}catch{}},[]);r.useEffect(()=>{ae(null),F(null),D(void 0),n&&!S&&Ee(n)},[n,S,Ee]);const $e=r.useCallback(async()=>{try{I(await Ft())}catch{}},[I]),Wn=r.useCallback(()=>{if(Z.current||h.current)return;h.current=!0;const u=y.current;u&&!S&&Ee(u),lt(!0).finally(()=>{h.current=!1})},[lt,Ee,S]);r.useEffect(()=>{if(z?.state!=="running"||!n)return;const u=setInterval(()=>{Ee(n),$e()},2500);return()=>{clearInterval(u),$e()}},[z?.state,n,Ee,$e]),r.useEffect(()=>{if(z!==void 0||!n||S)return;const u=setInterval(()=>{Ee(n)},5e3);return()=>clearInterval(u)},[z===void 0,n,S,Ee]);const Rt=r.useMemo(()=>e.some(u=>u.reportState==="running"),[e]);r.useEffect(()=>{if(!Rt||z?.state==="running")return;const u=setInterval(()=>{$e()},5e3);return()=>clearInterval(u)},[Rt,z?.state,$e]);const Yn=r.useCallback(async u=>{const M=y.current;if(M)try{const B=await hr(M,u);y.current===M&&D(B),$e()}catch(B){L(Ae(B,"starting the evaluation"))}},[L,$e]),ht=r.useCallback(u=>{$(u),u&&ae("inspect")},[$]),ft=r.useCallback(()=>ae(null),[]),Xn=r.useCallback(()=>F(null),[]),Jn=r.useCallback(()=>{Z.current||ae("agents")},[]),Zn=r.useCallback(u=>{u.presentation==="sheet"?ae(M=>M===u.id?null:u.id):F(M=>M===u.id?null:u.id)},[]),Qn=r.useCallback(u=>{if(Z.current)return;const M=V.current,B=ee.current;if(!M||!B)return;i.current++,_.current=void 0,X(void 0),N.current!==null&&(Ze(),N.current=null,ue(null),T(M,B)),j(u),fe.current.set(Ie,u);const ve=M.events[u]?.targets.find(ye=>ye.path)?.path;$(ve)},[Ze,j,T,$]),es=r.useCallback(u=>{j(u),ae("agents")},[j]),ts=r.useCallback(u=>{Z.current||j(u)},[j]);r.useEffect(()=>{const u=M=>{if(M.key.toLowerCase()!=="b"||!(M.metaKey||M.ctrlKey)||M.altKey||M.shiftKey)return;M.preventDefault();const B=Pe.getState();B.setRailCollapsed(!B.railCollapsed)};return window.addEventListener("keydown",u),()=>window.removeEventListener("keydown",u)},[]),r.useEffect(()=>{const u=M=>{if(M.key.toLowerCase()!=="v"||M.metaKey||M.ctrlKey||M.altKey||M.shiftKey)return;const B=M.target;if(B&&(B.tagName==="INPUT"||B.tagName==="TEXTAREA"||B.isContentEditable)||Z.current)return;const Q=Pe.getState();Q.setView(Q.view==="tree"?"terrain":"tree")};return window.addEventListener("keydown",u),()=>window.removeEventListener("keydown",u)},[]),r.useEffect(()=>{const u=new URL(window.location.href).searchParams;u.get("map")==="1"?Dn(u.get("repo")??void 0):lt(!1)},[]);const pt=r.useMemo(()=>z?.state==="running"?"running":z?.state==="failed"?"failed":z?.state==="done"?z.stale?"stale":"done":null,[z]),St=r.useMemo(()=>W===null?"Main":Y?.agents.find(u=>u.id===W)?.label??"Subagent",[W,Y]),ns=f==="tree"?s?"glow ∝ revisits":"static map":s?"height ∝ depth × revisits":"height ∝ lines",$t=r.useMemo(()=>new Ir(s,a),[s,a]),Te=r.useMemo(()=>$t.snapshotAt(o),[$t,o]),mt=r.useMemo(()=>{let u=0,M=0,B=0;for(const Q of Te.touchByPath.values())Q==="edit"?u++:Q==="read"?M++:B++;return{edited:u,read:M,seen:B}},[Te]),Oe=r.useMemo(()=>l?a?.files.find(u=>u.path===l):void 0,[a,l]),ss=r.useMemo(()=>{const u=new Map;for(const M of s?.events??[])for(const B of M.targets)B.touch==="edit"&&B.path&&u.set(B.path,(u.get(B.path)??0)+1);return[...u.entries()].filter(([,M])=>M>=3).map(([M,B])=>({path:M,edits:B})).sort((M,B)=>B.edits-M.edits||(M.path<B.path?-1:1))},[s]);return t.jsxs("main",{className:S||c?"app-frame rail-collapsed":"app-frame",children:[S?null:t.jsx(Ca,{sessions:e,activeKey:n,loading:m,hideEmpty:d,harnessFilter:b,collapsed:c,onSelect:Hn,onRefresh:Wn,onHideEmptyChange:P,onHarnessFilterChange:ne,onCollapse:Gn,onOpenMap:On,activeRepo:s?.session.cwd,locked:q,activeReportState:z===void 0?void 0:pt}),t.jsxs("section",{className:"stage",children:[t.jsxs("div",{className:"viewport",children:[!S&&c?t.jsx("button",{className:"rail-expand",onClick:Kn,title:`Show sidebar (${qn})`,"aria-label":"Show session sidebar",children:t.jsx(qs,{size:15})}):null,f==="tree"?t.jsx(la,{city:a,playback:Te,selectedPath:l,onSelect:ht,onCanvasReady:ke}):t.jsx(Qr,{city:a,playback:Te,selectedPath:l,onSelect:ht,onCanvasReady:ke,locHeights:S}),t.jsx(ga,{trace:s,city:a,agentLabel:St,editedNow:mt.edited,readNow:mt.read,seenNow:mt.seen,churn:ss,onSelectFile:ht,onOpenAgents:!S&&s?Jn:void 0,locked:q}),a?t.jsx(pr,{panels:[{id:"view",icon:f==="tree"?yn:xn,hint:`Scene view: ${f} — click to change, or press V`,section:"scene",presentation:"pop",render:()=>t.jsx(Lr,{view:f,onViewChange:w,note:ns,locked:q})},{id:"inspect",icon:Ns,hint:"Inspect the selected file",section:"session",presentation:"sheet",render:()=>t.jsx(ja,{file:Oe,touch:Oe?Te.touchByPath.get(Oe.path):void 0,history:Oe?Te.historyByPath.get(Oe.path)??[]:[],onClose:ft,onJumpTo:ts,locked:q})},...!S&&s?[{id:"agents",icon:rr,hint:`Agent lenses — current: ${St}`,section:"session",presentation:"sheet",render:()=>t.jsx(mr,{graph:Y,current:W,loading:se,loadingAgentID:je,locked:q,error:J,retryAgentID:ie,onSelect:u=>{ut(u)},onRetry:Un,onClose:ft})}]:[],...!S&&s?[{id:"evaluate",icon:vn,hint:Ia(pt),section:"session",presentation:"sheet",badge:pt,render:()=>t.jsx(Mr,{status:z,analyzing:z?.state==="running",locked:q,onAnalyze:u=>{Yn(u)},onClose:ft,onJumpTo:Qn})}]:[]],openSheet:de,openPop:le,onToggle:Zn,onClosePop:Xn}):null,!S&&!m&&e.length===0?t.jsx("div",{className:"empty-stage",children:t.jsxs("div",{className:"card",children:[t.jsx("h2",{children:"No sessions found"}),t.jsxs("p",{children:["Synapse scans ",t.jsx("code",{children:"~/.claude/projects"}),", ",t.jsx("code",{children:"~/.codex/sessions"}),","," ",t.jsx("code",{children:"~/.pi/agent/sessions"}),", and ",t.jsx("code",{children:"~/.gemini/antigravity-cli/brain"})," for agent traces. Run a session there, then refresh."]})]})}):null,m?t.jsx("div",{className:"toast",children:S?"Building the map…":e.length===0?"Scanning sessions…":"Reading trace…"}):null,v?t.jsx("div",{className:"toast error",children:v}):null]}),t.jsx(La,{trace:s,currentSeq:o,onChange:j,onExport:Nn()?Vn:void 0,exporting:q,onSubagentMark:es})]})]})}as.createRoot(document.getElementById("root")).render(t.jsx(r.StrictMode,{children:t.jsx(za,{})}));
3
+ //# sourceMappingURL=index-ndrpq0ER.js.map