# 마스터 라이프사이클

> founding spawn → boot measurement → steady state → clean succession → lineage 기록 루프와 Role State·compaction 규칙.

- Repository: local/mogui-ADE-orchestrator

- Human docs: https://grok-wiki.com/public/docs/local-mogui-ade-orchestrator-97afe791d5ac
- Complete Markdown: https://grok-wiki.com/public/docs/local-mogui-ade-orchestrator-97afe791d5ac/llms-full.txt

## Source Files

- `docs/public/master-lifecycle.md`
- `src/master_runtime/core/bootstrap.py`
- `src/master_runtime/core/bootstrap_live.py`
- `src/master_runtime/core/succession.py`
- `src/master_runtime/core/lineage.py`
- `src/master_runtime/core/recovery.py`
- `master-ops/docs/runbooks/role-state.md`

---

---
title: "마스터 라이프사이클"
description: "founding spawn → boot measurement → steady state → clean succession → lineage 기록 루프와 Role State·compaction 규칙."
---

마스터 세션은 장수(long-lived)하지만 불멸이 아니다. 이 런타임은 마스터를 **운영 lineage의 한 generation**으로 취급한다. 공개 표면은 `scripts/master-succeed`, `scripts/master-bootstrap`, `scripts/master-bootstrap-live`, `scripts/master-recover`, `scripts/model-identity-probe`, `scripts/model-drift-audit`이며, 핵심 구현은 `src/master_runtime/core/`의 bootstrap·succession·recovery·lineage 모듈이다.

## 루프 한눈에

```text
founding spawn → boot measurement → steady state → clean succession → lineage record
```

| 단계 | 목적 | 주 명령 |
| --- | --- | --- |
| Founding spawn | 설치 대화와 Gen 1 세션 분리, 좌석 placement 검증 | `scripts/master-succeed spawn` |
| Boot measurement | charter·handoff·Role State·budget·dual-instance 측정 | `scripts/master-bootstrap`, `scripts/master-bootstrap-live` |
| Steady state | continue-and-compact, 수락 상태 내구성 승격 | `scripts/l1-digest tick`, issue tracker / Git |
| Clean succession | 명시 트리거 → handoff → successor 검증 → retire | `scripts/master-succeed *` |
| Lineage | generation 메타 append-only 기록 (결정 권한 없음) | `append_entry` → `docs/lineage/MASTER-LINEAGE.md` |

```mermaid
flowchart LR
  A[Founding spawn] --> B[Boot measurement]
  B --> C[Steady state]
  C --> D{Succession trigger}
  D -->|NONE / ADVISORY only| C
  D -->|IMMEDIATE + owner path| E[Thin handoff]
  E --> F[Successor verify]
  F --> G[Predecessor retire]
  G --> H[Lineage append]
  H --> B
```

자동 succession은 허용되지 않는다. `detect`가 `ADVISORY`를 내도 spawn을 시작하지 않으며, 명시 지시(`IMMEDIATE`)와 운영 절차가 있어야 한다.

## Founding spawn

첫 실행 절차의 전체 소유권은 온보딩 가이드에 있다. 인스톨러 대화와 Generation 1 마스터 세션을 분리해, 마스터가 **깨끗한 컨텍스트**와 **감사 가능한 placement**로 시작하도록 한다.

### Placement

| 워크스페이스 형태 | 마스터 좌석 | Selector 형태 |
| --- | --- | --- |
| Multi-repository | workspace root의 folder workspace | `id:folder:<uuid>` |
| Single repository | primary worktree | 해당 worktree selector |

Multi-repository 안의 repository worktree는 **워커 좌석**이다. 마스터를 그 자리에 두면 placement 사고다.

### Spawn 진입점

실제 spawn 진입점은 `scripts/master-succeed spawn`이다. dry-run으로 호스트 명령을 먼저 확인한다.

```bash
scripts/master-succeed spawn \
  --workspace-selector "id:folder:<uuid>" \
  --kickoff-text "Founding master boot" \
  --root . \
  --model example-model \
  --title "Founding master boot" \
  --json \
  --dry-run
```

