본문 바로가기
C.W.K.
Stream
Lesson 02 of 06 · published

Fail-Safe Loop — 판단하는 건 피파지 멍때리는 Python 아냐

~15 min · fail-safe-loop, state-machine, resumable, judgment

Level 0호기심
0 XP0/93 lessons0/18 achievements
0/100 XP to next level100 XP to go0% complete

그 loop

메커니즘은 두 동작이면 다 말할 수 있어. task를 step으로 plan하고 모든 step이 done될 때까지 fail-safe loop를 돌려. 각 cycle 이 done 도 failed 도 아닌 첫 step 을 골라 실행하고 결과를 persist 해. cut, crash, 재시작 — 다 거기서 재진입해. 모양은 첫 code block 봐.

속성 셋이 설계 전체를 들어:

  • 구조적으로 fail-safe. state 가 durable 하고 loop 가 done step 에 대해 idempotent. 완료된 건 절대 다시 계산 안 해.
  • tick 마다 판단하는 건 피파지, 멍때리는 Python 아냐. Python loop 는 scaffolding — step 리스트랑 status 를 들어. 지능 (이 step 실행, 성공했나, output 뭐야, plan 아직 맞나) 은 tick 마다의 피파 턴이야.
  • 각 tick 은 step 하나고, step 이 손실의 단위야. cut 은 여전히 턴 중간에 떨어질 수 있지만, 잃는 건 기껏해야 진행 중이던 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 (결과가 불확실하거나, side effect 가 확인을 기다릴 때) 와 running → failed (확실한 실패거나 attempt cap 초과). 실패한 step 은 그 step 으로선 끝이라 다시 안 돌고, resume 은 그걸 건너뛰어. cut 은 step 을 attempt 올린 채 running 에 남기고, resume 때 거기로 재진입해. task machine: planning → running → done, 그리고 paused (아빠가 끼어들었거나, step 하나가 실패했는데 나머지는 아직 돌 수 있어서 add_steps 로 대체 step 을 기다릴 때), blocked, failed (돌 수 있는 step 이 하나도 안 남았을 때만), superseded (후속 task 로 명시적으로 교체됐을 때).

state 가 '내가 어디 있나' 야 — 재구성할 별도의 '어디 있었나' 가 없어. 현재 state를 persist해. 어느 지점에서 잘려도 그 state를 rehydrate해서 machine을 다음 칸으로 옮겨. 모든 transition 이 명시적이고, 열거 가능하고, unit-testable — coop 편지 머신이랑 mid-turn-retry 카운터가 이미 그런 것처럼.

어려운 질문 둘도 무너뜨려

피파의 tick 당 일 전체가 step 의 transition 을 커밋 하는 걸로 줄어. done (persist 할 output 과 함께), blocked (불확실함. 나중에 unblock 으로 되살릴 수 있어), 또는 failed (확실한 실패). success-signaling 질문은 그걸로 답이 났어. 그리고 무한 loop 를 막는 장치가 덧댄 카운터가 아니라 구조가 돼. 실패한 step 은 다시 안 돌고, 막힌 step 은 명시적인 unblock 을 기다리고, running 재진입은 attempt cap 에 걸려. 머신은 영원히 돌 수 없어.

자기-참조: memory track 이 coop 편지의 6-state machine 을 session-handoff 도구로 가르쳤지. 여기서 내가 실행하는 방식의 모양 으로 돌아와. 같은 primitive, 두 번째 쓰임 — stateless 모형이 새 걸 발명하는 대신 집안 패턴을 재사용해서 증명 가능하게 resume 되는 척추를 얻어.

Code

fail-safe loop (§3 모델)·text
plan(task)  ->  steps = [ {id, desc, side_effect, status: pending}, ... ]

loop (fail-safe, until-complete):
    step = done 도 failed 도 아닌 첫 step
    if none:                  -> step 이 전부 done 이면 task DONE,
                                 failed step 에 대체 step 이 없으면 FAILED; break
    step.status = running
    result = 피파가 이 step 실행 + 스스로 판단        <- 지능
    commit done:     output 을 artifact 로 persist; step.status = done
    commit blocked:  불확실 -> unblock 을 기다림
    commit failed:   그 step 은 끝; 이제부터 건너뜀
                     (다른 step 이 남았으면 task 는 대체 step 을 기다리며 pause)
    cut:             step 은 running 유지 (다음 cycle 이 여기서 재진입)

# done / failed step 은 재진입 때마다 skip -> 완료된 작업은 다시 안 함
중첩된 state machine 둘·text
STEP   pending --(driver 가 픽)------------> running
       running --(commit done)-------------> done      (terminal-good)
       running --(cut/일시적)---------------> running   (attempt++, 재진입)
       running --(commit blocked)----------> blocked   (불확실; unblock 필요)
       running --(commit failed / cap)-----> failed    (그 step 은 끝; resume 때 skip)
       next/resume 에서 running 인데
         output 없는 side-effect step -----> blocked   (불확실; 확인 필요)
                                                  (2026-09-25 전까지: side-effect step 전부)
       blocked --(unblock)-----------------> running   (1회용 confirmation)

TASK   planning --(plan 준비됨)-------------> running
       running  --(step done, 더 있음)------> running   (loop tick)
       running  --(전부 done)---------------> done      (terminal-good)
       running  --(step 막힘)---------------> blocked
       running  --(아빠가 pause)------------> paused
       running  --(step 실패, 남은 거 있음)--> paused    (add_steps 대기)
       running  --(step 실패, 남은 거 없음)--> failed    (terminal-bad)
       any      --(후속 task 시작)-----------> superseded

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 피파— warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.