# 모델 식별과 drift 감사

> `model-identity-probe`, `model-drift-audit`, transcript glob 해석, expected model, undecidable 상태와 register-time 검증을 설명합니다.

- Repository: local/master-ops-with-local-mogui-ADE-orchestrator

- Human docs: https://grok-wiki.com/public/docs/local-master-ops-with-local-mogui-ade-orches-0ac7093355f3
- Complete Markdown: https://grok-wiki.com/public/docs/local-master-ops-with-local-mogui-ade-orches-0ac7093355f3/llms-full.txt

## Source Files

- `local-mogui-ade-orchestrator:scripts/model-identity-probe`
- `local-mogui-ade-orchestrator:scripts/model-drift-audit`
- `local-mogui-ade-orchestrator:src/master_runtime/core/instance_runtime_config.py`
- `local-mogui-ade-orchestrator:config/instance-runtime.example.json`
- `local-mogui-ade-orchestrator:tests/test_model_identity_probe.py`
- `local-mogui-ade-orchestrator:tests/test_model_drift_audit.py`
- `local-master-ops:scripts/dispatch`

---

---
title: "모델 식별과 drift 감사"
description: "`model-identity-probe`, `model-drift-audit`, transcript glob 해석, expected model, undecidable 상태와 register-time 검증을 설명합니다."
---

`local-mogui-ade-orchestrator:scripts/model-identity-probe`는 세션 JSONL에서 최근 assistant turn의 `model` 필드를 측정하고, `local-mogui-ade-orchestrator:scripts/model-drift-audit`는 같은 transcript 전체를 걸어 모델 전이를 판정한다. `local-master-ops:scripts/dispatch`는 작업자 `register` 전에 worker transcript를 읽을 수 있을 때만 `model-identity-probe`를 register-time 검증 명령으로 연결하며, 범위를 특정 worker로 좁힐 수 없으면 검증 불가 상태를 명시한다.

## 명령 표면

| 명령 | 질문 | 기본 판정 단위 | 성공 의미 |
| --- | --- | --- | --- |
| `scripts/model-identity-probe` | 지금 최근 turn이 기대 모델인가 | 최근 assistant model 샘플, 기본 `--limit 10` | `--expect`가 있을 때 모든 샘플이 기대 모델과 일치 |
| `scripts/model-drift-audit` | 세션 중간에 모델이 바뀐 적이 있는가 | transcript 전체 assistant turn 순서 | 전이가 없고, `--expect`가 있으면 모든 실제 모델이 기대 모델과 일치 |
| `scripts/dispatch` register 단계 | 선언한 worker model이 실제 worker artifact와 맞는가 | worker-scoped transcript probe 또는 명시 glob | ledger에 `model_verified=true` 기록 |

<Note>
`model-identity-probe`의 `0`은 항상 같은 의미가 아니다. `--expect` 또는 `MODEL_IDENTITY_EXPECT`가 없으면 정보 출력만 하고 아무 것도 단정하지 않는다.
</Note>

## transcript 위치 해석

`model-identity-probe`에서 `--transcript`를 생략하면 위치는 다음 순서로 해석된다.

<Steps>
<Step title="명시 경로">
`--transcript <session.jsonl>`이 있으면 해당 파일을 그대로 사용한다.
</Step>
<Step title="환경 glob">
`MOGUI_TRANSCRIPT_GLOB`이 있으면 runtime 이름이나 instance config 없이도 이 glob의 최신 파일을 선택한다.
</Step>
<Step title="instance runtime config">
`--config`, `INSTANCE_RUNTIME_CONFIG`, 기본 `config/instance-runtime.json` 순서로 설정 파일을 찾고, `--runtime` 또는 `master_host_runtime`에 대응하는 `transcript_globs.<runtime>`을 읽는다.
</Step>
<Step title="unconfigured">
경로를 결정할 수 없으면 기본 transcript 위치를 추측하지 않고 exit `2`로 종료한다.
</Step>
</Steps>

설정 예시는 다음 구조를 갖는다.

