Commit graph

110 commits

Author SHA1 Message Date
Hibryda
5d69f6b28f perf(ui-gpui): focus-gated blink + comprehensive rendering analysis
Focus-gated blink: only first (focused) project blinks.
Root cause: 14 header divs × 2 boxes × 2/sec = 2.8% CPU.
Cached children (AgentPane, TerminalView) confirmed at 0%.
Path to <1%: custom Element for ProjectBox (major refactor).
2026-03-19 23:26:20 +01:00
Hibryda
f797a676f4 perf(ui-gpui): isolate StatusDotView entity, document 3% CPU floor
Root cause analysis:
- 0% baseline: calloop 60Hz polling has zero measurable CPU cost
- 3% is entirely from ProjectBox::render() rebuilding ~30 header divs
  × 2 boxes × 2/sec = 120 div constructions/sec
- AgentPane + TerminalView cached (into_cached_flex) = 0% contribution
- mark_view_dirty() walks ancestors unconditionally in GPUI 0.2.2
  → StatusDotView isolation doesn't prevent parent re-render
- Fragment shaders not exposed (paint_quad accepts static color only)
- GPUI AnimationElement uses request_animation_frame = 79% CPU (vsync)

StatusDotView pattern is architecturally correct for future GPUI versions
that may implement per-view dirty isolation.
2026-03-19 23:09:56 +01:00
Hibryda
727c7d2e06 perf(ui-gpui): revert AnimationElement (79% CPU), document shader limitation
GPUI's AnimationElement uses request_animation_frame() internally which runs
at vsync (60fps) causing 79% CPU. Fragment shaders not exposed through GPUI's
Scene API (paint_quad only accepts static color, no time uniform).

Reverted to BlinkState timer pattern (3% CPU, 2 renders/sec).
This is the same approach Zed uses for cursor blink.

Tested approaches and results:
- AnimationElement + pulsating_between: 79% CPU (vsync loop)
- BlinkState + timer(500ms) + cx.notify(): 3% CPU (correct)
- Custom Element + paint_quad: no shader access
- CSS animation (Blitz): 30% CPU (full repaint loop)
2026-03-19 23:03:04 +01:00
Hibryda
640e2bd494 fix(ui-gpui): re-enable start_blinking (was disabled for testing) 2026-03-19 22:50:16 +01:00
Hibryda
3859317477 perf(ui-gpui): add render counters, remove redundant cx.observe, reduce repaints
- BlinkState.start_from_context<V>() uses Context<V> spawn (not App)
  which correctly registers the async task in the window's executor
- ProjectGrid NOT cached (blocks child dirty propagation)
- AgentPane + TerminalView cached with into_cached_flex()
- Render diagnostic: ProjectBox renders 2x/sec (blink), both boxes
  re-render because shared parent, but inner cached views are free
- CPU: ~3% with pulsing dot visible
2026-03-19 22:48:29 +01:00
Hibryda
1f26e5b272 perf(ui-gpui): diagnostic counters confirm 2 renders/sec at window level (GPUI limit)
- Sidebar and StatusBar uncached (natural size collapsed with StyleRefinement::default)
- ProjectGrid cached with flex-1 style (into_cached_flex)
- AgentPane + TerminalView cached within ProjectBox
- BlinkState::start() fixed with &mut *cx deref coercion
- CPU: ~3% with full layout visible (down from 6.8% uncached)
- Remaining: ProjectBox re-renders full tree on blink (reads BlinkState)
- Next: isolate dot into StatusDotView entity to prevent ProjectBox re-render
2026-03-19 22:45:21 +01:00
Hibryda
a25e024d54 docs: add GPUI breakthrough (4.5% → 0.83% CPU) with shared-entity pattern 2026-03-19 22:36:13 +01:00
Hibryda
73cfdf6752 perf(ui-gpui): cache SharedStrings, remove diagnostics, zero alloc per render frame
- BlinkState as shared Entity (not child) → cx.notify() only dirties ProjectBox,
  NOT ancestors (Workspace, ProjectGrid). Siblings serve from GPU cache.
