---
task_id: task-2463
type: context
scope: task
created: 2026-05-05
updated: 2026-05-05
status: completed
---

# 맥락 노트: task-2463

**task**: task-2463 (Phase 3 재정의)

---

## 결정 근거

### 결정 1: task-2461 freeze 재적용 범위 명시

- task-2461의 12 commits 중 task-2463 P0 (5개)와 일치하는 부분만 명시 재적용
- **재적용 (P0와 정렬)**:
  - P0-1 (finish-task.sh sentinel hard gate) — task-2463 P0-1 보강
  - P0-2 (worktree_manager sentinel + --exit-on-block) — task-2463 P0-2 부분 일치
  - P0-3 (finish-task.sh main SHA hard gate, done-watcher.py main SHA) — task-2463 P0-1 + 2차 방어
  - P1-1 (gemini neutral → failure) — task-2463 P0-3 정확 일치
  - P1-2 (ci.yml phase3-merge-gate) — task-2463 P0-3 #4 정확 일치
  - guard.yml Phase 3 marker check — task-2463 P0-1 보조
  - post_merge_probe.py squash fallback — 회귀 방지 차원 적용
  - tests/phase3_hard_gate/ — 회귀 테스트로 채택
- **재적용 안 함 (task-2463 영역 외)**:
  - P2-1 (pre-push taskctl_verify strict) — taskctl_verify.py 부재 + forbidden_paths이므로 strict 강제 시 모든 push 차단됨. 본 task에서는 fallback 유지.
  - P2-2 (safe_pr_merge.sh wrapper) — 적용. 단 wrapper가 TASKCTL_INVOKED=1을 추가 검증하도록 수정.
- **신규 추가 (task-2463 NEW)**:
  - finish-task.sh에 `taskctl verify <task-id>` + `taskctl merge <task-id>` 호출 (P0-1)
  - worktree_manager.py에서 `gh pr merge` 직접 호출 0줄 **제거** (P0-2: 단순 sentinel 추가가 아님)
  - .github/workflows/guard.yml에 worktree_manager.py 정적 grep 검사 (P0-2 #4)

### 결정 2: taskctl merge 자동 호출 vs 수동

- taskctl.py:cmd_merge는 HUMAN_APPROVED 상태 요구. 자동 호출 시 state machine 위반 가능성.
- 본 task 결정: finish-task.sh는 `taskctl verify`만 강제 호출 (P0-1 #1).
  - `taskctl merge`는 verify PASS + 모든 게이트 통과 시 호출. 실패 시 .merge-failed 생성.
  - state가 HUMAN_APPROVED 아니면 taskctl merge가 자체 차단 → 단일 출입구 효과 달성.
- 대안 기각: 자동 takeover로 모든 state 강제 전환 → state machine 무력화 위험. 회장 의도 위배.

### 결정 3: 라이브 차단 4 로그 — 실제 시스템에 영향 없는 시뮬레이션

- 4 로그를 만들기 위해 실제 PR open/merge 트리거하면 부작용 큼.
- 본 task 결정: **shell-level 단위 시뮬레이션**으로 캡처
  - 로그 1 (gemini 0건): `python3 scripts/gemini_review_gate.py` 직접 호출 (no API key)
  - 로그 2 (worktree_manager 직접): `grep` 정적 검사 결과 + sentinel 출력 검증
  - 로그 3 (PR open .done 차단): finish-task.sh의 PR check 블록을 Mock PR_STATE=OPEN 환경변수로 주입 후 직접 실행
  - 로그 4 (taskctl bypass): `bash scripts/safe_pr_merge.sh` (no TASKCTL_INVOKED) → 차단 메시지
- 5필드 (명령/stderr/exit/레이어/timestamp) 모두 필수 박제

### 결정 4: anu_confirm_bot/** 격하 (P0-4)

- anu_confirm_bot 코드는 forbidden_paths이므로 **수정 불가**.
- 본 task 결정: 보고서에 "운영 경로 인식 변경"으로만 명시.
  - systemd not-found 상태 → 활성 봇 아님 → 본 task 합격 기준 외.
  - 후속 task에서 활성화 별도 처리.

## 3 Step Why 자문

1st Why: 왜 이 설계가 필요한가?
→ A: main 진입 경로가 다중화되어 있어 (worktree_manager 직접 머지, gh pr merge 직접 CLI, finish-task.sh 우회 등) taskctl의 state machine을 무력화한 케이스가 발생. 단일 출입구 강제로 evidence/audit/state 일관성 확보.

2nd Why: 왜 A가 최선의 접근인가? (대안 검토 포함)
→ B: 대안1 = "taskctl 폐지 후 finish-task.sh 단일 책임" — taskctl의 state machine + evidence 박제 기능 손실, audit trail 단절. 기각.
   대안2 = "worktree_manager에 모든 게이트 통합" — worktree_manager는 git 격리 도구, 머지 책임은 별 레이어. SRP 위배. 기각.
   채택안 = "finish-task.sh가 taskctl verify로 게이트 통과 검증, taskctl merge가 실제 main 진입" — 책임 분리 + 검증 중복 = 다층 방어선.

3rd Why: 왜 B가 다른 대안보다 나은가?
→ C: B 채택안은 (1) 기존 taskctl state machine 재사용 (재구축 비용 0), (2) finish-task.sh가 진입 검증 책임만 가져 단순화, (3) worktree_manager는 PR 생성까지만 담당하여 명확한 SRP, (4) 회장 한 줄 기준 ("taskctl 거치지 않는 main 진입 0개")과 정확히 정렬. 다른 대안은 코드 양 ↑ + 책임 모호 + 회장 기준 미달.

A → B → C 일관성 확인 ✓ 설계 확정.

## 참조 자료

- 사양: `/home/jay/workspace/memory/tasks/task-2463.md`
- task-2461 freeze: `/home/jay/workspace/memory/events/task-2461-freeze-20260505T200633/`
- 워크플로우: `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md`
- QC 규칙: `/home/jay/workspace/teams/shared/QC-RULES.md`
- taskctl 스펙: `/home/jay/workspace/scripts/taskctl.py` (verify=line 404, merge=line 777)

## 주의사항

- ⚠️ scripts/taskctl.py / taskctl_verify.py / start_task_guard.py / anu_confirm_bot/** **수정 절대 금지** (forbidden_paths)
- ⚠️ task-2461 freeze 자동 cherry-pick 금지 — **명시 재적용만**
- ⚠️ pre-push의 taskctl_verify fallback 제거 시 모든 push 차단됨 (taskctl_verify.py 부재). 본 task에서는 fallback 유지.
- ⚠️ "박제 완료 / 설계 완료 / 문서 작성 / 이론상 차단" 표현 보고서에 0건. 모두 0점 기준.