```json title="config/instance-runtime.example.json"
{
  "master_host_runtime": "claude",
  "transcript_globs": {
    "claude": "~/.claude/projects/-Users-example-workspace/*.jsonl",
    "codex": "~/.codex/sessions/**/*.jsonl",
    "grok": "~/.grok/sessions/**/*.jsonl"
  },
  "product_repo": "/absolute/path/to/primary-product-repo"
}
```

`transcript_globs`의 key는 host nickname이 아니라 agent CLI runtime 이름이다. `_docs`와 `_note`처럼 `_`로 시작하는 key는 문서용으로 무시된다. 잘못된 JSON, 빈 runtime key, 빈 glob 문자열은 구성 오류로 취급된다.

## expected model

두 스크립트 모두 기대 모델을 코드에 고정하지 않는다. 기대 모델은 workspace, host, dispatch lane마다 달라질 수 있으므로 호출자가 명시해야 한다.

```bash title="최근 model identity 확인"
scripts/model-identity-probe \
  --transcript ./sessions/session.jsonl \
  --expect claude-fable-5
```

```bash title="세션 전체 drift 감사"
scripts/model-drift-audit \
  --transcript ./sessions/session.jsonl \
  --expect claude-fable-5
```

`model-drift-audit --expect`는 전이가 없어도 실제 모델 중 하나가 기대 모델과 다르면 exit `1`을 반환한다. `--json`을 함께 쓰면 `expect`, `expect_mismatch`, `counts`, `transitions`, `transitions_including_synthetic`를 포함한 JSON을 출력한다.

## transcript event 해석

두 도구는 transcript shape 차이를 줄이기 위해 top-level event와 중첩 object를 함께 본다.

```text
event
├─ role/type/model
├─ message.role/type/model
├─ item.role/type/model
├─ payload.role/type/model
└─ response.role/type/model
```

assistant turn 판정은 `role == "assistant"` 또는 `type == "assistant"`이다. assistant turn인데 model 문자열을 읽을 수 없으면 `model-identity-probe`와 `model-drift-audit` 모두 `<missing>`을 모델 값으로 보존한다. 이 turn을 버리면 실제 drift가 `<missing>` 구간 안에 숨어도 “clean”으로 보일 수 있기 때문이다.

## exit code와 undecidable

| 명령 | `0` | `1` | `2` |
| --- | --- | --- | --- |
| `model-identity-probe` | 기대 모델 일치, 또는 기대 모델 없이 정보 출력 | 사용하지 않음 | drift, invalid limit, transcript/config 오류, unconfigured |
| `model-drift-audit` | 전이 없음, 기대 모델도 일치 | 전이 있음 또는 기대 모델 mismatch | transcript 없음, 읽기 실패, assistant turn 없음, 실제 모델 없음 |

`model-drift-audit`의 undecidable은 pass가 아니다. 예를 들어 transcript가 없거나, assistant turn이 0개이거나, 모든 assistant turn이 `<synthetic>` 또는 `<missing>`이면 실제 모델을 관측하지 못한 상태로 exit `2`를 반환한다.

<Warning>
`model-identity-probe`의 exit `2`는 drift와 undecidable을 같은 code로 보고한다. 자동화는 stdout의 `MODEL-PROBE DRIFT:` 또는 `unconfigured` 메시지를 함께 읽어야 한다.
</Warning>

## synthetic turn 처리

`model-drift-audit`는 synthetic turn을 `<synthetic>`으로 취급한다. `--ignore-synthetic`을 사용하면 synthetic turn 자체는 전이 계산에서 제외하지만, 양쪽 실제 모델 사이의 변화는 유지한다.

```text
claude-fable-5 -> <synthetic> -> claude-opus-5
```

`--ignore-synthetic` 후에는 위 sequence가 `claude-fable-5 -> claude-opus-5` 전이로 남는다. synthetic turn을 제거하면서 양쪽 모델 변화까지 지우는 동작은 drift를 놓치는 실패 모드다.

## register-time 검증

`local-master-ops:scripts/dispatch`는 `check -> task-create -> terminal -> dispatch --inject -> register` 순서에서 register 직전에 model probe 대상을 결정한다.

