# task-2711 — ANU_CODEX_REVIEW_LOOP_DECIDER (FINAL · DISPATCH_AUTHORIZED)

★ **FINAL · DISPATCH_AUTHORIZED** — 회장 verbatim "task-2711 draft 방향 승인한다 · task-2711 dispatch 인가한다 · executor dev1 Hermes · §7.3 fixture 분리 · §5.4 loop boundary 강화" 정합.

- **draft lineage**: `memory/tasks/task-2711_draft.md` sha `e442459f...` (★ 보존)
- **final origin**: 회장 verbatim §7.3 fixture 분리 + §5.4 boundary 강화 + chair_authorization_id 박제

---

## 0. Header / Authorization Anchor

- **task_id**: `task-2711`
- **task_type**: `system_hook` (★ executable runner + tests)
- **chair_authorization_id**: `CHAIR-AUTH-TASK-2711-ANU-CODEX-REVIEW-LOOP-DECIDER-260530` (★ 회장 verbatim 발급 · task-2710 chair_authorization_id 재사용 0 strict)
- **dispatch_status**: ★ **DISPATCH_AUTHORIZED · DISPATCH_PENDING**
- **executor_team**: `dev1-team` (헤르메스 · Hermes) (★ 회장 verbatim 결정)
- **verifier_team_candidate**: `dev2-team` (오딘 · Odin) **또는** 독립 verifier (★ task-2711 완료 보고 후 별도 결정 영역 · task-2711+1 분리)
- **anu_collector_key**: `c119085addb0f8b7`
- **callback_envelope_prompt_byte_limit**: UTF-8 ≤ 3900 bytes hard (★ wc -c · NOT wc -m)

---

## 1. Problem Statement (★ task-2710 7 round 사고 박제)

task-2710 v1~v8 lifecycle 동안 **Codex independent review 7 round** 가 진행되었고, **모든 round 마다 회장이 직접 verbatim instruction 복붙** 으로 ANU 에 R1~R5 매핑을 지시했다. 결과:

- 회장 인지 부하 ↑
- ANU bounded loop 자동화 미흡
- minor refinement 사이클이 회장 결정 영역으로 잘못 escalate

**해결**: Codex review 결과가 **NEEDS_REVISION / HOLD_FOR_CHAIR / PASS_WITH_RECOMMENDATIONS** 이고 **Critical 7 / 권한확대 / forbidden target / 실제 dispatch / GitHub write / 기존 evidence 변경 위험 0** 이면 ANU 가 회장 복붙 없이 자동 revision loop 를 돌리는 **decision runner** 설계 + 구현.

---

## 2. Goal

> Codex review verdict + remaining_recommendations + risk surface 를 입력 받아 5 enum 중 하나로 분류하고, AUTO_REVISION_CONTINUE 영역만 ANU 가 자동 처리하며, 나머지 4 영역은 회장에 escalate 하는 **decision runner** 설계 + 구현 + 테스트.

---

## 3. Decision Enum 5 (★ 회장 verbatim 그대로 유지)

| enum | 의미 | next action | 회장 보고 |
|---|---|---|---|
| **AUTO_REVISION_CONTINUE** | minor doc/spec/classifier/gate refinement only · risk 0 | ANU 자동 v+1 revision drafting + Codex round+1 재요청 | ★ NO (★ silent loop) |
| **CHAIR_DECISION_REQUIRED** | 기준값 신규 결정 / forbidden target 추가 / classifier rule 신규 / pilot gate 신규 / loop stagnation / 동일 blocker 3회 반복 / FAIL 2회 이상 같은 axis 반복 | ANU 회장 보고 + 회장 verbatim 대기 | ★ YES |
| **LOCK_READY** | Codex OVERALL PASS / PASS_WITH_RECOMMENDATIONS + remaining 0 또는 minor doc only + ANU self-check 5/5 통과 | ANU 회장 보고 + lock 인가 대기 | ★ YES (★ lock 인가 only) |
| **PILOT_READY_BUT_NEEDS_CHAIR** | Codex PILOT_READINESS READY 또는 READY_WITH_RECOMMENDATIONS + (★ remaining minor doc 있어도 chair 명시 인가 없음 시 본 영역) | ANU 회장 보고 + pilot 별도 결정 대기 (★ 신규 fresh task ID + 별도 chair_authorization_id) | ★ YES (★ pilot 인가 only) |
| **CRITICAL_ESCALATION** | Critical 7 / 권한확대 / forbidden target 침해 / 실제 dispatch 시도 / GitHub write 시도 / 기존 evidence 변경 시도 | ANU 즉시 회장 보고 + auto loop 중단 + lock/pilot 시도 0 | ★ YES (★ 즉시) |

