Files
correx/docs/specs/2026-05-20-router/exec/task-001-007-review.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

6.1 KiB

review-001-007

result

  • approved

findings

Build dependency tasks (001-003)

  • infrastructure/build.gradle: implementation project(":core:router") added correctly. Dependency ordering is clean — router is added before inference and approvals in the dependency block.
  • apps/server/build.gradle: implementation project(':core:router') added correctly. Placed between inference and tools dependencies, which is a reasonable ordering.
  • core/router/build.gradle: All four spec-required dependencies declared (:core:events, :core:context, :core:inference, :core:sessions). The task notes correctly observe that :core:inference transitively depends on :core:events and :core:context, but implementation deps do not propagate, so explicit declarations are necessary. No cross-core dependency violations detected — :core:router does not depend on any sibling core modules.

Event definition task (004)

  • SteeringNoteAddedEvent correctly defined in ContextEvents.kt with fields sessionId: SessionId, content: String, stageId: StageId? = null matching the task spec.
  • @Serializable annotation added — this is a sensible addition for round-trip serialization and follows the pattern of other events in the file.
  • Event is an EventPayload subclass, consistent with the existing pattern.

Serialization registration task (005)

  • Import added in alphabetical order among event imports (SteeringNoteAddedEvent after SessionStartedEvent).
  • subclass(SteeringNoteAddedEvent::class) registered after SessionFailedEvent and before StageStartedEvent in the eventModule polymorphic block.
  • All 8 pre-existing :core:events tests pass.
  • Detekt passes on :core:router and :core:context; pre-existing NewLineAtEndOfFile warnings in :core:events are unrelated to this change (noted in task-005).

RouterState model task (006)

  • RouterState correctly defined as @Serializable data class with all spec-required fields: sessionId, workflowStatus, currentStageId, l2Memory, conversationHistory.
  • Supporting enums correctly defined: WorkflowStatus (IDLE, RUNNING, PAUSED, COMPLETED, FAILED), StageOutcomeKind (SUCCESS, FAILURE, CANCELLED), TurnRole (USER, ROUTER).
  • All fields use sensible empty defaults (IDLE, null, emptyList()).
  • RouterL2Entry and RouterTurn defined with Instant timestamps (imported from kotlinx.datetime).
  • WorkflowStatus, StageOutcomeKind, and TurnRole are locally defined in the router module (not imported from :core:events), keeping router types self-contained per task notes.
  • No reducer logic implemented (per task non-goals).

RouterConfig model task (007)

  • RouterConfig correctly defined as @Serializable data class with keepLast: Int = 10 and tokenBudget: TokenBudget = TokenBudget(limit = 5000) matching spec defaults.
  • TokenBudget (pre-existing in :core:context) correctly annotated with @Serializable to enable its use as a field type in RouterConfig. The annotation is minimal and safe — TokenBudget only has Int properties.
  • No unused imports in any new file.

Compilation & static analysis

  • All affected modules compile: :infrastructure, :apps:server, :core:router, :core:events, :core:context — BUILD SUCCESSFUL.
  • Detekt passes on :core:router and :core:context; no new warnings introduced.
  • All 8 :core:events tests pass.

missing requirements

The following spec requirements are explicitly deferred to later tasks (per task non-goals) and are not missing — they are intentionally out of scope for tasks 001-007:

  • RouterReducer, RouterProjector, RouterRepository (Tasks 009-011 in plan)
  • RouterContextBuilder (Task 012 in plan)
  • RouterFacade (Task 013 in plan)
  • ChatMode, ChatInput, RouterResponseMessage protocol types (Tasks 014-015 in plan)
  • WebSocket handler wiring (Task 016 in plan)
  • InfrastructureModule wiring for RouterFacade (Task 018 in plan)
  • Deterministic tests (Tasks 020-023 in plan)
  • SteeringNote domain data class (deferred per task-004 notes)

No unplanned gaps detected in the implemented scope.

edge cases

  • TokenBudget serialization tests: No pre-existing serialization test exists for TokenBudget in :core:events tests or testing/ submodules. The @Serializable annotation was added but not verified with an explicit round-trip test. This is low risk given TokenBudget has only Int properties, but a serialization test would be advisable before TokenBudget is used in more complex serializable types.
  • SteeringNoteAddedEvent serialization test: The task notes correctly identify that no serialization round-trip test exists for SteeringNoteAddedEvent. The registration in eventModule prevents silent runtime deserialization failure (the primary safety concern), but an explicit round-trip test would provide higher confidence.
  • NewLineAtEndOfFile detekt warnings: 15 files in :core:events have this warning. None are new (confirmed pre-existing per task-005). The Serialization.kt file that was modified is among them. This is a known cosmetic issue that does not affect correctness.
  • Dependency declaration completeness: :core:router declares :core:inference and :core:sessions as dependencies, but the current source files (RouterState.kt, RouterConfig.kt) do not directly import from these modules. This is correct for the current phase (types are needed for subsequent tasks) but will produce unused-import warnings once source files are added and the unused deps are still present.

suggested follow-up

  1. Add serialization round-trip test for TokenBudget — low effort, high confidence gain. Add to :core:context or testing/deterministic once that test module is set up (depends on Task 019).
  2. Add serialization round-trip test for SteeringNoteAddedEvent — should be paired with the first test that actually exercises the event in the event store pipeline.
  3. Proceed with Tasks 008-010 (RouterResponse, RouterReducer, RouterProjector) as the natural next phase — the foundational types from tasks 001-007 are correctly in place and ready to be consumed.