Skip to content

Commit 28a8567

Browse files
AlexMikhalevclaude
andcommitted
docs: research and design for issue #611 sessions files subcommands
Add comprehensive research and implementation plan for: - sessions files <session-id> subcommand - sessions by-file <file-path> subcommand Documents: - Current session architecture in terraphim_sessions - Tool input extraction from ContentBlock::ToolUse - File path categorization (read vs write) - Implementation steps across 7 phases Part of: #611 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4c310c9 commit 28a8567

2 files changed

Lines changed: 624 additions & 0 deletions

File tree

docs/research/design-issue-611.md

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
# Implementation Plan: Issue #611 - Sessions Files and By-File Subcommands
2+
3+
**Status**: Draft
4+
**Research Doc**: docs/research/research-issue-611.md
5+
**Author**: Claude Code
6+
**Date**: 2026-03-11
7+
**Estimated Effort**: 4-6 hours
8+
9+
## Overview
10+
11+
### Summary
12+
Add `sessions files <session-id>` and `sessions by-file <file-path>` subcommands to terraphim-agent. Extract file paths from tool invocations in session messages and categorize them as read vs written.
13+
14+
### Approach
15+
Extend the existing session infrastructure:
16+
1. Add data types (`FileAccess`, `FileOperation`) to `terraphim_sessions`
17+
2. Add service methods (`extract_files`, `sessions_by_file`) to `SessionService`
18+
3. Extend `SessionsSubcommand` enum and parsing in `terraphim_agent`
19+
4. Add handler methods with table and JSON output
20+
21+
### Scope
22+
**In Scope:**
23+
- `sessions files <session-id> [--json]` subcommand
24+
- `sessions by-file <file-path> [--json]` subcommand
25+
- File path extraction from 7 tool types (Read, Edit, Write, MultiEdit, NotebookEdit, Glob, Grep)
26+
- Read vs Write categorization
27+
- Table output (default) and JSON output (--json)
28+
29+
**Out of Scope:**
30+
- File content diff tracking
31+
- Git integration
32+
- Real-time file watching
33+
- Path canonicalization/normalization
34+
35+
**Avoid At All Cost:**
36+
- Complex path resolution (relative vs absolute)
37+
- File system access (stat, exists checks)
38+
- Content hashing or comparison
39+
40+
## Architecture
41+
42+
### Component Diagram
43+
```
44+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
45+
│ CLI Parser │────▶│ SessionsSubcommand│────▶│ Handler Logic │
46+
│ (commands.rs) │ │ (commands.rs) │ │ (handler.rs) │
47+
└─────────────────┘ └──────────────────┘ └────────┬────────┘
48+
49+
┌────────────────────────┐
50+
51+
┌──────────────────┐
52+
│ SessionService │
53+
│ (terraphim_) │
54+
└────────┬─────────┘
55+
56+
┌────────▼────────┐
57+
│ Session Cache │
58+
│ (HashMap) │
59+
└────────┬────────┘
60+
61+
┌────────▼────────┐
62+
│ ContentBlock:: │
63+
│ ToolUse parsing │
64+
└─────────────────┘
65+
```
66+
67+
### Data Flow
68+
```
69+
User Input: "sessions files abc123"
70+
71+
Parse: SessionsSubcommand::Files { session_id: "abc123", json: false }
72+
73+
Handler: handle_sessions() -> handle_files_subcommand()
74+
75+
Service: session_service.extract_files("abc123")
76+
77+
Extract: Iterate messages -> ContentBlock::ToolUse -> extract path
78+
79+
Categorize: tool_name -> FileOperation::Read/Write
80+
81+
Output: Table or JSON with file paths and operations
82+
```
83+
84+
### Key Design Decisions
85+
| Decision | Rationale | Alternatives Rejected |
86+
|----------|-----------|----------------------|
87+
| Add types to terraphim_sessions | Single source of truth | Inline in handler |
88+
| Simple string matching for paths | Avoids filesystem dependencies | Path canonicalization |
89+
| Tool name determines read/write | Clear categorization | Analyzing tool output |
90+
91+
### Simplicity Check
92+
**What if this could be easy?**
93+
- Extract paths from JSON, no filesystem access
94+
- Tool name determines operation type
95+
- Simple substring matching for by-file search
96+
97+
## File Changes
98+
99+
### Modified Files
100+
| File | Changes |
101+
|------|---------|
102+
| `terraphim_sessions/src/model.rs` | Add `FileAccess`, `FileOperation` types |
103+
| `terraphim_sessions/src/service.rs` | Add `extract_files()`, `sessions_by_file()` |
104+
| `terraphim_agent/src/repl/commands.rs` | Extend `SessionsSubcommand`, add parsing |
105+
| `terraphim_agent/src/repl/handler.rs` | Add handler methods for new subcommands |
106+
107+
## API Design
108+
109+
### Public Types
110+
```rust
111+
/// File access operation type
112+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
113+
pub enum FileOperation {
114+
Read,
115+
Write,
116+
}
117+
118+
impl Display for FileOperation { ... }
119+
120+
/// Record of a file access in a session
121+
#[derive(Debug, Clone, Serialize, Deserialize)]
122+
pub struct FileAccess {
123+
pub path: String,
124+
pub operation: FileOperation,
125+
pub timestamp: Option<jiff::Timestamp>,
126+
pub tool_name: String,
127+
}
128+
```
129+
130+
### Public Functions
131+
```rust
132+
impl SessionService {
133+
/// Extract all file accesses from a session
134+
pub async fn extract_files(&self, session_id: &SessionId) -> Vec<FileAccess>;
135+
136+
/// Find sessions that accessed a file (substring match)
137+
pub async fn sessions_by_file(&self, file_path: &str) -> Vec<(Session, Vec<FileAccess>)>;
138+
}
139+
140+
impl Session {
141+
/// Extract file accesses from this session
142+
pub fn extract_file_accesses(&self) -> Vec<FileAccess>;
143+
}
144+
```
145+
146+
### Command Parsing
147+
```rust
148+
pub enum SessionsSubcommand {
149+
// ... existing variants
150+
151+
/// List files touched by a session
152+
Files {
153+
session_id: String,
154+
json: bool,
155+
},
156+
157+
/// Find sessions that touched a file
158+
ByFile {
159+
file_path: String,
160+
json: bool,
161+
},
162+
}
163+
```
164+
165+
## Test Strategy
166+
167+
### Unit Tests
168+
| Test | Location | Purpose |
169+
|------|----------|---------|
170+
| `test_extract_files_read` | `terraphim_sessions/model.rs` | Verify Read tool extraction |
171+
| `test_extract_files_write` | `terraphim_sessions/model.rs` | Verify Write tool extraction |
172+
| `test_extract_files_notebook` | `terraphim_sessions/model.rs` | Verify notebook_path extraction |
173+
| `test_sessions_by_file` | `terraphim_sessions/service.rs` | Verify file search |
174+
175+
### Integration Tests
176+
| Test | Location | Purpose |
177+
|------|----------|---------|
178+
| `test_sessions_files_command` | `terraphim_agent/tests` | Full CLI flow |
179+
| `test_sessions_byfile_command` | `terraphim_agent/tests` | Full CLI flow |
180+
181+
## Implementation Steps
182+
183+
### Step 1: Add FileAccess Types to terraphim_sessions
184+
**Files:** `crates/terraphim_sessions/src/model.rs`
185+
**Description:** Add `FileOperation` enum and `FileAccess` struct
186+
**Tests:** Unit tests for type construction
187+
**Estimated:** 30 minutes
188+
189+
```rust
190+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
191+
pub enum FileOperation {
192+
Read,
193+
Write,
194+
}
195+
196+
#[derive(Debug, Clone, Serialize, Deserialize)]
197+
pub struct FileAccess {
198+
pub path: String,
199+
pub operation: FileOperation,
200+
pub timestamp: Option<jiff::Timestamp>,
201+
pub tool_name: String,
202+
}
203+
```
204+
205+
### Step 2: Add File Extraction to Session Model
206+
**Files:** `crates/terraphim_sessions/src/model.rs`
207+
**Description:** Implement `extract_file_accesses()` method on `Session`
208+
**Tests:** Test with various tool input formats
209+
**Dependencies:** Step 1
210+
**Estimated:** 1 hour
211+
212+
```rust
213+
impl Session {
214+
pub fn extract_file_accesses(&self) -> Vec<FileAccess> {
215+
// Iterate messages, find ToolUse blocks, extract paths
216+
// Return Vec<FileAccess>
217+
}
218+
}
219+
```
220+
221+
### Step 3: Add Service Methods
222+
**Files:** `crates/terraphim_sessions/src/service.rs`
223+
**Description:** Add `extract_files()` and `sessions_by_file()` to `SessionService`
224+
**Tests:** Unit tests with test sessions
225+
**Dependencies:** Step 2
226+
**Estimated:** 45 minutes
227+
228+
```rust
229+
impl SessionService {
230+
pub async fn extract_files(&self, session_id: &SessionId) -> Vec<FileAccess> {
231+
self.get_session(session_id).await
232+
.map(|s| s.extract_file_accesses())
233+
.unwrap_or_default()
234+
}
235+
236+
pub async fn sessions_by_file(&self, file_path: &str) -> Vec<(Session, Vec<FileAccess>)> {
237+
// Search all sessions, return those with matching file paths
238+
}
239+
}
240+
```
241+
242+
### Step 4: Extend SessionsSubcommand
243+
**Files:** `crates/terraphim_agent/src/repl/commands.rs`
244+
**Description:** Add `Files` and `ByFile` variants, update parsing
245+
**Tests:** Command parsing tests
246+
**Dependencies:** None
247+
**Estimated:** 45 minutes
248+
249+
### Step 5: Add Handler Methods
250+
**Files:** `crates/terraphim_agent/src/repl/handler.rs`
251+
**Description:** Add handlers for `Files` and `ByFile` subcommands
252+
**Tests:** Integration with SessionService
253+
**Dependencies:** Steps 3, 4
254+
**Estimated:** 1 hour
255+
256+
```rust
257+
async fn handle_sessions(&mut self, subcommand: SessionsSubcommand) -> Result<()> {
258+
match subcommand {
259+
// ... existing handlers
260+
SessionsSubcommand::Files { session_id, json } => {
261+
self.handle_files(session_id, json).await
262+
}
263+
SessionsSubcommand::ByFile { file_path, json } => {
264+
self.handle_by_file(file_path, json).await
265+
}
266+
}
267+
}
268+
```
269+
270+
### Step 6: Add Unit Tests
271+
**Files:** `crates/terraphim_sessions/src/model.rs`, `service.rs`
272+
**Description:** Comprehensive tests for extraction logic
273+
**Estimated:** 45 minutes
274+
275+
### Step 7: Verification
276+
**Command:** `cargo check --workspace`
277+
**Command:** `cargo test -p terraphim_sessions`
278+
**Command:** `cargo test -p terraphim_agent --features repl-sessions`
279+
**Estimated:** 15 minutes
280+
281+
## Rollback Plan
282+
283+
If issues discovered:
284+
1. Revert changes to the 4 modified files
285+
2. Keep research and design documents for future reference
286+
287+
## Dependencies
288+
289+
No new dependencies required.
290+
291+
## Performance Considerations
292+
293+
| Metric | Target | Measurement |
294+
|--------|--------|-------------|
295+
| Extraction time | < 10ms per session | Benchmark with 1000 message session |
296+
| Memory overhead | O(n) where n = file accesses | Profiling |
297+
| Search time | < 100ms for 1000 sessions | Benchmark |
298+
299+
## Open Items
300+
301+
None.
302+
303+
## Approval
304+
305+
- [ ] Technical review complete
306+
- [ ] Test strategy approved
307+
- [ ] Human approval received

0 commit comments

Comments
 (0)