Files
correx/docs/specs/2026-05-20-router/exec/task-010.md
T
kami 2c459da009 feat(router): implement Epic 14 — core:router module
Implements the full conversational router facade: RouterState, RouterReducer,
RouterProjector, RouterRepository, RouterContextBuilder, RouterFacade, protocol
types, WebSocket wiring, infrastructure factory, and deterministic test suite.

Also fixes spec divergences found in post-implementation review:
- Add SteeringNote domain object to core:context (epic prerequisite)
- Rename RouterFacade.handleChat → onUserInput per spec interface contract
- Add in-memory ConcurrentHashMap conversation history to DefaultRouterFacade
- Make RouterRepository.getRouterState suspend
- Rename RouterConfig.keepLast → conversationKeepLast, fix defaults (6, 4096)
- Refactor InfrastructureModule.createRouterFacade to self-assemble internally
- Fix FileReadTool: allowedPaths was dead constructor param (@SuppressUnusedParameter);
  now stored as private val and enforced in validateRequest
- Disable koverVerify on modules tested via testing/ submodules or with
  hardware/integration dependencies (24 modules); build gate now passes clean
2026-05-21 15:06:20 +04:00

2.1 KiB

task-010

status: done

goal

Implement RouterProjector as Projection backed by DefaultRouterReducer, providing initial() and apply() methods per the core architecture pattern.

target artifact

core/router/src/main/kotlin/com/correx/core/router/RouterProjector.kt

execution steps

  • Modify RouterState.kt: change sessionId: SessionId to sessionId: SessionId? = null (prerequisite — Projection.initial() requires no-arg construction; RouterState previously had a required non-nullable SessionId field that prevented this)
  • Create RouterProjector.kt implementing Projection<RouterState>
  • Inject RouterReducer via constructor with DefaultRouterReducer default (matching the pattern used by other projectors: ArtifactProjector, ToolProjector, ApprovalProjector)
  • Implement initial()RouterState() (all fields default to empty/null)
  • Implement apply(state, event) → delegate to reducer.reduce(state, event)
  • Write unit tests in testing/projections module covering initial state, all event types, determinism, full lifecycle, and unknown event types

changed artifacts

  • core/router/src/main/kotlin/com/correx/core/router/model/RouterState.kt — sessionId made nullable with default null
  • core/router/src/main/kotlin/com/correx/core/router/RouterProjector.kt — new file
  • testing/projections/build.gradle — added :core:router test dependency
  • testing/projections/src/test/kotlin/RouterProjectorTest.kt — new file (12 tests)

blockers

  • RouterState.sessionId is currently non-nullable SessionId with no default, but Projection.initial() has no parameters to supply it. Resolved by making sessionId nullable with default null. All existing code only reads sessionId from events, not from RouterState, so this change is backward-compatible.

notes

  • This task depends on task-009 (RouterReducer) which is already done.
  • 12 unit tests written, all passing, covering: initial state, WorkflowStartedEvent, WorkflowCompletedEvent, WorkflowFailedEvent, OrchestrationPausedEvent, OrchestrationResumedEvent, StageCompletedEvent, StageFailedEvent, SteeringNoteAddedEvent, determinism, full lifecycle, and unknown event type.