# BACKLOG — 안전축 (회장 지시 2026-07-19: 문서 보존 · **착수 금지**)

> **상태**: 백로그. 소유자 미지정. dispatch 계획 없음. **지금 코드 작업 금지.**
> **사유**: 복합설계 계산기 목표로 복귀. 아래는 전부 **계약 merge·Track A/B 착수의 필수조건이 아니다.**
> 착수는 **각각 별도 회장 승인** 사안.

---

## B-1. CI-4c — `is_blocked` 보험 예외를 명시적 허용 목록으로 전환
**문제**: `if "보험" in kw: return False` 가 **모든 검사보다 앞**에 있어, "보험" 두 글자로 blocklist 10패턴 전부를 우회한다.

**실측 (2026-07-19, ANU)**
| 입력 | 현행 | 문제 |
|---|---|---|
| `보험 마약` · `보험 살인` · `보험 성범죄` | 통과 | **FN** — 절대금지어가 우회됨 |
| `자살면책` · `음주운전 면책` | 차단 | **FP** — 정당한 약관 용어인데 차단 |

**근본 원인**: "보험" **문자열 유무**를 문맥 판단의 대용으로 씀. 그래서 양방향 오류가 동시에 발생.

**설계 방향 (회장 확정)**: 포괄 면제 폐기 → **명시적 보험 도메인 허용 표현 목록**
- 명시 허용 예: `보험 채용` · `보험 시험` · `보험사기` · `보험계약대출` · `자살면책` · `음주운전 면책`
- 명시 허용이 아닌 것(`보험 마약`·`보험 살인`)은 **기존 blocklist 판정을 그대로 받는다**

**제약**: **별도 task · 별도 PR.** CI-unblock aggregate 에 섞지 않는다.
**상세 분석**: `memory/reports/ci4_blocklist_policy_decision_260719.md`
**동일 규칙 존재**: `server/scripts/news_keyword_extract.py` — 동시 적용 여부 결정 필요

---

## B-2. 범용 task ledger CAS 예약
**문제 (2026-07-19 실증)**: ANU 가 Track B 용으로 `task-2798` 을 브랜치 선점했으나, 직후 dispatch 가 **같은 번호를 CI-4b 에 할당**했다. **브랜치 선점은 예약이 아니다.**

**필요**: 중앙 ledger 의 lock/CAS 기반 ID 예약 · 중복 예약 거부 · 예약↔소비 원자성.
**임시 대응(적용됨)**: Track A/B canonical 문서에서 숫자 ID 제거 → **logical ID(`TRACK_A`/`TRACK_B`) + `<ALLOCATED_TASK_ID>` 템플릿**. 실제 번호는 **등록 성공 후 조회해서** 치환.

---

## B-3. timer reconciliation (stale running 정리)
**문제 (실측)**: 작업이 **완료됐는데 `.done` 마커가 없어** 타이머가 `running` 으로 남고, 그 팀에 신규 dispatch 가 거부된다.
- `task-2792`(CI-4, dev4) — 커밋 `ded17c1` 존재, 마커 없음
- `task-2796`(CI-2b, dev2) — 커밋 `e404e44` + 보고서 존재, **supervisor-crash-marker**, 마커 없음
- `task-2788+3`(dev5) — 완료된 지 오래, running 잔존

**필요**: 산출물(커밋·보고서)과 타이머 상태를 대조해 자동 화해. crash 시에도 타이머가 닫히도록.

---

## B-4. active cancel push
**문제**: `dispatch.py --cancel` 은 STOP 마커·`.cancelled` 파일을 남기지만, **이미 돌고 있는 봇에 즉시 전달되는 경로**가 약하다.
**실증**: CI-5 중복 dispatch 시 `task-2795` 취소는 됐으나, 봇이 **이미 편집을 시작했다면** 같은 worktree 충돌 위험이 있었다.
**필요**: 봇이 **Edit·commit·finish 직전에 cancel 재확인**. 취소 시 mutation 중단.

---

## B-5. retry 진단 분리
**문제**: `task-2796.retry_count = 1` 이 남았으나, **재시도 원인이 코드 실패인지 인프라 크래시인지 구분 불가**.
**필요**: retry 사유를 `CODE_FAILURE` / `INFRA_CRASH` / `TIMEOUT` 등으로 분류 기록. 인프라 재시도를 코드 실패로 오분류하지 않기.

---

## B-6. result schema 강화
**문제**: 봇 보고와 실물이 갈렸다.
**실증**: CI-5 보고서가 커밋 `60ed2b9` 를 적었으나 브랜치 실물은 `1670c8a`(amend 후). CI-5 는 "5회 PASS" 라 보고했으나 **ANU 첫 재실행은 3/3 실패**(원인 = dev 서버 미기동, 코드는 정상).
**필요**: 결과 스키마에 **검증 환경(포트·서버 기동 여부)·최종 커밋 SHA** 를 필수 필드로. 스키마 위반 시 fail-closed.
**원칙 재확인**: **봇 self-report 는 권위 증거가 아니다. ANU 독립검증이 권위.**

---

## B-7. state atomic write
**문제**: `memory/task-timers.json` 이 **혼합 구조**(`tasks` dict + `counter` + 최상위 `task-2347` 키)라 파싱이 취약하다. ANU 도 이 구조를 잘못 읽어 **"타이머와 dispatch 상태 불일치(split-brain)"라고 오판했다가 철회**했다(2026-07-19).
**필요**: 스키마 단일화 + 원자적 쓰기(temp+rename) + 동시 쓰기 보호.

---

## 착수 조건 (공통)
1. 복합설계 계산기(Track A/B → integration → 파일럿) **본선 진행에 지장이 없을 때**
2. **각 항목별 회장 승인**
3. 착수 시 이 문서의 실증 근거를 재확인(시간이 지나 상황이 달라졌을 수 있음)