---

## 4. Risk Surface (★ 회장 verbatim 승인 영역)

### 4.1 AUTO 허용 영역 7 (★ 회장 verbatim "AUTO 허용 영역 7은 승인")

| # | 영역 | 예시 |
|---|---|---|
| 1 | minor documentation | secondary_labels order-insensitive serialization 명시 |
| 2 | spec restatement | "v6 verbatim 유지" → self-contained 본문 박제 |
| 3 | classifier rule clarification | nested data-path mismatch fix |
| 4 | classifier discriminator tightening | policy/chain/attempt overlap precedence 명시 |
| 5 | pilot gate refinement | authoritative source cascade 명시 |
| 6 | enum expansion (★ existing 분류 내) | qc subcase enum +3 |
| 7 | numeric threshold formalization | G3 +50% / $15 verbatim 박제 (★ 회장이 한 번 결정한 값) |

### 4.2 CHAIR-ONLY 영역 5 (★ 회장 verbatim "CHAIR-ONLY 영역 5도 승인")

| # | 영역 | 자동 처리 차단 |
|---|---|---|
| 1 | Critical 7 (feedback_critical_escalation_only_260508.md) | CRITICAL_ESCALATION |
| 2 | 기준값 신규 결정 (★ 회장 미결정 threshold) | CHAIR_DECISION_REQUIRED |
| 3 | forbidden target 필요 (★ §11.3 추가 / immutable scope 확장 / 권한확대) | CHAIR_DECISION_REQUIRED |
| 4 | 실제 dispatch / pilot / PR / push / merge | PILOT_READY_BUT_NEEDS_CHAIR 또는 CRITICAL_ESCALATION |
| 5 | lock / pilot 인가 | LOCK_READY 또는 PILOT_READY_BUT_NEEDS_CHAIR |

### 4.3 Risk detection trigger 6 (★ draft §4.3 verbatim 유지)

| # | trigger 조건 | 분류 |
|---|---|---|
| 1 | Codex remaining_recommendations 가 Critical 7 doctrine 키워드 매칭 | CRITICAL_ESCALATION |
| 2 | 권한 확대 요구 (★ new allowed_path / new chair_auth scope) | CHAIR_DECISION_REQUIRED |
| 3 | forbidden target 변경 요구 | CHAIR_DECISION_REQUIRED |
| 4 | revision 산출물 expected_files 가 실제 dispatch/PR/push/merge/GitHub write 포함 | CRITICAL_ESCALATION |
| 5 | revision 산출물 allowed_existing_file_edits 가 immutable scope (§6.2 8 axis) 매칭 | CRITICAL_ESCALATION |
| 6 | revision 이 기존 evidence overwrite 시도 | CRITICAL_ESCALATION |

---

## 5. Architecture (★ executable)

### 5.1 Runner module

**Path**: `scripts/anu/codex_review_loop_decider.py`

**Public API** (★ Python ≥ 3.9):

```python
from typing import Literal, NamedTuple, Optional

DecisionEnum = Literal[
    'AUTO_REVISION_CONTINUE',
    'CHAIR_DECISION_REQUIRED',
    'LOCK_READY',
    'PILOT_READY_BUT_NEEDS_CHAIR',
    'CRITICAL_ESCALATION',
]

class CodexReviewInput(NamedTuple):
    task_id: str
    version: int
    round_number: int
    overall_verdict: str            # PASS / PASS_WITH_RECOMMENDATIONS / NEEDS_REVISION / HOLD_FOR_CHAIR
    pilot_readiness: str            # READY / READY_WITH_RECOMMENDATIONS / NOT_READY_WITHOUT_FOLLOWUP / NOT_READY
    axis_counts: dict               # {'pass': N, 'pwr': N, 'nr': N, 'fail': N}
    remaining_recommendations: list # verbatim 텍스트 리스트
    locked_status: bool
    chair_authorization_id: str
    # ★ 회장 verbatim §7.3 chair-authorized minor doc cleanup 분기
    chair_minor_doc_cleanup_authorized: bool = False
    # ★ §5.4 history (loop boundary)
    prior_rounds_history: Optional[list] = None  # [{round: 1, axis_counts: ..., remaining: ...}, ...]

class DecisionResult(NamedTuple):
    decision: DecisionEnum
    rationale: str
    next_action: str
    risk_triggers_matched: list     # §4.3 trigger 번호
    chair_facing_summary: str       # AUTO 시 빈 문자열
    audit_marker_path: str

def decide(input: CodexReviewInput) -> DecisionResult:
    """회장 verbatim 5 enum + risk gating + loop boundary."""
```

