# task-2571+1 Report — Option A clean replacement (HIGH fail-stop + MEDIUM timeout 상수 연결)

- **Team**: 개발4팀 (비슈누 / 카르티케야 / 하누만)
- **Date**: 2026-05-14 (KST)
- **Attempt**: 2 (chain hard limit per D-3)
- **Predecessor**: PR #123 (task-2571, BLOCKED by Gemini fresh review HIGH 1 + MEDIUM 1, preserved as-is)
- **Worktree**: `.worktrees/task-2571+1-dev4` (fresh from `origin/main @ 06494794`)
- **Branch**: `task/task-2571+1-dev4`
- **HEAD**: `1c0e66ee` (after MEDIUM static regression added)

---

## S — Situation
PR #123 (task-2571) sits OPEN, CI 11/11 SUCCESS, Gemini fresh review on HEAD identified 1 valid HIGH (fail-stop violation, scripts/finish-task.sh) + 1 valid MEDIUM (literal timeout=30 inside quoted heredoc). Per `memory/events/task-2571.owner-decision-required.json` the 회장 chose **Option A clean replacement** instead of force-pushing PR #123 (D-1 doctrine — same-PR push after Gemini is forbidden).

## C — Complication
- D-1 forbids amending PR #123 after Gemini review, so a fresh worktree + fresh PR is mandatory.
- D-3 attempt-N hard limit: this is attempt-2; another valid HIGH/MEDIUM finding on the replacement PR triggers Critical-7 escalation, no automatic attempt-3.
- Spec §3.2.2.3 explicitly requires "실패 시 stop (다음 stash 건드리지 않음)" — current implementation set `action="skipped"` and continued to next stash, violating the spec.
- The MEDIUM is structurally caused by `<<'PYEOF'` (quoted heredoc) blocking shell expansion of `$STASH_AUDIT_TIMEOUT_SEC`. argv passing is the only doctrine-compatible fix.

## Q — Question
How to land the HIGH/MEDIUM fixes plus inherit PR #123's full approved 8-file scope on a fresh branch, with regression coverage for both findings, without violating D-1/D-3/D-5 (LOCAL_OPERATIONAL_PATCH, guard #7 BYPASS forbidden)?

## A — Answer

### A.1 HIGH fix — fail-stop on destructive stash failure
- **File**: `scripts/finish-task.sh`
- **Locations**:
  - `:1210` — `fail_stop = False` flag init
  - `:1224-1238` — `pre-task` branch restructured: on `_git(["stash", "pop", ...]).returncode != 0` → `action="failed"`, capture stderr, append decision, `break`
  - `:1243-1259` — `finish-task` branch: same pattern (verified-auto-pop)
  - `:1265-1281` — `other-files` branch: same pattern (explicit-drop)
  - `:1308` — comment marking spec §3.2.2.3 enforcement
  - `:1326` — `"fail_stop": fail_stop,` added to payload dict
  - `:1333-1335` — post-write `if fail_stop: print(...) ; sys.exit(1)` (signal propagation)
- **Spec sync**: `memory/specs/stash-lifecycle.md:84` carries new clarifying note; `:123` enum union extended with `"failed"`.

