# task-2709+1 — task-2709 infra defect 1 fix 독립 검증 보고서 (READ-ONLY)

- **task_id**: task-2709+1
- **task_type**: read_only (Maat 독립 검증 lineage)
- **verifier**: dev2-team / 오딘 (Odin)
- **executor 피검증**: dev1-team / 헤르메스 (Hermes)
- **chair_authorization_id**: CHAIR-AUTH-TASK-2709PLUS1-DEFECT1-FIX-INDEPENDENT-VERIFICATION-READONLY-260529
- **검증 대상 커밋**: 9cec904f / 7df68c04 / 50bdce87
- **판정**: **ACCEPT_WITH_KNOWN_CAVEATS** (8/8 PASS + infra defect 2 known caveat)
- **작성 시각**: 2026-05-29 21:08 (KST)

---

## S (Situation) — 상황

task-2709(infra defect 1 = `allowed_resources` schema cross-key mismatch fix)는 dev1 헤르메스 팀이 구현 완료하고 `IMPLEMENTATION_COMPLETE_DEFECT1_FIXED_BUT_COMPLETION_BLOCKED_BY_INFRA_DEFECT2` 후보로 self-attestation 했다. 회장 verbatim 인가에 따라, **executor(dev1) ≠ verifier(dev2) 분리 강제** doctrine 하에 dev2 오딘이 defect 1 해결 여부만 독립 검증한다(completion routing 성공 여부는 별도 caveat).

## C (Complication) — 문제

- 봇 self-attestation은 신뢰 대상이 아니라 **독립 재현 검증 대상**이다.
- task-2709의 completion routing이 막혔는데, 그 원인이 defect 1 미해결인지 / 별개의 infra defect 2(shared branch contamination)인지 분리 판별이 필요하다.
- 검증자는 read-only 범위만 가지며 어떤 production code도 수정/실행 finish 해서는 안 된다.

## Q (Question) — 질문

task-2709의 infra defect 1 fix는 (a) dispatch/scope-guard 양쪽 layer에서 정상 동작하고, (b) 기존 paths-key 스키마와 신규 expected_files 스키마 모두 호환되며, (c) forbidden 강제·self scope violation 0을 유지하는가? 그리고 completion block의 진짜 원인은 무엇인가?

## A (Answer) — 답변

**8개 검증 항목 전부 PASS.** infra defect 1은 완전 해결되었으며, completion routing block의 원인은 defect 1이 아니라 **infra defect 2(shared branch contamination)** 임을 독립 재현으로 확인했다(65건 위반, 전부 외부 오염·task-2709 자체 0건).

### 8 검증 항목 결과 (회장 verbatim §2 1:1)

1. **dispatch.py cross-key normalization (BOTH layer)** — **PASS**
   - `_normalize_allowed_resources()` 신규 함수 추가. `_parse_allowed_resources`(yaml) + `_parse_allowed_resources_regex`(정규식 fallback) **양쪽**에서 호출 → BOTH layer 정합.
   - `paths` 비면 `expected_files ∪ allowed_existing_file_edits` union. 기존 `paths` 채워져 있으면 그대로 유지(backward compatible). 입력 dict 비파괴(`ar = dict(ar)`).

2. **task-scope-guard.sh cross-key fallback (L63-65)** — **PASS**
   - `paths = list(ar.get("paths") or [])` 후 비면 `expected_files ∪ allowed_existing_file_edits` OR union. `forbidden_paths` 라인 그대로 보존.

3. **paths key backward compatibility (task-2706)** — **PASS**
   - task-2706 snapshot은 `paths` key list 박힘(baseline). scope-guard replay → `PASS: 1 files in scope` (EXIT=0). 기존 동작 100% 유지.

4. **expected_files schema compatibility (task-2707/2708)** — **PASS**
   - task-2707/2708 snapshot은 `paths=null`, `expected_files` only. cross-key fallback normalization 후 scope-guard replay → 둘 다 PASS (2707: 1 file, 2708: 2 files, EXIT=0).

5. **mixed schema compatibility (task-2709)** — **PASS**
   - task-2709 snapshot은 `paths` AND `expected_files` 둘 다 채워짐(dogfooding). replay → `PASS: 2 files in scope` (EXIT=0). deterministic merge 안정.

6. **forbidden_paths priority (L121 verbatim)** — **PASS**
   - scope-guard L121 주석 `forbidden_paths 우선 매칭 (시스템 무시보다 먼저 — forbidden은 항상 강제)` 박제. forbidden 파일(`finish-task.sh`, `qc_verify.py`) 주입 시 paths fallback에도 불구하고 FAIL 감지(EXIT=1, 2건 위반). forbidden 강제 유지 확인.

7. **task-2708 replay PASS 재현** — **PASS**
   - 봇 self-attestation `scope_guard_smoke_RS3_task2708_replay=PASS` → 독립 재실행 동일 PASS(2 files in scope) 재현. false positive 0.

