agent-ecosystem/.planning/phases/01-provider-plumbing/01-01-SUMMARY.md
matt ae4833e310 feat(planning): add project planning documents and configuration for SSH multi-context workspaces
- Introduced new planning files including PROJECT.md, REQUIREMENTS.md, ROADMAP.md, and STATE.md to outline the vision and requirements for SSH multi-context workspaces.
- Added ARCHITECTURE.md and CONCERNS.md to detail the codebase structure and address technical debt, known bugs, and security considerations.
- Created CONVENTIONS.md to establish coding standards and practices for the project.
- Updated .gitignore to exclude demo files and added configuration for planning tools.

This commit lays the groundwork for enhancing SSH functionality and user experience in managing multiple workspaces.
2026-02-12 09:37:58 +09:00

7.2 KiB

phase plan subsystem tags dependency-graph tech-stack key-files decisions metrics
01-provider-plumbing 01 session-parsing
ssh-support
provider-threading
refactoring
requires provides affects
FileSystemProvider
ProjectScanner
provider-aware-parsing
provider-aware-subagent-detail
SessionParser
SubagentResolver
SubagentDetailBuilder
ChunkBuilder
IPC-handlers
added patterns
provider-injection
dependency-threading
created modified
src/main/services/discovery/ProjectScanner.ts
src/main/services/parsing/SessionParser.ts
src/main/services/discovery/SubagentResolver.ts
src/main/services/analysis/SubagentDetailBuilder.ts
src/main/services/analysis/ChunkBuilder.ts
src/main/ipc/subagents.ts
src/main/ipc/handlers.ts
test/main/services/parsing/SessionParser.test.ts
Added getFileSystemProvider() getter to ProjectScanner for consistent provider access across services
Threaded provider through all three parseJsonlFile() call sites instead of relying on optional parameter fallback
Refactored SubagentDetailBuilder to accept fsProvider and projectsDir as explicit parameters instead of using dynamic imports
Propagated ProjectScanner to IPC subagent handler to obtain provider and projectsDir at runtime
duration completed
4 2026-02-12T00:15:16Z

Phase 01 Plan 01: Thread FileSystemProvider Through Session Parsing Stack Summary

FileSystemProvider now flows consistently from ProjectScanner through SessionParser, SubagentResolver, and SubagentDetailBuilder, enabling SSH sessions to load conversation history over SFTP.

What Was Built

Threaded the FileSystemProvider abstraction through the entire session parsing stack, eliminating silent fallbacks to LocalFileSystemProvider that caused SSH sessions to show "No conversation history."

Task 1: Provider Threading Through SessionParser and SubagentResolver

Added getFileSystemProvider() getter to ProjectScanner and updated three parseJsonlFile() call sites to pass the provider:

  1. ProjectScanner.getFileSystemProvider() - New getter exposes the provider instance
  2. SessionParser.parseSessionFile() - Now passes this.projectScanner.getFileSystemProvider() to parseJsonlFile()
  3. SessionParser.parseSubagentFile() - Now passes this.projectScanner.getFileSystemProvider() to parseJsonlFile()
  4. SubagentResolver.parseSubagentFile() - Now passes this.projectScanner.getFileSystemProvider() to parseJsonlFile()

Updated SessionParser.test.ts mock to include getFileSystemProvider method returning LocalFileSystemProvider instance.

Commit: a3f5daf - feat(01-01): thread FileSystemProvider through SessionParser and SubagentResolver

Task 2: Refactor SubagentDetailBuilder to Use Provider

