Devin.KR

새 세션에서 이어가기

90분 안팎

학습 목표

오래된 완료 기록과 변경된 파일 fixture를 대조해 재검증 대상을 찾아냅니다.

개념

재개는 기록을 믿기 전에 대조하는 일입니다

새 세션의 시작 요청은 이어서 끝내 주세요 한 줄로 충분하지 않습니다. 기록한 완료가 현재 파일에서도 유효한지 확인해야 합니다. 이번 레슨은 state.json을 읽고 tasks.json의 정의와 실제 파일을 대조합니다. 기록에 verified가 있다는 이유로 다음 앱 기능을 구현하면 변경된 파일을 검사 없이 지나칠 수 있습니다. 반대로 모든 작업을 처음부터 반복하면 중단 전 검증 비용을 낭비합니다. 근거가 유지된 작업은 생략하고 달라진 작업부터 재검증하는 기준을 코드로 표현합니다.

재개 순서를 파일의 역할에 맞춥니다

먼저 RULES.md로 수정 경계를 확인하고 tasks.json으로 작업 ID·의존성·검사 정의를 읽습니다. 이어 state.json과 해당 로그를 확인한 뒤 현재 파일을 대조합니다. 마지막에 handoff.md에서 실패 원인과 다음 판단의 배경을 읽습니다. 인계 문장은 필요한 위치를 안내하지만 JSON과 파일 대조를 대신하지 않습니다. handoff에 전부 완료라고 적혀도 명시된 검사 근거가 빠졌다면 pending으로 다룹니다. 기계가 읽는 관찰과 사람이 읽는 맥락의 역할을 혼동하지 않습니다.

정의가 달라지면 같은 ID도 다른 작업입니다

작업 ID가 regression으로 같아도 files나 check가 바뀌면 검사 의미가 달라집니다. current_evidence는 저장한 definition을 현재 작업 객체와 비교하고 실제 argv도 현재 등록 명령과 비교합니다. 계획 version과 상태 planVersion이 다르면 이 작은 구현은 보수적으로 전체 작업을 대기로 돌립니다. 버전만 같다고 통과를 유지하지 않습니다. 계획 삽입이나 의미 변경을 자동으로 이주하는 복잡한 정책은 범위 밖입니다. 완료 ID를 재사용하면서 다른 검사를 붙이지 않는 이유를 설명할 수 있어야 합니다.

로그와 종료 기록이 없으면 미확인입니다

verified를 유지하려면 result가 passed이고 exitCode가 정수 0이어야 합니다. 로그가 존재하고 그 해시가 logHash와 같으며 검사 시각도 정상이어야 합니다. 저장한 정의나 시각이 빠져 있으면 current_evidence는 False를 반환합니다. 기록을 읽다가 필드가 없다는 이유로 프로그램이 중간에 죽지 않고 해당 작업의 검증 자격을 잃게 합니다. 단, 존재하지 않는 작업 ID나 알 수 없는 상태는 STATE 또는 UNKNOWN_STATE_ID로 거절합니다. 잘못된 계획 자체와 부족한 증거를 다른 종류로 다룹니다.

바뀐 파일은 과거 성공을 현재 성공으로 만들지 않습니다

합성 task.txt를 검사한 뒤 Z·A를 A·Z로 바꾸면 저장한 해시와 현재 해시가 달라집니다. reconcile은 status를 pending으로 돌리고 이유를 recheck로 보고합니다. 이전 result의 passed는 지우지 않습니다. 당시 자식 명령이 성공했다는 과거 관찰과 지금 다시 확인해야 한다는 판단을 함께 보존하는 것입니다. 오래된 로그를 최신 파일의 근거로 재포장하거나 해시만 현재 값으로 덮어써 통과를 유지하지 않습니다. 변경 내용을 검토한 후 같은 계약의 검사를 새로 실행합니다.

실행 중 기록은 완료로 승격하지 않습니다

