docs(02-02): complete registry integration plan
- 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
This commit is contained in:
parent
24051acac8
commit
d10c56adb7
2 changed files with 273 additions and 12 deletions
|
|
@ -10,29 +10,29 @@ See: .planning/PROJECT.md (updated 2026-02-12)
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 2 of 4 (Service Infrastructure)
|
Phase: 2 of 4 (Service Infrastructure)
|
||||||
Plan: 1 of 3
|
Plan: 2 of 3
|
||||||
Status: Plan 02-01 complete
|
Status: Plan 02-02 complete
|
||||||
Last activity: 2026-02-12 - Completed 02-01 (ServiceContext infrastructure)
|
Last activity: 2026-02-12 - Completed 02-02 (Registry integration)
|
||||||
|
|
||||||
Progress: [███░░░░░░░] 37.5% (1.5/4 phases)
|
Progress: [████░░░░░░] 50.0% (2.0/4 phases)
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
**Velocity:**
|
**Velocity:**
|
||||||
- Total plans completed: 2
|
- Total plans completed: 3
|
||||||
- Average duration: 4 min
|
- Average duration: 5 min
|
||||||
- Total execution time: 0.13 hours
|
- Total execution time: 0.23 hours
|
||||||
|
|
||||||
**By Phase:**
|
**By Phase:**
|
||||||
|
|
||||||
| Phase | Plans | Total | Avg/Plan |
|
| Phase | Plans | Total | Avg/Plan |
|
||||||
|-------|-------|-------|----------|
|
|-------|-------|-------|----------|
|
||||||
| 01 Provider Plumbing | 1 | 4 min | 4 min |
|
| 01 Provider Plumbing | 1 | 4 min | 4 min |
|
||||||
| 02 Service Infrastructure | 1 | 4 min | 4 min |
|
| 02 Service Infrastructure | 2 | 10 min | 5 min |
|
||||||
|
|
||||||
**Recent Trend:**
|
**Recent Trend:**
|
||||||
- Last 5 plans: 4, 4
|
- Last 5 plans: 4, 4, 6
|
||||||
- Trend: Consistent velocity
|
- Trend: Slight increase (registry integration more complex)
|
||||||
|
|
||||||
*Updated after each plan completion*
|
*Updated after each plan completion*
|
||||||
|
|
||||||
|
|
@ -53,6 +53,10 @@ Recent decisions affecting current work:
|
||||||
- ServiceContext bundles all session-data services for single workspace isolation (02-01)
|
- ServiceContext bundles all session-data services for single workspace isolation (02-01)
|
||||||
- dispose() separate from stop() - stop pauses (reversible), dispose destroys (permanent) (02-01)
|
- dispose() separate from stop() - stop pauses (reversible), dispose destroys (permanent) (02-01)
|
||||||
- removeAllListeners() called LAST in dispose() to prevent events during cleanup (02-01)
|
- removeAllListeners() called LAST in dispose() to prevent events during cleanup (02-01)
|
||||||
|
- File watcher event rewiring via exported onContextSwitched callback from index.ts (02-02)
|
||||||
|
- SSH handler dynamically imports onContextSwitched to avoid circular dependencies (02-02)
|
||||||
|
- Context ID for SSH uses simple format: ssh-{host} (02-02)
|
||||||
|
- Destroy existing SSH context on reconnection to same host (02-02)
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
|
|
@ -78,9 +82,9 @@ None yet.
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-02-12
|
Last session: 2026-02-12
|
||||||
Stopped at: Completed 02-01 (ServiceContext and ServiceContextRegistry) — ready for 02-02
|
Stopped at: Completed 02-02 (Registry integration) — ready for 02-03
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|
||||||
---
|
---
|
||||||
*Created: 2026-02-12*
|
*Created: 2026-02-12*
|
||||||
*Last updated: 2026-02-12 after completing 02-01-PLAN.md*
|
*Last updated: 2026-02-12 after completing 02-02-PLAN.md*
|
||||||
|
|
|
||||||
257
.planning/phases/02-service-infrastructure/02-02-SUMMARY.md
Normal file
257
.planning/phases/02-service-infrastructure/02-02-SUMMARY.md
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
---
|
||||||
|
phase: 02-service-infrastructure
|
||||||
|
plan: 02
|
||||||
|
subsystem: main-process
|
||||||
|
tags: [registry-integration, ipc-refactoring, ssh-context-management]
|
||||||
|
dependency-graph:
|
||||||
|
requires: [02-01]
|
||||||
|
provides: [registry-based-service-routing]
|
||||||
|
affects: [all-ipc-handlers, ssh-connect-flow]
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: [registry-routing, dynamic-service-resolution, context-switching]
|
||||||
|
key-files:
|
||||||
|
created: []
|
||||||
|
modified:
|
||||||
|
- src/main/index.ts
|
||||||
|
- src/main/ipc/handlers.ts
|
||||||
|
- 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
|
||||||
|
decisions:
|
||||||
|
- "File watcher event rewiring handled by exported onContextSwitched callback from index.ts"
|
||||||
|
- "SSH handler imports onContextSwitched dynamically to avoid circular dependencies"
|
||||||
|
- "Context ID for SSH uses simple format: ssh-{host}"
|
||||||
|
- "Destroy existing SSH context on reconnection to same host"
|
||||||
|
metrics:
|
||||||
|
duration: 6
|
||||||
|
completed: 2026-02-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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 `handleModeSwitch` callback entirely
|
||||||
|
- Created `wireFileWatcherEvents(context)` helper to manage event listener cleanup
|
||||||
|
- Created `onContextSwitched(context)` export for SSH handler to call
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```typescript
|
||||||
|
// 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 `initializeIpcHandlers` to accept `ServiceContextRegistry` instead of individual services
|
||||||
|
- Removed `reinitializeServiceHandlers` entirely (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:**
|
||||||
|
```typescript
|
||||||
|
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 `projectScanner` via `registry.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 `projectScanner` via `registry.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 `onModeSwitch` callback parameter
|
||||||
|
- **SSH_CONNECT handler:**
|
||||||
|
- Creates new `ServiceContext` with SSH provider
|
||||||
|
- Registers in registry
|
||||||
|
- Starts context
|
||||||
|
- Switches registry to new context
|
||||||
|
- Dynamically imports `onContextSwitched` from index.ts and calls it
|
||||||
|
- **SSH_DISCONNECT handler:**
|
||||||
|
- Switches registry back to 'local'
|
||||||
|
- Destroys SSH context
|
||||||
|
- Calls `onContextSwitched` with 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 `contextRegistry` instead of individual service globals
|
||||||
|
- `reinitializeServiceHandlers` no 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:**
|
||||||
|
1. **No service recreation** - contexts are isolated, switching is instant
|
||||||
|
2. **Local context persists** - can switch back without re-initialization
|
||||||
|
3. **No reinitializeServiceHandlers** - dynamic routing eliminates the need
|
||||||
|
4. **Clean separation** - SSH connection management vs. service context management
|
||||||
|
5. **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*
|
||||||
Loading…
Reference in a new issue