| 옵션 | 역할 |
| --- | --- |
| `--workspace-selector` | 생성 대상 worktree / folder workspace (필수) |
| `--kickoff-text` / `--kickoff-file` | 상호 배타, 하나 필수 |
| `--root` | 에이전트 cwd (필수) |
| `--title` | pane title (필수) |
| `--model` | 런치 모델 플래그 |
| `--agent` | 기본 `claude`; `grok`, `codex`, 커스텀 실행 파일명 가능 |
| `--expected-placement` | 독립 기대 worktree id; 불일치 시 exit **26** (`SPAWN_PLACEMENT_MISMATCH`) |
| `--dry-run` | 생성 없이 명령 스냅샷만 |

### Fail-closed 검증

호스트가 managed terminal 생성을 지원하면 non-dry-run spawn은:

1. 반환 worktree id가 요청 selector와 일치하는지 확인한다. 불일치 시 fail-closed이며, 가능하면 방금 만든 터미널을 닫는다.
2. 반환 handle이 **live**인지 확인한다. 생성 전 terminal list 스냅샷 → 생성 → 재조회.
3. 보고된 handle이 live·new·요청 worktree 안이면 `MATCH`.
4. 그렇지 않으면 요청 worktree에서 **요청 pane title을 가진 새 터미널이 정확히 하나**일 때만 대체 handle을 채택하고 `MATCH_REISSUED` / `handle_reissued=true`로 보고한다.
5. 후보 0개 또는 2개 이상은 fail-closed. 이때 생성된 터미널이 관리되지 않은 채 남을 수 있으므로, 재시도 전 호스트 terminal list로 조정한다.

관련 exit 상수: `SPAWN_CREATE_ERROR` 20, `SPAWN_PARSE_ERROR` 21, `SPAWN_WORKTREE_MISMATCH` 22, `SPAWN_CLOSE_ERROR` 23, `SPAWN_HANDLE_STALE` 24, `SPAWN_LIST_ERROR` 25, `SPAWN_PLACEMENT_MISMATCH` 26.

## Boot measurement

Boot는 추측이 아니라 **측정**이다. Charter(필수), optional handoff, Role State, budget 사용량, dual-instance 경고를 한 스냅샷으로 읽는다.

### `master-bootstrap` (측정 스냅샷)

```bash
scripts/master-bootstrap \
  --charter master-ops/docs/MASTER-OPERATIONS.md \
  --handoff ./handoffs/latest.md \
  --session-id example-session \
  --json
```

| 플래그 | 기본 | 의미 |
| --- | --- | --- |
| `--charter` | (필수) | L0 본문 소스 |
| `--handoff` | 없음 | L1 + Role State 소스 |
| `--budget` | `24000` | L0 우선 적재 후 잔여를 L1에 |
| `--session-id` | 없음 | dual-instance 프로브 키 |
| `--strict-lease` | off | `DUAL_INSTANCE:*` 있으면 `BootstrapError` (exit 2) |
| `--json` | off | `BootstrapResult` 직렬화 |

적재 순서:

1. Charter 전체 읽기 (없으면 fail).
2. Handoff가 있으면 Role State 파싱; 블록 없으면 `ROLE_STATE_MISSING`, 파일 없으면 `HANDOFF_MISSING`.
3. L0 = charter를 budget에 맞춤. 잘리면 `BUDGET_TRUNCATED:L0` + `[TRUNCATED:BOOTSTRAP_BUDGET_EXCEEDED]`.
4. 잔여 budget으로 L1 = handoff. 잘리면 `BUDGET_TRUNCATED:L1` + `[TRUNCATED:L1_BUDGET_EXCEEDED]`.
5. `session_id`가 있으면 프로세스 목록에서 동일 session id를 담은 `claude` 명령을 찾고, 자기 PID를 제외한 중복에 `DUAL_INSTANCE:<pid>`를 붙인다.

### `master-bootstrap-live` (SessionStart 배선)

라이브 부트는 세션 시작 훅용이다. 메모리 본문을 재발행하지 않고, ~1KB self-block과 audit 라인만 낸다. 내부 예외는 `[BOOTSTRAP-FALLBACK] …` 한 줄로 접어 **부트를 죽이지 않는다**.

```bash
scripts/master-bootstrap-live \
  --handoff-dir ./handoffs \
  --role-state-file master-ops/docs/runbooks/role-state.md
```

