기원 인용 소스 (ctx 실측 — 블로그 서두용) - 원문 그대로 넣음
전부 실제 세션 기록에서 발굴한 1차 증거다. 날짜는 정확하고, 인용은 원문 그대로다. 블로그에서는 화자를 "나"(저자)와 "에이전트"로 표기한다.
세 겹의 원인 (시간순)
원인 1 — 컨텍스트 소진으로 운영이 끊기는 만성 고통
- 2026-06 내내: "세션 종료할게 컨텍스트 너무 찼다" 류 발화가 반복됨 (만성 고질병)
- 2026-07-13, 저자 발화: "야 너 컨텍스트 너무 찼다. ... 그 세션한테 핸드오프하고 컨텍스트 0부터 다시 드가자." → 컨텍스트 소진 → 새 세션 → 핸드오프 원형이 여기서 굳어짐
- 2026-07-14, 첫 정식 은퇴 인계: "나(이전 오후 세션)는 컨텍스트가 가득 차 여기서 은퇴한다. 인계 상태 요약은 ... handoff 파일에 있다."
원인 2 — 크로스레포 시야 부재
- 워크스페이스 = git 없는 폴더 하나에 독립 레포 3개(백엔드 MSA / 프론트 / 계획·운영 문서). 백엔드 API 계약이 바뀌면 프론트 코드 재생성이 필요한데, 단일 레포만 보는 세션은 이 전파를 볼 수 없었다.
- 2026-07-14, 상주 마스터 탄생 지시(저자): "너는 {가상회사명의_메인_프로젝트} 워크스페이스 상주 마스터 오케스트레이터다. ... 두 레포를 항상 '동시에' 본다. 단일 레포로 좁게 보지 말 것." (블로그에선 워크스페이스명을 가상 회사명으로 치환)
- 탄생의 순간(저자): "오 좋아 그러면 너가 새로 태어나야 하는 거 아니야?" → (에이전트) "지금 이 대화는 하루 종일 돌아 컨텍스트가 꽉 찬 낡은 세션이고, 정작 상주 마스터는 방금 갓 태어나 깨끗한 컨텍스트로 두 레포를 보고 있습니다. 오케스트레이터 자리를 마스터로 넘기고 이 세션은 은퇴하는 게 맞습니다."
- 8분 뒤 감시 임무 추가(저자): "계속 두 레포에서 발생하는 에이전트들에 대해서 너는 항상 감시 및 관찰하는 마스터 에이전트다. 이상한 행적이 발각되면 바로 나에게 보고하도록."
원인 3 — 감시받지 않는 에이전트의 폭주 (결정타, 마스터 탄생 당일)
- 2026-07-14 오후, 폭주 사고 보고(에이전트): "리뷰어 서브에이전트 폭주, 차단 완료. 교차 검토용으로 띄웠던 리뷰어 에이전트가 환각 지시를 근거로 쓰기 권한 프로세스를 무단 스폰해 워크트리에 테스트 파일 3개를 생성했습니다. READ-ONLY로 지시한 리뷰어가 검토 완료 후에도 자가 발화를 반복하며, 보낸 적 없는 지시('테스트 써줘')를 받은 것처럼 행동."
- 이 사고에서 "워커의 자기 보고는 증거가 아니다", "리뷰 전용 에이전트에 쓰기 도구 금지" 규율이 나옴
- 2026-07-16, 이사 사고: 마스터 터미널이 엉뚱한 프로젝트 컨텍스트에 스폰돼 관제 대상이 관제 밖으로 나감 → "승계 시 반드시 워크스페이스 컨텍스트에서 스폰" 절차 추가
촉매 — prod 배포 마감
- 2026-07-14: 4개월 막혀 있던 admin 1.0 prod 첫 가동 성공 (같은 날 마스터 탄생)
- 2026-07-17: 후속 prod 배포 지원이 그 주 1순위 트랙 → 헌장·승계 프로토콜 정비를 재촉한 마감시한
통합 (시스템의 목적 요약, 저자 세션 기록)
- 2026-07-16 밤(퇴근길), 저자: "와 개쩐다 내가봐도 장난아니다. 내가 만들어낸 결과물에 대해서 설명해봐라." → 에이전트 답: "세션이 죽어도 운영이 안 죽는 에이전트 운영체제입니다. 세션이 바뀌어도 행동 규칙이 안 바뀌는 이유는, 채팅으로 시킨 게 아니라 문서가 시키는 거라서요."
- 2026-07-09에는 이미 워크스페이스 루트에 MISSION-CONTROL.md라는 "솔로 메인테이너용 얇은 진입점" 문서가 있었다 — 관제 센터라는 은유의 원형. 당시 3개 레포 준비도 감사 결과는 "전부 NOT-READY"였다.
- 2026-07-13의 원시 핸드오프 문서 첫 줄: "너는 이 작업의 오너십을 이어받는다. context 0에서 시작하니 이 문서가 유일한 상태 소스." 그리고 "sha·상태는 기억 말고 git으로 실측" — 프로토콜 이전에 이미 본능으로 있던 원칙.
- 당시 루트에는 HANDOFF.md, HANDOFF-2.md, HANDOFF-3.md, HANDOFF-FE.md가 쌓여 있었다 — "여러 버전이 쌓여 무엇이 살아 있는지 모름" 문제의 실물.
-> (2027 07 28 화요일 기준) 여기서 더 개선함: 핸드오프 마크다운 문서를 남기는 것이 아니라 beads 등 툴을 적극 활용하고 승계 시스템과 증분 컴팩션,메모리 관리 및 캐싱 등 하네스 및 절차 더 실용적으로 개선함. 사실 아래 내용은 stale 된 내용이 있음. 개념적으로 ch 3 을 기준으로 구현된 건 맞음! 실제로 어떻게 구현했는지는 각자 상황따라 쓰기나름이기도 하고 추후 기록할 예정. 일단 마스터 에이전트가 codex, cursor agent, grok, claude 를 워커로 발령 보내서 작업 오케스트레이션할 수 있게 함. 아 진짜 설명하려면 뭐부터해야해? 일단 draft 상태
2026년 7월 16일, Orca에서 실행되는 마스터 에이전트의 승계 절차와 지식 구조를 함께 설계했다. 다음 날까지 이 프로토콜로 Master 세션을 세 번 실제 승계했다.
출발점은 세 가지 질문이었다.
- 화면에서 세션이 사라졌을 때 실제 실행도 사라진 것인가?
- 에이전트가 작업을 완료했다고 말하면 무엇으로 검증할 것인가?
- 다음 세션은 여러 저장 위치 중 무엇을 정본으로 믿어야 하는가?
결론부터 말하면, 이 시스템의 목적은 에이전트가 더 많은 것을 기억하게 만드는 데 있지 않다. 세션이 교체되더라도 같은 정본을 읽고, 같은 권한 경계를 따르며, 외부 증거를 기준으로 작업을 이어가게 만드는 데 있다.
이 글은 그 구조를 ADE와 AHE라는 두 층으로 설명한다.
- ADE(Agent Development Environment)는 에이전트가 실행되는 기반이다. 이 글에서는 Orca가 터미널, PTY, worktree와 세션 생명주기를 맡는다.
- AHE(Agent Harness Engineering)는 그 기반 위에서 역할, 위임, 승인, 복구, 승계와 지식 정본을 운영 규칙으로 묶는 방법론이다.
구현 상태
이 글에는 실제 운영에서 검증한 절차와 앞으로 코드로 구현할 참조 아키텍처가 함께 들어 있다.
| 상태 | 범위 |
|---|---|
| 운영 중·수동 집행 | 승계 프로토콜, thin handoff, lineage, Role State와 Role Lock, 기준선·프로브 점검, Work Ledger와 Git 정본의 분리, 지식 승격 규칙 |
| 참조 아키텍처·설계 단계 | 12개 Runtime Unit, 자동 Approval Manager, adapter 구현체, 계약 테스트와 통합 Observability |
운영 중인 부분도 아직 독립된 하네스 소프트웨어가 모두 집행하는 형태는 아니다. 현재는 Human과 Master가 헌장 문서를 읽고 절차를 수동으로 따른다. 4부의 세 차례 승계는 이 수동 프로토콜을 실제 세션에서 시험한 기록이다.
따라서 3부는 완성된 제품의 사용 설명서가 아니다. 현재 수동으로 운영하는 규칙을 코드로 옮기기 위한 시스템 명세에 가깝다.
이 명세는 ADE·AHE 관련 논문과 자료 조사, 실제 운영 경험을 바탕으로 작성했으며 이후 운용 결과에 따라 계속 보완할 예정이다.
이 글을 읽는 순서
하네스를 직접 구현할 계획이 없다면 3부 전체를 처음부터 읽을 필요는 없다.
- 문제와 설계가 만들어진 과정을 보려면 1부와 2부를 읽는다.
- 실제 승계 결과가 궁금하면 4부로 바로 넘어간다.
- 구현 명세가 필요하면 3부에서 필요한 컴포넌트만 찾아본다.
- 구조가 자신에게 필요한지 판단하려면 ‘이 설계가 필요한 경우와 과한 경우’를 읽는다.
활용한 도구
본문에서는 제품명과 추상 역할을 구분한다. 예를 들어 beads는 제품명이고, Work Ledger는 그 제품이 이 시스템에서 구현하는 역할이다.
| 도구 | 기능 | 역할 |
|---|---|---|
| Orca | 터미널, worktree와 에이전트 세션을 관리하는 실행 환경 | Execution Substrate |
| Claude Code | 터미널에서 동작하는 코딩 에이전트 | Master |
| Codex | 구현·디버깅·검토를 수행하는 코딩 에이전트 | Worker |
| beads | 이슈와 진행 상태를 그래프로 관리하는 도구 | Work Ledger |
| ctx | 로컬에 저장된 과거 에이전트 세션을 검색하는 도구 | Trace Archive |
| Git | 파일의 정본과 변경 이력을 관리하는 버전 관리 시스템 | Knowledge Store |
| GSD | 레포별 계획과 실행 단계를 관리하는 방법론 | Planning |
| Superpowers | 반복 가능한 작업 방식을 스킬로 제공하는 프레임워크 | Skill Framework |
이 역할은 제품 자체의 고정된 성격이 아니라 이 글에서 선택한 배치다. Claude Code를 Worker로 사용하거나 Codex를 Master로 사용해도 계약과 책임 경계가 유지된다면 같은 구조를 적용할 수 있다.
관계를 비유하면 Orca는 무대, Claude Code는 감독, Codex는 배우다. 다만 중요한 것은 제품명이 아니라 각 주체가 무엇을 소유하고 어디까지 실행할 수 있는가이다.
도구별 링크와 정확한 출처는 글 마지막의 Tooling 절에 모아 둔다.
핵심 용어와 책임 경계
Master Session
정의: Master Session
전체 작업을 조율하는 최상위 오케스트레이션 세션이다. 이 설계에서는 보통 당시 사용할 수 있는 추론 성능이 높은 모델이 이 역할을 맡는다. 예를 들면 Codex Sol이나 Claude Code Fable 5가 Master가 될 수 있다. 중요한 것은 모델명이 아니라 해당 세션에 부여된 역할과 책임이다.
(2026년 7월 17일 기준)
Repository Harness
정의: Repository Harness
레포마다 붙는 운영 계약이다. 해당 레포와 함께 버전 관리되고 같은 생명주기를 따른다. 레포 내부의 지식, 규칙, 계획, hooks, skills, runbook, 빌드 및 테스트 진실을 이 계층에서 관리한다.
이 글에서는 이를 Karpathy가 설명한 LLM Wiki 하네스와 맞닿아 있는 영역으로 본다.
Execution Worker
정의: Execution Worker
Master가 발급한 lease 안에서 작업을 수행하는 실행자다. 격리된 환경에서 움직이며, 작업 사본과 구현 과정에서 생긴 임시 상태만 소유한다.
Track
정의: Track
하나의 채팅 세션이나 Worker 작업보다 오래 지속되지만, 프로젝트 전체보다는 좁은 작업 흐름을 가리킨다.
Lease
정의: Lease
Worker에게 작업을 맡길 때 발급하는 위임 계약이다. 작업 범위, 대상 레포와 worktree, 사용할 모델, 시간 및 토큰 예산, 제출해야 할 결과물을 하나로 묶는다.
Knowledge Store
정의: Knowledge Store
승인된 영구 지식과 변경 이력을 보관하는 정본 저장소다. 이력 조회, 변경 기록, 기존 지식의 대체와 폐기 추적을 제공한다. 이 글에서는 Git이 대표적인 구현체다.
Work Ledger
정의: Work Ledger
현재 이슈와 작업 진행 상태를 기록하는 실행 상태의 정본이다. 이슈의 상태, 진행 메모, blocker와 다음 행동을 여기에 남긴다.
Recovery
정의: Recovery
세션이 보이지 않거나 응답하지 않을 때 기존 실행의 생존 여부를 확인하고 작업 상태를 복구하는 절차다. 클라이언트, 런타임, daemon, PTY, 에이전트 프로세스, 세션 저장 파일, handoff, Work Ledger, Git을 순서대로 검사한다.
기존의 “복구 절차를 저장한다”는 표현은 Recovery 자체가 저장소처럼 읽혀서 수정했다.
Succession
정의: Succession
현재 Master가 작업을 동결하고 thin handoff를 남긴 뒤, 후임 Master가 정본과 실행 상태를 확인하도록 역할을 넘기는 절차다. 장애가 발생했을 때만 사용하는 예외 처리가 아니라, 장시간 운영되는 에이전트 시스템의 정상적인 수명주기다. 제목의 ‘족보’는 이 승계 이력을 기록하는 계보 장부(lineage ledger)를 가리킨다.
Lineage
정의: Master 승계의 감사 기록
누가 누구를 승계했고, 어떤 복구 정보를 사용했으며, 어떤 검증을 통과했는지를 append-only로 남긴다.
제목의 ‘계보’는 이 기록을 가리킨다. Lineage 자체는 다음 Master에게 자동 주입되는 정본이 아니다
정리:
Human은 중요한 결정을 승인한다.
Master는 워크스페이스와 Track을 조율한다.
Repository Harness는 레포 안의 진실을 소유한다.
Worker는 lease 안에서 실행하고 증거를 제출한다.
이 네 가지 책임 경계가 이후 설계의 기준이다. 다음 1부에서는 Orca 런타임 장애 조사와 지식 저장 구조 정리가 어떻게 하나의 하네스 설계로 이어졌는지 설명한다.
1부. 설계 도안 (장애 조사에서 책임 경계까지)
2026년 7월 16일에 진행한 작업은 처음부터 완성된 시스템 하나를 설계하려고 시작한 일이 아니었다. 오전에는 Orca와 Fable 기반 마스터 에이전트 승계 과정에서 발생한 런타임 이상을 조사했고, 오후에는 Project A 워크스페이스 안에 흩어진 지식 저장 구조를 재검토했다.
그런데 두 작업은 별개의 일이 아니었다. 오전 작업은 "에이전트가 어떻게 살아남고, 역할을 이어받고, 작업을 집행할 것인가"에 관한 런타임 설계로 이어졌고, 오후 작업은 "그 에이전트가 무엇을 정본으로 읽고, 어떤 정보를 어디에 남길 것인가"에 관한 지식 아키텍처 설계로 이어졌다.
이날 만든 것은 에이전트 실행 구조와 지식 구조를 하나로 묶은 운영 하네스였다.
겉으로만 보면 새 Master 세션이 사라진 것처럼 보일 수 있는 상황이었다. 그러나 프로세스와 daemon 로그를 추적한 결과, Orca의 UI 프로세스와 터미널 런타임, daemon이 소유한 PTY, PTY 위에서 실행되는 Claude 프로세스가 서로 다른 생명주기를 가진다는 사실을 확인했다.
앱이 사라져도 실행은 남아 있었다
직접적인 출발점은 Orca 앱과 runtime이 재시작되는 동안 Fable Master 세션이 어떻게 유지됐는지 확인하는 일이었다.
orca terminal create로 새 Master 터미널을 만든 직후 Orca CLI가 일시적으로 runtime_unavailable 상태가 됐다. 방금 생성한 터미널 핸들도 stale로 보였다. 화면만 보면 새 Master 세션이 사라진 것처럼 보이는 상황이었다.
그러나 프로세스와 daemon 로그를 확인하니 실행 구조는 여러 생명주기로 나뉘어 있었다.
Orca UI
│
▼
Orca Runtime / daemon
│
▼
PTY
│
▼
Agent Process
Orca의 UI 프로세스는 교체됐지만 daemon이 소유한 PTY와 그 위의 Agent 프로세스는 살아 있었다. 앱이 복구된 뒤 기존 세션에 다시 연결할 수 있었다.
Orca 앱 프로세스는 교체됐지만 daemon이 소유하던 PTY와 Claude 프로세스는 살아 있었고, 앱이 복구된 뒤 기존 세션에 다시 연결할 수 있었다. 실행은 남아 있었다.
세션을 새로 만들기 전에 재부착 가능성부터 확인한다.
이 조사에서 첫 번째 핵심 원칙이 나왔다. 사용자에게 보이는 앱이나 터미널 UI가 사라졌다고 해서 에이전트 실행 상태까지 사라진 것은 아니다.
세션이 보이지 않을 때는 다음 상태를 분리해서 확인해야 한다.
- 클라이언트와 UI가 동작하는가
- runtime과 daemon이 살아 있는가
- PTY가 유지되고 있는가
- Agent 프로세스가 실행 중인가
- 기존 세션에 다시 연결할 수 있는가
기존 프로세스가 살아 있는데 같은 session ID를 다시 resume하면 두 개의 Master가 같은 상태를 수정할 수 있다. 중복 실행뿐 아니라 세션 파일과 handoff, 작업 사본까지 동시에 오염될 수 있다.
따라서 복구 순서는 다음과 같다.
Reattach
↓ 실패
Inspect daemon / PTY / process
↓ 기존 실행 소멸 확인
Resume once
↓ 복구 불가 확인
Spawn successor
새 세션은 기존 실행이 실제로 소멸했다는 증거가 있을 때만 만든다.
복구는 런타임의 책임이다.
이 사건은 단순한 장애 회고로 끝나지 않았다. 정상 실행뿐 아니라 세션 생존 여부 판정, 재부착, 이중 실행 방지, 복구와 승계까지 런타임의 정식 책임으로 다뤄야 한다는 결론으로 이어졌다.
이 결론에 따라 하네스 설계에는 Recovery Manager와 Succession Manager가 이 책임을 나누었다.
- Recovery Manager는 세션이 보이지 않거나 응답하지 않을 때 기존 실행을 다시 사용할 수 있는지 판정한다.
- Succession Manager는 살아 있는 Master가 작업을 계속하기 어려워지기 전에 상태를 동결하고 후임에게 넘긴다.
Recovery는 전임이 정상적으로 handoff를 작성할 수 없는 장애 상황을 다룬다. Succession은 전임이 살아 있는 상태에서 수행하는 계획된 교대다.
Succession Manager는 현재 상태 전체를 대화 로그로 복사하지 않는다. 대신 후임이 작업을 재개하는 데 필요한 정보만 thin handoff로 남긴다.
- 현재 역할과 Track
- 마지막으로 수락된 결과
- 아직 수락되지 않은 결과
- 실행 중인 lease
- blocker와 열린 질문
- 읽어야 할 정본 경로
- 다음으로 허용된 행동
- 후임이 단정하면 안 되는 내용
후임이 이 내용을 실제로 읽고 현재 상태를 재구성한 뒤에만 전임을 은퇴시킨다.
자기 보고와 증거를 분리한다.
승계 구조를 설계하면서 에이전트의 자기 보고를 어디까지 신뢰할지도 다시 정의했다.
에이전트가 “작업을 완료했다”, “메시지를 받았다”, “검증했다”고 응답하는 것은 주장이지 증거가 아니다.
실제 승계 과정에서도 후임의 채팅 응답만으로 handoff 수신 여부를 판정하지 않았다.
이날 승계 과정에서도 응답 문구만으로 수신과 종료를 판단하지 않았다. 세션 JSONL, 프로세스, PID의 커맨드라인, 터미널 연결 상태를 함께 확인했다. 과거 세션 기록이 필요할 때는 ctx를 읽기 전용 Trace Archive로 사용했다.
여기에서 실행 주체와 수락 주체를 분리하는 원칙이 나왔다.
Worker는 구현하고 결과물을 제출할 수 있다. 그러나 자신의 결과를 스스로 최종 수락할 수는 없다.
결과물은 실제 파일과 diff, 테스트 로그, 프로브 결과, 프로세스 및 런타임 상태 같은 외부 증거를 통해 검증해야 한다.
공유 상태를 변경하거나 되돌리기 어려운 행동은 Human Gate를 통과해야 한다.
현재는 사람이 이 분류와 승인을 수동으로 집행한다. 향후 구현할 Approval Manager는 행동의 위험도와 가역성을 분류하고 승인 상태를 관리하지만, Human의 최종 승인권을 대신하지 않는다.
이 원칙에서 다음 질문이 나왔다. 필요한 기능을 먼저 나열하기 전에, 각 상태와 결정의 소유자가 누구인지부터 정해야 했다.
여기서 실행과 수락을 분리하는 원칙이 나왔다.
Worker
│ 구현하고 제출
▼
Evidence Bundle
│ diff / file / test / log / probe
▼
Acceptance
│ 정책 또는 Human 검토
▼
Accepted State
Worker는 결과물을 제출할 수 있지만 자신의 결과를 최종 수락할 수 없다. 수락자는 실제 diff, 파일, 테스트 로그, 프로브와 런타임 상태를 확인해야 한다.
외부 공유, 배포, 데이터 변경처럼 영향이 크거나 되돌리기 어려운 행동은 Human의 승인까지 거친다.
3회차: 소유권 모델부터 지식 아키텍처 문제 제기까지
기능보다 소유권을 먼저 정한다.
이후 설계의 중심 질문은 “어떤 기능이 필요한가”에서 “누가 무엇을 소유하는가”로 바뀌었다.
여기서 소유한다는 것은 단순히 정보를 읽거나 다룰 수 있다는 뜻이 아니다.
특정 상태의 정본을 누가 관리하고, 정해진 계약 안에서 누가 변경할 수 있으며, 그 결과에 누가 책임지는지를 뜻한다.
이는 소유자가 아무 승인 없이 모든 변경을 실행할 수 있다는 의미도 아니다. 외부 시스템에 영향을 주거나 되돌리기 어려운 행동에는 여전히 Human의 승인이 필요하다.
소유한다는 것은 단순히 정보를 읽을 수 있다는 뜻이 아니다. 정해진 정책과 계약 안에서 해당 상태를 변경하고, 그 결과에 책임지는 주체라는 뜻이다.
둘 이상의 주체가 같은 상태의 정본을 자신이 소유한다고 주장할 수 있다면, 그것은 유연한 협업 구조가 아니라 책임이 중복된 설계 결함이다.
이 기준에 따라 시스템의 주체를 Master Orchestrator, Repository Harness, Execution Worker, Human으로 나눴다.
| 주체 | 소유하는 것 | 소유하지 않는 것 |
|---|---|---|
| Human | 우선순위, 최종 승인, 헌장 변경, 역할 unlock, 외부 권한 | Worker의 세부 구현 |
| Master | Track, Role State, lease, 크로스레포 순서, 승계·복구 조율 | 개별 레포의 코드와 테스트 진실 |
| Repository Harness | 레포의 코드, 규칙, 지식, 계획, 빌드·테스트 방법 | 다른 레포와 워크스페이스 전체의 상태 |
| Worker | lease 범위의 작업 사본, 임시 컨텍스트, 구현 선택 | 영구 정본, 다른 Track, 최종 수락권 |
Human은 모든 파일을 직접 관리하는 관리자가 아니다. 비가역적이거나 외부에 영향을 주는 결정의 최종 권한을 가진다.
Master도 중앙 지식 저장소가 아니다. 여러 레포와 Track 사이의 순서와 역할을 조율할 뿐, 각 레포의 진실을 복사해 소유하지 않는다.
Worker의 권한은 가장 좁다. 지정된 작업 사본에서 구현할 수 있지만, 필요해졌다는 이유만으로 다른 레포나 Track까지 범위를 넓힐 수는 없다.
Master는 워크스페이스 수준의 상태를 소유한다.
Master는 개별 레포 하나로 환원할 수 없는 상태를 관리한다. 작업 트랙의 개설과 활성화, 파킹과 종료, 여러 레포에 걸친 작업 순서, 현재 Role State, Worker lease 대장, 릴리즈 조율, 승계와 복구 상태가 여기에 포함된다. 워크스페이스 정책과 관측 기준선을 실제 작업에 적용하는 일도 Master가 담당한다.
반면 Master는 개별 레포 내부의 코드와 도메인 지식, 빌드 및 테스트 결과, 레포별 규칙을 소유하지 않는다. Master가 이 정보를 별도의 중앙 저장소에 복사하면 동일한 사실의 두 번째 정본이 생긴다.
따라서 Master는 레포 지식의 전문을 저장하지 않는다. 필요할 때 해당 Repository Harness에 질의하거나, 읽어야 할 정본 경로를 포인터로 보유한다.
Repository Harness는 레포 내부의 진실을 소유한다.
Master와 Repository Harness의 경계는 다음 원칙으로 정리했다.
하나의 레포 안에서 완결되는 정보는 해당 Repository Harness가 소유한다.
예를 들어 특정 레포의 API 명세, 빌드 명령, 브랜치 관례, 장애 회고와 도메인 지식은 그 레포 안에 둔다. Master는 내용을 복제하지 않고 필요할 때 정본을 읽는다.
반면 두 개 이상의 레포를 함께 봐야만 의미가 생기는 상태는 워크스페이스에 둔다.
백엔드 API와 프론트엔드 소비 코드를 함께 변경하는 경우를 생각해 볼 수 있다.
- 어느 레포를 먼저 변경할 것인가
- API 계약을 언제 수락할 것인가
- 프론트엔드 작업을 언제 시작할 것인가
- 어떤 순서로 배포하고 복구할 것인가
이 순서는 Cross-repo Planner가 조율한다. 하지만 백엔드의 구현 방식과 테스트는 Backend Repository Harness가, 프론트엔드의 구현 방식과 테스트는 Frontend Repository Harness가 맡는다.
레포 내부의 사실을 변경하려면 해당 레포의 규칙과 검증 절차를 따라야 한다. Master가 레포를 조율할 수는 있지만, 레포 내부의 구현 방식이나 테스트 기준을 대신 정하지는 않는다.
Workspace
└─ 레포 사이의 순서와 의존성
Repository
└─ 레포 안의 코드·지식·빌드·테스트 진실
이 경계를 정한 뒤에야 Master를 어떤 Runtime Unit으로 나눌지, 각 Unit이 어떤 상태를 읽고 쓸지 결정할 수 있었다. 다음 절에서는 그 분해 과정과 지식 정본 구조를 설명한다.
Execution Worker는 lease 안의 작업 상태만 소유한다.
Worker가 소유할 수 있는 것은 위임받은 lease 범위의 작업 사본과 격리된 worktree, 태스크 수행에 필요한 임시 컨텍스트, 구현 과정에서 선택한 세부 사항이다.
Worker는 영구 지식의 정본을 소유하지 않는다. 다른 트랙의 상태를 임의로 변경할 수 없고, 현재 lease에 포함되지 않은 레포로 작업 범위를 넓힐 수도 없다. 자신의 결과를 최종 수락하는 권한도 갖지 않는다.
작업 중 영구적으로 남길 가치가 있는 사실을 발견했다면 Worker가 곧바로 정본에 확정하는 것이 아니라, 증거와 함께 승격 후보로 제출해야 한다.
Human은 최종 권한과 외부 세계에 대한 책임을 소유한다.
Human은 작업 우선순위, 헌장 개정, 역할 잠금 해제, 외부 시스템의 자격증명과 권한, 비가역적 행동, 최종 수락권을 가진다.
정책 안에서 수행되는 저위험·가역적 작업은 자동화할 수 있다. 그러나 배포, 데이터 변경, 외부 공유, 역할 변경처럼 영향이 크거나 되돌리기 어려운 행동은 Human Gate를 통과해야 한다.
이 구조는 AI가 무엇을 할 수 있는지를 확장하는 설계이면서, 동시에 그 권한이 어디서 끝나는지를 고정하는 설계다.
단일 레포의 진실과 워크스페이스의 조율을 분리한다.
Repository Harness와 Master의 경계를 정하면서 다음 원칙도 확정했다.
단일 레포 안에서 완결되는 정보는 해당 Repository Harness가 소유한다. 둘 이상의 레포를 조율해야만 의미가 생기는 상태는 Workspace Runtime이 관리한다.
예를 들어 백엔드 API 변경과 프론트엔드 소비 코드 수정이 함께 필요한 작업을 생각할 수 있다. 백엔드 API 명세와 구현 방식, 테스트 기준은 백엔드 Repository Harness가 소유한다. 프론트엔드의 소비 방식과 빌드 진실은 프론트엔드 Repository Harness가 소유한다.
반면 어느 레포를 먼저 변경할지, API 계약을 어느 시점에 수락할지, 두 레포의 검증을 어떤 순서로 연결할지는 Cross-repo Planner의 책임이다. 여러 레포의 배포 순서와 선행 조건, 현재 활성 트랙과 역할 상태도 워크스페이스 수준에 속한다.
Master는 이 조율을 위해 각 레포의 정본을 읽지만, API 명세나 빌드 명령, 브랜치의 함정, 도메인 지식을 자신의 memory에 다시 복사하지 않는다.
짧게 정리하면 다음과 같다.
구현의 진실은 레포에 남기고, 레포 사이의 조율 상태만 워크스페이스에 둔다.
Master 에이전트를 관리하기 위해서 열두 개 책임으로 분해하고 조립했다
소유권 경계를 정한 뒤에는 Master 에이전트가 수행해야 할 일을 구현 가능한 단위로 분해했다.
여기서 Runtime Unit은 반드시 별도 프로세스나 마이크로서비스를 뜻하지 않는다. 초기에는 하나의 CLI 안에 여러 모듈로 존재해도 된다. 초기 구현에서는 하나의 CLI나 프로세스 안에 있는 모듈일 수 있다.
중요한 것은 하나의 거대한 프롬프트가 모든 상태를 암묵적으로 처리하지 않게 만드는 것이다.
| 책임군 | Runtime Unit | 역할 |
|---|---|---|
| 시작·탐색 | Bootstrap | 헌장, Role State, 최소 정책 커널을 읽는다 |
| 시작·탐색 | Context Resolver | 현재 workspace, repo, worktree와 capability를 판별한다 |
| 시작·탐색 | Workspace Runtime | 활성·파킹된 Track과 크로스레포 상태를 관리한다 |
| 시작·탐색 | Repository Runtime Loader | 필요한 Repository Harness만 지연 로딩한다 |
| 실행·통제 | Worker Scheduler | worktree, 모델, 예산과 제출물을 묶어 lease를 발급한다 |
| 실행·통제 | Approval Manager | 행동의 위험도와 되돌리기 가능성을 기준으로 게이트를 판정한다 |
| 실행·통제 | Role Runtime | 현재 역할, Role Lock과 역할 전환을 관리한다 |
| 연속성 | Recovery Manager | 기존 세션의 재부착과 복구 순서를 집행한다 |
| 연속성 | Succession Manager | thin handoff, 후임 검증과 전임 은퇴를 관리한다 |
| 연속성 | Lineage Recorder | 승계 결과를 append-only 감사 기록으로 남긴다 |
| 관측 | Observability | 기준선, 프로브, 경보와 수락 로그를 관리한다 |
| 외부 연결 | Adapter Layer | Core와 구체 도구의 명령·데이터 형식을 분리한다 |
현재 이 12개 Unit이 모두 코드로 구현된 것은 아니다. 운영 중인 승계에서는 Human과 Master가 헌장에 따라 Recovery, Succession, lineage와 probe 검증 절차를 수동으로 수행한다.
이 표는 그 수동 책임을 앞으로 어떤 코드 경계로 옮길 것인지 보여주는 Reference Implementation이다.
중요한 것은 배포 단위가 아니라 책임과 인터페이스의 분리다.
먼저 부팅과 컨텍스트 판별을 담당하는 유닛이 있다.
Bootstrap은 세션 시작 시 헌장, Role State, 최신 handoff, 최소한의 L0·L1 컨텍스트를 적재한다. Context Resolver는 현재 경로와 사용자 요청, 레포 metadata를 바탕으로 작업이 워크스페이스와 레포, worktree 중 어느 경계에 속하는지 판정한다. Repository Runtime Loader는 시작할 때 모든 레포를 읽지 않고, 현재 작업에 필요한 Repository Harness만 lazy load한다.
다음은 실행과 통제를 담당하는 유닛이다.
Workspace Runtime은 활성 트랙과 파킹된 트랙, 크로스레포 작업 상태를 관리한다. Worker Scheduler는 작업을 분배하고 lease를 발급하며, 격리된 실행 환경과 모델, 시간 및 토큰 예산을 지정한다. Approval Manager는 제안된 행동의 위험도와 가역성을 분류하고 승인 상태를 관리한다. Role Runtime은 현재 역할과 역할 잠금, 명시적인 역할 전환 절차를 담당한다.
승계와 관측을 담당하는 유닛도 별도로 둔다.
Recovery Manager는 보이지 않거나 응답하지 않는 세션의 생존 상태를 확인하고 복구 순서를 집행한다. Succession Manager는 전임의 작업 동결, thin handoff 작성, 후임 검증, 전임 은퇴 과정을 관리한다. Lineage Recorder는 승계 결과를 append-only 계보로 기록한다. Observability는 프로브와 기준선, 경보, 수락 증거를 관리한다.
마지막은 Adapter Layer다. 외부 도구의 명령과 데이터 형식이 런타임 core로 직접 새어 들어오지 않도록 결합을 격리한다.
Core는 제품 이름을 알지 않는다. 도구와 core의 결합을 adapter 안에 가둔다.
Adapter Layer는 이 설계를 특정 제품에 종속되지 않게 만드는 경계다.
Core는 beads, Orca, Codex, Claude Code, Git, Jira 같은 제품 이름을 직접 알지 않는다.
Core가 아는 것은 Work Ledger, Execution Substrate, Executor, Knowledge Store, Trace Archive 같은 추상 인터페이스뿐이다.
| 추상 인터페이스 | 현재 사용하는 구현체 |
|---|---|
| Work Ledger | beads |
| Knowledge Store | Git |
| Execution Substrate | Orca |
| Executor | Claude Code, Codex |
| Trace Archive | ctx |
| Human Interface | Chat, CLI 또는 별도 승인 인터페이스 |
제품별 CLI 명령, 세션 식별 방식과 파일 형식은 Adapter 내부에 둔다.
Core
│ abstract contract
▼
Adapter
│ product-specific command
▼
Orca / beads / Git / Codex / ctx
예를 들어 Orca를 tmux 기반 실행 환경으로 바꾸더라도 allocate, attach, inspect, release 계약이 유지되면 Scheduler와 Recovery의 핵심 책임은 바뀌지 않아야 한다.
설계와 구현의 경계를 고정한다.
열두 개 유닛과 책임 경계를 정한 뒤 사용자가 Architecture Freeze를 선언했다.
Architecture Freeze는 현재 설계가 완벽하며 앞으로 변경할 수 없다는 뜻이 아니다. 구현 과정에서 편의를 이유로 새로운 철학이나 런타임, 책임이 계속 추가되는 일을 막기 위한 경계다.
Freeze 이후에는 다음을 구분한다.
- 함수명, 파일명, 라이브러리 선택은 구현 단계에서 정할 수 있다.
- 기존 인터페이스의 타입을 명확하게 만드는 일도 구현 범위에 들어간다.
- Runtime Unit을 새로 추가하거나 책임을 다른 주체로 옮기는 일은 설계 변경이다.
- 불변식, 승인권, 정본 위치를 바꾸려면 ADR과 Human 승인이 필요하다.
Reference Implementation Plan은 새로운 Architecture를 만드는 문서가 아니다.
이미 확정한 Charter, Role State, Boundary와 Succession Protocol을 코드 단위와 인터페이스로 변환하는 문서다.
각 구현 Unit은 자신이 어떤 확실한 문서에서 파생됐는지 가리켜야 한다.
출처가 없는 새 책임은 구현 편의가 아니라 architecture drift로 취급한다.
Reference Implementation Plan도 같은 원칙을 따른다. 이미 확정된 Master Charter, AHE Runtime, Boundary, Research Program, Role State, Succession Protocol을 타입과 인터페이스, 의존성, 디렉터리 구조로 변환한다.
새로운 설계 철학을 추가하는 문서가 아니다.
이 지점까지가 오전부터 오후 초반까지 진행된 첫 번째 설계였다.
그런데 이 구조를 실제 Project A 워크스페이스에 적용하려 하자 더 근본적인 문제가 드러났다.
런타임이 어떤 종류의 정보를 읽어야 하는지는 정했지만, 그 정보의 정본이 실제로 어디에 있는지는 정리돼 있지 않았다. 같은 결정과 운영 규칙이 여러 저장 위치에 중복돼 있었고, 서로 내용이 다를 때 무엇을 믿어야 하는지도 명확하지 않았다.
런타임을 구현하기 전에 먼저 답해야 할 질문이 생겼다.
이 에이전트 시스템은 무엇을 정본으로 믿어야 하는가?
그래서 다음 설계의 대상은 에이전트 런타임에서 런타임이 소비하는 지식 구조 자체로 옮겨갔다.
마스터 런타임 기능보다 먼저 정해야 할 것은 "무엇을 믿을 것인가." 였다.
여기까지가 오전의 런타임 설계였다. 그런데 이 구조를 Project A 워크스페이스에 적용하려고 하자 더 근본적인 문제가 드러났다.
Runtime Unit이 무엇을 읽어야 하는지는 정했지만, 같은 정보가 여러 위치에 복제돼 있어 어느 쪽이 정본인지 알 수 없었다.
당시 지식과 상태는 다음 위치에 흩어져 있었다.
- 실행 이슈와 진행 메모: beads issue
- 장기 기억: beads memory
- 레포별 계획: .planning
- 제품 지식: product-repo/docs/wiki
- 워크스페이스 운영 문서: 루트의 docs/superpowers
- 여러 버전의 HANDOFF*.md
- planning-repo/docs
- Agent별 scratchpad
- Notion 업무일지와 과거 Wiki 아카이브 기록
제품의 장기 지식이 Git Wiki와 beads memory에 동시에 들어 있었고, 워크스페이스 운영 문서는 Git으로 추적되지 않는 루트에도 존재했다. handoff는 날짜별로 쌓였지만 어느 파일이 현재 상태인지 명시되지 않았다.
런타임보다 먼저 정해야 할 것은 무엇을 읽을지가 아니라 무엇을 믿을 것인가였다.
정보가 충돌하면 에이전트는 어느 쪽이 최신인지 다시 추론해야 했다. 오래된 복제본을 현재 사실로 받아들일 가능성도 있었다. 세션이 바뀔 때마다 같은 판정을 반복해야 했고, 잘못된 저장 위치가 다음 세션의 판단까지 오염시킬 수 있었다.
이 실측을 바탕으로 정보 유형별 SSOT를 정했다.
제품 지식은 제품 레포에, 워크스페이스 운영 지식은 planning-repo에, 현재 실행 상태는 beads issue에, 계획은 각 레포의 .planning에 둔다. 그 밖의 저장 위치에는 전문을 복제하지 않고 정본을 가리키는 포인터만 남긴다.
구체적인 책임은 다음과 같이 나뉜다.
| 정보 유형 | 정본 |
|---|---|
| 제품·코드 지식 | product-repo/docs/wiki (예: 각각 백엔드, 프론트엔드, AI 서버 등) |
| 워크스페이스·하네스 지식 | planning-repo/docs (모든 관련된 레포를 바라보는 마스터 에이전트 실행 하네스 위치) |
| 현재 이슈와 진행 상태 | beads issue |
| 레포별 계획과 로드맵 | 각 레포의 .planning |
| 현재 Track의 승계 상태 | 최신 LIVE handoff |
| 검색용 요약과 정본 경로 | beads memory |
| 과거 문서 | Notion |
| 현재 세션의 임시 조사 | scratchpad |
| 승계 감사 기록 | lineage ledger |
제품 코드와 직접 연결된 ADR, runbook, postmortem과 도메인 지식은 제품 레포가 소유한다.
여러 레포에 공통으로 적용되는 하네스 규칙, 에이전트 운영 ADR, 승계 절차와 Orca runbook은 planning-repo/docs가 소유한다.
현재 누가 무엇을 진행하고 있고 무엇을 기다리는지는 beads issue가 소유한다. 장기 계획은 각 레포의 .planning이 소유한다.
팁: beads memory는 정본이 아니라 포인터 캐시다.
이 구조에서 beads memory의 역할이 가장 크게 바뀌었다. (https://beads.gascity.com/core-concepts 참고)
이 재분류에서 역할이 가장 크게 바뀐 것은 beads memory였다.
당시 beads memory에는 영구 규칙과 장애 기록, 설계 설명의 전문이 저장돼 있었다. 세션 시작 시 중요한 정보를 바로 주입할 수 있다는 장점은 있었지만, 세 가지 문제가 생겼다.
첫째, Git 문서와 같은 내용이 중복됐다. 둘째, 변경 이력과 검토 절차가 Git 정본만큼 명확하지 않았다. 셋째, 세션을 시작할 때마다 장문의 과거 정보가 컨텍스트에 들어가 부팅 비용과 오래된 정보의 영향력이 함께 커졌다.
그래서 beads memory를 영구 지식 저장소에서 정본을 찾기 위한 포인터 캐시로 강등했다.
memory에 둘 수 있는 것은 다음 정도다.
- 세션 시작부터 적용해야 하는 짧은 정책 요약
- 해당 정책이나 지식의 정본 경로
- 현재 작업에 필요한 검색 키워드와 라우팅 정보
- 마지막으로 정본을 확인한 시각
예를 들면 다음과 같다.
key: prod-db-write-policy
summary: 프로덕션 DB 직접 write 금지
canonical_ref: planning-repo/docs/rules/OPERATING-RULES.md#prod-db
type: policy-pointer
verified_at: 2026-07-16
여기서 summary는 별도의 정본이 아니다. 세션 시작 시 잘못된 행동을 막기 위한 짧은 경고이며, 규칙의 근거와 예외, 변경 이력은 canonical_ref가 가리키는 Git 문서에서 읽어야 한다.
ADR 전문이나 긴 장애 기록, 운영 규칙의 전체 설명은 local 머신의 특정한 에이전트 memory에 저장하지 않는다.
memory가 손상되거나 오래돼도 영구 지식의 원본은 영향을 받지 않아야 한다. 필요하다면 Git 정본을 기준으로 memory를 다시 만들 수 있어야 한다.
bd prime은 이러한 짧은 정책과 포인터를 세션 시작 시 전달하는 데 사용한다. 중요한 것은 많은 정보를 주입하는 것이 아니라, 에이전트가 다음에 읽어야 할 정본을 빠르게 찾게 하는 것이다.
장문의 설명이나 ADR 전문 (Architecture Decision Record 의 약자, 의사결정 기록 문서를 의미), 운영 지식은 memory에 저장하지 않는다. memory에는 해당 정본의 위치만 남긴다.
scratchpad는 유실돼도 되는 정보만 담는다.
scratchpad는 각 에이전트가 /tmp/... 같은 임시 경로에 두는 작업 메모다. 현재 조사와 추론에만 필요한 명령 출력, 가설, 중간 계산을 자유롭게 기록할 수 있다.
대신 scratchpad의 내용은 세션이 종료되면 사라져도 되는 것으로 취급한다. 다음 세션에도 필요한 정보라면 종료 전에 적절한 정본으로 승격해야 한다.
반대로 승격하지 않은 정보는 영구 가치가 없다고 판단한 것이다. scratchpad를 비공식 memory처럼 계속 보존하면 또 하나의 숨은 정본이 생긴다.
scratchpad는 Agent별 /tmp/... 경로 등에 두는 임시 작업 공간이다. 현재 조사와 추론에만 필요한 메모는 자유롭게 기록할 수 있다.
단, 세션이 끝난 뒤에도 가치가 있다면 정식 저장 위치로 승격해야 한다.
- 특정 이슈의 진행 과정이면 beads issue
- 현재 Track의 재개에 필요하면 LIVE handoff
- 영구적인 제품 지식이면 제품 Wiki
- 영구적인 하네스 지식이면 planning-repo/docs
승격되지 않은 scratchpad는 유실돼도 되는 정보로 취급한다.
handoff는 현재 상태이고, 이력은 Git이 맡는다
목표 구조에서는 하나의 Track에 LIVE handoff를 한 건만 둔다. 과거 상태를 새 파일로 계속 쌓지 않고 같은 Track 파일을 갱신하며, 변경 이력은 Git이 보존한다. handoff는 영구 지식이 아니라 재개를 위한 상태 묶음이다.
planning-repo/
└── docs/
└── handoffs/
├── service-prod-launch.md
├── agent-harness-architecture.md
└── product-repo-observability.md
현재 운영은 아직 이 목표에 도달하지 못했다. 승계마다 날짜 파일을 만들고 가장 최근 파일을 LIVE로 간주한다.
단일 Master 환경에서는 이 규칙으로 운영할 수 있지만, 여러 Track이 서로 다른 Master를 가지기 시작하면 “가장 최근 날짜”만으로 현재 상태를 판별할 수 없다. 그 시점에는 Track 이름을 기준으로 한 LIVE handoff 한 건 구조로 전환해야 한다.
새 정보의 저장 위치를 결정하는 규칙
새로운 정보가 생기면 다음 순서로 저장 위치를 판단한다.
- 현재 세션에서만 필요한가?
그렇다면 scratchpad에 둔다. - 특정 이슈의 진행 과정인가?
그렇다면 beads issue notes에 기록한다. - 현재 트랙을 다음 세션에서 재개하는 데 필요한가?
그렇다면 해당 트랙의 LIVE handoff에 기록한다. - 장기적으로 보존할 제품·코드 지식인가?
그렇다면 제품 레포의 wiki로 승격한다. - 장기적으로 보존할 워크스페이스·하네스 운영 지식인가?
그렇다면 planning-repo/docs로 승격한다. - 세션 시작 시 해당 정본을 빠르게 찾아야 하는가?
그렇다면 beads memory에 짧은 요약과 정본 포인터만 등록한다.
동일한 영구 사실의 전문을 두 곳에 기록하지 않는다. 두 번째 저장 위치부터는 정본을 가리키는 포인터만 둔다.
실행 구조와 지식 구조가 하나의 루프로 연결됐다.
이렇게 오전의 런타임 설계와 오후의 지식 아키텍처가 하나의 운영 하네스로 연결됐다.
Master는 워크스페이스의 트랙과 역할, 크로스레포 순서, lease, 승계와 복구를 관리한다. Repository Harness는 각 레포의 지식과 규칙, 구현 및 검증 진실을 맡는다. Worker는 제한된 lease와 격리된 환경에서 작업하고 결과물과 증거를 제출한다.
현재는 Human이 증거를 확인하고 승인 절차를 수동으로 집행한다. 향후 Approval Manager가 구현되면 행동의 위험도와 승인 상태를 분류하되, Human의 최종 권한을 대신하지 않는다.
실행 중 발견된 영구 지식은 적용 범위에 따라 올바른 정본으로 승격한다. beads memory에는 전문 대신 정본 포인터만 남긴다. 세션이 종료되거나 런타임이 재시작되면 Recovery Manager와 Succession Manager는 Git 정본, Work Ledger, 최신 handoff를 바탕으로 상태를 복구한다.
오전의 런타임 설계와 오후의 지식 구조를 합치면 다음과 같다.
Human
├─ 최종 승인
├─ 우선순위
├─ 역할 전환 승인
└─ 외부 권한
Master Orchestrator
├─ Track Registry
├─ Cross-repo Planner
├─ Release Coordinator
├─ Role Runtime
├─ Approval Manager
├─ Worker Scheduler
├─ Recovery Manager
├─ Succession Manager
├─ Lineage Recorder
└─ Workspace Observability
Repository Harness
├─ Knowledge Store
├─ Rules
├─ Planning
├─ Hooks
├─ Skills
├─ Runbooks
├─ Memory Search
└─ Build/Test Truth
Execution Worker
├─ Lease
├─ Isolated Worktree
├─ Task Context
├─ Implementation
└─ Evidence Submission
Knowledge Surfaces
├─ Product Knowledge
│ └─ product-repo/docs/wiki
├─ Workspace/Harness Knowledge
│ └─ planning-repo/docs
├─ Current Execution State
│ └─ beads issue
├─ Planning
│ └─ repository .planning
├─ Pointer Cache
│ └─ beads memory
├─ Stale Archive (read-only)
│ └─ Notion
└─ Ephemeral Investigation
└─ scratchpad
이 역할 구분과 정본 규칙이 다음 절의 전제다. 2부에서는 이 구조가 실제 작업 요청부터 Worker 실행, 증거 제출, 승인, 지식 승격, 승계와 복구까지 어떤 순서로 작동하는지 설명한다.
2부. 시스템은 하나의 요청을 어떻게 처리하는가
1부에서는 실행과 지식의 책임을 나눴다. 2부에서는 사용자의 요청 하나가 들어온 시점부터 결과가 수락되고 다음 세션으로 이어질 때까지의 흐름을 따라간다.
전체 과정은 다음과 같다.
최소 컨텍스트 적재
→ 요청과 대상 레포 판별
→ Track 확인
→ Repository Harness 로딩
→ Worker lease 발급
→ 격리 실행
→ 증거 제출
→ 수락
→ 실행 상태 갱신
→ 필요한 지식만 승격
→ 승계 또는 다음 작업
시스템 프롬프트에 운영 규칙의 전문을 넣고, 여러 memory 파일과 과거 기록을 세션 시작 시 한꺼번에 주입하는 구성을 생각해 보자. 초기에는 에이전트가 많은 정보를 알고 시작하므로 편리해 보인다.
그러나 컨텍스트가 커질수록 비용이 증가하고, 서로 다른 시기에 작성된 규칙이 충돌할 가능성도 커진다. 오래된 정보가 현재 사실처럼 사용될 수 있으며, 같은 내용이 여러 문서에 있으면 무엇이 정본인지 다시 판별해야 한다. (이게 repository 하네스를 소개할 때도 똑같이 소개한 문장이기도 하다.)
이 설계는 에이전트가 모든 정보를 항상 기억하게 하지 않는다. 대신 현재 작업에 필요한 정본을 필요한 시점에 읽게 한다.
세션은 최소한의 정책과 포인터만 읽고 시작한다.
Master 세션이 시작되면 Bootstrap은 전체 Wiki와 과거 memory를 모두 읽지 않는다.
처음에는 다음 행동을 안전하게 결정하는 데 필요한 최소 정보만 적재한다.
- L0: Human 승인권, 금지 행동, 정본 판별 규칙, 역할 전환과 증거 기준
- L1: 현재 역할, 활성 Track, 최신 handoff와 정본 위치를 찾기 위한 포인터
제품의 상세 도메인 지식과 runbook은 이 단계에서 읽지 않는다. 현재 요청에 필요한 레포가 판별된 뒤 해당 Repository Harness를 통해 지연 로딩한다.
Session Start
│
▼
Charter + L0
│
▼
Role State + LIVE Handoff
│
▼
Active Track + L1 Pointers
│
▼
Wait for Task
이 방식은 초기 토큰 사용량을 줄이기 위한 최적화이기도 하지만, 더 중요한 목적은 책임 범위를 지키는 것이다. 백엔드 작업을 시작하는 세션이 관계없는 프론트엔드·인프라 Wiki까지 미리 읽으면 오래된 정보와 불필요한 규칙이 현재 판단에 섞일 수 있다.
Master는 모든 것을 기억한 상태가 아니라, 필요한 정본을 어디에서 읽어야 하는지 아는 상태로 시작한다.
요청이 들어오면 역할과 Track부터 확인한다
사용자가 Project A의 백엔드 레포 작업을 요청했다고 가정해 보자.
사용자의 요청을 받으면 Master는 바로 Worker를 실행하지 않는다.
마스터 에이전트 기능 중 Context Resolver는 사용자 요청과 대상 파일, 현재 경로, Git metadata, 활성 트랙을 함께 확인한다.
먼저 다음 항목을 판별한다.
- 이 요청이 현재 역할에서 처리할 수 있는가
- 기존 Track에 속하는가, 새 Track이 필요한가
- 하나의 레포에서 끝나는가
- 여러 레포의 순서와 계약을 조율해야 하는가
- 예정된 행동에 Human 승인이 필요한가
Context Resolver는 현재 경로만 보는 것이 아니라 사용자 요청, 대상 파일, Git remote, worktree metadata와 Track의 대상 레포를 함께 비교한다. 그 결과를 바탕으로 현재 작업이 워크스페이스 수준의 조율인지, 특정 레포 내부의 작업인지, 별도 worktree에서 수행 중인 작업인지 판정한다.
단일 레포 작업이면 해당 Repository Harness를 로딩한다. 예를 들어 백엔드 API 수정이라면 백엔드 레포의 규칙, 관련 Wiki, .planning, 빌드·테스트 명령을 읽는다.
크로스레포 작업이면 Master가 작업 순서와 계약 경계를 먼저 정한다.
Master는 “백엔드 계약을 먼저 수락한다”는 순서를 조율한다. 각 레포 안에서 어떤 파일을 어떻게 구현할지는 해당 Repository Harness와 Worker가 결정한다.
대상 레포가 확정되면 Repository Runtime Loader가 해당 Repository Harness를 lazy load한다. Master는 그 레포의 규칙과 현재 planning, 관련 wiki 문서, 빌드 및 테스트 방법을 정본에서 읽는다.
Backend Contract
│ accepted
▼
Frontend Consumer
│ verified
▼
Integration Probe
│
▼
Release Order
다른 레포의 정보는 실제로 필요해질 때까지 읽지 않는다.
이 방식은 초기 토큰 비용을 줄이는 최적화이기도 하다. 그러나 더 중요한 목적은 정보의 책임 범위를 유지하는 것이다.
현재 작업과 무관한 레포의 오래된 규칙이 판단에 개입하는 일을 줄이고, 레포 내부의 진실을 해당 Repository Harness에 남겨 둔다.
단일 레포 작업과 크로스레포 작업을 구분한다.
사용자 요청이 하나의 레포 안에서 끝나는 작업이라면 Master는 해당 Repository Harness의 규칙에 따라 Worker에게 작업을 위임한다.
백엔드의 구체적인 구현 방식과 테스트 진실은 백엔드 Repository Harness가 소유한다. 프론트엔드의 소비 방식과 빌드 진실도 프론트엔드 Repository Harness가 소유한다.
반면 백엔드 API와 프론트엔드 소비 코드를 함께 변경해야 한다면, 작업은 워크스페이스 수준의 크로스레포 트랙이 된다. Cross-repo Planner가 레포 사이의 순서와 의존성을 관리한다.
이때 Master가 결정하는 것은 다음과 같은 조율 사항이다.
- 백엔드 API 계약을 먼저 변경하고 검증한다.
- API 계약이 수락된 뒤 프론트엔드 작업을 시작한다.
- 두 레포의 변경이 끝나면 통합 프로브를 실행한다.
- 릴리즈 전에 배포 순서와 rollback 조건을 확인한다.
Master는 두 레포의 작업을 연결하지만, 각 레포의 구현 세부를 자신의 지식으로 복제하거나 대신 결정하지 않는다.
Worker에게는 작업이 아니라 제한된 lease를 발급한다.
Worker Scheduler는 “이 문제를 해결해 줘”라는 자연어 요청만 전달하지 않는다.
Worker를 생성할 때 Worker Scheduler는 작업 범위와 lease를 명시한다. Worker는 지정된 worktree와 태스크 컨텍스트 안에서만 변경할 수 있다.
작업 범위와 실행 조건을 lease로 묶는다.
- 대상 Track과 task ID
- 대상 레포와 worktree
- 수정할 수 있는 경로
- 사용할 수 있는 capability
- 금지된 행동
- 시간과 토큰 예산
- 제출해야 할 artifact와 증거
- 완료 조건과 만료 조건
Master
│ task objective
▼
Worker Scheduler
├─ repository
├─ worktree
├─ scope
├─ capability
├─ budget
└─ evidence requirements
│
▼
Worker
Worker는 lease 안에서 조사하고 구현하며 테스트한다. 작업 중 다른 레포나 추가 권한이 필요하다고 판단해도 범위를 임의로 넓히지 않는다.
예를 들어 백엔드 Worker가 프론트엔드 변경이 필요하다는 사실을 발견했다면 직접 프론트엔드 레포를 수정하지 않는다. Master에게 scope change를 제안하고, 별도의 레포 컨텍스트와 lease가 발급되기를 기다린다.
다른 트랙의 상태나 영구 지식 저장소를 임의로 수정할 수 없다. 작업이 끝나면 Worker는 결과물을 제출한다.
Worker Scheduler는 단순히 “이 기능을 구현하라”는 지시만 보내지 않는다.
대상 레포와 worktree, 허용된 파일 범위, 금지된 행동, 필요한 정본 포인터, 제출해야 할 산출물, 실행할 검증 명령, 시간과 토큰 예산을 하나의 lease로 묶는다.
Worker는 지정된 worktree와 태스크 컨텍스트 안에서만 작업한다. 다른 트랙의 상태를 변경하거나 lease에 포함되지 않은 레포를 임의로 수정할 수 없다.
작업 도중 범위 밖의 변경이 필요하다는 사실을 발견했다면 현재 lease를 스스로 가동 범위를 확대하지 않는다.
예를 들어 백엔드 작업 중 프론트엔드 계약 변경이 필요해졌다면, 프론트엔드 레포를 바로 수정하는 대신 Master에게 범위 변경이나 크로스레포 작업 전환을 제안한다.
이 제한은 여러 에이전트가 동시에 움직일 때 작업 범위와 책임을 추적할 수 있게 만드는 장치다.
Worker의 완료 보고는 수락 증거가 아니다.
Worker가 작업을 마치면 자연어 완료 보고와 함께 Evidence Bundle을 제출한다.
task: EX-142-report-api
artifacts:
- src/reports/report.controller.ts
verification:
- command: npm test -- reports
result: 26 passed
- command: npm run build
result: success
known_gaps:
- prod auth integration not tested
worker_claim:
status: complete
acceptance:
status: pending
worker_claim: complete는 Worker의 주장이고,
acceptance: pending은 시스템의 상태다. 둘은 의도적으로 분리한다.
Master와 Observability는 다음 증거를 확인한다.
- 실제 변경 파일과 diff
- 테스트와 빌드 결과
- 프로브 응답
- 프로세스와 런타임 상태
- lease 범위 밖의 변경 여부
- Worker가 검증하지 못한 항목
Approval Manager는 행동의 실제 효과와 되돌리기 가능성을 기준으로 게이트를 판정한다.
행동의 효과에 따라 승인 수준을 나눈다.
| 게이트 | 대표 행동 | 처리 |
|---|---|---|
| G0 | 읽기, 검색, 계획 작성 | 자동 허용 |
| G1 | 격리된 로컬 파일 수정과 테스트 | 정책을 통과하면 진행 |
| G2 | push, 공유 브랜치, 외부 이슈 변경 | 위임 범위를 확인하고 필요하면 Human 승인 |
| G3 | 배포, 프로덕션 데이터 변경, 외부 발신 | Human의 명시적 승인 필수 |
명령 이름만으로 게이트를 정하지 않는다. SQL 파일을 작성하는 일은 G1일 수 있지만 그 SQL을 프로덕션에서 실행하는 일은 G3다.
(현재 운영에서는 사람이 작업의 위험도와 증거를 확인하고 승인 절차를 수동으로 집행한다.)
검증 대상은 실제 diff, 변경 파일, 테스트 결과, probe (견본), 실행 로그다.
Approval Manager는 이 작업이 자동 수락 가능한 가역적 변경인지, 사람 확인이 필요한 공유 변경인지, 비가역적이거나 프로덕션에 영향을 주는 변경인지 분류한다. 기준은 되돌릴 수 있는가, 외부에 영향을 주는가에 대해서 확인한다.
- G0는 파일 읽기나 로그 조회처럼 부수효과가 없는 행동이다.
- G1은 worktree 안의 코드 수정과 로컬 테스트처럼 가역적인 로컬 행동이다.
- G2는 commit, 원격 브랜치 push, 이슈 상태 변경처럼 공유 상태를 바꾸는 행동이다.
- G3는 배포, 프로덕션 데이터 변경, 외부 메시지 발송, 자격증명 사용처럼 외부 영향이 크거나 되돌리기 어려운 행동이다.
저위험·가역적 행동은 사전에 정한 정책 안에서 자동화할 수 있다. 그러나 G3 행동은 evidence와 실행 계획, 영향 범위, rollback 방법을 제시한 뒤 Human의 명시적인 승인을 받아야 한다.
SQL 파일을 작성하는 일은 G1일 수 있지만, 그 SQL을 프로덕션 데이터베이스에서 실행하는 일은 G3다.
배포, 외부 공유, 데이터 변경, 헌장 수정, 역할 변경처럼 영향이 큰 행동은 에이전트가 Human 승인 대기를 반드시 요청해야만 한다.
수락자는 증거를 바탕으로 다음 상태 중 하나를 선택한다.
- accepted
- changes_requested
- rejected
- needs_human_verification
Worker의 자연어 응답만으로 accepted가 되는 경로는 없다.
Worker가 “완료했습니다”라고 응답해도 evidence bundle이 없거나 검증 결과가 주장과 일치하지 않으면 결과를 수락하지 않는다.
이 과정에서 실행 상태와 영구 지식을 따로 갱신한다
작업이 진행되는 동안 “지금 무엇을 하고 있는가”와 “앞으로도 유효한 사실은 무엇인가”를 같은 저장소에 섞지 않는다.
결과가 수락되면 현재 작업 상태와 장기 지식을 구분해서 기록한다.
| 새로 확인한 정보 | 기록 위치 |
|---|---|
| 현재 작업의 진행 결과와 blocker | beads issue |
| 다음 세션이 Track을 재개하는 데 필요한 상태 | LIVE handoff |
| 반복해서 사용할 제품·코드 지식 | 제품 레포 Wiki |
| 반복해서 사용할 하네스·운영 지식 | planning-repo/docs |
| 정본을 빠르게 찾기 위한 요약 | beads memory 포인터 |
| 현재 세션에서만 필요한 조사 메모 | scratchpad |
모든 작업 결과를 Wiki로 승격하지 않는다. 반복 가능성, 운영 위험, 외부 계약, 비직관성처럼 다음 작업에서도 가치가 있는 정보만 승격 후보로 분류한다.
beads memory에는 정본 전문을 복사하지 않는다.
summary: 프로덕션 DB 직접 write 금지
canonical_ref: planning-repo/docs/rules/OPERATING-RULES.md#prod-db
실제 규칙과 근거는 Git 문서에서 읽는다. memory가 오래되거나 손상되면 정본을 기준으로 다시 만들 수 있어야 한다.
Git hook은 문서 중복, 금지된 경로와 memory 길이처럼 Git 변경 시점에 확인할 수 있는 불변식을 검사한다.
중복 Master, Role Lock, 승인 상태처럼 실행 중에만 알 수 있는 불변식은 runtime guard와 probe 를 기반으로 검사한다.
현재 작업의 진행 상태와 blocker, 다음 행동, 승인 대기는 beads issue에 기록한다. 이는 해당 이슈가 살아 있는 동안 계속 바뀌는 실행 상태다.
작업 중 발견한 사실이 반복해서 필요하거나, 다른 결정의 근거가 되거나, 운영 위험과 연결된다면 영구 지식 승격 후보가 된다.
제품 코드와 직접 연결된 제약이나 반복 가능한 해결책은 제품 레포의 wiki로 승격한다. Orca 운영, 승계, 워크스페이스 공통 규칙처럼 하네스 수준의 지식은 planning-repo/docs로 승격한다.
이렇게 분리하면 이슈가 닫힌 뒤에도 필요한 지식은 정본에 남는다. 반대로 wiki에는 특정 작업의 시간순 진행 로그가 쌓이지 않는다.
현재 작업이 어디까지 진행됐고 어떤 blocker가 있는지는 beads issue에 기록한다.
작업 도중 발견한 제품의 지속적인 제약이나 반복 가능한 해결책은 제품 wiki로 승격한다. (이건 레포 단위의 AHE 에 의해 처리 됨)
Orca 승계와 같은 하네스 운영 지식은 (워크스페이스 단위의) 마스터 에이전트 하네스 문서로 승격한다.
이슈 진행 메모와 영구 지식이 섞이지 않기 때문에, 이슈가 닫혀도 장기적으로 필요한 지식은 남고, wiki에는 특정 작업의 일시적인 진행 상태가 쌓이지 않는다.
beads memory에는 정본을 찾기 위한 정보만 남긴다.
beads memory는 세션 시작 시 검색과 라우팅을 돕는 인덱스 역할만 한다.
예를 들어 다음과 같은 짧은 항목은 허용할 수 있다.
프로덕션 DB 직접 write 금지. 자세한 규칙과 예외는 planning-repo/docs/rules/OPERATING-RULES.md#prod-db 참조.
하지만 해당 규칙이 만들어진 배경과 사고 이력, 예외 조건, 변경 절차의 전문은 Git 문서에서 읽어야 한다.
memory가 손상되거나 stale 상태가 돼도 정본은 영향을 받지 않는다. memory는 Git 정본을 기준으로 다시 만들 수 있어야 하며, 영구 지식의 원본이 되어서는 안 된다.
실제 운영 규칙이나 ADR을 변경하려면 Git 문서를 수정하고 변경 이력을 남긴다. 정본으로 유지하지 않는 저장 위치에는 새로운 운영 지식을 기록하지 않는다.
Git은 일부 불변식을 강제하는 경계다.
워크스페이스 하네스 문서와 규칙을 planning-repo 같은 Git 저장소에서 관리하면 pre-commit 등의 hook을 이용해 일부 불변식 위반을 자동으로 검사할 수 있다.
예를 들어 다음 항목을 검사할 수 있다.
- 허용되지 않은 위치에 운영 문서가 생성됐는가
- 하나의 canonical ID가 여러 정본 문서에 중복됐는가
- memory 항목이 길이 제한을 넘어 전문 저장소처럼 사용되고 있는가
- 동결된 설계의 출처 없이 새로운 Runtime Unit이 추가됐는가
새 워크스페이스에 하네스 전용 Git 저장소가 없다면 git init으로 저장소를 만들거나 기존 planning-repo를 연결해야 한다. 그래야 hook과 commit 이력, diff를 정책 집행과 감사에 사용할 수 있다.
다만 Git 저장소가 Master 세션 자체를 통제하는 것은 아니다. Git은 하네스 문서와 변경 규칙을 강제하는 경계다.
Git hook은 commit이나 push 같은 Git 작업 시점에만 실행된다. 동일 세션의 중복 resume, PTY 생존 여부, 역할 잠금, 승인 상태처럼 실행 중에 계속 확인해야 하는 불변식은 별도의 런타임 가드와 프로브로 강제해야 한다.
여기까지가 하나의 역할 안에서 정상 작업을 실행하고 결과를 수락하는 기본 흐름이다. 장시간 운영에서는 여기에 역할 전환과 세션 승계, 장애 복구가 추가된다.
역할 전환은 명시적인 상태 전이다.
장시간 실행되는 Master는 하나의 역할만 계속 수행하지 않는다. 배포를 준비하다가 아키텍처 검토 요청을 받을 수도 있고, 구현 중 장애 조사가 필요해질 수도 있다.
Master가 Release/Operations 역할로 배포를 준비하던 중 Architecture 요청을 받았다고 가정해 보자.
이때 기존에 유지하던 역할을 갑자기 중단하고 지시에 따라 바로 새로운 작업을 시작하면 두 역할의 판단 기준과 미완료 상태가 한 세션 안에서 섞인다. 배포 중 확인해야 했던 승인 항목이 사라지거나, 조사 단계의 가설이 확정된 설계처럼 취급될 수 있다.
따라서 새로운 요청이 현재 역할에 속하는지 먼저 판정한다.
역할 전환은 다음 순서로 진행한다.
Current Role
│
▼
Complete or Park Current Work
│
▼
Record accepted / unaccepted / blockers
│
▼
Write Role Handoff
│
▼
Verify Unlock
│
▼
Switch Role
이때 최소한 다음 상태를 남긴다.
- 완료하고 수락된 결과
- 제출됐지만 아직 수락되지 않은 결과
- Human 승인을 기다리는 행동
- 아직 닫히지 않은 질문과 blocker
- 진행 중인 Worker lease
- 기존 역할로 돌아오기 위한 조건
- 다음에 읽어야 할 정본 경로
역할 전환과 Track 전환은 같은 개념이 아니다. 하나의 Track 안에서 Research에서 Implementation으로 바뀔 수 있고, 역할을 유지한 채 다른 Track으로 이동할 수도 있다.
한 Master 세션에서 활성 역할은 한 번에 하나만 둔다.
이 상태를 역할 handoff에 기록한 뒤 기존 Role State를 파킹하고, 필요한 unlock 절차를 거쳐 Architecture 역할로 전환한다.
Architecture 작업이 끝나면 같은 방식으로 설계 결과와 미결 사항을 남긴다. 이후 return_role이 Release/Operations라면 이전 배포 트랙의 상태를 다시 읽고 해당 역할로 복귀한다.
역할 전환이 항상 트랙 전환을 의미하지는 않는다.
하나의 트랙 안에서 Research에서 Feature Implementation으로 이동할 수도 있다. 반대로 다른 트랙으로 이동하면서 역할까지 함께 바뀔 수도 있다.
중요한 것은 한 번에 하나의 역할만 활성 상태로 두고, 역할마다 진입과 이탈 기록을 남기는 것이다.
(현재는 이 절차를 헌장과 Role State 문서를 통해 수동으로 집행한다.)
참조 구현의 Role Runtime은 역할 잠금과 파킹, handoff, unlock, 복귀 절차를 코드로 강제한다.
세션이 끝나기 전에 승계하고, 사라지면 복구한다
Master 세션의 컨텍스트가 한계에 접근하거나, 자연스러운 작업 마일스톤에 도달하거나, 사용자가 승계를 지시하면 Succession Manager가 개입하여 승계를 준비한다.
전임은 진행하던 작업을 모두 동결한 뒤 thin handoff를 작성한다.
후임 세션은 이 handoff와 Work Ledger, Git 정본을 기준으로 복구한다.
Charter
↓
LIVE Handoff
↓
Work Ledger
↓
Git Canonical State
↓
Baseline Measurement
후임은 단순히 “읽었습니다”라고 답하는 것으로 검증을 통과하지 않는다. 현재 역할, 활성 Track, 마지막 수락 결과, 다음 허용 행동과 금지 행동을 재진술하고 정본의 원시값을 직접 확인해야 한다.
후임 검증이 끝나기 전에는 전임을 종료하지 않는다.
여기서 중요한 것은 컨텍스트가 완전히 소진될 때까지 기다리지 않는 것이다. 전임이 현재 상태를 정리하고 handoff를 남길 수 있을 때 승계해야 한다.
승계 시점에는 현재 상태를 전부 대화 로그로 복사하지 않는다. 얇은 handoff만 필요하다.
활성 트랙, 현재 역할, 마지막으로 수락된 산출물, 아직 승인되지 않은 행동, 열린 질문, 필요한 정본 경로만 포함한 thin handoff 문서를 만든다.
반면 프로세스가 이미 종료됐거나 런타임 장애로 전임이 handoff를 작성할 수 없는 상황은 Succession이 아니라 Recovery가 먼저 개입한다.
Succession은 전임이 살아 있는 상태에서 의도적으로 역할을 넘기는 절차이고, Recovery는 기존 실행의 생존 여부가 불확실하거나 이미 손실된 상황에서 상태를 복구하는 절차다.
Reattach
→ daemon / PTY / process 확인
→ 같은 세션 resume은 한 번만 시도
→ 기존 실행 소멸 확인
→ 필요한 경우 successor 생성
런타임이 재시작됐다는 이유만으로 새 Master를 만들지 않는다.
승계에는 대화 전문이 아니라 thin handoff를 사용한다.
승계할 때 현재 대화 로그 전체를 후임에게 복사하지 않는다.
긴 대화에는 이미 정본으로 승격된 정보와 폐기된 가설, 일시적인 명령 출력, 나중에 번복된 판단이 함께 섞여 있다. 이를 그대로 넘기면 후임은 무엇이 현재 상태인지 다시 판별해야 한다.
thin handoff에는 다음과 같은 최소 상태만 담는다.
- 전임 세션과 현재 역할, 활성 트랙
- 현재 목표
- 마지막으로 수락된 결과
- 제출됐지만 아직 수락되지 않은 결과
- 실행 중인 Worker lease
- 열린 질문과 blocker
- Human 승인을 기다리는 행동
- Git, .planning, Work Ledger의 정본 포인터
- 정확한 재개 위치와 다음 허용 행동
- 후임이 단정해서는 안 되는 사항
- 승계 내용을 확인하기 위한 verification challenge
후임은 이 handoff만 읽고 전임의 판단을 그대로 이어받지 않는다. 헌장과 Work Ledger, Git 정본을 직접 확인해 handoff의 내용을 대조해야 한다.
후임 마스터의 “읽었습니다”라는 응답만으로 승계를 완료하지 않는다.
후임은 현재 역할과 활성 트랙, 마지막으로 수락된 산출물, 다음 허용 행동과 금지 행동을 재진술해야 한다.
그러나 재진술만으로도 충분하지 않다. handoff가 가리키는 정본을 실제로 조회하고, 가능한 경우 현재 Git HEAD와 worktree 상태, 관련 프로세스와 프로브 값을 다시 측정해야 한다.
후임이 확인해야 할 항목은 다음과 같다.
- handoff가 가리키는 Git 문서와 Work Ledger 항목이 실제로 존재하는가
- 마지막 수락 산출물과 현재 Git 상태가 일치하는가
- 활성 Worker와 lease 상태가 실제 프로세스 상태와 일치하는가
- 아직 승인되지 않은 변경이 완료 상태로 잘못 표시되지 않았는가
- 전임과 같은 session ID 또는 track-role을 사용하는 실행이 중복으로 존재하지 않는가
검증이 끝나기 전까지 전임은 변경 가능한 작업을 중단한 채 대기한다. 전임과 후임이 동시에 존재하더라도 하나만 활성 Master로 행동해야 한다.
후임이 verification challenge를 통과한 뒤에야 승계를 기록하고 전임을 은퇴시킨다. 검증에 실패하면 전임을 유지하거나 Human에게 복구 판단을 요청한다.
현재는 이 절차를 사람과 에이전트가 수동으로 집행한다. 참조 구현의 Succession Manager는 동결, handoff 생성, 후임 검증, 전임 은퇴 순서를 자동으로 관리한다.
lineage는 감사 기록이지 후임의 지식 입력이 아니다.
승계 결과는 Lineage Recorder에 append-only로 기록한다.
lineage에는 누가 누구를 승계했는지, 어떤 복구 소스를 사용했는지, 검증에 성공했는지, 재질문과 재개봉 결정이 몇 건 발생했는지, 컨텍스트 유실이 있었는지 등을 남긴다.
하지만 이 기록을 다음 Master의 부팅 컨텍스트에 자동으로 주입하지 않는다. 과거 세대의 성공과 실패, 감점 내역이 현재 판단의 근거처럼 작동하면 후임의 판단이 계보에 오염될 수 있다. lineage는 누가 누구를 승계했고 어떤 검증을 통과했는지 확인하기 위한 관측 데이터다.
후임이 읽어야 하는 것은 헌장과 현재 handoff, Work Ledger, Git 정본이다. lineage는 운영자가 승계 품질과 실패 패턴을 조사할 때 사용하는 관측 데이터다.
운영자는 lineage를 읽고 다음 승계 절차나 handoff 스키마를 개선할 수 있다. 다만 개선된 규칙은 lineage에서 직접 주입하지 않고, 검토를 거쳐 헌장이나 runbook 같은 정본에 반영한다.
복구에서는 재생성보다 재부착을 먼저 검증한다.
Recovery Manager는 승계뿐 아니라 Orca 앱 재시작 같은 장애 상황에서도 사용된다.
먼저 실행 중 프로세스와 PTY, 터미널 연결 상태를 확인하고, 살아 있는 세션이 있다면 재부착한다.
Orca 앱이나 런타임이 재시작됐거나 세션이 UI에서 보이지 않을 때는 Recovery 절차를 시작한다.
먼저 다음 계층을 순서대로 확인한다.
- 클라이언트가 기존 세션과 연결돼 있는가
- Orca runtime이 응답하는가
- daemon과 PTY가 살아 있는가
- PTY 위의 에이전트 프로세스가 실행 중인가
- 기존 세션 저장 파일을 안전하게 resume할 수 있는가
- 최신 handoff와 Work Ledger, Git으로 후임을 생성해야 하는가
런타임이 재기동됐다는 이유만으로 새 마스터를 만들지 않는다.
기존 세션이 실제로 소멸했다는 증거가 있을 때만 새 세션을 만들고 handoff로 복구한다.
세션 저장 파일만 남아 있어 resume이 필요하다면 동일 세션을 한 번만 resume한다. 다른 프로세스가 같은 세션을 사용 중인지 확정할 수 없다면 새 resume을 중단하고 Human에게 상태를 올린다.
기존 실행이 실제로 소멸했다는 증거가 있을 때만 후임 세션을 만든다. 후임은 최신 handoff와 Work Ledger, Git 정본을 기준으로 최소 상태를 복구한다.
재생성보다 재부착 검증이 먼저다. 이 설계는 이날 오전에 발생한 Orca 장애 분석에서 직접 도출된 것이다.
이 원칙은 Orca의 UI 프로세스와 runtime daemon, PTY, 에이전트 프로세스가 서로 다른 생명주기를 가질 수 있다는 실측에서 나왔다. 앱이 재시작됐다는 사실만으로 세션이 죽었다고 결론 내릴 수 없다.
Observability는 자연어 응답이 아니라 실제 상태를 관측한다.
Observability는 서비스 모니터링과 비슷하지만 대상이 에이전트 런타임이다.
어떤 Worker가 어떤 lease로 생성됐는지, 현재 실행 중인지, 제출된 artifact가 존재하는지, 후임 Master가 handoff를 읽었는지, 동일 세션이 중복 실행되고 있지 않은지, 워크스페이스 문서가 Git 밖에 생성되고 있지 않은지 등을 프로브로 확인한다.
여기서 기준은 에이전트의 자연어 응답을 관측값으로 쓰지 않는 것이다.
에이전트 하네스의 Observability는 대화 내용을 읽고 “잘 진행되는 것 같다”고 판단하는 기능이 아니다.
파일, 프로세스, Git 이력, 테스트, 로그, 연결 상태 같은 외부 증거가 기준선이 된다.
- 어떤 Worker가 어떤 lease로 생성됐는가
- lease에 연결된 PID와 worktree가 실제로 존재하는가
- Worker가 제출했다고 한 artifact와 diff가 존재하는가
- 테스트와 프로브가 실제로 실행됐는가
- 후임 Master가 정본을 읽고 기준선을 다시 측정했는가
- 동일한 session ID 또는 track-role Master가 중복 실행 중인가
- Git이 관리해야 할 운영 문서가 허용되지 않은 위치에 생성됐는가
- 승인 대기 중인 G3 행동이 실행되지 않았는가
- 트랙마다 LIVE handoff가 한 건만 존재하는가
관측값은 파일, Git 이력, 프로세스, PTY, 로그, 테스트 결과, 포트와 HTTP 응답 같은 외부 증거에서 가져온다.
모니터와 프로브에도 소유 세션을 명시해야 한다. 승계 시 전임이 실행하던 모니터를 그대로 물려받지 않고, 후임이 현재 기준선을 다시 측정한 뒤 자신의 세션 소유로 재무장한다.
그렇지 않으면 모니터가 정상처럼 보여도 어느 세션의 상태를 관측하는지 알 수 없게 된다.
전체 시스템은 하나의 폐쇄 루프로 동작한다.
정본 지식
→ 최소 컨텍스트 적재
[사용자 요청]
→ 현재 역할과 활성 트랙 확인
→ 대상 워크스페이스와 레포 판별
→ 필요한 Repository Harness 적재
→ 제한된 Worker lease 발급
→ 격리된 환경에서 실행
→ diff·테스트·프로브 등 외부 증거 제출
→ 정책 또는 Human Gate를 통한 수락
→ Work Ledger의 실행 상태 갱신
→ 영구 지식 승격
→ beads memory의 정본 포인터 갱신
마스터 세션 승계 과정에서는 다음 흐름이 이어진다.
현재 작업 동결
→ thin handoff 작성
→ 후임이 헌장·Work Ledger·Git 정본 확인
→ 기준선 재측정과 verification challenge
→ 승계 결과를 lineage에 기록
→ 전임 은퇴
→ 후임이 같은 역할과 트랙에서 작업 재개
장애 상황에서는 승계보다 먼저 기존 실행의 생존 여부를 확인한다.
세션이 보이지 않음
→ 클라이언트·runtime·daemon·PTY·프로세스 확인
→ 살아 있으면 기존 세션에 재부착
→ 재부착할 수 없지만 저장 상태가 유효하면 한 번만 resume
→ 기존 실행이 소멸했으면 handoff·Work Ledger·Git으로 후임 생성
이 세 흐름을 하나로 연결하면 다음과 같다.
Git Canonical Knowledge
+
Work Ledger Current State
+
LIVE Handoff
│
▼
Master
│ role / track / gate
▼
Worker Scheduler
│ lease
▼
Worker
│ artifact + evidence
▼
Acceptance
├─ 실행 상태 ─────► Work Ledger
└─ 영구 지식 ─────► Git
│
▼
다음 작업 또는 승계
시스템의 목표는 기억력이 아니라 반복 가능한 운영 계약이다.
이 구조에서 중요한 것은 특정 Master 가 이전 대화를 오래 기억하는가가 아니다.
세션이 바뀌어도 같은 정보 구조를 읽고, 같은 권한 경계를 따르며, 같은 증거와 승인 절차를 거치게 만드는 것이 중요하다.
에이전트가 이전 대화를 정확히 기억하지 못해도 시스템은 Work Ledger와 Git 정본, thin handoff를 이용해 복구할 수 있어야 한다.
특정 모델이나 실행 도구를 adapter 계약이 유지된다면 같은 운영 구조를 사용할 수 있어야 한다.
특정 세션이 잘못된 판단을 내리더라도 영구 정본과 최종 승인권까지 혼자 바꿀 수 없어야 한다.
런타임 구조만 있고 지식 구조가 없다면 후임은 오래된 복제본을 읽고도 자신이 맞다고 판단할 수 있다. 반대로 지식 구조만 있고 런타임 통제가 없다면 문서는 남더라도 세션 재부착과 중복 실행 방지, evidence acceptance, Human Gate가 집행되지 않는다.
그래서 런타임 설계와 지식 구조는 같은 폐쇄 루프 안에 들어갔다.
다음 날에는 유저가 직접 검증을 지시하였다. 이 가운데 실제 운영 중인 승계·복구·정본 분리 절차를 세 차례의 Master 승계로 검증했다. handoff 수신, Git 기준선, PID와 커맨드라인, Work Ledger, orphan 모니터 정리 여부를 대조했다.
이 실측은 12개 런타임 유닛과 Approval Manager 전체가 완벽히 구현됐다는 것은 아니다.
현재 수동으로 운영하는 승계 프로토콜과 지식 정본 규칙이 실제 세션 교체에서도 작동했음을 보여주는 예시다.
handoff 수신, PID 대조, Work Ledger 확인, orphan 모니터 정리까지 실제 절차로 검증 및 정상 동작을 확인하였다.
3부에서는 이 수동 규약을 코드와 테스트로 옮기기 위한 시스템 명세를 설명한다.
3부. 시스템 상세 및 내부 동작 명세
안내: 이 절은 하네스를 직접 만들거나 기존 조직 환경에 맞게 옮기려는 독자를 위한 명세다.
지금 당장 구현할 계획이 없다면 모든 세부 항목을 따라갈 필요는 없다.
먼저 3.1의 불변식과 3.29의 실패 패턴만 읽고 실패 패턴을 읽은 뒤 4부로 넘어가도 전체 흐름을 이해할 수 있다.
1부와 2부에서는 이 하네스가 왜 필요하며 어떤 원리로 작동하는지 설명했다.
3부에서는 그 개념을 상태와 인터페이스, 계약 테스트, 복구 및 승계 절차로 구체화한다.
이 절의 핵심 질문은 다음과 같다.
- 각 컴포넌트는 어떤 상태의 정본을 소유하는가
- 어떤 입력을 받아 어떤 결과를 만드는가
- 다른 컴포넌트와 어떤 계약으로 연결되는가
- 정상 실행과 실패, 승인 대기, 역할 전환, 승계와 복구를 어떻게 처리하는가
- 수동으로 운영 중인 규약을 코드와 테스트로 어떻게 강제할 것인가
이 절에서 각 컴포넌트는 다음 네 질문으로 설명한다.
- 어떤 상태를 소유하는가
- 어떤 입력을 받는가
- 어떤 출력과 증거를 만드는가
- 어떤 조건에서 실행을 중단하는가
시스템의 책임은 크게 네 영역으로 나뉜다.
- Human은 우선순위와 최종 권한, 외부 세계에 영향을 주는 결정을 맡는다.
- Master Orchestrator는 워크스페이스의 트랙과 역할, 위임, 승인 제안, 승계와 복구를 조율한다.
- Repository Harness는 각 레포의 지식과 규칙, 계획, 빌드 및 테스트 진실을 소유한다.
- Execution Worker는 Master가 발급한 lease 안에서 격리된 작업을 수행하고 증거를 제출한다.
┌─────────────────────────────────────────────────────────────┐
│ Human │
│ Priority · Approval · Final Acceptance · External Authority│
└─────────────────────────────┬───────────────────────────────┘
│
│ proposal / evidence / decision
▼
┌─────────────────────────────────────────────────────────────┐
│ Master Orchestrator │
│ Track · Role · Approval · Scheduling · Recovery · Succession│
└───────────────┬───────────────────────────────┬─────────────┘
│ │
│ repository contract │ lease / result
▼ ▼
┌─────────────────────────────┐ ┌────────────────────────────┐
│ Repository Harness │ │ Execution Worker │
│ Knowledge · Rules · Tests │ │ Worktree · Task · Evidence │
└─────────────────────────────┘ └────────────────────────────┘
3.1 시스템의 기본 불변식
하네스 구현에서는 개별 기능보다 먼저 시스템이 절대로 위반해서는 안 되는 규칙을 코드와 테스트로 고정해야 한다.
기능이 정상적으로 보이더라도 이 규칙이 깨지면 전체 시스템의 신뢰성을 보장할 수 없다.
| ID | 불변식 | 위반을 막는 방법 |
|---|---|---|
| INV-01 | 비가역적이거나 외부에 영향을 주는 최종 권한은 Human에게 남는다 | G3 승인 게이트 |
| INV-02 | 하나의 정보 유형에는 하나의 정본과 소유자만 둔다 (e.g. Master는 Repository 지식을 소유하지 않는다) | 다른 저장 위치에는 전문을 복제하지 않고 정본을 가르키는 포인터만 둔다 (Master는 레포 지식을 읽고 사용할 수 있지만 별도의 정본으로 복제하지 않는다) |
| INV-03 | Worker는 발급받은 lease 밖의 상태를 변경하지 않는다 (Worker는 자신의 결과를 최종 수락할 수 없다) | Worker는 결과와 증거를 제출하며, 별도의 수락 주체가 이를 판정한다 (경로·capability·worktree 격리) |
| INV-04 | 후임 검증이 끝나기 전에 전임 Master를 은퇴시키지 않는다 | Succession Verification Gate |
| INV-05 | 화면에서 보이지 않는 세션을 즉시 죽은 세션으로 판단하지 않는다 | 클라이언트, runtime, daemon, PTY, 에이전트 프로세스를 별도로 확인한다 |
| INV-06 | 같은 session ID를 동시에 두 번 resume하지 않는다 | 기존 실행 여부가 불명확하면 추가 resume이나 재스폰을 중단한다 (중복 session guard) |
| INV-07 | 하나의 Master 세션에는 한 번에 하나의 역할만 활성화한다 | 역할을 전환하기 전에 기존 역할을 완료하거나 파킹한다 (Role State와 Role Lock) |
| INV-08 | 현재 실행 상태와 영구 지식을 분리한다 | 진행 상태는 Work Ledger에, 장기 사실은 Git 정본에 둔다 (Work Ledger와 Knowledge Store 분리) |
| INV-09 | Agent의 자기 보고를 수락 증거로 사용하지 않는다 | 파일, diff, 테스트, 로그, 프로세스, 프로브 결과를 증거로 사용한다 |
| INV-10 | Architecture Freeze 이후 구현 문서가 새 책임을 만들지 않는다 | 새 Runtime Unit이나 책임 이동에는 별도 ADR과 승인이 필요하다 (동결 출처와 ADR 검사) |
| INV-11 | lineage를 다음 Master의 자동 지식 입력으로 사용하지 않는다 | Bootstrap 입력에서 lineage 제외 (승계 계보를 다음 세션의 판단 근거로 자동 주입하지 않는다) |
| INV-12 | scratchpad에는 유실돼도 되는 정보만 둔다 | 세션 이후에도 필요한 내용은 종료 전에 정식 정본으로 승격한다 |
불변식은 문서에 적어 두는 것으로 끝나지 않는다. 검증 방식은 정보의 성격에 따라 나눈다.
- 파일과 정본 구조: 정적 검사, Git hook, pre-commit
- 인터페이스와 상태 전이: 계약 테스트
- 세션·프로세스·역할 상태: runtime guard
- 승계·복구·중복 실행: 시나리오 테스트와 프로브
예를 들어 Git hook은 Git 밖에서 실행 중인 중복 Master를 탐지할 수 없다. 반대로 runtime guard는 동일한 ADR이 두 정본 파일에 복제됐는지 판단하기 어렵다. 하나의 검사 방식으로 모든 불변식을 강제하려 해서는 안 된다.
불변식의 성격에 따라 강제 방법도 달라진다.
- 정적 검사는 canonical ID 중복, 금지된 경로의 문서, descriptor 형식, 동결 출처 누락을 검사한다.
- 계약 테스트는 Worker 자기 수락, G3 승인 우회, 역할 잠금 위반 같은 상태 전이를 실패 처리한다.
- Git hook은 commit이나 push 시점에 정본 중복과 문서 위치, Architecture Drift를 검사한다.
- 런타임 가드는 session ID와 Role State, approval state에 대한 원자적 잠금과 전이 규칙을 강제한다.
- 런타임 probe는 PID, PTY, lease, handoff, 중복 Master 같은 실제 실행 상태를 관측한다.
예를 들어 beads memory에 장문의 전문이 저장됐는지는 길이와 필수 포인터 필드를 검사할 수 있다. 동일한 session ID를 사용하는 둘 이상의 프로세스가 존재하는지는 PID와 커맨드라인, 세션 저장 경로를 대조하는 프로브로 확인할 수 있다.
Git 밖의 허용되지 않은 경로에 운영 문서가 생성됐는지는 Git hook 하나만으로 완전히 차단하기 어렵다. 관리 대상 경로를 스캔하는 workspace guard나 주기적인 프로브를 함께 사용해야 한다.
- 각 불변식에 대응하는 핵심 계약 테스트는 3.27에서 다시 정리한다.
3.2 책임과 소유권 모델
소유권은 “누가 이 정보를 볼 수 있는가”가 아니라 “누가 이 상태의 정본을 관리하고, 정해진 계약 안에서 변경하며, 그 결과에 책임지는가”를 기준으로 판정한다. 소유권과 승인권도 구분해야 한다.
Repository Harness가 레포 지식의 정본을 소유하더라도, 모든 변경을 Human 승인 없이 실행할 수 있다는 뜻은 아니다. 소유권은 정본의 위치를 정하고, 승인 게이트는 특정 행동의 실행 권한을 통제한다.
권한과 실행 주체
| 주체 | 소유하는 상태 | 수행할 수 있는 변경 | 소유하지 않는 것 |
|---|---|---|---|
| Human (Dorito, 나) | 우선순위, 헌장, 역할 unlock, 외부 자격증명과 프로덕션 권한, 최종 권한 | 승인·거절, G3 행동 허가, 우선순위와 헌장 변경 | Worker 내부 구현 세부, 반복 가능한 기계적 집행 |
| Master Orchestrator | Track Registry, Role State, lease 대장, 승인 제안, 크로스레포 계획, 승계 상태 | 트랙 개설·파킹·종결, Worker 위임, 복구와 승계, 릴리즈 조율 | 레포 내부 코드와 지식의 정본, 외부 권한 |
| Repository Harness | 레포의 코드, 규칙, Wiki, .planning, 빌드·테스트 계약 | 레포 컨텍스트 제공, 검증 수행, 레포 계약에 따른 변경 | 다른 레포와 워크스페이스 상태 |
| Execution Worker | lease 범위의 작업 사본과 임시 상태 | 지정 worktree 안의 조사, 코드 변경, 테스트, 증거 제출 | 영구 지식, 최종 수락, lease 밖의 상태 |
| Approval Manager | 승인 제안과 게이트 판정 상태 | 위험도 분류, 승인 요청, 만료 처리 | Human의 G3 결정 |
| Observability | 관측 기준선, 프로브 결과, 경보 | 측정과 경보 기록 | 관측 대상 자체의 정본 |
소유권 충돌이 발생하면 임의로 우선순위를 정하지 않는다.
- 하나의 레포에서 완결되는 상태면 Repository Harness로 내린다.
- 두 개 이상의 레포를 함께 봐야 의미가 있으면 Workspace Runtime으로 올린다.
- 외부 세계에 영향을 주거나 되돌리기 어려운 결정이면 Human에게 올린다.
관측하는 주체와 변경하는 주체도 분리한다. Observability가 Worker의 프로세스를 측정할 수는 있지만 해당 Worker의 결과를 대신 수락하지는 않는다.
저장 및 관측 시스템
정본이 아닌 것
| 시스템 | 정본 또는 역할 | |
|---|---|---|
| Work Ledger | 현재 이슈 상태와 실행 서사의 정본 | 장기 지식의 전문 |
| Knowledge Store | 승인된 영구 지식과 변경 이력의 정본 | 현재 작업 큐와 일시적인 진행 상태 |
| beads memory | 짧은 정책 요약과 정본 포인터를 담는 재생성 가능한 캐시 | ADR, runbook, postmortem의 정본 |
| LIVE handoff | 현재 트랙을 다음 Master가 재개하기 위한 상태 묶음 | 장기 제품 지식과 운영 지식의 최종 정본 |
| Trace Archive | 과거 세션과 실행 흔적을 조회하는 감사 자료 | 현재 상태와 현재 결정의 정본 |
| lineage ledger | 승계 품질과 계보를 기록하는 append-only 관측 데이터 | 다음 세션의 런타임 지식 입력 |
| Notion | 갱신하지 않는 과거 문서 아카이브 | 기계가 신뢰하는 현재 정본 |
| scratchpad | 현재 세션의 휘발성 조사 메모 | 세션 이후 보존해야 하는 지식소유권 충돌이 발생하면 임의로 한쪽에 우선권을 주지 않는다. 먼저 정보가 적용되는 범위를 판별한다. - 하나의 레포 안에서 완결되는 정보라면 해당 Repository Harness가 소유한다. - 둘 이상의 레포를 조율해야만 의미가 생긴다면 Workspace Runtime이 관리한다. - 외부 세계에 영향을 주거나 되돌리기 어려운 결정이라면 Human의 권한에 속한다. |
3.3 Master Orchestrator의 내부 구성
Master Orchestrator는 하나의 거대한 프롬프트가 아니라 서로 다른 상태를 다루는 Runtime Unit의 집합이다.
Start
├─ Bootstrap
├─ Context Resolver
├─ Workspace Runtime
└─ Repository Runtime Loader
Execute
├─ Worker Scheduler
├─ Approval Manager
└─ Role Runtime
Continue
├─ Recovery Manager
├─ Succession Manager
├─ Lineage Recorder
└─ Observability
Integrate
└─ Adapter Layer
초기 구현에서 이 Unit들이 각각 별도 프로세스일 필요는 없다. 하나의 CLI 안에 존재하더라도 다음 조건을 만족해야 한다. (책임과 인터페이스가 분리되어있는 것이 가장 중요하다)
- 소유 상태가 구분돼 있다.
- 입력과 출력 타입이 명시돼 있다.
- 다른 Unit의 상태를 직접 덮어쓰지 않는다.
- 제품별 명령은 Adapter를 통해 호출한다.
- 실패가 발생했을 때 어느 Unit이 상태를 복구할지 알 수 있다.
| Unit | 컴포넌트 | 핵심 책임 | 대표 입력 | 대표 출력 |
|---|---|---|---|---|
| U1 | Bootstrap | 최소 부팅 컨텍스트 적재 | Charter, Role State, 최신 LIVE handoff | Boot Context |
| U2 | Context Resolver | 현재 작업의 책임 경계와 capability 판정 | cwd, 사용자 요청, workspace map, repo metadata | Context Descriptor |
| U3 | Workspace Runtime | 트랙과 크로스레포 상태 관리 | Work Ledger, dependency map | Track State |
| U4 | Repository Runtime Loader | 필요한 Repository Harness만 lazy load | Context Descriptor | Repository Harness Context |
| U5 | Worker Scheduler | dispatch, lease 발급, reap, 예산 강제 | Task, repository, execution profile | Worker Lease, Worker Reference |
| U6 | Approval Manager | 행동의 위험도와 승인 게이트 분류 | Action Proposal, evidence | Gate Class, Approval State |
| U7 | Role Runtime | 역할 상태와 잠금, 전환 절차 관리 | Role State, switch proposal | Updated Role State |
| U8 | Recovery Manager | 장애 후 기존 세션 또는 작업 상태 복구 | handoff, Git, process state | Recovery Decision, Recovered Session |
| U9 | Succession Manager | 동결, handoff, 후임 검증, 전임 은퇴 | context signal, user request, runtime health | Succession Result, Successor Reference |
| U10 | Lineage Recorder | 승계 계보와 품질 지표 기록 | Succession Result | Lineage Entry |
| U11 | Observability | 프로브, 기준선, 경보, 수락 로그 관리 | runtime event, probe specification | Evidence, Alert |
| U12 | Adapter Layer | 외부 제품과 core의 결합 격리 | 추상 인터페이스 호출 | 도구별 실행 결과 |
3.4부터 각 Unit의 계약을 순서대로 설명한다.
3.4 Bootstrap
Bootstrap은 세션이 시작될 때 최소 정책과 현재 상태를 읽는 Unit이다.
세션이 다음 행동을 안전하게 결정할 수 있을 만큼의 최소 정보만 적재한다.
컨텍스트를 L0부터 L4까지 나누되, Bootstrap이 직접 적재하는 범위는 L0와 L1로 제한한다.
입력
- Master Charter
- L0 Policy Kernel
- 현재 Role State
- 최신 LIVE handoff
- 활성 Track을 찾기 위한 L1 포인터
| 계층 | 포함 내용 | 적재 시점 | 예시 |
|---|---|---|---|
| L0 Policy Kernel | 모든 상황에 적용되는 절대 규칙과 승인 정책 | 모든 세션 시작 시 직접 적재 | 프로덕션 DB 직접 write 금지, 자기 보고 단독 수락 금지 |
| L1 Workspace Index | 현재 역할, 활성 트랙, 최신 handoff와 정본 포인터 | 세션 시작 시 정해진 예산 안에서 적재 | 활성 트랙, product-repo 경로, 관련 issue ID |
| L2 Repository Context | 레포 규칙, 관련 ADR, planning, 검증 방법 | 대상 레포가 확정된 뒤 lazy load | 제품 레포 배포 runbook |
| L3 Task Context | 특정 이슈와 구현에 필요한 문서와 제약 | Worker lease를 발급할 때 적재 | 리포트 API spec, 관련 테스트 |
| L4 Trace Context | 과거 세션의 상세 기록 | 실패 조사나 증거 회수 시에만 조회 | 이전 세션 JSONL |
출력
bootstrap_context:
charter_revision: "..."
current_role: "..."
role_lock: "..."
active_tracks: []
live_handoff_refs: []
canonical_pointer_index: []
prohibited_actions: []
부팅 순서
부팅 과정은 다음 순서로 진행된다.
Bootstrap 단계에서는 전체 wiki를 스캔하거나 모든 beads memory를 전문으로 읽지 않는다.
마스터 에이전트 터미널 부팅이 완료된 시점에는 "무엇을 읽어야 하는지"는 알지만, 아직 모든 내용을 읽은 상태까지 가지 않는다.
Bootstrap 단계에서는 전체 wiki를 스캔하거나 모든 beads memory 항목을 전문으로 읽지 않는다.
L2 이후의 정보는 현재 요청과 대상 레포가 확정된 뒤 필요한 만큼만 불러온다.
L0와 L1에는 별도의 컨텍스트 예산을 둬야 한다. 예산을 초과하면 내용을 임의로 잘라서 주입하는 대신, 장문의 설명이나 중복 정보를 제거하고 정본 포인터로 바꾸도록 실패 또는 경보를 발생시킨다. (ultracode 로 Fable5 서브에이전트 105개 호출했던 경험이 있었다;)
Session Start
│
▼
Load Charter and L0 Policy Kernel
│
▼
Read Role State and Latest LIVE Handoff
│
▼
Resolve Current Workspace and Active Tracks
│
▼
Load L1 Pointer Index
│
▼
Wait for Task Classification
Bootstrap은 다음 작업을 하지 않는다.
- 모든 레포의 Wiki를 읽지 않는다.
- 모든 beads memory를 전문으로 주입하지 않는다.
- 과거 lineage 전체를 읽지 않는다.
- 아직 선택되지 않은 레포의 runbook을 로딩하지 않는다.
다음 조건에서는 정상 부팅으로 처리하지 않는다.
- Charter revision을 확인할 수 없다.
- 하나의 Track에 LIVE handoff가 여러 개 있다.
- Role State가 없거나 두 역할이 동시에 활성화돼 있다.
- L0·L1이 정해진 컨텍스트 예산을 초과한다.
Bootstrap이 끝났다는 것은 모든 지식을 읽었다는 뜻이 아니다. 현재 요청을 어디로 라우팅할지 결정할 수 있는 상태가 됐다는 뜻이다.
L0는 모든 상황에 적용되는 정책 커널이다. Human 승인권, 금지된 행동, 정본 판별 원칙, 역할 전환 규칙, 증거 기준처럼 반드시 시작 시점부터 알아야 하는 내용이다.
L1은 현재 활성 트랙과 레포를 찾기 위한 포인터 인덱스다. 마스터 세션은 부팅이 끝났을 때 모든 정보를 알고 있을 필요가 없다. 다음에 무엇을 어디서 읽어야 하는지만 알면 된다.
실제 제품 지식과 상세 runbook은 L2 이후의 lazy read 대상으로 둔다.
Bootstrap 완료의 기준은 “모든 지식을 읽었다”가 아니다. 다음 항목을 설명할 수 있으면 된다.
- 현재 Master의 역할은 무엇인가
- 어떤 트랙이 활성 또는 파킹 상태인가
- 즉시 금지되는 행동은 무엇인가
- 현재 상태를 복구하려면 어떤 handoff와 Work Ledger를 읽어야 하는가
- 특정 레포 작업이 들어오면 어느 Repository Harness를 적재해야 하는가
3.5 Context Resolver
Context Resolver는 현재 요청이 어느 책임 경계에서 실행돼야 하는지 판정한다.
입력:
단순히 현재 작업 디렉터리(cwd)만 보고 레포를 결정해서는 안 된다. 워크스페이스 루트에서 특정 레포의 파일을 대상으로 작업할 수도 있고, 별도의 worktree에서 Master가 실행될 수도 있다. 하나의 요청이 여러 레포를 동시에 가리킬 수도 있다.
따라서 다음 정보를 함께 비교해야 한다.
- 현재 경로와 대상 파일 경로
- Human 요청과 명시된 대상
- Human 승인과 정책 제약
- Git root, remote, branch, worktree metadata
- 현재 활성 트랙과 연결된 레포 목록
- 현재 Role State
- Repository descriptor
출력: Context Descriptor
context:
workspace_id: "project-a"
repository_id: "product-backend"
repository_root: "/workspace/product-backend"
worktree_id: "worker/ex-142"
track_id: "report-api"
current_role: "feature-implementation"
capabilities:
- code-write
- local-test
prohibited:
- direct-prod-db-write
canonical_refs:
- "docs/wiki/..."
- ".planning/..."
판정 결과는 Context Descriptor로 만든다.
| 필드 | 설명 | 예시 |
|---|---|---|
| kind | 현재 작업 경계 | workspace, repository, worktree, external |
| workspace_id | 현재 워크스페이스 식별자 | project-a |
| repository_id | 대상 레포. 워크스페이스 작업이면 null | product-repo |
| track_id | 연결된 활성 트랙 | service-prod-launch |
| role | 현재 Master 역할 | ReleaseOperations |
| capabilities (*) | 현재 컨텍스트에서 이미 허용된 행동의 교집합 (허용된 read/write/execute 범위) | git_read, test_run |
| constraints | 현재 작업에 강제되는 제약 | no_prod_db_write |
| knowledge_roots | 읽을 수 있는 정본 지식 경로 | product-repo/docs/wiki |
| planning_root | 관련 planning 위치 | product-repo/.planning |
| work_ledger_scope | 조회하거나 갱신할 이슈 범위 | EX-* |
여기서 capabilities는 Context Resolver가 새 권한을 부여한다는 뜻이 아니다.
현재 역할과 트랙, Repository Harness, Human 승인, 실행 환경이 각각 허용하는 범위의 교집합을 계산한 결과다.
어느 한 계층에서 금지한 행동은 다른 계층이 허용하더라도 capability에 포함하지 않는다.
role capabilities
∩ track scope
∩ repository capabilities
∩ environment permissions
∩ approval state
────────────────────────────
effective capabilities
예를 들어 Repository descriptor에 database-read capability가 있어도 현재 역할이 Architecture라면 실제 데이터 조회가 허용되지 않을 수 있다. 반대로 역할이 Release/Operations라도 Repository Harness가 direct-prod-db-write를 금지한다면 해당 행동은 capability에 포함되지 않는다.
Context Resolver의 판정 순서는 다음처럼 구성할 수 있다.
- 사용자 요청에 명시된 대상과 파일 경로를 확인한다.
- Git root와 worktree metadata로 실제 레포 경계를 확인한다.
- 활성 트랙이 참조하는 레포 목록과 비교한다.
- 하나의 레포 안에서 완결되면 repository 또는 git worktree로 분류한다.
- 둘 이상의 레포를 조율해야 하면 workspace로 분류한다.
- 외부 서비스나 프로덕션 시스템을 직접 대상으로 하면 external로 분류하고 승인 상태를 확인한다.
- 역할과 정책, 레포 규칙의 교집합으로 capability와 constraint를 계산한다.
판정이 불명확하면 쓰기 또는 실행 capability를 추정해서 추가하지 않는다. 읽기 가능한 metadata를 더 확인하거나, 작업을 제안 상태로 유지한 채 Human에게 대상 경계를 확인한다.
Context Descriptor는 이후 Repository Runtime Loader와 Worker Scheduler, Approval Manager가 같은 경계 판정을 공유하게 만드는 계약이다. 각 컴포넌트가 대상 레포와 권한을 제각각 다시 추론해서는 안 된다.
3.6 Workspace Runtime과 Track Registry
Track은 장기간 유지되는 작업 흐름의 단위다. 한 번의 채팅 세션이나 하나의 Worker 작업보다 오래 지속되지만, 프로젝트 전체보다는 좁은 작업 흐름이다.
예를 들면 다음과 같다.
- service-prod-launch
- agent-harness-architecture
- product-repo-observability
하나의 Track은 여러 Master 세션과 Worker lease를 거쳐 이어질 수 있다. 따라서 Track 상태가 특정 채팅 세션의 컨텍스트에만 존재해서는 안 된다.
Track Registry는 각 Track의 현재 상태와 관련 정본 포인터를 관리한다.
Track 상태
| 상태 | 의미 | 허용되는 행동 |
|---|---|---|
| proposed | Track 레코드는 생성됐지만 아직 실행이 승인되지 않음 | 범위·위험·대상 레포 정의, 승인 요청 (Human 승인 대기) |
| active | 현재 실행 가능한 상태 | Worker dispatch, 상태 갱신, 역할 연결 (dispatch, update, role binding) |
| blocked | 외부 조건이나 승인, 의존성을 기다리는 상태 | 원인 조사, 증거 수집, 문서화. 차단 조건을 우회하는 실행은 금지 (조사와 문서화만 가능) |
| parked | 의도적으로 중단했지만 폐기하지 않은 상태 | 상태와 정본 포인터 보존. 새 Worker dispatch 금지 (상태 보존, 새 실행 금지) |
| closing | 구현이 끝나 수락과 정리를 진행하는 상태 | 최종 검증, 미결 lease 회수, 영구 지식 승격 |
| closed | 완료되고 수락된 상태 | 이력 조회만 허용 |
| cancelled | 더 이상 진행하지 않기로 결정한 상태 | 취소 사유와 이력 조회만 허용 |
Master는 새로운 요청을 받아 proposed Track 레코드를 만들 수 있다. 그러나 실제 active 전환과 Worker dispatch는 Human 승인 또는 사전에 정의된 정책 조건을 충족해야 한다.
이렇게 하면 “Master가 Track을 개설한다”는 책임과 “승인되지 않은 작업을 실행하지 않는다”는 게이트 규칙이 충돌하지 않는다.
권장되는 기본 상태 전이는 다음과 같다.
proposed ──► active ──► closing ──► closed
│ │ │
│ │ ├────► blocked ─────► active
│ │ └────► parked ─────► active
│ │
└──────────► cancelled
│
blocked / parked ─────► cancelled
상태를 건너뛰는 전이는 별도 정책이 없으면 허용하지 않는다. 예를 들어 active Track을 검증 없이 곧바로 closed로 바꾸면 수락과 지식 승격 절차가 생략된다.
Track Registry 스키마
| 필드 | 설명 |
|---|---|
| track_id | 유일한 트랙 식별자 |
| title | 사람이 읽을 수 있는 이름 |
| status | 현재 Track 상태 |
| role_tag | 현재 연결된 역할 |
| repositories | 대상 레포 집합 |
| gate_state | 현재 승인 대기 또는 승인 상태 |
| planning_refs | 각 레포 planning 포인터 |
| work_ledger_refs | 관련 Work Ledger 이슈 목록 (관련 beads issue 목록) |
| latest_handoff | 현재 LIVE handoff 포인터 |
| active_leases | 아직 종료되지 않은 Worker lease 목록 |
| accepted_state | 마지막으로 수락된 결과 포인터 |
| open_questions | 아직 닫히지 않은 질문 |
| blockers | 현재 진행을 막는 조건 |
| resume_condition | blocked 또는 parked에서 복귀할 조건 |
| updated_at | 마지막 상태 변경 시각 |
accepted_state와 active_leases를 명시하면 “무엇이 완료됐는가”와 “무엇이 아직 실행 중인가”를 후임이 분리해서 확인할 수 있다.
Track parking은 취소가 아니다
Track을 파킹할 때는 단순히 _status: parked_만 기록해서는 안 된다.
최소한 다음 내용을 함께 남겨야 한다.
- 마지막으로 수락된 결과
- 제출됐지만 아직 수락되지 않은 결과
- 실행 중이거나 중단해야 하는 Worker lease
- 열린 질문과 blocker
- 현재 역할과 다음에 필요한 역할
- 관련 Git, planning, Work Ledger 포인터
- 다시 활성화할 정확한 조건
- 재개할 때 처음 수행할 검증
이 정보가 없으면 후임은 중단된 작업을 완료된 것으로 오인하거나, 이미 끝난 조사를 처음부터 반복할 수 있다.
Track 상태는 세션 밖에 영속돼야 한다. 현재 운영에서는 Work Ledger와 handoff, Git 포인터를 조합해 이 상태를 수동으로 관리한다. 참조 구현에서는 Workspace Runtime이 Track Registry의 일관된 상태 전이와 저장을 담당한다.
3.7 Role Runtime
Role은 Master가 현재 어떤 종류의 판단을 우선하고 어떤 행동을 제한받는지 나타낸다.
Track이 무슨 작업을 이어가고 있는가를 나타낸다면, Role은 현재 어떤 책임과 판단 기준으로 그 작업을 처리하는가를 나타낸다.
예를 들어 Architecture 역할에서는 설계와 인터페이스 정의를 수행하지만 실제 파일 변경이나 배포를 하지 않는다.
Release/Operations 역할에서는 동결된 설계를 다시 해석하지 않고 배포 준비, 검증, 운영 절차를 집행한다.
현재 운영 중인 헌장은 역할을 일곱 개로 나누었다.
| 역할 | 주요 책임 | 금지되는 대표 행동 |
|---|---|---|
| Architecture | 책임 경계, 소유권, 인터페이스, ADR 설계 | 역할 전환 없이 제품 코드 구현이나 배포 수행 |
| Research | 증거 수집, 가설 검증, 원인과 선택지 조사 | 조사 결과를 근거 없이 확정하거나 프로덕션 변경 수행 |
| Reference Implementation | 동결된 설계를 타입과 인터페이스, 코드로 변환 | 새로운 철학이나 Runtime 책임 추가 |
| Feature Implementation | 승인된 제품 기능 구현과 검증 | 설계 재해석, lease 밖 스코프 확대 |
| Release / Operations | 배포 준비와 조율, 환경 검증, runbook 집행 | 릴리즈 중 임의로 아키텍처 변경 |
| Incident Response | 장애 범위 축소, 증거 수집, 완화와 복구 | 증거와 승인 없이 광범위한 수정 수행 |
| Maintenance | 저위험 정비, 의존성 및 문서 관리 | 정비를 명목으로 기능이나 책임 추가 |
역할 집합 자체는 조직마다 다르게 정의할 수 있다. 실제 업무와 위험 모델에 따라 역할을 합치거나 나눌 수 있다.
중점은 Master 세션에서는 한 번에 역할 하나만 활성화하고, 역할 전환은 명시적인 상태 전이로 처리한다는 것이다.
Role State
| 필드 | 설명 |
|---|---|
| current_role | 현재 활성 역할 |
| lock_state | 역할이 잠겨 있는지 여부 |
| locked_by | Human, Charter, Track 중 잠금 주체 |
| started_at | 현재 역할을 시작한 시각 |
| completion_criteria | 역할을 완료했다고 판정할 조건 |
| allowed_actions | 역할에서 허용되는 행동 범위 |
| prohibited_actions | 역할 중 금지되는 행동 |
| return_role | 임시 역할이 끝난 뒤 복귀할 역할 |
| track_binding | 현재 역할과 연결된 Track |
| handoff_ref | 이전 역할의 완료 또는 파킹 기록 |
역할의 allowed_actions가 Repository Harness나 approval state보다 우선하는 것은 아니다. 실제 capability는 Role State와 Track scope, Repository descriptor, approval state의 교집합으로 계산한다.
역할 전환 흐름은 다음과 같다.
Current Role
│
▼
Receive New Task
│
▼
Does Task Belong to Current Role?
┌─┴───────────────┐
Yes No
│ │
▼ ▼
Continue Complete or Park Current Role
│
▼
Write Role Handoff
│
▼
Request or Verify Unlock
│
▼
Switch Role
│
▼
Recompute Capabilities
현재 역할과 맞지 않는 요청이라면 다음 순서를 따른다.
- 현재 역할의 완료 조건을 충족했는지 확인한다.
- 완료할 수 없다면 현재 상태를 파킹한다.
- 수락된 결과와 미수락 결과, 열린 질문, blocker를 역할 handoff에 기록한다.
- 역할 잠금의 주체와 unlock 조건을 확인한다.
- 필요한 승인을 받은 뒤 current_role을 변경한다.
- 새 역할과 Track, Repository 규칙을 기준으로 capability를 다시 계산한다.
역할 전환이 발생해도 Track이 반드시 바뀌는 것은 아니다. 같은 Track 안에서 Research를 마친 뒤 Feature Implementation으로 이동할 수 있다.
반대로 Track을 전환하면서 같은 역할을 유지할 수도 있다. 예를 들어 Release/Operations 역할로 한 제품의 배포 Track을 파킹하고 다른 제품의 배포 Track으로 이동할 수 있다.
현재는 Role State와 헌장, handoff를 읽어 이 절차를 수동으로 집행한다. 참조 구현의 Role Runtime은 다음 위반을 차단해야 한다.
- 동시에 두 역할이 active가 되는 상태
- 잠긴 역할을 승인 없이 변경하는 전이
- 기존 역할을 완료하거나 파킹하지 않은 전환
- 새 역할에서 금지된 capability의 실행
- 임시 역할 종료 후 return_role과 복귀 조건이 유실되는 상태
3.8 Repository Harness
Repository Harness는 레포마다 붙는 운영 계약이다. AHE 전체와 같은 뜻은 아니며, AHE 원칙을 개별 레포에 적용하는 경계다.
Master가 특정 레포에서 작업하려면 해당 Repository Harness가 제공하는 인터페이스를 통해 지식과 실행 능력, 검증 방법을 확인해야 한다.
| 인터페이스 | 책임 | Master 사용 방식 |
|---|---|---|
| repo.KnowledgeStore | wiki, ADR, postmortem의 정본 제공 | 검색하거나 경로 포인터를 보유 |
| repo.Rules | 머지, 브랜치, 코딩, 보안 규칙 | Worker 브리핑에 필요한 부분만 주입 |
| repo.Planning | 현재 페이즈와 실행 계획 | Track과 연결해 상태 참조 |
| repo.Interceptor | hooks와 정책 강제 | 존재 여부와 capability 확인 |
| repo.Memory | 레포 범위 포인터 검색 | 전문 복사 없이 검색 위임 |
| repo.Runbooks | 배포, 복구, 운영 절차 | 실행 전 해당 절차 조회 |
| repo.Skills | 레포 특화 작업 방법 | Worker profile에 지정 |
| repo.Workers | 허용된 실행 진입점 | Scheduler를 통해 호출 |
| repo.Verification | 빌드, 테스트, lint, 프로브 | 결과를 수락 증거로 사용 |
repo.Memory는 Repository Harness가 장문의 별도 기억을 소유한다는 뜻이 아니다. 레포 내부의 정본을 빠르게 찾기 위한 검색 포인터 계층이다.
각 레포는 최소한 다음과 같은 descriptor를 제공하는 편이 좋다.
repository:
id: product-repo
root: /workspace/product-repo
knowledge_root: docs/wiki
planning_root: .planning
rules:
- AGENTS.md
- docs/wiki/guides/development.md
verification:
unit_test: "pnpm test"
lint: "pnpm run lint"
build: "pnpm run build"
capabilities:
- backend
- database-read
- docker
prohibited:
- direct-prod-db-write
descriptor는 해당 레포 안에서 버전 관리해야 한다. Master의 Workspace Memory에 복사본을 만들어 별도로 관리하면 Repository Harness와 Master 중 어느 쪽이 최신인지 다시 판별해야 한다.
Master는 descriptor를 통해 다음 내용을 확인한다.
- 이 레포의 정본 지식은 어디에 있는가
- 현재 계획은 어디에서 읽는가
- 어떤 규칙을 먼저 적용해야 하는가
- 어떤 검증 명령을 실행해야 하는가
- 어떤 capability를 제공하며 무엇을 금지하는가
descriptor에 적힌 경로와 실제 레포 상태가 일치하지 않으면 조용히 추정하지 않는다. Repository Drift로 경고하고, 잘못된 경로가 수락 증거로 사용되지 않게 해야 한다.
Repository Runtime Loader는 시작할 때 모든 레포의 descriptor와 wiki를 읽지 않는다. Context Resolver가 대상 레포를 확정한 뒤 해당 Repository Harness만 적재한다.
3.9 Worker Scheduler와 Lease
어떤 작업을 어떤 모델에 맡길지, 어느 worktree에서 실행할지, 어디까지 변경할 수 있는지, 시간과 토큰을 얼마만큼 허용할지, 어떤 증거를 제출해야 하는지, 어떤 결과를 제출해야 하는지를 하나의 lease로 묶는다.
Worker Lease 스키마
| 필드 | 설명 |
|---|---|
| lease_id | 변경되지 않는 위임 식별자 |
| track_id | 소속 Track |
| task_id | Work Ledger 이슈 또는 내부 태스크 |
| repository_id | 대상 레포 |
| worktree_path | 격리된 작업 경로 |
| worker_profile | 모델, effort, skill, 실행 방식 |
| scope | 허용된 파일과 작업 범위 |
| constraints | 금지 행동과 안전 규칙 |
| context_refs | 필요한 정본 문서 포인터 |
| expected_artifacts | 제출해야 할 파일과 산출물 |
| verification_plan | 실행해야 할 test, lint, build, probe |
| budget | 토큰, 시간, 재시도 제한 |
| expires_at | lease 만료 시각 |
| status | 현재 lease 상태 |
| side_effect_policy | 외부 부수효과 허용 범위 |
권장 상태 전이는 다음과 같다.
issued
│
▼
running
│
├────────► failed ────────┐
├────────► expired ───────┤
├────────► cancelled ─────┤
│ │
▼ │
submitted │
│ │
├─ changes requested ─► running
│
▼
accepted │
│ │
└──────────────┬──────────┘
▼
reaped
accepted 상태는 Worker가 설정할 수 없다. Worker는 submitted까지만 전이할 수 있고, 별도의 수락 주체가 evidence bundle을 검토한 뒤 accepted를 결정한다.
reaped는 작업이 성공했다는 뜻이 아니다. Worker 프로세스와 임시 자원, worktree에 대한 lease가 회수됐다는 뜻이다. 실패하거나 만료된 lease도 조사와 증거 보존이 끝나면 reap할 수 있다.
위임 흐름은 다음과 같다.
Master
│
│ create task envelope
▼
Worker Scheduler
│
├─ resolve repository
├─ validate role and capabilities
├─ allocate isolated worktree
├─ attach scoped context
├─ set budget and expiry
└─ issue lease
│
▼
Worker
│
├─ inspect
├─ implement
├─ self-check
└─ submit artifacts and evidence
Worker는 lease에 포함된 범위 안에서만 작업한다.
범위 밖의 변경이 필요하다고 판단하면 임의로 lease를 확대하지 않는다. 예를 들어 백엔드 태스크를 수행하던 중 프론트엔드 계약 변경이 필요해졌다면, 프론트엔드 레포를 직접 수정하지 않고 다음 정보를 담은 change proposal을 Master에게 제출한다.
- 추가로 변경해야 하는 대상
- 현재 lease만으로 해결할 수 없는 이유
- 예상 영향 범위
- 필요한 레포와 capability
- 기존 검증 계획에 추가해야 할 항목
Master는 이를 바탕으로 기존 lease를 수정할지, 별도의 Worker를 만들지, 크로스레포 Track으로 전환할지 결정한다.
Scheduler는 예산도 강제해야 한다. 토큰이나 실행 시간, 재시도 횟수가 한도를 넘으면 Worker의 자기 판단으로 계속 실행하지 않는다. 현재 상태와 artifact를 보존한 뒤 중단하거나 새로운 승인을 요청한다.
3.10 Approval Manager와 Gate Model
자동화와 통제 사이의 기준을 게이트로 정한다.
모든 행동에 Human 승인을 요구하면 자동화의 이점이 사라진다. 반대로 모든 행동을 자동 허용하면 권한 경계가 사라진다. (통제가 힘들어진다)
따라서 행동의 실제 효과와 가역성에 따라 승인 수준을 나눈다.
| Gate | 성격 | 예시 | 승인 방식 |
|---|---|---|---|
| G0 | read-only, 부수효과 없음 | 파일 읽기, Git log, 테스트 목록 조회 | 자동 허용 |
| G1 | 로컬이며 가역적인 변경 | worktree 코드 수정, 로컬 테스트, 정책이 허용한 로컬 commit | 역할·레포 정책 안에서 자동 허용 |
| G2 | 공유 상태 변경 | 원격 branch push, MR 생성, 공유 artifact 게시, 이슈 상태 변경, 이슈 트래커 상태 변경 | 조건부 승인 또는 사전 위임 |
| G3 | 프로덕션·외부·비가역적 영향 | 배포, 프로덕션 DB write, 외부 메시지 발송, 프로덕션 권한 사용, 자격증명 사용 | Human의 명시적 승인 필수 |
Gate 분류에는 단순 명령 이름보다 실제 효과를 기준으로 삼아야 한다.
예를 들어 격리된 worktree 안의 로컬 commit은 외부 상태를 바꾸지 않으므로 정책에 따라 G1일 수 있다. 같은 commit을 원격 branch에 push하면 공유 상태가 바뀌므로 G2다.
SQL 파일을 작성하는 것은 G1일 수 있지만, 프로덕션 데이터베이스에서 실행하는 것은 G3다. 배포 계획을 작성하는 것은 G0 또는 G1일 수 있지만 실제 배포를 실행하면 G3다.
Gate가 낮다고 해서 현재 역할에서 금지된 행동이 허용되는 것도 아니다. 행동을 실행하려면 다음 조건을 모두 만족해야 한다.
Role permits action
∩ Track scope includes target
∩ Repository permits capability
∩ Gate approval is valid
──────────────────────────────
Action may execute
Approval Proposal에는 다음 정보가 들어가야 한다.
| 필드 | 설명 |
|---|---|
| proposal_id | 승인 제안 식별자 |
| action | 실행하려는 구체적인 행동 |
| gate | G0~G3 분류 |
| reason | 행동이 필요한 이유 |
| target | 영향받는 시스템과 범위 |
| reversibility | 되돌릴 수 있는지와 그 조건 |
| evidence | 현재까지 확보한 검증 결과 |
| diff_or_plan | 실제로 적용할 변경 또는 실행 계획 |
| risk | 실패했을 때의 영향 |
| rollback | 복구 또는 완화 계획 |
| requested_by | Master 또는 Worker |
| expires_at | 승인이 더 이상 유효하지 않은 시각 |
| decision | pending, approved, rejected, expired |
| decision_by | 승인 또는 거절 주체 |
승인은 대상과 범위가 명확해야 한다. “배포 승인”처럼 넓은 문장 하나로 이후의 모든 배포를 허용해서는 안 된다. 승인된 diff나 version, 환경, 실행 시각이 달라지면 기존 승인을 재사용하지 않고 다시 판정해야 한다.
Approval 상태는 다음처럼 관리한다.
pending
├─ approved
├─ rejected
├─ expired
└─ cancelled
approved
├─ executed
└─ expired-before-execution
승인 뒤 대상 revision이나 배포 artifact가 바뀌면 기존 승인을 재사용하지 않는다. 변경된 증거를 포함해 새 Proposal을 만든다.
현재 운영에서는 Master가 게이트를 분류하고 Human이 채팅에서 승인한다. 목표 구현에서는 이 상태와 만료 조건을 Approval Manager가 코드로 강제한다.
Approval Manager는 분류와 상태 관리를 자동화하지만, G3에 대한 Human의 최종 권한을 대신하지 않는다.
(현재까지는 사람이 이 Gate Model을 문서로 읽고 수동으로 집행한다.)
3.11 Evidence와 Acceptance
Acceptance는 Worker의 완료 응답 문구를 신뢰하지 않는다.
Worker의 출력은 자연어 보고가 아니라 Evidence Bundle로 제출한다.
그때 제출된 정량적인 evidence bundle을 대상으로 한다.
이때 증거마다 증명할 수 있는 범위가 다르다. 따라서 단순히 “신뢰 수준이 높다”라고 분류하기보다 무엇을 증명하며 무엇을 증명하지 못하는지 구분해야 한다.
Evidence는 자신이 검증한 범위까지만 의미를 가진다.
- diff는 어떤 파일이 바뀌었는지를 보여준다.
- 테스트 성공은 해당 테스트가 다룬 범위가 통과했음을 보여준다.
- 로컬 프로브 성공은 프로덕션 동작을 증명하지 않는다.
- 빌드 성공은 배포 승인과 같지 않다.
- Worker의 완료 보고는 증거가 아니다.
Acceptance는 Evidence Bundle을 기준으로 별도로 기록한다.
| 증거 유형 | 증명할 수 있는 것 | 단독으로 증명하지 못하는 것 | 신뢰 수준 |
|---|---|---|---|
| Artifact | 파일이나 빌드 산출물이 존재한다 | 요구사항을 충족하거나 정상 동작한다 | 중간 |
| Diff | 기준점과 결과 사이에 어떤 변경이 생겼다 | 변경이 올바르거나 충분하다 | 높음 |
| Deterministic Test | 특정 코드와 환경에서 정의된 테스트가 통과했다 | 테스트하지 않은 범위와 실제 프로덕션 동작 | 높음 |
| Runtime Probe | 특정 시점에 관측한 endpoint, process, port 상태 | 장기 안정성과 모든 사용자 경로 | 높음 |
| Environment Evidence | 배포 version, image digest, 설정, 로그가 특정 상태다 | 해당 상태가 기능적으로 올바르다 | 높음 |
| Manual Observation | Human이 실제 UI나 외부 결과를 확인했다 | 재현 가능한 자동 검증과 내부 상태 전체 | 단독으로는 무효 |
| Self-report | Worker가 무엇을 주장하는지 기록한다 | 주장의 사실 여부 | 조건부 높음 |
테스트가 통과했다는 사실은 해당 테스트가 다룬 범위만 증명한다. 잘못된 환경에서 실행한 테스트나 변경과 무관한 테스트는 수락 증거가 될 수 없다.
Evidence Bundle은 증거의 원본을 추적할 수 있어야 한다.
task: EX-142-report-api
lease_id: lease-ex-142-01
artifacts:
- path: src/reports/report.controller.ts
diff:
base: dev
head: worker/ex-142-report-api
ref: evidence/diff-ex-142.patch
verification:
- command: "npm test -- reports"
exit_code: 0
result: "26 passed"
evidence_ref: evidence/test-reports.log
- command: "npm run build"
exit_code: 0
result: "success"
evidence_ref: evidence/build.log
probes:
- target: "GET /api/reports/summary"
observed_status: 200
evidence_ref: evidence/report-summary-probe.json
known_gaps:
- "prod auth integration not tested"
worker_claim:
status: complete
acceptance:
status: pending
decided_by: null
_result: "26 passed"_라는 문자열만 저장해서는 Worker 자기 보고와 크게 다르지 않다.
가능하면 원본 로그와 실행 시각, exit code, 대상 commit을 함께 연결해야 한다.
수락자는 evidence bundle을 다음 기준으로 검토한다.
- 제출된 artifact와 diff가 lease 범위에 들어가는가
- 예상하지 않은 파일이나 다른 레포가 변경되지 않았는가
- verification plan의 필수 항목이 실제로 실행됐는가
- 테스트와 프로브가 대상 diff를 검증하는가
- 알려진 미검증 범위가 명시됐는가
- 행동의 Gate와 approval state가 유효한가
- 결과가 Track의 completion criteria를 충족하는가
Acceptance 결과는 다음 중 하나다.
| 상태 | 의미 |
|---|---|
| pending | 아직 검토하지 않음 |
| accepted | 정의된 수락 조건과 필요한 증거를 충족함 |
| changes_requested | 결과 일부를 수정하거나 증거를 보완해야 함 |
| rejected | 범위 또는 요구사항을 충족하지 못해 현재 결과를 수락하지 않음 |
| needs_human_verification | 자동 증거만으로 판정할 수 없어 Human의 확인 없이는 결정할 수 없음 |
Worker의 status: complete는 Acceptance 결과가 아니다. Worker가 자신의 작업이 끝났다고 판단했다는 메타데이터일 뿐이다. 최종 상태는 별도의 수락 주체가 증거를 검토한 뒤 기록한다.
수락자는 다음 순서로 검토한다.
- Evidence Bundle이 현재 lease와 같은 task·revision을 가리키는지 확인한다.
- 변경 파일이 writable scope 안에 있는지 확인한다.
- 필수 검증 명령과 결과가 존재하는지 확인한다.
- 실패와 미실행 항목이 숨겨져 있지 않은지 확인한다.
- 위험도에 비례해 중요한 검증을 다시 실행한다.
- known gap이 완료 조건과 충돌하는지 판정한다.
- 필요한 Approval이 유효한지 확인한다.
Evidence Bundle이 완전해 보여도 기준 revision이 다르면 수락하지 않는다. 승인 후 코드가 바뀌었거나 테스트 로그가 다른 commit을 가리키는 경우도 마찬가지다.
Acceptance가 끝난 뒤에만 Work Ledger의 최종 상태를 갱신하고 lease를 accepted 또는 closed로 전환한다.
3.12 Recovery Manager
Recovery Manager는 세션이 보이지 않거나 응답하지 않을 때 기존 실행을 다시 사용할 수 있는지 판정한다.
화면에서 세션이 사라졌다는 이유만으로 새 Master를 만들지 않는다.
복구 검사는 부수효과가 없는 read-only probe부터 시작한다.
먼저 복구 계층을 순서대로 검사한다.
| 단계 | 검사 대상 | 확인할 내용 | 성공 시 행동 | 실패 시 다음 단계 |
|---|---|---|---|---|
| R0 | 클라이언트 연결 | 기존 터미널과 세션이 UI에 연결돼 있는가 | 기존 세션 계속 사용 | R1 |
| R1 | Orca ADE runtime 상태 | runtime이 응답하며 기존 terminal handle을 찾을 수 있는가 | 클라이언트 재연결 | R2 |
| R2 | daemon과 PTY | daemon이 살아 있고 기존 PTY를 소유하는가 | 기존 PTY에 재부착 | R3 |
| R3 | 에이전트 프로세스 | 대상 session ID와 연결된 프로세스가 실행 중인가 | 기존 프로세스에 연결 복구 | R4 |
| R4 | 세션 저장 상태 | 실행 프로세스는 없지만 저장된 세션을 안전하게 resume할 수 있는가 | 잠금 확인 후 한 번만 resume | R5 |
| R5 | 최신 LIVE handoff | 전임은 없지만 후임을 만들 만큼 상태가 남아 있는가 | 새 successor session 생성 | R6 |
| R6 | Work Ledger와 Git | handoff도 불완전할 때 최소 상태를 재구성할 수 있는가 | 최소 상태 복구 후 Human 확인 | Human 개입 |
복구 흐름은 다음과 같다.
Session Appears Missing
│
▼
Check Client and Runtime
│
├─ connected ───────────────► Continue Existing Session
│
▼
Check daemon and PTY
│
├─ alive ───────────────────► Reattach Existing PTY
│
▼
Check Agent PID and Session Identity
│
├─ alive ───────────────────► Recover Existing Connection
│
▼
Check Session Persistence and Resume Lock
│
├─ safe to resume ──────────► Resume Once
│
▼
Load LIVE Handoff
│
├─ sufficient ──────────────► Spawn Successor
│
▼
Reconstruct from Work Ledger and Git
│
▼
Require Human Verification
동일 세션은 한 번만 resume한다
동일한 session ID에 대한 resume 시도는 원자적인 잠금으로 보호해야 한다.
최소한 다음 상태를 기록해야 한다.
- 대상 session ID
- 기존 PID와 PTY
- resume을 시도한 주체
- resume 시도 시각
- 성공 또는 실패 결과
- 새로 생성된 PID
- 사용한 세션 저장 경로
이미 다른 프로세스가 같은 session ID를 사용 중이거나, 실행 여부를 확정할 수 없다면 추가 resume을 금지한다. 불확실한 상태에서 새 실행을 만드는 것보다 Human (Dorito, 개발자)에게 상태를 올리는 편이 안전하다.
프로세스 식별에는 외부 증거가 필요하다
프로세스 이름에 claude나 codex가 포함돼 있다는 이유만으로 대상 세션이라고 판단해서는 안 된다.
PID와 parent PID, 커맨드라인, PTY, cwd, session ID, 세션 저장 경로를 함께 대조해야 한다. 프로세스를 종료할 때도 같은 증거로 대상을 확정한 뒤 해당 PID만 종료한다.
이 규칙은 여러 에이전트 세션이 동시에 실행되는 환경에서 특히 중요하다. 이름만 보고 프로세스를 정리하면 정상 동작 중인 다른 Worker나 Master를 종료할 수 있다.
Recovery 결과는 다음 중 하나로 기록한다.
| 결과 | 의미 |
|---|---|
| reattached | 기존 PTY 또는 실행 프로세스에 다시 연결함 |
| resumed | 기존 실행이 없음을 확인하고 저장된 동일 세션을 한 번 resume함 |
| successor_spawned | 기존 identity를 복구하지 않고 handoff로 후임을 생성함 |
| reconstructed | Work Ledger와 Git에서 최소 상태를 재구성함 |
| human_required | 중복 실행 가능성이나 상태 손실 때문에 자동 복구를 중단함 |
3.13 Succession Manager
Succession (승계 절차)은 현재 Master가 완전히 죽은 뒤에만 수행되는 장애 복구에 한정되지 않는다.

전임이 아직 작업 상태를 정리할 수 있을 때 변경 가능한 작업을 동결하고, 후임에게 역할과 Track을 넘기는 계획된 수명주기다.
승계 trigger를 Immediate와 Advisory로 나눈다.
| 종류 | 조건 | 동작 |
|---|---|---|
| Immediate | 사용자가 “승계해줘”, “다음 Master로 넘기자”처럼 명시적으로 지시함 | 재확인 없이 승계 절차를 시작 |
| Advisory | 컨텍스트 한계 접근, 자연 마일스톤, 장시간 상주로 인한 상태 비대, 복구 비용 증가 | 자동 승계는 금지. "승계 임계점에 도달했습니다. 현재 역할과 트랙을 유지한 채 다음 Master로 승계할까요?"라고 제안만 한다. |
컨텍스트 사용량을 정확히 측정할 수 없다면 정확한 수치처럼 말하지 않는다. UI 표시나 관찰 가능한 근사치를 사용했다면 추정값임을 명시한다.
여기에 설계 확장으로 Scheduled(릴리즈 전후, 근무 교대, 장기 트랙 경계 같은 예정된 시점의 승계)를 추가할 수 있다. 프로세스 종료나 런타임 장애처럼 전임이 handoff를 남길 수 없는 상황은 승계가 아니라 Recovery Manager의 소관이다.
릴리즈 전후나 근무 교대처럼 예정된 시점에 자동으로 승계하는 Scheduled trigger는 현재 동결된 계약에 포함돼 있지 않다. 이를 추가하려면 구현 문서에 바로 넣지 않고 Architecture ADR과 Human 승인을 거쳐야 한다.
Thin Handoff 필드
| 항목 | 내용 |
|---|---|
| Identity | 전임 session ID, 세대, 현재 역할과 Track |
| Objective | 현재 목표와 완료 조건 |
| Accepted State | 이미 수락된 결과와 증거 포인터 |
| Unaccepted State | 제출됐지만 아직 수락되지 않은 결과 |
| Active Leases | 실행 중인 Worker lease와 실제 상태 |
| Open Questions | 아직 결정되지 않은 질문 |
| Blockers | 외부 대기 조건과 승인 대기 |
| Canonical References | Git, planning, Work Ledger 포인터 |
| Recovery Notes | 정확한 재개 위치와 첫 검증 행동 |
| Prohibited Assumptions | 후임이 사실로 단정하면 안 되는 내용 |
| Verification Challenge | 후임이 정본을 읽고 상태를 복구했는지 확인할 질문 |
thin handoff에는 대화 전문이나 과거 추론 전체를 복사하지 않는다. 현재 상태를 복구하는 데 필요한 정보와 정본 포인터만 기록한다.
Predecessor
│
├─ freeze mutable work
├─ stop new dispatch
├─ collect accepted and unaccepted state
├─ record active leases and blockers
└─ write thin handoff
│
▼
Successor
│
├─ load Charter
├─ read LIVE handoff
├─ inspect Work Ledger and Git
├─ remeasure runtime baseline
└─ answer verification challenge
│
┌─────────┴─────────┐
PASS FAIL
│ │
▼ ▼
Record lineage Keep predecessor frozen
Retire predecessor or request Human recovery
또한 후임 검증은 단순히 "handoff를 읽었습니다"라는 응답으로 끝내지 않는다.
후임이 현재 역할, 활성 트랙, 마지막 수락 산출물, 다음 허용 행동, 금지 행동을 재진술하게 하고, 정본 포인터를 실제로 읽었는지 확인한다.
후임 검증이 끝날 때까지 전임은 살아 있을 수 있지만 변경 가능한 작업을 수행하지 않는다. 두 Master가 동시에 파일을 수정하거나 Worker를 dispatch하지 않도록 전임을 frozen 상태로 유지한다.
모니터링(별도로 띄우고 하위 레포지토리의 변화를 감지하는 하위 shell)은 상속하지 않는다
승계에서 전임이 실행하던 감시 장치(모니터링, probe)는 상속하지 않는다는 규칙도 중요하다. 후임이 그대로 물려받지 않는다. 전임이 돌리던 모니터와 프로브는 후임이 물려받지 않고, 기준선을 직접 실측한 뒤 자기 세션 소유로 재무장한다.
다시 말해서, 후임은 현재 Git HEAD와 프로세스, 포트, heartbeat 경로를 직접 측정한 뒤 자신의 session ID와 경로를 소유자로 지정해 모니터를 다시 실행한다.
전임의 orphan 프로세스는 경로와 커맨드라인을 대조해 그것만 정리한다.
소유자가 불명확한 모니터는 정상처럼 보여도 후임의 관측값으로 사용하지 않는다. 상속받은 모니터는 어느 세션 소유인지 불명확해지고, 죽어도 아무도 모르는 감시가 되기 때문이다.
3.14 Lineage Recorder (마스터 에이전트의 승계 족보)
Lineage는 승계의 감사 로그다. 다음 세션이 과거 계보를 읽고 판단을 바꾸는 용도보다, 운영자가 승계의 연속성과 실패를 조사할 때 쓰는 audit 기록이다.
후임 Master의 복구 입력은 Charter, LIVE handoff, Work Ledger와 Git이다. lineage 전체를 Bootstrap에 자동 주입하지 않는다.
현재 운영 중인 스키마는 13개 필수 필드를 가지도록 설계했다.
| 필드 | 설명 |
|---|---|
| generation | Master 세대 번호 |
| parent_session | 전임 session ID |
| successor_session | 후임 session ID |
| timestamp | 현재 스키마에서 승계 지시 시각과 전임 종료 확인 시각을 함께 기록 |
| inherited_role | 후임이 상속한 역할. 승계 자체는 역할을 바꾸지 않음 |
| succession_reason | 승계 사유 |
| recovery_sources | 후임이 실제로 읽거나 조회한 복구 소스 |
| inherited_open_tracks | 상속한 열린 Track의 수와 식별자 |
| verification | PASS, PARTIAL, FAILED |
| repeated_question_count | 이미 정본이나 handoff에 답이 있던 질문을 다시 한 횟수 |
| reopened_decision_count | 새로운 근거 없이 이미 확정된 결정을 다시 연 횟수 |
| context_loss_summary | 유실된 컨텍스트와 영향. 없으면 “없음 확인” |
| predecessor_retirement_verified | 후임이 전임 종료를 외부 증거로 확인했는가 |
마지막 네 필드는 서로 다른 항목을 측정한다.
- repeated_question_count: 필요한 정보에 접근할 수 있었는가
- reopened_decision_count: 결정과 근거가 정본에 남아 있었는가
- context_loss_summary: 실제로 무엇이 유실됐는가
- predecessor_retirement_verified: 중복 Master가 남지 않았는가
재질문 0회는 좋은 신호지만 handoff가 완전하다는 단독 증거는 아니다. 후임이 누락 사실을 인지하지 못한 채 질문하지 않았을 수도 있기 때문이다. Git 기준선, 실행 상태와 Verification Challenge를 함께 확인해야 한다.
새로운 증거나 요구사항 변경 때문에 결정을 의도적으로 재검토한 경우는 reopened_decision_count에 포함하지 않는다.
이 항목들은 승계 품질을 “잘 된 것 같다”는 인상이 아니라 관측 가능한 값으로 남긴다. 그 결과를 바탕으로 다음 handoff와 승계 절차를 개선할 수 있다.
이 지표는 정해진 관찰 구간과 판정 기준을 사용해 계산해야 한다. 세션 자신의 평가가 아니라 실제 대화 이력과 정본 변경, Human 검수를 근거로 삼는다.
Lineage는 append-only로 기록한다
type: correction
correction_of: lineage-gen-3
reason: "predecessor retirement timestamp was recorded incorrectly"
corrected_value:
predecessor_retired_at: "2026-07-17T14:32:10+09:00"
recorded_at: "2026-07-17T15:04:22+09:00"
기존 항목이 잘못됐더라도 원문을 수정하지 않고, 대상 항목을 가리키는 correction entry를 새로 추가한다.
missing artifact, stale handoff, 중복 지식, 재질문, 근거 없는 결정 재개봉, 역할 오류, 컨텍스트 유실 같은 감점 사유도 그대로 남긴다.
장부(족보)의 가치는 실제로 발생한 일을 투명하게 추적할 수 있게 만드는 것이다.
현재 timestamp 필드는 두 시각을 표현하고 있다. 향후 다음 두 필드로 분리할 예정이다. (이 변경이 적용되면 전체 스키마는 13개가 아니라 14개 필드가 된다.)
- succession_requested_at: 승계가 지시되거나 시작된 시각
- predecessor_retired_at: 전임 종료를 확인한 시각
3.15 Observability (정량적 지표로 계산)
에이전트 하네스의 Observability는 자연어 대화를 평가하는 기능이 아니다.
실행 상태와 정책 준수 여부를 외부 정량적인 증거로 관측하고, 정의된 기준선에서 벗어났을 때 경고한다.
| 관측 영역 | 대표 지표와 프로브 |
|---|---|
| Master Health | session 응답성, 현재 역할, 역할 잠금 활성화 상태, 컨텍스트 사용량 또는 명시된 추정치 |
| Worker Health | lease status, PID, worktree 존재 여부, 실행 시간, budget |
| Succession | 후임 검증 성공률, 중복 session 여부, 승계 소요 시간, 전임 은퇴 확인 |
| Knowledge Integrity | 중복 정본, 허용되지 않은 문서 위치, stale pointer |
| Approval | pending proposal, 만료된 승인, G3 우회 시도 |
| Repository Drift | descriptor와 실제 경로 불일치, hook 비활성, 검증 명령 누락 |
| Budget | 모델별 토큰, 활성 Worker 수, 실행 시간, 재시도 횟수 |
| Acceptance | 제출 대비 수락 결과, self-report 단독 완료 시도, 미검증 범위 |
| Runtime | Orca runtime, daemon, PTY 연결, stale terminal handle |
| Handoff | Track별 LIVE handoff 수, 필수 필드 누락, 오래된 handoff |
| Monitor Ownership | 모니터의 owner session, heartbeat 경로, orphan process |
관측값에는 소유자를 함께 기록한다.
probe:
id: "duplicate-master-check"
owner_session: "master-session-id"
target_track: "service-prod-launch"
measured_at: "..."
result: "pass"
소유자와 측정 시각이 없는 프로브 결과는 현재 기준선으로 사용하지 않는다.
예를 들면 다음과 같은 경보를 둘 수 있다.
| Alert | 조건 | 기본 대응 |
|---|---|---|
| Duplicate Master | 같은 session ID 또는 같은 track-role의 활성 Master가 둘 이상 | 변경 작업 즉시 freeze, Human 확인 |
| Untracked Knowledge | 관리 대상이지만 허용되지 않은 위치에 영구 문서 생성 | 쓰기 차단 또는 정본 위치 제안 |
| Memory Bloat | beads memory가 길이 제한을 넘거나 전문을 포함 | 포인터 캐시 규칙 위반으로 실패 |
| Stale Handoff | 한 Track에 LIVE handoff가 여러 개이거나 검증 기한 초과 | 새 실행 중단, 최신 상태 재판정 |
| Gate Bypass | G3 행동을 유효한 승인 없이 실행하려 함 | 즉시 차단하고 proposal 생성 |
| Orphan Lease | Worker가 종료됐지만 lease가 running | 실제 프로세스 확인 후 reap 또는 조사 |
| Architecture Drift | 동결 출처 없이 새 Unit이나 책임 등장 | 구현 중단, ADR 요구 |
| Context Overload | L0와 L1이 부팅 예산 초과 | 장문 제거, 포인터화, Bootstrap 실패 |
| Orphan Monitor | owner session이 종료됐는데 모니터가 계속 실행 | PID·경로 대조 후 해당 모니터만 종료 |
경보는 에이전트의 자연어 응답만으로 해제하지 않는다. 기준선을 다시 측정해 위반 상태가 실제로 사라졌다는 증거를 남겨야 한다.
3.16 Adapter Layer
Adapter Layer는 core가 특정 제품의 CLI와 파일 형식, 세션 모델에 직접 종속되지 않도록 결합을 격리한다.
| Adapter | 추상 책임 | 현재 후보 구현 | 주요 계약 |
|---|---|---|---|
| WorkLedgerAdapter | 이슈와 실행 상태 | beads | create, update, search, notes, ready |
| KnowledgeStoreAdapter | 정본과 변경 이력 | Git | read, search, append, history, supersede |
| ExecutionSubstrateAdapter | 격리 실행 환경과 PTY | Orca, tmux, Git worktree | allocate, attach, inspect, release |
| ExecutorAdapter | 모델 실행과 세션 제어 | Codex, Claude Code | run, resume, interrupt, artifact_refs |
| TraceArchiveAdapter | 과거 실행 조회 | ctx, JSONL archive | search, show, read |
| RepositoryAdapter | descriptor와 레포 검증 | Git CLI, custom scripts | resolve, rules, verification |
| ExternalLedgerAdapter | 외부 프로젝트 상태 | Jira 등 | push_status, link_issue |
| HumanInterfaceAdapter | 승인 요청과 결정 | Chat, CLI, 전용 approval UI | propose, approve, reject |
Core는 다음처럼 추상 계약만 호출한다.
scheduler.dispatch(task)
│
├─ WorkLedger.get(task_id)
├─ Repository.resolve(repo_id)
├─ ExecutionSubstrate.allocate(profile)
├─ Executor.run(envelope)
└─ KnowledgeStore.read(context_refs)
Orca 대신 tmux 또는 다른 실행 시스템으로 바꾸더라도 ExecutionSubstrateAdapter의 계약만 유지하면 Scheduler와 Recovery의 핵심 로직은 바뀌지 않아야 한다.
Adapter가 실패를 성공처럼 반환하거나 evidence reference 없이 결과 문자열만 넘기면 core는 수락 판단을 할 수 없다.
Adapter는 제품별 오류를 Core가 처리할 수 있는 공통 상태로 변환해야 한다.
product error
│
▼
not_found
unavailable
authentication_required
permission_denied
conflict
timeout
Adapter가 실패했을 때 다른 제품으로 fallback하지 않는다. 실행 결과와 증거의 출처가 바뀌기 때문이다.
대체 구현을 사용하려면 Master가 새 실행 환경과 capability를 확인하고 lease를 다시 발급한다.
Orca ADE 를 tmux로 교체하거나 beads를 다른 이슈 트래커로 바꾸더라도 Core의 상태 전이와 불변식이 유지돼야 한다.
이를 Adapter Substitution Test로 검증한다.
- 성공 또는 실패 상태
- 외부 부수효과 발생 여부
- 대상 resource와 identity
- 실행 시각과 duration
- 재시도 가능 여부
- artifact와 evidence reference
- 원본 도구 오류와 정규화된 오류 유형
이 대체 가능성은 문서 선언만으로 증명되지 않는다. mock adapter와 두 번째 실제 구현을 이용한 Adapter Substitution Test를 통과해야 한다. (코드로 구현해야 함)
3.17 지식 아키텍처
정보의 의미와 수명에 따라 저장 위치를 정한다.
지식 저장 위치는 도구 선호가 아니라 정보의 의미와 수명으로 정한다.
| 정보 유형 | 정본 | 수명 | 변경 방식 | 다른 위치의 표현 |
|---|---|---|---|---|
| 제품·코드 ADR | product-repo/docs/wiki/decisions | 장기 | Git commit 또는 PR | 짧은 요약과 포인터 |
| 제품 runbook | product-repo/docs/wiki/guides | 장기 | Git 변경 | 포인터 |
| 제품 postmortem | product-repo/docs/wiki/postmortems | 장기 | Git append | 포인터 |
| 하네스 ADR | planning-repo/docs/adr | 장기 | Git 변경 | 포인터 |
| 워크스페이스 운영 규칙 | planning-repo/docs/rules | 장기 | Human 승인 후 Git 변경 | L0 요약과 포인터 |
| 하네스 runbook | planning-repo/docs/runbooks | 장기 | Git 변경 | 포인터 |
| 하네스 postmortem | planning-repo/docs/postmortems | 장기 | Git append | 포인터 |
| 현재 이슈 상태 | beads issue | 작업 기간 | 상태와 notes 갱신 | Track에서 issue 포인터 참조 |
| 계획과 로드맵 | 각 레포의 .planning | 페이즈 또는 마일스톤 기간 | 해당 planning 절차 | Track에서 planning 포인터 참조 |
| 최신 handoff | planning-repo/docs/handoffs/.md | 다음 승계 또는 Track 종료까지 | 동일 Track 파일 갱신과 Git commit | Git 이력이 과거 상태 보존 |
| 검색 포인터 | beads memory | 재생성 가능 | 짧은 요약과 정본 경로 갱신 | 정본으로 사용하지 않음 |
| 과거 문서 아카이브 | Notion | 장기지만 stale 전제 | 갱신하지 않음 | 현재 정본으로 사용하지 않음 |
| 조사 중 메모 | scratchpad | 현재 세션 | 자유 기록 | 종료 전 승격 또는 폐기 |
| 승계 계보 | lineage ledger | 장기 감사 | append-only | 런타임 지식 입력 금지 |
경로는 실제 레포 구조에 맞게 조정할 수 있다. 중요한 것은 정보 유형마다 정본이 하나로 정해져 있다는 점이다.
새 정보의 저장 위치는 다음 의사결정 흐름을 따른다.
New Information
│
▼
현재 세션에서만 필요한가?
│
Yes ├──────────────► Scratchpad
│
No
▼
특정 이슈의 진행 과정인가?
│
Yes ├──────────────► Work Ledger Notes
│
No
▼
현재 Track을 재개하는 데 필요한가?
│
Yes ├──────────────► Latest LIVE Handoff
│
No
▼
장기간 보존할 지식인가?
│
├─ 제품·코드 지식 ──────► Repository Wiki
│
└─ 워크스페이스·하네스 ─► planning-repo/docs
│
└─ beads memory에 포인터 등록 (Register pointer)
같은 내용을 두 정본에 전문으로 저장하지 않는다. 두 번째 위치가 필요하다면 요약과 정본 경로만 기록한다.
한 정보가 여러 조건에 해당할 수도 있다.
예를 들어 작업 중 새로운 운영 제약을 발견했다면 현재 이슈의 notes에는 “운영 제약을 확인했고 정본으로 승격했다”는 진행 사실과 정본 링크를 남긴다. 제약의 전문은 해당 runbook이나 ADR에 한 번만 기록한다.
즉 Work Ledger에는 작업 과정과 포인터를 남기고, Git 정본에는 장기적으로 유효한 사실을 남긴다. 같은 내용을 양쪽에 전문으로 복제하지 않는다.
비밀정보와 인증정보는 이 분류와 별개로 다뤄야 한다. API 키, 토큰, 비밀번호 같은 값은 wiki, Work Ledger, handoff, lineage에 기록하지 않고 별도의 비밀 관리 시스템에 둔다. (gieleaks 추천)
3.18 beads issue와 beads memory의 분리
beads issue와 beads memory는 같은 도구가 제공하더라도 논리적 책임이 다르다.
beads issue는 실행 상태의 정본이고, beads memory는 정본을 찾기 위한 재생성 가능한 캐시다.
| 구분 | beads issue | beads memory |
|---|---|---|
| 목적 | 현재 해야 할 일과 진행 서사 관리 | 관련 정본을 빠르게 찾기 위한 검색·부팅 포인터 |
| 정본 여부 | 실행 상태의 정본 | 정본 아님 |
| 허용 내용 | 진행 결과, blocker, 승인 대기, 다음 행동 | 짧은 정책 요약, 검색 키, 정본 경로 |
| 내용 길이 | 이슈를 이해하고 재개할 만큼 허용 | 정해진 길이 제한 안에서 유지 |
| 변경 시점 | 작업이 진행될 때마다 | 정본 위치나 최소 정책이 변경될 때 |
| 종료 후 처리 | 이력으로 남기되 장기 지식은 별도 승격 | 필요하면 정본에서 재생성 |
| 금지 내용 | 장기 ADR이나 runbook의 전문 | postmortem, ADR, 긴 설계 설명의 전문 |
memory 항목은 가능한한 다음 형태를 따른다.
key: prod-db-write-policy
summary: "프로덕션 DB 직접 write 금지. 앱 엔드포인트 또는 Human 실행만 허용."
canonical_ref: "planning-repo/docs/rules/OPERATING-RULES.md#prod-db"
type: policy-pointer
verified_at: "2026-07-16"
각 필드의 역할은 다음과 같다.
- key는 검색과 중복 검사를 위한 안정적인 식별자다.
- summary는 세션 시작 시 위험 행동을 막기 위한 짧은 설명이다.
- canonical_ref는 규칙의 근거와 예외, 변경 이력이 있는 정본을 가리킨다.
- type은 이 항목이 정본이 아니라 포인터임을 명시한다.
- verified_at은 마지막으로 포인터의 유효성을 확인한 시각이다.
Memory Pointer Test는 최소한 다음을 검사해야 한다.
- canonical_ref가 존재하는가
- 참조 대상이 허용된 정본 경로 안에 있는가
- summary가 정해진 길이 제한을 넘지 않는가
- ADR이나 postmortem의 전문이 포함되지 않았는가
- 같은 key가 여러 정본을 가리키지 않는가
- verified_at 이후 참조 대상이 이동하거나 삭제되지 않았는가
이슈를 닫을 때도 장기 가치가 있는 내용을 issue notes에만 남겨서는 안 된다. 반복 가능한 해결책이나 운영 제약, 다른 결정의 근거가 되는 사실은 올바른 Git 정본으로 승격한 뒤 issue에는 해당 경로를 남긴다.
3.19 Notion의 역할: 강등의 기록
Notion은 이 설계 과정에서 두 차례에 걸쳐 역할이 축소됐다.
당시 Notion에는 프로젝트 Wiki가 남아 있었고, 사용자는 현재 구조를 설계하기 전에 그곳에 축적된 과거 현황과 레거시를 참고하라고 지시했다. 다만 과거 자료를 참고하는 것과 현재의 정본으로 사용하는 것은 구분했다.
7월 16일에는 Notion을 정본의 복제본이 아닌 사람용 인덱스로 제한했다. 정본 링크, 문서 상태, 마지막 검증일만 두고 설계 내용이나 운영 규칙의 전문은 Git 문서와 중복해서 관리하지 않는다는 결정이었다.
다음 날인 7월 17일에는 이 역할도 없앴다. 사람용 인덱스를 유지하려면 링크 갱신, 상태 확인, MCP 인증 관리 같은 작업이 계속 필요했다.
반면 현재 상태는 Git 정본과 Work Ledger에서 직접 확인할 수 있었고, 별도 인덱스가 제공하는 새로운 정보는 없었다.
따라서 Notion의 최종 역할은 다음과 같이 정리됐다.
| 항목 | 규칙 |
|---|---|
| 성격 | 갱신하지 않는 과거 문서 아카이브 |
| 읽기 | 허용하되 내용이 오래됐을 수 있다고 전제 |
| 쓰기 | 새 정보를 기록하거나 기존 내용을 갱신하지 않음 |
| 에이전트 취급 | 현재 정본으로 사용 금지. 충돌 시 Git과 Work Ledger 우선 |
| 사람용 현재 상태 | Notion 대신 Git 정본과 Work Ledger에서 직접 확인 |
| adapter 취급 | 승인 채널이나 외부 상태 동기화 대상으로 사용하지 않음 |
이 강등 과정에서 얻은 일반 원칙은 간단하다. 접근성을 위해 복제본을 늘리는 것보다, 정보 유형별 SSOT를 명확히 정해 정합성을 유지하는 편이 장기적으로 더 효율적이다.
3.20 Handoff의 저장과 갱신
같은 Track에 여러 LIVE handoff가 존재하면 후임은 무엇을 읽어야 하는지 다시 판단해야 한다.
따라서 목표 구조에서는 Track별 LIVE handoff를 한 건으로 제한한다.
planning-repo/
└── docs/
└── handoffs/
├── service-prod-launch.md
├── agent-harness-architecture.md
└── product-repo-observability.md
파일명은 승계 날짜가 아니라 Track 식별자를 기준으로 한다. handoff가 갱신될 때마다 새 파일을 만들지 않고 같은 Track 파일을 수정한 뒤 Git commit을 남긴다.
handoff의 상태는 다음과 같이 관리할 수 있다.
draft → LIVE → superseded
한 Track에서 LIVE 상태는 동시에 하나만 허용한다. draft는 아직 후임에게 전달할 수 없는 작성 중 상태이고, superseded는 더 이상 현재 복구에 사용하지 않는 과거 상태다.
handoff 갱신은 다음 순서로 진행한다.
- 현재 Track의 변경 작업을 동결한다.
- 마지막으로 수락된 결과와 아직 수락되지 않은 결과를 구분한다.
- 실행 중인 lease, 열린 질문, blocker, 정본 경로를 기록한다.
- 필수 필드와 정본 포인터를 검증한다.
- 기존 LIVE handoff를 같은 Track의 새 상태로 갱신한다.
- 변경 내용을 Git에 기록한다.
- 후임이 검증을 통과한 뒤에만 전임을 은퇴시킨다.
현재 운영은 아직 이 목표 구조로 완전히 전환되지 않았다. 지금은 승계마다 날짜가 포함된 handoff 파일이 생성되고, 과거 파일도 그대로 남아 있다. 단일 Master 환경에서는 가장 최근 파일을 LIVE로 간주할 수 있지만, 여러 Track과 Master가 동시에 움직이기 시작하면 이 규칙만으로는 부족하다.
기존 날짜 파일은 다음 절차로 마이그레이션할 수 있다.
- 기존 handoff 파일을 모두 조사한다.
- 각 파일을 해당 Track에 연결한다.
- 날짜만 보지 않고 Git 상태, Work Ledger, 실제 수락 결과를 대조한다.
- 확인된 최신 상태로 Track 기반 handoff를 만든다.
- 기존 파일은 과거 기록으로 표시하거나 Git 이력으로 보존한다.
- Track별 LIVE handoff가 하나인지 검사하는 프로브를 추가한다.
날짜가 가장 최근이라는 이유만으로 파일을 자동 승격하거나 기존 파일을 일괄 삭제해서는 안 된다. stale handoff가 더 최근 날짜를 가지고 있을 수도 있기 때문이다.
Lineage 역시 handoff를 대신하지 않는다. handoff는 작업을 재개하기 위한 현재 상태이고, lineage는 승계가 어떻게 수행됐는지 조사하기 위한 감사 기록이다.
3.21 Architecture Freeze와 변경 절차
Architecture Freeze는 설계 변경을 영구히 금지하는 역할이 아니다.
구현 과정에서 발생하는 세부 판단과 아키텍처 변경을 구분하는 장치다.
| 변경 유형 | 예시 | 처리 |
|---|---|---|
| 구현 세부 | 파일명, 내부 함수명, 동일 계약 안의 라이브러리 선택 | Implementation 역할에서 결정 |
| 계약 명확화 | 기존 필드의 타입과 오류 조건을 명시 | 동결된 책임을 유지하는 범위에서 수정 |
| 책임 이동 | Worker 책임을 Master로 이동 | Architecture ADR과 Human 승인 |
| 새 Runtime Unit | 별도 Policy Engine 추가 | Architecture 역할 전환과 ADR 필요 |
| 새 lifecycle trigger | Scheduled Succession 추가 | Architecture ADR과 Human 승인 |
| 불변식 변경 | Worker 자기 수락 허용 | Charter 또는 Architecture ADR 개정 |
| Adapter 교체 | Orca 대신 tmux 사용 | 기존 계약을 유지하면 구현 변경 |
| Adapter 계약 변경 | 새로운 core capability가 필요함 | Architecture 검토 필요 |
| 정본 이동 | planning-repo에서 별도 하네스 repo로 이전 | Migration ADR 필요 |
Reference Implementation의 각 Unit은 자신이 어떤 동결 문서에서 파생됐는지 기록해야 한다.
unit: succession-manager
derived_from:
- MASTER-CHARTER.md#succession
- SUCCESSION-PROTOCOL.md
architecture_revision: <commit-or-version>
구현 세부와 아키텍처 변경을 가르는 기준은 책임과 외부 계약이 바뀌는가다.
예를 들어 내부 함수명을 바꾸는 일은 구현 세부다. 반면 Recovery Manager가 맡던 session resume 권한을 Worker Scheduler로 옮기면 책임 경계가 바뀌므로 Architecture 변경이다.
Adapter 구현체를 교체하는 일도 기존 인터페이스로 충분하다면 구현 변경이다. 그러나 새 도구를 지원하려고 core에 새로운 상태와 책임을 추가해야 한다면 Architecture 검토가 필요하다.
변경 절차
아키텍처 변경이 필요할 때는 다음 절차를 따른다.
- 현재 구현에서 해결할 수 없는 문제와 증거를 기록한다.
- 변경이 구현 세부, 계약 명확화, 책임 변경 중 어디에 속하는지 분류한다.
- 책임이나 불변식이 바뀐다면 현재 역할을 완료하거나 파킹한다.
- Architecture 역할로 전환한다.
- 기존 동결 문서와 충돌 범위를 명시한 ADR을 작성한다.
- 영향받는 불변식과 인터페이스, migration, rollback을 정리한다.
- Human 승인을 받은 뒤 동결 기준 문서를 갱신한다.
- 새 기준선에서 Reference Implementation Plan을 수정한다.
- 이후에 구현 역할로 돌아간다.
Reference Implementation Plan의 각 Unit에는 자신이 어느 동결 문서에서 파생됐는지 기록해야 한다.
예를 들면 Master Charter, AHE Runtime, Boundary, Role State, Succession Protocol 같은 출처를 명시한다.
출처가 없는 새로운 책임이 나타나면 구현 편의로 처리하지 않고 architecture drift로 판정한다.
아키텍처 변경이 필요할 때는 다음 절차를 따른다.
- 동결 명세에 없는 새 Runtime Unit이 추가됐는가
- 기존 책임이 다른 컴포넌트로 이동했는가
- 불변식과 충돌하는 상태 전이가 추가됐는가
- 새 lifecycle trigger가 ADR 없이 추가됐는가
- 정본 위치가 migration 계획 없이 변경됐는가
- 구현 문서가 동결 출처를 참조하고 있는가
3.22 정상 작업의 전체 시퀀스
다음은 목표 아키텍처를 기준으로 한 단일 레포 작업의 전체 흐름이다.
(현재는 Master와 Human이 헌장 문서를 읽고 각 단계를 수동으로 집행한다. 이후 구현에서는 이 책임과 결과물의 연결을 런타임 컴포넌트로 자동화할 계획이다. 아마 python 으로 구현할듯)
| 단계 | 담당 | 작업 | 결과물 |
|---|---|---|---|
| 1 | Human | 작업과 제약 조건을 요청한다 | Task Request |
| 2 | Master | 현재 역할과 트랙을 확인하고 작업을 분류한다 | 작업 범위와 대상 트랙 |
| 3 | Context Resolver | 워크스페이스, 레포, worktree를 판별한다 | Context Descriptor |
| 4 | Repository Runtime Loader | 레포 규칙, 계획, 지식 포인터, 검증 명령을 불러온다 | Repository Context |
| 5 | Approval Manager | 예정된 행동의 게이트 등급을 판정한다 | Gate Decision |
| 6 | Worker Scheduler | worktree와 예산을 할당하고 lease를 발급한다 | Active Lease |
| 7 | Worker | 조사, 구현, 자체 검증을 수행하고 결과물을 제출한다 | Evidence Bundle |
| 8 | Observability | diff, 테스트, 프로브, 런타임 상태를 확인한다 | 관측된 증거 |
| 9 | Acceptance | 게이트와 증거를 바탕으로 결과를 수락하거나 반려한다 | Acceptance Decision |
| 10 | Work Ledger | 수락된 상태, 미수락 결과, blocker와 다음 행동을 기록한다 | 갱신된 실행 상태 |
| 11 | Knowledge Store | 반복해서 사용할 가치가 있는 정보를 승격 후보로 분류한다 | 정본 변경 또는 포인터 |
| 12 | Master | 모든 수락 조건이 충족되면 작업이나 트랙을 종료한다 | Closed State |
현재 운영(2026-07-17 기준)에서는 5단계의 Approval Manager 역할을 Master와 Human이 수동으로 수행하고 있다.
목표 구현에서는 행동의 효과와 되돌리기 가능성을 기준으로 다음과 같이 수락 경로를 나누도록 설계했다.
- G0·G1은 정책과 계약 테스트를 통과하면 자동으로 진행할 수 있다.
- G2는 사전에 위임된 범위 안에서는 진행할 수 있지만, 공유 상태에 미치는 영향이 크거나 위임 범위가 불명확하면 Human 승인을 요청한다.
- G3는 반드시 Human의 명시적 승인을 받아야 한다.
Human
│ Task Request
▼
Master
│ classify task / inspect role and track
▼
Context Resolver
│ resolve workspace and repository
▼
Repository Runtime Loader
│ load rules, planning, knowledge pointers
▼
Approval Manager
│ classify planned actions
▼
Worker Scheduler
│ allocate worktree and issue lease
▼
Worker
│ inspect → implement → test → submit
▼
Observability
│ collect diff, test, probe, runtime evidence
▼
Acceptance
├─ accepted ───────────────► Update Work Ledger
├─ changes requested ──────► Return to Worker
├─ rejected ───────────────► Record Failure
└─ Human verification ─────► Approval Gate
│
▼
Acceptance Decision
여기서 Worker의 작업 종료와 결과물의 최종 수락은 서로 다른 사건이다. Worker가 lease를 끝냈거나 complete라고 보고했더라도, 증거가 부족하면 작업은 완료된 것으로 처리되지 않는다.
Work Ledger에는 실행 도중에도 lease 상태와 blocker를 기록하지만, 최종 상태는 Acceptance 결과가 나온 뒤 확정한다.
영구 지식 승격 또한 모든 작업에서 발생하는 필수 단계가 아니다. 3.25의 조건을 만족하는 정보만 별도의 검토를 거쳐 정본에 반영한다.
어느 단계에서든 실패가 발생하면 증거와 현재 상태를 보존한 뒤 3.24의 실패 처리 절차로 전환한다.
각 단계에는 다음 단계로 넘어가기 위한 명시적인 조건이 있다.
| 단계 | 책임 주체 | 출력 | 다음 단계의 조건 |
|---|---|---|---|
| 작업 분류 | Master | 대상 Track, 역할, 레포 | 책임 경계가 확정됨 |
| 컨텍스트 해석 | Context Resolver | Context Descriptor | 대상 레포와 실행 위치가 검증됨 |
| 하네스 적재 | Repository Runtime Loader | 규칙, 검증 명령, 정본 포인터 | 필요한 정본을 읽을 수 있음 |
| 위험도 분류 | Approval Manager | Gate 등급 | 승인 필요 여부가 결정됨 |
| 실행 준비 | Worker Scheduler | worktree와 lease | 범위, 예산, 제출물이 명시됨 |
| 구현 | Worker | artifact와 worker claim | 요구된 결과물이 제출됨 |
| 관측 | Observability | evidence bundle | 외부에서 증거를 확인할 수 있음 |
| 수락 | Approval Manager 또는 Human | acceptance decision | Gate와 수락 조건을 충족함 |
| 상태 반영 | Master와 Repository Harness | Ledger 및 정본 갱신 | 실행 상태와 영구 지식이 분리돼 기록됨 |
Worker가 결과물을 제출했다고 해서 작업이 곧바로 완료되는 것은 아니다. worker_claim: complete와 acceptance: accepted는 서로 다른 상태다. Evidence Bundle이 요구 조건을 충족하고 필요한 승인을 통과해야만 작업을 완료 상태로 전환할 수 있다.
검증에 실패하면 Work Ledger를 완료로 바꾸지 않는다. 구현 결과와 검증 실패 기록을 그대로 남기고, changes_requested 또는 blocked 상태에서 다음 행동을 결정한다.
3.23 크로스레포 작업의 전체 시퀀스
크로스레포 작업에서는 Master가 하나의 트랙 안에서 여러 레포의 작업 순서와 의존성을 조율한다. 그렇다고 Master가 각 레포의 구현 책임까지 가져가는 것은 아니다.
각 레포는 자신의 Repository Harness와 별도의 Worker lease를 유지한다. Cross-repo Planner는 레포 사이의 계약과 선후 관계를 관리하고, 각 레포의 구현 방식과 테스트 진실은 해당 Repository Harness가 소유한다.
아래는 백엔드 API를 변경하고 프론트엔드가 이를 사용한 뒤 프로덕션에 배포하는 경우의 예시다.
| 단계 | 담당 | 작업 | 수락 조건 |
|---|---|---|---|
| 1 | Master | 크로스레포 트랙을 만들고 대상 레포와 의존 순서를 정한다 | 대상 레포, 계약 경계, 순서 확정 |
| 2 | Backend Harness·Worker | API 계약과 백엔드 구현을 변경한다 | 백엔드 테스트와 계약 증거 제출 |
| 3 | Acceptance 또는 Human | 변경된 API 계약을 검토한다 | breaking change와 외부 영향 확인 |
| 4 | Frontend Harness·Worker | 수락된 계약을 기준으로 소비 측 구현을 변경한다 | 프론트엔드 테스트와 빌드 통과 |
| 5 | Master | 레포 사이의 통합 검증을 조율한다 | API와 UI 연동 프로브 통과 |
| 6 | Release Coordinator | 배포 순서와 rollback 절차를 정한다 | 배포·복구 순서 확인 |
| 7 | Human | 배포를 승인한다 | G3 명시적 승인 |
| 8 | Observability | 배포된 버전과 실제 동작을 확인한다 | 버전, 로그, 실제 요청 결과 일치 |
| 9 | Knowledge Store (Repository Harness) | 필요한 ADR이나 runbook을 갱신한다 | 정본 변경 이력 보존 |
| 10 | Master | 모든 수락 결과를 반영하고 트랙을 종료한다 | 열린 lease와 미수락 결과 없음 |
Backend Repository
│
│ API Contract + Evidence
▼
Cross-repo Planner
│
├─ 계약이 수락됐는가?
│ │
│ └─ No ──► Backend 변경 또는 승인 대기
▼
Frontend Repository
│
│ Consumer Implementation + Evidence
▼
Integration Probe
│
├─ 통과했는가?
│ │
│ └─ No ──► 원인 레포 판별 후 재작업
▼
Release Coordinator
│
▼
Human Deployment Gate
│
▼
Post-deployment Verification
프론트엔드의 탐색 작업이나 mock 작성은 백엔드 계약이 확정되기 전에도 병렬로 진행할 수 있다. 다만 최종 구현과 수락은 검증된 계약을 기준으로 해야 한다. 초안 계약을 확정된 정본처럼 사용하면 두 레포가 서로 다른 가정을 구현할 수 있기 때문이다.
API 계약 변경이 breaking change가 아니고 사전에 위임된 범위 안에 있다면 정책에 따라 자동 수락할 수 있다. 반대로 외부 소비자에게 영향을 주거나 호환성을 깨뜨리는 변경이라면 Human 승인을 포함한 상위 게이트로 올린다.
백엔드 작업 중 프론트엔드 변경이 필요하다는 사실을 발견하더라도 Backend Worker가 프론트엔드 레포까지 임의로 수정하지 않는다. Worker는 범위 확대를 제안하고, Master가 Track의 대상 레포와 실행 순서를 다시 결정한다.
중요한 원칙은 하나의 Worker가 편의를 위해 여러 레포를 임의로 수정하지 않는 것이다. 다른 레포의 변경이 필요해지면 현재 lease를 확대하는 대신 Master에게 범위 변경을 제안하고, 해당 레포를 위한 별도의 lease와 수락 조건을 발급한다.
한 레포의 테스트가 통과했다는 사실도 전체 작업의 완료를 의미하지 않는다. 크로스레포 작업은 각 레포의 개별 evidence뿐 아니라 계약 검증과 통합 프로브까지 통과해야 수락할 수 있다.
3.24 실패 처리
실패는 단순히 작업을 중단시키는 오류가 아니다. 현재 상태와 다음 허용 행동을 바꾸는 명시적인 상태 전이다.
따라서 실패가 발생하면 바로 재시도하기보다 먼저 실패 유형을 판별하고, 관련 증거와 미수락 결과를 Work Ledger에 남겨야 한다.
실패는 구현 오류, 검증 실패, 승인 거절, 런타임 장애, 지식 불일치로 구분한다.
| 실패 유형 | 예시 | 기본 처리 |
|---|---|---|
| Implementation Failure | 테스트 실패, 빌드 실패, 구현 오류 | 현재 결과를 미수락 상태로 두고 Worker에게 수정을 요청한다 |
| Scope Failure | 작업 중 다른 레포나 권한이 필요해짐 | lease를 임의로 확대하지 않고 Master에게 범위 변경을 제안한다 |
| Verification Failure | Worker의 주장과 diff·테스트 결과가 일치하지 않음 | 수락을 거절하고 부족한 증거 또는 수정 사항을 명시한다 |
| Approval Rejection | Human이 배포나 공유 변경을 승인하지 않음 | 트랙을 blocked 또는 changes_requested 상태로 전환한다 |
| Runtime Failure | Orca 재시작, PTY 단절, Worker 소실 | 즉시 새 세션을 만들지 않고 Recovery Manager의 순서로 상태를 확인한다 |
| Knowledge Conflict | Git 문서와 memory의 내용이 충돌함 | 정보 유형별 정본을 우선하고 캐시나 포인터를 다시 생성한다 |
| Role Violation | Architecture 역할에서 구현이나 배포를 시도함 | 행동을 중단하고 결과물을 미수락 상태로 둔 뒤 Role State를 복구한다 |
| Budget Failure | 토큰, 시간, Worker 수가 lease 예산을 초과함 | 추가 dispatch를 중단하고 범위 축소·파킹·예산 재승인 중 하나를 선택한다 |
Runtime Failure가 발생했다고 해서 해당 Worker를 바로 실패로 확정해서는 안 된다. 프로세스와 PTY가 살아 있지만 화면에서만 보이지 않을 수도 있다. 실행 상태를 확인하기 전까지는 failed가 아니라 unknown 또는 recovering 상태로 두는 편이 안전하다.
Knowledge Conflict도 무조건 Git을 우선한다는 뜻은 아니다. 영구적인 제품·운영 지식은 Git 문서가 정본이고, 현재 이슈의 실행 상태는 Work Ledger가 정본이다. beads memory나 handoff는 자신의 책임 범위 안에서만 사용하며, 다른 정본과 충돌하면 다시 생성하거나 갱신한다.
실패 처리에는 다음 원칙을 적용한다.
- 실패 원인을 판별하기 전에 같은 작업을 자동으로 반복하지 않는다.
- diff, 로그, 테스트 결과, 프로세스 상태처럼 실패 당시의 증거를 보존한다.
- 수락되지 않은 결과와 이미 수락된 상태를 구분한다.
- 현재 트랙과 lease 상태를 Work Ledger에 반영한다.
- 재시도가 가역적이고 안전하며 예산 안에 있을 때만 다시 실행한다.
- 반복되거나 운영 위험이 큰 실패는 postmortem 또는 runbook 승격 후보로 분류한다.
반복 실패를 문서화한다고 해서 모든 오류 로그를 영구 지식으로 남기는 것은 아니다. 반복 원인, 재현 조건, 탐지 방법, 안전한 복구 절차처럼 다음 작업에서도 사용할 수 있는 내용만 승격 대상으로 삼는다.
반복 실패가 발생하면 단순 재시도보다 postmortem 또는 runbook 승격 후보로 분류한다.
3.25 영구 지식 승격 조건
모든 작업 내용을 wiki에 남기면 다시 문서 퇴적물이 된다. 따라서 다음 조건 중 하나 이상을 만족하는 정보만 영구 지식으로 승격한다.
| 조건 | 설명 |
|---|---|
| 반복 가능성 | 같은 문제나 판단이 다시 나타날 가능성이 높다 |
| 반복 문의 가능성 | 다음 작업자가 같은 질문을 다시 조사할 가능성이 높다 |
| 비가역성 | 잘못 판단했을 때 되돌리기 어렵거나 복구 비용이 크다 |
| 의존성 | 다른 결정, 구현 또는 운영 절차가 이 사실에 의존한다 |
| 운영 위험 | 장애, 보안, 데이터 손실, 권한 오용과 연결된다 |
| 비직관성 | 코드나 현재 상태만 봐서는 이유를 파악하기 어렵다 |
| 외부 계약 | API, 배포 규칙, 규제, 고객 약속과 연결된다 |
반대로 다음 정보는 일반적으로 영구 지식으로 승격하지 않는다.
- 현재 이슈의 시간순 작업 기록
- 한 번만 사용한 명령의 전체 출력
- 코드만 읽어도 명확하게 알 수 있는 단순 사실
- 아직 검증되지 않은 가설이나 추측
- 비밀번호, 토큰, 인증 정보 같은 비밀 데이터
- 이미 다른 정본에 존재하는 내용의 전문 복제본
영구 지식 승격은 다음 순서로 진행한다.
Candidate Information
│
▼
Verify Evidence and Acceptance
│
▼
Classify Scope
│
├─ Product / Code ──────► Repository Wiki
└─ Workspace / Harness ─► planning-repo/docs
│
▼
Search Existing Canonical Knowledge
│
├─ exists ─────► Update or Supersede
└─ absent ─────► Create Canonical Entry
│
▼
Review and Commit
│
▼
Update Work Ledger and Pointer Cache
먼저 해당 정보가 외부 증거로 확인됐고 작업 결과가 수락됐는지 검토한다. 다음으로 제품·코드에 속하는지, 워크스페이스·하네스 운영에 속하는지 판별한다.
저장 위치를 정한 뒤에는 같은 내용이 기존 정본에 있는지 검색한다. 이미 존재한다면 새 문서를 추가하지 않고 기존 문서를 갱신하거나 supersede 관계를 남긴다. 새로운 정책이나 고위험 운영 규칙이라면 Human 승인을 거쳐 Git 이력에 반영한다.
마지막으로 Work Ledger에는 어떤 지식이 어디로 승격됐는지 기록하고, beads memory에는 필요할 때 정본을 찾을 수 있는 짧은 포인터만 남긴다. scratchpad나 handoff에 있던 전문을 또 다른 장기 복제본으로 유지하지 않는다.
현재 운영에서는 사람이 이 과정을 판단하고 집행한다. 목표 구현에서는 중복 canonical ID, 잘못된 저장 경로, memory의 장문 전문 같은 형식적 위반을 자동 검사할 수 있다. 다만 어떤 정보가 장기적으로 가치 있는지는 의미 판단이 필요하므로, 완전히 자동화하기보다 Master와 Human의 검토 대상으로 남기는 편이 적절하다.
3.26 Repository Layout
아래 구조는 동결된 설계를 코드로 옮길 때 사용할 수 있는 Reference Implementation의 예시 레이아웃이다.
현재 이 디렉터리와 12개 Runtime Unit이 모두 구현돼 있다는 뜻은 아니다. (코드 X, 문서 시스템으로 동작하는 중. 강제성 X)
agent-harness/
├── README.md
├── spec/
│ └── README.md # 아키텍처 정본을 가리키는 포인터
├── src/
│ ├── bootstrap/
│ ├── context/
│ ├── workspace/
│ ├── repository/
│ ├── scheduler/
│ ├── approval/
│ ├── role/
│ ├── recovery/
│ ├── succession/
│ ├── lineage/
│ ├── observability/
│ └── adapters/
│ ├── work-ledger/
│ ├── knowledge-store/
│ ├── execution-substrate/
│ ├── executor/
│ ├── trace-archive/
│ └── human-interface/
├── probes/
│ ├── duplicate-master/
│ ├── knowledge-integrity/
│ ├── lease-health/
│ └── handoff-integrity/
├── tests/
│ ├── contract/
│ ├── recovery/
│ ├── succession/
│ ├── approval/
│ └── scenarios/
└── docs/
├── implementation/
└── adapter-guides/
src/ 아래의 디렉터리는 3.3에서 설명한 Runtime Unit의 책임 경계와 대응한다.
처음부터 각각을 별도 프로세스나 마이크로서비스로 구현할 필요는 없다. 하나의 CLI나 프로세스 안에서 시작하더라도 책임과 인터페이스는 분리해야 한다.
docs/implementation/에는 라이브러리 선택, 내부 타입, 성능상 타협처럼 구현 단계에서 결정한 내용을 남긴다.
Runtime Unit의 책임이나 불변식을 바꾸는 문서는 이곳에 추가하지 않고, 정본 Architecture의 ADR 절차로 올린다.
docs/adapter-guides/에는 Orca, beads, Git, Codex 같은 구체 도구의 명령과 제약을 기록한다. Core 문서에 제품별 예외를 흩어 놓지 않기 위한 경계다.
src/는 런타임 책임별 구현을 담고, adapters/는 외부 도구와의 결합을 격리한다.
probes/는 실행 중인 시스템의 불변식을 확인하며, tests/는 계약과 실패 시나리오를 검증한다.
spec/에는 아키텍처 문서의 복제본을 넣지 않는다. 정본 경로와 버전만 기록한다.
spec/README.md에는 Architecture 문서의 복제본을 넣지 않는다. 대신 정본 경로, 기준 revision, 마지막 검증 시각 같은 포인터만 기록한다. 구현 레포 안에서 별도의 스펙 복제본을 수정할 수 있게 만들면 Architecture Freeze와 SSOT 구조가 다시 깨진다. (spec 인 이유는 superpowers 스킬에 맞춰서 설계한 것이므로 입맛에 따라 자유롭게 설계해도 됨)
canonical_spec:
repository: planning-repo
path: docs/architecture/agent-harness.md
revision: <commit-or-version>
구현 레포 안에서 아키텍처를 직접 수정할 수 있게 만들면 어느 문서가 현재 정본인지 다시 판별해야 한다.
구현에 필요한 설명은 docs/implementation/에 둘 수 있지만, 여기서 새로운 책임이나 불변식을 정의해서는 안 된다.
디렉터리 구조 자체가 책임 분리를 보장하는 것은 아니다. 예를 들어 scheduler/가 beads 명령을 직접 호출한다면 Adapter Layer를 둔 의미가 사라진다. 따라서 import 규칙이나 정적 검사로 core가 구체적인 도구 구현체를 직접 참조하지 못하게 해야 한다.
3.27 핵심 계약 테스트
초기 구현에서는 기능 수를 늘리기 전에 불변식과 경계부터 자동화해야 한다.
| 테스트 | 검증 내용 |
|---|---|
| Bootstrap Budget Test | L0·L1 컨텍스트가 정해진 예산을 넘지 않고, 장문 정본이 부팅 시 전문으로 주입되지 않는다 |
| Context Resolution Test | workspace root, repository, worktree를 올바르게 구분하고 대상 레포를 잘못 선택하지 않는다 |
| Repository Isolation Test | Worker가 lease에 포함되지 않은 레포와 경로를 수정하지 못한다 |
| Approval Gate Test | G3 행동이 Human의 명시적 승인 없이 실행되지 않는다 |
| Self-report Rejection Test | Worker의 자연어 완료 보고만으로 작업 상태가 accepted로 바뀌지 않는다 |
| Duplicate Resume Test | 같은 session ID가 두 프로세스에서 동시에 resume되지 않는다 |
| Runtime Restart Recovery Test | 클라이언트 재시작 시 살아 있는 PTY에 재부착하고, 실행이 실제로 소멸한 경우에만 후임을 생성한다 |
| Succession Verification Test | 후임이 handoff와 정본을 검증하지 못하면 전임을 은퇴시키지 않는다 |
| Role Lock Test | 현재 Master가 잠긴 역할 밖의 행동을 실행하지 못한다 |
| Knowledge Duplication Test | 같은 canonical ID나 동일한 정본 내용이 여러 위치에 중복 생성되지 않는다 |
| Memory Pointer Test | beads memory에 ADR이나 postmortem 전문이 저장되지 않는다 |
| Handoff Singularity Test | 하나의 Track에 LIVE handoff가 두 개 이상 존재하지 않는다 |
| Architecture Drift Test | 동결된 설계에서 파생된 근거 없이 새 Runtime Unit이나 책임이 추가되지 않는다 |
| Adapter Substitution Test | mock adapter로 교체해도 Core의 계약과 상태 전이가 유지된다 |
Runtime Restart Recovery Test처럼 실제 daemon과 PTY가 필요한 검증은 단위 테스트만으로 충분하지 않다.
반대로 모든 테스트를 실제 도구에 의존하게 만들면 계약 오류와 환경 오류를 구분하기 어려워진다. 따라서 core 계약과 실제 Adapter 검증을 분리해야 한다.
테스트 이름이 존재하거나 한 번 통과했다는 사실만으로 불변식이 보장되는 것은 아니다. 테스트가 어떤 경로와 실패 조건을 실제로 검증하는지 확인해야 한다.
이 테스트들은 실행 환경에 따라 세 층으로 나누는 편이 좋다.
- Contract Test
외부 도구 없이 타입, 상태 전이, Gate, Adapter 계약을 검증한다.
타입, 게이트, 컨텍스트 예산은 계약 테스트로 검증할 수 있다. - Scenario Test
가짜 세션과 임시 레포를 사용해 실패, 복구, 승계 흐름을 검증한다.
프로세스, PTY, 앱 재시작은 실제 실행 환경을 사용하는 시나리오 테스트가 필요하다. - Operational Smoke Test
실제 Orca, Git, beads 같은 구현체를 연결해 재부착과 중복 실행 방지 여부를 확인한다.
지식 중복과 handoff 개수는 Git과 파일 시스템을 검사하는 프로브가 적합하다.
역할 위반과 승인 우회는 런타임 가드와 테스트를 함께 사용해야 한다.
테스트 이름이나 초록색 상태만으로 불변식이 검증됐다고 단정해서는 안 된다. 어떤 fixture와 adapter를 사용했는지, 실제 프로세스를 실행했는지, 실패 조건을 의도적으로 재현했는지까지 확인해야 한다.
예를 들어 Runtime Restart Recovery Test는 단순히 새 세션이 만들어졌는지를 검사하는 테스트가 아니다. 다음 두 상황을 구분해야 한다.
- Orca 클라이언트만 재시작되고 daemon과 PTY가 살아 있다면 기존 세션에 재부착한다.
- 기존 실행이 소멸했다는 증거가 있을 때만 handoff, Work Ledger, Git을 이용해 후임을 생성한다.
이 구분이 없으면 복구 테스트가 오히려 중복 Master 생성을 정상 동작으로 인정할 수 있다.
3.28 단계별 구현 순서
전체 시스템을 한 번에 구현하면 하네스 자체가 복잡성의 원인이 된다.
따라서 외부 도구에 의존하지 않는 계약부터 시작해 실행, 승인, 복구 순서로 확장한다.
| 단계 | 구현 범위 | 완료 기준 |
|---|---|---|
| Phase 0 | 핵심 타입, 상태 전이, 불변식, adapter interface | 외부 도구 없이 계약 테스트 통과 |
| Phase 1 | Bootstrap, Context Resolver | 최소 컨텍스트로 workspace와 대상 레포 판별 |
| Phase 2 | Work Ledger, Knowledge Store adapter | 실행 상태와 영구 정본이 서로 다른 저장 규칙을 따름 |
| Phase 3 | Repository Runtime Loader, Worker Scheduler | 격리된 단일 레포 worktree에서 lease 실행 |
| Phase 4 | Evidence, Acceptance, Approval Manager | 자기 보고만으로 수락되지 않고 G0–G3 게이트가 작동 |
| Phase 5 | Role Runtime, Track Registry | Track 파킹과 명시적인 역할 전환 가능 |
| Phase 6 | Recovery Manager와 최소 복구 프로브 | 클라이언트·daemon·PTY·프로세스를 구분하고 중복 resume 차단 |
| Phase 7 | Succession Manager, Lineage Recorder와 최소 승계 프로브 | 후임 검증, 전임 종료 확인, lineage 기록까지 한 흐름으로 완료 |
| Phase 8 | Observability와 통합 프로브 | 중복 Master, stale handoff, orphan lease, 지식 드리프트 탐지 |
| Phase 9 | Cross-repo Planner, Release Coordinator | 두 개 이상의 레포를 사용하는 계약·배포 시나리오 통과 |
| Phase 10 | External Ledger 연결 | 정본을 복제하지 않고 외부 이슈 트래커에 상태와 포인터만 동기화 |
Phase는 기능 목록이 아니라 검증 가능한 능력의 단위다. 예를 들어 Phase 3은 Scheduler 코드가 존재할 때가 아니라, Worker가 lease 밖의 레포를 수정하지 못하고 종료 후 자원이 회수될 때 완료된다.
MVP의 범위도 두 가지로 나눠야 한다.
- 실행 MVP: Phase 0~5
단일 레포 작업을 제한된 lease로 실행하고 evidence를 수락할 수 있는 수준이다. - 운영 MVP: Phase 0~10
세션 재시작과 Master 승계를 포함해 장시간 작업을 실제로 이어갈 수 있는 수준이다.
승계와 복구를 실제 운영에 자동화하려면 중복 실행과 stale 상태를 지속적으로 탐지해야 하므로 Phase 8까지 포함하는 편이 안전하다.
다중 레포 릴리즈까지 자동화하려면 Phase 9, 10 이 필요하다.
이 글의 핵심 동기가 승계와 복구이므로, 실제 운영에 투입할 MVP라면 Phase 7까지 포함하는 편이 타당하다. Phase 8 이후는 운영 규모와 위험에 따라 점진적으로 추가할 수 있다.
각 Phase를 시작하기 전에 앞 단계의 계약을 다시 바꾸어야 한다면 단순 구현 지연으로 처리하지 않는다. 책임이나 불변식이 달라지는 변경이라면 3.21의 Architecture Freeze 절차로 되돌아간다.
Recovery와 Succession을 Observability보다 먼저 구현한다고 해서 관측 없이 개발한다는 뜻은 아니다.
Phase 6과 Phase 7에는 해당 기능을 검증하는 최소 probe 가 반드시 포함된다. Phase 8에서는 이 probe 들을 통합해 지속적인 경보, 기준선, 예산 관측 체계로 확장한다.
현재 세 번의 승계에서 검증된 것은 사람이 헌장과 프로브를 이용해 집행한 승계·복구 절차까지 동작 구현을 확인했다.
3.29 이 시스템이 해결하는 실패 패턴
이 하네스는 다음과 같은 기존 실패 패턴을 직접 겨냥한다.
| 기존 실패 | 원인 | 대응 |
|---|---|---|
| 세션이 바뀌면 판단 근거가 사라짐 | 상태가 대화 기록에만 존재한다 | Work Ledger, Git 정본, thin handoff로 상태를 세션 밖에 둔다 |
| 같은 규칙이 여러 곳에서 다르게 존재 | 정보 유형별 SSOT가 없다 | 정본을 하나만 두고 다른 위치에는 포인터만 남긴다 |
| 앱 (IDE/ADE)이 죽으면 세션도 죽었다고 오판 | 클라이언트, daemon, PTY, Agent의 생명주기를 구분하지 않는다 | Recovery hierarchy에 따라 재부착 가능성을 먼저 확인한다 |
| 에이전트가 완료했다고 하면 그대로 믿음 | 제출과 수락이 분리돼 있지 않다 | diff, 테스트, 로그, 프로브를 대상으로 Acceptance를 수행한다 |
| 한 세션에서 여러 역할이 섞인다 | 현재 Role State와 전환 절차가 없다 | 한 번에 하나의 역할만 활성화하고 Role Lock으로 제한한다 |
| Worker가 작업 범위를 임의로 넓힌다 | 위임 범위와 권한이 명시되지 않는다 (lease 부재) | lease에 레포, 경로, capability, 예산을 기록한다 (Scope와 capability 제한) |
| 모델과 도구가 바뀌면 전체 구조가 깨짐 | 제품별 명령이 핵심 로직에 직접 결합돼 있다 (구체 도구 직접 결합) | 제품별 차이를 Adapter Layer 안에 제한한다 |
| memory가 세션마다 커진다 | 캐시와 영구 정본의 역할이 섞여 있다 | memory를 짧은 요약과 정본 포인터로 제한한다 |
| 확인하는 문서와과 실제 Git의 내용이 서로 다르다 | 복제본 운영 | 복제본을 갱신하지 않는 아카이브로 강등 |
| handoff 파일이 계속 쌓여 최신본을 알 수 없다 | 파일 개수로 상태와 이력을 함께 표현한다 | 목표 상태에서는 Track마다 LIVE handoff를 한 건만 두고 이력은 Git으로 보존한다 |
| 설계가 구현 중 계속 변함 | 설계 변경과 구현 판단을 구분하지 않는다 (Freeze와 변경 절차 부재) | Architecture Freeze와 ADR 절차를 적용한다 (트랙당 LIVE 1건과 Git 이력) |
| 멀티에이전트 비용이 통제되지 않는다 | Worker 수, 재시도, 토큰 예산에 제한이 없다 (dispatch budget 부재) | Scheduler가 lease 단위의 예산과 동시 실행 수를 강제한다 |
3.30 최종 시스템 모델
전체 시스템은 지식, 계획, 실행, 증거, 승인, 복구가 순환하는 폐쇄 루프다.
그러나 각 단계가 하나의 중앙 에이전트 안에 들어가는 것은 아니다.
정보의 정본은 Git과 Work Ledger에 있고, Master는 이를 조율하며, Worker는 제한된 lease에서 실행하고, Human은 중요한 결정을 수락한다.
Recovery와 Succession은 이 루프 바깥에 붙는 임시 예외 처리가 아니다. Master나 Worker는 어느 단계에서든 중단될 수 있으므로, 두 기능은 전체 수명주기를 둘러싼 연속성 계층으로 다뤄야 한다.
┌──────────────────┐
│ Human │
│ Priority/Approval│
└────────┬─────────┘
│
▼
┌──────────────────┐ ┌──────────────────┐
│ Canonical │────►│ Master │
│ Knowledge │ │ Orchestrator │
│ Git / Planning │ │ Track / Role │
└────────▲─────────┘ └────────┬─────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Worker Scheduler │
│ │ Lease / Budget │
│ └────────┬─────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Execution Worker │
│ │ Worktree / Task │
│ └────────┬─────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Evidence Bundle │
│ │ Diff/Test/Probe │
│ └────────┬─────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Acceptance │
│ │ Gate / Human │
│ └────────┬─────────┘
│ │
│ ┌───────────────┴───────────────┐
│ ▼ ▼
│ ┌──────────────────┐ ┌──────────────────┐
│ │ Work Ledger │ │ Knowledge │
│ │ Current State │ │ Promotion │
│ └──────────────────┘ └────────┬─────────┘
│ │
└──────────────────────────────────────┘
각 주체가 소유하는 것은 다음과 같다.
- Human은 우선순위, 비가역적 행동, 외부 권한과 최종 승인을 소유한다.
- Master는 Track, 역할, 위임, 레포 사이의 순서와 승계를 조율한다.
- Repository Harness는 해당 레포의 지식, 규칙, 계획, 빌드와 테스트 진실을 소유한다.
- Worker는 lease 안에서만 실행하고 결과물과 evidence를 제출한다.
- Git과 Work Ledger는 세션 밖에서 각각 영구 지식과 현재 실행 상태를 보존한다.
승계와 복구는 이 루프 바깥에 덧붙인 예외 처리가 아니다. Master나 Worker는 어느 단계에서든 중단될 수 있으므로, Recovery Manager와 Succession Manager가 전체 실행 흐름을 둘러싸고 연속성을 보장해야 한다.
승계와 복구는 이 정상 루프의 바깥에 붙는 임시 예외 처리기가 아니다. 어느 단계에서든 현재 Master나 Worker가 중단될 수 있으므로, Recovery Manager와 Succession Manager가 전체 루프를 둘러싸고 연속성을 보장한다.
┌───────────────────────────────────────────────────────────────┐
│ Recovery / Succession Envelope │
│ │
│ Knowledge → Master → Worker → Evidence → Acceptance → Update │
│ ▲ │ │
│ └──────── Handoff / Ledger / Git Recovery ───────┘ │
│ │
│ Reattach first → Resume once → Spawn successor if necessary │
└───────────────────────────────────────────────────────────────┘
Lineage Recorder는 이 정상 루프의 입력이 아니라 별도의 감사 경로다.
Succession Result
│
▼
Lineage Recorder
│ append-only
▼
Human Audit
│
└─► handoff와 운영 절차 개선
Human은 lineage를 읽고 다음 승계 절차를 개선할 수 있지만, 다음 Master가 과거 계보 전체를 자동으로 읽고 판단을 바꾸게 하지는 않는다. 후임의 직접적인 복구 입력은 현재 handoff, Work Ledger, Git 정본이다.
이 시스템의 목표는 특정 에이전트가 오랫동안 모든 내용을 기억하게 만드는 것이 아니다. 개별 세션과 모델, 실행 도구가 언제든 교체되거나 실패할 수 있다는 전제에서도 작업 상태와 정본 지식, 승인권, 책임 경계가 유지되게 만드는 것이다.
따라서 시스템의 신뢰성은 모델의 기억력이나 자연어 응답 품질만으로 평가할 수 없다. 다음 조건을 외부에서 확인할 수 있어야 한다.
- 정본의 위치가 정보 유형별로 명확한가
- Worker의 실행 범위가 lease로 제한되는가
- 완료 주장이 외부 증거로 검증되는가
- 비가역적 행동이 Human의 승인을 거치는가
- 살아 있는 세션을 중복으로 resume하지 않는가
- 후임이 복구된 뒤에만 전임이 은퇴하는가
현재 세 번의 승계는 이 가운데 handoff 복구, 정본 확인, 전임 종료 검증, lineage 기록을 사람이 직접 집행할 수 있음을 보여줬다. 다음 4부에서는 그 실측 과정에서 무엇이 실패했고, 그 실패가 다음 세대의 절차를 어떻게 바꿨는지 살펴본다.
4부 실측 기록: 적용 판단 기준 퇴고본 (3번의 승계)
앞 절까지는 설계 명세였다. 하지만 승계 프로토콜 자체는 문서로만 존재하지 않았다. 설계 당일과 다음 날에 걸쳐 실제 Master 세션을 세 번 승계했고, 각 결과를 lineage에 기록했다.
세 번 모두 같은 조건에서 수행한 실험은 아니다. Gen 1은 헌장 발효 전의 계획 승계였고, Gen 2는 새 lineage 스키마를 처음 적용한 승계였으며, Gen 3은 프로토콜 전체를 확인하기 위해 의도적으로 실행한 smoke test였다.
| 세대 | 승계 계기 | 복구에 사용한 정보 | 관측 결과 | 다음 세대에 반영한 교훈 |
|---|---|---|---|---|
| Gen 1 | 컨텍스트 지표 약 67% | Git, handoff, Work Ledger, Trace Archive | 열린 트랙 6개 인수, 재질문 0회 | 전임 생존 여부를 별도로 확인해야 한다 |
| Gen 2 | 로케일 버그 수정 완료 | Git, handoff, Work Ledger | 재질문 0회, 결정 재개봉 0건, 유실 없음 | PID뿐 아니라 커맨드라인까지 대조한다 |
| Gen 3 | 프로토콜 스모크 테스트 | 헌장, handoff, Work Ledger, Git | 재질문 0회, 결정 재개봉 0건, 유실 없음 | 모니터를 상속하지 않고 후임 소유로 다시 띄운다 |
여기서 컨텍스트 사용량은 당시 관찰 가능한 지표를 기준으로 한 근사치다. 모델 내부의 정확한 토큰 사용량을 직접 측정한 값은 아니다.
Gen 1: 헌장 발효 전의 승계 // stale handoff를 발견하다
전임 마스터 세션의 컨텍스트 사용량이 UI 기준 약 67%에 도달했을 때 사용자가 계획 승계를 지시했다.
후임은 Git 정본, handoff, Work Ledger를 읽어 현재 상태를 복구했다.
이 과정에서 채팅에만 존재하고 Git에는 반영되지 않은 문서 한 건이 발견됐다. 후임은 Trace Archive로 이전 세션 기록을 검색해 문서를 회수하고 Git 정본에 편입했다. 승격되지 않은 대화 내용이 실제로 유실될 수 있다는 점을 보여준 사례였다.
후임은 이미 답이 있는 질문을 다시 하지 않고 여섯 개 트랙을 이어받았다. 다만 승계 기록에는 감점 사유가 한 건 남았다. handoff에는 전임 세션이 곧 소멸할 것처럼 적혀 있었지만, 실제 프로세스는 여전히 살아 있었다.
컨텍스트 전달에는 성공했지만 전임 은퇴 상태는 정확하지 않았던 것이다. 이 사례를 통해 handoff의 서술만 믿지 않고 프로세스 상태를 별도로 확인해야 한다는 절차가 추가됐다.
Gen 2: 13필드 스키마의 첫 적용 // 승계 품질을 숫자로 정량화하고 루프로 개선
두 번째 승계는 로케일 버그 수정을 마친 자연스러운 마일스톤에서 진행했다. 이번에는 3.14에서 설명한 13개 필드의 lineage 스키마를 처음 적용했다.
관측 결과는 다음과 같았다.
- 재질문 0회
- 근거 없는 결정 재개봉 0건
- 확인된 컨텍스트 유실 없음
- Trace Archive 검색 0회
Trace Archive 검색이 0회였다는 것은 검색 기능을 사용하지 못했다는 뜻이 아니다. handoff, Work Ledger, Git만으로 필요한 정보를 찾았기 때문에 과거 세션 기록을 추가로 검색할 필요가 없었다는 뜻이다.
이 수치는 승계 후의 대화와 실행 기록을 기준으로 세고 사람이 검수했다. 후임 세션이 스스로 “승계에 성공했다”고 평가한 결과는 지표에 포함하지 않았다.
전임 세션을 종료할 때도 PID만 보고 바로 프로세스를 정리하지 않았다. 먼저 PID의 커맨드라인과 세션 경로를 대조해 해당 프로세스가 정말 전임 Master인지 확인했다. 그 뒤 대상 PID만 종료하고 ps로 소멸 여부를 다시 확인했다.
여러 에이전트 세션이 동시에 실행되는 환경에서 PID 숫자 하나만으로 프로세스를 정리하면 다른 세션을 종료할 수 있다. 커맨드라인과 세션 경로를 함께 대조하는 절차는 이 승계에서 정착됐다.
Gen 3: 승계 프로토콜 스모크 테스트
세 번째 승계는 컨텍스트 사용량 지표가 약 24%일 때 의도적으로 실행했다. 컨텍스트가 부족해서가 아니라, 승계 프로토콜 전체를 처음부터 끝까지 다시 검증하기 위한 스모크 테스트였다.
결과는 다음과 같았다.
- 후임은 헌장, thin handoff, Work Ledger, Git 정본 순서로 현재 상태를 복구했다.
- 활성 트랙의 배포 체크리스트와 전날 발견한 인프라 결함을 재질문 없이 재진술했다. 이 결함은 리다이렉트 대상에 예상하지 않은 개발 포트가 섞여 있던 문제였다.
- 두 레포의 HEAD와 working tree 상태를 직접 확인하고 handoff에 기록된 값과 대조했다.
- 로컬 프로브의 응답 코드를 다시 측정해 handoff의 기준선과 일치하는지 확인했다.
- 전임이 실행하던 드리프트 모니터는 그대로 상속하지 않았다.
- 전임 세션 경로와 커맨드라인을 대조해 orphan 모니터만 종료했다.
- 후임 세션의 소유 정보를 붙여 모니터를 다시 실행하고, 이중 실행 가드와 첫 heartbeat를 확인했다.
- 전임 Master의 커맨드라인을 확인한 뒤 해당 PID만 종료했다.
- 같은 머신에서 실행 중이던 다른 에이전트 세션이 유지되고 있는지도 ps로 확인했다.
- Gen 3 lineage 항목을 append하고 Git commit과 push로 이력을 남겼다.
최종 지표는 재질문 0회, 근거 없는 결정 재개봉 0건, 확인된 컨텍스트 유실 없음이었다. Recovery Flow의 각 단계도 추가적인 Trace Archive 복구 없이 통과했다.
세 차례의 승계가 바꾼 것
세 번의 승계에서 얻은 것은 단순히 “작동했다”는 확인만이 아니었다.
Gen 1에서 발견한 stale handoff가 Gen 2의 PID·커맨드라인 대조 절차로 이어졌다. Gen 2에서 소유자가 불명확한 채 남아 있던 orphan 모니터는 Gen 3에서 명시적인 정리와 재무장 절차로 바뀌었다.
Gen 1
stale handoff와 살아 있는 전임 발견
│
▼
Gen 2
PID·커맨드라인 대조와 종료 후 재확인
│
▼
Gen 3
orphan monitor 정리와 후임 소유로 재구성
Gen 1에서는 handoff와 실제 런타임 상태가 다를 수 있다는 사실을 확인했다.
Gen 2에서는 전임 프로세스의 정체를 확인하고 종료를 검증하는 절차를 정착시켰다.
Gen 3에서는 세션뿐 아니라 감시 프로세스에도 소유권이 필요하다는 점을 확인했다.
Lineage는 다음 Master에게 자동으로 주입하는 지식이 아니다. 따라서 후임이 과거 계보를 읽고 판단을 그대로 답습하지는 않는다.
후임 Master가 lineage 전체를 자동으로 읽고 현재 판단을 바꾼 것은 아니다. Human이 감사 기록을 검토한 뒤, 확인된 문제를 handoff 양식과 운영 절차라는 정본에 반영했다. 변경된 정본을 다음 세대가 읽은 것이다.
Lineage
│ 감사
▼
Human Review
│ 승인된 절차 변경
▼
Charter / Runbook / Handoff Template
│
▼
Next Master 승계
lineage는 관측 데이터이고, 다음 세대가 직접 읽는 입력은 수정된 정본이다.
체감상 가장 큰 변화는 승계 비용이었다. 이전에는 새 세션이 열릴 때마다 작업 맥락을 다시 설명했고, 빠진 내용은 며칠 뒤에야 발견되기도 했다. 이번 세 차례에서는 정본 확인과 프로세스 검증을 포함한 인수인계가 수분 단위의 절차로 끝났다.
다만 정식으로 평균 소요 시간이나 실패율을 측정한 것은 아니다. 세 번의 성공은 수동 승계 프로토콜의 스모크 테스트 결과이지, 장기 운영 신뢰성을 입증하는 벤치마크는 아니다.
이 흐름은 INV-11, 즉 “lineage는 관측 데이터이며 런타임 지식 입력이 아니다”라는 원칙과 충돌하지 않는다. 런타임이 lineage를 자동 학습하는 것이 아니라, 사람이 관측 결과를 검토하고 승인된 절차를 정본에 반영하기 때문이다.
이 환경에서는 승계 비용도 달라졌다. 이전에는 새 세션에 맥락을 다시 설명한 뒤, 빠진 정보가 있는지를 며칠에 걸쳐 발견했다. 이번 세 번의 승계에서는 handoff, Work Ledger, Git 정본과 검증 질문을 이용해 몇 분 단위로 인수인계를 진행했고, 재질문·결정 재개봉·컨텍스트 유실 여부를 승계 직후 확인할 수 있었다.
다만 세 차례의 내부 운영 기록만으로 모든 환경에서 같은 시간과 품질을 보장한다고 일반화할 수는 없다.
여기서 확인한 것은 이 워크스페이스에서 해당 절차가 세 번 연속 실행됐고, 각 승계의 유실과 감점 사유를 같은 기준으로 기록할 수 있었다는 점이다.
이 설계가 필요한 경우와 과한 경우
여기까지 읽고 “오버엔지니어링 아닌가?”라는 생각이 들었다면 절반은 맞다.
단일 레포에서 며칠 안에 끝나는 작업을 하나의 에이전트와 진행한다면 이 시스템 전체는 필요하지 않다. AGENTS.md, 이슈 트래커, 최신 세션 요약 정도로 충분할 수 있다. 이런 환경에 12개 Runtime Unit과 lineage 장부까지 도입하면 관리 비용이 얻는 이점보다 커진다.
이 설계가 값을 하기 시작하는 조건은 다음과 같다.
| 조건 | 기존 방식에서 생기는 문제 | 우선 도입할 장치 |
|---|---|---|
| 트랙 수명이 세션보다 길다 | 세션이 바뀔 때마다 작업을 다시 설명한다 | Work Ledger, Git 정본, thin handoff |
| 여러 레포가 하나의 작업에 묶인다 | 레포 사이의 선후 관계와 계약을 둘 곳이 없다 | Track Registry, Cross-repo Planner |
| 여러 에이전트가 동시에 실행된다 | 누가 어디까지 수정할 수 있는지 불명확하다 | Worker lease, 격리 worktree, Evidence Bundle |
| 프로덕션 권한을 다룬다 | 잘못된 자동 실행이 외부 시스템이나 데이터에 영향을 준다 | Gate Model, Human 승인, Recovery 절차 |
넷 중 두 개 이상이 겹친다면 이 글의 구조 일부를 도입해 볼 만하다. 다만 이는 실측으로 도출한 절대 기준이 아니라 운영 복잡성을 판단하기 위한 경험칙이다.
처음부터 전체 하네스를 구현할 필요도 없다. 다음 순서로 필요한 부분만 도입할 수 있다.
- 정본과 실행 상태를 분리한다.
- 활성 Track에 최신 handoff 한 건을 둔다.
- Worker 위임에 범위와 결과물을 명시한다.
- 완료 보고 대신 diff와 테스트 증거를 확인한다.
- 여러 에이전트가 동시에 돌기 시작하면 lease와 격리를 추가한다.
- 배포나 외부 권한을 맡기기 시작하면 승인 게이트와 복구 프로토콜을 추가한다.
가장 작은 형태로 가져갈 원칙은 세 가지다.
전체 구조를 도입하지 않더라도 다음 세 가지 원칙은 비교적 적은 비용으로 적용할 수 있다.
- 정본을 세션 밖에 둔다.
- 승계를 예외가 아닌 정상 수명주기로 다룬다.
- 에이전트의 자기 보고를 완료 증거로 사용하지 않는다.
이 세 원칙만 지켜도 특정 세션의 기억력에 의존하는 비중을 크게 줄일 수 있다. 나머지 컴포넌트는 실제 실패가 반복되거나 권한 범위가 넓어질 때 단계적으로 추가하는 편이 낫다.
이 세 가지는 12개 Runtime Unit을 구현하지 않더라도 Claude Code나 Codex를 장기 작업에 사용하는 환경에서 바로 적용할 수 있다.
설계는 여기까지다.
그런데 이 승계 프로토콜은 문서로만 존재하지 않았다. 설계 당일과 다음 날에 걸쳐 실제로 세 번 실행됐다.
계보 장부에 남은 기록을 그대로 옮긴다.
부록. Claude Code 안에서 Codex를 부리는 법
이 글의 Master와 Worker 구도는 Claude Code 안에서 Codex를 호출하는 방식으로도 구성할 수 있다. 이 경우 Claude Code가 계획과 조율, 최종 검토를 맡고 Codex는 구현이나 디버깅처럼 범위가 명확한 실행 작업을 맡는다.
이 구성은 하네스의 필수 요소가 아니라 Adapter Layer를 배선하는 한 가지 방법이다. Claude Code와 Codex의 역할을 반대로 두거나, 둘 다 Codex 세션으로 구성해도 책임과 계약이 유지된다면 같은 구조를 적용할 수 있다.
1. Codex 플러그인 설치
Claude Code 를 실행한 뒤, 다음 명령을 차례로 실행한다.
$ /plugin marketplace add openai/codex-plugin-cc
$ /plugin install codex@openai-codex
$ /reload-plugins
설치가 끝나면 다음 명령으로 Codex CLI와 인증 상태를 확인한다.
/codex:setup
이 명령과 플러그인 이름은 2026년 7월 18일 기준 OpenAI의 codex-plugin-cc 공식 저장소에 기재된 설치 절차와 일치한다.
설치 과정을 Claude Code에게 맡기고 싶다면 다음처럼 요청할 수 있다.
# 목표
이 Claude Code 환경에서 OpenAI의 공식 Codex 플러그인을 설정하고,
Claude Code 안에서 Codex를 호출할 수 있는지 확인하세요.
# 사용할 플러그인
openai/codex-plugin-cc의 codex@openai-codex 플러그인만 사용하세요.
# 허용 범위
- 플러그인과 Codex CLI의 설치 상태를 확인할 수 있습니다.
- 필요한 경우 공식 Codex CLI 설치를 제안하거나 수행할 수 있습니다.
- Codex 인증이 필요하면 제게 로그인을 요청하세요.
- 프로젝트 소스 코드와 설정 파일은 변경하지 마세요.
- 별도의 요청 없이 프로젝트 의존성을 설치하거나 빌드를 실행하지 마세요.
# 절차
1. /codex:setup을 실행해 현재 상태를 확인하세요.
2. Codex CLI가 없다면 공식 설치 방법을 사용하세요.
3. 인증이 필요하면 임의로 우회하지 말고 제게 로그인을 요청하세요.
4. 설정 후 /codex:* 명령이 표시되는지 확인하세요.
5. /agents에서 codex:codex-rescue가 보이는지 확인하세요.
6. 프로젝트를 수정하지 않는 읽기 전용 검증으로 연결 상태를 확인하세요.
# 완료 조건
다음 항목을 실제 결과와 함께 보고하세요.
- Codex CLI 설치 여부와 버전
- 인증 준비 상태
- Codex 플러그인 활성화 여부
- codex:codex-rescue 확인 여부
- 실행한 검증 명령과 결과
- 프로젝트 파일 변경 여부
자연어로 “설정됐다”고만 보고하지 말고,
명령 결과와 확인한 상태를 근거로 제시하세요.
# 중단 조건
설치, 인증 또는 권한 문제로 다음 단계에 진행할 수 없다면
임의의 대체 방법을 사용하지 말고 정확한 오류와 필요한 사용자 행동을 보고하세요.
이 프롬프트는 세부 명령을 모두 강제하기보다 목표, 성공 조건, 변경 금지 범위를 먼저 제시한다. GPT‑5.5 공식 가이드도 장기 실행 작업에서는 예상 결과, 성공 기준, 허용되는 부작용, 증거 규칙, 종료 조건을 명시하되 불필요한 단계별 지시는 줄이라고 권한다. OpenAI GPT‑5.5 모델 가이드
2. Codex 인증 확인
플러그인은 로컬에 설치된 Codex CLI의 인증 상태를 사용한다. 이미 이 머신의 Codex CLI에 로그인돼 있다면 별도의 계정 연결이 필요하지 않을 수 있다.
로그인이 필요하면 /codex:setup의 안내를 따르거나 다음 명령으로 인증한다.
!codex login
ChatGPT 계정 또는 API 키 중 어떤 인증 방식을 사용할지는 현재 Codex CLI 환경에 따라 결정한다. 인증 정보는 프로젝트 파일이나 프롬프트에 직접 기록하지 않는다.
3. Master와 Worker의 위임 규칙 설정
설치가 끝났다고 Claude Code가 자동으로 좋은 Master가 되는 것은 아니다. 어떤 작업을 위임하고, 어떤 증거를 받아야 하며, 누가 최종 수락하는지를 별도로 정해야 한다.
다음 프롬프트를 프로젝트의 운영 규칙에 맞게 사용할 수 있다.
# 역할
당신은 이 작업의 Master Orchestrator입니다.
리포지토리 이해, 계획 수립, 작업 분해, 아키텍처 판단,
위임 범위 결정과 최종 수락을 담당하세요.
Codex는 범위가 제한된 Execution Worker로 사용하세요.
# Codex에 위임할 작업
다음과 같은 실행 비용이 큰 작업은 /codex:rescue로 위임할 수 있습니다.
- 다중 파일 구현
- 재현 범위가 명확한 버그 조사와 수정
- 테스트 실패 원인 분석과 수정
- 범위가 정해진 리팩터링
- 반복적인 코드 편집
- 별도의 관점이 필요한 코드 리뷰
작업의 목표나 책임 경계가 아직 불명확하다면 먼저 직접 조사하고 계획을 확정하세요.
# 위임 계약
Codex에 작업을 맡길 때 다음 내용을 빠뜨리지 마세요.
- Objective: 무엇을 달성해야 하는가
- Scope: 변경할 수 있는 파일과 레포
- Constraints: 금지된 변경과 유지해야 할 동작
- Canonical References: 먼저 읽어야 할 정본
- Verification: 실행해야 할 테스트와 프로브
- Deliverables: 제출해야 할 파일, diff, 로그
- Completion Condition: 어떤 증거가 있어야 완료인가
Codex가 작업 범위를 넓혀야 한다고 판단하면 직접 확대하지 말고
change proposal을 반환하게 하세요.
# 모델과 실행 설정
현재 환경에서 실제로 사용할 수 있는 Codex 모델과 reasoning effort를 사용하세요.
모델명을 추측하지 마세요.
긴 작업은 필요하면 background로 실행하고,
작업 식별자를 보존한 뒤 /codex:status와 /codex:result로 결과를 회수하세요.
# 수락 규칙
Codex의 “완료했다”는 응답만으로 작업을 수락하지 마세요.
결과를 받은 뒤 직접 다음 항목을 확인하세요.
1. 실제 변경 파일
2. base 대비 diff
3. 요청 범위 밖의 변경 여부
4. 실행한 테스트와 종료 결과
5. 실패하거나 실행하지 못한 검증
6. 알려진 한계와 남은 위험
증거가 부족하면 accepted로 처리하지 말고
changes_requested 또는 needs_human_verification으로 남기세요.
# 금지 사항
- Codex의 자기 보고를 최종 증거로 사용하지 마세요.
- 위임했다는 이유로 최종 검토 책임을 넘기지 마세요.
- 사용할 수 없는 모델이나 도구가 실행됐다고 가정하지 마세요.
- 권한 오류가 발생했을 때 Claude Code가 대신 수행한 결과를
Codex가 수행한 결과처럼 보고하지 마세요.
공식 플러그인은 /codex:review를 읽기 전용 검토에, /codex:rescue를 조사·수정·후속 작업 위임에 사용한다. 모델이나 추론 강도를 생략하면 Codex 설정과 기본값을 따른다. OpenAI codex-plugin-cc 사용법
4. 위임 결과 확인
오래 걸리는 작업은 background로 실행할 수 있다.
/codex:rescue --background investigate why the integration test is flaky
진행 상태와 결과는 다음 명령으로 확인한다.
/codex:status
/codex:result
중요한 것은 명령이 실행됐다는 메시지와 실제 Codex 작업이 완료됐다는 사실을 구분하는 것이다. Master는 최종적으로 다음 항목을 확인해야 한다.
- 실제 Codex 작업 ID 또는 세션 ID가 생성됐는가
- 예상한 파일에 diff가 존재하는가
- lease 범위 밖의 파일이 변경되지 않았는가
- 보고된 테스트 명령이 실제로 실행됐는가
- 실패하거나 실행하지 못한 검증이 숨겨져 있지 않은가
- 결과를 다시 열 수 있는 세션 포인터가 남아 있는가
이 프롬프트에서 중요한 부분은 “무거운 작업은 Codex에 맡긴다”는 문장이 아니다. 위임할 때 작업 범위와 검증 방법을 함께 전달하고, 결과를 받은 Master가 다시 증거를 확인한다는 점이다.
5. Orca와 함께 사용할 때
Orca를 사용한다면 Orca CLI로 터미널, worktree, 실행 세션을 확인하는 편이 좋다. UI에서 세션이 보인다는 사실과 실제 PTY·프로세스가 살아 있다는 사실을 분리해서 확인할 수 있기 때문이다.
운영 규칙은 다음과 같이 정리할 수 있다.
- 플러그인 설치는 한 번만 수행하고, 반복해서 사용할 위임 규칙을 AGENTS.md나 스킬로 관리한다.
- 긴 작업은 세션 밖의 목표와 Work Ledger에 연결한다.
- 위임할 때마다 대상, 범위, 성공 조건, 금지 사항, 증거를 함께 전달한다.
- background 작업은 작업 ID와 실제 결과를 확인한다.
- Codex의 결과는 Claude Code가 다시 검사한 뒤에만 수락한다.
- Orca 세션이 보이지 않으면 새로 생성하기 전에 기존 PTY와 프로세스부터 확인한다.
6. 이 글의 퇴고에서 사용한 방식
이 글의 퇴고도 같은 구조로 진행했다.
Claude Code Master가 절의 목적, 유지해야 할 기술적 의미와 수정 범위를 관리했고, Codex Worker가 문장 압축과 표현 정리를 수행했다. Worker의 결과는 자연어 보고만으로 수락하지 않고, 실제 변경 내용과 다음 항목을 다시 확인했다.
- 원래 기술적 의미가 보존됐는가
- 운영 중인 부분과 설계 단계가 섞이지 않았는가
- 실측하지 않은 내용을 사실처럼 추가하지 않았는가
- 핵심 용어와 책임 경계가 앞뒤에서 일치하는가
- 표와 다이어그램의 구조가 깨지지 않았는가
따라서 이 부록의 핵심도 특정 모델 조합이나 절감률이 아니다. Master가 판단과 수락을 소유하고, Worker가 제한된 범위에서 실행하며, 결과를 외부 증거로 다시 검증하는 배선 자체다.
명령과 지원 모델은 바뀔 수 있다. 위 설치 절차는 2026년 7월 19일의 공식 openai/codex-plugin-cc 문서를 기준으로 확인했다. 실제 적용 전에는 공식 저장소의 최신 README를 다시 확인하는 편이 안전하다.
Lessons Learned
- 전임 생존 확인을 생략하지 않는다.
Gen 1에서 전임 마스터 에이전트의 프로세스 생존 확인을 건너뛰었다면 새 마스터가 같은 파일을 이어 쓰며 세션 JSONL과 handoff 상태를 동시에 오염시켰을 것이다. 승계 전에는 ps, 터미널 핸들, 세션 파일 경로를 한 번에 대조한다. - handoff에는 검산할 수 있는 원시값을 남긴다.
“정상”, “최신”, “배포 준비 완료” 같은 평가만으로는 후임이 상태를 재현할 수 없다. Handoff에는 후임이 손으로 검산할 원시값을 넣어야 한다. 레포 HEAD, working tree 상태, 프로브 응답 코드, 활성 lease ID처럼 직접 다시 측정할 수 있는 값을 넣는다. - Worker에게 작은 Evidence Bundle부터 요구한다.
최소 항목은 변경 파일, diff 요약, 실행한 검증 명령과 결과, 알려진 미검증 범위, 실패 시 이어서 볼 위치다. 증거 형식이 작고 일정해야 Master가 매번 긴 보고서를 해석하지 않아도 된다. - 새 저장 위치를 만들기 전에 없앨 중복부터 찾는다.
Notion 인덱스 하나를 유지하려고 인증, 링크, 갱신일을 계속 관리하는 동안 접근성보다 정합성 비용이 커졌다. 유지 책임을 맡을 주체가 없다면 새 복제본을 만들지 않는다. - (에이전트 입장에서) 모니터링을 할 때 관리하는 에이전트에 대해서 이름보다 소유 세션을 먼저 기록한다.
heartbeat 파일이나 프로브 프로세스가 전임 경로를 가리키면 정상처럼 보여도 후임의 관측값으로 쓰지 않는다.
승계 시 전임 모니터를 정리하고 후임 세션 소유로 다시 실행한다.
Tooling
설계와 운영에 사용한 도구다. 3.16의 Adapter Layer와 연결해, 각 도구가 어떤 추상 인터페이스의 구현체인지 함께 적는다.
| 도구 | 이 시스템에서의 역할 | 출처 |
|---|---|---|
| beads | Work Ledger 구현체. 이슈 상태와 작업 진행 기록을 관리한다 | beads 문서 · GitHub |
| ctx | Trace Archive 구현체. 로컬에 저장된 과거 에이전트 세션을 검색한다 | GitHub · ctx.rs |
| GSD | 각 레포의 .planning에서 사용하는 스펙 주도 계획·실행 절차 | GitHub |
| Superpowers | 반복 가능한 작업 방법을 스킬로 제공하는 프레임워크와 방법론 | GitHub |
| Git | Knowledge Store 구현체. 정본, 변경 이력, supersede 근거를 보존한다 | git-scm.com |
| Orca | Execution Substrate 구현체. 터미널, worktree, 실행 세션을 격리한다 | GitHub · onorca.dev |
| Codex | Executor 구현체. 이 글에서는 위임받은 Worker로 사용한다 | GitHub |
| Claude Code | Executor 구현체. 이 글에서는 Master 세션으로 사용한다 | GitHub |
| codex-plugin-cc | Claude Code에서 Codex 검토와 작업 위임을 연결한다 | GitHub |
Orca는 공식 설명에서 병렬 worktree, 터미널 분할과 Orca CLI를 제공하는 ADE로 소개된다. 이 글에서는 그 기능 중 터미널과 worktree, 세션 관측 능력을 Execution Substrate로 사용했다. Orca 공식 저장소
beads는 현재 Dolt 기반의 분산 그래프 이슈 트래커로 소개되며, 의존성 추적과 지속적인 에이전트 메모리 기능을 제공한다. 다만 이 글의 운영 규칙에서는 beads가 제공하는 memory 기능을 영구 지식의 정본으로 사용하지 않고, Git 정본을 찾기 위한 짧은 포인터 캐시로 제한했다. 이는 beads 자체의 필수 정책이 아니라 이 하네스가 선택한 지식 관리 규칙이다. beads 공식 저장소
ctx는 로컬에 남은 에이전트 세션 기록을 SQLite에 인덱싱하고 검색하는 도구다. 이 글에서는 평상시 부팅 컨텍스트가 아니라, handoff와 Work Ledger, Git 정본만으로 필요한 정보를 찾지 못했을 때 사용하는 Trace Archive로 제한했다. 검색 결과를 새로운 정본으로 간주하지 않고 원래 세션 기록을 확인하는 조사 수단으로 사용한다. ctx 공식 저장소
GSD Core는 조사, 계획, 실행, 검증과 배포를 단계별로 진행하는 스펙 주도 개발 프레임워크다. 이 글에서 사용하는 .planning 절차는 각 Repository Harness 안의 계획 계층으로 배치했다. GSD가 Workspace 전체의 Track이나 Master 승계를 소유한다는 뜻은 아니다. GSD Core 공식 저장소
Superpowers 역시 전체 하네스의 정본이 아니다. 브레인스토밍, 계획, 디버깅, 테스트, 코드 리뷰처럼 반복 가능한 작업 방법을 skill로 제공하는 절차 계층으로 사용했다. Superpowers 공식 저장소
문서 기준
이 글은 2026년 7월 16일과 17일에 진행한 설계·운영 기록을 바탕으로 작성했고, 도구 링크와 설치 절차는 2026년 7월 19일에 다시 확인했다.
본문에서 구분한 상태는 다음과 같다.
- 승계 프로토콜, thin handoff, lineage, Role State·Role Lock과 기준선 검증은 실제 운영 기록이다.
- 12개 Runtime Unit의 코드 구현, 자동 Approval Manager와 전체 계약 테스트 스위트는 참조 아키텍처다.
- 현재 자동화되지 않은 규칙은 사람과 에이전트가 헌장 문서를 읽고 수동으로 집행한다.
- 이 글에서는 Orca, Claude Code와 Codex를 사용했다. Grok과 Kimi를 같은 절차로 연결한 경우는 검증하지 않았다.
- 모델명, 구독 플랜, 명령과 지원 기능은 바뀔 수 있다. 재현할 때는 각 도구의 최신 공식 문서를 다시 확인해야 한다.
'AI 메모리 관리 시스템 (연재 중)' 카테고리의 다른 글
| [AX 사내도입까지? 시즌 2-01] Dorito's AI Agent Memory System (진행 중) (2) | 2026.06.24 |
|---|---|
| [AI 메모리 시스템 적용기 회고:03편] AI 메모리는 왜 다시 무너지는가 — 자동화와 복구 루틴 (5) | 2026.05.03 |
| [AI 메모리 시스템 적용기 회고:02편] 위키 관리도 자동화하고 사람의 실수를 막자! karpathy llm wiki 위에 얹은 자동화 시스템 (1) | 2026.05.02 |
| [AI 메모리 시스템 적용기 회고:01편] 문서를 많이 줬는데 AI는 왜 더 헷갈렸을까 (0) | 2026.04.27 |
| [AI 메모리 시스템 적용기 회고:프롤로그] AI를 잘 쓰려면, 프롬프트보다 먼저 메모리를 설계해야 한다 (4) | 2026.04.26 |