# task-2775+1 — PR #255 same-branch 보정: N=3 누계를 epoch-scope window 누계로 보정 (ACTIVE=false)

상태명: `TASK2775_R1_EPOCH_SCOPE_MICROFIX_APPROVED_FOR_DEV2_ACTIVE_FALSE`
담당: dev2-team (PR #255 / branch `task/task-2775-dev2` 소유)
회장 승인: 2026-06-26 — **PR #255 같은 브랜치 보정용 micro-fix 1회**.
★ 이 승인은 **activation / merge / real fire / systemd enable·start / flag 생성 / canary / recurring /
backlog consumption 승인이 아님.** ACTIVE=false · systemd disabled · flags OFF 유지.

## 배경 (ANU 독립검증 결함)
ANU 독립검증(`memory/reports/task2775_anu_independent_verification_n_window_scope_260626.md`):
`TASK2775_N_WINDOW_SCOPE_GAP_ACTIVE_FALSE`. `_count_active_window_pickups()`가 이름과 달리
`p0b_activation_epoch` 이후 필터 없이 ledger의 `outcome==LIVE_PROCESSED` **전체**를 셈 →
**첫 limited 창은 우연히 안전하나, 재가동(두 번째 창부터)은 이전 창 entry 때문에 즉시 false-OFF** 구조.
PR #255 방향·범위는 맞고, **N window scope만 보정**하면 다시 MERGE_CANDIDATE 후보.

## 목표
N=3 자동 OFF 기준을 **ledger 전체 누계 → 현재 limited activation window(epoch 이후) 누계**로 보정.

## 필수 구현
1. `_count_active_window_pickups()`는 **`p0b_activation_epoch` 이후의 `LIVE_PROCESSED` entry만** 카운트.
2. ledger entry의 `processed_at`(ISO8601 문자열, 예 `2026-06-18T15:36:29.955784+09:00`)을
   **timezone-aware datetime으로 파싱한 뒤 unix epoch(float)와 비교**. KST `+09:00` 등 **timezone offset 보존**.
   (epoch 마커 `p0b_activation_epoch`는 unix timestamp float — 문자열↔float 직접 비교 금지, 변환 후 비교.)
3. **epoch 이전 entry는 N 카운트 제외.**
4. **`processed_at` 필드 부재 / 파싱 실패 entry는 활성창 entry로 오인하지 말고 N 카운트에서 제외**(보수적 제외).
5. **epoch 부재 상태에서 active limited 판정이 필요한 경우**: 전체 ledger를 세거나 조용히 통과시키지 말 것 →
   **fire 0 fail-closed 또는 자동 disabled 정책을 명시하고 테스트로 고정.**
   (단 default-OFF / `NOOP_DISABLED` 기존 경로는 무손상 — "active인데 epoch 부재"만 위 정책 적용.)
6. **T=120 만료도 실제 `main()` 경로 L1 스모크로 추가 확인**(기존엔 unit test만, main() 미실측이었음).
7. kill → N → T 게이트 순서·governor·launcher build 이전 fire 0 단락·atomic disabled write 등
   **기존 +0 동작 무손상.**

## 범위 (엄수)
- **PR #255 같은 브랜치(`task/task-2775-dev2`) 위 commit 추가**. **새 PR 생성 금지**
  (기술적으로 불가하면 STOP 보고).
- expected_files **2개만**:
  - `dispatch/anu_pickup_driver.py`
  - `tests/regression/test_limited_activation_bounds_2775.py`
- **수정 금지**: governor / runner / launcher / owner-proof / freshness / systemd / `.github/**` /
  `scripts/finish-task.sh`.
- **금지**: merge / activation / real fire / `systemctl enable·start` / activation flag 생성 / canary 주입 /
  recurring 등록 / backlog consumption.

## 필수 테스트 (test_limited_activation_bounds_2775.py)
- **epoch 이전 LIVE_PROCESSED 3건 → N 카운트 0**.
- **epoch 이후 LIVE_PROCESSED 3건 → 자동 disabled + NOOP + fire 0**.
- **이전 limited 창 3건이 있어도 새 epoch 이후 0건이면 즉시 false-OFF 없음**(재가동 안전).
- `processed_at` **부재** entry 제외.
- `processed_at` **파싱 실패** entry 제외.
- **timezone-aware ISO8601 비교 검증**(KST `+09:00` 보존).
- **epoch 부재 active 상태 정책 검증**(fail-closed 또는 자동 disabled, 명시 정책대로).
- **T=120 만료 `main()` L1 스모크**.
- kill / N / T 모두 governor·launcher build 이전 **fire 0 단락 유지**.
- **기존 12개 테스트 + driver 회귀 PASS**.
- `py_compile` PASS · expected_files 밖 수정 **0**.

## 중단 조건 (하나라도 → STOP_REPORT, 우회 0)
- expected_files 밖 수정 필요 / 새 PR 불가피.
- governor/runner/launcher/systemd/finish-task 수정 필요.
- activation 또는 real fire가 필요해지는 경우.
- 기존 default-OFF / `NOOP_DISABLED` / B 1-shot / kill·N·T 단락 경로를 깨는 경우.
- self-callback / owner-proof / raw key redaction 축으로 scope가 번지는 경우.

## 결과 보고 (필수)
- PR #255 **유지 여부** · base/head SHA · **expected_files 2개 내 diff 증거**.
- **epoch 이전/이후 카운트 테스트 결과**.
- **timezone / `processed_at` 부재 / 파싱 실패 테스트 결과**.
- **T `main()` L1 스모크 결과**.
- ACTIVE=false / systemd disabled / flags OFF / real fire 0 / canary 0 증거.
- **MERGE_CANDIDATE 가능 여부**.

## 완료 처리 + ANU callback (필수)
- 완료 시 `memory/events/task-2775+1.done` + `memory/reports/task-2775+1.md`.
- 봇 idle 전 **ANU callback 필수**(성공/실패/blocked 무관). collector=ANU, owner_key=`c119085addb0f8b7`,
  self-key 금지. callback prompt UTF-8 **≤3900 bytes** (`printf '%s' "$P" | wc -c`), envelope 만
  (task_id·PR#255·new head sha·result_path·report_path·one-line). **merge 절대 금지.**
- PASS 나와도 **머지 금지** — ANU 독립검증 → fresh-head Gemini → CI 확인 → MERGE_CANDIDATE로만 보고.
  회장 명시 승인 전까지 PR #255 open 유지.

## 진행
dev2는 epoch-scope 보정 구현·테스트(real fire 0)·로컬검증 후 branch push로 **PR #255 갱신**,
보고서 + .done + ANU callback으로 마감. ANU가 이후 독립검증/Gemini/CI 확인 → 회장 머지 판단.

## allowed_resources (본 task의 capability)

```yaml
allowed_resources:
  paths:
    - "dispatch/anu_pickup_driver.py"
    - "tests/regression/test_limited_activation_bounds_2775.py"
    - "memory/reports/task-2775+1.md"
    - "memory/events/task-2775+1.done"
  forbidden_paths:
    - ".github/**"
    - "memory/events/*.cron-*"
    - "scripts/finish-task.sh"
    - "utils/spawn_safety_governor.py"
    - "dispatch/anu_result_pickup_runner.py"
    - "dispatch/anu_callback_launch_audit.py"
    - "dispatch/anu_owned_callback_enforcement.py"
    - "memory/state/p0b_driver_enabled"
    - "memory/state/p0b_callback_launch_enabled"
  commands:
    - "pytest"
    - "python3 -m py_compile"
    - "git"
    - "gh"
  merge_policy: "manual"
  ttl_hours: 24
```