71cac9426d
One adapter-facing seam replaces the Slack-only callback: an adapter whose clarify prompt is a persistent card (Slack Block Kit) defines `retire_clarify_card(clarify_id, notice)`, and the gateway calls it from every path that ends a clarify without a button click: - TurnRunner._clarify_callback_sync: when the bounded wait returns a sentinel (timeout, /new or run-end clear_session), schedule the retire with the expired notice on the gateway loop (#110821). - run_inbound TEXT_REJECTED_PROSE: retire with the cancelled notice before the prose is routed as a follow-up (#111019). Lookup is on the adapter class so MagicMock doubles cannot fabricate the method; no platform == SLACK special-case. The Slack map is keyed by clarify_id and popped before the first await, so a late timer cannot touch a newer prompt and the button handler's ts-keyed guard makes a racing click a no-op. Gateway-restart-orphaned cards stay out of scope: nothing is waiting on the new process, and the click path already renders them expired. Tests trimmed to invariants: the runner-level timeout probe (card adapter vs no-card adapter), the inbound prose retire, and one Slack test covering buttons-dropped + late-click-noop. Docs updated for the new in-place edit.