# task-2950 — Lv.3+ 4096자 절벽 본수정 (개발1팀 헤르메스)

- **작업일**: 2026-08-13
- **레벨**: critical
- **merge_policy**: local_only (머지는 ANU 소관)
- **repo**: /home/jay/workspace (메타인프라), task-2946 라이브 트리 기반

---

## 1. 결론 (실측)

| 팀 | normal | critical | security | 종전 critical |
|---|---|---|---|---|
| dev1 | 3,029 | 3,416 | 3,419 | 4,646 |
| dev2 | 3,025 | 3,412 | 3,415 | 4,642 |
| dev3 | 3,054 | 3,441 | 3,444 | 4,671 |
| dev4 | 3,032 | 3,419 | 3,422 | 4,649 |
| dev5 | 3,028 | 3,415 | 3,418 | 4,645 |
| dev6 | 3,026 | 3,413 | 3,416 | 4,643 |
| dev7 | 3,030 | 3,417 | 3,420 | 4,647 |
| **dev8** | 3,254 | **3,641** | **3,644** | **4,871 / 4,874** |
| marketing | 2,579 | 2,966 | 2,969 | 4,196 |
| design | 2,608 | 2,995 | 2,998 | 4,225 |
| consulting / content | 2,413 | 2,800 | 2,803 | 4,030 |
| publishing | 2,419 | 2,806 | 2,809 | 4,036 |

- **상한 초과 셀 0개** (종전 20개)
- **dev8 Lv.3+ = 3,641 / 3,644 ≤ 3,700 목표 충족** (3,900 가드 대비 여유 256 / 259)
- 측정: `python3 scripts/measure_dispatch_prompt_sizes.py` · 문자수(len) 기준
- Lv.3+ 증분 1,241자 → **387자**

## 2. 변경 내역

### 2-1. `prompts/team_prompts.py`

- `_build_verification_section` 재작성
  - 인지 검증 doctrine **552 → 145자** 압축, **인라인 유지**.
    핵심 동사 7개 verbatim 보존: 단정하지 않는다 / 확신도를 드러내고 / 먼저 실행한다 /
    직접 확인한다 / 교차 / 좁히는 법 / 보고에 밝힌다
  - 게이트 지시(437자) · Codex 사전 검증 명령 · Sanitize 블록(240자) → **QC-RULES.md verbatim 이관**
    (§게이트 / §Lv.3+ / §sanitize), 프롬프트엔 **경로 + sha256 short 핀 + 절 참조**만
  - **trip-wire 5종 인라인**(151자): `Critical7=0 · PII net-new=0 · 회귀실패=0 ·
    forbidden_paths침범=0 · nonce=task_id 일치` + result.json `trip_wire` 기록 지시
- `qc_rules_sha_short()` 신설 — 파일 부재/권한 오류에도 **raise 하지 않고** `unavailable` 반환(무손상)
- `build_qc_rules_transferred_sections()` 신설 — 이관 본문의 **코드 단일 진실원천**
- `_build_three_docs_section` 압축 (494 → 180자) — 아래 §4 참조

### 2-2. `dispatch/__init__.py`

- `DISPATCH_PROMPT_MAX_CHARS` **4096 → 3900** (절벽 앞 196자 여유)
- `DISPATCH_PROMPT_HARD_CEILING = 4096` 신설
- `_resolve_prompt_max_chars()` env 정책 변경
  - 자유 상향 경로 제거 → **4096 초과는 clamp**
  - 0 이하·파싱 실패 → 기본값 유지(**비활성화 불가, fail-closed**)
  - 하향(더 엄격)은 허용
- 측정은 `len()` 문자수 (바이트 아님) — 종전 유지
- `_prompt_has_sanitize_instruction()` 신설 — §5 참조
- **콜백 byte 가드는 손대지 않음**: `CALLBACK_PROMPT_MAX_BYTES=3900` 그대로 (회귀 테스트로 고정)

### 2-3. `teams/shared/QC-RULES.md` (v4.1 → v4.2)

