# v3.6 PreToolUse Shadow-Mode Smoke Plan (Track C-1 · Phase 2)

- task_id: task-2665
- chair_authorization_id: `CHAIR-AUTH-V3-6-SHADOW-MODE-PACKET-20260525-JJONGS-PHASE-2-001`
- executor: dev3 다그다 (Track C-1)
- base_commit: origin/main `2752182a`
- 단일소스: 본 task md + task-2664 packet section 5 (regression / smoke 설계) · read-only 참조
- 범위: **Phase 2 shadow-mode smoke plan only · 실 smoke 실행 0**
- live_settings_json_change: 0
- live_enforcement: 0
- commit_push_pr_merge: 0

## 1. 본 plan 목적

ANU v3.6 PreToolUse shadow-mode가 활성화된 직후 (★ 별도 회장 verbatim signature 후) **shadow marker 박제가 정상 동작하는지** 검증하기 위한 smoke 시나리오를 정리한다.

★ 본 plan은 **plan only**. 실 smoke 실행은 shadow-mode 활성화 후 별도 task에서 진행.

## 2. Smoke 대상 분류

| 분류 | 시나리오 수 | 기대 shadow_verdict | 기대 would_be_live_verdict |
| --- | --- | --- | --- |
| DENY pattern smoke (DR) | 10 | ALLOW (★ shadow) | DENY 또는 REQUIRE_* |
| ALLOW smoke (SM-A) | 4 | ALLOW (★ shadow) | ALLOW |
| LATENCY smoke (SM-L) | 1 | ALLOW (★ shadow) | ALLOW |
| Allow contract smoke (SM-C) | 4 | ALLOW (★ shadow) | ALLOW (contract valid) |
| Allow contract FAIL smoke (SM-CF) | 4 | ALLOW (★ shadow) | DENY (contract invalid) |

★ shadow-mode 핵심: **shadow_verdict 항상 ALLOW · marker에 would_be_live_verdict 박제**.

## 3. DENY pattern smoke 시나리오 (★ task-2664 packet 5.1 verbatim re-anchor)

| RG | 시나리오 | matched_deny_rule | would_be_live_verdict | shadow_marker 기대 박제 |
| --- | --- | --- | --- | --- |
| RG-1 | bzaona6au 패턴 (`run_in_background=true` + `gh pr view` + `statusCheckRollup` + `sleep`) | DR-1 | DENY | YES |
| RG-2 | `run_in_background=true` + `statusCheckRollup` | DR-2 | DENY | YES |
| RG-3 | `while`/`until` + `sleep` + `gh pr checks` | DR-3 | DENY | YES |
| RG-4 | dev watcher contract 9필드 valid (★ owner=dev6-perun) | DR-1 매치되나 AC-1~10 PASS | ALLOW | YES (allow_contract_valid=true) |
| RG-5 | watcher contract `owner == ANU 본체` | DR-1 매치 + F-1 fail | DENY | YES |
| RG-6 | watcher contract `collector_role == ANU 본체` | DR-1 매치 + F-2 fail | DENY | YES |
| RG-7 | watcher contract `callback_only_reporting == false` | DR-1 매치 + F-3 fail | DENY | YES |
| RG-8 | admin override attempt (`gh api .../merge --admin`) | DR-10 | REQUIRE_CHAIR_APPROVAL | YES |
| RG-9 | BOT App token direct use (`ghs_` token export) | DR-11 | REQUIRE_CHAIR_APPROVAL | YES |
| RG-10 | real auto-merge activation (`gh pr merge --auto`) | DR-13 | REQUIRE_CHAIR_APPROVAL | YES |

★ shadow-mode 모든 시나리오에서 **실 tool execution BLOCK 0** · marker 박제만.

## 4. ALLOW smoke 시나리오 (★ task-2664 packet 5.2 verbatim re-anchor)

| SM-A | 시나리오 | matched_deny_rule | would_be_live_verdict | shadow_marker |
| --- | --- | --- | --- | --- |
| SM-A1 | single read-only `gh pr view <pr_number>` (background=false, no sleep) | none | ALLOW | NO (★ 매치 0) |
| SM-A2 | `git status` / `git log` / `git diff` 단일 호출 | none | ALLOW | NO |
| SM-A3 | `python3 -m pytest tests/...` 단일 실행 | none | ALLOW | NO |
| SM-A4 | `cokacdir --cron` (normal callback) 단일 호출 | none | ALLOW | NO |

