# Troubleshooting

> preflight BLOCKED, placement mismatch, MODEL_PROBE_FAILED, undecidable exit 2, seat 중복, revival, 복구 프로브.

- 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/defense-inventory.md`
- `src/master_runtime/core/recovery.py`
- `scripts/master-recover`
- `scripts/model-identity-probe`
- `scripts/model-drift-audit`
- `master-ops/docs/runbooks/succession-boot-card.md`
- `master-ops/docs/runbooks/error-and-logging.md`
- `tests/test_recovery.py`

---

---
title: "Troubleshooting"
description: "preflight BLOCKED, placement mismatch, MODEL_PROBE_FAILED, undecidable exit 2, seat 중복, revival, 복구 프로브."
---

런타임 장애는 `scripts/onboarding-preflight.sh`, `scripts/master-succeed`, `scripts/dispatch-gate`, `scripts/model-identity-probe`, `scripts/model-drift-audit`, `scripts/master-recover`, 그리고 `master-ops/docs/runbooks/succession-boot-card.md`의 측정 가능한 exit·reason code로 표면화된다. 가드는 확인 불가 상태를 통과로 접지 않으며, exit `2`(undecidable)·`MODEL_PROBE_FAILED`·`SPAWN_PLACEMENT_MISMATCH`(26)는 “성공 아님”으로 기록된다.

## 증상 → 명령 빠른 표

| 증상 | 우선 명령 | 핵심 신호 |
| --- | --- | --- |
| 온보딩 전 FAIL 누적 | `bash scripts/onboarding-preflight.sh` | 요약 `BLOCKED`, process exit `1` |
| 마스터가 잘못된 worktree에 앉음 | `scripts/master-succeed spawn --expected-placement …` | exit `26`, `SPAWN_PLACEMENT_MISMATCH` |
| register 시 모델 검증 실패 | `dispatch-gate register --model-probe-cmd …` | ledger reason `MODEL_PROBE_FAILED` (경고, register는 계속) |
| 최근 턴 모델 드리프트 / 판독 불가 | `scripts/model-identity-probe` | `MODEL-PROBE DRIFT:…`, exit `2` |
| 세션 전체 모델 전환 감사 | `scripts/model-drift-audit` | exit `0` 무전환 / `1` 전환·불일치 / `2` undecidable |
| succession 후 좌석 중복 | `scripts/master-succeed check-duplicates --self-handle … --marker …` | `duplicates` 비어 있지 않음; 인자 누락·introspect 실패 시 exit `2` |
| 은퇴 세션 부활 | lineage session id + process/tty 측정 | process·pane·tty 세 소멸이 측정돼야 retire 완료 |
| 비정상 종료 후 상태 복원 프로브 | `scripts/master-recover --charter … --handoff …` | Recovery Flow 0–6, step status `OK`/`MISS`/`WARN`/`SKIP` (항상 exit `0`) |
| redaction 범위 불명 | `scripts/redaction-scan.sh` | exit `2` cannot decide (`REDACTION_REQUIRE_EXTRA=1` 포함) |

## Preflight BLOCKED

`scripts/onboarding-preflight.sh`는 읽기 전용 필수 체크를 누적한다. FAIL이 하나라도 있으면 요약에 `BLOCKED: fix every FAIL before onboarding`을 찍고 **exit 1**로 끝난다. FAIL이 없으면 `READY`, waiver만 있으면 `READY WITH WAIVERS`.

### 자주 보는 FAIL 라벨

| 라벨 | 의미 | 복구 방향 |
| --- | --- | --- |
| `orca` | CLI 부재·비지원 basename·`status --json`이 `ok:true`가 아님 | `orca` / `orca-dev` / `orca-ide` 노출, Settings에서 Shell command 활성화 후 재측정 |
| `orchestration` | legacy read-only, Run unbound(`run: null`), RPC 불가 | `orca orchestration run-create`로 non-legacy Run 바인딩. 앱 재시작만으로는 legacy coordinator가 안 풀림 |
| `skills` | `orca-cli`·`orchestration` skill 아티팩트 부재 | 글로벌 skill 설치/갱신 후 `--fix` 또는 수동 설치 |
| `redaction-extra` | 조직 규칙 파일 없음·비어 있음·malformed | 규칙 파일을 채워 로드 가능한 규칙 ≥1 확보 |
| `bd` / agent CLI / `gh` 등 | PATH·ops repo·자격 범위 | 해당 바이너리·인증 상태 수정 (`gh` 미인증은 보통 WARN) |

```console
$ cd "{{RUNTIME_ROOT}}"
$ ORCA_AGENT_CLI="<agent-cli>" bash scripts/onboarding-preflight.sh
```

<Warning>
필수 체크를 통째로 건너뛰지 않는다. 한 체크만 합법적으로 완화할 때는 `PREFLIGHT_WAIVE=<check-label>`(쉼표 구분)로 FAIL→인쇄된 waiver로 내린다. 오타 waiver는 매칭되지 않으며 해당 체크는 계속 강제된다.
</Warning>

### Orchestration 함정

| 측정 상태 | 동작 | 조치 |
| --- | --- | --- |
| `legacy_read_only` | 읽기는 응답, 쓰기는 `effectsApplied:false`로 드롭 | 새 Run 생성 |
| unbound / `run_required` | task family 실패 | `run-create` 후 preflight 재실행 |
| binding drop 후 `count:0` | 빈 mailbox와 동일하게 보임 | Run 재바인딩 후 재측정 |

`gitleaks`·`ctx` 부재는 preflight에서 **WARN**(마스터 기동을 막지 않음). 다만 publish 경로의 redaction 엔진 부재는 게이트 exit `2`로 이어진다.

## Placement mismatch (`SPAWN_PLACEMENT_MISMATCH` = 26)

`scripts/master-succeed spawn --expected-placement <worktree-id>`는 생성 후 실제 worktree를 요청 selector·독립 expected placement와 비교한다. 불일치 시 터미널 정리 시도 후 **exit 26**.

관련 spawn exit:

| 코드 | 상수 | 의미 |
| --- | --- | --- |
| 20 | `SPAWN_CREATE_ERROR` | create 실패 |
| 21 | `SPAWN_PARSE_ERROR` | spawn JSON 파싱 실패 |
| 22 | `SPAWN_WORKTREE_MISMATCH` | 요청 vs 실제 worktree |
| 23 | `SPAWN_CLOSE_ERROR` | close 실패 |
| 24 | `SPAWN_HANDLE_STALE` | 보고 handle을 live로 신뢰 불가 |
| 25 | `SPAWN_LIST_ERROR` | terminal list 실패 |
| 26 | `SPAWN_PLACEMENT_MISMATCH` | expected placement vs 실제 |

### Placement evidence three-set

`master-ops/docs/runbooks/succession-boot-card.md` 기준, UI 제목·status line은 증거가 아니다.

1. host pane/worktree selector = 의도한 workspace  
2. process cwd ⊆ workspace root  
3. session artifact/log path ∈ 예상 namespace  

```console
$ scripts/master-succeed spawn \
    --expected-placement "<workspace-folder-selector>" \
    # … selector, kickoff, model 등 호스트 인자
