Skip to content

Commit 40fc5b9

Browse files
committed
docs: map existing codebase
- STACK.md - Technologies and dependencies - ARCHITECTURE.md - System design and patterns - STRUCTURE.md - Directory layout - CONVENTIONS.md - Code style and patterns - TESTING.md - Test structure - INTEGRATIONS.md - External services - CONCERNS.md - Technical debt and issues
1 parent 4171bc5 commit 40fc5b9

File tree

7 files changed

+1071
-0
lines changed

7 files changed

+1071
-0
lines changed

.planning/codebase/ARCHITECTURE.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Architecture
2+
3+
**Analysis Date:** 2026-01-13
4+
5+
## Pattern Overview
6+
7+
**Overall:** Plugin-based architecture with layered state management and event-driven processing
8+
9+
**Key Characteristics:**
10+
- Zellij plugin using WASM (WebAssembly) with WASI sandbox
11+
- Event-driven: Zellij sends events → Plugin processes → State updates → UI renders
12+
- Single executable with two-screen UI (Main list, NewSession creation)
13+
- Stateless request handling within plugin instance
14+
15+
## Layers
16+
17+
**Plugin Layer:**
18+
- Purpose: Zellij plugin trait implementation, event dispatcher
19+
- Contains: `ZellijPlugin` trait methods (`load`, `update`, `pipe`, `render`)
20+
- Location: `src/main.rs`
21+
- Depends on: State layer for coordination
22+
- Used by: Zellij runtime
23+
24+
**State Layer:**
25+
- Purpose: Central state management, business logic coordination
26+
- Contains: `PluginState` struct, key handlers, item combination logic
27+
- Location: `src/state.rs`
28+
- Depends on: Config, Session, Zoxide, NewSessionInfo, UI modules
29+
- Used by: Plugin layer
30+
31+
**Session Layer:**
32+
- Purpose: Zellij session operations, lifecycle management, stability tracking
33+
- Contains: `SessionManager`, `SessionItem`, `SessionAction`
34+
- Location: `src/session/manager.rs`, `src/session/types.rs`
35+
- Depends on: No internal dependencies (isolated)
36+
- Used by: State layer
37+
38+
**Zoxide Layer:**
39+
- Purpose: Directory discovery and fuzzy search
40+
- Contains: `ZoxideDirectory`, `SearchEngine`
41+
- Location: `src/zoxide/directory.rs`, `src/zoxide/search.rs`
42+
- Depends on: Session types (for `SessionItem`)
43+
- Used by: State layer
44+
45+
**UI Layer:**
46+
- Purpose: Terminal rendering
47+
- Contains: `PluginRenderer`, `Theme`, `Colors`, components
48+
- Location: `src/ui/renderer.rs`, `src/ui/theme.rs`, `src/ui/components.rs`
49+
- Depends on: Session types, State for display data
50+
- Used by: Plugin layer (render method)
51+
52+
**Configuration Layer:**
53+
- Purpose: Zellij layout-based configuration parsing
54+
- Contains: `Config` struct
55+
- Location: `src/config.rs`
56+
- Depends on: None
57+
- Used by: State layer
58+
59+
## Data Flow
60+
61+
**Plugin Initialization:**
62+
63+
1. `ZellijPlugin::load()` in `src/main.rs:16` → Registers plugin with Zellij
64+
2. Requests permissions (RunCommands, ReadApplicationState, ChangeApplicationState, MessageAndLaunchOtherPlugins)
65+
3. Subscribes to events (ModeUpdate, SessionUpdate, Key, RunCommandResult, PermissionRequestResult)
66+
67+
**Permission Grant & Zoxide Query:**
68+
69+
1. User receives PermissionRequestResult → `update()` in `src/main.rs:50`
70+
2. `fetch_zoxide_directories()` runs `zoxide query -l -s` command
71+
3. Results returned via RunCommandResult event
72+
73+
**Zoxide Output Processing:**
74+
75+
1. `process_zoxide_output()` in `src/main.rs:161` parses score+path lines
76+
2. `generate_smart_session_names()` creates context-aware names (`src/main.rs:197-235`)
77+
3. Names conflict-resolved with parent context and truncated to 29 chars
78+
4. `update_zoxide_directories()` in `src/state.rs:102` stores directories
79+
80+
**Session Updates:**
81+
82+
1. Zellij sends SessionUpdate event with current and resurrectable sessions
83+
2. `update_sessions()` in `src/state.rs:57` uses stability tracking (MISSING_THRESHOLD=3)
84+
3. Prevents UI flickering from Zellij's inconsistent event timing
85+
86+
**User Interaction:**
87+
88+
1. Key event in `update()``handle_key()` in `src/state.rs:108`
89+
2. Routes to main screen or new session screen handlers
90+
3. Actions trigger session switches, deletions, or new session creation
91+
92+
**State Management:**
93+
- File-based state for previous session: `/tmp/zsm-previous-session`
94+
- Each plugin instance has isolated state (per Zellij session)
95+
- State does not transfer between sessions automatically
96+
97+
## Key Abstractions
98+
99+
**SessionManager:**
100+
- Purpose: Orchestrates Zellij session operations with stability tracking
101+
- Examples: `update_sessions_stable()`, `execute_action()`, `generate_incremented_name()`
102+
- Location: `src/session/manager.rs`
103+
- Pattern: Stability threshold (MISSING_THRESHOLD=3) prevents UI flicker from inconsistent Zellij events
104+
105+
**SessionItem:**
106+
- Purpose: Represents displayable items in the session list
107+
- Examples: `ExistingSession`, `ResurrectableSession`, `Directory`
108+
- Location: `src/session/types.rs`
109+
- Pattern: Enum with variant data
110+
111+
**SearchEngine:**
112+
- Purpose: Fuzzy matching for search functionality
113+
- Examples: `search()`, `update_search()`, `get_results()`
114+
- Location: `src/zoxide/search.rs`
115+
- Pattern: Uses `SkimMatcherV2` from `fuzzy-matcher` crate
116+
117+
**PluginState:**
118+
- Purpose: Central orchestrator holding all plugin state
119+
- Examples: `combined_items()`, `display_items()`, `handle_key()`
120+
- Location: `src/state.rs`
121+
- Pattern: Singleton state container, coordinates between all layers
122+
123+
## Entry Points
124+
125+
**Plugin Entry:**
126+
- Location: `src/main.rs:13` - `register_plugin!(PluginState)` macro
127+
- Triggers: Zellij loads plugin WASM binary
128+
- Responsibilities: Register plugin with Zellij runtime
129+
130+
**ZellijPlugin Implementation:**
131+
- Location: `src/main.rs:15-152`
132+
- Triggers: Zellij events (permissions, keys, session updates)
133+
- Responsibilities: Event dispatch, zoxide command execution, rendering
134+
135+
**Renderer Entry:**
136+
- Location: `src/ui/renderer.rs:14`
137+
- Triggers: Zellij render call
138+
- Responsibilities: Determine active screen, render UI, display overlays
139+
140+
## Error Handling
141+
142+
**Strategy:** Uses `Option<T>` for nullable values, UI error display for user feedback
143+
144+
**Patterns:**
145+
- Validation errors shown via `.set_error()` method (`src/state.rs:26`)
146+
- Error cleared on next keypress
147+
- Permission denial shows error, prevents zoxide fetch
148+
- Invalid session names blocked with descriptive messages
149+
150+
## Cross-Cutting Concerns
151+
152+
**Logging:**
153+
- Plugin logs to Zellij's plugin log output
154+
- No external logging framework
155+
156+
**Validation:**
157+
- Session name validation at creation time (`src/state.rs:614-622`)
158+
- Max 108 bytes, no `/` characters
159+
- Path validation for zoxide results
160+
161+
**Smart Session Naming:**
162+
- Complex algorithm spanning `src/main.rs:197-502`
163+
- Conflict detection, context-aware naming, truncation to 29 chars
164+
- Respects Unix socket path limits
165+
166+
**WASM Sandbox Handling:**
167+
- Direct filesystem writes use sandboxed paths
168+
- Shelling out via `run_command` for persistent file operations
169+
- Inter-plugin communication via `pipe_message_to_plugin`
170+
171+
---
172+
173+
*Architecture analysis: 2026-01-13*
174+
*Update when major patterns change*

