# task-2774+14 — PR #254 same-PR micro-fix: raw key redaction(--key=) HIGH + 예외 type-only MED

상태명: `TASK2774P13_PR254_RAW_KEY_REDACTION_MICROFIX_APPROVED_ACTIVE_FALSE`
담당: dev2-team (PR #254 / branch `task/task-2774+13-dev2` 소유)
회장 승인: 2026-06-25 선택지 1 — fresh Gemini **security-HIGH + MED 둘 다** micro-fix. **루프성 polish 아님**:
PR #254 핵심 DoD(raw key 노출 0)를 깨는 보안 결함이라 닫는다. **PR #254 위 commit 1개만 추가**(same-PR).

## 배경
ANU 독립검증서 PR #254 코드/테스트/CI는 깨끗했으나 fresh Gemini가 2건:
- **security-HIGH**: `_redact_callback_argv`가 `--key VALUE`(공백)만 redact하고 **`--key=VALUE`(등호) 형식은
  미redact** → 그 형식이면 raw ANU key가 audit/log에 노출 가능(raw key hygiene DoD#7 구멍).
- **MED**: `real_launch_fn` 예외를 완전 swallow(아무 로그 0) → 발사 실패 원인 추적 곤란.
  `type(e).__name__` 정도만 남기면 raw key 노출 없이 디버깅 가능.

## 수정 범위 (엄수)
- **PR #254 위 micro-fix commit 1개만** 추가 (새 PR 금지). branch `task/task-2774+13-dev2`.
- 수정 허용: **`dispatch/anu_callback_launch_audit.py`** + **`tests/regression/test_normal_callback_real_launcher_2774p13.py`** 만.
- 설계문서 수정 필요 없으면 하지 말 것.
- **driver / runner / enforcement / pickup_once / governor / matrix / flag 수정 금지.**

## 수정 요구
1. `_redact_callback_argv` 가 **다음 두 형식 모두 redaction**:
   - `--key VALUE` (공백 구분) — 기존 동작 유지
   - `--key=VALUE` (등호) — **신규**
2. redaction 결과는 raw key 가 아니라 **`<ANU_SEALED_KEY>` 또는 동등 고정 마커**.
3. audit/result/stdout/stderr **어느 경로에도 raw key 0**.
4. `--key=` 뒤 값이 비어있거나 비정상이어도 raw key 노출 없이 안전 처리.
5. `real_launch_fn` 예외 처리 시 **예외 객체/메시지 그대로 남기지 말 것**. MED 처리는 **`type(e).__name__` 정도만**
   포함. 예외 message 원문·argv·key·env·path 등 민감정보 섞일 수 있는 내용 **기록 금지**.
6. 기존 **default OFF surface-only** 동작 유지. 기존 **gated 1-shot mock launcher** 동작 유지.
   **PR 내부 real cokacdir 발사 0** 유지.

## 필수 테스트 (test_normal_callback_real_launcher_2774p13.py)
- `--key VALUE` redaction 테스트 **유지**.
- **`--key=VALUE` redaction 신규 테스트 추가**.
- raw key 가 audit/result 에 남지 않음 확인.
- `real_launch_fn` 예외 시 verdict 는 실패(`REAL_FIRE_FAILED`)로 남되 **raw key 0**.
- `real_launch_fn` 예외 시 error 에 **예외 type 만** 포함. 예외 message 원문 미기록.
- default OFF → launcher 0 / gate 미충족 → launcher 0 / full gate 충족 → launcher 1회.
- governor BLOCK / owner-proof FAIL → launcher 0.
- `py_compile` PASS · 수정 후 전체 관련 테스트 PASS · 관련 회귀 PASS.

## ★ LOOP_BOUNDARY
- 이번 micro-fix 는 **HIGH 보안 결함 1회 처리**.
- fresh Gemini 가 **새 HIGH/Critical7** 다시 내면 → **즉시 CHAIR_REQUIRED** 보고.
- fresh Gemini 가 동일 redaction 축 **사소한 스타일 MED만** 내면 → **evidence 분리 후보**로 보고.
- 자동 2차/3차 수정 루프 **금지**.

## 절대 금지
merge / B real 1-shot 실행 / real cokacdir 발사 / activation flag 생성 / systemd start·enable /
recurring 생성 / matrix `ACTIVE=true` / `ENFORCED=true` 단정 / driver·runner·enforcement·pickup_once 수정 /
owner-key 서명 위조 / auto merge.

## 보고 항목 (필수)
micro-fix commit sha · 수정 파일 · `--key VALUE` redaction 증거 · `--key=VALUE` redaction 증거 ·
raw key 0 증거 · 예외 type-only 기록 증거 · 테스트 결과 · CI/Gemini 상태 · ACTIVE=false 유지 증거 · merge-ready 여부.

## 완료 처리 + ANU callback (필수)
- 완료 시 `memory/events/<task_id>.done` + `memory/reports/<task_id>.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#254·new head sha·result_path·report_path·one-line). **merge 절대 금지.**

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

## allowed_resources (본 task의 capability)

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