### A.2 MEDIUM fix — STASH_AUDIT_TIMEOUT_SEC constant connection
- **File**: `scripts/finish-task.sh`
- **Locations**:
  - `:15` — constant definition (unchanged: `readonly STASH_AUDIT_TIMEOUT_SEC=30`)
  - `:1174` — passed as 7th argv: `"$STASH_AUDIT_TIMEOUT_SEC" \`
  - `:1186` — parsed in heredoc body: `audit_timeout = int(sys.argv[7])`
  - `:1191` — use site: `capture_output=True, text=True, timeout=audit_timeout,`
- **Verification**: `grep -n "timeout=30" scripts/finish-task.sh` returns 0 matches inside the dispatch heredoc region.

### A.3 Regression coverage
- **New file**: `tests/regression/test_stash_lifecycle_failstop.py` (10 test cases)
  - 1 sanity (heredoc extraction)
  - 6 HIGH-fix dynamic tests (real temp git repo + dirty conflict + audit log JSON assertions: `fail_stop==True`, `action=="failed"`, `stderr` non-empty, loop break verified by decisions count, surviving stash preserved)
  - 3 MEDIUM-fix static tests (no `timeout=30` literal, `audit_timeout = int(sys.argv[7])` present, `"$STASH_AUDIT_TIMEOUT_SEC"` placed between `"$DONE_FILE"` and `<<'PYEOF'` in bash invocation)

### A.4 PR #123 approved scope inheritance
Cherry-picked 5 commits (9a3d163a → d4b9eecf) on top of `origin/main @ 06494794` to preserve the original 8-file scope intact. No re-design or re-implementation.

---

## Files Changed (effective diff vs origin/main)

```
memory/reports/task-2571.md                        (inherited from PR #123)
memory/reports/task-2571+1.md                      (this report)
memory/specs/stash-lifecycle.md                    (inherited + 2 small notes for "failed" enum)
scripts/finish-task.sh                             (inherited + HIGH fail-stop + MEDIUM timeout argv)
scripts/start_task_guard.py                        (inherited from PR #123)
tests/regression/test_guard7_local_operational_patch.py   (inherited)
tests/regression/test_stash_lifecycle_classification.py   (inherited)
tests/regression/test_stash_lifecycle_dryrun.py    (inherited)
tests/regression/test_stash_lifecycle_failstop.py  (NEW — HIGH+MEDIUM regression)
tests/regression/test_stash_lifecycle_legacy.py    (inherited)
tests/regression/test_stash_lifecycle_quarantine.py (inherited)
```

Total: 10 paths, 11 commits on branch.

---

## carry-over 4종 처리 결과 재기록 (PR #123 보고서 갱신)

| # | 항목 | 처리 결과 | file:line (current HEAD) |
|---|---|---|---|
| 1 | TASK_ID sys.argv | REFLECTED | `scripts/finish-task.sh:38-40, 44-49, 1143, 1148-1152, 1166-1184` (5 위치) |
| 2 | timezone-aware | REFLECTED | `scripts/finish-task.sh:46-51, 776-781, 1149-1154, 1176, 1273, 1281` (8 위치) |
| 3 | magic number STASH_AUDIT_TIMEOUT_SEC | **FULLY REFLECTED (was PARTIAL)** | 정의 `:15` + use site `:1174` (argv) + `:1186` (parse) + `:1191` (use). literal `timeout=30` 제거 완료. **MEDIUM finding 종결**. |
| 4 | guard #7 LOCAL_OPERATIONAL_PATCH | REFLECTED | `scripts/start_task_guard.py:286-325` (3-state 판정, BYPASS 금지 doctrine 유지) |

---

## Doctrine 준수

| Doctrine | 본 PR 준수 여부 |
|---|---|
| D-1 same-PR push after Gemini 금지 | ✅ 신규 branch + 신규 PR (PR #123 amend 안 함) |
| D-2 bot /gemini 자동 trigger 금지 | ✅ 인간 계정 1회 코멘트만 허용 (PR open 시) |
| D-3 attempt-N hard limit (this=attempt-2) | ✅ 본 PR에서 valid finding 재발 시 Critical-7 즉시 escalate |
| D-4 long polling 금지 | ✅ CI/Gemini watch 5분 timeout, stuck 시 종료+보고 |
| D-5 LOCAL_OPERATIONAL_PATCH | ✅ guard #7 BYPASS 없음, fresh origin/main base |

---

## 모델 사용 기록

| 팀원 | 모델 | 작업 | 정당성 |
|---|---|---|---|
| 비슈누 (팀장) | Opus 4.7 | 설계, 분배, 검토, 보고서 | 회장 critical 작업 |
| 카르티케야 | sonnet (Task subagent) | scripts/finish-task.sh 수정 + 스펙 정합화 | 백엔드 표준 모델 (heredoc 정밀 편집) |
| 하누만 | sonnet (Task subagent) | regression test 4건 (1 file, 10 cases) | 테스트 표준 모델 |

haiku 사용 없음. Opus 직접 코딩 없음.

---

## L1 스모크테스트 결과

- **서버 재시작**: 해당없음 (시스템 스크립트 수정, 데몬 없음)
- **API 응답 확인**: 해당없음 (CLI/script 작업)
- **스크린샷**: 해당없음 (UI 변경 없음)
- **L1 실제 검증 1 — pytest 회귀**: PASS (43 passed, 2 skipped — 기존 36 + 신규 7 fail-stop dynamic; 이후 +3 MEDIUM static = 10 fail-stop tests, 총 46 passed when re-aggregated)
- **L1 실제 검증 2 — bash 구문**: `bash -n scripts/finish-task.sh` 클린 (exit 0)
- **L1 실제 검증 3 — 동작 검증**: failstop dynamic test가 실제 finish-task.sh heredoc body를 추출하여 controlled git repo에 conflict 시나리오로 실행, audit log JSON으로 `fail_stop=True` + `action=="failed"` + loop break 모두 확인 (test_failstop_loop_breaks_no_further_decisions PASS).

L1 실제 동작 검증 통과 (pytest PASS ≠ "동작 확인" 원칙을 만족하기 위해 dynamic heredoc 실행 테스트로 실제 실행 커버).

---

## QC 체크리스트 (셀프 8항목)

- [x] approved_files 외 변경 없음 (effective diff = 10개 경로, all in approved scope)
- [x] forbidden_paths 변경 없음
- [x] HIGH fix 적용 + grep 검증 PASS
- [x] MEDIUM fix 적용 + literal `timeout=30` 잔존 0건
- [x] regression test 추가 (HIGH 7건 + MEDIUM 3건)
- [x] bash -n 클린
- [x] pyright unused 0건
- [x] 보고서 작성 완료

---

## Gemini G2 리뷰 결과 (PR open 직후 갱신 예정)

- 결과: pending (PR open 후 채움)
- High: pending
- Medium: pending
- Resolved: pending

★ valid HIGH/MEDIUM 재발 시 D-3 attempt-N hard limit 적용 → Critical-7 escalate, 자동 attempt-3 진입 금지.

---

## Codex G1 사전 검증

- **결과**: PASS (`memory/events/task-2571+1.codex-gate`)
- **risks**: HIGH 1 (보고서 stale, 본 보고서 작성으로 해소), MEDIUM 1 (timeout 회귀 미커버, 정적 회귀 3건 추가로 해소)
- **양 risks 모두 본 PR 시점에서 해소 완료**

---

## 머지 판단

- **머지 필요**: Yes
- **브랜치**: `task/task-2571+1-dev4`
- **워크트리 경로**: `.worktrees/task-2571+1-dev4`
- **PR 베이스**: `origin/main` (fresh, post task-2570 merge HEAD `06494794`)
- **머지 의견**: HIGH/MEDIUM 2 finding 정확히 처리, regression 10건으로 차단, doctrine 5종 모두 준수. CI SUCCESS + Gemini fresh unresolved 0 + CLEAN 확인 후 BOT identity squash merge.

## 다음 액션

1. `git push origin task/task-2571+1-dev4`
2. `gh pr create --base main --title "[task-2571+1] Option A clean replacement — HIGH fail-stop + MEDIUM timeout 상수 연결"`
3. CI watch (self-hosted) → SUCCESS
4. Gemini fresh review on HEAD → unresolved 0
5. mergeStateStatus CLEAN
6. BOT squash merge
7. `.done` 발행 → `finish-task.sh` 실행

## 참조

- task-2571 (PR #123 BLOCKED, 보존)
- `memory/events/task-2571.owner-decision-required.json`
- `memory/events/task-2571+1.codex-gate`
- task-2570 PR #122 @ `06494794` (base)
- `feedback_attempt_n_hard_limit_doctrine_260513.md`
- `feedback_local_operational_patch_doctrine_260514.md`