| 동작 | 규칙 |
| --- | --- |
| Role State 로드 | `--role-state-file` 우선, 실패 시 handoff dir의 사전순 최대 `*.md` |
| Tracks | `bd` 수집, self-block cap **1000** chars (tracks 우선 절단) |
| `bd prime --memories-only` | 본문 재출력 금지; L0/L1/untagged 카운트 audit만 |
| Dual-instance | 동일 프로브, `[DUAL-INSTANCE] none` 또는 경고 목록 |
| Charter pointer | `--charter-pointer` → `CHARTER_POINTER` env → 워크스페이스 중립 기본 문구 |
| Memory budget 기본 | **12000** chars |

### 모델 신원 측정

런치 플래그의 모델과 **세션이 실제로 쓰는 모델**은 분리한다. 측정 불가면 unavailable로 보고하고, 플래그로 추론하지 않는다.

```bash
# 최근 턴 샘플 — 지금 무엇인가
scripts/model-identity-probe \
  --transcript ./sessions/example-session.jsonl \
  --expect example-model

# 전체 트랜스크립트 — 중간에 바뀌었는가
scripts/model-drift-audit \
  --transcript ./sessions/example-session.jsonl \
  --expect example-model
```

| Exit | 의미 |
| --- | --- |
| 0 | 전이 없음 / 기대와 일치 (도구별 계약) |
| 1 | 전이 또는 기대 불일치 |
| 2 | undecidable (파싱 불가·스키마 불명) — pass로 접지 말 것 |

트랜스크립트 워커가 읽는 스키마는 빌드 대상(예: Claude Code JSONL)에 묶인다. Codex 등 다른 저장 형태는 exit 2 → **unsupported**로 보고한다. CLI 간 portable 키는 process argv의 **session id**이며, revival 스캔도 이 키를 쓴다.

Boot 측정은 **한 순간의 스냅샷**이다. 재측정 시점은 workspace master-operations 문서가 정한다. 현장 원인에는 미전파 런치 플래그뿐 아니라 quota·credit 소진 중 모델 전환이 포함되며, 선언 모델과 측정 모델이 어긋난 generation이 succession 감사에서야 발견된 사례가 있다. 안전한 대응: 측정값을 기록하고, 필요 시 민감 레인에서 마스터를 빼고, 신뢰할 수 없으면 clean successor를 연다.

## Role State

Role State는 handoff(또는 `role-state.md`)의 고정 필드 블록이다. Bootstrap 파서는 `## Role State` 근처 fenced block 또는 `Current Role:`…`Unlock:` 폴백을 읽는다.

캐논 템플릿 (`master-ops/docs/runbooks/role-state.md`):

```text
Current Role: (not booted; declare on first master start)
Role Lock: ENABLED
Frozen: all other roles
Unlock: explicit user instruction only
```

| 필드 | 허용 값 / 규칙 |
| --- | --- |
| `Current Role` | `Architecture`, `Research`, `Reference Implementation`, `Feature Implementation`, `Release / Operations`, `Incident Response`, `Maintenance` 만 |
| `Role Lock` | `ENABLED` / `DISABLED` (그 외 `BootstrapError`) |
| `Frozen` | 보통 `all other roles` |
| `Unlock` | 보통 `explicit user instruction only` |
| Generation | 0 → 첫 부트 시 1; 역할 전환은 Proposal→Approval 직후 또는 succession boot 때만 |
| 감사 | Git history가 transition audit trail |

Succession handoff 작성 시 `freeze_roles`가 현재 역할만 남기고 lock을 `ENABLED`로 고정한다. 필수 필드 누락·알 수 없는 역할은 bootstrap이 예외로 거부한다.

**역할 침식 함정:** 마스터가 대상 저장소의 agent instruction 파일을 읽은 뒤 그 저장소의 paired developer 역할을 함께 주장하는 구조적 유인. 대상 repo 지침은 **조정 대상에 대한 지식**이며, 그 역할 채택은 금지. 운영 규칙은 workspace master-operations에 둔다.

## Steady state (continue-and-compact)