.planning/codebase/CONCERNS.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Codebase Concerns
2+
3+
**Analysis Date:** 2026-01-13
4+
5+
## Tech Debt
6+
7+
**Code Duplication - Range Calculation:**
8+
- Issue: Duplicate range-to-render logic
9+
- Location: `src/new_session_info.rs:271` - TODO comment: "merge with similar function in zoxide_directories"
10+
- Why: Rapid development, similar patterns emerged independently
11+
- Impact: Maintenance burden, risk of divergent behavior
12+
- Fix approach: Extract shared utility function
13+
14+
**Complex Smart Naming Algorithm:**
15+
- Issue: 300+ lines of interrelated functions for session name generation
16+
- Location: `src/main.rs:197-502` - `generate_smart_session_names`, `generate_context_aware_name`, `normalize_path`, `apply_smart_truncation`, `abbreviate_segment`
17+
- Why: Feature complexity (conflict detection, context-awareness, truncation limits)
18+
- Impact: Difficult to test, maintain, and debug
19+
- Fix approach: Extract to dedicated module, add comprehensive unit tests
20+
21+
## Known Bugs
22+
23+
**None identified during analysis.**
24+
25+
The codebase appears stable with no obvious bugs. Session stability tracking specifically addresses Zellij's inconsistent event behavior.
26+
27+
## Security Considerations
28+
29+
**Shell Command Injection (Medium Risk):**
30+
- Risk: Session names interpolated into shell commands without escaping
31+
- Location: `src/state.rs:675-686` (write_previous_session function)
32+
- Code: `format!("echo '{}' > /tmp/zsm-previous-session", session_name)`
33+
- Current mitigation: Session name validation blocks `/` characters (`src/state.rs:619-621`)
34+
- Recommendations: Use shell-safe escaping, or write directly if WASM sandbox permits
35+
36+
**World-Writable Temp File:**
37+
- Risk: `/tmp/zsm-previous-session` is world-readable/writable
38+
- Location: `src/state.rs:675, 690`
39+
- Current mitigation: File only contains session name (low sensitivity)
40+
- Recommendations: Use user-specific path or XDG_RUNTIME_DIR
41+
42+
## Performance Bottlenecks
43+
44+
**None identified.**
45+
46+
The codebase handles small datasets (typically <100 directories/sessions). No performance issues expected at current scale.
47+
48+
**Potential Future Concern - Combined Items Rebuild:**
49+
- Location: `src/state.rs:524-529` (update_search_if_needed)
50+
- Pattern: `combined_items()` rebuilds full list on every search update
51+
- Impact: Low with current dataset sizes
52+
- Improvement path: Cache combined items, use incremental updates
53+
54+
## Fragile Areas
55+
56+
**Smart Session Naming Algorithm:**
57+
- Location: `src/main.rs:197-502`
58+
- Why fragile: Complex interdependent functions, many edge cases (Unicode, symlinks, deep paths)
59+
- Common failures: Edge cases with unusual path structures
60+
- Safe modification: Add comprehensive unit tests before changes
61+
- Test coverage: **None** - HIGH RISK
62+
63+
**WASM Sandbox Limitations:**
64+
- Location: `src/state.rs:675-702` (file I/O workarounds)
65+
- Why fragile: Relies on shelling out to bypass WASM restrictions
66+
- Common failures: File persistence issues, race conditions between plugin instances
67+
- Safe modification: Understand WASM sandbox constraints before changes
68+
- Test coverage: Cannot test in isolation (WASM-specific)
69+
70+
## Scaling Limits
71+
72+
**Not applicable.**
73+
74+
Plugin runs locally with user's directory history. No cloud services or shared resources.
75+
76+
## Dependencies at Risk
77+
78+
**All dependencies current (as of Jan 2026):**
79+
- `zellij-tile 0.43.1` - Actively maintained with Zellij
80+
- `zellij-utils 0.43.1` - Same lifecycle as zellij-tile
81+
- `serde 1.0.164` - Stable, widely used
82+
- `fuzzy-matcher 0.3.7` - Stable, minimal updates expected
83+
- `uuid 1.8.0` - Stable, widely used
84+
- `humantime 2.2.0` - Stable, low update frequency
85+
86+
No immediate risks identified.
87+
88+
## Missing Critical Features
89+
90+
**None identified.**
91+
92+
The plugin provides complete session/directory management functionality as designed.
93+
94+
## Test Coverage Gaps
95+
96+
**Smart Naming Algorithm (HIGH PRIORITY):**
97+
- What's not tested: 503 lines of logic in `src/main.rs` - conflict detection, context naming, truncation
98+
- Location: `src/main.rs:197-502`
99+
- Risk: Naming bugs affect user experience, edge cases unknown
100+
- Priority: HIGH
101+
- Difficulty to test: Medium - need to mock or construct path data
102+
103+
**State Coordination Logic:**
104+
- What's not tested: 709 lines in `src/state.rs` - display logic, selection, item combination
105+
- Location: `src/state.rs`
106+
- Risk: State management bugs could cause UI issues
107+
- Priority: Medium
108+
- Difficulty to test: Medium - need to simulate events
109+
110+
**Fuzzy Search Engine:**
111+
- What's not tested: 204 lines in `src/zoxide/search.rs`
112+
- Location: `src/zoxide/search.rs`
113+
- Risk: Search ranking issues
114+
- Priority: Low (uses well-tested fuzzy-matcher crate)
115+
- Difficulty to test: Low - pure function logic
116+
117+
**UI Rendering:**
118+
- What's not tested: 431 lines in `src/ui/renderer.rs`
119+
- Location: `src/ui/renderer.rs`
120+
- Risk: Display issues
121+
- Priority: Low (visual verification during development)
122+
- Difficulty to test: High - Zellij rendering API
123+
124+
## Minor Issues
125+
126+
**Error Messages Clear on Any Keypress:**
127+
- Location: `src/state.rs:108-113`
128+
- Behavior: Any keypress clears error, even if user didn't read it
129+
- UX impact: Users might miss validation errors
130+
- Recommendation: Only clear errors on meaningful actions
131+
132+
**Unicode Truncation Edge Case:**
133+
- Location: `src/main.rs:343-344`
134+
- Problem: `.len()` counts bytes, not characters; multibyte UTF-8 could truncate mid-character
135+
- Impact: Low probability (requires non-ASCII paths)
136+
- Recommendation: Use `.chars().count()` or check byte boundaries
137+
138+
**Configuration Delimiter Fragility:**
139+
- Location: `src/config.rs:43-51`
140+
- Issue: `base_paths` uses `|` delimiter with no escape mechanism
141+
- Impact: Cannot use `|` in paths (edge case)
142+
- Recommendation: Document limitation or add escape support
143+
144+
---
145+
146+
## Summary
147+
148+
**Overall Assessment:** Clean, well-structured codebase with no critical issues.
149+
150+
**Priorities:**
151+
1. **HIGH**: Add unit tests for smart naming algorithm (`src/main.rs:197-502`)
152+
2. **MEDIUM**: Address shell command injection concern in session persistence
153+
3. **LOW**: Extract duplicate range calculation logic
154+
155+
**Positive Notes:**
156+
- No `unsafe` blocks
157+
- No unchecked `unwrap()` or `expect()` calls
158+
- Good inline documentation
159+
- CI/CD properly configured with tests, clippy, and fmt checks
160+
- Error handling is defensive and informative
161+
162+
---
163+
164+
*Concerns audit: 2026-01-13*
165+
*Update as issues are fixed or new ones discovered*

0 commit comments

Comments
 (0)