# task-2775 보고서 — limited activation guard micro-PR: 3경계(kill/N/T) 선행 안전 결선 (ACTIVE=false)

- 작업 ID: task-2775
- 팀: dev2-team (오딘/팀장)
- 상태명: `LIMITED_ACTIVATION_GUARD_MICRO_PR_APPROVED_FOR_DEV2_ACTIVE_FALSE`
- 작성: 2026-06-26 18:59 KST
- 검증 레벨: normal · 게이트: Lv.2 (X팀 한정승인 → 팀장 자체 G1/G2/G3)

---

## S (Situation)
limited activation §10 gap audit(`memory/reports/limited_activation_gap_audit_260626.md`)
판정 = `GAP_PRESENT_MICRO_PR_REQUIRED_ACTIVE_FALSE`. 순간 폭주 방지(governor 6게이트)와
fail-closed·관측은 PRESENT이나, **limited를 "진짜 limited"로 만드는 3경계(누계 N 자동OFF /
시간창 T 자동OFF / 즉시 kill)가 부재** → "무인인데 스스로 안 꺼지는 상태".

## C (Complication)
3경계가 없으면 limited activation 가동 불가. 단, 본 micro-PR은 **activation이 아닌 선행 안전
결선**이어야 한다: ACTIVE=false · systemd disabled · flags OFF 유지, 기존 default-OFF /
NOOP_DISABLED / B 1-shot 경로 절대 무손상, governor/runner/launcher/owner-proof/systemd/
finish-task/.github **무수정**, expected_files 2개 엄수.

## Q (Question)
driver 진입 최상단(fire 가능 경로 이전)에 **kill→N→T** 순서의 limited-bound gate 1개를,
기존 동작을 한 글자도 깨지 않고 박을 수 있는가? 그리고 실제 main() 경로에서 fire 0 ·
governor 미호출로 단락됨을 관측 가능하게 증명할 수 있는가?

## A (Answer)
구현했고, 실제 `main()` 경로 L1 스모크로 증명했다.

### 변경 파일 (expected_files 정확히 2개 — 밖 수정 0)
1. `dispatch/anu_pickup_driver.py` (+161): 상수 3종 + verdict 라벨 3종 + 헬퍼 2개 +
   `limited_activation_bound_gate()` + `main()` 최상단 결선 + `__all__` 노출.
2. `tests/regression/test_limited_activation_bounds_2775.py` (신규, 306줄, 12 케이스).

### 게이트 설계 (kill → N → T)
- **kill**: `memory/state/p0b_kill` 존재 → 즉시 `NOOP_KILL_SWITCH` 반환, **flag write 없음**
  (1-touch 즉시 정지, governor 호출 전 단락).
- **N**: processed_ledger(`memory/events/p0b_processed_ledger.jsonl`)의 `outcome==LIVE_PROCESSED`
  누계 ≥ **N=3** → `p0b_driver_enabled`에 **atomic `disabled` write**(tempfile+os.replace) + `NOOP_N_EXCEEDED_AUTO_DISABLED`.
- **T**: `p0b_activation_epoch` + **120분(T)** 경과 → 동일 atomic disabled write + `NOOP_T_EXPIRED_AUTO_DISABLED`.
- 세 조건 모두 미해당(kill 없음·누계<N·epoch 없음/T 이내) → **None 반환, side-effect 0** → 기존 경로 100% 보존.
- `main()` 최상단(activation_intended preflight·launcher/callback/governor build·scan **이전**)에서
  게이트가 None 아니면 stderr 1줄 출력 후 `return 0` → fire 0, governor 미호출.

### N 누계 기준 / fail-safe
- 누계 N의 기준 = processed_ledger의 `LIVE_PROCESSED` 실발사 entry 수(활성창 첫 창은 ledger가
  비어 시작 → 총계 == 활성창 누계). 개별 라인 파싱 실패 → 그 라인만 skip. ledger 전체 읽기 실패
  → count 0 반환(**false-OFF 방지**; downstream governor가 LEDGER_UNREADABLE 시 fail-closed BLOCK으로 fire 0 보장).
- 자동 disabled write 실패 시에도 해당 cycle은 NOOP(fire 0)로 단락, 다음 cycle 재시도.

---

## 머지 판단
- **머지 필요**: No (회장 명시 승인 전까지 PR open 유지 — task md §완료 처리 강제)
- **브랜치**: `task/task-2775-dev2`
- **워크트리 경로**: `/home/jay/workspace/.worktrees/task-2775-dev2`
- **PR**: https://github.com/Jeon-Jonghyuk/dev_workspace/pull/255 (아래 "PR 정보"에 기재)
- **머지 의견**: 로컬 검증 PASS이나 task 지침에 따라 **머지 금지**. ANU 독립검증 → fresh-head
  Gemini → CI 확인 → MERGE_CANDIDATE 보고 → 회장 머지 판단 순으로 진행. 충돌 가능성 낮음
  (단일 파일 추가 결선 + 신규 테스트 파일, governor/runner 등 공유 모듈 무접촉).

## PR 정보
- base SHA: `e8925d91959fee06d003e14c93d15facce28810c`
- head SHA: `de96e52e34c5b99c307c1c585be52ba29b339fe6`
- PR 번호/URL: **#255** — https://github.com/Jeon-Jonghyuk/dev_workspace/pull/255

---

## 테스트 결과

