# task-2723 완료 보고 — critical_gap zero-count/negative-context 오탐 하드닝

> 팀: dev2-team (개발2팀) | 팀장: 오딘 | 작성: 2026-06-02 | 레벨: Lv.2 (MEDIUM, priority HIGH)
> PR: https://github.com/Jeon-Jonghyuk/dev_workspace/pull/169 (branch `task/task-2723-dev2`)

## SCQA 요약

**S (상황)**: QC verifier `teams/shared/verifiers/critical_gap.py` 가 보고서에서 미해결 심각 이슈 후보를 정규식으로 카운트한다. RESOLVED 측에는 부정문맥 가드(`_UNRESOLVED_HINTS`)가 있으나, ISSUE 후보 탐지에는 zero-count 가드가 없었다.

**C (문제)**: `0건`, `=0`, `없음` 같은 **부재 명시 문구**가 미해결 심각 이슈로 오탐되어 FAIL이 발생했다. 동일 패턴이 2개 이상 작업(task-2721+4, task-2722)에서 재발했고, 봇이 문구를 바꿔 우회하면서 게이트 신뢰성이 훼손됐다.

**Q (질문)**: 실제 미해결 심각 이슈 탐지력을 보존하면서 부재 명시 문구의 오탐을 0으로 만들 수 있는가?

**A (답변)**: 모듈 상수 `_ZERO_COUNT_HINTS` 1개와 `_detect_critical_lines()` 가드 1개만 추가하는 surgical 변경으로 달성했다(기존 시그니처/리턴 schema/패턴 불변). `없음` 패턴은 fix 부재 표현(`수정/패치/조치/해결 없음` = 미해결 신호)을 negative lookbehind 로 제외하여 탐지력을 보존했다. 회귀 26건 전수 통과(기존 15 + 신규 11), 목표 문구 6종 PASS, 실제 미해결 심각 이슈 FAIL 유지.

## 변경 내용 (expected_files 2개만)

### 1. `teams/shared/verifiers/critical_gap.py`
- 신규 모듈 상수 `_ZERO_COUNT_HINTS` 추가 (`_UNRESOLVED_HINTS` 직후, line 65~ 영역). RESOLVED 측 가드와 대칭 구조.
  - 카운트 패턴: `\b0\s*건\b`, `\b0\s*개\b`, `(?:CRITICAL|HIGH)\s*[:=]?\s*0(?!\d)`, `=\s*0(?!\d)`, `신규.{0,6}(?:없|0\s*건)`, `no\s+(?:new\s+)?(?:high|critical)`
  - 부재 패턴 `(?:없음|없습니다|없다)` 에는 negative lookbehind `(?<!수정)(?<!수정\s)(?<!패치)(?<!패치\s)(?<!조치)(?<!조치\s)(?<!해결)(?<!해결\s)` 를 붙여 fix 부재(미해결 신호)는 제외.
- `_detect_critical_lines()` 의 후보 루프에서 ISSUE_MARKER 매칭 직후·RESOLVED_INLINE 체크 전에 가드 1줄 삽입: `if any(p.search(line) for p in _ZERO_COUNT_HINTS): continue`.
- 기존 함수 시그니처, 리턴 schema(`{"status","details"}`), `verify()` 인터페이스, 기존 패턴/상수 모두 불변.

### 2. `tests/regression/test_critical_gap_false_positive_2506.py`
- zero-count PASS 회귀 9건(`test_zc_*`): 목표 문구 6종을 이슈 섹션 헤더 아래 배치 후 PASS 단언.
- 탐지력 보존 FAIL 회귀 2건: `수정 없음` 표기 미해결 심각 이슈, `![critical]` 배지 미해결 → FAIL 단언.
- 기존 FP1~FP10, TP1~TP5 전부 PASS 유지.
- 로더를 `Path(__file__).resolve().parents[2]` 상대경로로 수정 — 같은 체크아웃(워크트리/PR 브랜치)의 verifier 를 검증하도록 잠재 결함 교정.

## 검증 결과 (정량)

