# task-2775+5 — PR #255 same-branch: production limited 전용 신호 `limited_runtime` 신설 + epoch fail-closed 결선 (옵션1, ACTIVE=false)

상태명: `TASK2775_PLUS5_LIMITED_RUNTIME_SIGNAL_MICROFIX_APPROVED_FOR_DEV2_ACTIVE_FALSE`
담당: dev2-team (PR #255 / branch `task/task-2775-dev2` 소유)
회장 승인: 2026-06-26 — **옵션1(preflight 무수정 / driver + 2775 테스트 2파일) micro-PR 1회**.
★ 이 승인은 **activation / merge / real fire / systemd enable·start / flag 생성 승인이 아님.**
ACTIVE=false · systemd disabled · flags OFF 유지.

## 배경 (4 STOP의 결론 → 신호 분리)
+3(flag-combo 무조건 주입)=test-2760 `drv.main()` 직접 호출 충돌 STOP. +4(`__main__`에서
`activation_intended=True`)=canary preflight `CANARY_PATHS_REQUIRED` 충돌 STOP. 근본 = **"canary가 아닌
production limited 무인 가동"을 표현하는 단일 신호 부재**. 설계 packet
(`memory/plans/spawn_safety_governor/limited_runtime_signal_design_packet_260626.md`) 권장안 = `limited_runtime`
신설. 이번 +5는 그 신호를 코드에 박는 micro-PR.

## ★ 설계 확정 (회장 verbatim)
- `activation_intended`는 **canary 전용**으로 유지.
- production limited 무인 가동은 **새 파라미터 `limited_runtime: bool = False`**로 표현.
- **`__main__` 경로만** `main(limited_runtime=True)`로 진입.
- test-2760이 호출하는 `drv.main()` **인자 0** 기본 호출은 `limited_runtime=False` · `activation_intended=False`로
  남겨 **legacy/test 경로 보존**.
- limited runtime은 **canary preflight를 호출하지 않는다**.
- limited runtime 안전모델 = **epoch bound + N/T 자동 OFF + kill switch + governor + owner-proof +
  callback_launch final gate**.

## 필수 구현
1. `main()`에 `limited_runtime: bool = False` 파라미터 추가.
2. `__main__`: `raise SystemExit(main(limited_runtime=True))`.
3. `limited_runtime=True` 경로에서 `limited_activation_bound_gate()`에
   `is_activated_fn=lambda: is_activated(CANONICAL_ROOT) and read_callback_launch_enabled(CANONICAL_ROOT)` 결선.
4. 두 flag 모두 ON + `p0b_activation_epoch` 부재/손상 → `NOOP_ACTIVE_EPOCH_MISSING_AUTO_DISABLED` + fire 0 +
   atomic disabled.
5. callback flag OFF 또는 driver flag OFF → 기존 **default-OFF / legacy 경로 무손상**.
6. canary preflight는 **`activation_intended=True` 경로에서만** 기존 그대로 유지(무수정·무변경).
7. ★ **`limited_runtime=True`와 `activation_intended=True`가 동시에 들어오는 경우는 의미 충돌** →
   **STOP 또는 fail-closed로 명시하고 테스트로 고정**. **임의로 둘 중 하나를 우선하지 말 것.**

## 범위 (엄수)
- **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`
- **수정 금지**: `dispatch/anu_activation_preflight.py` / **test-2760** / entrypoint shell·systemd /
  governor / runner / launcher / owner-proof / freshness / `.github/**` / `scripts/finish-task.sh`.
- **금지**: merge / activation / real fire / `systemctl enable·start` / activation flag 생성 / canary 주입 /
  recurring 등록 / backlog consumption.

## 필수 테스트 (test_limited_activation_bounds_2775.py)
- `__main__` / `python3 -m dispatch.anu_pickup_driver` 경로가 **`limited_runtime=True`로 들어오는지** 검증.
- `limited_runtime=True` + driver ON + callback ON + epoch **부재** → auto disabled + fire 0 +
  **governor/launcher 미호출**.
- `limited_runtime=True` + driver ON + callback ON + epoch **손상** → auto disabled + fire 0.
- `limited_runtime=True` + **정상 epoch** → **canary preflight를 타지 않고** 기존 scan 경로로 진행 가능.
- `limited_runtime=True` + **callback flag OFF** → legacy/default 경로 무손상.
- `limited_runtime=True` + **driver flag OFF** → default-OFF 무손상.
- `drv.main()` 인자 0 호출은 `limited_runtime=False` 유지.
- **test-2760 36 PASS 유지**.
- **2775 bounds 전체 PASS**.
- 기존 epoch-scope N/T/kill/timezone/processed_at 테스트 **무회귀**.
- **`limited_runtime=True` + `activation_intended=True` 동시 True 정책 테스트**(STOP/fail-closed 고정).
- `py_compile` PASS · expected_files 밖 수정 **0**.

## STOP 조건 (하나라도 → STOP_REPORT, 우회 0)
- limited_runtime 분기가 canary 또는 legacy/test-2760 경로를 깨는 경우.
- limited_runtime이 canary preflight를 타서 `CANARY_PATHS_REQUIRED`로 정상 pickup을 막는 경우.
- preflight 수정이 필요해지는 경우.
- entrypoint shell/systemd 수정이 필요해지는 경우.
- expected_files 밖 수정이 필요한 경우.
- activation / real fire / canary / systemd enable·start가 필요해지는 경우.

## 결과 보고 (필수)
- PR #255 **유지 여부** · base/head SHA · **expected_files 2개 내 diff 증거**.
- **`__main__` limited_runtime 경로 검증 결과**.
- **active+epoch 부재/손상 L1 결과** · **정상 epoch 경로 결과** · **canary preflight 미호출 증거**.
- **test-2760 결과** · **2775 bounds 결과**.
- ACTIVE=false / systemd disabled / flags OFF / real fire 0 / canary 0 증거.
- **MERGE_CANDIDATE 가능 여부**.

## 완료 처리 + ANU callback (필수)
- 완료 시 `memory/events/task-2775+5.done` + `memory/reports/task-2775+5.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는 `limited_runtime` 신호 신설·결선 구현·테스트(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+5.md"
    - "memory/events/task-2775+5.done"
  forbidden_paths:
    - ".github/**"
    - "memory/events/*.cron-*"
    - "scripts/finish-task.sh"
    - "dispatch/anu_activation_preflight.py"
    - "tests/regression/test_*2760*.py"
    - "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
```

## goal_assertions (auto-generated)
- `python3 -m dispatch.anu_pickup_driver`