running 상태로 중단되면 명령이 실행 전이었는지, 실행 중이었는지, 결과 저장 직전이었는지 기록만으로 확정할 수 없습니다. 재개 보고는 interrupted 사유로 pending 후보를 만듭니다. 이것이 앱의 생성 API를 다시 호출하라는 뜻은 아닙니다. 검증 스크립트의 안전한 재실행 여부를 먼저 판단합니다. 외부 결제나 알림 같은 부작용 작업에는 이 정책을 그대로 적용할 수 없습니다. 이번 프로젝트는 로컬 검사 후보만 보고하며 실제 사용자 작업을 자동으로 재실행하지 않습니다.

선행 근거의 만료는 후속 작업에도 전달됩니다

rules의 파일이 바뀌면 rules가 pending이 됩니다. harness가 독립적으로 검사 통과했던 기록이 있어도 rules에 의존하므로 현재 완료 자격을 보류합니다. regression도 harness에 의존하므로 연쇄적으로 pending이 됩니다. 배열에 후속 작업이 먼저 있더라도 결과가 같아야 합니다. reconcile은 더 이상 상태 변화가 없을 때까지 의존성 검사를 반복합니다. 한 번만 앞에서 뒤로 확인하면 표시 순서에 따라 일부 손자가 verified로 남을 수 있어 역순 배열 fixture로 검사합니다.

ready와 skipped는 동작이 아닌 판단 결과입니다

ready는 pending이며 모든 직접 선행 작업이 verified인 ID 배열입니다. skipped는 현재 근거가 유효한 verified ID 배열입니다. reasons는 각 작업을 current·recheck·interrupted·dependency로 설명합니다. resume.py는 이 보고를 출력하고 조정한 상태를 저장하지만 명령을 실행하지 않습니다. checkpoint.py가 ready 작업을 명시적으로 선택했을 때 검사합니다. 같은 상태로 재개를 두 번 수행해도 완료 기록이 그대로여야 하며 이 테스트는 완료 작업 중복 실행을 막는 구조를 확인합니다.

해시를 신뢰할 수 있는 범위를 설명합니다

SHA-256은 파일 바이트가 저장한 값과 같은지 비교하는 도구입니다. 내용이 같다는 사실이 요구사항 충족이나 안전한 코드라는 의미는 아닙니다. 상태 파일과 해시를 함께 조작할 수 있는 공격자에 대한 위조 방지 체계도 아닙니다. 재개 검사에서 source 파일 목록을 빼면 그 변경은 탐지되지 않습니다. 따라서 파일 목록의 충분성, 검사 자체의 명세 적합성, 상태를 누가 쓸 수 있는지는 따로 검토합니다. 이번 단계의 자동화는 선의의 작업 중단과 변경 누락을 줄이는 범위입니다.

실패 메시지에서 비교 위치를 찾습니다

test_changed_file_invalidates_old_pass가 기대 pending 대신 verified를 보고하면 현재 파일 해시 비교부터 읽습니다. 로그 삭제 fixture가 실패하면 digest 오류를 False로 처리하는지 확인합니다. UNKNOWN_STATE_ID는 계획에서 제거한 작업이 상태에 남아 있다는 뜻이므로 상태를 무작정 합치지 않습니다. NOT_READY는 선행 근거가 아직 없다는 뜻이며 검증 실패와 다릅니다. ready가 비었는데 pending이 남으면 reasons의 dependency와 선행 작업 상태를 읽습니다. 실제 출력 ID를 계약과 함께 해석합니다.

인계 문장은 다음 행동을 작게 만듭니다

handoff.md에는 변경한 파일, 실행 명령과 결과, 실패 입력과 로그 경로, 미확인 범위, 다음 후보를 적습니다. 다음 작업은 rules를 검증한 뒤 harness와 regression을 차례로 확인한다고 구체적으로 씁니다. 실패 원인을 조사한 내용은 가설과 관찰을 나누어 남깁니다. 실제 HTTP 소켓·동시성·운영 환경은 이 로컬 검사로 확인되지 않았으므로 그대로 기록합니다. AI가 작성한 요약을 사용했다면 현재 파일과 JSON 및 로그를 읽어 누락되거나 완료로 바뀐 표현이 없는지 직접 검토합니다.