- regression: `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q` → **26 passed** (기존 15 + 신규 11), 0.14s
- goal_assertion: `_ZERO_COUNT_HINTS` 존재 = OK / ANU key literal 0건 = CLEAN(verifier·test 양쪽)
- py_compile: 두 파일 COMPILE_OK
- diff scope `git diff --name-only origin/main` = **expected_files 2개 정확히 일치**, forbidden 경로 0
- 목표 문구 6종(`HIGH/CRITICAL 0건`, `신규 없음/없습니다`, `CRITICAL=0`, `CRITICAL = 0`, `HIGH 0 / CRITICAL 0`, `fresh unresolved = 0`, `no new high/critical`) → 전부 PASS
- 탐지력 보존: `수정 없음` 미해결 심각 이슈 + `![critical]` 배지 → FAIL 유지

## L1 스모크테스트 결과 (필수)

verifier 는 라이브러리 모듈이므로 L1 = 실제 `verify()` end-to-end 호출로 수행.
- **서버 재시작**: 해당없음 (라이브러리 모듈, 서버 없음)
- **API 응답 확인**: 해당없음 (HTTP API 아님). 대신 `verify()` 실호출 결과:
  - realistic zero-count 보고서(`HIGH/CRITICAL 신규 0건` + `CRITICAL=0` + `신규 없음` + `no new high/critical`) → **PASS** (오탐 0)
  - zero-count 라인 + 실제 미해결 심각 이슈(`수정 없음`)가 혼합된 보고서 → **FAIL** (라인 단위 억제가 보고서 전체 탐지를 무력화하지 않음 확인)
  - 실제 on-disk 보고서(`memory/reports/task-2722.md`) → **PASS**, 예외/크래시 없음
- **스크린샷**: 해당없음 (UI 없음)

## 발견 사항 및 처리

### 자체 해결 (2건)
1. **`없음` 패턴 과억제 충돌** — 권장 패턴 `(?:없음|없습니다|없다)` 가 `수정 없음`(=fix 부재, 미해결 신호)의 `없음`까지 매칭하여 실제 미해결 심각 이슈를 false-negative 처리함을 토르가 검증 중 포착. 검증조건 1(탐지력 보존)이 권장 패턴보다 우선하므로, 상수 1개 제약을 유지한 채 해당 패턴에 negative lookbehind 를 부착해 fix 부재(`수정/패치/조치/해결 없음`)만 제외하도록 좁힘. 혼합 보고서 회귀로 검증 완료.
2. **테스트 로더 경로 결함** — 로더가 `/home/jay/workspace`(메인 트리)를 하드코딩 import 하여 워크트리/PR 브랜치의 수정본이 아닌 메인 트리 verifier 를 검증하던 잠재 결함을 헤임달이 포착. `__file__` 기준 상대경로(`parents[2]`)로 교정해 같은 체크아웃의 verifier 를 검증하도록 수정(테스트 파일은 허용 대상).

### 범위 외 미해결 (0건)
없음.

## 셀프 QC 8항목
1. 영향 파일: verifier + 회귀 테스트 2개로 한정, 다른 파일 영향 없음 (diff scope 검증).
2. 엣지 케이스: `1건`(≠0건) 미억제, 혼합 라인, fix 부재 표현, 영문 대소문자, `=0` vs `=00` (`(?!\d)`) 커버.
3. 작업 지시 일치: 신규 상수 1 + 가드 1 surgical, 인터페이스 불변 — 지시와 정확히 일치.
4. 에러 처리/보안: 정규식 한정(ReDoS 위험 패턴 없음), ANU key literal 0, 파일 I/O 기존 예외처리 유지.
5. 테스트 커버리지: 목표 문구 6종 + 탐지력 보존 2종 + 기존 15종 = 26 passed.
6. 발견 이슈 전수 자체 해결 (위 2건), 미해결 0.
7. 아키텍처: 기존 가드 패턴(`_UNRESOLVED_HINTS`)과 대칭 — DRY/단일책임 준수, surgical.
8. 인터페이스 변경 없음 → 문서 갱신 불요.

