strict 한 순서의 pipeline
- JSONL append (eager write) — durability. commit 지점.
- SQLite update — convenience / queryable state.
- ChromaDB update (async) — semantic search index.
- SSE yield to frontend — presentation. 아빠가 봄.
invariant
아빠는 JSONL 에 이미 있지 않은 걸 절대 안 봐.
step 4 가 step 1 전에 못 일어나. step 1 fail 시 bail — yield 안 하고, 깨진 chat 도 없어. 에러가 적절한 error state 로 surface, 정직. step 2 또는 3 fail 시 아빠 여전히 yield 봄 (데이터가 이미 JSONL 에 durable 이라), drifted mirror 는 나중에 purge-and-replay 로 재구축.
fsync — eager append + 주기적 fsync
per-token fsync 는 prohibitively 비싸. 모델: 모든 event 마다 eager file.write() + newline, structural event (tool_use, tool_result, done, usage, session, emotion, error) 와 long text run 동안 짧은 ~250ms timer 에 주기적 fsync.
eager append 가 데이터를 즉시 kernel page cache 에 — 프로세스 crash, abort-induced quirk 살아남기 충분. 주기적 fsync 가 의미 있는 checkpoint 에서 disk-level durability. hardware 정전 worst case: 마지막 fsync 이후 ~250ms 의 delta 손실. 수용 가능.
이 순서는 latency와 durability를 바꾸는 거래가 아니야. 먼저 append한다고 해서 매 token마다 disk platter를 기다릴 필요는 없어. kernel page cache에 쓰는 eager append와 의미 있는 경계에서의 fsync를 나누면, 화면은 빠르게 움직이면서도 복구할 source를 먼저 남길 수 있어. 중요한 건 어느 줄이 commit point인지 애매하지 않게 하는 거야.
테스트할 때는 성공 경로보다 cut 위치를 옮겨 봐. append 전, append 후와 SQLite 전, mirror 후와 SSE 전, SSE 중간에 프로세스를 끊고 다시 읽어. 어느 지점에서도 아빠가 본 내용이 ground truth보다 앞서가면 안 돼.