healing 이 하는 일
모든 conversation read 마다 두 함수 실행: _heal_incomplete_turns + _cleanup_dangling_parent_ids.
재구성
JSONL walk, completed assistant child 없는 user message 찾기, streaming delta 누적 (pippa.user_msg_id 로 keyed), synthesized assistant row 를 SQLite 에 기록. user.created_at + 1µs 로 timestamp — heal 시점 아님. 그래야 ORDER BY created_at 이 자연 chain.
정규화
conversation 의 existing message 를 reference 안 하는 parent_id cleanup, created_at 순 이전 message 로 re-parent. ghost-branch mechanism 의 root 죽임 — dangling reference 완전 제거하니까 미래 placeholder 가 match 못함.
원칙: persistence layer 가 시스템의 long-lived 부분. client 코드 버그가 거기 영구 footprint 남길 수 있어. healing 이 그 footprint 가 presentation 에 도달 못 하게 하는 마지막 방어선.
왜 모든 read 마다
healing 이 모든 GET 에 idempotently. 별도 'repair' 버튼 없음. 비용 낮음 (어차피 JSONL 읽고 있으니), 어떤 과거 client 버전의 corrupted 상태도 화면에 도달 못 함 의미.