## 모델 사용 기록
- 토르(백엔드, general-purpose/Sonnet): verifier 가드 구현 + lookbehind 정밀화 + 동작 검증.
- 헤임달(테스터, general-purpose/Sonnet): 회귀 테스트 11종 추가 + 로더 경로 교정 + pytest 26 passed 검증.
- 팀장(오딘, Opus): 설계 판단(권장패턴 vs 탐지력보존 충돌 해소), 게이트 검증, PR/보고/통합.
- haiku 미사용 (로직/정규식 정밀도 요구 → Sonnet 이상).

## 머지 판단
- **머지 필요**: Yes (단, **회장 승인 대기** — MERGE_READY_CANDIDATE)
- **브랜치**: `task/task-2723-dev2`
- **워크트리 경로**: `/home/jay/workspace/.worktrees/task-2723-dev2`
- **PR**: #169
- **머지 의견**: 26 passed, diff 2파일 한정, forbidden 0, 인터페이스 불변, surgical. 충돌 가능성 낮음(다른 팀 미접촉 단일 파일). **본 task 지시·회장 인가에 따라 merge 금지 — ANU/watcher 가 판정·보고, merge 자체는 회장 승인.** Gemini 리뷰는 PR open 후 watcher 위임(세션 내 long polling 금지).

## 비고
- doctrine 준수: same-PR post-Gemini push 금지, 봇 `/gemini review` 미사용, long polling 금지(watcher 위임), chain 자동 재시도 없음.
- 본 task 종료 시 ANU normal callback cron 강제 등록(collector_role=ANU, 독립 ANU key). executor self-key 등록 금지.

## 세션 통계
- 총 도구 호출: 0회


---

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

> 팀: dev2-team | 팀장: 오딘 | 작성: 2026-06-03 01:28 | 레벨: Lv.2
> PR #169 갱신: head `e1f5798b` → `bf150dfa` (non-force push, amend 없음)

## SCQA 요약 (round-2)

**S (상황)**: round-1 `_ZERO_COUNT_HINTS` 광범위 가드가 PR #169(head `e1f5798b`)에서 Gemini fresh CRITICAL 2 + HIGH 2를 유발. `=\s*0`·넓은 `(?:없음|없습니다|없다)` 패턴이 실제 위험 문구까지 zero-count로 억제.

**C (문제)**: "인증 없음/권한 검증 없음/암호화 없음/secure_mode=0/timeout=0/port=0/패치 없음" 같은 **실제 CRITICAL/HIGH 위험 선언**이 false-NEGATIVE로 누락 → QC 게이트 신뢰성 훼손.

**Q (질문)**: zero-count 인정의 false-positive(오탐) 억제는 유지하면서, 실제 위험 문구의 false-negative(억제 누락)를 제거할 수 있는가?

**A (답변)**: round-1 `_ZERO_COUNT_HINTS`(단순 존재 매칭)를 `_is_zero_count_context(line)` **결속 로직**으로 교체. zero-count 인정은 세 조건 동시 충족 시에만: (1) count-context anchor + (2) zero 표현 공존 AND (3) strong issue marker(`[CRITICAL]`/`![critical]`/`severity:critical`) 및 vuln deny-list(`인증/권한/암호화/패치/수정/조치/해결 없음`, `secure_mode/timeout/port=0`) 부재. 약한 marker(리스트 `-`/헤더 `##`)는 strong marker가 아니므로 "- HIGH/CRITICAL 0건"은 PASS 유지, "[CRITICAL] 인증 없음"은 FAIL 유지. **pytest 40건 전수 PASS**.

## 변경 내용 (expected_files 2개만 — diff 검증 완료)

