5abf7d1253ff4b20ff5808c578a816b851ff7a0a
ApprovalCoordinator (added in epic-13) was never instantiated. Its four capabilities — multi-client fan-out, single-resolver dedupe, request timeout, and a unified domain mapper — were duplicated piecemeal across GlobalStreamHandler and SessionStreamHandler, with a STEER-outcome divergence between them (coordinator mapped STEER → APPROVED while GlobalStreamHandler mapped STEER → REJECTED). This refactor wires the coordinator and removes the duplication. Protocol: drop ApprovalDecision.STEER. STEER is no longer a discriminator; it's expressed as (APPROVE | REJECT) + non-null steeringNote, so the user can steer alongside either choice. TUI's current single-keybind STEER input flow now sends APPROVE + note (matching the original epic-13 intent); a future overlay UX will let the user pick APPROVE or REJECT explicitly. Mapper: ClientMessage.ApprovalResponse → DomainApprovalDecision lives in a single shared `toDomain` helper (apps/server/approval/ ApprovalResponseMapper.kt). Both stream handlers and the coordinator use it. Config: delete the duplicate apps/server/approval/ApprovalConfig.kt; ApprovalCoordinator now takes core.config.ApprovalConfig (already had timeoutMs=300_000L). ConfigLoader already populates it. Wiring: - ServerModule owns a SupervisorJob-backed moduleScope, constructs ApprovalCoordinator, and on start() subscribes eventStore.subscribeAll() to route ApprovalRequestedEvent payloads to onApprovalRequested. - GlobalStreamHandler delegates ApprovalResponse to approvalCoordinator.handleResponse and registers/unregisters via the new registerGlobalClient/unregisterGlobalClient (global sockets aren't bound to one SessionId, so broadcasts union session and global sets). - SessionStreamHandler delegates ApprovalResponse and registers per-session via registerClient/unregisterClient. - Timeout is on by default at 5 minutes via config.timeoutMs. Tests: ApprovalCoordinatorWiringTest covers delegate path, dedupe producing ProtocolError, and event-stream subscription routing.
Description
No description provided
Languages
Kotlin
88.4%
Go
11.4%
Python
0.2%