Durable Agent Runner
durable job record + 파일 아티팩트를 진실원으로 삼는 에이전트 실행 계약 — worktree 격리, bounded retry, git finalization 경계
한눈에 보기
Durable Agent Runner는 “터미널을 원격 조종하는 러너”가 아니라 “durable job record와 파일 아티팩트가 진실원인 러너”라는 계약 설계입니다.
- 핵심 질문: 에이전트 실행을 어떻게 재시작 가능하고 감사 가능한 작업 단위로 만들 것인가?
- 읽는 대상: 에이전트 작업 큐/러너를 설계하려는 운영자
- 연결 문서: Multi-Agent Issue Automation, Runtime Contract
설계 위치
Durable runner는 Keystone-owned contract와 최소 로컬 worker의 조합입니다. raw terminal controller가 아니고 scheduler도 아닙니다. 진실원은 durable job record와 파일시스템 아티팩트입니다.
결정 사항
- Contract: backend-neutral JSON job/status 아티팩트.
- 첫 구현: dependency-free Node.js 로컬 러너.
- 기존 거버넌스 스크립트(completion policy, doctor)는 Python으로 유지.
- OS 지원은 job마다
execution.execution_surface로 명시:macos,windows-native,wsl2,linux. - 에이전트 호출은 bounded non-interactive CLI 명령으로 시작. Codex, Claude, Agents SDK는 adapter이지 durable 진실원이 아니다.
- 격리 기본값은 git worktree. Docker는 선택적 미래 sandbox 모드.
- live job 아티팩트는 러너 전용 jobs 디렉토리를 사용. 다른 런타임 상태 디렉토리와 분리 유지.
- Commit, push, merge는 러너가 수행하지 않는다. git finalization은 대상 저장소의 completion-git policy를 통해서만 진행한다.
Job Shape
job 스키마는 JSON Schema로 관리합니다. 필수 contract 그룹:
portable: repository identity, issue repo, work repo, base branch, work branch, PR repolocal: 머신 로컬 경로 해석 필드 (work_repo_path,allowed_roots, 선택적worktree_parent)execution: runner 이름과 OS execution surfaceisolation: worktree 또는 미래 container 경계agent: adapter, prompt, argv-only commandretry: bounded retry countverification: argv-only verification commandapproval: durable pause 상태git_finalization: 요청된 finalization mode
명령은 shell string이 아니라 argv 배열로 표현합니다. 로컬 러너는 터미널 세션에 raw stdin을 흘려 넣지 않습니다.
아티팩트
job마다 아래 파일이 생깁니다.
status.jsonevents.jsonlattempts/<nnn>/worktree-setup.logattempts/<nnn>/agent.logattempts/<nnn>/verification.logattempts/<nnn>/worktree-status.txtattempts/<nnn>/diff.patch
status 형식도 별도 JSON Schema로 고정합니다.
로컬 명령
# job descriptor 검증
node durable-agent-runner.mjs validate fixtures/runner/success-job.json
# job 실행
node durable-agent-runner.mjs run path/to/job.json
# 결정론적 fixture 검증
node durable-agent-runner.mjs verify-fixtures
fixture 검증이 증명하는 것:
- 성공 job이 격리 worktree에서 실행되고 patch 아티팩트를 남긴다
- approval pause가 attempt를 소모하지 않고 durable status를 남긴다
- 실패 job은 retryable이 되고 bounded retry count 후 fail이 된다
- 실패 attempt 후에도 main worktree는 clean을 유지한다
- 요청된 git finalization은
WAITING_COMPLETION_POLICY에서 멈춘다
Approval과 Retry
approval.state가 required 또는 paused면, 러너는
WAITING_APPROVAL을 기록하고 worktree 생성이나 attempt 소모 없이 종료합니다.
재개하려면 job descriptor를 approved 또는 not_required로 갱신하고 다시 실행합니다.
Retry는 명시적이고 bounded입니다. 호출마다 최대 한 attempt를 소모하고 attempt별로 새 worktree 경로를 만듭니다. 실패한 job은 운영자가 재실행 전 점검할 수 있습니다.
Git Finalization 경계
러너는 commit, push, merge, 브랜치 삭제, 보호 브랜치 변형을 절대 수행하지 않습니다.
git_finalization.mode가 none이 아니면 성공 실행은
WAITING_COMPLETION_POLICY로 끝납니다. 운영자 또는 별도 승인 프로세스가
대상 저장소의 completion-git policy로 마무리해야 합니다.
Source Notes
이 문서는 KeystoneHub의 durable runner 첫 contract slice 설계 문서를 공개용으로 정리한 것입니다. 내부 이슈 번호와 저장소 내 스키마 경로는 일반화했습니다. Provenance: keystone-native.