- Created 02-02-SUMMARY.md with implementation details - Updated STATE.md: Plan 2 of 3 complete, 50% progress - Added decisions: onContextSwitched callback, SSH context ID format - Updated metrics: 3 plans completed, 5 min average - No deviations from plan
7.7 KiB
| phase | plan | subsystem | tags | dependency-graph | tech-stack | key-files | decisions | metrics | |||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-service-infrastructure | 02 | main-process |
|
|
|
|
|
|
Phase 02 Plan 02: Registry Integration Summary
Registry-based service routing with multi-context SSH support
Objective Achieved
Replaced global service variables in main/index.ts with ServiceContextRegistry, updated all IPC handlers to route through registry.getActive(), and implemented SSH context creation/destruction flow.
Tasks Completed
Task 1: Refactor main/index.ts to use ServiceContextRegistry
Changed:
- Removed global service variables (projectScanner, sessionParser, subagentResolver, chunkBuilder, dataCache, fileWatcher, cleanupInterval)
- Added
contextRegistry: ServiceContextRegistry - Removed
handleModeSwitchcallback entirely - Created
wireFileWatcherEvents(context)helper to manage event listener cleanup - Created
onContextSwitched(context)export for SSH handler to call
Implementation:
// Create ServiceContextRegistry
contextRegistry = new ServiceContextRegistry();
// Create local context
const localContext = new ServiceContext({
id: 'local',
type: 'local',
fsProvider: new LocalFileSystemProvider(),
});
// Register and start
contextRegistry.registerContext(localContext);
localContext.start();
// Wire file watcher events
wireFileWatcherEvents(localContext);
// Initialize IPC handlers with registry
initializeIpcHandlers(contextRegistry, updaterService, sshConnectionManager);
handlers.ts changes:
- Changed
initializeIpcHandlersto acceptServiceContextRegistryinstead of individual services - Removed
reinitializeServiceHandlersentirely (no longer needed) - Updated all domain handler initialize calls to pass registry
Files modified:
- src/main/index.ts (111 insertions, 161 deletions)
- src/main/ipc/handlers.ts
Commit: 5bf41c6
Task 2: Update domain IPC handlers to route via registry
Pattern applied to all handlers:
let registry: ServiceContextRegistry;
export function initialize{Domain}Handlers(contextRegistry: ServiceContextRegistry): void {
registry = contextRegistry;
}
async function handleXxx(...): Promise<...> {
const { projectScanner, sessionParser, ... } = registry.getActive();
// Use services
}
projects.ts:
- Changed signature to
initializeProjectHandlers(registry: ServiceContextRegistry) - Resolve
projectScannerviaregistry.getActive()in each handler - 3 handlers updated
sessions.ts:
- Changed signature to
initializeSessionHandlers(registry: ServiceContextRegistry) - Destructure all services from
registry.getActive()at invocation time - 6 handlers updated
search.ts:
- Changed signature to
initializeSearchHandlers(registry: ServiceContextRegistry) - Resolve
projectScannerviaregistry.getActive() - 1 handler updated
subagents.ts:
- Changed signature to
initializeSubagentHandlers(registry: ServiceContextRegistry) - Resolve all services from
registry.getActive() - Still passes fsProvider and projectsDir to buildSubagentDetail as before
- 1 handler updated
ssh.ts:
- Changed signature to
initializeSshHandlers(manager, registry) - Removed
onModeSwitchcallback parameter - SSH_CONNECT handler:
- Creates new
ServiceContextwith SSH provider - Registers in registry
- Starts context
- Switches registry to new context
- Dynamically imports
onContextSwitchedfrom index.ts and calls it
- Creates new
- SSH_DISCONNECT handler:
- Switches registry back to 'local'
- Destroys SSH context
- Calls
onContextSwitchedwith local context
- All other SSH handlers unchanged (test, getConfigHosts, etc.)
Files modified:
- src/main/ipc/projects.ts
- src/main/ipc/sessions.ts
- src/main/ipc/search.ts
- src/main/ipc/subagents.ts
- src/main/ipc/ssh.ts (100 insertions, 70 deletions)
Commit: 24051ac
Deviations from Plan
None - plan executed exactly as written.
Verification Results
Type checking: ✅ Pass
pnpm typecheck — zero errors
Tests: ✅ Pass
Test Files: 31 passed
Tests: 494 passed
Duration: 4.88s
Code inspection: ✅ Pass
- main/index.ts has
contextRegistryinstead of individual service globals reinitializeServiceHandlersno longer exists in handlers.ts- All IPC handlers use
registry.getActive()pattern (12 occurrences) - SSH connect creates ServiceContext and registers it
- SSH disconnect destroys SSH context and switches to local
- File watcher events rewired via onContextSwitched callback
Architecture Impact
Before (single-context):
main/index.ts:
let projectScanner: ProjectScanner
let sessionParser: SessionParser
...
IPC handlers:
let projectScanner = /* set at init */
function handleXxx() {
projectScanner.scan() // always uses same instance
}
SSH connect:
recreate all services with new provider
call reinitializeServiceHandlers()
After (multi-context):
main/index.ts:
let contextRegistry: ServiceContextRegistry
contextRegistry.registerContext(localContext)
IPC handlers:
let registry: ServiceContextRegistry
function handleXxx() {
const { projectScanner } = registry.getActive()
projectScanner.scan() // dynamically resolved
}
SSH connect:
create new ServiceContext
registry.registerContext(sshContext)
registry.switch('ssh-host')
// local context stays alive in background
Key improvements:
- No service recreation - contexts are isolated, switching is instant
- Local context persists - can switch back without re-initialization
- No reinitializeServiceHandlers - dynamic routing eliminates the need
- Clean separation - SSH connection management vs. service context management
- File watcher stays alive - only pause/resume on switch
Next Steps
Phase 02 Plan 03 (SSH notification manager integration):
- Set NotificationManager on SSH context's FileWatcher
- Ensure error detection works for SSH sessions
- Wire up SSH context file watcher to NotificationManager
Phase 03 (Renderer state management):
- Snapshot/restore Zustand state on context switch
- Validate tab restoration against current context
- Update workspace indicators in sidebar
Self-Check
Created files exist: N/A (no new files created)
Modified files verified:
✓ src/main/index.ts — uses contextRegistry
✓ src/main/ipc/handlers.ts — accepts registry, no reinitialize function
✓ src/main/ipc/projects.ts — routes via registry.getActive()
✓ src/main/ipc/sessions.ts — routes via registry.getActive()
✓ src/main/ipc/search.ts — routes via registry.getActive()
✓ src/main/ipc/subagents.ts — routes via registry.getActive()
✓ src/main/ipc/ssh.ts — creates/destroys ServiceContext
Commits exist:
✓ 5bf41c6 — refactor(02-02): main/index.ts to use ServiceContextRegistry
✓ 24051ac — refactor(02-02): IPC handlers route via ServiceContextRegistry
Self-Check: PASSED
Completed: 2026-02-12 Duration: 6 minutes