# task-2723 — QC critical_gap zero-count/negative-context false-positive hardening

## ANU 인가 (2026-06-02, 회장 수면 중 자율 권한 확대)
회장 verbatim: ANU-Core 안정화 범위 LOW/MEDIUM hardening 은 task→dispatch→PR→OWNER /gemini review→CI/Gemini 수렴→MERGE_READY_CANDIDATE 까지 자동 진행. **merge 는 금지(회장 승인 대기)**. priority 1순위 = QC critical_gap hardening.

## 분류 / loop budget
- severity: MEDIUM (Core hardening). priority HIGH.
- remediation_round 예산: PR당 최대 2. same blocker 2회+ = LOOP_BOUNDARY. 새 HIGH/CRITICAL = 즉시 CHAIR_REQUIRED(자동 fix 0).
- decision-as-data: 완료 시 ANU 가 bounded-loop-decision.json/finding-attribution.json 기록.

## 근본 원인 (ANU read-only 확정, 2026-06-02)
`teams/shared/verifiers/critical_gap.py` `_detect_critical_lines()`:
- 보고서 텍스트에 `_CRITICAL_RE_EN`/`_CRITICAL_RE_KO` + `ISSUE_MARKER_PATTERNS`(예: `^\s*[-*]\s+.*CRITICAL`) 매칭으로 critical 이슈 후보 카운트.
- RESOLVED 측에는 `_UNRESOLVED_HINTS` 부정문맥 가드(line 54-63, 223)가 있으나,
- **ISSUE 후보 탐지에는 zero-count/negative-count 가드가 없음.**
→ `- HIGH/CRITICAL 신규 0건`, `CRITICAL=0`, `fresh unresolved HIGH/CRITICAL = 0` 같은 **0건/없음 명시 문구**가 미해결 critical 이슈로 **오탐** → FAIL. 봇이 보고서 문구를 바꿔 우회 → 게이트 신뢰성 훼손.
- 재발 2회+ (task-2721+4, task-2722). 단일소스: `memory/events/backlog_qc_text_token_false_positive_260602.json`.

## 목표
아래 zero-count/negative-context 문구를 unresolved issue 로 카운트하지 않는다(오탐 0). **단 실제 미해결 HIGH/CRITICAL 탐지력은 보존**:
- "HIGH/CRITICAL 0건" / "HIGH/CRITICAL 신규 0건"
- "신규 HIGH/CRITICAL 없음" / "없습니다"
- "CRITICAL=0" / "CRITICAL = 0" / "CRITICAL 0"
- "HIGH 0 / CRITICAL 0"
- "fresh unresolved HIGH/CRITICAL = 0"

## 구현 지시 (surgical — Simplicity First)
1. `teams/shared/verifiers/critical_gap.py`:
   - 모듈 상수에 `_ZERO_COUNT_HINTS: list[re.Pattern]` 추가 (RESOLVED 의 `_UNRESOLVED_HINTS` 패턴과 대칭 구조). 권장 패턴(과억제 방지 — critical/high 토큰과 **동일 줄** 공존 시에만):
     - `\b0\s*건\b` , `\b0\s*개\b`
     - `(?:없음|없습니다|없다)`
     - `(?:CRITICAL|HIGH)\s*[:=]?\s*0(?!\d)` (CRITICAL=0 / HIGH 0)
     - `=\s*0(?!\d)` (= 0)
     - `신규.{0,6}(?:없|0\s*건)`
     - `no\s+(?:new\s+)?(?:high|critical)` (대소문자 무시)
   - `_detect_critical_lines()` 의 후보 루프에서 **ISSUE_MARKER 매칭 직후**(현재 line 199-200 `if not any(... ISSUE_MARKER_PATTERNS)` 다음, RESOLVED_INLINE 체크 전후) 에 가드 삽입:
     `if any(p.search(line) for p in _ZERO_COUNT_HINTS): continue` (해당 줄을 이슈 후보에서 제외).
   - ★ 기존 함수 signature/리턴 schema(`{"status","details"}`)·verify() 인터페이스·기존 패턴/상수 **변경 금지**. 신규 상수+가드 1개만 추가(Surgical Changes).