- .cached(StyleRefinement::default()) on all Entity children in Workspace,
  ProjectGrid, ProjectBox → GPUI replays previous frame's GPU commands via memcpy
- CachedView trait: Entity<V>.into_cached_view() → AnyView::from().cached()
- Result: 4.5% CPU → 0.83% CPU (25 ticks / 30s) for pulsing dot animation
2026-03-19 22:35:41 +01:00
Hibryda
ad45a8d88d docs: comprehensive GPUI findings (API, animation patterns, gotchas, benchmarks) 2026-03-19 09:43:17 +01:00
Hibryda
5dbf5bd43c perf(ui-gpui): cache SharedStrings, remove diagnostics, zero alloc per render frame 2026-03-19 09:38:00 +01:00
Hibryda
b557aeb833 perf(ui-gpui): diagnostic counters confirm 2 renders/sec at window level (GPUI limit) 2026-03-19 09:33:34 +01:00
Hibryda
7ab5d97352 perf(ui-gpui): add render counters, remove redundant cx.observe, reduce repaints 2026-03-19 09:27:08 +01:00
Hibryda
8dd3d82d31 fix(ui-gpui): re-enable start_blinking (was disabled for testing) 2026-03-19 09:21:21 +01:00
Hibryda
ba74e19ff2 feat(ui-gpui): Zed-style BlinkManager pattern for pulsing dot (epoch guard, 500ms timer) 2026-03-19 09:20:04 +01:00
Hibryda
84324f9ae3 chore: add daemon package-lock, gitignore test-results 2026-03-19 08:20:52 +01:00
Hibryda
3383334821 feat(ui-gpui): custom Element with direct paint_quad() for zero-overhead pulse 2026-03-19 08:16:44 +01:00
Hibryda
713b53ba0c perf(ui-gpui): throttle pulse to 5fps via spawn+timer instead of request_animation_frame 2026-03-19 08:11:22 +01:00
Hibryda
c4d0707514 fix(ui-gpui): set first project to Running status so pulse animation triggers 2026-03-19 08:08:53 +01:00
Hibryda
18cfe7979c fix(ui-gpui): color interpolation instead of alpha (GPUI ignores alpha on bg) 2026-03-19 08:03:24 +01:00
Hibryda
573105eae6 feat(ui-gpui): render-driven pulse via request_animation_frame() (GPUI native) 2026-03-19 07:59:32 +01:00
Hibryda
57e0e3a087 feat(ui-gpui): add pulsing dot via GPUI async runtime (entity-scoped repaint) 2026-03-19 07:51:25 +01:00
Hibryda
3e6307ffd0 perf(ui-dioxus): 6-step color fade without CSS transition engine (~0% CPU) 2026-03-19 07:28:38 +01:00
Hibryda
8b5a4daf72 feat(ui-dioxus): smooth pulse via background-color transition (bounded, not infinite) 2026-03-19 07:24:00 +01:00
Hibryda
a1e2a66cd6 feat(ui-dioxus): smooth 8-step opacity pulse via CSS class cycling 2026-03-19 07:14:43 +01:00
Hibryda
2f03cf0ef0 fix(ui-dioxus): class-toggle animation instead of inline opacity (Blitz compatible) 2026-03-19 07:11:01 +01:00
Hibryda
67ab77ebf4 feat(ui-dioxus): use dioxus-motion for Blitz-compatible pulse animation 2026-03-19 07:04:23 +01:00
Hibryda
c9f8679744 fix(ui-dioxus): use schedule_update() for cross-thread Blitz animation 2026-03-19 06:50:26 +01:00
Hibryda
7cea86361a fix(ui-dioxus): use atomic+thread for Blitz animation (Signal not Send) 2026-03-19 06:45:52 +01:00
Hibryda
b0547d5c05 feat(ui-dioxus): add signal-based PulsingDot animation (Blitz-friendly) 2026-03-19 06:39:47 +01:00
Hibryda
6f9607d1ba fix(ui-dioxus): remove CSS animations causing 30% CPU in Blitz renderer 2026-03-19 06:31:48 +01:00
Hibryda
d5172275e2 feat(ui-dioxus): switch to Blitz/wgpu native renderer (no WebView) 2026-03-19 06:12:11 +01:00
Hibryda
f3d2ca78ba feat: add Dioxus and GPUI UI prototypes for framework comparison
Dioxus (ui-dioxus/): 2,169 lines, WebView mode (same wry as Tauri),
  Catppuccin theme, 12 components, agor-core integration, compiles clean.
  Evolution path — keeps xterm.js, gradual migration from Tauri.

