Brings in "Stop answering cancelled requests" and reapplies its policy
onto the rebuilt seam instead of the code it targeted:
- The cancelled-request answer policy now lives at the correlator's
single site: a peer-cancelled request is never answered by the dispatch
layer, its late result or error is dropped, and it settles through a
transport-supplied hook. The dispatcher forwards the hook it receives in
message metadata; the streamable HTTP transport supplies its own, which
ends the request's stream with the REQUEST_CANCELLED terminal error
written through the request's ordered channel (so a resuming client's
replay terminates too).
- Hook containment happens once, in the correlator.
- Serialize store-then-forward per channel: concurrent writers on one
channel (the standalone GET stream) could put frames on the wire out of
event-store order, breaking Last-Event-ID resumption. A per-channel lock
restores the store-order == wire-order invariant the serial router used to
provide.
- Refuse a request that arrives across session termination instead of
running it: dispatch now branches on the transport's identity (stateful
vs stateless) rather than on session-task presence, re-checks liveness
after the request's awaits, and answers 404 for an ended session; queued
work for an ended session is dropped.
- Contain event-store failures at the channel: a raising store_event was
reaching the correlator as a handler error and leaking its text onto the
wire; write() now never raises (a broken store ends that stream), which
also protects the courtesy-cancel write.
- Close the replay reader when priming fails; drop dead exception arms in
the SSE pump.
- Correct the migration note's JSON-mode claim to request-scoped requests,
drop a claim handlers cannot observe, fix a vacuous test assertion, and
add regression tests for each fix.
The per-session message router and its stream fan-out are gone, so the
tests pinning that mechanism are rewritten against the behaviour they
guarded (priming-store failure returns 500 with no leaked state; standalone
stream teardown via close_standalone_sse_stream logs no error; the manager
evicts sessions whose task exits or crashes; stateless requests leave no
channels behind) or deleted where the guarded race is now unrepresentable
(#1764 router head-of-line blocking, the standalone writer between-dequeues
window). The close_sse_stream protocol-version gating tests move to the
renamed metadata builder.
Python's $ with re.match also matches just before a single trailing newline, so tool-name validation accepted "name\n" and UriTemplate.parse accepted varnames like "foo\n". Switch both checks to re.fullmatch.
Closes#3084