diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 97adcc4..ab7e741 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -5,7 +5,7 @@ - v1 is a single-file Python app (`bterminal.py`). Changes are localized. - v2 docs are in `docs/`. Architecture decisions are in `docs/task_plan.md`. - v2 Phases 1-7 + multi-machine (A-D) + profiles/skills complete. Extras: SSH, ctx, themes, detached mode, auto-updater, shiki, copy/paste, session resume, drag-resize, session groups, Deno sidecar, Claude profiles, skill discovery. -- v3 Mission Control (All Phases 1-10 Complete + S-1 Phase 1/1.5/2/3 + S-2 Session Anchors + Provider Adapter Pattern + Provider Runners + Memora Adapter): project groups, workspace store, 12 Workspace components, session continuity, workspace teardown, file overlap conflict detection, inotify-based external write detection, multi-provider adapter pattern (3 phases + Codex/Ollama runners), worktree isolation, session anchors, Memora adapter (read-only SQLite), dead v2 component cleanup. 272 vitest + 49 cargo tests. +- v3 Mission Control (All Phases 1-10 Complete + S-1 Phase 1/1.5/2/3 + S-2 Session Anchors + Provider Adapter Pattern + Provider Runners + Memora Adapter): project groups, workspace store, 12 Workspace components, session continuity, workspace teardown, file overlap conflict detection, inotify-based external write detection, multi-provider adapter pattern (3 phases + Codex/Ollama runners), worktree isolation, session anchors, Memora adapter (read-only SQLite), dead v2 component cleanup. 286 vitest + 49 cargo tests. - v3 docs: `docs/v3-task_plan.md`, `docs/v3-findings.md`, `docs/v3-progress.md`. - Consult Memora (tag: `bterminal`) before making architectural changes. diff --git a/CHANGELOG.md b/CHANGELOG.md index e44c32e..69a0a93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Security -- `claude_read_skill` path traversal: added `canonicalize()` + `starts_with()` validation to prevent reading arbitrary files via crafted skill paths (lib.rs) +- `claude_read_skill` path traversal: added `canonicalize()` + `starts_with()` validation to prevent reading arbitrary files via crafted skill paths (commands/claude.rs) ### Fixed - **Reconnect loop race in RemoteManager** — orphaned reconnect tasks continued running after `remove_machine()` or `disconnect()`. Added `cancelled: Arc` flag to `RemoteMachine`; set on removal/disconnect, checked each reconnect iteration. `connect()` resets flag for new connections (remote.rs) +### Changed +- **lib.rs command module split** — 976-line monolith with 48 Tauri commands split into 11 domain modules under `src-tauri/src/commands/` (pty, agent, watcher, session, persistence, knowledge, claude, groups, files, remote, misc). lib.rs reduced to ~170 lines (AppState + setup + handler registration) +- **Attention scorer extraction** — `scoreAttention()` pure function extracted from inline health store code to `utils/attention-scorer.ts` with 14 tests. Priority chain: stalled > error > context critical > file conflict > context high +- **Shared type guards** — deduplicated `str()`/`num()` runtime guards from claude-messages.ts, codex-messages.ts, ollama-messages.ts into shared `utils/type-guards.ts` + ### Added - **Configurable stall threshold** — per-project range slider (5–60 min, step 5) in SettingsTab. `stallThresholdMin` in `ProjectConfig` (groups.json), `setStallThreshold()` API in health store with `stallThresholds` Map and `DEFAULT_STALL_THRESHOLD_MS` fallback. ProjectBox `$effect` syncs config → store on mount/change - **Memora adapter** — `MemoraAdapter` (memora-bridge.ts) implements `MemoryAdapter` interface, bridging to Memora's SQLite database (`~/.local/share/memora/memories.db`) via read-only Rust backend (`memora.rs`). FTS5 text search, tag filtering via `json_each()`. 4 Tauri commands (memora_available, memora_list, memora_search, memora_get). Registered in App.svelte onMount. 16 vitest + 7 cargo tests. MemoriesTab now shows Memora memories on startup diff --git a/CLAUDE.md b/CLAUDE.md index ad931b3..341aae3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -36,7 +36,8 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `v2/src-tauri/src/pty.rs` | PTY backend (thin re-export from bterminal-core) | | `v2/src-tauri/src/groups.rs` | Groups config (load/save ~/.config/bterminal/groups.json) | | `v2/src-tauri/src/fs_watcher.rs` | ProjectFsWatcher (inotify per-project recursive file change detection, S-1 Phase 2) | -| `v2/src-tauri/src/lib.rs` | Tauri commands (pty + agent + session + file + fs_watcher + settings + 12 remote + 4 claude + 2 groups) | +| `v2/src-tauri/src/lib.rs` | AppState + setup + handler registration (~170 lines) | +| `v2/src-tauri/src/commands/` | 11 domain command modules (pty, agent, watcher, session, persistence, knowledge, claude, groups, files, remote, misc) | | `v2/src-tauri/src/sidecar.rs` | SidecarManager (thin re-export from bterminal-core) | | `v2/src-tauri/src/event_sink.rs` | TauriEventSink (implements EventSink for AppHandle) | | `v2/src-tauri/src/remote.rs` | RemoteManager (WebSocket client connections to relays) | @@ -79,6 +80,8 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `v2/src/lib/adapters/telemetry-bridge.ts` | Frontend telemetry bridge (routes events to Rust tracing via IPC) | | `docker/tempo/` | Docker compose: Tempo + Grafana for trace visualization (port 9715) | | `v2/src/lib/stores/machines.svelte.ts` | Remote machine state store (Svelte 5 runes) | +| `v2/src/lib/utils/attention-scorer.ts` | Pure attention scoring function (extracted from health store, 14 tests) | +| `v2/src/lib/utils/type-guards.ts` | Shared runtime guards: str(), num() for untyped wire format parsing | | `v2/src/lib/utils/agent-tree.ts` | Agent tree builder (hierarchy from messages) | | `v2/src/lib/utils/highlight.ts` | Shiki syntax highlighter (lazy singleton, 13 languages) | | `v2/src/lib/utils/detach.ts` | Detached pane mode (pop-out windows via URL params) | diff --git a/TODO.md b/TODO.md index 6c65132..9d67811 100644 --- a/TODO.md +++ b/TODO.md @@ -7,8 +7,13 @@ - [ ] **Multi-machine real-world testing** -- Test bterminal-relay with 2 machines. - [ ] **Multi-machine TLS/certificate pinning** -- TLS support for bterminal-relay + certificate pinning in RemoteManager. - [ ] **Agent Teams real-world testing** -- Env var whitelist fix done. 3 test sessions ran ($1.10, $0.69, $1.70) but model didn't spawn subagents — needs complex multi-part prompts to trigger delegation. Test with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1. +- [ ] **SOLID Phase 2 — agent-dispatcher.ts** -- God module (496 lines, 9 concerns). Extract event routing, session persistence, subagent routing into separate modules. +- [ ] **SOLID Phase 2 — session.rs** -- Mixed concerns (1008 lines, 8 tables). Split by table lifecycle. +- [ ] **SOLID Phase 3 — Primitive obsession** -- SessionId, ProjectId, FilePath as raw strings across 15+ files. Introduce value objects. + ## Completed +- [x] **SOLID Phase 1 Refactoring** -- Extracted AttentionScorer pure function (14 tests), shared str()/num() type guards, split lib.rs (976→170 lines, 11 command modules). 286 vitest + 49 cargo tests. | Done: 2026-03-11 - [x] **Configurable stall threshold** -- Per-project range slider (5–60 min, step 5) in SettingsTab. `stallThresholdMin` in ProjectConfig, `setStallThreshold()` API in health store, ProjectBox $effect sync. Adaptive suggestions deferred (needs 50+ sessions in session_metrics). | Done: 2026-03-11 - [x] **Register Memora adapter** -- MemoraAdapter (memora-bridge.ts) implements MemoryAdapter, reads ~/.local/share/memora/memories.db via Rust memora.rs (read-only SQLite, FTS5 search). 4 Tauri commands, 16 vitest + 7 cargo tests. 272 vitest + 49 cargo total. | Done: 2026-03-11 - [x] **Add Codex/Ollama provider runners** -- Full provider stack for both: ProviderMeta constants, message adapters (codex-messages.ts, ollama-messages.ts), sidecar runners (codex-runner.ts uses @openai/codex-sdk dynamic import, ollama-runner.ts uses direct HTTP). 30 new tests, 256 vitest total. | Done: 2026-03-11 @@ -18,5 +23,3 @@ - [x] **Files tab PDF viewer + CSV table** -- PdfViewer.svelte (pdfjs-dist 5.5.207, canvas multi-page, zoom 0.5x–3x, HiDPI). CsvTable.svelte (RFC 4180 parser, delimiter auto-detect, sortable columns, sticky header). | Done: 2026-03-11 - [x] **Filesystem Write Detection (S-1 Phase 2)** -- inotify-based file change detection via notify crate (fs_watcher.rs). Timing heuristic (2s grace) for PID attribution. 202/202 vitest + 42/42 cargo tests. | Done: 2026-03-11 - [x] **Conflict Detection Enhancements (S-1 Phase 1.5)** -- Bash write detection, acknowledge/dismiss conflicts, worktree-aware suppression. 194/194 tests. | Done: 2026-03-11 -- [x] **File Overlap Conflict Detection (S-1 Phase 1)** -- conflicts.svelte.ts store tracks per-session Write/Edit file paths. Detects 2+ agents writing same file. 170/170 tests. | Done: 2026-03-10 -- [x] **Project Health Dashboard (S-3)** -- health.svelte.ts store, Mission Control status bar, session_metrics SQLite table. | Done: 2026-03-10 diff --git a/docs/v3-progress.md b/docs/v3-progress.md index 553618f..377bd5a 100644 --- a/docs/v3-progress.md +++ b/docs/v3-progress.md @@ -747,3 +747,20 @@ Ran nemezis-audit on Rust backend. 0 verified exploitable findings, 10 recon tar #### Results - [x] cargo check: clean - [x] cargo test: 49/49 pass + +### Session 2026-03-11 (SOLID Phase 1 Refactoring) + +#### SOLID Analysis +- [x] Ran /solid on full v2 codebase (TypeScript + Rust) +- [x] Identified 3 critical, 5 high, 5 medium issues; 8 good-practice modules + +#### Phase 1 Refactoring — High-impact, Low-risk +- [x] **AttentionScorer extraction**: scoreAttention() pure function from health.svelte.ts → utils/attention-scorer.ts (14 tests) +- [x] **Shared type guards**: str()/num() from 3 adapter copies → utils/type-guards.ts +- [x] **lib.rs command module split**: 976 → 170 lines, 48 commands → 11 domain modules under commands/ +- [x] Skipped withRemoteSupport() HOF — parameter shapes differ, 3-line duplication doesn't justify abstraction + +#### Results +- [x] vitest: 286/286 pass (14 new attention-scorer tests) +- [x] cargo check: clean +- [x] cargo test: 49/49 pass