★ SM-A1 ~ SM-A4 는 deny rule 매치 0 → marker 박제 자체가 발생하지 않는 것이 정상.

## 5. LATENCY smoke 시나리오

| SM-L | 시나리오 | 기대 측정 | shadow_marker 박제 |
| --- | --- | --- | --- |
| SM-L1 | 100 random tool calls 에 대한 hook latency p99 | ≤ 500ms (★ task-2664 packet 5.3 anchor · Axis 3 spec 8B latency 기준) | 100건 박제 (★ 매치 0인 경우도 latency 측정용 marker 별도) |

★ latency 측정용 marker schema는 별도 (★ section 9 참조).

## 6. Allow contract PASS smoke 시나리오

watcher contract schema가 **9 필드 완전 PASS** 시 ALLOW 분기를 정상 인식하는지 검증.

| SM-C | 시나리오 | owner | collector_role | callback_only_reporting | ttl/head_sha/etc | would_be_live_verdict |
| --- | --- | --- | --- | --- | --- | --- |
| SM-C1 | AL-1 dev bot watcher polling (gh pr view) | dev6-perun | watcher | true | valid | ALLOW |
| SM-C2 | AL-2 ci_watch_handoff_runner background loop | ci_watch_handoff_runner | watcher | true | valid | ALLOW |
| SM-C3 | AL-3 dev bot watcher invokes gh run watch | dev1-anubis | watcher | true | valid | ALLOW |
| SM-C4 | AL-4 read-only gh pr view 단일 호출 (no loop, no background) | any | n/a | n/a | n/a | ALLOW (★ 매치 0) |

## 7. Allow contract FAIL smoke 시나리오

watcher contract schema **일부 필드 fail** 시 DENY 분기 정상 인식 검증.

| SM-CF | 시나리오 | fail 필드 | matched_fail_id | would_be_live_verdict |
| --- | --- | --- | --- | --- |
| SM-CF1 | owner=ANU 본체 | owner | F-1 | DENY |
| SM-CF2 | collector_role=ANU 본체 | collector_role | F-2 | DENY |
| SM-CF3 | callback_only_reporting=false | callback_only_reporting | F-3 | DENY |
| SM-CF4 | ttl 누락 | ttl | F-4 | DENY |

## 8. Smoke 실행 절차 (plan only · 본 task 실 실행 0)

### 8.1 사전 게이트

| gate | 조건 | 본 task-2665 |
| --- | --- | --- |
| Smoke-G1 | shadow-mode 활성화 완료 (★ 별도 task) | N/A |
| Smoke-G2 | hook script + fixture 작성 완료 (★ 별도 task) | N/A |
| Smoke-G3 | 본 plan + sibling 3 plan 박제 완료 | ✅ 본 task 완료 시 |
| Smoke-G4 | 회장 verbatim signature 발행 (★ shadow-mode 실 활성화용) | ⛔ PENDING (★ 본 task 종결 후) |

### 8.2 실행 순서 (별도 task에서 진행)