GPUI (ui-gpui/): 2,490 lines, GPU-accelerated rendering, alacritty_terminal
  for native terminal, 17 files, Catppuccin palette, demo data.
  Revolution path — pure Rust UI, 120fps target, no WebView.

Both are standalone (not in workspace), share agor-core backend.
Created for side-by-side comparison to inform framework decision.
2026-03-19 06:05:58 +01:00
Hibryda
90c7315336 docs: add v3.2 features and architecture decisions to TODO
- Profile export/import with format evaluation
- Keyboard shortcuts settings (levels, compose, conflicts)
- Per-project settings cascade (global → group → project)
- Custom AI-augmented editors (image, video, audio, 3D)
- Tauri vs WGPU alternative evaluation
- Frontend-backend tight binding investigation
- More realistic E2E fixtures (multi-provider, multi-group)
2026-03-18 05:56:26 +01:00
Hibryda
60614a75f5 fix(e2e): daemon runner parses per-spec PASSED/FAILED from WDIO output
Previously marked all specs as failed when any single spec failed.
Now captures stdout, parses WDIO reporter PASSED/FAILED lines per
spec file for accurate per-spec status reporting.
2026-03-18 05:36:56 +01:00
Hibryda
d7dd7722ab feat(e2e): add test daemon CLI with ANSI dashboard and Agent SDK bridge
- index.ts: CLI entry point (--full, --spec, --watch, --agent flags)
- runner.ts: programmatic WDIO launcher with result streaming
- dashboard.ts: ANSI terminal UI (pass/fail/skip/running icons, summary)
- agent-bridge.ts: NDJSON stdin/stdout for Agent SDK queries
  (status, rerun, failures, reset-cache)
- Standalone package at tests/e2e/daemon/
2026-03-18 05:17:17 +01:00
Hibryda
46f51d7941 feat(e2e): add smart test caching and error toast catching
- results-db.ts: TestPassCache with consecutivePasses counter,
  recordTestResult(), shouldSkip(threshold=3), resetCache()
- wdio.conf.js: afterTest hook catches unexpected .toast.error/.load-error
  elements, records results to smart cache. FULL_RESCAN=1 bypasses caching
2026-03-18 05:16:49 +01:00
Hibryda
0803dc3844 docs: update TODO and CHANGELOG for session work
- TODO: mark completed (SPKI persistence, theme editor, pro components,
  error handling, marketplace, E2E expansion), add new items (E2E failures,
  daemon integration)
- CHANGELOG: add ThemeEditor, marketplace, 6 commercial modules, AppError
  enum, E2E daemon, security fixes (5 critical + 14 high)
2026-03-18 05:16:37 +01:00
Hibryda
a94158e894 fix(e2e): fix remaining selector and state issues (3 files)
- settings.test.ts: use browser.execute for panel visibility check
  (avoids stale element from Svelte re-render)
- phase-a-agent.test.ts: accept 'done' as valid final status (was 'idle'),
  cost/context tests accept prompt-only state (no session yet)