- **7절 프롬프트 이관 지시** — §게이트(Lv.2/3/4) · §Lv.3+ · §sanitize · §3문서 (생성 영역)
- **8절 trip-wire 5종 증거 정책** (§trip-wire)
  - 5종 ↔ result.json `trip_wire` 필드 매핑표
  - **8-B 자기증명 신뢰 금지**: result.json 수치는 대조용 백업일 뿐.
    ANU 가 **clean worktree(CI parity)에서 게이트 재실행** → 항목별 대조 →
    불일치 시 **재실행 수치 채택 + 완료 보류**, 필드 부재/전부 null = 미측정(통과 아님)
  - 미측정을 0 으로 적지 않는다(null + 사유 기재)

### 2-4. 신규 파일

- `utils/trip_wire_evidence.py` — build / attach(비변형) / verify / compare(관측치 채택) / extract
- `scripts/sync_qc_rules_sections.py` — 코드 canonical → QC-RULES.md 재생성 (`--write`), 드리프트 검사
- `tests/regression/test_prompt_lv3_cliff_2950.py` — 신규 회귀 **137건**

## 3. 검증 결과

### 신규 + 관련 회귀
| 대상 | 결과 |
|---|---|
| `test_prompt_lv3_cliff_2950.py` (신규) | **137 passed** |
| `test_dispatch_prompt_4096_guard_2946.py` | **27 passed** (정책 변경분 동시 수정) |
| `test_team_prompts.py` | **153 passed** (계약 변경분 동시 수정) |
| 합계 3파일 | **317 passed / 0 failed** |

### 회귀 (base ↔ head 대조)
영향 표면(`team_prompts` / `build_prompt` / `QC-RULES` / 가드 / 게이트 / sanitize / 3문서 /
trip_wire)을 참조하는 테스트 **38파일**을 식별하고, 그중 실패 이력이 있는 **22파일**을
**파일 단위 격리 실행**(전체 일괄 실행은 dispatch 모듈 재로딩 때문에 상호 오염됨)으로 대조:

- **base 25건 · head 25건 · 신규 실패 0 · 해소 0 — 실패 집합 완전 동일**
- base 재현 방법: task-2950 변경을 in-place 역적용(fail-closed 앵커 검증) 후 동일 명령 실행
- 잔존 25건은 전부 **pre-existing** (예: `_create_task_docs` 속성 부재,
  `generate_task_id` tmp_path 미반영, `test_dispatch.py` 400초 타임아웃 행 — base/head 동일)

> ⚠️ 기존 테스트 실패 25건 (본 작업 범위 외, base 동일)
> ⚠️ 수집 에러 5건 (`tests/scripts`, satori 2건, worktree 전용 `test_base_source_isolation_2729p9`,
> `test_routing_classification`) — 전부 base/head 동일한 환경 문제

### 계약 유실 방지 (verbatim 강제)
- 게이트 Lv.2/3/4 텍스트, Codex 명령, Sanitize 블록, 3문서 doctrine이 QC-RULES.md 안에
  **글자 단위로 동일**하게 존재함을 테스트가 강제
- `build_qc_rules_transferred_sections()` 출력 전체가 파일에 통째로 존재 + sync 스크립트 **no-op** 확인
- QC-RULES.md sha256: `75cd7353ee3a` (프롬프트 핀과 일치 — 테스트가 매 실행 대조)

## 4. 지시 항목 밖 변경 1건 (보고 대상)

**`_build_three_docs_section` 압축 (494 → 180자)**

지시된 3개 블록만 이관하면 dev8 critical = **3,942자**로 새 가드(3,900)에 **여전히 걸려
Lv.3+ 발사가 불가능**했습니다. 남은 Lv.3+ 증분의 대부분이 3문서 섹션이었습니다.
→ 운용 산문 + 3 Step Why 문항을 §3문서로 verbatim 이관하고, **task별로 달라져 정적 파일로
옮길 수 없는 경로**와 보고서 전 업데이트 의무만 인라인에 남겼습니다.
QC-RULES.md 셀프 QC 항목 11·12가 이미 3문서 의무를 담고 있어 정합적입니다.