정상 운영은 continue-and-compact다. 컨텍스트 압력이 급해지기 **전에** 수락된 지식, active tracks, open decisions를 issue tracker 또는 Git 등 **내구성 저장소**로 승격한다. Compaction·clear 직후에는 issue-tracker 컨텍스트를 다시 읽고 active tracks를 재확인한다.

| 표면 | 역할 |
| --- | --- |
| `scripts/master-bootstrap-live` | 세션 시작 시 bounded Role State / tracks / audit |
| `scripts/l1-digest tick --config …` | repo·ledger·job log·process pattern 관찰 후 digest 기록 (작업·acceptance 자체는 외부) |
| issue tracker / Git | 승격된 SSOT; 휘발 context만 잃도록 |

의도적 context-limit 실험에서 마스터는 한도 근처까지 조정을 이어갔지만, 다음 compacted 턴에서 회상·훅 커버 공백이 드러났다. 교훈: full window가 안전하다는 뜻이 아니라, 압력은 측정하고, 수락 상태는 이미 내구성 저장소에 있어야 하며, compaction vs succession은 낙관이 아니라 증거로 고른다.

사고 복구(프로세스 사망, 호스트 재시작, stale UI handle, 실수 pane 닫힘)는 succession이 아니다. 동일 session의 중복 live 프로세스가 없음을 증명한 뒤 same-session resume을 먼저 시도한다 (`master-ops/docs/runbooks/succession-boot-card.md`).

## Clean succession

### 트리거 분류

```bash
scripts/master-succeed detect \
  "succession now" \
  --context-ratio 0.65 \
  --json
```

| Status | 조건 | 자동 spawn |
| --- | --- | --- |
| `IMMEDIATE` | 문구 포함: `succession now`, `handoff to successor`, `승계해줘`, `다음 마스터로 넘기자`, `승계 진행해` | 아니오 — 절차 시작 신호일 뿐 |
| `ADVISORY` | `context_ratio >= 0.60` 또는 `milestone` 비어 있지 않음 | 아니오 — propose only |
| `NONE` | 위 아님 | — |

### 절차

<Steps>
  <Step title="Promotion audit">
    현재 마스터가 수락 지식·active tracks·open decisions·미해결 acceptance 증거를 내구성 저장소로 올린다. audit 없이 successor를 spawn하지 않는다.
  </Step>
  <Step title="Thin handoff 작성">
    ```bash
    scripts/master-succeed handoff --spec ./ops/handoff-spec.json --json
    ```
    출력 섹션: Role State (frozen), Current Objective, Active/Open Tracks, Accepted Artifacts, Deferred Work, Open Questions, Recommended Next Role, Observed Baseline.
  </Step>
  <Step title="Successor spawn">
    founding과 동일하게 `spawn` + placement 검증. kickoff·model·root·title 명시. Boot card: successor cwd는 workspace root 또는 승인된 orchestrator root.
  </Step>
  <Step title="Recovery 측정 + verify-successor">
    `scripts/master-recover`가 Recovery Flow 0–6을 **읽기 전용**으로 실행한다 (파일 쓰기·프로세스 변이 없음). 보고 형태를 검증:

    ```bash
    scripts/master-succeed verify-successor \
      --report ./ops/recovery-report.json \
      --json
    ```

    | 판정 | 조건 |
    | --- | --- |
    | `FAILED` | 어떤 step status라도 `MISS` |
    | `PASS` | open tracks 낭독(step 6 OK) + baseline(step 2-3 OK/없음) + monitors rearmed(step 5 OK) 세 체크 |
    | `PARTIAL` | 일부 체크만 |
  </Step>
  <Step title="Predecessor retire (handshake 후)">
    검증 후에만 retire. Freeze ≠ retirement. `scripts/master-succeed retire`는 후보 정확히 1개, self-handle 거부, 기본 dry-run, pane 생존 시 거부.
  </Step>
  <Step title="Lineage append">
    검증·retirement 결과를 `docs/lineage/MASTER-LINEAGE.md`에 append. lineage로 다음 행동을 결정하지 않는다.
  </Step>
</Steps>

### Placement evidence three-set (boot card)

1. host pane / worktree selector가 의도 workspace와 일치
2. process cwd가 workspace root 아래
3. session artifact / log path가 기대 namespace

UI pane title·status line은 **힌트**이지 placement 증거가 아니다.

## Retirement handshake

