# task-2785 — merge_group auditor/resolver observability diagnostics (additive, ACTIVE=false)

## 레벨
Lv3 (auditor/resolver additive diagnostics + 회귀). 코드 작업. **코드+테스트+worktree 커밋+ANU 보고까지. PR 생성 금지(ANU 별도 승인 후).**

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "scripts/merge_group_pr_resolver.py"
    - "scripts/merge_group_evidence_auditor.py"
    - "tests/regression/test_merge_group_evidence_auditor_2781.py"
    - "memory/reports/task-2785.md"
  forbidden_paths:
    - ".github/**"
    - ".git/hooks/**"
    - "scripts/gemini_review_gate.py"
    - "scripts/gemini_evidence_verify.py"
    - "scripts/finish-task.sh"
    - "utils/**"
    - "dispatch.py"
    - ".claude/**"
    - ".env*"
    - "memory/state/**"
  commands:
    - "git"
    - "pytest"
    - "python3"
  merge_policy: "none"
  ttl_hours: 8
```

## 목표 (한 줄)
auditor/resolver가 `MERGE_GROUP_PRS_UNRESOLVED` 또는 gh api 실패를 낼 때 **어느 tier가 무엇을 시도했고 왜 실패했는지**(tier/api_path/rc/stderr_snip/accept 거부 사유)를 **verdict JSON의 `diagnostics` 필드**에 남긴다. **순수 additive diagnostics** — status enum·exit code·PASS/FAIL 판정 로직·resolve 대상 **불변**.

## 단일 소스 (반드시 먼저 읽을 것)
설계 packet: `memory/reports/pr265_observability_microfix_packet_260704.md` (§2 현재 구조·§4 설계·§5 불변·§7 테스트 그대로).
관측 근거: `memory/reports/pr265_stage1_dryrun_5f707910_260704.md`.

## 현재 구조 (merged main 5f707910)
- `merge_group_pr_resolver.py`: `_gh_api`/`_gh_graphql`가 실패 시 `proc.stderr`를 capture하나 **버림**. 3-tier(`resolve_via_api`/`resolve_via_event_context`/`resolve_via_ref_and_trailers`)가 각 `[]` 조용히 반환. `resolve_merge_group_prs`가 tier별 내역 없이 `raise MergeGroupPRsUnresolved`.
- `merge_group_evidence_auditor.py`: `audit_merge_group`이 예외 시 `status=MERGE_GROUP_PRS_UNRESOLVED`, reason "after all 3 tiers"만.

## 구현 요구 (설계 packet §4 verbatim)
1. **gh wrapper diagnostics sink (구현안 b·시그니처 불변)**: `_gh_api`/`_gh_graphql`의 기존 반환 `(rc, data)`/`(rc, {})` **유지**. 실패(rc!=0/empty/JSONDecode/timeout/Exception) 시 전달식/모듈-레벨 **diagnostics sink(list)** 에 `{tier, api_path, rc, stderr_snip}`(stderr는 앞 N자 snippet) 누적. **시그니처 변경 금지.**
2. **tier별 시도/실패 기록**: `resolve_merge_group_prs`가 각 tier에 `{tier:"api|event|ref", invoked:bool, entry_count:int, accepted:bool, reject_reason:"empty|incomplete_entry|exception", gh:[{api_path,rc,stderr_snip}]}` 누적.
3. **예외에 diagnostics 부착**: `MergeGroupPRsUnresolved`에 `.diagnostics`(list) 부착 → `audit_merge_group`이 verdict JSON 신규 **`diagnostics`** 필드에 실어 출력.
4. **출력 채널**: verdict JSON `diagnostics` 필드가 1순위(기계판독 원본). stderr는 **선택적 1줄 요약**만 허용.
5. **조회 repo slug 노출**: diagnostics에 실제 조회한 `repo` slug 포함(DEFAULT_REPO 불일치가 향후 자동 표면화. 단 **slug 값 수정 금지**).

## ★ 불변 (변경 금지 — 회귀 0 보장선)
- status enum 8종 의미 변경 금지 · exit code 의미 변경 금지(0=PASS/1=그 외) · PASS/FAIL 판정 로직 변경 금지 · resolve 대상/resolver 추적 범위 변경 금지.
- **`commits/{sha}/pulls` fallback 추가 금지**(추적범위 확장=별도 안건) · **repo slug 값 수정 금지**(별도 backlog `PR265_DEFAULT_REPO_SLUG_MISMATCH_CONFIG_HYGIENE_BACKLOG`).
- diagnostics는 **순수 additive**(설명만 추가, 결과 불변).

## 테스트 요구 (신규 회귀)
1. 모든 tier fail → `MERGE_GROUP_PRS_UNRESOLVED` 시 verdict JSON에 `diagnostics`(tier별 시도/거부 사유) 존재.
2. gh api 실패 mock(rc!=0 + stderr 주입)에서 diagnostics에 `rc`·`stderr_snip`·`api_path`·`tier` 존재.
3. PASS 케이스의 status/exit code/기존 필드 불변(diagnostics 추가가 결과 안 바꿈) assert.
4. `--publish-check` 없는 실행에서 check-run 생성 0.
5. 기존 task-2781 회귀 **13 유지** · PR#263 P1 **36** · PR#264 **10** (통합 **59**).
6. diagnostics에 조회 repo slug 포함 확인.

## 검증
- `pytest tests/regression/test_merge_group_evidence_auditor_2781.py` 전체 PASS(개수 명시) + 통합 59.
- diff **3파일**(expected_files)뿐 · forbidden(.github/ruleset/utils/gemini gate/finish-task) 무접촉.
- status enum/exit code/PASS-FAIL 불변 확인.

## 금지 (전부)
`.github` 수정 · ruleset/branch protection · required check 등록 · Merge Queue activation · `--publish-check` 사용 · check-run 생성 · workflow 연결 · production activation · ACTIVE=true · resolver 추적 범위 확장(commits/{sha}/pulls) · repo slug 값 수정 · status enum/exit code/PASS-FAIL 로직 변경 · PR 생성 · merge.

## STOP_REPORT 조건
expected_files 3개 밖 수정 필요 · status/exit/판정 로직 변경 필요 · resolver 추적 범위 확장 필요 · repo slug 수정이 cross-env 영향 · `.github`/ruleset/required/Merge Queue/`--publish-check` 요구 · 회귀(13/36/10) 깨짐 · activation 표현 등장.

## 산출물 & 보고 (PR 없음 — ANU 보고까지만)
1. worktree 커밋(브랜치). **PR 생성 금지**(ANU 독립검증 후 별도 승인 시).
2. ANU 보고: diff(3파일)/pytest 결과(통합 59)/diagnostics 동작(UNRESOLVED·gh 실패 mock)/status·exit·PASS-FAIL 불변/check-run 0/forbidden 무접촉.
3. 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B).

## 검증 루프
자체 리뷰 1회 → pytest 통과(통합 59) → 3파일 diff·forbidden 무접촉 → status/exit/판정 불변 → additive 확인.

## goal_assertions (auto-generated)
- `pytest tests/regression/test_merge_group_evidence_auditor_2781.py`