# task-2554+2 context notes

## 3 Step Why (회장 §명시 해석 2 승인 1:1)

**1st Why: 왜 이 설계가 필요한가?**

A. PR #105 (task-2554+1 head 08f2d29c) 가 IMPLEMENTATION_INCOMPLETE_PER_OWNER_SPEC. Gemini fresh medium 3건 잔존 (회장 §1~§2 직접 미충족):
- `_iter_rows` O(N) full scan → 회장 §2 bounded/reverse scan 위반
- `RESULT_PENDING` import 누락 → 회장 §2 sentinel 미사용
- `http_post` 직전 PENDING 미기록 → 회장 §2 crash-safety fail-closed 위반

또한 §3 (executor integration), §4 (file evidence), §5 (regression fixtures) 가 PR #105 에 부재. capability 통합 완성이 main 미반영 상태 — task-2554+1 ESCALATED 경로의 근본 차단 요인.

**2nd Why: 왜 A 가 최선의 접근인가?**

B. PR #105 추가 수정 (재push) 은 회장 §명시 금지 (chain 정책 — code-changing 재발 시 OWNER_DECISION_REQUIRED). 회장 §명시 옵션 E (해석 2) "5층 통합 완성 별도 PR" 승인.
- PR #105 close 보존 (lineage 박제)
- 새 PR 으로 §1~§5 1:1 박제 + 6 신규 fixture 로 regression catch
- 단일 task 안에서 5 layer 통합 — markdown only 가 아닌 실제 capability 가 main 에 박제

**3rd Why: 왜 B 가 다른 대안보다 나은가?**

C. 대안 비교:
- 대안 1 (PR #105 force-push 보완): 회장 §명시 금지 (forbidden 18 #2/#7/#10)
- 대안 2 (Gemini medium 무시 + merge): 회장 §명시 unresolved > 0 시 same-PR push 0 + 회장 결정 대기 — capability 결함 박제 위험
- 대안 3 (별도 PR 으로 §1~§2 만 보완): §3~§5 누락 → capability incomplete 잔존, task-2554+3 발행 필요
- 대안 4 (본 task 선택, 5 layer 통합): 회장 §명시 옵션 E 해석 2 직접 승인 — 단일 PR 으로 capability 완성

→ 대안 4 가 회장 §명시 직접 일치 + capability 완성 + chain 정책 보존.

## 주요 결정 근거

### 결정 1: PR #105 baseline 코드 재활용
- PR #105 head 08f2d29c 의 `owner_trigger_only.py` / `owner_trigger_audit.py` / `owner_trigger_decision.py` 는 race fix + 2단 lock 구조가 회장 §명시와 일관.
- §1~§2 fix 만 적용 (3 medium 보완), 나머지는 그대로.
- 7 existing test files 도 carry-over (104 baseline tests 보존).

### 결정 2: bounded reverse scan 설계
- audit JSONL 이 시간순 append-only — 최신 trigger 는 끝에. tail-read 또는 last N rows 캐싱이 자연.
- `_iter_rows_reverse(max_rows=N)` helper 추가, `_has_posted` / `_has_active_trigger` 가 사용.
- N=512 (한 PR/head 에 대한 trigger 시도가 512건 넘으면 다른 운영 문제) — 회장 §2 bounded.
- 기존 `_iter_rows` 는 호환성 보존 (legacy/test 가 사용 가능).

### 결정 3: PENDING sentinel 위치
- `trigger_gemini_review` 흐름:
  1. txn.check_dedupe (POSTED + PENDING)
  2. txn.record(PENDING) — http_post 직전
  3. http_post 호출
  4. 성공: txn.record(POSTED), 실패: txn.record(FAILED)
- crash-safety: http_post 호출 직전 crash → PENDING 기록은 살아있어 다음 runner 가 DEDUPED 판정.
- PENDING dedupe 은 transaction.check_dedupe 가 이미 처리 (PR #105 baseline 보존).

### 결정 4: merge_queue_executor minimal patch
- 기존 `evaluate` flow 변경 X. 새 method `evaluate_owner_trigger_required(pr, gemini_review_commit_id)` 만 추가.
- runner 호출 + marker 생성도 helper method 로 분리.
- Phase 외 변경 0 (회장 §명시 forbidden_paths 1:1).

### 결정 5: 6 신규 fixture 설계
1. `test_owner_trigger_bootstrap_gap_pr105` — head 08f2d29c 시 stale 1e907722 review 만 존재 → OWNER_TRIGGER_REQUIRED 판정
2. `test_owner_trigger_fresh_medium_3_2554plus1` — §1~§2 충족 시 unresolved 0
3. `test_owner_trigger_dedupe_same_head` — 동일 (pr, head) 2회 호출 시 2번째 DEDUPED
4. `test_owner_trigger_head_changed_fail_closed` — runner 호출 후 head 변경 감지 → 즉시 FAILED
5. `test_owner_trigger_token_unavailable` — OWNER_GEMINI_TRIGGER_TOKEN 부재 → FAILED + audit
6. `test_executor_posted_but_no_fresh_evidence` — post 후 24h+ fresh 미도착 → marker 생성 + ESCALATED 분류 (auto-resume X)

## 안전 절차

- Codex 사전 검증 PASS 필요 (G1)
- Sanitize gate: 외부 AI 호출 시 PII 마스킹 (실 token 0, owner repo SHA 만 노출)
- forbidden path 0 어셀션 (PR #104 head 4e8f89795ab1 / PR #105 head 08f2d29c unchanged)
- chain 정책: 본 PR Gemini fresh review 도착 후 push 0. code-changing 재발 시 OWNER_DECISION_REQUIRED (자동 task-2554+3 X)