### 5.2 Risk gating precedence (★ 5-step)

```
Step 1: CRITICAL_ESCALATION (★ trigger 1, 4, 5, 6)
    ↓ no match
Step 2: CHAIR_DECISION_REQUIRED (★ trigger 2, 3 + §5.4 boundary)
    ↓ no match
Step 3: LOCK_READY (★ Codex OVERALL PASS/PWR + remaining 0 또는 minor doc only)
    ↓ no match
Step 4: PILOT_READY_BUT_NEEDS_CHAIR (★ Codex PILOT_READINESS READY/READY_WITH_RECOMMENDATIONS + ★ chair_minor_doc_cleanup_authorized False)
    ↓ chair_minor_doc_cleanup_authorized True 시
Step 5: AUTO_REVISION_CONTINUE (★ default · minor refinement only)
```

★ **회장 verbatim 강화**: PILOT_READINESS READY_WITH_RECOMMENDATIONS 도달 시 **기본값 PILOT_READY_BUT_NEEDS_CHAIR**. `chair_minor_doc_cleanup_authorized=True` 명시 시에만 AUTO_REVISION_CONTINUE 로 분기.

### 5.3 Auto revision bounded actions

`AUTO_REVISION_CONTINUE` 시 ANU 자동 수행 action set:

| action | 허용 |
|---|---|
| vN+1 task md draft 작성 (★ vN 보존) | YES |
| Codex review marker JSON 박제 | YES |
| ANU self-check 박제 | YES |
| Codex round+1 재요청 (★ codex:codex-rescue subagent) | YES |
| 기존 evidence 변경 (★ §6.2 immutable) | **NO → CRITICAL_ESCALATION** |
| 실제 dispatch / PR / push | **NO → CRITICAL_ESCALATION** |
| 동일 lineage 내 chair_authorization_id 재사용 | YES |
| 신규 chair_authorization_id 발급 | **NO → CHAIR_DECISION_REQUIRED** |

### 5.4 Loop boundary (★ 회장 verbatim 강화)

| boundary | rule | 위반 시 |
|---|---|---|
| **max round per task lineage** | **7** (★ 회장 verbatim 유지) | CHAIR_DECISION_REQUIRED |
| **동일 blocker 3회 반복** (★ 회장 verbatim 신규) | round N · N-1 · N-2 의 remaining_recommendations 가 같은 핵심 영역 매칭 (★ §5.4.1 detection) | CHAIR_DECISION_REQUIRED |
| **FAIL 2회 이상 같은 axis 반복** (★ 회장 verbatim 신규) | axis_counts 에서 동일 axis 가 round N · N-1 모두 FAIL | CHAIR_DECISION_REQUIRED |
| **stagnation** | round N axis 분포 ↔ round N-1 axis 분포 동일 + remaining ≥ N-1 | CHAIR_DECISION_REQUIRED |
| **LOCK_READY 도달** | auto loop 중단 | chair 보고 (LOCK_READY) |
| **CRITICAL_ESCALATION** | auto loop 즉시 중단 | chair 즉시 보고 |

#### 5.4.1 동일 blocker detection (★ 회장 verbatim "동일 blocker 3회 반복")

`prior_rounds_history` 의 최근 3 round (★ N, N-1, N-2) 에서 `remaining_recommendations` 의 핵심 키워드 (★ 정규화 후) 가 ≥ 2/3 매칭 시 "동일 blocker 3회 반복" 으로 분류.

#### 5.4.2 FAIL 2회 같은 axis detection (★ 회장 verbatim "FAIL이 2회 이상 같은 axis에서 반복")

`prior_rounds_history` 의 최근 2 round (★ N, N-1) 에서 동일 axis (★ AXIS_1~AXIS_5) 가 FAIL 판정 받으면 분류.

---

## 6. Decision Schema (★ JSON fixture)

