# task-2775 ANU 독립검증 — N window scope 확인 (260626)

> ★ read-only 독립검증. 코드/ledger 직접 확인. 머지 0 · activation 0 · real fire 0 · flag 생성 0 · ACTIVE=false 유지.
> 회장 1차 판단(2026-06-26): MERGE_CANDIDATE 보류, N window scope 확인 요구.

## 최종 판정: `TASK2775_N_WINDOW_SCOPE_GAP_ACTIVE_FALSE`
**N=3 자동 OFF 기준이 "활성창(epoch 이후) 누계"가 아니라 "ledger 전체 누계"로 구현됨.**
회장 판정기준 2번(전체 ledger 누계 + false-OFF 가능 → MERGE_CANDIDATE 금지)에 해당. **머지 후보 보류.**

---

## 1. 코드 직접 확인 (PR #255 head de96e52e)
`_count_active_window_pickups()` 본문:
```python
path = os.path.join(root, LIVE_LEDGER_REL)
for line in fh:
    obj = json.loads(line)
    if isinstance(obj, dict) and obj.get("outcome") == VERDICT_LIVE_PROCESSED:
        count += 1
return count
```
- **epoch 이후 필터 없음.** `processed_at` 비교·`p0b_activation_epoch` 기준선 전무 → ledger 파일의
  LIVE_PROCESSED **전체**를 셈.
- 함수명은 `_count_active_window_pickups`(active window)이나 **실제 동작은 total count** — 이름↔동작 불일치.
- dev2 안전 근거 = 보고서상 *"활성창 첫 창은 ledger가 비어 시작 → 총계 == 활성창 누계"* 라는 **가정뿐, 코드/절차
  강제 없음.**

## 2. 경로 사실관계 (정직한 뉘앙스)
- dev2가 읽는 ledger: `LIVE_LEDGER_REL = "memory/events/p0b_processed_ledger.jsonl"` (events 경로).
- 과거 LIVE_PROCESSED 1건(task-canary-real-260618, 삭제금지 audit evidence)은
  `memory/state/p0b_processed_ledger.jsonl` (**state 경로**)에 있음 — driver가 읽는 경로 아님.
- events 경로 파일은 **현재 부재** → 지금 이 순간 count=0.

→ **정직한 결론**: "지금 당장 켜면 즉시 false-OFF"는 아님(events ledger가 우연히 비어 첫 창은 안전).
   **그러나 구조적 결함은 그대로**다 ↓

## 3. 왜 그래도 GAP인가 (false-OFF 가능 경로)
- events ledger는 **append-only**. 첫 limited 창에서 3건 발사 → 3줄 누적 → OFF(첫 창은 의도대로).
- **두 번째 limited 창**을 열면 이전 창의 3줄이 남아있어 **즉시 3/3 → false-OFF**. 즉 **재가동부터 구조적
  false-OFF.**
- driver 정상 처리도 이 경로에 LIVE_PROCESSED를 append하므로, 어떤 이유로든 entry가 쌓이면 활성창과 무관하게 오염.
- N이 **활성창(epoch 이후) 누계가 아니라 ledger 누적 총계**라는 점이 결함의 본질 → 회장 우려 정확히 적중.

## 4. 나머지 검증 항목 결과
- **kill/N main() 단락**: L1 스모크에서 `governor 빌더 0회·launcher 빌더 0회` 확인 → ✅ governor·launcher build
  이전 fire 0 단락 맞음.
- **T=120 만료**: unit test(epoch_reader 주입)로는 PASS이나 **main() 경로 L1 스모크는 미수행**(kill/N만 main()
  스모크). → T의 실경로 단락은 코드상 동일 gate 위치이나 **실측 미확인**(부수 gap, 치명 아님).
- expected_files 2개 엄수 · 신규 12 PASS · 기존 driver 65 PASS · PR open 유지 · ACTIVE=false·flags OFF·real
  fire 0 — **모두 양호**(방향·범위·머지금지 준수는 긍정).

## 5. micro-fix 필요 범위 (★구현 자동 진행 안 함 — 회장 승인 후 dev2 재위임)
**목적**: N 카운트를 "활성창(epoch 이후) 누계"로 scope.
- `_count_active_window_pickups`가 **`p0b_activation_epoch` 이후 entry만** LIVE_PROCESSED 카운트.
  ledger entry `processed_at`(ISO8601) ≥ activation_epoch(unix) 비교. epoch 부재 시 보수 정책 명시.
  (대안: limited window 전용 epoch 기준선/카운터. ledger 비우기는 audit evidence 삭제금지라 부적합 → **epoch
  필터가 정석**.)
- 부수: T=120 만료도 **main() 경로 L1 스모크** 추가.
- expected_files: `dispatch/anu_pickup_driver.py` + `tests/regression/test_limited_activation_bounds_2775.py`
  (과거/이전창 entry 존재해도 epoch 이후만 카운트 / 재가동 false-OFF 0 / epoch 부재 정책 테스트 추가).
- governor/runner/launcher/owner-proof/systemd/.github/finish-task **무수정** 유지.

## 6. 금지 유지 (회장 지시)
merge / activation / real fire / systemd enable·start / flag 생성 / canary / recurring — **전부 금지 유지.**
ACTIVE=false · systemd disabled · flags OFF. micro-fix는 **범위 제시까지만**, 구현·PR·머지 **자동 진행 0**,
회장 승인 대기.

## 7. 한 줄 결론
**kill·T·자동 OFF 방향은 맞고 dev2 범위 준수도 좋다. 단 N=3이 "활성창 누계"가 아니라 "ledger 누적 총계"라
재가동부터 false-OFF 구조 → MERGE_CANDIDATE 보류, epoch-scope micro-fix 1건 필요.**