### 신규 회귀 (test_limited_activation_bounds_2775.py) — 12 PASS
kill(즉시 NOOP·flag write 0), N 초과(atomic disabled), N 미만(None·side-effect 0),
outcome 필터, T 만료(disabled), T 이내(None), epoch 부재, kill>N 우선순위,
atomic write 완전성, flag_writer 주입, clean-state None(default-OFF 회귀 가드).
```
12 passed in 0.17s
```

### 기존 driver 회귀 무손상 — 65 PASS
```
test_anu_pickup_driver_2721.py ............ 34 passed
test_anu_pickup_activation_hardening_2729p7.py .. 11 passed
test_activation_intended_safety_2774p5.py ...... 20 passed
65 passed in 0.35s
```

### 광범위 무회귀 스윕 (pickup/governor/owner/callback/activation/freshness/fire)
`826 passed`. 단, **base(e8925d91)에서도 동일하게 실패하는 기존 실패 6건** 존재 →
`test_anu_pickup_p0b_audit_decision_check.py`(5) + `test_sealed_key_and_launcher_wiring_2729p13.py::test_07`(1).
교차 확인: 내 코드 미존재(grep 0) base에서 동일 6건 실패 → **본 변경과 무관한 기존 실패**(회귀 아님).

### py_compile
`dispatch/anu_pickup_driver.py`, `tests/.../test_limited_activation_bounds_2775.py` 모두 PASS.

---

## L1 스모크테스트 결과 (실제 main() 경로 — 격리 tmp, production 무접촉)
- **서버 재시작**: 해당없음 (driver는 systemd oneshot 진입점, 상시 서버 아님)
- **API 응답 확인**: 해당없음 (코드-레벨 안전 게이트)
- **실동작 검증 (main() 직접 실행)**:
  - L1-kill: kill 스위치 설치 → `main()` rc=0 · **governor 빌더 0회 · launcher 빌더 0회** ·
    `p0b_driver_enabled` 미생성(flag write 0) · stderr `... bound gate NOOP (fire 0, governor 미호출): NOOP_KILL_SWITCH`.
    → **fire 가능 경로 진입 0 증명**.
  - L1-N: ledger LIVE_PROCESSED 3줄 → `main()` rc=0 · governor 빌더 0회 ·
    `p0b_driver_enabled == "disabled"`(atomic 자동 OFF) · stderr `... NOOP_N_EXCEEDED_AUTO_DISABLED`.
- **스크린샷**: 해당없음 (백엔드 CLI 진입점, UI 없음)
- CANONICAL_ROOT monkeypatch로 격리, production `memory/state/{p0b_kill,p0b_driver_enabled,p0b_activation_epoch}`
  및 ledger **전부 미생성(무접촉) 확인**.

---

## ACTIVE=false / real fire 0 증거
- production flags 전부 OFF: `p0b_kill`/`p0b_driver_enabled`/`p0b_activation_epoch` 미존재, ledger 미존재(무접촉).
- systemd: 본 PR 무접촉 (유닛 파일 수정 0, `systemctl enable/start` 미실행).
- real fire 0 / canary 0 / recurring 0: 본 작업은 코드 결선 + 테스트만. cokacdir 발사·cron 등록 0.
  callback_launch_fn/launcher_fn은 ACTIVE flag gate 내장(OFF 기본) — 게이트 도달조차 안 함(default-OFF에서 scan_once NOOP_DISABLED).

## limited GO 후보 가능 여부
- 3경계(kill/N/T)가 코드에 결선되어 "무인 자동 OFF 경계" 부재 gap 해소. ACTIVE=false 무손상.
- **단, 머지 전이므로 GO 아님.** ANU 독립검증 + fresh-head Gemini + CI PASS + 회장 머지 승인 후
  limited GO 후보 packet 진입 가능. 본 PR 자체는 `MERGE_CANDIDATE`로만 보고.

---

## 발견 이슈 및 해결
1. **pre-commit 가드 차단** (`start_task_guard not passed: lock missing`): main 워크트리에서 브랜치
   작업 시 worktree 격리 위반. → 변경을 패치 보존 → main 워크트리 복구 → 정식 `.worktrees/task-2775-dev2`
   생성 → `start_task_guard.py`로 9검증 통과 + lock 생성 → 패치 재적용 → micro-commit 정상.
2. **테스트 import 가림** (`tests/dispatch/` stub이 실제 dispatch 패키지 가림): 기존 테스트와 동일한
   `importlib.util` 직접 로드 부트스트랩으로 해소(대상 코드 무수정).
3. **광범위 스윕 6건 실패**: base 동일 실패로 교차 확인 → 기존 실패(무관), 회귀 아님으로 정리.

## 모델 사용 기록
- 토르(백엔드, 게이트 구현): `sonnet` — 안전-critical 로직 구현, haiku 부적합.
- 헤임달(테스터, 회귀 12케이스): `sonnet` — 테스트 설계 정확도 필요, haiku 부적합.
- 팀장(오딘): 설계/분배/검토/L1 직접 검증/통합 (Opus, 직접 코딩 없음).

## 비고
- 중단 조건(expected_files 밖 수정 / governor 등 수정 / activation 필요 / false-OFF / B 1-shot 손상 /
  self-callback·owner-proof scope 번짐) **해당 0** — STOP 없이 정상 완료.
- merge 절대 금지 준수. ANU normal callback은 finish-task.sh의 ANU-owned launcher 게이트
  (owner_key=ANU `c119085addb0f8b7`, self-key fail-closed) 경유로 등록(executor self-key 직접 등록 0).

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


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


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


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


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


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


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


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


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


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

