# task-2719-check 보고서 — PR #165 bot-invoked one-shot check (read-only)

## SCQA

- **Situation**: PR #165 (`task/task-2719-dev1`, head `af05d588`)에는 이미 만들어진 부품(runner+adapter)이 존재한다. 회장 인가(2026-05-31): ANU 직접 manual-gated verification 금지, 봇이 자동화 부품을 **1회 실행**해 PR #165 를 read-only 체크한다.
- **Complication**: active watcher 승격 금지 · 실 GitHub write 금지 · `/gemini review` 실제 comment 금지 · 코드 수정 금지 · polling/sleep loop 금지. 봇은 terminal result JSON 만 작성, ANU 가 그것만 수집·보고.
- **Question**: 신규 구현 0·write 0·dry_run 고정 상태에서 PR #165 의 terminal enum 1개를 산출할 수 있는가?
- **Answer**: 가능. `run_one_shot_dry_run(pr=165, dry_run 고정)`을 worktree(af05d588)에서 1회 실행 → **`MERGE_READY_CANDIDATE`**, github_writes=0. 2회 독립 재현 동일.

## 실행 내용 (read-only, 실행/조회만 — 코드 수정 0)

부품(무수정 import-only 실행):
- runner: `anu_v2.ci_gemini_watcher_runner.run_watch_cycle`
- adapter: `anu_v2.ci_gemini_watcher_gh_adapter.run_one_shot_dry_run` → `build_readonly_gh_runner` + `default_gh_cli`(실 gh GET-only, write guard 내장)
- worktree: `/home/jay/workspace/.worktrees/task-2719-dev1` (PR #165 head `af05d588`)

회장 verbatim 체크 1~9 결과:
1. PR #165 head `af05d58881d6099013086aad148e244cd37bb02c` 확인 ✓
2. diff 2파일 only 확인 (`anu_v2/ci_gemini_watcher_gh_adapter.py`, `tests/regression/test_ci_gemini_watcher_gh_adapter_2719.py`) ✓
3. gh_adapter op 5종 read-only 조회: actual_head / diff_paths / ci_rollup / reviews / findings ✓
4. `run_watch_cycle` 실행 (adapter 주입, dry_run=True 고정) ✓
5. owner_gemini_trigger = decision-only (trigger_decision=NONE) ✓
6. auto_gemini_triage = finding 분류 사용 (applied 4 / dismissed 0 / escalated 0) ✓
7. GitHub write 0 ✓ (`github_writes=0`, 계약 assert PASS)
8. 실제 `/gemini review` comment 0 ✓ (gemini_freshness=FRESH → 재트리거 불요)
9. terminal enum 1개: **`MERGE_READY_CANDIDATE`** ✓

## 결과 요약

- terminal_enum: **MERGE_READY_CANDIDATE**
- ci_state: SUCCESS / gemini_freshness: FRESH / triage: applied 4, escalated 0
- github_writes: **0** / dry_run: **true** / gemini_trigger_needed: **false**
- head_match: true / scope_clean: true (2파일)
- 산출물: `memory/events/task-2719-check-result.json`

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

- 서버 재시작: 해당없음 (서버 기동 작업 아님 — read-only 모듈 실행 체크)
- API 응답 확인: 실 `gh` GET-only 호출로 PR #165 actual_head/diff/ci/reviews/findings 실측 → `run_one_shot_dry_run` 정상 반환. **2회 독립 재현 결과 동일**. 계약 assert(github_writes==0 ∧ dry_run==True ∧ actual_head==expected_head) PASS.
- 스크린샷: 해당없음 (CLI/모듈 실행, 프론트 아님)
- 비고: pytest 단독이 아닌 **실제 모듈+실 gh GET 실행**으로 실동작 확인. GhWriteForbiddenError 미발생, stderr 에러 0.

## 모델 사용 기록

- 아르고스(테스터): sonnet — read-only one-shot 실행 (단순 실행/조회, 단 read 검증 성격상 sonnet 사용)
- 팀장(Hermes, Opus): 오케스트레이션·독립 재현 검증·result JSON/보고서 작성

## 금지사항 준수 확인

코드 수정 0 · 실 GitHub write 0 · `/gemini review` 실제 comment 0 · push/merge/rebase/admin 0 · polling/sleep loop 0 · OS-level crontab/systemd/inotify 0 · PR #162/#163/#164 미접촉 · adapter/runner/test 코드 미수정. dispatch 템플릿 G3(PR/머지) 미적용(코드 변경 0 → PR 생성 없음, `finish-task.sh --action pr` 금지).

## QC 게이트 결과 — ESCALATE (아누 판단 필요)

작업(PR #165 read-only check) 자체는 **완료·정상**이나, finish-task.sh QC 게이트가 **구조적으로 통과 불가**하여 **ESCALATE** 되었습니다. `.done` 미생성(수동 생성 금지 준수), `.escalate` 마커 생성됨.

`.escalate` 사유: 동일 verifier 3회 연속 FAIL — `browser_verify`, `data_integrity`, `git_evidence`.

### 근본 원인: task_id 형식 비호환 (인프라/디스패치 결함, 작업 결함 아님)

dispatch 가 할당한 task_id **`task-2719-check`** 는 시스템 통일 검증 정규식(`^task-N[.N][_P.P][_x][+R]$`, `utils/task_id_parser.is_valid_task_id`)에 **위반**됩니다(`-check` suffix 불허). 이 검증기는 타이머·QC 전반에서 일관 적용되어 아래 3건이 모두 막힙니다:

- **data_integrity (MANDATORY) FAIL**: `task-timer.py start task-2719-check` 자체가 동일 정규식으로 거부 → task-timers.json 등록 불가 → "task not found". (등록 시도했으나 형식 거부됨)
- **browser_verify FAIL**: `is_valid_task_id("task-2719-check")==False` → 형식 단계에서 즉시 FAIL (프론트 변경 0이라 형식만 통과하면 SKIP될 항목).
- **git_evidence FAIL**: COMMIT_EXISTS 0건. 본 task 는 read-only(코드 수정 0)이며 산출물은 gitignore 대상(`memory/events/`)이라 커밋 evidence 부재.

### 제약 준수 (회장 verbatim)

- 코드 수정 0 — QC verifier / 검증기(`task_id_parser`) **수정하지 않음** (forbidden + "code fix 0").
- QC **우회 시도 없음** (`--skip` 미사용, 수동 `.done` 미생성).
- task_id 변경 없음(이벤트/디스패치 추적 무결성 보존, 팀장 권한 밖).
- 결과적으로 게이트를 정직하게 ESCALATE → 아누 판단에 위임.

### 아누/회장 권고

1. 본 task 의 실제 산출물은 `memory/events/task-2719-check-result.json` (terminal=MERGE_READY_CANDIDATE, github_writes=0). 태스크 정의대로 **ANU 가 이 JSON 만 수집·보고**하면 작업 목적은 달성됨.
2. `.done` 발급이 필요하면, 다음 중 하나를 ANU/디스패치 측에서 처리 권장:
   - task_id 를 형식 적합값(예: `task-2719+1` 또는 `task-2719_1.0`)으로 relabel 후 재dispatch, 또는
   - 검증 정규식에 `-check` 류 suffix 허용(인프라 수정 — 별도 task 필요).
3. ANU normal callback: dispatch 시점에 무장된 fallback safety-net(recovery-only)이 본 비완료 상태를 회수하도록 설계됨. 봇은 self-key 콜백 자가등록을 시도하지 않음(SELF_COLLECTOR_FORBIDDEN 준수).

## 비고

- ANU normal callback = ANU key `c119085addb0f8b7`, envelope-only (단일 launcher 경유, executor self-key fail-closed).
- 본 task 는 **active watcher 가 아닌 bot-invoked one-shot check** — wired/active 승격 없음.
- 터미널 상태: 작업 PASS(MERGE_READY_CANDIDATE) / 완료 게이트 ESCALATE(task_id 형식 인프라 결함).

## 세션 통계
- 총 도구 호출: 0회

