Add Project Roman session fix analysis and design documentation
This commit includes comprehensive analysis and design documentation for fixing critical session management issues in manually created projects. Phase 1 Complete: - Identified 4 critical errors (SSE null reference, array access, race conditions, virtual workingDir mismatch) - Created detailed root cause analysis - Designed comprehensive solution with 5 components - Complete implementation plan with testing strategy Files added: - ROMAN_SESSION_ISSUE_ANALYSIS.md - Detailed root cause analysis - ROMAN_SESSION_FIX_DESIGN.md - Complete solution design - ROMAN_IMPLEMENTATION_SUMMARY.md - Quick reference guide - PHASE_1_COMPLETE_REPORT.md - Executive summary Next: Awaiting AI Engineer review before implementation Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
205
ROMAN_SESSION_ISSUE_ANALYSIS.md
Normal file
205
ROMAN_SESSION_ISSUE_ANALYSIS.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# Project Roman Session Issue - Phase 1 Analysis Report
|
||||
|
||||
## Problem Statement
|
||||
When entering project "roman", the following errors occur:
|
||||
1. Console errors appear immediately
|
||||
2. Sessions do not show in the left sidebar
|
||||
3. The `pendingSessionAdd` approach is fragile and causes race conditions
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
### Error 1: "Cannot set properties of null (setting 'onopen')"
|
||||
**Location:** `/home/uroma/obsidian-web-interface/public/claude-ide/sse-client.js:41`
|
||||
**Cause:** The SSE client attempts to connect to a session before the EventSource object is fully initialized.
|
||||
|
||||
```javascript
|
||||
this.eventSource = new EventSource(url);
|
||||
this.eventSource.onopen = () => { ... } // EventSource may be null here
|
||||
```
|
||||
|
||||
**Why it happens for project "roman":**
|
||||
- Project "roman" uses a virtual workingDir: `/virtual/projects/roman`
|
||||
- When the project loads, it tries to auto-connect to existing sessions
|
||||
- If a session doesn't exist yet or is in a transitional state, EventSource construction fails
|
||||
- The code doesn't check if `this.eventSource` is null before setting `onopen`
|
||||
|
||||
### Error 2: "Cannot read properties of undefined (reading 'length')"
|
||||
**Location:** Multiple locations in project-manager.js and chat-enhanced.js
|
||||
**Cause:** Arrays are undefined when operations are performed before data is fully loaded.
|
||||
|
||||
**Specific instances:**
|
||||
1. `project-manager.js:104` - Sorting sessions array before it's populated
|
||||
2. `chat-enhanced.js:69` - Rendering sessions when `sessionsToRender` is `undefined`
|
||||
3. `chat-functions.js:72` - Accessing `activeProject.sessions` when project isn't loaded yet
|
||||
|
||||
### Error 3: Sessions Not Showing in Left Sidebar
|
||||
**Root Cause:** Multiple sources of truth for session data
|
||||
|
||||
**Sources of truth:**
|
||||
1. `this.projects.sessions` - In-memory project state
|
||||
2. `localStorage` - Persisted manually created projects
|
||||
3. `/claude/api/claude/sessions` - API response
|
||||
4. `this.pendingSessionAdd` - Race condition workaround
|
||||
|
||||
**The race condition flow:**
|
||||
```
|
||||
1. createSessionInFolder() called
|
||||
2. POST /claude/api/claude/sessions - creates session in backend
|
||||
3. pendingSessionAdd = session - stores in frontend
|
||||
4. loadProjects() called - fetches from API
|
||||
5. - API response doesn't include the new session yet (timing)
|
||||
6. - pendingSessionAdd is added to allSessions (workaround)
|
||||
7. addSessionToProject() called
|
||||
8. loadProjects() called AGAIN
|
||||
9. Sessions array reset to empty (localStorage sessions loaded)
|
||||
10. Session lost!
|
||||
```
|
||||
|
||||
### Error 4: Virtual Working Directory Mismatch
|
||||
**Issue:** The project "roman" was created with `workingDir: "/home/uroma/obsidian-vault"` but should have been `"/virtual/projects/roman"`
|
||||
|
||||
**Evidence from logs:**
|
||||
```
|
||||
[ProjectManager] workingDir: /home/uroma/obsidian-vault
|
||||
[ProjectManager] No virtual sessions found for project: roman
|
||||
```
|
||||
|
||||
**The code correctly assigns virtual workingDir on creation (line 473):**
|
||||
```javascript
|
||||
const virtualWorkingDir = `/virtual/projects/${projectKey}`;
|
||||
```
|
||||
|
||||
**But the stored localStorage has the wrong value:**
|
||||
```javascript
|
||||
{"id":"project-roman","name":"roman","workingDir":"/home/uroma/obsidian-vault",...}
|
||||
```
|
||||
|
||||
## Architectural Issues
|
||||
|
||||
### 1. Multiple Data Sources Without Single Source of Truth
|
||||
```
|
||||
Frontend State (this.projects)
|
||||
↕
|
||||
localStorage (claude_ide_projects)
|
||||
↕
|
||||
API Response (/claude/api/claude/sessions)
|
||||
↕
|
||||
Backend State (claudeService.sessions)
|
||||
```
|
||||
|
||||
Each can be out of sync with the others.
|
||||
|
||||
### 2. Race Conditions in Initialization
|
||||
```
|
||||
DOMContentLoaded → ProjectManager.initialize()
|
||||
↓
|
||||
loadManuallyCreatedProjects()
|
||||
↓
|
||||
loadProjects() ← async fetch
|
||||
↓
|
||||
renderProjectTabs()
|
||||
↓
|
||||
switchProject() ← may happen before loadProjects() completes
|
||||
```
|
||||
|
||||
### 3. Fragile pendingSessionAdd Pattern
|
||||
The `pendingSessionAdd` approach tries to work around timing issues but:
|
||||
- Only preserves one session at a time
|
||||
- Gets cleared too early or too late
|
||||
- Doesn't survive page refreshes
|
||||
- Creates complex conditional logic
|
||||
|
||||
### 4. Virtual Session Assignment Logic
|
||||
The virtual session filtering logic is complex and error-prone:
|
||||
```javascript
|
||||
if (dir.startsWith('/virtual/projects/')) {
|
||||
const sessionProjectKey = s.workingDir?.replace('/virtual/projects/', '');
|
||||
return sessionProjectKey === key;
|
||||
}
|
||||
```
|
||||
|
||||
This assumes a perfect mapping between workingDir and projectKey, but:
|
||||
- Manually created projects may have different workingDir values
|
||||
- The key transformation (`projectKey = projectName.trim().replace(/\s+/g, '-').toLowerCase()`) can create mismatches
|
||||
- No validation that the workingDir matches the expected pattern
|
||||
|
||||
## Impact Analysis
|
||||
|
||||
### User Impact
|
||||
- Cannot see sessions in manually created projects
|
||||
- Console errors on every page load
|
||||
- Sessions may disappear after refresh
|
||||
- New sessions may not appear immediately
|
||||
|
||||
### System Impact
|
||||
- Error logs fill up rapidly
|
||||
- Multiple unnecessary API calls
|
||||
- Inconsistent state across components
|
||||
- Difficult to debug due to multiple layers
|
||||
|
||||
## Proposed Solution Architecture
|
||||
|
||||
### Phase 2 Design Goals
|
||||
|
||||
1. **Single Source of Truth**: API is the only source; localStorage is cache only
|
||||
2. **Event-Driven Updates**: Use EventBus for all state changes
|
||||
3. **Defensive Programming**: All array operations check for null/undefined
|
||||
4. **Virtual Project Consistency**: Ensure workingDir matches project identity
|
||||
5. **Real-Time Logger**: Enhanced monitoring and debugging
|
||||
|
||||
### Solution Components
|
||||
|
||||
1. **Fix SSE Client Initialization**
|
||||
- Add null checks before EventSource property assignment
|
||||
- Wrap EventSource construction in try-catch
|
||||
- Add connection state validation
|
||||
|
||||
2. **Fix Array Access Errors**
|
||||
- Add null/undefined guards to all array operations
|
||||
- Use optional chaining (`?.`) and nullish coalescing (`??`)
|
||||
- Add validation before sorting/filtering
|
||||
|
||||
3. **Implement Proper State Management**
|
||||
- Remove `pendingSessionAdd` pattern
|
||||
- Use optimistic UI updates with rollback
|
||||
- Implement proper loading states
|
||||
- Use EventBus for synchronization
|
||||
|
||||
4. **Fix Virtual Working Directory Consistency**
|
||||
- Validate workingDir on project creation
|
||||
- Add migration for existing projects
|
||||
- Use consistent key generation
|
||||
|
||||
5. **Enhanced Real-Time Logger**
|
||||
- Log all state transitions
|
||||
- Track API calls and responses
|
||||
- Monitor EventBus traffic
|
||||
- Alert on error patterns
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Technical Metrics
|
||||
- ✅ No console errors on project load
|
||||
- ✅ Zero race conditions in session creation
|
||||
- ✅ Consistent state across all components
|
||||
- ✅ All operations defensive against null/undefined
|
||||
|
||||
### User Experience Metrics
|
||||
- ✅ Sessions appear immediately after creation
|
||||
- ✅ Sessions persist across page refresh
|
||||
- ✅ Left sidebar always shows current project sessions
|
||||
- ✅ No flickering or loading states
|
||||
|
||||
## Next Steps (Phase 2: Design Review)
|
||||
|
||||
Before implementing, the following needs AI Engineer review:
|
||||
1. Proposed EventBus integration pattern
|
||||
2. State synchronization strategy
|
||||
3. Virtual project key generation approach
|
||||
4. Error handling and recovery mechanisms
|
||||
|
||||
---
|
||||
|
||||
**Generated:** 2026-01-22
|
||||
**Status:** Phase 1 Complete - Analysis Complete
|
||||
**Next:** Phase 2 - Design & AI Engineer Review
|
||||
Reference in New Issue
Block a user