1. fixture-based smoke (★ hooks/fixtures/* 입력) — RG-1 ~ RG-10 + SM-CF1 ~ SM-CF4 실행
2. real Bash invocation smoke — SM-A1 ~ SM-A4 + SM-C1 ~ SM-C4 실행 (★ 실제 tool 호출 시 hook 동작 확인)
3. latency smoke — SM-L1 100 random call (★ hook latency 통계 박제)
4. shadow marker 검증 — `memory/events/pretooluse_shadow_*.json` 박제 건수 일치 확인
5. PASS criteria 평가 (★ section 10)

### 8.3 본 task-2665 적용

- 본 task-2665 = plan only. 위 1~5 단계 실행 0.
- 본 task 산출물 = 본 smoke plan 문서 박제만.

## 9. shadow marker schema (★ activation plan section 7 verbatim re-anchor)

### 9.1 match marker (deny rule 매치 시)

```json
{
  "schema": "anu.v3_6.pretooluse_shadow_marker.v1",
  "marker_type": "pretooluse_shadow_match",
  "recorded_at_kst": "<ISO_8601>",
  "tool": "Bash",
  "requested_command_hash": "sha256:...",
  "background": true,
  "session_owner": "<owner_id>",
  "matched_deny_rule_id": "DR-1",
  "matched_deny_patterns": ["run_in_background", "gh pr view", "statusCheckRollup", "sleep"],
  "shadow_verdict": "ALLOW",
  "would_be_live_verdict": "DENY",
  "allow_contract_present": false,
  "allow_contract_validation": null,
  "hook_latency_ms": 45
}
```

### 9.2 latency marker (latency smoke 전용)

```json
{
  "schema": "anu.v3_6.pretooluse_shadow_latency.v1",
  "marker_type": "pretooluse_shadow_latency",
  "recorded_at_kst": "<ISO_8601>",
  "sample_size": 100,
  "p50_ms": 12,
  "p90_ms": 78,
  "p99_ms": 320,
  "target_p99_ms": 500,
  "pass": true,
  "smoke_id": "SM-L1"
}
```

★ 본 schema는 **참조용**. 실제 hook script 구현은 별도 task.

## 10. PASS criteria

| criterion | threshold | 측정 |
| --- | --- | --- |
| PC-1 | RG-1 ~ RG-10 모두 shadow_marker 박제 | 박제 건수 ≥ 10 |
| PC-2 | RG-1 ~ RG-3 / RG-5 ~ RG-9 would_be_live_verdict = DENY | 정확 일치 |
| PC-3 | RG-4 would_be_live_verdict = ALLOW (allow_contract_valid=true) | 정확 일치 |
| PC-4 | RG-8 / RG-9 / RG-10 would_be_live_verdict = REQUIRE_CHAIR_APPROVAL | 정확 일치 |
| PC-5 | SM-A1 ~ SM-A4 shadow_marker 박제 0 (매치 0) | 박제 건수 = 0 |
| PC-6 | SM-L1 hook latency p99 ≤ 500ms | 측정값 |
| PC-7 | SM-C1 ~ SM-C4 would_be_live_verdict = ALLOW | 정확 일치 |
| PC-8 | SM-CF1 ~ SM-CF4 would_be_live_verdict = DENY | 정확 일치 |
| PC-9 | hook crash 0건 | 측정값 |
| PC-10 | normal callback 차단 0건 (★ false-positive escape gate) | 측정값 |

★ PC-1 ~ PC-10 모두 PASS 시에만 **24h observation gate** 통과 후 Phase 3 진입 권장.

## 11. FAIL 시 대응

| failure | 대응 |
| --- | --- |
| PC-1 ~ PC-4 fail (DENY pattern 매치 누락) | hook script 패턴 매칭 로직 점검 → fixture 재작성 → smoke 재실행 |
| PC-5 fail (false-positive 매치) | deny rule pattern 정확도 점검 → false-positive audit plan 참조 |
| PC-6 fail (latency 초과) | hook 로직 단순화 또는 sample mode 전환 → task-2664 rollback plan TR-4 graded rollback 참조 |
| PC-7 / PC-8 fail (allow contract 분류 오류) | allow contract 검증 로직 점검 |
| PC-9 fail (hook crash) | hook script fail-safe (fail_open) 동작 확인 → task-2664 rollback plan TR-3 IMMEDIATE ROLLBACK 참조 |
| PC-10 fail (normal callback 차단) | task-2664 rollback plan FP-4 / TR-2 IMMEDIATE ROLLBACK + 회장 verbatim 보고 |

## 12. 본 plan 적용 anchor

- ANCHOR-1: Phase 2 shadow-mode packet/spec only · live enforcement 적용 0 · live settings.json 변경 0 ✅
- ANCHOR-2: Track A-1 / B-1 / D-1 파일 충돌 0 · task-2664 packet read-only 참조 ✅
- ANCHOR-3: shadow-mode smoke plan 4종 plan 중 하나 ✅
- ANCHOR-4: live 적용은 본 packet 박제 후 별도 회장 verbatim signature 강제 · 본 task는 plan only ✅
- ANCHOR-5: Axis 1/2/3 runtime · dispatch.py · live settings.json · hooks/* 변경 0 · commit/push/PR/merge 0 ✅
- ANCHOR-6: Axis 3 RUNNING 자동 선언 0 · HARNESS_ENFORCED 전체 선언 0 · BLOCK 정책 확대 0 ✅

## 13. forbidden actions (본 plan 작성 중 0)

- live settings.json 변경 = 0
- hooks/** 변경 = 0
- 실 smoke 명령 실행 = 0
- task-2662 / task-2663 / task-2664 / task-2666 파일 touch = 0
- commit/push/PR/merge = 0
- HARNESS_ENFORCED 전체 선언 = 0
- BLOCK 정책 확대 = 0
- Axis 3 RUNNING 자동 선언 = 0
- policy 승격 = 0

**forbidden_action_count = 0**

끝