### 6.1 Input schema (`schemas/codex_review_input_schema.json`)

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["task_id", "version", "round_number", "overall_verdict", "pilot_readiness", "axis_counts", "remaining_recommendations", "locked_status", "chair_authorization_id"],
  "properties": {
    "task_id": {"type": "string", "pattern": "^task-\\d+(\\+\\d+)?$"},
    "version": {"type": "integer", "minimum": 1},
    "round_number": {"type": "integer", "minimum": 1},
    "overall_verdict": {"enum": ["PASS", "PASS_WITH_RECOMMENDATIONS", "NEEDS_REVISION", "HOLD_FOR_CHAIR"]},
    "pilot_readiness": {"enum": ["READY", "READY_WITH_RECOMMENDATIONS", "NOT_READY_WITHOUT_FOLLOWUP", "NOT_READY"]},
    "axis_counts": {"type": "object"},
    "remaining_recommendations": {"type": "array", "items": {"type": "string"}},
    "locked_status": {"type": "boolean"},
    "chair_authorization_id": {"type": "string"},
    "chair_minor_doc_cleanup_authorized": {"type": "boolean", "default": false},
    "prior_rounds_history": {"type": "array", "items": {"type": "object"}}
  }
}
```

### 6.2 Output schema (`schemas/codex_review_decision_output_schema.json`)

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["decision", "rationale", "next_action", "risk_triggers_matched", "chair_facing_summary", "audit_marker_path"],
  "properties": {
    "decision": {"enum": ["AUTO_REVISION_CONTINUE", "CHAIR_DECISION_REQUIRED", "LOCK_READY", "PILOT_READY_BUT_NEEDS_CHAIR", "CRITICAL_ESCALATION"]},
    "rationale": {"type": "string"},
    "next_action": {"type": "string"},
    "risk_triggers_matched": {"type": "array", "items": {"type": "integer", "minimum": 1, "maximum": 6}},
    "chair_facing_summary": {"type": "string"},
    "audit_marker_path": {"type": "string"}
  }
}
```

---

## 7. task-2710 사례 fixture (★ 회장 verbatim "§7.3 fixture 분리")

### 7.1 round 1 fixture (★ NEEDS_REVISION + 5/5 NR)

```json
{
  "task_id": "task-2710", "version": 1, "round_number": 1,
  "overall_verdict": "NEEDS_REVISION",
  "pilot_readiness": "NOT_READY_WITHOUT_FOLLOWUP",
  "axis_counts": {"pass": 0, "pwr": 0, "nr": 5, "fail": 0},
  "remaining_recommendations": ["R1 §5 사전 조건 C 제거", "R2 §3 classifier executable", "R3 §4 qc subcase", "R4 §6 structural guard", "R5 §7 pilot gates"],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2710-..."
}
```

**expected**: `AUTO_REVISION_CONTINUE`

### 7.2 round 6 fixture (★ PASS_WITH_RECOMMENDATIONS + PILOT_READINESS NOT_READY)

```json
{
  "task_id": "task-2710", "version": 6, "round_number": 6,
  "overall_verdict": "PASS_WITH_RECOMMENDATIONS",
  "pilot_readiness": "NOT_READY_WITHOUT_FOLLOWUP",
  "axis_counts": {"pass": 2, "pwr": 2, "nr": 1, "fail": 0},
  "remaining_recommendations": ["case 6 ACCEPT_WITH_KNOWN_CAVEATS", "§4.3 overlap signal recording", "§4.2 G8 reference 정정", "§7.5.2 case 8 tie-resolution"],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2710-..."
}
```

**expected**: `AUTO_REVISION_CONTINUE` (★ PILOT_READINESS 미충족 + minor refinement only)

### 7.3 round 7 fixture **A** — chair_minor_doc_cleanup_authorized **False** (★ 회장 verbatim 강화 · 기본값)

```json
{
  "task_id": "task-2710", "version": 7, "round_number": 7,
  "overall_verdict": "PASS_WITH_RECOMMENDATIONS",
  "pilot_readiness": "READY_WITH_RECOMMENDATIONS",
  "axis_counts": {"pass": 3, "pwr": 2, "nr": 0, "fail": 0},
  "remaining_recommendations": ["secondary_labels order-insensitive", "§5/§6 self-contained restatement"],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2710-...",
  "chair_minor_doc_cleanup_authorized": false
}
```

**expected**: ★ **`PILOT_READY_BUT_NEEDS_CHAIR`** (★ 회장 verbatim "기본값으로 부적절 · PILOT_READINESS READY_WITH_RECOMMENDATIONS 도달 시 chair lock/pilot 결정 받아야 하는 상태")

### 7.3-B round 7 fixture **B** — chair_minor_doc_cleanup_authorized **True** (★ 회장 verbatim 분리 · 명시 인가 분기)