```

<Check>
복구: 저장소 worktree가 아닌 **workspace folder seat** selector인지 확인 → 잘못된 터미널 close/reconcile (`orca terminal list`) → expected placement를 독립 측정값으로 다시 공급 → spawn 재시도.
</Check>

## `MODEL_PROBE_FAILED`와 모델 프로브

### `register` 경로

`scripts/dispatch-gate register --model-probe-cmd …`가 프로브 실패·빈 결과·비정상 exit를 만나면 ledger에 `MODEL_PROBE_FAILED`를 **경고**로 남기고 등록은 계속한다(모델 보고 불가 런타임을 강제 off 하지 않기 위함). ledger 필드: `model_declared`, `model_measured`, `model_verified`.

| reason | 효과 |
| --- | --- |
| `MODEL_PROBE_FAILED` | 경고, register 유지 |
| `MODEL_UNVERIFIED` | 선언/측정 부재 경고 |
| `MODEL_MISMATCH` | 선언≠측정 기록 |
| `MODEL_TIER_ESCALATION` | **deny** (상향 티어 측정) |

신규 워커 세션 파일이 아직 없을 때 첫 `register`가 `MODEL_PROBE_FAILED`를 내는 것은 의도된 열화이며, 검증 성공 위장이 아니다.

### `model-identity-probe` (최근 턴)

```console
$ scripts/model-identity-probe --transcript <jsonl> --expect <model>
$ scripts/model-identity-probe   # MOGUI_TRANSCRIPT_GLOB 또는 instance-runtime transcript_glob
```

| 출력 / exit | 의미 |
| --- | --- |
| `MODEL-PROBE OK …` / 0 | 최근 assistant 모델이 `--expect`와 일치 |
| `MODEL-PROBE INFO … nothing asserted` / 0 | expect 없음 — 측정만, 단언 없음 |
| `MODEL-PROBE DRIFT:…` / **2** | 드리프트 또는 undecidable (transcript 부재·JSONL 오류·설정 누락·limit&lt;1) |

해석 순서: `--transcript` → `MOGUI_TRANSCRIPT_GLOB` → `INSTANCE_RUNTIME_CONFIG` / `config/instance-runtime.json`의 runtime `transcript_glob` (최신 mtime 매치). 기본 expect 모델은 하드코딩되지 않는다 (`--expect` 또는 `MODEL_IDENTITY_EXPECT`).

### `model-drift-audit` (전체 세션)

최근 10턴만 보면 중간 전환이 가려진다. succession 감사는 전체 transcript walk를 사용한다.

| exit | 의미 |
| --- | --- |
| 0 | 단일 모델, 전환 없음 |
| 1 | 전환 발견 또는 `--expect` 불일치 |
| **2** | undecidable: transcript 없음·비가독·assistant turn 0·unresolved model only |

```console
$ scripts/model-drift-audit --transcript <path>
$ scripts/model-drift-audit --transcript <path> --expect <model> --json
```

환경 대체: `MODEL_DRIFT_EXPECT`, `MODEL_DRIFT_PROJECTS_DIR`, `MODEL_DRIFT_WORKSPACE_DIR`.

<Warning>
exit `2`를 exit `0`처럼 읽지 않는다. “검사 불가”와 “문제 없음”은 분리된 계약이다. 동일 규칙은 redaction-scan/inventory에도 적용된다.
</Warning>

## Undecidable exit 2 패턴

| 표면 | exit 2 의미 | 통과 위장 여부 |
| --- | --- | --- |
| `model-identity-probe` | drift 또는 판독 불가 | 없음 (`MODEL-PROBE DRIFT`) |
| `model-drift-audit` | undecidable | 없음 |
| `redaction-scan` / `redaction-inventory` | cannot decide (규칙 부재 포함) | 없음; coverage 출력 |
| `master-succeed check-duplicates` | `SuccessionError` (인자·introspect) | 스캔 생략, 조용한 빈 결과 아님 |
| ledger append 권한 등 | 기록 실패 경로 | 환경에 따라 2 또는 실패 |

벤더 세션 경로/포맷 변경 시 가드는 false pass 대신 위 열화로 떨어진다.

## Seat 중복 (empty seat + runtime)

### Founding empty-seat

`master-ops/onboarding/09-spawn.md`: spawn 전 seat의 terminal 수가 **0**이어야 한다.

```console
$ orca terminal list --worktree <selector> --json
```

잔여 seat-check·이전 마스터 터미널이 있으면 hard stop. list 실패·malformed JSON이면 점유를 증명할 수 없어 spawn 거부.

### Runtime `check-duplicates`

```console
$ scripts/master-succeed check-duplicates \
    --self-handle <current-handle> \
    --marker <session-marker>
