# task-2786 — G3 stale fail marker hygiene (clear-on-PASS, ACTIVE=false)

## 레벨
Lv2-3 (finish-task/G3 verifier marker lifecycle + 회귀). 코드 작업. **코드+테스트+worktree 커밋+ANU 보고까지. PR 생성 금지(ANU 별도 승인 후).**

## allowed_resources

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

## 목표 (한 줄)
G3가 **현재 PASS일 때만** 이전 실행의 stale G3 fail marker(4변종)를 정리해 `.done` 발행이 stale 마커에 막히지 않게 한다. **진짜 현재 G3 FAIL은 기존처럼 `.done`을 계속 차단한다**(안전게이트 약화 0). 마커 lifecycle(정리)만 추가 — G3 판정 로직·terminal artifact·result.json·callback contract **무변경**.

## 단일 소스 (반드시 먼저 읽을 것)
착수 packet: `memory/reports/g3_stale_fail_marker_hygiene_kickoff_packet_260705.md` (§2 근본원인·§3 수정방향·§5 불변·§6 테스트 그대로).

## 근본 원인 (코드 실측 — canonical cedea4be)
- `.g3-fail` ← `scripts/g3_independent_verifier.py:397 write_fail_file()`(라인 402), FAIL 시 작성(main fail 분기 586·616 호출).
- `.g3-failed` ← `scripts/finish-task.sh:1519`, G3 gate FAIL(`G3_EXIT != 0`) 시 작성 후 `exit 1`.
- **G3 PASS 분기(finish-task.sh:1517)가 이전 stale fail 마커를 정리하지 않음.**
- 차단: `finish-task.sh:1806 → lifecycle_guards.check_g3_fail_blocks_done` → `find_g3_fail_markers`(4변종 인식)가 stale 마커 발견 시 `ok=False`로 `.done` 차단. **마커 존재만 검사(timestamp 비교 X)** → stale이 현재 PASS를 무효화.
- `lifecycle_guards.py`에 clear/정리 함수 **없음**.

## 구현 요구 (GPT verbatim — clear-on-PASS)
1. **`scripts/lifecycle_guards.py`**: marker 변종 단일소스 정리 helper 신규 — `clear_g3_fail_markers(task_id, events_dir=None)` (또는 동등 이름). **해당 `task_id`의 4변종(`g3-fail`/`g3-failed`/`g3_fail`/`g3_failed`) 마커만** 정리. **다른 task_id 마커 절대 미삭제.** 인식 대상은 기존 `G3_FAIL_MARKER_NAMES`/`find_g3_fail_markers` 재사용.
2. **`scripts/g3_independent_verifier.py`**: **PASS 결정 경로**에서 자기 `.g3-fail` 계열 stale marker 정리(producer가 자기 마커 lifecycle 소유). PASS 확정 후에만.
3. **`scripts/finish-task.sh`**: G3 gate **PASS 분기(1517, `G3_EXIT=0` 확정 직후)**에서 `clear_g3_fail_markers($TASK_ID)` 호출로 전변종 stale 마커 정리(자신이 쓴 `.g3-failed` + belt-and-suspenders). **FAIL 경로(1519)는 마커 유지/작성 + 즉시 `exit 1` 차단 그대로.**
4. ★ **정리는 PASS 이후에만** — PASS 전 선제 삭제 **금지**.

## ★ 불변 / 안전게이트 (변경 금지)
- 진짜 **현재 G3 FAIL → `.done` 계속 차단**(안전게이트 약화 0). 현재 FAIL이면 verifier가 마커 쓰고 nonzero→finish-task 1519가 `.g3-failed` 쓰고 exit 1→`.done` 미도달→여전히 차단(구조적 보장).
- **G3 판정 기준(PASS/FAIL 로직) 무변경** — 마커 lifecycle(정리)만 추가.
- terminal artifact(.done/.done.escalated) · result.json envelope · callback contract(owner-pickup·self-key 0) **무접촉**(PR#264 축).
- `check_g3_fail_blocks_done`의 차단 의미 무변경(stale 마커 없어지면 자연 통과).
- **timestamp/run-id 게이트 미채택**(1차 구현).

## 테스트 요구 (신규 회귀 — mock/tmp 격리, 4파일 안)
1. 첫 G3 FAIL → `.g3-fail`(verifier) / `.g3-failed`(finish-task) 마커 생성 확인.
2. 이후 G3 **PASS** → stale fail 마커(4변종) 정리 확인 + `check_g3_fail_blocks_done` ok=True → `.done` 발행 허용.
3. **현재 G3 FAIL** → 여전히 `.done` 차단(안전 보존) 확인.
4. 4변종 마커가 모두 해당 `task_id` 범위에서 정리되는지 확인.
5. **다른 `task_id` 마커는 정리되지 않음** 확인(격리).
6. task-2785 유사 흐름 재현(FAIL→marker→PASS→clear→finish-task 재실행 가능).
7. 기존 terminal artifact(`test_finish_task_terminal_termination_2782`) / callback artifact / finish-task 관련 회귀 보존.

## 검증
- `pytest tests/regression/test_g3_stale_fail_marker_hygiene_2786.py` 전체 PASS(개수 명시).
- 기존 회귀 보존(terminal 2782 등) — 통합 회귀 무손상.
- diff **4파일**(expected_files)뿐 · forbidden(terminal_state_callback/merge-executor/.github/ruleset) 무접촉.
- `bash -n scripts/finish-task.sh` OK.

## STOP_REPORT 조건
진짜 현재 G3 FAIL을 통과시키는 변경 필요 · 안전게이트 약화 필요 · terminal artifact/result.json/callback contract 변경 필요 · expected_files 4개 밖 수정 필요 · `.github`/ruleset/Merge Queue 요구 · G3 판정 로직 변경 필요 · 기존 회귀 깨짐.

## 금지 (전부)
`.github`/ruleset/branch protection/required check/Merge Queue activation · terminal_state_callback/merge-executor 체인 접촉 · G3 판정 로직 변경 · 안전게이트 약화 · PASS 전 선제 마커 삭제 · 다른 task_id 마커 삭제 · timestamp 게이트 도입 · PR 생성 · merge · activation 표현.

## 산출물 & 보고 (PR 없음 — ANU 보고까지만)
1. worktree 커밋(브랜치). **PR 생성 금지**(ANU 독립검증 후 별도 승인 시).
2. ANU 보고: diff(4파일)/pytest 결과/현재 FAIL 차단 보존 증거/현재 PASS 시 정리 증거/task_id 격리/forbidden 무접촉.
3. 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B).

## 검증 루프
자체 리뷰 1회 → pytest 통과 → 4파일 diff·forbidden 무접촉 → 현재 FAIL 차단 보존 + PASS 정리 확인 → bash -n.

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