- phase-a-navigation.test.ts: wait for terminal-tabs after expanding,
  add tab before checking active styling, re-open palette if closed
2026-03-18 04:56:06 +01:00
Hibryda
1b838eb9fc fix(e2e): update selectors for redesigned UI (9 spec files)
- BTerminal → Agent Orchestrator (title, describe blocks, LLM context)
- Settings: .sidebar-panel → .settings-panel .settings-content,
  .dropdown-trigger → .dropdown-btn, .dropdown-option → .dropdown-item
- Settings open: [data-testid=settings-btn] + .panel-close
- Font controls: .size-control → .stepper, .size-btn → stepper button
- Terminal: data-testid selectors for toggle/tab-add
- Agent pane: .cost-bar → .status-strip/.done-bar, context meter conditional
- Project header: .cwd → .info-cwd
- Health: .health-dot → .status-dot
- Multi-project: proper this.skip() when single-project fixture
2026-03-18 04:45:22 +01:00
Hibryda
6459877c89 fix: change dev port from 9700 to 9710 (avoid BridgeCoach conflict)
Port 9700 was occupied by BridgeCoach Docker container, causing the
Tauri debug binary to load the wrong frontend. Changed to 9710:
- vite.config.ts: server.port 9700 → 9710
- tauri.conf.json: devUrl localhost:9700 → localhost:9710
- wdio.conf.js: DEV_URL_PORT check updated
- Binary rebuilt with new port baked in
2026-03-18 04:20:49 +01:00
Hibryda
10de2a3c8b fix(e2e): detect devUrl port conflict before launching tests
Debug binary has devUrl (localhost:9700) baked in via cfg(debug_assertions).
If another app (Docker, Nuxt, etc.) serves on that port, the Tauri WebView
loads the WRONG frontend. onPrepare now fails fast with a clear message
if port 9700 is occupied, preventing false test results against wrong app.
2026-03-18 04:11:31 +01:00
Hibryda
c73a2e1caf fix(e2e): build frontend before tests (prevents wrong-app loading)
- onPrepare: run `npm run build` before `cargo tauri build --debug --no-bundle`
  (--no-bundle skips beforeBuildCommand, leaving no dist/ for the WebView)
- SKIP_BUILD: still verify dist/index.html exists, build frontend if missing
- Without this fix, the Tauri binary falls back to devUrl and loads whatever
  app is serving on that port (e.g., BridgeCoach on another project)
2026-03-18 04:06:28 +01:00
Hibryda
1f21a9fb46 fix(e2e): kill stale processes, verify app identity before tests
- onPrepare: kill stale tauri-driver on port 9750 before spawning
- onPrepare: verify debug binary exists (fail fast with clear message)
- before: app identity check — waits for known Agent Orchestrator elements
  (status-bar, project-grid, settings-panel) or matching window title
- Prevents wrong-app connection when other Tauri/WebKit2GTK apps are running
2026-03-18 04:01:46 +01:00
Hibryda
ae321ad108 fix(e2e): use dedicated port 9750 for tauri-driver (avoid conflicts)
- tauri-driver spawned with --port 9750 (was default 4444)
- Pre-check: fail fast if port already in use (clear error message)
- TCP readiness probe uses the dedicated port
- Follows project port convention (9000-9999 range)
2026-03-18 03:58:21 +01:00
Hibryda
91a3b56dba test(e2e): split + expand phase-b into grid + LLM specs
- phase-b-grid.test.ts (227 lines): multi-project grid, tab switching,
  status bar, accent colors, project icons, scroll, tab bar completeness
- phase-b-llm.test.ts (211 lines): LLM-judged agent response, code gen,
  context tab, tool calls, cost display, session persistence
- Original phase-b.test.ts (377 lines) deleted
- New exhaustive tests added for grid layout and agent interaction
2026-03-18 03:47:16 +01:00
Hibryda
718133f9f6 test(e2e): split + expand agent-scenarios into Phase A (22 → 47 tests)
- phase-a-structure.test.ts (156 lines, 14 tests): structural integrity,
  settings panel, sidebar gear, accent colors, project name/icon, grid layout