Removed hardcoded fs/promises, os.homedir(), and fs.access() calls from SubagentDetailBuilder, replacing them with provider-based operations:

  1. SubagentDetailBuilder.buildSubagentDetail() - Added fsProvider and projectsDir parameters, removed dynamic imports of fs/promises, os, replaced os.homedir() with projectsDir, replaced fs.access() with fsProvider.exists()
  2. ChunkBuilder.buildSubagentDetail() - Added fsProvider and projectsDir parameters, passed through to buildSubagentDetailFn()
  3. IPC subagents handler - Updated initializeSubagentHandlers() to accept ProjectScanner, obtains fsProvider and projectsDir from scanner in handleGetSubagentDetail()
  4. IPC handlers.ts - Updated both initializeIpcHandlers() and reinitializeServiceHandlers() to pass scanner to initializeSubagentHandlers()

Commit: c12b329 - feat(01-01): refactor SubagentDetailBuilder to use FileSystemProvider

Technical Implementation

Provider Flow Architecture

index.ts (creates ProjectScanner with SSH provider)
  └─> ProjectScanner.fsProvider (stored privately)
      └─> ProjectScanner.getFileSystemProvider() (public getter)
          ├─> SessionParser.parseSessionFile() → parseJsonlFile(path, provider)
          ├─> SessionParser.parseSubagentFile() → parseJsonlFile(path, provider)
          ├─> SubagentResolver.parseSubagentFile() → parseJsonlFile(path, provider)
          └─> IPC subagents handler → ChunkBuilder → SubagentDetailBuilder
              ├─> fsProvider.exists() (file check)
              └─> projectsDir (path construction)

Key Pattern Changes

Before (Task 1):

const messages = await parseJsonlFile(filePath);
// Silently falls back to LocalFileSystemProvider

After (Task 1):

const messages = await parseJsonlFile(filePath, this.projectScanner.getFileSystemProvider());
// Explicitly uses the provider from ProjectScanner

Before (Task 2):

const fs = await import('fs/promises');
const os = await import('os');
const claudeDir = path.join(os.homedir(), '.claude', 'projects');
await fs.access(subagentPath);
// Always uses local filesystem, always assumes ~/.claude/projects

After (Task 2):

const subagentPath = path.join(projectsDir, projectId, 'subagents', `agent-${subagentId}.jsonl`);
if (!(await fsProvider.exists(subagentPath))) { /* ... */ }
// Uses injected provider and projectsDir, works for both local and SSH

Deviations from Plan

None - plan executed exactly as written.

Testing & Verification

  • Type safety: pnpm typecheck passes with zero errors
  • Test suite: All 494 tests pass (31 test files)
  • No local filesystem leaks: Verified zero matches for fs/promises, os.homedir, and bare parseJsonlFile(filePath) calls in SessionParser, SubagentResolver, and SubagentDetailBuilder
  • Provider flow confirmed: All three services now receive FileSystemProvider from ProjectScanner's getter

Impact

Immediate

  • SSH sessions will now load conversation history correctly (once SSH provider is fully wired in index.ts)
  • Subagent drill-down will work over SFTP
  • No more silent fallbacks to local filesystem in parsing stack

Downstream

  • Phase 1 Plans 02-04 can now implement provider-based operations for todos, watchers, and search
  • All file operations in the parsing/analysis layer now use the provider abstraction consistently

Self-Check: PASSED

Created Files

No new files created (all modifications to existing files).

Modified Files Verified

  • src/main/services/discovery/ProjectScanner.ts - Contains getFileSystemProvider() getter
  • src/main/services/parsing/SessionParser.ts - Both parseJsonlFile() calls pass provider
  • src/main/services/discovery/SubagentResolver.ts - parseJsonlFile() call passes provider
  • src/main/services/analysis/SubagentDetailBuilder.ts - No fs/promises or os.homedir, uses fsProvider.exists()
  • src/main/services/analysis/ChunkBuilder.ts - Passes fsProvider and projectsDir parameters
  • src/main/ipc/subagents.ts - Obtains provider from ProjectScanner
  • src/main/ipc/handlers.ts - Passes scanner to initializeSubagentHandlers()
  • test/main/services/parsing/SessionParser.test.ts - Mock includes getFileSystemProvider()

Commits Verified

All files exist, all commits present. Self-check passed.