```json
{
  "task_id": "task-2710", "version": 7, "round_number": 7,
  "overall_verdict": "PASS_WITH_RECOMMENDATIONS",
  "pilot_readiness": "READY_WITH_RECOMMENDATIONS",
  "axis_counts": {"pass": 3, "pwr": 2, "nr": 0, "fail": 0},
  "remaining_recommendations": ["secondary_labels order-insensitive", "§5/§6 self-contained restatement"],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2710-...",
  "chair_minor_doc_cleanup_authorized": true
}
```

**expected**: ★ **`AUTO_REVISION_CONTINUE`** (★ 회장 verbatim "chair 명시 인가 시에만 AUTO 가능")

### 7.4 v8 post-self-check fixture (★ LOCK_READY)

```json
{
  "task_id": "task-2710", "version": 8, "round_number": 7,
  "overall_verdict": "PASS_WITH_RECOMMENDATIONS",
  "pilot_readiness": "READY_WITH_RECOMMENDATIONS",
  "axis_counts": {"pass": 3, "pwr": 2, "nr": 0, "fail": 0},
  "remaining_recommendations": [],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2710-..."
}
```

**expected**: `LOCK_READY`

### 7.5 가상 CRITICAL_ESCALATION fixture

```json
{
  "task_id": "task-2710", "version": 9, "round_number": 8,
  "overall_verdict": "NEEDS_REVISION",
  "pilot_readiness": "NOT_READY_WITHOUT_FOLLOWUP",
  "axis_counts": {"pass": 2, "pwr": 1, "nr": 1, "fail": 1},
  "remaining_recommendations": ["task-2706+1 verifier marker recorded_at 를 accepted_no_caveat 으로 reclassify"],
  "locked_status": true,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2710-..."
}
```

**expected**: `CRITICAL_ESCALATION` (★ trigger 6 evidence overwrite 시도)

### 7.6 loop boundary fixture **A** — 동일 blocker 3회 반복

```json
{
  "task_id": "task-2799", "version": 3, "round_number": 3,
  "overall_verdict": "NEEDS_REVISION",
  "pilot_readiness": "NOT_READY_WITHOUT_FOLLOWUP",
  "axis_counts": {"pass": 1, "pwr": 0, "nr": 3, "fail": 1},
  "remaining_recommendations": ["spec X 보강 필요"],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2799-...",
  "prior_rounds_history": [
    {"round": 1, "axis_counts": {"fail": 1, "nr": 4}, "remaining": ["spec X 보강 필요"]},
    {"round": 2, "axis_counts": {"fail": 1, "nr": 3, "pass": 1}, "remaining": ["spec X 보강 필요"]}
  ]
}
```

**expected**: `CHAIR_DECISION_REQUIRED` (★ §5.4 동일 blocker 3회 반복)

### 7.7 loop boundary fixture **B** — FAIL 2회 같은 axis 반복

```json
{
  "task_id": "task-2799", "version": 2, "round_number": 2,
  "overall_verdict": "HOLD_FOR_CHAIR",
  "pilot_readiness": "NOT_READY_WITHOUT_FOLLOWUP",
  "axis_counts": {"pass": 0, "pwr": 1, "nr": 3, "fail": 1, "fail_axes": ["AXIS_3"]},
  "remaining_recommendations": ["AXIS_3 추가 정합"],
  "locked_status": false,
  "chair_authorization_id": "CHAIR-AUTH-TASK-2799-...",
  "prior_rounds_history": [
    {"round": 1, "axis_counts": {"fail": 1, "fail_axes": ["AXIS_3"], "nr": 4}, "remaining": ["AXIS_3 정합"]}
  ]
}
```

**expected**: `CHAIR_DECISION_REQUIRED` (★ §5.4 FAIL 2회 같은 axis)

---

## 8. Test scenarios (★ `tests/test_codex_review_loop_decider_2711.py`)