- phase-a-agent.test.ts (210 lines, 14 tests): agent pane, prompts,
  provider badge, cost display, context meter, status transitions
- phase-a-navigation.test.ts (297 lines, 19 tests): terminal tabs,
  command palette, focus switching, palette categories, shortcut hints
- Original agent-scenarios.test.ts (429 lines) deleted
- 25 new exhaustive tests added
2026-03-18 03:46:40 +01:00
Hibryda
56971c3f27 test(e2e): add Phase D/E/F specs covering new architecture (54 tests)
Phase D — Settings & Error Handling:
- D1: Settings panel 6-category tabs, search, active highlighting
- D2: Appearance settings (themes, fonts, cursor, scrollback)
- D3: Theme Editor (color pickers, groups, save/cancel)
- D4: Toast notifications, notification center bell/dropdown
- D5: Error states (no loadError warnings, status bar)

Phase E — Agents & Health:
- E1: ProjectBox tab bar (7+ tabs, PERSISTED-LAZY switching)
- E2: Agent session UI (prompt input, context meter, cost)
- E3: Provider configuration (panels, capabilities, toggles)
- E4: Status bar fleet state (counts, cost, attention queue)
- E5: Project health indicators (status dot, CWD, pressure, burn rate)
- E6: Metrics tab (fleet aggregates, health cards, Live/History)
- E7: Conflict detection (no false badges on fresh launch)
- E8: Audit log (manager-only tab, toolbar, entries)

Phase F — Search & LLM Quality:
- F1: Search overlay (Ctrl+Shift+F, input, empty state, close)
- F2: Context tab & anchors (visualization, budget scale)
- F3: SSH tab (connection list, add button)
- F4-F7: LLM-judged quality (settings completeness, theme editor,
  error messages, overall UI consistency)
2026-03-18 03:20:37 +01:00
Hibryda
6f247da514 refactor(e2e): complete agor.test.ts split (799 lines → 5 files)
- smoke.test.ts (47) — stateless smoke checks
- workspace.test.ts (79) — workspace & projects
- settings.test.ts (247) — settings panel + interaction
- features.test.ts (220) — command palette + keyboard shortcuts
- terminal-theme.test.ts (292) — terminal tabs + theme switching
- Reset-to-home-state hooks in all stateful before() blocks
- Original agor.test.ts deleted, wdio.conf.js specs updated
- All 50+ original tests preserved
2026-03-18 03:11:10 +01:00
Hibryda
f08c4b18cf refactor(e2e): split spec files under 300-line limit
- phase-c.test.ts (626 lines) → phase-c-ui.test.ts (279), phase-c-tabs.test.ts
  (272), phase-c-llm.test.ts (76) — all 11 scenarios preserved
- agor.test.ts (799 lines) → smoke.test.ts (47), workspace.test.ts (79),
  settings.test.ts (247), features.test.ts (488) — split in progress
- Reset-to-home-state hooks added to stateful before() blocks
- wdio.conf.js specs array updated for all new filenames
2026-03-18 03:09:29 +01:00
Hibryda
e76bc341f2 refactor(e2e): extract infrastructure into tests/e2e/infra/ module
- Move fixtures.ts, llm-judge.ts, results-db.ts to tests/e2e/infra/
- Deduplicate wdio.conf.js: use createTestFixture() instead of inline copy
- Replace __dirname paths with projectRoot-anchored paths
- Create test-mode-constants.ts (typed env var names, flag registry)
- Create scripts/preflight-check.sh (validates tauri-driver, display, Claude CLI)
- Create scripts/check-test-flags.sh (CI lint for AGOR_TEST flag drift)
- Rewrite tests/e2e/README.md with full documentation
- Update spec imports for moved infra files
2026-03-18 03:06:57 +01:00