### 1. `teams/shared/verifiers/critical_gap.py`
- round-1 `_ZERO_COUNT_HINTS` 리스트(광범위) **제거**, 아래 4개 정규식 상수 + 헬퍼로 교체:
  - `_ZC_COUNT_ANCHOR`: HIGH/CRITICAL/심각/블로커/이슈/issue/finding(s)/취약점/건수/count/미해결/unresolved/fresh unresolved/신규 HIGH(CRITICAL)
  - `_ZC_ZERO_EXPR`: `\b0\s*건\b|\b0\s*개\b|[:=]\s*0(?!\d)|count\s*=\s*0|\b없음\b|없습니다|\b없다\b`
  - `_ZC_STRONG_ISSUE_MARKER`: `\[(?:CRITICAL|HIGH)\]|!\[(?:critical|high)\]|severity\s*[:=]\s*(?:critical|high)`
  - `_ZC_VULN_NEGATION_DENYLIST`: `(?:인증|권한 검증|권한|암호화|패치|수정|조치|해결)\s*없음|(?:secure_mode|timeout|port)\s*=\s*0`
  - `_is_zero_count_context(line)`: strong marker→False, deny-list→False, 그 외 anchor∧zero→True
- 호출부: `if any(p.search(line) for p in _ZERO_COUNT_HINTS): continue` → `if _is_zero_count_context(line): continue`
- **불변 보존**: verify() 시그니처(`def verify(task_id, report_path="") -> dict`)·리턴 schema(`{status,details}`)·화이트리스트·메타라벨·RESOLVED·ISSUE_MARKER·issue-section 로직 전부 불변.

### 2. `tests/regression/test_critical_gap_false_positive_2506.py`
- round-2 narrowed 회귀 14건 추가(`test_r2_*`): PASS 4(R2-1~4) + FAIL 7(R2-5~11) + e2e 3(R2-12a/b/c).
- ZC7/ZC9 body 보강: narrowed ZERO_EXPR이 `:/=` 구분자·명시적 zero를 요구 → ZC7 `HIGH: 0 / CRITICAL: 0`, ZC9 `no new high/critical: 0건` (의도=zero-count PASS 보존).
- 기존 FP1~10, TP1~5, ZC1~6/8/10/11 불변.

## 필수 regression 12건 결과 (회장 명시)
- PASS 4건: HIGH/CRITICAL 0건 / CRITICAL=0 / fresh unresolved HIGH/CRITICAL=0 / 신규 HIGH·CRITICAL 없음 → 전부 zero-count 인정(True/PASS)
- FAIL 7건: [CRITICAL] 인증 없음 / 권한 검증 없음 / 암호화 없음 / [HIGH] secure_mode=0 / timeout=0 / [CRITICAL] port=0 / [CRITICAL] 신규 버그 패치 없음 → 전부 미억제(False, 탐지력 유지)
- 탐지력 보존 1건: 기존 FP/TP/ZC 전수 PASS + e2e [CRITICAL] 미해결 → verify FAIL 보존

## 검증 결과
- pytest: `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q` → **40 passed in 0.17s**
- `git diff --name-only origin/main` = critical_gap.py + test 파일 **2개만** (expected_files 내부) ✓
- forbidden 0 / ANU key literal(`c119085...`) grep 0건 ✓
- verify interface/schema 불변 ✓ / py_compile OK ✓

## L1 스모크테스트 결과 (필수 기록)
- **서버 재시작**: 해당없음 (순수 verifier 모듈 — 서버 무관)
- **API 응답 확인**: 해당없음 (HTTP API 아님)
- **실동작 확인(LIVE verify() 실행)**: 통과 — 임시 보고서 4종을 작성해 `critical_gap.verify()` 라이브 호출:
  - `HIGH/CRITICAL 0건` → PASS ✓ / `신규 HIGH·CRITICAL 없음` → PASS ✓
  - `[CRITICAL] 인증 없음` → FAIL ✓ / `[CRITICAL] secure_mode=0 설정 잔존` → FAIL ✓
  - helper 라이브: `[HIGH] timeout=0`→False ✓, `[CRITICAL] port=0`→False ✓, `CRITICAL=0`→True ✓, `fresh unresolved HIGH/CRITICAL=0`→True ✓
  - L1 RESULT: ALL PASS (pytest와 별개로 실제 모듈 실행 확인)
- **스크린샷**: 해당없음 (CLI/모듈 — UI 없음)

