---
task_id: task-2471
type: context
scope: task
created: 2026-05-07
updated: 2026-05-07
status: in-progress
---

# 맥락 노트: task-2471

**task**: task-2471

---

## 결정 근거

### 1. silent_corruption_guard 별도 모듈로 분리
- `utils/silent_corruption_guard.py` 신설 — taskctl/lifecycle_guards/외부 호출 모두에서 재사용
- 대안 (taskctl 내부 함수만 추가)은 기각: lifecycle_guards에서도 같은 검증이 필요할 수 있음 + regression test 작성 용이성

### 2. RECOVERABLE_BLOCKED state 추가 위치
- `MERGING → {MERGED, FAILED, RECOVERABLE_BLOCKED}` 확장
- `RECOVERABLE_BLOCKED → {MERGING, FAILED, ESCALATED}` 양방향 진입 허용
- terminal 아님 (FAILED와 차이)
- 객관 4 조건 (review threads resolved + CI PASS + Gemini High 0 + scope-guard 0 + mergeStateStatus CLEAN) 충족 시 자동 MERGING 전이 + audit jsonl

### 3. dispatch.py +N suffix 처리
- `--task-id` 명시 옵션은 이미 존재 (4041행) — 자동 증분 미발생 확인됨
- 핵심 수정: `--task-file` 사용 시 파일명에서 task ID 자동 추출 (없으면 자동 생성). 이때 `+N` 보존.
- `_sync_counter_if_needed`는 `+N` 무관하게 base ID 추출이라 안전 — 하지만 task-2469+1을 task-2470으로 변환하는 곳은 명확히 차단

### 4. pre_push_guard 4결함
- numbered heading: `## 7. allowed_resources` 인식 — 정규식 `r"^##\s+(?:\d+\.\s+)?allowed_resources\s*\n```"`로 확장
- inline comment strip: `- "path"  # comment` → path만 추출. 따옴표 포함 path 처리.
- +N branch parsing: `task/task-2467+3-dev6` → `task-2467+3` 추출 (regex `task-\d+(?:\+\d+)?`)
- task 파일 부재 시 fail-closed: `_resolve_allowed_resources`가 `None`이면 sys.exit(1) (현재는 None+에러 메시지로 sys.exit 동작 → 검증)

### 5. Gemini image severity 탐지
- `![high](...)` 패턴: `_HIGH_INLINE_LABEL`은 `**High:**`만 인식 → 이미지 마크다운은 누락
- 신규 정규식: `r"!\[\s*(High|Critical|Blocking)\s*\]\("` (대소문자 무관)
- code block strip 이후 적용

### 6. P0-6 SHA fetch race fix
- `fetch_origin_head_sha`는 `git rev-parse origin/main`만 호출 — race 조건 발생 가능
- 수정: 호출 전 `git fetch origin --no-tags +refs/heads/main:refs/remotes/origin/main` 강제
- 2회 교차 검증: fetch → SHA 1차 조회 → 0.5초 대기 → SHA 2차 조회 → 일치하면 PASS / 불일치면 1회 재시도

### 7. 3 Step Why 자문 (회장 §3 Step Why)
- **1st Why: 왜 이 설계가 필요한가?**
  → A: green path 자동화 신뢰성 확보. 회장 수동 개입 5건 발생 패턴(silent corruption / state FAILED terminal / dispatch ID 충돌 / pre_push_guard 결함 / Gemini gate 우회)을 영구 차단해야 향후 모든 task 자동화가 가능.
- **2nd Why: 왜 A가 최선의 접근인가?**
  → B: 8개 결함을 1차로 묶어 hardening — 분리하면 (1) 새 결함 추가 시 기존 hardening과 정합성 깨짐 (2) 자기 hardening으로 자기 PR 머지하는 drink-your-own-champagne 검증 불가 (3) regression test 묶어서 작성하면 inter-dependency 검증 가능.
- **3rd Why: 왜 B가 다른 대안보다 나은가?**
  → C: 대안 (각 결함을 별도 task로 분리)은 의존성 누락 위험. 예: state machine 확장 없이 silent_corruption_guard 적용 시 RECOVERABLE_BLOCKED 진입 불가 → silent corruption guard FAIL 시 곧장 FAILED terminal 진입 → 회장 수동 개입 재발. 8건이 한 묶음이어야 자동화 폐쇄 회로가 닫힌다. + 회장 명시 "1차 hardening"이라는 요구사항이 task-2471 한 task에 모두 포함됨을 강제.

A-B-C 일관: green path 자동화 → 결함 묶음 처리 필수 → drink-your-own-champagne로 자체 검증.

## 참조 자료

- task spec: `memory/tasks/task-2471.md`
- 회장 hardening 승인: `task-2469 manual recovery DONE (origin/main 2e8f0697)`
- 선행 사고 보고서: `memory/reports/task-2468.md`, `memory/reports/task-2469.md`, `memory/reports/task-2470.md`
- 기존 lifecycle_guards: `scripts/lifecycle_guards.py:565-696` (P0-6 SHA fetch)
- 기존 taskctl done: `scripts/taskctl.py:1536-1606` (cmd_done — mergedAt/mergeCommit 검증 누락)
- 기존 pre_push_guard: `scripts/pre_push_guard.py:139-167` (allowed_resources YAML parser — heading regex 결함)
- 기존 dispatch task ID: `dispatch/__init__.py:1611-1748` (4-layer counter)

## 주의사항

- ★ task-2468/2469/2470 산출물(events/reports/orchestration-audit) 변경 절대 금지 (allowed_resources forbidden)
- ★ 자동 ack 데몬 / cron / watchdog 코드 작성 시 즉시 reject (회장 명시 범위 위반)
- ★ admin override 사용 금지 — drink-your-own-champagne 핵심
- ★ self-approve 차단 강제 (`PR author = jeon-jonghyuk-taskctl-bot[bot]`)
- ★ 본 task PR이 머지되어야 합격 — 자기 hardening 코드로 자기 PR 머지 검증
- ★ 코드 변경 후 즉시 grep 검증 (Edit 직후)
- ★ pytest 시 worktree 경로 의존성 제거 (test_transitions.py 처럼 hardcode WORKSPACE 금지)