8. **task-2709 자체 scope violation 0** — **PASS**
   - 봇 3커밋 변경 4파일(`dispatch/__init__.py`, `scripts/task-scope-guard.sh`, `tests/test_allowed_resources_paths_normalization.py`, `memory/reports/task-2709.md`) → scope-guard `PASS: 3 files in scope` (report는 SYSTEM_IGNORE). **self_file_scope_violations = 0**.

### 회귀 스모크 (read-only)

- 단위 테스트: `tests/test_allowed_resources_paths_normalization.py` **8/8 PASS** (RS-1~5: backward compat / 입력 비파괴 / forward compat union / task2708 replay / empty union / mixed priority).
- scope-guard replay: task-2706/2707/2708/2709 **전부 PASS** (회귀 0).
- 봇 self-attestation 교차검증: marker(unit 8/8, existing scope 11/11, forbidden_files_changed=0)와 독립 재현 결과 **일치**.
- forbidden core files sha256 검증 전후 **불변**.

---

## L1 스모크테스트 결과 (필수 기록)

- **서버 재시작**: 해당없음 (read-only 검증 작업 · 서버 코드 미수정)
- **API 응답 확인**: 해당없음 (백엔드 API 무관 · scope-guard CLI 실동작으로 대체)
- **실동작 검증(pytest 대체 아님)**: `bash scripts/task-scope-guard.sh` 실제 호출 4종(2706/2707/2708/2709) + forbidden 주입 1종 + self 4파일 1종 = **실 CLI 실행**으로 normalization·forbidden·self-scope 동작을 직접 관측 (EXIT code + stdout 박제). pytest PASS에 의존하지 않고 실제 scope-guard 바이너리 실행으로 확인.
- **스크린샷**: 해당없음 (프론트엔드 무관)

---

## 발견 이슈 및 해결

- **이슈 1 (검증자 부작용·전면 공개)**: item 6 forbidden 기능테스트 중 scope-guard가 부작용으로 untracked 런타임 파일 `memory/events/task-2709.scope-violation.json`을 덮어씀(2건). 
  - **해결**: item 8 검증 과정에서 실제 working-tree contamination diff(73 files)로 scope-guard를 재실행하여 **진본 65건 contamination 증거**로 재생성. 원본(58건 기록 시점)은 untracked 파생 아티팩트라 git 복원 불가하나, `58 violations · self 0` 본질 증거는 task-2709 보고서 및 escalation-detail JSON에 보존됨. defect-1 판정에 영향 없음.
- **미해결 이슈**: 없음 (defect 1 범위 내).

---

## 5 ENUM 판정 및 근거

- **최종 판정: `ACCEPT_WITH_KNOWN_CAVEATS`**
- **근거**: 8/8 items PASS + smoke 회귀 0 → FULL_ACCEPT 후보였으나, parent task-2709의 completion routing은 **infra defect 2(shared branch contamination)** 로 여전히 block. 본 verifier가 실제 diff로 65건 contamination을 독립 재현(전부 외부 오염, task-2709 자체 0건). defect 1은 완전 해결이나 known caveat(defect 2)가 잔존·문서화됨 → 회장 verbatim §4/§101 정합.
- **귀결**: infra defect 1 **closeout 후보** + infra defect 2 **다음 우선순위 승격 후보**.

### Known Caveats
- **CAVEAT-1 (infra defect 2)**: completion block 원인 = shared branch contamination(65건 위반 재현, task-2709 자체 0건). 본 task OUT-OF-SCOPE · 다음 우선순위 승격.
- **CAVEAT-2 (검증자 프로세스 노트)**: 위 '발견 이슈 1' 참조. 전면 공개.

---

## OUT-OF-SCOPE 준수 (위반 0)

infra defect 2 해결 시도 0 · completion routing 평가 0 · branch 재구성/main merge 0 · finish-task.sh 재실행 0 · `.done` 생성 0 · self-key callback cron 0 · dispatch/scope-guard 수정 0 · GitHub write/PR/push/merge 0.

---

## 산출물 (verifier artifacts only · 4 files)

1. `memory/events/task-2709+1.decision.json` — 5 enum verdict + 8 items 박제
2. `memory/reports/task-2709+1.md` — 본 SCQA 보고서
3. `memory/events/task-2709+1.callback-envelope.json` — ANU envelope (≤3900 bytes)
4. `memory/events/task-2709+1.dispatched-20260529.json` — dispatch.py 자동 생성

## 모델 사용 기록

- 팀장(오딘/Opus) 단독 수행. 본 작업은 read-only 독립 검증(증거 수집 + 판정)으로, 팀장의 판단·검토 역할의 핵심 범위이며 코딩 위임 대상이 아니다. 팀원(토르/프레이야/미미르/헤임달) 소환 없음.

## ANU Doctrine Compliance

- executor(dev1 헤르메스) ≠ verifier(dev2 오딘) 분리 강제 준수.
- evidence-only · ANU 자체 분류 결정 0 · ANU 자체 FULL_ACCEPT 0.
- ANU normal callback cron 등록은 ANU key(`c119085addb0f8b7`)로 별도 spawn (self-key 0).
