# CW typed response boundary ## Source correction, 2026-10-25 The shared typed dispatcher sends its response only when the registered function returns nil (or the handler has already sent the response explicitly). Several CW paths returned resource, validation or save errors directly. Those paths therefore left the Client waiting instead of receiving the revision's typed error response. CW registrations now use `cwHandle` / `cwHandleNamed`, which still resolve request and response IDs by their names through the existing protocol table. When a CW operation returns an application error, the wrapper preserves a nonzero retcode already selected by that handler, or assigns `RET_GRID_FIGHT_CONF_MISS` if it was still zero. It logs the error and returns control to the dispatcher to send exactly one typed response. It never converts an unsupported operation into success or replays a failed transaction. Every explicit packet send within these registered handlers uses `cwSend` to mark any send error, including serialization or projection failures. The wrapper propagates that error, network/EOF/closed-connection errors, and `errResponseAlreadySent` unchanged. It does not attempt an additional packet in those cases. The former pending-action-specific error defer was removed because it swallowed send errors as though they were application failures. `GridFightUpdatePos` also rejects position changes while `CURRENT_BATTLE` is active, matching the existing Preparation-only mutation boundary used by shop, equipment and grants. This does not remove or settle the active battle. ## Validation and limits - `go build ./internal/gameserver` succeeded. No tests were run. - No executable was replaced, no server restarted, no live save changed and no probe was staged by this change. - This closes a source-level missing-response path. Client behavior is not yet verified, and Tea Break choices, automatic Orb drops/opening and later route recipes are still incomplete. - The existing `GridFightEnterBonfire` handler's success-only navigation response is not proof of a working Tea Break. Its game-event consumer and the associated current revision's choices/effects still need runtime evidence before new pending state can be implemented. The static inventory scanner recognizes both CW wrappers, so registration reports continue to distinguish present handlers from actual gameplay support.