## 5. 설계상 필수 수반 수정 1건

**dispatch sanitize 재-append 차단.** 본문을 이관하자 dispatch 의
`SANITIZE_GATE_HEADING in prompt` 검사가 '부재'로 오판해 240자 블록을 **다시 붙이는**
상태가 되었습니다(이관 효과 전부 상쇄 + 절벽 재잠식). `_prompt_has_sanitize_instruction()` 이
heading **또는** §sanitize 참조를 인정하도록 확장했습니다.
`task_type=research/check` 처럼 검증 섹션이 없는 경로는 **종전대로 삽입**됩니다(지시 유실 0).

## 6. trip-wire 5종 (본 작업 자체)

| trip-wire | 값 | 근거 |
|---|---|---|
| Critical7 | 0 | Critical Escalation 7종 해당 없음 |
| PII net-new | 0 | 신규/수정 파일에 PII 리터럴 0 (ANU_KEY 등 비밀은 테스트에서 더미 패치) |
| 회귀 실패 | 0 | base 25 ↔ head 25 실패 집합 완전 동일 |
| forbidden_paths 침범 | 0 | `/home/jay/workspace` 하위만 수정, 타 팀 디렉토리 0 |
| nonce | task-2950 | 발사 task_id 일치 |

★ 위 수치는 **자기증명**입니다. QC-RULES.md §trip-wire 8-B 에 따라 ANU 가 clean worktree 에서
재실행해 대조해 주십시오. 불일치 시 재실행 수치가 채택됩니다.

## 7. 회장 결정 필요

1. **local_only = 이미 라이브** — main 워킹트리가 dirty 상태로 운영되므로 이 변경은 커밋 없이도
   **다음 dispatch 부터 적용**됩니다(task-2946과 동일 구조). 롤백 가부 판단 필요.
2. **실발사 end-to-end 미검증** — 전 검증은 프롬프트 생성/가드/문자수 계측 수준입니다.
   실제 Lv.3+ 봇 1건 발사로 왕복 확인이 남아 있습니다(본 작업 범위 밖).
3. **§3문서 이관 승인** (위 §4) — 수치 목표 달성에 필요했던 지시 항목 밖 변경.
4. **env 상향 clamp 정책** — 종전 `DISPATCH_PROMPT_MAX_CHARS=8192` 같은 임시 완화가
   더 이상 통하지 않습니다. 채널 개선 시 상수 자체를 올려야 합니다.

## 8. L1 스모크테스트

- 서버 재시작: **해당없음** (프롬프트 생성/가드 모듈, 상시 프로세스 없음)
- API 응답 확인: **해당없음**
- 스크린샷: **해당없음**
- 대체 실동작 확인: `scripts/measure_dispatch_prompt_sizes.py` 실행으로 13팀×3레벨
  **실제 프롬프트를 생성**해 문자수 계측(상한 초과 0), `sync_qc_rules_sections.py` 실행으로
  파일 동기 상태(sha256 `75cd7353ee3a`) 확인

## 9. 수정 파일 목록

| 파일 | 상태 |
|---|---|
| `prompts/team_prompts.py` | verified (317 테스트) |
| `dispatch/__init__.py` | verified |
| `teams/shared/QC-RULES.md` | verified (verbatim 대조) |
| `utils/trip_wire_evidence.py` | verified (신규) |
| `scripts/sync_qc_rules_sections.py` | verified (신규) |
| `tests/regression/test_prompt_lv3_cliff_2950.py` | verified (신규 137건) |
| `tests/regression/test_dispatch_prompt_4096_guard_2946.py` | verified (정책 동시 수정) |
| `tests/test_team_prompts.py` | verified (계약 동시 수정) |
| `tests/test_3docs_e2e.py` | verified (헤더 1건) |
| `memory/plans/tasks/task-2950/{plan,context-notes,checklist}.md` | 3문서 completed |
