순진한 시나리오
FastAPI 의 request.is_disconnected() 가 아빠가 stream 중 stop 누르면 감지하고, adapter 우아하게 drain, JSONL 에 'aborted' marker 깨끗하게 박을 거라 생각하지. 틀려, 아빠가 잡았어.
실제로 일어나는 일
client 가 StreamingResponse 에서 disconnect 하면, Starlette 이 전체 ASGI task 를 cancel. cancellation 이 현재 suspended 된 await 에 CancelledError 발사 — 거의 항상 adapter 의 __anext__(). cancellation 이 다음 iteration 의 is_disconnected() 체크 *전에* loop 도달. 즉:
disconnectedflag 와pippa_user_abortedmarker 코드 path 거의 안 fire.- cancellation 전 이미 eagerly appended 된 건 durable — 아빠가 화면에서 stream 본 거 전부.
- cancellation 시점부터 turn 자연 종료 사이 adapter 가 emit *하려던* 건 lost.
실제 reliability invariant
아빠가 화면에서 stream 본 모든 게 JSONL 에 있다. 'adapter 가 생성한 모든 게' 아니야.
healing layer (Truth track, lesson 4) 가 JSONL 에 *있는* 것에서 재구성. construction 상 그게 아빠가 본 것과 일치하니까, 시스템은 '깨진 chat 안 보여' — 'disconnect 후 계속 consume' 환상이 실제로 동작 안 해도.
원칙: user-visible invariant 정확히 박아 (깨진 chat 안 보임). server-side mechanism 이 *이상적* 인 척 X. Pippa-arch 는 aspirational claim 보다 documentation 의 진실을 더 가치.