| 상태 | 조건 | register 출력 의미 |
| --- | --- | --- |
| `explicit-glob` | 호출자가 `--transcript-glob`을 제공 | caller가 확인한 glob으로 model probe 수행 |
| `scoped-to-worktree` | runtime이 worker worktree 경로로 transcript glob을 만들 수 있음 | worker-scoped transcript로 model probe 수행 |
| `unavailable` | glob을 worker 하나로 좁힐 수 없음 | `declared_model`은 측정값이 아니며 수동 확인 필요 |

현재 wrapper는 Claude transcript 경로만 worktree에서 파생한다. 다른 runtime은 working directory가 transcript path가 아니라 JSONL 내부에 저장될 수 있어, 단순 glob으로 특정 worker를 식별할 수 없으면 probe를 붙이지 않는다. 넓은 glob으로 최신 파일을 고르면 다른 세션이나 master transcript를 “검증”할 수 있으므로, 검증 실패보다 나쁜 false pass가 된다.

`dispatch-gate register`는 job id probe가 실패하면 등록을 거부한다. model probe는 graded verdict다.

| register 결과 | 조건 | ledger 의미 |
| --- | --- | --- |
| verified | `model_declared`와 `model_measured`가 case-insensitive 일치 | `model_verified=true` |
| `MODEL_UNVERIFIED` | 선언 모델 또는 측정 모델이 없음 | 등록은 허용, `model_verified=false` |
| `MODEL_PROBE_FAILED` | probe command가 실패하거나 출력이 없음 | 등록은 허용, 실패 상태 기록 |
| `MODEL_MISMATCH` | 측정 모델이 선언 모델과 다르지만 더 엄격한 tier가 아님 | 등록은 허용, warning 기록 |
| `MODEL_TIER_ESCALATION` | 측정 모델이 선언 모델보다 더 엄격한 tier | 등록 거부 |

## 운영 기준

부팅 시 측정한 모델은 세션 전체의 속성이 아니라 한 시점의 snapshot이다. resume, continue, compaction, succession audit, session close처럼 세션 상태가 바뀐 뒤에는 다시 측정한다. 최근 turn 샘플은 “지금 무엇으로 보이는가”를 답하고, 중간 drift 여부는 전체 transcript 감사로만 답한다.

TUI status line은 model 증거로 쓰지 않는다. register-time model probe는 agent가 만든 artifact, 예를 들어 session transcript를 읽어야 한다. provider나 agent CLI마다 transcript 위치와 shape가 다르므로 이 설계는 특정 vendor API를 전제하지 않고, 파일 artifact를 읽을 수 없을 때는 unavailable 또는 undecidable을 기록한다.

## 문제 해결 신호

| 증상 | 확인할 것 | 처리 |
| --- | --- | --- |
| `MODEL-PROBE INFO ... nothing asserted` | `--expect` 또는 `MODEL_IDENTITY_EXPECT` 누락 | 기대 모델을 명시해 assertion으로 실행 |
| `MODEL-PROBE DRIFT: <none>` | assistant model turn을 읽지 못함 | transcript path와 event shape 확인 |
| `model-drift-audit: FAIL. zero assistant turns` | transcript는 있으나 assistant turn 없음 | 올바른 session file인지 재확인 |
| `no real model observed` | 모든 assistant turn이 `<synthetic>` 또는 `<missing>` | clean으로 처리하지 말고 다른 artifact로 확인 |
| dispatch 출력의 `model=unavailable` | worker-scoped transcript glob 없음 | 수동 확인하거나 검증된 `--transcript-glob` 제공 |
| ledger warning `MODEL_PROBE_FAILED` | model probe command 실패 또는 빈 출력 | probe command가 exit `0`이고 실제 model id를 stdout에 출력하는지 확인 |

## Related pages

<CardGroup>
<Card title="작업자 위임" href="/dispatch-workers">
`check -> dispatch -> register` 흐름과 worker contract, completion channel 검증을 함께 봅니다.
</Card>
<Card title="방어 인벤토리" href="/defense-inventory">
model verification이 다른 guard와 어떤 증거 강도로 연결되는지 확인합니다.
</Card>
<Card title="CLI 참조" href="/cli-reference">
공개 scripts surface, option, exit code 차이를 빠르게 대조합니다.
</Card>
<Card title="문제 해결" href="/troubleshooting">
model probe undecidable, register warning, transcript 위치 문제를 증상별로 확인합니다.
</Card>
</CardGroup>