```

`detect_duplicate_instances`가 `--self-handle`을 제외한 same-marker 세션을 반환한다. 비어 있지 않으면 **finding**(soft warning 아님). 필수 인자 누락·Orca introspect 불가는 exit `2`.

<Check>
중복 시: 어느 handle이 현 마스터인지 확정 → 선임을 retire(아래 revival 측정) → 동일 세션 double-start 금지 → 재스캔.
</Check>

## Revival (은퇴 세션 부활)

동결 세션은 전화·원격 포함 어떤 터미널에서도 재개 가능하다. 측정 사고: 은퇴 마스터 4개가 모바일 resume으로 동시 부활.

### Retire 완료 조건 (세 소멸)

close 명령 반환값이 아니라 측정이 결정한다.

1. **process** — pid 소멸  
2. **pane** — host terminal list에 live handle 없음  
3. **tty** — device·login chain 소멸  

`retire`의 `CLOSED`는 세 소멸 전부. process/tty 스킵이 있으면 `CLOSED_PARTIAL`.

### Boot / 신고 시 절차

1. `docs/lineage/MASTER-LINEAGE.md`의 session id로 실행 중 agent process argv 스캔 (CLI 플래그가 아니라 **session id**가 이식 키).  
2. 히트 시: 동결 이후 활동(도구 호출·repo 쓰기) 확인 → 미응답 owner 지시 회수 → agent process 종료 → hosting tty chain hang-up → tty 소멸 확인.  
3. lineage id 미기록·다른 머신·process introspect 불가면 탐지가 약해질 수 있으나, 그 경우에도 false pass로 “부활 없음”을 단언하지 않는다.

프로세스 사망·호스트 재시작·stale UI handle은 succession이 아니다. live 중복 process가 없음을 증명한 뒤 same-session resume을 먼저 시도한다.

## 복구 프로브 (`master-recover`)

비정상 종료 후 **쓰기·프로세스 변이 없이** Recovery Flow 0–6을 실행한다. 구현: `src/master_runtime/core/recovery.py`, CLI: `scripts/master-recover`.

```console
$ scripts/master-recover \
    --charter <path> \
    --handoff <path> \
    [--ledger <jsonl>] \
    [--repo <path>]… \
    [--monitor-pattern <pgrep>]… \
    [--session-id <id>] \
    [--json]