| test ID | scenario | fixture | expected |
|---|---|---|---|
| T-1 | task-2710 round 1 NEEDS_REVISION 5/5 NR | §7.1 | AUTO_REVISION_CONTINUE |
| T-2 | task-2710 round 6 PWR + PILOT_READINESS NOT_READY | §7.2 | AUTO_REVISION_CONTINUE |
| **T-3a** | task-2710 round 7 PWR + READY_WITH_RECOMMENDATIONS + chair_minor_doc_cleanup_authorized=False | §7.3 | ★ **PILOT_READY_BUT_NEEDS_CHAIR** (★ 회장 verbatim 강화) |
| **T-3b** | task-2710 round 7 동일 + chair_minor_doc_cleanup_authorized=True | §7.3-B | ★ **AUTO_REVISION_CONTINUE** (★ 명시 인가 분기) |
| T-4 | task-2710 v8 post-self-check (remaining 0) | §7.4 | LOCK_READY |
| T-5 | 가상 CRITICAL_ESCALATION (evidence reclassify) | §7.5 | CRITICAL_ESCALATION |
| T-6 | LOCK_READY 후 PILOT_READINESS READY + locked_status True | (§7.4 후속) | PILOT_READY_BUT_NEEDS_CHAIR |
| **T-7a** | 동일 blocker 3회 반복 | §7.6 | ★ **CHAIR_DECISION_REQUIRED** (★ §5.4) |
| **T-7b** | FAIL 2회 같은 axis 반복 | §7.7 | ★ **CHAIR_DECISION_REQUIRED** (★ §5.4) |
| T-8 | Critical 7 키워드 매칭 (`CHAIR_REQUIRED` / `Critical 7`) | (★ 신규 fixture) | CRITICAL_ESCALATION |
| T-9 | forbidden path 변경 요구 | (★ 신규 fixture) | CHAIR_DECISION_REQUIRED |
| T-10 | 실제 dispatch 요구 (`dispatch.py 변경` / `bot_settings.json 변경`) | (★ 신규 fixture) | CRITICAL_ESCALATION |
| T-11 | 권한 확대 요구 (new allowed_path) | (★ 신규 fixture) | CHAIR_DECISION_REQUIRED |
| T-12 | revision 산출물에 PR/push/merge 포함 | (★ 신규 fixture) | CRITICAL_ESCALATION |
| T-13 | revision allowed_existing_file_edits 가 immutable scope 매칭 | (★ 신규 fixture) | CRITICAL_ESCALATION |
| T-14 | max 7 round 도달 시 | (★ 신규 fixture · round_number=8) | CHAIR_DECISION_REQUIRED |

**총 14 test scenarios** (★ T-3a/T-3b 분리 + T-7a/T-7b 분리 추가)

---

## 9. Affected Files (★ 회장 인가 후 작성)

1. `scripts/anu/codex_review_loop_decider.py` (★ 신규 · executable runner)
2. `tests/test_codex_review_loop_decider_2711.py` (★ 신규 · 14 test scenarios)
3. `schemas/codex_review_input_schema.json` (★ 신규)
4. `schemas/codex_review_decision_output_schema.json` (★ 신규)
5. `tests/fixtures/codex_review_2711/task-2710_round1.json`
6. `tests/fixtures/codex_review_2711/task-2710_round6.json`
7. `tests/fixtures/codex_review_2711/task-2710_round7_chair_minor_false.json` (★ §7.3)
8. `tests/fixtures/codex_review_2711/task-2710_round7_chair_minor_true.json` (★ §7.3-B)
9. `tests/fixtures/codex_review_2711/task-2710_v8_lock_ready.json` (★ §7.4)
10. `tests/fixtures/codex_review_2711/critical_escalation_evidence_reclassify.json` (★ §7.5)
11. `tests/fixtures/codex_review_2711/loop_boundary_same_blocker_3.json` (★ §7.6)
12. `tests/fixtures/codex_review_2711/loop_boundary_fail_2_same_axis.json` (★ §7.7)
13. `memory/reports/task-2711.md` (★ 보고서)
14. `memory/events/task-2711.formalization-commit-260530.json` (★ formalization marker)
15. `memory/events/task-2711.callback-envelope.json` (★ ANU envelope · ≤ 3900 bytes)

**총 expected_files 15 개**

---

## 10. Allowed / Forbidden Files

### 10.1 expected_files (★ 위 §9 verbatim)

### 10.2 allowed_existing_file_edits

- **NONE** (★ 신규 파일만 · 기존 파일 edit 0)

### 10.3 forbidden_files (★ 강제 sha256 동일)

- `scripts/finish-task.sh`
- `scripts/task-scope-guard.sh`
- `scripts/session-watchdog.sh`
- `.claude/settings.json` / `/home/jay/.claude/settings.json`
- `dispatch.py` / `dispatch/__init__.py` / `dispatch/normal_fallback_callback_helper.py`
- `bot_settings.json` / `memory/bot_settings.json`
- `qc_verify.py`
- `utils/merge_queue_executor.py` / `utils/real_merge_hooks.py`
- `anu_v3/`
- `memory/capabilities/**`
- task-2706~2709+1 모든 산출물 (★ immutable historical)
- `memory/tasks/task-2710.md` / `task-2710_v2.md` / `task-2710_v3.md` / `task-2710_v4.md` / `task-2710_v5.md` / `task-2710_v6.md` / `task-2710_v7.md` / `task-2710_v8.md` (★ final LOCKED)
- task-2710 모든 marker (★ events/task-2710.*.json)

