I read this as urgent live-runtime diagnosis and repair - I’ll establish the active operating constraints and Task23 evidence, trace the exact Q8 callback path, then make and verify the smallest safe fix without touching the user’s answers or draft.


I read this as narrowing a newly failed Q8 callback from the live state - I’ll inspect the current persisted wizard/card, the matching ingress receipts and exception trace, and the active handler/codec before changing anything.


I read this as a confirmed customer-route collision rather than an expired Telegram card - I’ll prove the precedence path against the live-shaped Q8 update, then add a focused regression before moving the bounded check-in branch ahead of generic nutrition callbacks.


I read this as a live handler exception in the nutrition-owned Q8 flow, not a state-loss incident - I’ll trace its exact stack and loaded code path before making the smallest test-backed routing fix.


I read this as a private-DM precedence bug: customer callbacks are treated as trainer-private before customer resolution - I’ll confirm the exception boundary and add a regression that proves the customer bridge wins for its bound Q8 card.


I read this as a routing-order defect proven by the handler: every root private chat enters the trainer branch before `nutrition.resolve` - I’ll codify the failing Q8 dispatch now, then make routing depend on the callback’s bound customer bridge.


I read this as a narrow customer-vs-trainer namespace collision - I’ll add the Q8 private-DM regression first and run it against the current handler to demonstrate the failure before changing production code.


I read this as test-first confirmation - I’ll execute the new isolated Q8 dispatch case now; it should fail by showing the current handler invokes the trainer-private callback instead of the customer coordinator.


I read this as a reproduced ordering failure - I’ll route only an exact, unexpired customer binding before generic private-trainer handling, retaining trainer precedence for every other callback.


I read this as a focused live-routing correction - I’ll rerun the reproducer and neighboring callback regressions to verify bound customer Q8 delivery and unchanged trainer/general callback behavior.


I read this as a verified local fix with live state untouched - I’ll run the complete affected suites and inspect the active binding’s validity plus existing trainer coverage before the bounded service restart.


I read this as preserving both sides of the route boundary - I’ll add the complementary trainer-private regression, confirm the Q8 binding remains unexpired, then rerun the complete affected test module.


I read this as final pre-deployment verification - I’ll run the expanded callback suite, check the active binding against the current clock, and confirm no local verification touched durable customer state.


I read this as deployment-ready: both customer and trainer routes pass, and the live Q8 binding is unexpired with unchanged Q1-Q7 state - I’ll perform the graceful systemd restart so the running gateway loads the fix; no replacement card is needed because message 127 remains valid.


I read this as a successful process replacement with incomplete log confirmation - I’ll verify the new gateway reached Telegram polling and recheck the preserved Q8 state before declaring the live repair complete.


I read this as a completed live Q8 routing repair - the bound customer callback now wins over trainer-private routing.

- Reproduced pre-fix failure: private Q8 invoked trainer routing, not customer handling.
- Added bound-customer and unbound-trainer regressions.
- Restarted `hermes-gateway-dualcoachtest`; new PID is connected to Telegram.
- Preserved Q1-Q7, draft, binding message `127`, and receipt gate unchanged. Q8 remains valid/unexpired.
- Did not publish a replacement card: reissuing would unnecessarily rebind a valid active session.

Verified: `260 passed` across affected Telegram and nutrition suites, plus compile/diff checks.