Retirement는 두 live 에이전트 사이의 teardown이다. 도구의 `close`만 호출하는 것은 TCP `RST`에 가깝다 — 에이전트 합의 없이 unflushed 작업을 잃는 경로이며, owner 승인 없이 쓰지 않는다.

| TCP | Master retirement | 행위자 |
| --- | --- | --- |
| `FIN →` | 작업 수락 중지·flush 지시 | successor |
| `← ACK` | 인지 후 CLOSE_WAIT | predecessor |
| half-close | send 측 유지: commit·보고 가능 | predecessor |
| `← FIN` | 합의된 FIN 한 줄, 이후 무출력 | predecessor |
| `ACK →` | 수신 확인 | successor |
| TIME_WAIT | 호스트 last-output + pane read로 quiet 측정 | successor |
| `CLOSED` | `retire --execute` + 삼중 disappearance | successor |
| `RST` | 합의 없는 abortive close | successor (owner 승인) |

CLOSE_WAIT에서 predecessor는:

1. 신규 dispatch 없음  
2. successor가 drain할 peer-mailbox ack 없음 (또는 양쪽 이중 drain)  
3. orchestration에 추가 송신 없음 — pane close가 Run binding 해제  
4. uncommitted 상태 commit, 불가 시 경로·내용 보고  
5. 소유 live worker와 미완료 track 이름 나열  
6. 합의 FIN 한 줄만 출력  

FIN은 idle 상태 live prompt에 전달한다. mailbox만 쓰고 idle 에이전트가 안 읽으면 배달이 아니다. send 성공 ≠ 소비 — pane 읽기로 확인. FIN 마커는 successor 지시 문자열에 그대로 들어가면 안 된다(또는 출현 횟수 ≥ 2 요구).

TIME_WAIT: handle 회전·transcript replay 중 dual process가 있을 수 있다. FIN 직후 즉시 close하면 재생성 중인 pane을 닫을 수 있다.

```bash
scripts/master-succeed retire \
  --self-handle <successor-handle> \
  --target-handle <predecessor-handle> \
  --target-pid <measured-pid> \
  --target-tty <measured-tty> \
  --json \
  --execute
```

Folder-workspace pane은 host list에서 `process_id: null`인 경우가 많다. pid·tty는 호출자가 측정해 넘긴다. 도구가 null 레코드에서 pid를 지어내지 않는다.

| `disappearances` 값 | 의미 |
| --- | --- |
| `measured` | 해당 축 소멸 확인 |
| `still_present` | 잔존 → 전체 `REFUSED` |
| `skipped:…` | 측정 입력 없음 |

| Status | 조건 |
| --- | --- |
| `DRY_RUN` | `--execute` 없음 |
| `REFUSED` | 후보 0/다수, self match, still_present, pane 미측정 |
| `CLOSED` | pane·process·tty 모두 `measured` |
| `CLOSED_PARTIAL` | pane `measured`, still_present 없음, process/tty 중 skip |

CLOSE 명령 반환값만으로 완료를 판단하지 않는다. Full `CLOSED` 전 predecessor scratchpad를 비-git 내구성 위치에 복사하고 trunk와 diff 판정을 남긴다.

### Revival

동결된 세션은 에이전트 CLI가 도는 어떤 터미널(폰·원격 포함)에서도 resume 가능하다. 측정 사고: 은퇴 마스터 4개가 모바일 resume으로 동시 부활. Boot card 규칙:

1. boot 시 및 owner가 stray를 보고할 때, `MASTER-LINEAGE.md`의 session id를 **process argv**에서 스캔  
2. hit 시: 동결 이후 활동 읽기 → 미응답 owner 지시 회수 → 에이전트 종료 → host terminal chain hangup → tty 소멸 확인  
3. 동일 삼중 disappearance로 닫기  

Handoff 문구의 “predecessor gone”과 runtime state를 분리한다. 클린 succession = handoff 읽기만이 아니라 role·track·process ownership·verification 책임의 측정된 이전.

## Lineage

Lineage는 **append-only observability**다. bootstrap 소스가 아니고 runtime 결정 입력이 아니다. 공개 규칙: 검증 후 append, 다음 행동 권한으로 쓰지 않음.