```

CLI는 리포트 출력 후 **항상 exit 0**. 판단은 step `status` 필드로 한다.

| step | 내용 | 대표 상태 |
| --- | --- | --- |
| `0` | charter 존재 + bootstrap → Role State | `MISS`(charter/bootstrap 실패) 시 이후 fail-closed `SKIP` |
| `1` | handoff 본문 + `Current Role:` / `Role Lock:` | 부재 `MISS`, Role block 누락 `WARN` |
| `1-ledger` | active tracks (ledger 없으면 `SKIP`) | warnings 시 `WARN` |
| `2-3` | repo `git` HEAD/branch/dirty 관찰 | non-git → `WARN` |
| `4` | miss 수집; Trace Archive 검색은 **수동** | 항상 manual_actions 포함 |
| `5` | monitor pgrep; 실행 중 매치 시 takeover 후 재장전 안내 | 매치/`pgrep` 실패 → `WARN` |
| `6` | successor 검증 체크리스트 (active tracks 낭독, PID 비교, lineage append) | status `OK` + manual_actions |

step 0 `MISS`면 step 1/2–3/5는 `SKIP` (`fail-closed after step 0 MISS`). `DUAL_INSTANCE:` bootstrap warning은 manual_actions로 승격된다.

텍스트 모드 예:

```text
0 OK: charter exists; Role State restored: …
1 OK: handoff exists; Role State block present; body present
1-ledger OK: active tracks=1
2-3 OK: …
4 OK: no misses collected; Trace Archive search is manual
5 OK: …
6 OK: successor verification checklist generated
```

## 로깅 경계 (진단 시)

| 로그 | 경로 | 용도 |
| --- | --- | --- |
| hook-fire | `~/.mogui/hook-fire-log.jsonl` | hook 수명주기; `hook-coverage-report` 호환 |
| event | `~/.mogui/event-log.jsonl` | 결정 이벤트 (`ts`, `level`, `event`, `outcome`, `reason`, …) |

`mg_emit`은 fail-open: 로그 append 실패가 guard 결정을 바꾸지 않는다. 이벤트에 raw command·절대경로·자격증명을 넣지 않는다.

## 운영 체크리스트

<Steps>
  <Step title="표면 신호 고정">
    preflight 요약 줄, spawn exit 코드, ledger `reason`, `MODEL-PROBE`/`model-drift-audit` 한 줄, `check-duplicates` JSON을 먼저 확보한다.
  </Step>
  <Step title="계약 표면 vs 벤더 내부">
    스크립트 exit·`orca` 서브커맨드는 계약 표면이다. 세션 파일 위치/스키마는 벤더 내부라 깨지면 exit 2 / `MODEL_PROBE_FAILED`로 열화한다 — 통과로 해석하지 않는다.
  </Step>
  <Step title="좌석·배치 재측정">
    terminal list, cwd, session artifact, lineage session id process 스캔을 독립적으로 다시 잰다. UI 라벨만으로 판단하지 않는다.
  </Step>
  <Step title="복구 프로브 후 수동 항목">
    `master-recover` JSON의 `manual_actions`·`active_tracks`를 수행하고, 필요 시 clean succession(프로모션 감사 → spawn → 세 소멸 retire → lineage)으로 넘긴다.
  </Step>
</Steps>

## Related pages

<CardGroup>
  <Card title="방어 인벤토리" href="/defense-inventory">
    가드별 경로·측정·깨짐 조건 표.
  </Card>
  <Card title="Installation" href="/installation">
    preflight 전제조건과 FAIL/WARN 맥락.
  </Card>
  <Card title="Clean succession" href="/succession">
    handoff·placement spawn·retire·revival·lineage.
  </Card>
  <Card title="master-succeed 레퍼런스" href="/succession-cli-reference">
    spawn/check-duplicates exit 코드와 플래그.
  </Card>
  <Card title="Supervised dispatch" href="/supervised-dispatch">
    check → register, model probe, ledger.
  </Card>
  <Card title="dispatch-gate 레퍼런스" href="/dispatch-gate-reference">
    reason code·ledger 스키마.
  </Card>
</CardGroup>
