# task-2723+1 — critical_gap zero-count guard NARROWED re-fix (round-2, 회장 명시 승인)

## 회장 인가 (2026-06-03, A안 — round-2 narrowed re-fix, 자동 fix 아님)
PR #169(head `e1f5798b`)에 Gemini fresh **CRITICAL 2 + HIGH 2** 발생 = 유효: round-1 의 `_ZERO_COUNT_HINTS` 가드가 **과광범위** → "인증 없음/권한 검증 없음/암호화 없음/secure_mode=0/timeout=0/port=0/패치 없음" 같은 **실제 위험 문구를 zero-count 로 억제** → false-NEGATIVE(실제 CRITICAL/HIGH 누락). QC 게이트 신뢰성 문제 → dismiss/close 금지, surgical narrowed fix.
★ 회장 명시 승인 remediation round (자동 fix 아님). 새 HIGH/CRITICAL 발생 시 자동 fix 금지·즉시 CHAIR_REQUIRED.

## worktree
- `/home/jay/workspace/.worktrees/task-2723-dev2` (branch `task/task-2723-dev2`, head `e1f5798b`)에서 **이어서**. base origin/main. new head → non-force push.

## 핵심 설계 (NARROWED — round-1 가드 교체)
기존 round-1 `_ZERO_COUNT_HINTS`(넓은 `(?:없음|없습니다|없다)`, `=\s*0`, `신규.{0,6}...`)를 **아래 결속 로직으로 교체**한다. 단순 "없음/=0/0건" 존재만으로 suppress 금지.

zero-count 로 인정(=이슈 후보에서 제외)하려면 **세 조건 모두** 충족:
1. **count-context anchor** 동일 줄 존재: `(?:HIGH|CRITICAL|심각|블로커|이슈|issue|finding|findings|취약점|건수|count|미해결|unresolved|fresh\s+unresolved|신규\s*(?:HIGH|CRITICAL))` (대소문자 무시)
2. **zero 표현** 동일 줄 존재: `(?:\b0\s*건\b|\b0\s*개\b|[:=]\s*0(?!\d)|count\s*=\s*0|\b없음\b|없습니다|\b없다\b)`
3. **억제 차단 조건 부재** — 아래 둘 중 하나라도 매칭되면 **절대 suppress 안 함**:
   - **강한 issue marker**: `\[(?:CRITICAL|HIGH)\]` 또는 `!\[(?:critical|high)\]` 또는 `severity\s*[:=]\s*(?:critical|high)` (badge/명시 severity 선언)
   - **실제 취약점 부정/제로 deny-list**: `(?:인증|권한\s*검증|권한|암호화|패치|수정|조치|해결)\s*없음` 또는 `(?:secure_mode|timeout|port)\s*=\s*0`

즉 `_is_zero_count_context(line)`:
```
if STRONG_ISSUE_MARKER.search(line):      return False   # 실제 severity 선언 줄 — 탐지 유지
if VULN_NEGATION_DENYLIST.search(line):   return False   # 실제 위험 부정/제로 — 탐지 유지
return bool(COUNT_ANCHOR.search(line) and ZERO_EXPR.search(line))
```
`_detect_critical_lines()` 후보 루프에서 (ISSUE_MARKER 매칭 직후) `if _is_zero_count_context(line): continue`.

★ 구현 메모: 후보 줄은 이미 CRITICAL/HIGH 토큰 + 약한 marker(리스트 `-`/헤더 `##`)를 가짐. 약한 marker(리스트/헤더)는 strong issue marker 가 **아님** — `[CRITICAL]`/`![critical]`/`severity:` 만 strong. 따라서 "- HIGH/CRITICAL 0건"(리스트)은 strong marker 부재 → anchor+zero 충족 → suppress(PASS), "[CRITICAL] 인증 없음"은 strong marker 존재 → 미억제(FAIL 유지).

## 허용 파일 (expected_files 2개 — 그 외 수정 금지)
1. `teams/shared/verifiers/critical_gap.py` ← `_ZERO_COUNT_HINTS` narrowed 로직 교체(헬퍼 추가 가능)
2. `tests/regression/test_critical_gap_false_positive_2506.py` ← 12 regression 추가/보강

## 필수 regression (12 — 회장 명시)
PASS(zero-count 인정):
1. "HIGH/CRITICAL 0건" → PASS
2. "CRITICAL=0" → PASS
3. "fresh unresolved HIGH/CRITICAL = 0" → PASS
4. "신규 HIGH 없음 / 신규 CRITICAL 없음" → PASS
FAIL(탐지력 유지 — strong marker 또는 vuln denylist):
5. "[CRITICAL] 인증 없음" → FAIL
6. "[CRITICAL] 권한 검증 없음" → FAIL
7. "[CRITICAL] 암호화 없음" → FAIL
8. "[HIGH] secure_mode=0" → FAIL
9. "[HIGH] timeout=0" → FAIL
10. "[CRITICAL] port=0" → FAIL
11. "[CRITICAL] 신규 버그, 패치 없음" → FAIL (★ FAIL 케이스는 실제 critical 후보로 잡히도록 issue marker/severity 토큰 포함 형태로 구성)
12. 기존 unresolved HIGH/CRITICAL 탐지력 유지(기존 fp1~fpN 전부 PASS + 실제 미해결 critical FAIL 회귀 보존)

## 금지 (회장 verbatim)
- expected_files 2개 밖 수정 금지 · finish-task.sh / dispatch runtime / pickup driver / systemd / activation flag / systemctl / actual wake / credential 확장 / Work 착수 / merge / force push·rebase·admin override 금지.
- **verifier public interface/schema 변경 금지** (verify signature·return `{status,details}` 불변). critical_gap 기존 화이트리스트/메타라벨/RESOLVED 로직 변경 금지(zero-count 가드만 narrowed 교체).

## 검증 조건
1. 12 regression 전부 의도대로(4 PASS + 7 FAIL + 1 탐지력보존) PASS.
2. `git diff --name-only origin/main` = expected_files 2파일 내부.
3. forbidden 0. 4. ANU key full literal(`c119085addb0f8b7`) 0. 5. verify interface/schema 불변.
- smoke: `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q`.

## doctrine (필수)
- same-PR post-Gemini push 금지(이미 Gemini 1회 리뷰 도착 — round-2 fix 는 새 commit→new head→non-force push 로 진행, amend 금지). bot `/gemini review` 무효(인간 OWNER 1회만). chain limit. long polling 금지(watcher 위임).

## finalize (PR 갱신까지 — merge 금지)
1. narrowed fix → 12 regression PASS → `git add` 2파일 → commit → **non-force push** (PR #169 갱신, new head).
2. `memory/reports/task-2723.md` 보고서 갱신(round-2 + L1).
3. `memory/events/task-2723+1.done` 생성.
4. ANU normal callback cron 강제 등록 — collector_role=ANU, ANU_KEY=c119085addb0f8b7(sealed, literal 노출 금지). self-key 금지(SELF_COLLECTOR_FORBIDDEN). cron 0+sendfile only = NOT_REGISTERED fail-closed.
5. ★ merge 금지 — ANU/watcher 가 새 head OWNER /gemini review → CI/Gemini watcher → MERGE_READY_CANDIDATE 판정·보고. 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+1.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(1 if 'c119085addb0f8b7' in s else 0)"`