diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index b5255b3..f81fe3c 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -58,6 +58,7 @@ - tool-files.ts utility: shared extractFilePaths(tc) → ToolFileRef[], extractWritePaths(tc) → string[], extractWorktreePath(tc) → string|null. Bash write detection via regex (>, >>, sed -i, tee, cp, mv). Used by ContextTab (all ops) and agent-dispatcher (writes + worktree tracking for conflict detection). - ProjectHeader shows status dot (green pulse=running, gray=idle, orange pulse=stalled, dim=inactive) + external write badge (orange ⚡ clickable, shown when externalConflictCount > 0) + agent conflict badge (red ⚠ clickable with ✕) + context pressure badge (>90% red, >75% orange, >50% yellow) + burn rate badge ($/hr). Health prop from ProjectBox via getProjectHealth(). ProjectBox starts/stops fs watcher per project CWD via $effect. - session_metrics SQLite table: per-project historical session data (project_id, session_id, timestamps, peak_tokens, turn_count, tool_call_count, cost_usd, model, status, error_message). 100-row retention per project. Tauri commands: session_metric_save, session_metrics_load. Persisted on agent completion via agent-dispatcher. +- Session anchors (S-2): Preserves important turns through compaction chains. Types: auto (on first compaction, 3 turns, 6144 token budget, observation-masked), pinned (user-created via pin button in AgentPane), promoted (user-promoted from pinned, re-injectable). Re-injection: anchors.svelte.ts → AgentPane.startQuery() → system_prompt field → sidecar → SDK. ContextTab shows anchor section with budget meter + promote/demote. SQLite: session_anchors table. Files: types/anchors.ts, adapters/anchors-bridge.ts, stores/anchors.svelte.ts, utils/anchor-serializer.ts. Ollama warning toast when injecting anchors with potentially small context window. - Agent tree (AgentTree.svelte) uses SVG with recursive layout. Tree data built by `agent-tree.ts` utility from agent messages. - ctx integration opens `~/.claude-context/context.db` as SQLITE_OPEN_READ_ONLY — never writes. CtxDb uses Option for graceful absence if DB doesn't exist. - SSH sessions spawn TerminalPane with shell=/usr/bin/ssh and args array. No SSH library needed — PTY handles it natively. diff --git a/CHANGELOG.md b/CHANGELOG.md index e702f1e..922e6b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `claude_read_skill` path traversal: added `canonicalize()` + `starts_with()` validation to prevent reading arbitrary files via crafted skill paths (lib.rs) ### Added +- **S-2 Session Anchors** — preserves important conversation turns through context compaction chains. Auto-anchors first 3 turns (6144 token budget) with observation masking on first compaction event. Manual pin button on AgentPane text messages. Three anchor types: auto (re-injectable), pinned (display-only), promoted (user-promoted, re-injectable). Re-injection via `system_prompt` field. ContextTab anchor section with budget meter bar, per-anchor promote/demote/remove actions. Ollama context warning toast when injecting into small context windows. SQLite `session_anchors` table with 5 CRUD commands. 5 new files (types/anchors.ts, anchors-bridge.ts, anchors.svelte.ts, anchor-serializer.ts, anchor-serializer.test.ts), 7 modified. 219 vitest + 42 cargo tests - **Agent provider adapter pattern** — full implementation (3 phases complete): core abstraction layer (provider types/registry/capabilities, message adapter registry, 4 file renames), Settings UI (collapsible per-provider config panels, per-project provider dropdown, settings persistence), sidecar routing (provider-based runner selection, env var stripping for CLAUDE*/CODEX*/OLLAMA*). 5 new files, 4 renames, 20+ modified. 6 architecture decisions (PA-1–PA-6). Docs at `docs/provider-adapter/` - **PDF viewer** in Files tab: `PdfViewer.svelte` using pdfjs-dist (v5.5.207). Canvas-based multi-page rendering, zoom controls (0.5x–3x, 25% steps), HiDPI-aware via devicePixelRatio. Reads PDF via `convertFileSrc()` — no new Rust commands needed - **CSV table view** in Files tab: `CsvTable.svelte` with RFC 4180 CSV parser (no external dependency). Auto-detects delimiter (comma, semicolon, tab). Sortable columns (numeric-aware), sticky header, row numbers, text truncation at 20rem diff --git a/CLAUDE.md b/CLAUDE.md index 7381313..9023c84 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -40,7 +40,7 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `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) | -| `v2/src-tauri/src/session.rs` | SessionDb (rusqlite, sessions + layout + settings + ssh_sessions + agent_messages + project_agent_state) | +| `v2/src-tauri/src/session.rs` | SessionDb (rusqlite, sessions + layout + settings + ssh_sessions + agent_messages + project_agent_state + session_anchors) | | `v2/src-tauri/src/watcher.rs` | FileWatcherManager (notify crate, file change events) | | `v2/src-tauri/src/ctx.rs` | CtxDb (read-only access to ~/.claude-context/context.db) | | `v2/src-tauri/src/telemetry.rs` | OTEL telemetry (TelemetryGuard, tracing + OTLP export, BTERMINAL_OTLP_ENDPOINT) | @@ -69,6 +69,7 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `v2/src/lib/adapters/files-bridge.ts` | File browser IPC wrapper (list_directory_children, read_file_content) | | `v2/src/lib/adapters/memory-adapter.ts` | Pluggable memory adapter interface (MemoryAdapter, registry) | | `v2/src/lib/adapters/fs-watcher-bridge.ts` | Filesystem watcher IPC wrapper (project CWD write detection) | +| `v2/src/lib/adapters/anchors-bridge.ts` | Session anchors IPC wrapper (save, load, delete, clear, updateType) | | `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) | @@ -88,6 +89,9 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `v2/src/lib/components/Workspace/CsvTable.svelte` | CSV table viewer (RFC 4180 parser, delimiter auto-detect, sortable columns) | | `v2/src/lib/stores/health.svelte.ts` | Project health store (activity state, burn rate, context pressure, file conflicts, attention scoring) | | `v2/src/lib/stores/conflicts.svelte.ts` | File overlap + external write conflict detection (per-project, session-scoped, worktree-aware, dismissible, inotify-backed) | +| `v2/src/lib/stores/anchors.svelte.ts` | Session anchor store (per-project anchors, auto-anchor tracking, re-injection support) | +| `v2/src/lib/types/anchors.ts` | Anchor types (AnchorType, SessionAnchor, AnchorSettings, SessionAnchorRecord) | +| `v2/src/lib/utils/anchor-serializer.ts` | Anchor serialization (turn grouping, observation masking, token estimation) | | `v2/src/lib/utils/tool-files.ts` | Shared file path extraction from tool_call inputs (extractFilePaths, extractWritePaths, extractWorktreePath) | | `v2/src/lib/components/StatusBar/StatusBar.svelte` | Mission Control bar (agent states, $/hr burn rate, attention queue, cost) | | `v2/src/lib/components/Notifications/ToastContainer.svelte` | Toast notification display | diff --git a/TODO.md b/TODO.md index 8ccb46e..cacadd6 100644 --- a/TODO.md +++ b/TODO.md @@ -10,11 +10,11 @@ - [ ] **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. - [ ] **Configurable stall threshold** -- health.yaml per-project config for stall threshold (currently hardcoded 15 min). Adaptive suggestions after 50 sessions from session_metrics data. - [ ] **Add Codex/Ollama provider runners** -- Provider adapter pattern implemented (all 3 phases). Need to create codex-runner.ts and ollama-runner.ts sidecar runners + corresponding message adapters (codex-messages.ts, ollama-messages.ts) + register providers in App.svelte. -- [ ] **S-2 — session anchors** -- Preserve first 5 turns / 2K tokens verbatim through checkpoint chains. Pin additional turns via AST conversation tree action. - [ ] **Worktree isolation per project (S-1 Phase 3)** -- Three parts: (1) **UI toggle**: useWorktrees checkbox in SettingsTab per-project settings, persisted in groups.json ProjectConfig. (2) **Spawn with --worktree**: when useWorktrees=true, pass `--worktree ` flag to Claude Code CLI via sidecar AgentQueryOptions. Sidecar creates worktree at `/.claude/worktrees//`, agent CWD is set there. (3) **Worktree detection improvement**: current extractWorktreePath checks tool_call params, but agents don't signal worktrees in tool calls — the real signal is CWD-based (path contains `.claude/worktrees/`) or from sidecar notification events (`worktreePath`/`worktreeBranch` fields, Claude Code v2.1.72+). Update agent-dispatcher to parse init event CWD or notification fields. For Codex/Cursor agents: detect `$CODEX_HOME/worktrees/` or `~/.cursor/worktrees/` CWD patterns. Conflict suppression already works once worktree is registered via setSessionWorktree(). ## Completed +- [x] **S-2 — Session Anchors** -- Preserves important turns through compaction chains. Auto-anchors first 3 turns (6144 token budget, observation-masked) on first compaction event. Manual pin via AgentPane button. Promote/demote in ContextTab. Re-injection via system_prompt. Ollama context warning. 5 new files, 7 modified. 219 vitest + 42 cargo tests. | Done: 2026-03-11 - [x] **Agent provider adapter pattern** -- Multi-provider support (Claude, Codex, Ollama) via 3-phase adapter pattern. Core abstraction (provider types/registry/capabilities, message adapter registry, file renames), Settings UI (collapsible provider panels, per-project dropdown), Sidecar routing (provider-based runner selection, env var stripping). 5 new files, 4 renames, 20+ modified. 202 vitest + 42 cargo tests. | Done: 2026-03-11 - [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). FilesTab routing: Binary+pdf→PdfViewer, Text+csv→CsvTable. | 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 — suppresses agent's own writes, surfaces external edits. EXTERNAL_SESSION_ID sentinel, recordExternalWrite(), externalConflictCount. Orange "ext write" badge + red "agent conflict" badge in ProjectHeader. ProjectBox $effect starts/stops per-project. Inotify watch limit sensing: reads /proc/sys max_user_watches, counts watched dirs, warns at >75% usage with fix command. 202/202 vitest + 42/42 cargo tests. | Done: 2026-03-11 @@ -24,4 +24,3 @@ - [x] **Context tab repurpose** -- Replaced ContextPane (ctx database viewer) with ContextTab (LLM context window visualization). Stats bar, segmented token meter, file references, turn breakdown. Tribunal debate (S-1-R4 at 82%). Token estimation via ~4 chars/token heuristic. | Done: 2026-03-10 - [x] **CodeMirror 6 editor** -- Replaced shiki viewer in FilesTab with CodeMirror 6. CodeEditor.svelte wrapper: 15 lazy-loaded language modes, Catppuccin theme, auto-close brackets, bracket matching, code folding, Ctrl+S save, dirty tracking, save-on-blur setting. write_file_content Rust command. | Done: 2026-03-10 - [x] **FilesTab reactivity fixes** -- Fixed HTML nesting (