2. `tests/regression/test_critical_gap_false_positive_2506.py`:
   - zero-count/negative-context 회귀 케이스 추가(목표 문구 6종을 이슈 섹션 헤더 아래 배치 → `verify()` 결과 status=PASS 단언).
   - **탐지력 보존 회귀**: 실제 미해결 CRITICAL(예: `- CRITICAL: SQL injection (수정 없음)`, badge `![critical]` + resolved 마커 없음) → status=FAIL 유지 단언(최소 1건).
   - 기존 fp1~fpN 케이스 전부 PASS 유지.

## expected_files (그 외 수정 금지)
1. `teams/shared/verifiers/critical_gap.py`
2. `tests/regression/test_critical_gap_false_positive_2506.py`
- 산출물: `memory/tasks/task-2723.md`(this) · `memory/reports/task-2723.md` · `memory/events/task-2723.done`

## forbidden (회장 자동 dispatch 금지목록 — 절대 미접촉)
- finish-task.sh / dispatch 핵심 runtime / pickup driver / systemd unit / activation flag / systemctl / actual wake / bounded_loop_decider.py runtime / credential·permission 확장 / merge / force push·rebase·admin override.
- QC 외 다른 verifier 동작 변경 금지. critical_gap 의 기존 화이트리스트/메타라벨/RESOLVED 로직 변경 금지(신규 가드만 add).

## 검증 조건 (필수)
1. 기존 실제 HIGH/CRITICAL unresolved 탐지 유지 (FAIL 회귀 1건+).
2. zero-count/negative-context 목표 문구 6종 → PASS.
3. regression PASS (기존 fp 케이스 + 신규).
4. `git diff --name-only origin/main` = expected_files 2파일 내부.
5. forbidden 0.
6. ANU key full literal(`c119085addb0f8b7`) 0.
7. 기존 verifier interface(verify signature / return schema) 유지.
- smoke: `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q`.

## doctrine (필수 준수)
- same-PR post-Gemini push 금지(Gemini review 도착 후 같은 PR push/amend 금지 — 위반 시 Option A replacement/OWNER_DECISION).
- bot 의 `/gemini review` 코멘트는 무효 — 인간 OWNER 계정 1회 코멘트만 trigger.
- chain limit: 회장 hard limit 외 자동 재시도 금지.
- long polling 금지(session-bound CI 대기 금지) — PR open 후 watcher 위임.

## finalize (PR 생성까지 — merge 금지)
1. fix → regression PASS → `git add` 2파일 → commit → worktree finish --action pr 로 **PR 생성**.
2. `memory/reports/task-2723.md` 보고서 작성(L1 결과 포함).
3. `memory/events/task-2723.done` 생성.
4. 본 task 종료 시 **ANU normal callback cron 강제 등록** — collector_role=ANU, ANU_KEY=c119085addb0f8b7(sealed, literal 노출 금지). executor self-key 등록 금지(SELF_COLLECTOR_FORBIDDEN). cron 등록 0 + sendfile 만 = NOT_REGISTERED fail-closed.
5. ★ **merge 금지** — MERGE_READY_CANDIDATE 는 ANU/watcher 가 판정·보고, merge 자체는 회장 승인.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "teams/shared/verifiers/critical_gap.py"
    - "tests/regression/test_critical_gap_false_positive_2506.py"
    - "memory/reports/task-2723.md"
    - "memory/events/task-2723.done"
  forbidden_paths:
    - "scripts/finish-task.sh"
    - "dispatch/**"
    - "deploy/systemd/**"
    - ".github/**"
  commands:
    - "pytest"
    - "python3 -m pytest"
    - "python3 -m py_compile"
  merge_policy: "none"
  ttl_hours: 48
```

## goal_assertions (auto)
- `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q`
- `python3 -c "import sys; s=open('teams/shared/verifiers/critical_gap.py').read(); sys.exit(0 if '_ZERO_COUNT_HINTS' in s else 1)"`
- `python3 -c "import sys; s=open('teams/shared/verifiers/critical_gap.py').read(); sys.exit(1 if 'c119085addb0f8b7' in s else 0)"`