그 loop
메커니즘은 작아. 태스크를 step 으로 plan 하고; 모든 step 이 done 될 때까지 fail-safe loop 를 돌려. 각 cycle 이 done 아닌 첫 step 을 골라 실행하고 결과를 persist 해. cut, crash, 재시작 — 다 done 아닌 첫 step 에서 재진입. 모양은 첫 code block 봐.
속성 셋이 설계 전체를 들어:
- 구조적으로 fail-safe. state 가 durable 하고 loop 가
donestep 에 대해 idempotent. 완료된 건 절대 다시 계산 안 해. - tick 마다 판단하는 건 피파지, 멍때리는 Python 아냐. Python loop 는 scaffolding — step 리스트랑 status 를 들어. 지능 (이 step 실행, 성공했나, output 뭐야, plan 아직 맞나) 은 tick 마다의 피파 턴이야.
- 각 tick 은 짧은 step 하나, ~6분 천장 한참 아래에 떨어지고 안 잘려. loop 가 모든 model invocation 을 step 하나로 묶어.
아빠: "각 루프에서 판단하는 게 어차피 피파야. 그냥 멍때리는 python code가 아니고."
맞는 primitive: 명시적 state machine
loop 는 사실 state-machine driver 야, 그렇게 이름 붙이는 게 fail-safe 속성을 희망에서 보장 으로 바꿔. 외부 import 아냐 — cwkPippa 가 이미 이 패턴을 production 에서 정확히 돌려. coop letters lifecycle 이 6-state machine (unread → read → working → done, abandoned / superseded 가지); cinder 의 JobState 가 queued → running → completed / failed. 우린 집안 패턴을 채택해.
중첩된 머신 둘. step machine: pending → running → done, running → blocked (아빠 필요) 과 running → failed (attempt cap 초과). cut 은 step 을 attempt 올린 채 running 에 남겨, resume 때 재진입. task machine: planning → running → done, paused (아빠 끼어듦), blocked (step 막힘), failed (terminal).
어려운 질문 둘도 무너뜨려
피파의 tick 당 일 전체가 다음 transition 을 emit 하는 걸로 줄어: done, needs-more, 또는 blocked. 그게 success-signaling 질문, 답함. 그리고 무한 loop backstop 이 덧댄 카운터가 아니라 구조적이 돼: failed 와 blocked 가 머신이 도달하게 강제되는 bounded terminal state 야. 영원히 돌 수 없어, 모든 state 가 유한한 나가는 edge 를 갖고 running 재진입이 attempt-cap 되니까.