복사본에서 변경 fixture를 수행합니다

미션 solution을 별도 복사본에 풀고 체크포인트 세 개를 저장합니다. 변경 없는 재개는 세 ID를 skipped로 보고해야 합니다. RULES.md 끝에 줄바꿈을 추가한 뒤 재개하면 rules만 ready이고 후속 두 작업은 dependency가 됩니다. 끝에 줄바꿈을 더하는 것은 규칙 의미를 바꾸지 않아도 바이트가 달라진다는 예시입니다. 실습이 끝나면 새 ZIP의 초기 상태와 비교하고 자신의 실제 로그만 완료 근거로 남깁니다. 더 읽기의 맥락 예산 장은 전달할 기록 선택을 다루며 여기서는 최신성 판정을 마무리합니다.

따라하기

완료와 다음 후보를 나눕니다

변경 없는 선행이 완료된 고정 상태에서 다음 후보를 계산합니다.

entries = {'rules':'verified', 'harness':'pending', 'regression':'pending'}
deps = {'rules':[], 'harness':['rules'], 'regression':['harness']}
ready = [key for key in entries if entries[key] == 'pending' and all(entries[d] == 'verified' for d in deps[key])]
print('ready:', ready)
print('skipped:', [key for key in entries if entries[key] == 'verified'])

실행 결과

ready: ['harness']
skipped: ['rules']

과거 관찰을 보존합니다

실습의 재개 함수는 실제 파일을 비교합니다. 여기서는 판정 뒤 기록의 어떤 부분을 바꾸는지 관찰합니다.

entry = {'status':'verified', 'result':'passed', 'exitCode':0}
changed = True
if changed:
    entry['status'] = 'pending'
print('현재 상태:', entry['status'])
print('과거 결과:', entry['result'])
print('과거 종료 코드:', entry['exitCode'])

실행 결과

현재 상태: pending
과거 결과: passed
과거 종료 코드: 0

변경 감지 결함을 고칩니다

ai-workflow-resume starter 폴더에서 실행합니다. test_changed_file_invalidates_old_pass의 기대 pending과 실제 verified를 확인하고 current_evidence의 현재 해시 비교 TODO를 수정합니다. 14개 테스트 전체를 다시 확인합니다.

bash check.sh

프로젝트 재개 fixture를 수행합니다

미션 solution의 별도 복사본에서 실행합니다. 최초 세 체크포인트 뒤 ready는 비고 skipped는 rules·harness·regression이어야 합니다. RULES.md 끝에 줄바꿈을 추가해 python3 resume.py를 다시 실행하면 ready는 rules이고 후속 사유는 dependency입니다. 의존성 캐시 환경은 regression 명령 앞에 LAB_OFFLINE=1을 붙입니다. 시각·로그·종료 코드는 생성된 state.json을 열어 직접 확인합니다.

python3 checkpoint.py rules
python3 checkpoint.py harness
python3 checkpoint.py regression
python3 resume.py

실행 결과

rules passed verified
harness passed verified
regression passed verified
{"ready": [], "reasons": {"harness": "current", "regression": "current", "rules": "current"}, "skipped": ["rules", "harness", "regression"]}

확인 문제

실습

current_evidence에서 현재 파일의 해시를 저장한 값과 대조하도록 수정합니다. 이전 passed는 보존하면서 현재 status를 pending으로 돌리고 의존성 전파·완료 생략 검사를 함께 통과시킵니다. 미션에서는 재개 후보를 handoff.md의 다음 행동에 연결합니다.

시작 코드·테스트 내려받기

실행 명령

bash check.sh

기대 결과

starter는 변경된 파일의 오래된 통과 검출에 실패합니다. 수정 및 solution은 14개 unittest 전부 OK이며 종료 코드 0입니다.

모범 답안모범 답안 내려받기

더 읽기

면접 질문

  • 세션이 바뀌어도 작업을 이어갈 기록을 설명해 주시면 됩니다.