### 10.4 forbidden_actions (★ 회장 verbatim 9 강제)

1. task-2710 변경 0 (★ 회장 verbatim)
2. task-2706~2709+1 evidence 변경 0 (★ 회장 verbatim)
3. bot_settings.json 변경 0 (★ 회장 verbatim)
4. dispatch.py 변경 0 (★ 회장 verbatim)
5. settings.json 변경 0 (★ 회장 verbatim)
6. finish-task.sh 변경 0 (★ 회장 verbatim)
7. PR / push / merge / GitHub write 0 (★ 회장 verbatim)
8. pilot dispatch 0 (★ 회장 verbatim)
9. 실제 모델 설정 변경 0 (★ 회장 verbatim)

### 10.5 Capability Scope YAML (★ paths key explicit)

```yaml
allowed_resources:
  paths:
    - scripts/anu/codex_review_loop_decider.py
    - tests/test_codex_review_loop_decider_2711.py
    - schemas/codex_review_input_schema.json
    - schemas/codex_review_decision_output_schema.json
    - tests/fixtures/codex_review_2711/task-2710_round1.json
    - tests/fixtures/codex_review_2711/task-2710_round6.json
    - tests/fixtures/codex_review_2711/task-2710_round7_chair_minor_false.json
    - tests/fixtures/codex_review_2711/task-2710_round7_chair_minor_true.json
    - tests/fixtures/codex_review_2711/task-2710_v8_lock_ready.json
    - tests/fixtures/codex_review_2711/critical_escalation_evidence_reclassify.json
    - tests/fixtures/codex_review_2711/loop_boundary_same_blocker_3.json
    - tests/fixtures/codex_review_2711/loop_boundary_fail_2_same_axis.json
    - memory/reports/task-2711.md
    - memory/events/task-2711.formalization-commit-260530.json
    - memory/events/task-2711.callback-envelope.json
  expected_files:
    - scripts/anu/codex_review_loop_decider.py
    - tests/test_codex_review_loop_decider_2711.py
    - schemas/codex_review_input_schema.json
    - schemas/codex_review_decision_output_schema.json
    - tests/fixtures/codex_review_2711/task-2710_round1.json
    - tests/fixtures/codex_review_2711/task-2710_round6.json
    - tests/fixtures/codex_review_2711/task-2710_round7_chair_minor_false.json
    - tests/fixtures/codex_review_2711/task-2710_round7_chair_minor_true.json
    - tests/fixtures/codex_review_2711/task-2710_v8_lock_ready.json
    - tests/fixtures/codex_review_2711/critical_escalation_evidence_reclassify.json
    - tests/fixtures/codex_review_2711/loop_boundary_same_blocker_3.json
    - tests/fixtures/codex_review_2711/loop_boundary_fail_2_same_axis.json
    - memory/reports/task-2711.md
    - memory/events/task-2711.formalization-commit-260530.json
    - memory/events/task-2711.callback-envelope.json
  allowed_existing_file_edits: []
  forbidden_paths:
    - scripts/finish-task.sh
    - scripts/task-scope-guard.sh
    - scripts/session-watchdog.sh
    - .claude/settings.json
    - /home/jay/.claude/settings.json
    - dispatch.py
    - dispatch/__init__.py
    - dispatch/normal_fallback_callback_helper.py
    - bot_settings.json
    - memory/bot_settings.json
    - qc_verify.py
    - utils/merge_queue_executor.py
    - utils/real_merge_hooks.py
    - anu_v3/
    - memory/capabilities/**
    - memory/tasks/task-2710.md
    - memory/tasks/task-2710_v2.md
    - memory/tasks/task-2710_v3.md
    - memory/tasks/task-2710_v4.md
    - memory/tasks/task-2710_v5.md
    - memory/tasks/task-2710_v6.md
    - memory/tasks/task-2710_v7.md
    - memory/tasks/task-2710_v8.md
```

---

## 11. Acceptance Criteria