## 머지 판단
- **머지 필요**: Yes (단, 회장 승인 대기 — merge_policy=none)
- **브랜치**: task/task-2723-dev2
- **워크트리 경로**: /home/jay/workspace/.worktrees/task-2723-dev2
- **머지 의견**: round-2 surgical narrowed fix. expected_files 2개 내부, pytest 40건 PASS, false-negative 제거 검증 완료. ★ merge 금지 — ANU/watcher가 새 head(`bf150dfa`) OWNER `/gemini review` → CI/Gemini watcher → MERGE_READY_CANDIDATE 판정. 실제 merge는 회장 승인.

## doctrine 준수
- same-PR post-Gemini push: 새 commit→new head(`bf150dfa`)→non-force push로 진행, amend 미사용 ✓
- 자동 fix 금지: 새 HIGH/CRITICAL 발생 시 CHAIR_REQUIRED (본 round는 회장 명시 승인 remediation)
- long polling 금지: Gemini 리뷰는 watcher 위임 ✓

## 모델 사용 기록
- 토르(백엔드, critical_gap.py 교체): sonnet
- 헤임달(테스터, regression 14건 + ZC7/9 보강): sonnet
- 통합/검증/PR/보고/L1: 오딘(Opus, 팀장)
- haiku 미사용 (로직 정밀도 요구)

## 세션 통계
- 총 도구 호출: 0회

---

# task-2723+2 round-3 FINAL surgical fix (2026-06-03, 오딘 / 회장 명시 승인)

> 이어서 작업: PR #169, worktree `/home/jay/workspace/.worktrees/task-2723-dev2` (branch `task/task-2723-dev2`)
> 이전 head `bf150dfa` → 새 head `a2783b39` (non-force push)

## SCQA 요약 (round-3)

**S (상황)**: round-2(`bf150dfa`)에서 `_ZC_ZERO_EXPR` 의 zero 표현 정규식이 선행 `\b` 에 의존했다.

**C (문제)**: Gemini T5 HIGH 유효 — Python `re` 에서 한글은 `\w`(word char)라 "총0건"의 한글(총)↔숫자(0), "이슈없음"의 한글(이슈)↔한글(없음) 사이에 `\b` 경계가 없다. 따라서 `\b0`/`\b없음` 미매칭 → zero-expr suppress 실패 → 정상 zero-count 문구("- CRITICAL 총0건", "- 이슈없음", "- 이슈없다")가 오탐되어 FAIL.

**Q (질문)**: anchor 결속·strong marker·vuln deny-list 원칙을 전부 유지하면서 한글 무공백 zero-count 오탐만 제거할 수 있는가?

**A (답변)**: `_ZC_ZERO_EXPR` 의 **선행 `\b`만 숫자 전방 방어 `(?<!\d)` 로 교체**하고 한글어 word-boundary 의존을 제거하는 surgical 변경으로 달성. 나머지 가드(count-context anchor 결속, strong issue marker 미억제, vuln deny-list 미억제, `_is_zero_count_context` 우선순위)는 불변. verify 시그니처·return `{status,details}` 스키마 불변. 회귀 43건(기존 40 + 신규 3) 전수 통과.

## 변경 내용 (round-3)

```python
# before (round-2)
_ZC_ZERO_EXPR = re.compile(
    r"(?:\b0\s*건\b|\b0\s*개\b|[:=]\s*0(?!\d)|count\s*=\s*0|\b없음\b|없습니다|\b없다\b)"
)
# after (round-3)
_ZC_ZERO_EXPR = re.compile(
    r"(?:(?<!\d)0\s*건|(?<!\d)0\s*개|[:=]\s*0(?!\d)|count\s*=\s*0|없음|없습니다|없다)"
)
```
- `\b0\s*건\b` → `(?<!\d)0\s*건` / `\b0\s*개\b` → `(?<!\d)0\s*개` (숫자 전방 방어 유지: "10건"은 미매칭)
- `\b없음\b` → `없음` / `\b없다\b` → `없다` (한글 word-boundary 의존 제거)
- 유지: `[:=]\s*0(?!\d)` · `count\s*=\s*0` · `없습니다`

