docs(01-03): complete daemon composition root plan — Phase 1 done
- Created 01-03-SUMMARY.md with self-check passed - Updated STATE.md: Phase 1 complete, 3/3 plans done - Updated ROADMAP.md: Phase 1 marked complete - daemon/index.ts: 1087 → 140 lines (87% reduction) - All 1077 tests pass, zero type errors
This commit is contained in:
@@ -63,7 +63,7 @@ Three phases, each delivering one complete capability. Phase 1 decomposes the mo
|
|||||||
|
|
||||||
| Phase | Status | Requirements |
|
| Phase | Status | Requirements |
|
||||||
|-------|--------|--------------|
|
|-------|--------|--------------|
|
||||||
| 1 — Daemon Decomposition | planned | DECO-01..08 (8) — 3 plans, 2 waves |
|
| 1 — Daemon Decomposition | **complete** | DECO-01..08 (8) — 3 plans, 2 waves |
|
||||||
| 2 — Config Overlays | not_started | CONF-01..03 (3) |
|
| 2 — Config Overlays | not_started | CONF-01..03 (3) |
|
||||||
| 3 — Live Ops Dashboard | not_started | DASH-01..05 (5) |
|
| 3 — Live Ops Dashboard | not_started | DASH-01..05 (5) |
|
||||||
|
|
||||||
@@ -71,4 +71,4 @@ Three phases, each delivering one complete capability. Phase 1 decomposes the mo
|
|||||||
|
|
||||||
---
|
---
|
||||||
*Roadmap created: 2026-02-09*
|
*Roadmap created: 2026-02-09*
|
||||||
*Last updated: 2026-02-09*
|
*Last updated: 2026-02-10*
|
||||||
|
|||||||
+20
-15
@@ -9,15 +9,15 @@
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
**Phase:** 1 — Daemon Decomposition
|
**Phase:** 1 — Daemon Decomposition
|
||||||
**Plan:** 2 of 3 complete (01-01, 01-02 done, next: 01-03)
|
**Plan:** 3 of 3 complete (01-01, 01-02, 01-03 done)
|
||||||
**Status:** executing
|
**Status:** phase_complete
|
||||||
**Progress:** ░░░░░░░░░░ 0/3 phases (phase 1 in progress)
|
**Progress:** ███░░░░░░░ 1/3 phases complete
|
||||||
|
|
||||||
## Phase Status
|
## Phase Status
|
||||||
|
|
||||||
| Phase | Status | Plans |
|
| Phase | Status | Plans |
|
||||||
|-------|--------|-------|
|
|-------|--------|-------|
|
||||||
| 1 — Daemon Decomposition | executing | 2/3 plans complete |
|
| 1 — Daemon Decomposition | **complete** | 3/3 plans complete |
|
||||||
| 2 — Config Overlays | not_started | — |
|
| 2 — Config Overlays | not_started | — |
|
||||||
| 3 — Live Ops Dashboard | not_started | — |
|
| 3 — Live Ops Dashboard | not_started | — |
|
||||||
|
|
||||||
@@ -25,12 +25,15 @@
|
|||||||
|
|
||||||
| Metric | Value |
|
| Metric | Value |
|
||||||
|--------|-------|
|
|--------|-------|
|
||||||
| Test count | 1077 (baseline, verified) |
|
| Test count | 1077 (baseline, verified across all plans) |
|
||||||
| daemon/index.ts lines | 385 (from 1087 baseline, -65%) |
|
| daemon/index.ts lines | 140 (from 1087 baseline, -87%) |
|
||||||
|
| Total daemon modules | 9 files, 1271 lines |
|
||||||
| Plan 01-01 duration | 9 min |
|
| Plan 01-01 duration | 9 min |
|
||||||
| Plan 01-01 tasks | 3/3 |
|
| Plan 01-01 tasks | 3/3 |
|
||||||
| Plan 01-02 duration | ~25 min |
|
| Plan 01-02 duration | ~25 min |
|
||||||
| Plan 01-02 tasks | 3/3 |
|
| Plan 01-02 tasks | 3/3 |
|
||||||
|
| Plan 01-03 duration | ~8 min |
|
||||||
|
| Plan 01-03 tasks | 2/2 |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -45,27 +48,29 @@
|
|||||||
- Deps-interface factory pattern (ChannelsDeps, AgentsDeps) for explicit dependency injection
|
- Deps-interface factory pattern (ChannelsDeps, AgentsDeps) for explicit dependency injection
|
||||||
- registerChannels returns cronScheduler so Tier 1 cron tools can still be wired in startDaemon
|
- registerChannels returns cronScheduler so Tier 1 cron tools can still be wired in startDaemon
|
||||||
- Lifecycle wiring stays in the module that owns the resource (agents.ts owns sandbox shutdown)
|
- Lifecycle wiring stays in the module that owns the resource (agents.ts owns sandbox shutdown)
|
||||||
|
- Grouped skills/MCP/pairing/gateway/startup into services.ts rather than multiple tiny modules
|
||||||
|
- getChannelAgents callback for late-binding channel agents into gateway token usage reporting
|
||||||
|
- Type-only imports in index.ts for values only referenced in DaemonContext type definition
|
||||||
|
|
||||||
### Technical Notes
|
### Technical Notes
|
||||||
- daemon/index.ts now 385 lines — models, memory, tools, routing, agents, channels all extracted
|
- daemon/index.ts now 140 lines — thin composition root: imports → init calls → wire → return DaemonContext
|
||||||
- Extracted modules: models.ts, memory.ts, tools.ts (Plan 01), routing.ts, agents.ts, channels.ts (Plan 02)
|
- 8 extracted modules: models.ts (251), memory.ts (99), tools.ts (89), routing.ts (239), agents.ts (48), channels.ts (102), services.ts (269), lifecycle.ts (34)
|
||||||
- Factory pattern established: initMemory(deps), initTools(deps), initAgents(deps), registerChannels(deps), createMessageRouter(deps), createModelRouter(config)
|
- Factory pattern established for all modules: initX(deps) → result
|
||||||
- Tier 1 agent tools remain in daemon/index.ts (depend on later-created objects)
|
- Tier 1 agent tools (session, agent list, message send, cron) remain in index.ts — they need deps from multiple init functions
|
||||||
- Remaining in daemon/index.ts: session store, hooks, skills, gateway, PairingManager, signal handlers, service startup, heartbeat monitor, Tailscale serve
|
|
||||||
- Web dashboard is vanilla JS SPA at src/gateway/ui/
|
- Web dashboard is vanilla JS SPA at src/gateway/ui/
|
||||||
- Config loader at src/config/loader.ts, schema at src/config/schema.ts (409 lines)
|
- Config loader at src/config/loader.ts, schema at src/config/schema.ts (409 lines)
|
||||||
|
|
||||||
### TODOs
|
### TODOs
|
||||||
_(none yet)_
|
_(none)_
|
||||||
|
|
||||||
### Blockers
|
### Blockers
|
||||||
_(none)_
|
_(none)_
|
||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
**Last session:** Plan 01-02 (extract routing/agents/channels) completed
|
**Last session:** Plan 01-03 (composition root finalization) completed — Phase 1 done
|
||||||
**Stopped at:** Completed 01-02-PLAN.md
|
**Stopped at:** Completed 01-03-PLAN.md (final plan in Phase 1)
|
||||||
**Next action:** Execute Plan 01-03 (remaining extractions: skills, gateway, lifecycle/infra) or continue Phase 1
|
**Next action:** Plan Phase 2 (Config Overlays) — run `/gsd-plan-phase` for Phase 2
|
||||||
|
|
||||||
---
|
---
|
||||||
*State initialized: 2026-02-09*
|
*State initialized: 2026-02-09*
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
phase: 01-daemon-decomposition
|
||||||
|
plan: 03
|
||||||
|
subsystem: infra
|
||||||
|
tags: [daemon, refactoring, composition-root, services-extraction, typescript]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires:
|
||||||
|
- phase: 01-01
|
||||||
|
provides: "models.ts, memory.ts, tools.ts extraction reducing daemon/index.ts to ~458 lines"
|
||||||
|
- phase: 01-02
|
||||||
|
provides: "routing.ts, agents.ts, channels.ts extraction reducing daemon/index.ts to ~385 lines"
|
||||||
|
provides:
|
||||||
|
- "src/daemon/services.ts — skills, MCP, system prompt, pairing manager, gateway server, service startup, signal handlers"
|
||||||
|
- "src/daemon/index.ts as thin 140-line composition root — imports, wiring, lifecycle, DaemonContext"
|
||||||
|
- "Phase 1 complete: daemon fully decomposed into 8 focused modules"
|
||||||
|
affects: [02-config-overlays, 03-live-ops-dashboard]
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Callback-based late binding: getChannelAgents() callback passed to gateway for deferred token usage reporting"
|
||||||
|
- "Type-only imports for values only used in DaemonContext type definition"
|
||||||
|
- "Section dividers with Unicode box-drawing comments for scannable composition root"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- src/daemon/services.ts
|
||||||
|
modified:
|
||||||
|
- src/daemon/index.ts
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Grouped skills, MCP, pairing, gateway, system prompt, and service startup into one services.ts rather than multiple tiny modules — related service-init code stays together"
|
||||||
|
- "Used getChannelAgents callback for late-binding channel agents into gateway token usage reporting"
|
||||||
|
- "Converted ModelRouter, McpManager, SkillRegistry, SkillInstaller, GatewayServer to type-only imports in index.ts"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Composition root pattern: daemon/index.ts is pure wiring — import → init → connect → return"
|
||||||
|
- "Services module groups service initialization that shares config/lifecycle dependencies"
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: ~8min
|
||||||
|
completed: 2026-02-10
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 1 Plan 3: Daemon Composition Root Summary
|
||||||
|
|
||||||
|
**Extracted services/skills/MCP/gateway/lifecycle into services.ts (269 lines), achieving 140-line composition root — 87% reduction from 1087-line baseline**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** ~8 min (across two sessions)
|
||||||
|
- **Started:** 2026-02-10T04:19:31Z
|
||||||
|
- **Completed:** 2026-02-10T04:27:00Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 2 (1 created, 1 modified)
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
- Extracted 6 functions into `src/daemon/services.ts`: initSkills(), initMcp(), loadSystemPrompt(), initPairingManager(), createGateway(), startServices()
|
||||||
|
- Reduced daemon/index.ts from 385 lines (post-Plan 02) to 140 lines — well under the 200-line target
|
||||||
|
- daemon/index.ts is now a pure composition root: imports → init calls → wire → return DaemonContext
|
||||||
|
- All 1077 tests pass, zero type errors, zero regressions
|
||||||
|
- Cumulative reduction: 1087 → 140 lines (87% reduction, 947 lines extracted)
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Extract services/skills/gateway/MCP into services.ts, clean up index.ts** — `701fcfc` (refactor)
|
||||||
|
2. **Task 2: Final validation** — No separate commit (validation-only task, all changes in Task 1)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
- `src/daemon/services.ts` — Skills registry/installer, MCP server manager, system prompt assembly, pairing manager, gateway server creation, channel/gateway startup, Tailscale serve, heartbeat monitor, signal handlers (269 lines)
|
||||||
|
- `src/daemon/index.ts` — Thin composition root with organized imports, section dividers, DaemonContext return (140 lines)
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
- Grouped all remaining service initialization (skills, MCP, pairing, gateway, system prompt, lifecycle startup) into a single `services.ts` rather than multiple tiny modules — these all share config/lifecycle dependencies and are called sequentially
|
||||||
|
- Used `getChannelAgents()` callback pattern to handle late-binding of channel agents into gateway's token usage reporting — avoids circular dependency between channel registration and gateway creation
|
||||||
|
- Converted `ModelRouter`, `McpManager`, `SkillRegistry`, `SkillInstaller`, `GatewayServer` to type-only imports in index.ts since they're only referenced in the DaemonContext type definition (values come from factory functions in extracted modules)
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None — plan executed exactly as written. daemon/index.ts was 385 lines as expected, extraction targets matched plan analysis, final line count (140) comfortably under the 200-line target.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
None.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
None — no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
- **Phase 1 complete:** daemon/index.ts is a 140-line composition root
|
||||||
|
- 8 daemon modules total: models.ts (251), memory.ts (99), tools.ts (89), routing.ts (239), agents.ts (48), channels.ts (102), services.ts (269), lifecycle.ts (34) — 1131 lines of extracted logic
|
||||||
|
- All modules use consistent factory pattern with typed deps/result interfaces
|
||||||
|
- Phase 2 (Config Overlays) can proceed — config loading changes are low-risk since daemon wiring is now modular
|
||||||
|
- Phase 3 (Live Ops Dashboard) can proceed — metrics hooks can be wired into individual modules rather than the monolithic god file
|
||||||
|
|
||||||
|
## Module Summary (Final State)
|
||||||
|
|
||||||
|
| Module | Lines | Responsibility |
|
||||||
|
|--------|-------|---------------|
|
||||||
|
| index.ts | 140 | Composition root — imports, wiring, DaemonContext |
|
||||||
|
| models.ts | 251 | Model client factory, GitHub mapping, auto-fallback, model router |
|
||||||
|
| services.ts | 269 | Skills, MCP, system prompt, pairing, gateway, service startup |
|
||||||
|
| routing.ts | 239 | Message router, agent cache, sandbox wiring, audio |
|
||||||
|
| channels.ts | 102 | All channel adapter registration (8 adapters) |
|
||||||
|
| memory.ts | 99 | Memory store, vector store, hybrid search, indexer |
|
||||||
|
| tools.ts | 89 | Tool registry, builtin tools, web search, process/browser managers |
|
||||||
|
| agents.ts | 48 | Agent config registry, agent router, sandbox manager |
|
||||||
|
| lifecycle.ts | 34 | Lifecycle state management |
|
||||||
|
| **Total** | **1271** | **Full daemon initialization** |
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 01-daemon-decomposition*
|
||||||
|
*Completed: 2026-02-10*
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- All 2 files verified present (services.ts, index.ts)
|
||||||
|
- Task 1 commit verified (701fcfc)
|
||||||
|
- Line counts match: index.ts=140, services.ts=269
|
||||||
|
- Typecheck: clean
|
||||||
|
- Tests: 1077/1077 passed
|
||||||
Reference in New Issue
Block a user