`append_entry(path, entry)` 필수 필드:

| 필드 | 타입 / 제약 |
| --- | --- |
| `generation` | non-negative int; 동일 generation 재기록 거부 |
| `parent_session` | str |
| `successor_session` | str |
| `timestamp` | str |
| `inherited_role` | str |
| `succession_reason` | str |
| `recovery_sources` | str |
| `inherited_open_tracks` | str |
| `verification` | `PASS` \| `PARTIAL` \| `FAILED` |
| `repeated_question_count` | non-negative int |
| `reopened_decision_count` | non-negative int |
| `context_loss_summary` | str |
| `predecessor_retirement_verified` | str |
| `notes` | optional str |

쓰기는 원본 bytes + 새 섹션 동등성 검사; 실패 시 원본 복구 후 `LineageAppendError`. 렌더 형태: `## Gen <n> — <timestamp>` 마크다운 섹션.

## 공개 CLI 요약

| 명령 | 하위 명령 / 용도 |
| --- | --- |
| `scripts/master-succeed` | `detect`, `handoff`, `verify-successor`, `check-duplicates`, `retire`, `spawn` |
| `scripts/master-bootstrap` | L0/L1 budgeted snapshot + Role State + dual-instance |
| `scripts/master-bootstrap-live` | SessionStart bounded block, fail-open fallback |
| `scripts/master-recover` | Recovery Flow 0–6 read-only report |
| `scripts/model-identity-probe` | 최근 턴 모델 측정 |
| `scripts/model-drift-audit` | 전체 트랜스크립트 모델 전이 감사 |
| `scripts/l1-digest` | 관찰 전용 L1 digest loop |

공통: 대부분 `--json` 지원. 하드 가드 위반은 exit **2** 계열 (`SuccessionError`, `BootstrapError`). Spawn placement mismatch는 **26**.

## 실패 모드 체크리스트

| 증상 | 우선 확인 |
| --- | --- |
| `SPAWN_PLACEMENT_MISMATCH` / exit 26 | selector vs 생성 worktree; multi-repo에서 worker worktree에 앉혔는지 |
| `MATCH_REISSUED` / 미해결 handle | title 유일성; orphan terminal list 정리 후 재시도 |
| `DUAL_INSTANCE:*` / strict-lease fail | 동일 session id 프로세스; `check-duplicates` |
| `ROLE_STATE_MISSING` / step 0 WARN | handoff Role State 블록 필드 네 개 |
| model probe exit 2 | 에이전트 transcript 스키마 unsupported → unavailable 보고, 추측 금지 |
| `CLOSED_PARTIAL` | `--target-pid` / `--target-tty` 측정 후 재실행 |
| `still_present` after retire | TIME_WAIT·동의 경로 재확인; RST는 owner 승인 |
| 은퇴 후 세션 재개 | lineage session id revival 스캔 |
| 역할 이중 주장 | 대상 repo AGENTS/Claude 지침을 역할로 채택했는지 |

## Related pages

<CardGroup cols={2}>
  <Card title="프로그레시브 온보딩" href="/onboarding">
    ONBOARDING 라우터, founding spawn, Stage 1/2, 1회 1로드 Verify
  </Card>
  <Card title="Orca 객체 모델" href="/orca-object-model">
    project·folder workspace·worktree·terminal·Run, 마스터 좌석, selector
  </Card>
  <Card title="Clean succession" href="/succession">
    handoff·placement·verify-successor·retire·revival·lineage 필드 상세
  </Card>
  <Card title="master-succeed 레퍼런스" href="/succession-cli-reference">
    하위 명령 옵션, exit 코드, SPAWN_PLACEMENT_MISMATCH, JSON 출력
  </Card>
  <Card title="런타임 유닛" href="/runtime-units">
    U1–U12, L0/L1, bootstrap·dispatch·succession·lineage 대응
  </Card>
  <Card title="방어 인벤토리" href="/defense-inventory">
    placement·empty-seat·duplicate·revival·onboarding 가드 표
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    placement mismatch, undecidable exit 2, seat 중복, revival 복구
  </Card>
  <Card title="Quickstart" href="/quickstart">
    Gen 1 부트부터 첫 supervised worker까지 최단 경로
  </Card>
</CardGroup>