## 수정 파일 (expected_files 2개 내부, 그 외 0)
1. `teams/shared/verifiers/critical_gap.py` — `_ZC_ZERO_EXPR` 1줄 + 의도 주석 3줄
2. `tests/regression/test_critical_gap_false_positive_2506.py` — round-3 회귀 3건 append (기존 40건 무수정)

## 테스트 결과 (round-3)
- `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q` → **43 passed in 0.18s**
- 신규 PASS(zero-count 인정): R3-1 `- CRITICAL 총0건`, R3-2 `- 이슈없음`, R3-3 `- 이슈없다` ("이슈"가 anchor)
- 탐지력 보존(FAIL 유지): `[CRITICAL] 인증 없음`, `[CRITICAL] port=0`, `[HIGH] secure_mode=0`, `[HIGH] timeout=0`, `[CRITICAL] 신규 버그 패치 없음`, ZC10 `수정 없음`, ZC11 `![critical]` 전부 유지

## 검증 조건 (전수 충족)
1. round-3 regression 43건 의도대로 PASS ✓
2. `git diff --name-only origin/main` = expected_files 2파일 내부 ✓ (forbidden 0)
3. goal_assertion `(?<!\d)0` present → PASS ✓
4. goal_assertion ANU key literal 부재 (critical_gap.py + 테스트 파일 모두) → PASS ✓
5. verify interface/return schema 불변 ✓

## L1 스모크테스트 결과 (round-3, 필수 기록)
- **서버 재시작**: 해당없음 (순수 verifier 모듈 — 서버/HTTP 무관)
- **API 응답 확인**: 해당없음 (HTTP API 아님)
- **실동작 확인(LIVE verify() end-to-end)**: 통과 — 임시 보고서 5종을 작성해 `critical_gap.verify()` 라이브 호출:
  - `- CRITICAL 총0건` → PASS ✓ / `- 이슈없음` → PASS ✓ / `- 이슈없다` → PASS ✓
  - `- [CRITICAL] 인증 없음` → FAIL ✓ / `- [CRITICAL] port=0` → FAIL ✓
  - L1 RESULT: **ALL_OK** (pytest와 별개로 실제 모듈 실행 확인. pytest PASS ≠ 실동작이므로 별도 e2e 호출 수행)
- **스크린샷**: 해당없음 (CLI/모듈 — UI 없음)

## 머지 판단 (round-3)
- **머지 필요**: Yes (단, merge_policy=none — ★ 본 task에서 merge 금지)
- **브랜치**: task/task-2723-dev2 (head `a2783b39`)
- **워크트리 경로**: /home/jay/workspace/.worktrees/task-2723-dev2
- **머지 의견**: round-3 FINAL surgical. expected_files 2개 내부, 회귀 43건 PASS(PASS/FAIL 의도 일치), L1 e2e ALL_OK. ★ merge 금지 — ANU/watcher가 새 head(`a2783b39`) OWNER `/gemini review` → CI/Gemini watcher → MERGE_READY_CANDIDATE 판정·보고. 실제 merge는 회장 승인.

## doctrine 준수 (round-3)
- same-PR post-Gemini push: 새 commit(`a2783b39`)→new head→non-force push로 진행, amend 미사용 ✓
- ★ round-3 = 같은 regex 영역 FINAL. 이후 새 HIGH/CRITICAL → 추가 패치 금지 → LOOP_BOUNDARY/CHAIR_REQUIRED (redesign/alternative resolver) ✓
- bot `/gemini review` 무효(인간 OWNER 1회만), long polling 금지(watcher 위임) ✓

## 모델 사용 기록 (round-3)
- 토르(백엔드, `_ZC_ZERO_EXPR` 교체 + sanity check): sonnet
- 헤임달(테스터, round-3 회귀 3건 append): sonnet
- 통합/회귀/검증/커밋/push/L1 e2e/보고: 오딘(Opus, 팀장)
- haiku 미사용 (정규식 정합성·탐지력 보존 정밀도 요구)


## 세션 통계
- 총 도구 호출: 0회


---

