Commit graph

5 commits

Author SHA1 Message Date
Hibryda
162b5417e4 feat(electrobun): hierarchical state tree (Rule 58)
New files:
- project-state.types.ts: all per-project state interfaces
- project-state.svelte.ts: unified per-project state with version counter
- app-state.svelte.ts: root facade re-exporting all stores as appState.*

Rewired components (no more local $state):
- ProjectCard: reads via appState.agent.* and appState.project.tab.*
- TerminalTabs: state in appState.project.terminals.*
- FileBrowser: state in appState.project.files.*
- CommsTab: state in appState.project.comms.*
- TaskBoardTab: state in appState.project.tasks.*

All follow Rule 57 (no $derived with new objects) and Rule 58
(state tree architecture, components are pure renderers).
2026-03-24 15:20:09 +01:00
Hibryda
20e4d2cdec fix(electrobun): eliminate $effect/$derived cycles in 3 more components
TaskBoardTab: $effect called loadTasks() which wrote ++pollToken ($state)
→ triggered $effect re-run → infinite loop. Fix: onMount instead.
Also tasksByCol $derived created new objects via .reduce/.filter.

FileBrowser: $effect read openDirs (via new Set(openDirs)) AND wrote to
it (openDirs = s) → infinite loop. Fix: onMount with fresh Set.

CommsTab: $effect called loadChannels()/loadAgents() which wrote $state
→ potential cycle. Fix: onMount instead.

Rule: NEVER use $effect for initialization that writes to $state.
Always use onMount for async init + side effects.
2026-03-24 13:03:48 +01:00
Hibryda
f0850f0785 feat: @agor/stores package (3 stores) + 58 BackendAdapter tests
@agor/stores:
- theme.svelte.ts, notifications.svelte.ts, health.svelte.ts extracted
- Original files replaced with re-exports (zero consumer changes needed)
- pnpm workspace + Vite/tsconfig aliases configured

BackendAdapter tests (58 new):
- backend-adapter.test.ts: 9 tests (lifecycle, singleton, testing seam)
- tauri-adapter.test.ts: 28 tests (invoke mapping, command names, params)
- electrobun-adapter.test.ts: 21 tests (RPC names, capabilities, stubs)

Total: 523 tests passing (was 465, +58)
2026-03-22 04:45:56 +01:00
Hibryda
0f75cb8e32 fix(electrobun): complete all 16 Codex #3 findings
CRITICAL:
- Message persistence race: snapshot batchEnd before async save
- Double-start guard: startingProjects Set prevents concurrent launches
- Symlink path traversal: fs.realpathSync() in path-guard.ts
- Relay false success: connect() returns { ok, machineId, error }

HIGH:
- Session restore skips if active session exists
- Remote remove: new RPC, cleans backend map
- Task board poll token: stale responses discarded after drag-drop
- Health concurrent tools: toolsInFlight counter (was boolean)
- bttask transactions: delete wraps comments+task, addComment validates
- PTY buffer cleared on reconnect
- PTY large paste: chunked String.fromCharCode (8KB chunks)
- Sidecar max line: 10MB limit prevents unbounded memory
- btmsg authorization: group validation, channel membership checks

MEDIUM:
- Session retention: max 5 per project, purgeSession/untrackProject
- Relay IPv6: URL parser replaces string split
- PTY schema: fixed misleading base64 comment
2026-03-22 02:52:04 +01:00
Hibryda
252fca70df feat(electrobun): file management — CodeMirror editor, PDF viewer, CSV table, real file I/O
- CodeEditor: CodeMirror 6 with Catppuccin theme, 15+ languages, Ctrl+S save,
  dirty tracking, save-on-blur
- PdfViewer: pdfjs-dist canvas rendering, zoom 0.5-3x, HiDPI, lazy page load
- CsvTable: RFC 4180 parser, delimiter auto-detect, sortable columns, sticky header
- FileBrowser: real filesystem via files.list/read/write RPC, lazy dir loading,
  file type routing (code→editor, pdf→viewer, csv→table, images→display)
- 10MB size gate, binary detection, base64 encoding for non-text files
2026-03-22 01:36:02 +01:00