1. ★ §9 affected files 15 개 작성
2. ★ §8 14 test scenarios 모두 PASS (★ pytest 로컬 실행)
3. ★ §3 5 enum classification 정합
4. ★ §5.2 risk gating precedence 5-step 정합
5. ★ §5.4 loop boundary 정합 (★ max 7 + 동일 blocker 3회 + FAIL 2회 같은 axis)
6. ★ §5.3 auto revision bounded actions 정합
7. ★ §6 input/output schema validation
8. ★ §7 fixture 7 개 (★ §7.1~7.7) 박제
9. ★ §10.3 forbidden_files sha256 동일 (★ 0 변경)
10. ★ §10.4 forbidden_actions 9 위반 0
11. ★ 로컬 pytest 실행 PASS (★ 단 PR / push / merge / GitHub write 0)

---

## 12. dev1 Hermes 실행 지침 (★ 회장 verbatim "dev1은 구현과 로컬 테스트까지만 수행")

### 12.1 실행 단계

| 단계 | 내용 | 산출물 |
|---|---|---|
| Step 1 | §5 architecture + §6 schema 기준 `codex_review_loop_decider.py` 구현 | §9 #1 |
| Step 2 | §7 fixture 7 개 박제 | §9 #5~12 |
| Step 3 | §8 14 test scenarios 작성 + pytest 로컬 실행 PASS | §9 #2 |
| Step 4 | §6 input/output schema 박제 | §9 #3, #4 |
| Step 5 | `memory/reports/task-2711.md` 작성 (★ 14 test 결과 + risk gating verbatim + loop boundary verbatim) | §9 #13 |
| Step 6 | `memory/events/task-2711.formalization-commit-260530.json` 박제 | §9 #14 |
| Step 7 | `memory/events/task-2711.callback-envelope.json` 박제 (★ UTF-8 ≤ 3900 bytes hard) | §9 #15 |
| Step 8 | finish-task.sh 통해 정상 종료 (★ scope-guard PASS + callback registration) | — |

### 12.2 금지 사항 (★ 회장 verbatim 9 + 추가)

1~9: §10.4 verbatim
10. PR / push / merge / GitHub write 0 (★ 로컬 commit 만 허용)
11. pilot dispatch 0
12. task-2710 / task-2706~2709+1 evidence 변경 0
13. ANU 자체 분류 결정 0 (★ §3 5 enum 분류 결정은 본 runner 동작 영역 · 봇 자체 새 enum 추가 0)
14. 새 forbidden target 추가 0 (★ §10.3 기존 doctrine 정합)
15. 새 chair_authorization scope 확장 0

### 12.3 callback envelope (★ ANU 콜백 강제)

- envelope 의 `collector_role` = `ANU` strict
- `owner_key` = `c119085addb0f8b7` (★ ANU key strict · self-key 0)
- prompt UTF-8 ≤ 3900 bytes hard limit (★ wc -c)
- normal callback registration enforce (★ envelope sendfile only 0)

### 12.4 완료 후 흐름

- dev1 → ANU normal callback (★ ANU key)
- ANU → 회장 보고 (★ 14 test 결과 + 4-doctrine compliance + forbidden_files sha256 동일 verbatim 박제)
- 회장 → task-2711+1 verifier 별도 결정 (★ dev2 Odin 또는 독립 verifier)

---

## 13. ANU Doctrine Compliance (★ 본 task-2711 dispatch)

- ★ ANU 자체 코드 구현 0 (★ dev1 위임)
- ★ ANU 자체 dispatch 인가 0 (★ 본 dispatch 는 회장 verbatim 명시 인가 영역)
- ★ ANU 자체 chair_authorization_id 발급 0 (★ 회장 verbatim 발급)
- ★ task-2710 / task-2706~2709+1 evidence 변경 0
- ★ ANU 자체 새 forbidden target 추가 0
- ★ ANU 자체 새 chair_authorization scope 확장 0
- ★ ANU 자체 lock/pilot 인가 0

---

## 14. Sentinel

★ task-2711 = FINAL · DISPATCH_AUTHORIZED · ANU_CODEX_REVIEW_LOOP_DECIDER · executor dev1 Hermes · 5 enum decision · risk gating 6 trigger · loop boundary (★ max 7 + 동일 blocker 3회 + FAIL 2회 같은 axis) · §7.3 chair_minor_doc_cleanup_authorized 분기 (★ False=PILOT_READY_BUT_NEEDS_CHAIR / True=AUTO_REVISION_CONTINUE) · 15 affected files · 14 test scenarios · 7 fixture (§7.1~7.7) · task-2710 변경 0 · task-2706~2709+1 evidence 변경 0 · bot_settings.json/dispatch.py/settings.json/finish-task.sh 변경 0 · PR/push/merge/GitHub write 0 · pilot dispatch 0 · 모델 설정 변경 0 · 로컬 commit + pytest PASS only · verifier task-2711+1 분리. 끝