# task-2723+3 — critical_gap zero-count REDESIGN (severity-count 구조 파싱, 회장 승인)

## Situation
round-1~3 의 zero-count 판정은 "줄에 zero 표현(0건/=0/없음)이 있으면 줄 전체를 suppress" 하는 라인 단위 휴리스틱이었다. 3회 진동(over-broad → word-boundary → mixed-count) 끝에 LOOP_BOUNDARY. 회장이 추가 regex 한 줄 incremental patch를 금지하고 **구조적 재설계**를 승인했다.

## Complication
mixed-count 한 줄 `"CRITICAL: 0, HIGH: 1"` 에서 라인 전체 suppress 는 HIGH 1(실제 미해결)까지 통째로 억제(false-negative)한다. 줄 단위 판정 자체가 한계.

## Question
줄을 통째로 보지 않고, **줄에서 severity별 (severity, count) 쌍을 파싱**하여 "모든 count 0 → 억제, 하나라도 >0 → 탐지 유지"로 전환할 수 있는가?

## Answer (redesign 구현)
`_is_zero_count_context(line)` 를 5단계 구조 파싱으로 재구현:
1. **STRONG_ISSUE_MARKER** (`[CRITICAL]`/`[HIGH]`/`![critical|high]`/`severity:critical|high`) → `return False` (실제 finding).
2. **VULN_NEGATION_DENYLIST** (인증/권한/암호화/패치/수정/조치/해결 없음, secure_mode|timeout|port=0) → `return False`.
3. **`parse_severity_counts(line)`** (신규 헬퍼): `_ZC_BIND_RE`로 severity 클러스터(슬래시 결합 그룹)에 결합된 숫자를 좌→우 추출.
   - `"CRITICAL: 0, HIGH: 1"` → `[0, 1]`, `"CRITICAL 0개, HIGH 2개"` → `[0, 2]`, `"HIGH/CRITICAL 0건"` → `[0]`, `"fresh unresolved HIGH/CRITICAL = 0"` → `[0]`, `"CRITICAL=0"` → `[0]`.
   - `if counts: return all(c == 0 for c in counts)` → **하나라도 >0 이면 False(탐지 유지)**.
4. **숫자 없는 부재형**: COUNT_ANCHOR + (ABSENCE_EXPR `없음|없습니다|없다`) → True. 단독 zero-count(`0건/0개`가 유일 카운트, >0 카운트 부재) → True.
5. 그 외 → `return False`.

★ 핵심 차이: round-1~3 = "zero 표현 있으면 통째 suppress" / redesign = "모든 severity count 0일 때만 suppress". → `"CRITICAL: 0, HIGH: 1"` 의 HIGH 1 을 정확히 탐지(FAIL).

## 수정 파일 (expected_files 2개 내부 — 그 외 0)
1. `teams/shared/verifiers/critical_gap.py` — 구 `_ZC_ZERO_EXPR` 라인 suppress 휴리스틱 폐기, `parse_severity_counts` + `_ZC_BIND_RE`/`_ZC_GAP`/`_ZC_SEVERITY_CLUSTER`/`_ZC_ABSENCE_EXPR`/`_ZC_ZERO_UNIT`/`_ZC_NONZERO_UNIT` 신설, `_is_zero_count_context` 5단계 재구현. verify() public interface/schema 불변.
2. `tests/regression/test_critical_gap_false_positive_2506.py` — R4 블록 9건 추가(parse 단위 3 + _is_zero_count_context mixed/all-zero 3 + e2e verify FAIL/PASS 3). 기존 43건 전부 유지.

## 테스트 결과
- `python3 -m pytest tests/regression/test_critical_gap_false_positive_2506.py -q` → **52 passed** (기존 43 + 신규 R4 9).
  - PASS(억제 보존): HIGH/CRITICAL 0건, CRITICAL=0, fresh unresolved=0, 신규 HIGH 없음, 총0건, 이슈없음/이슈없다, HIGH:0/CRITICAL:0.
  - FAIL(탐지 유지): **CRITICAL: 0, HIGH: 1**(mixed), **CRITICAL 0개, HIGH 2개**(mixed), [CRITICAL] 인증/권한/암호화 없음, [HIGH] secure_mode=0/timeout=0, [CRITICAL] port=0, 패치 없음, 기존 TP/ZC 탐지력 전부 보존.

