0.3.1 — Assistants hardening
Hardening the assistant, after an adversarial review of 0.3.0. Nine defects in the concurrency, recovery and kill-switch guarantees the release advertised — every one now a regression test that failed on 0.3.0. Nothing changes what an assistant may do; it changes what can happen to a case while she is doing it.
- A customer's next question can no longer be answered around (R1). Every speaking path locks the ticket, then the conversation row chats updates inside every message insert, before reconciling — so an in-flight message blocks the answer until it commits and makes the turn stale. Holds on PostgreSQL and MySQL; on SQLite it is documented and
doctorwarns. - Seats are decided under the lock (R2);
assign!/release!take aturn:whenby:is an assistant — the one API change. - A lost registration is repairable (R3): the fold commits on its own, and
redispatch_assistant_turns!looks for unregistered messages before it looks at clocks. - Equal-timestamp messages no longer deadlock the turn (R4): the watermark is
(created_at, id)in chats' transcript order, one rule in Ruby and SQL. - The silent sweep rechecks before it escalates (R5).
- Stranded seats come back (R6):
SupportDesk.reclaim_assistant_seats!/rake support_desk:reclaim_assistant_seatsread the seats that exist, with no timeout and no clock; doctor seat checks run whenever assistant rows exist. - Running out of turns publishes
:ticket_escalated(R7). - Disclosure on old messages stops moving (R8): name and mode are snapshotted onto the assistant row.
- The kill switch is read after waiting for the lock (R9).
Hosts with no assistant are untouched. Gem SHA-256: 0b7bd2310212553a911aa0643ef872aff63aae901a13308b689f709e4dd5b886