## L1 스모크테스트 결과 (필수)
- **서버 재시작**: 해당없음 (verifier 모듈 — 상주 서버/HTTP 없음, CLI 호출형).
- **API 응답 확인**: 해당없음 (curl 대상 엔드포인트 없음). 대신 **모듈 실로드 e2e**: 워크트리(=PR 코드)의 `critical_gap.py`를 `importlib`로 직접 로드 → `parse_severity_counts`/`_is_zero_count_context` 실호출.
  - `parse('CRITICAL: 0, HIGH: 1')` = `[0, 1]`, `parse('CRITICAL 0개, HIGH 2개')` = `[0, 2]` ✓
  - mixed `CRITICAL: 0, HIGH: 1` → False(탐지) ✓ / `CRITICAL 0개, HIGH 2개` → False(탐지) ✓
  - all-zero `HIGH/CRITICAL 0건` → True(억제) ✓ / `CRITICAL=0`,`fresh ... =0`,`신규 HIGH 없음`,`총0건`,`이슈없음` → True ✓
  - `[CRITICAL] 인증 없음` → False(strong+deny) ✓
  - **L1 RESULT: PASS** (pytest와 별개로 실제 모듈 실행 확인. pytest PASS ≠ 실동작이므로 별도 e2e 수행)
- **스크린샷**: 해당없음 (CLI/모듈 — UI 없음).

## 검증 조건 충족
1. redesign regression 전부 의도대로 PASS (52 passed: PASS 케이스 + mixed-count FAIL 2 + 기존 FAIL + 탐지력 보존) ✓
2. `git diff --name-only origin/main` = expected_files 2파일 내부 ✓
3. forbidden 0 (FORBIDDEN_CLEAN) ✓
4. ANU key full literal(`c119085...`) 0 — 두 파일 KEY_CLEAN ✓
5. verify interface/schema 불변 (`def verify(task_id, report_path="") -> dict`, `{"status","details"}`) ✓

## 머지 판단 (+3 redesign)
- **머지 필요**: Yes (단, merge_policy=none — ★ 본 task에서 merge 금지)
- **브랜치**: task/task-2723-dev2 (new head `822c0c0b`)
- **워크트리 경로**: /home/jay/workspace/.worktrees/task-2723-dev2
- **머지 의견**: 구조적 redesign으로 round-1~3 진동 근본 해소. expected_files 2개 내부, 회귀 52건 PASS(mixed-count FAIL 정확), L1 e2e PASS. ★ merge 금지 — ANU/watcher가 new head(`822c0c0b`) OWNER `/gemini review` → CI/Gemini watcher → MERGE_READY_CANDIDATE 판정·보고. 실제 merge는 회장 승인.

## doctrine 준수 (+3)
- same-PR post-Gemini push: redesign = 새 commit 2건(`a2d1c429`, `822c0c0b`)→new head→**non-force push**(`a2783b39..822c0c0b` fast-forward), amend 미사용 ✓
- ★ 사후 정책: 이후에도 같은 critical_gap zero-count 계열 HIGH/CRITICAL 재발 시 **추가 패치 금지** → PR #169 hold 또는 alternative resolver 보고. merge 회장 승인 전 금지 ✓
- bot `/gemini review` 무효(인간 OWNER 1회만), long polling 금지(watcher 위임) ✓

## 모델 사용 기록 (+3)
- 토르(백엔드, `_is_zero_count_context` 구조 파싱 재구현 + parse_severity_counts): sonnet
- 헤임달(테스터, R4 회귀 9건 append + 전체 pytest): sonnet
- 통합/독립 재검증/커밋/push/L1 e2e/보고: 오딘(Opus, 팀장)
- haiku 미사용 (정규식 구조 파싱 정합성·탐지력 보존 정밀도 요구)

## 세션 통계
- 총 도구 호출: 0회

