# Notes: 60 · 연혁 + 폐기 정본 — 마일스톤 3 (`03-divergence.md`)

> 계획서: `.claude/plans/insuniverse-docs-60-history-deprecated-m3.plan.md`
> 이 파일은 `/mccp:prp-implement` 게이트 산출물이다. 계획서 본문은 바이트 그대로 두어
> `mccp-plan-codex` receipt 의 `plan_hash`
> (`sha256:6ca308f16c08651368066b2f257845e7fe4dcf7051357fd6cfa67a22516de93d`) 앵커를 유지한다.

## Codex Implementation Review

- 호출: `node .../scripts/lib/codex-invoke.js adversarial-review` — `classification: disabled`
  로 spawn 전 short-circuit. 2.5.0 정책 봉인이
  `.git/worktrees/60-history-deprecated/mccp/tmp/codex-policy.json` 에 `codex_disabled=true` 다.
- 라운드 수: 0
- 합치 결론: **없음.** Codex 가 이 창의 구현 결정에 의견을 낸 적이 없다. `MCCP_CODEX_DISABLED=1`
  은 `~/.claude/settings.json` `env` 의 영구 운영자 정책이며 게이트 우회가 아니라 입력 부재다.
- YAGNI Triage: 대상 0건 — 판정할 finding 이 없다.
- Deferred to backlog: 0
- Open Questions: 없음 (auto-CRITICAL 대상 0건). 단 계획서 §Codex Adversarial Review 가 남긴
  *"이 계획서는 적대 리뷰로 검증되지 않았다"* 는 **이 게이트에서도 해소되지 않는다** —
  plan 축과 implement 축이 같은 env 정책으로 함께 접혔다. `codex_verdict=skipped` 이므로
  교차 게이트 dedupe 는 fail-closed 로 닫히고 `/mccp:pr` 의 PR-Codex 가 그대로 돈다(그 축도
  같은 env 로 접힌다).
- Codex session 참조: 없음

> Codex skipped per MCCP_CODEX_DISABLED=1

### 2.5.1 — 교차 게이트 dedupe 미적용 사유

`## Codex Adversarial Review` 절은 계획서에 있으나 그 절의 `합치 결론` 이 **`없음`** 이다.
수렴한 decision-set 이 존재하지 않으므로 dedupe 의 전제(*"plan 축에서 이미 수렴했다"*)가
성립하지 않는다. dedupe 를 적으면 *리뷰 0라운드* 를 *리뷰 완료* 로 위장하게 된다. 적용하지 않는다.

### 2.5.2 — 이 창의 implement-time 결정 (Codex 가 봤어야 할 목록)

리뷰가 돌지 않았으므로 아래는 **적대 검토를 받지 않은 결정** 목록으로 남긴다.

1. 하네스를 `m3.gates.mjs` 단일 파일 13서브커맨드로 둔다 — 형제 창(`m1`·`m2`·`m2b`)의 형식이며
   신규 의존 0(INV1), Node 표준 모듈만 쓴다.
2. 발산 원장 257행을 **계획서에 사본으로 두지 않는다.** 문서는 손으로 저작하고 하네스가 매 실행
   `releases.yaml`·`commits.<repo>.jsonl` 과 양방향 대조한다. 2r 이 SHA 셀을 자리표시자로 남긴
   비용이 근거다.
3. `m1.gates.mjs check6` (1) 개정을 **단언 이동**으로 한다 — 귀속(기준선 트리 공집합) + 현재
   (실 파일 ⊆ 트리). 삭제가 아니라는 것을 검사 `#11` 이 3방향 반사실로 잡는다.
4. sha 는 **40자리 전체**를 쓴다. 단축형을 집합 대조 단위로 쓰면 절단 길이가 어떤 검사도 안 보는
   계약이 된다(INV4).
5. git 재유도(`rev-list` · `tag` · `for-each-ref`)를 하네스 안에서 `execFileSync` 배열 인자로
   돌린다 — 셸 문자열 조립을 쓰지 않는다. 저장소 판독 실패는 die 이고 공집합으로 받지 않는다.
6. 기준선 blob 을 `git log --diff-filter=A -- <하네스>` 의 Task 0 커밋에서 읽는다 — 같은 창
   자기승인 차단. 그 앵커가 변경 창 안이라는 잔여는 `id=60m3-anchor` 로 이월한다.
7. 미수록 5건 절을 **`{sha, reason}` 2열**로 고정한다 — 4건이 `planning-only` 이고 `planning/`
   은 등급 L 이다(UI7·INV5). 열이 늘면 sha 가 맞아도 검사 `#3` 이 떨어뜨린다.
8. 참조 카운트에서 *교집합 0* 과 *축 부재* 를 한 칸에 접지 않는다 — 검사 `#5` 가 축별로 앵커
   보유 행수와 교집합을 **둘 다** 찍고 앵커 0 인 축은 따로 센다.

### Security Reviewer

> security-reviewer 미호출 — 이 창의 산출물은 문서(마크다운) · PRD · findings · backlog ·
> `golden.txt` · 로컬 게이트 하네스이며 Phase 2.5.5 가 지정한 보안 민감 영역(auth · crypto ·
> secrets · 입력 검증 · SQL/cmd injection · SSRF · path traversal · 권한 상승) 중 어느 것도
> 건드리지 않는다. 하네스가 부르는 git 은 전부 `execFileSync` 배열 인자이고 입력은 저장소 안
> 인덱스 파일이다. 자동 fallback 이 아니라 **트리거 미충족**이므로 `security_skipped` 를 찍지 않는다.

### Design Review

> impeccable 트리거 미충족 — `impeccable-detect --mode implement` 가
> `skill_available=true` · `design_signal=false` · `silent_skip=true` · `reason=no-signal` 을 냈다.
> 이 창의 변경 집합은 마크다운과 `.mjs` 하네스뿐이라 렌더링 표면이 0건이다. receipt 에
> `impeccable_silent_skip=true` 로 정직하게 기록한다. critique 루프 · 2.5.5b 라우팅 ·
> 2.5.5c grounding capture · 3.6 finish 라우팅 · 3.7 grounding verify 는 전부 no-op 이다.

---

## 로컬 code-review 반영 (2026-08-27)

`/mccp:code-review` Local Review Mode 를 이 브랜치의 미푸시 3커밋(`079e01f`·`97b77c1`·`92e5dc6`)에
돌려 나온 지적 5건을 전건 수용했다. 리뷰는 13검사를 재실행해 실측 대조했고 전건 `ok` 였다 —
지적은 산출값이 아니라 **게이트 강도와 문면 정합**이다.

### 수용 · 코드 수정 4건

| 등급 | 지적 | 수정 |
|---|---|---|
| HIGH | `check6` (1) 의 귀속이 **스냅샷**이라 실 호출에서 반증 불가였다. 기준선은 M1 Task 0 커밋(`34baeabd`)이고 M1 자신의 산출은 정의상 그 뒤에 오므로, M1 이 발행했더라도 그 트리는 비어 통과한다 | 귀속을 **구간**으로 옮겼다 — `[M1 기준선, 다음 마일스톤 기준선)` 에서 `--diff-filter=A` 추가가 0건인지 본다. 창 끝은 `nextMilestoneBaseline()` 이 형제 하네스 추가 커밋에서 유도한다(리터럴 0 · INV4). 실측 유도값 `34baeabd..b6cbe8ae` · 추가 0건 |
| — | 위 수정으로 `check6` 선택 인자가 `<ref>` 에서 `<start> [end]` 로 바뀌었다 | `#11` (b) 반사실을 **실 이력에서 유도**하도록 고쳤다 — 발행이 처음 들어온 추가 커밋 `P` 의 `P^..P` 창. 임시 인덱스 `write-tree` 프로브를 걷어내 커밋 상태 의존을 없앤 성질은 그대로 두고 수단만 단순해졌다 |
| LOW | `#11` (c) 가 실 트리에 만드는 프로브에 sweep 이 없다. 하드 킬이면 발행 디렉터리에 미추적 파일이 남고 다음 `#11` (a) 가 부분집합 사유로 죽어 오진을 만든다 | `sweepRepoProbes()` 를 디스패치 앞머리에 놓았다. 이름 규칙 + `STALE_MS` 로 동시 실행을 안 건드린다. `write-tree` 프로브가 사라져 `os.tmpdir()` 등록부 전체(`TEMPS`·`mktemp`·`runRoot`·`sweepTemps`)는 죽은 코드가 되어 걷어냈다 |
| LOW | `bucketSections()` 의 `if (hi < 0) die(...)` 가 도달 불가였다 — `countOfHeading()` 이 같은 행을 먼저 찾고 없으면 die 한다 | 계수를 한 번만 유도해 재사용하고 죽은 갈래를 제거했다 |

### 수용 · 기록만 — 계획서 본문 미수정 2건

계획서 §Validation 의 `# 기대:` 가 실제로 만든 하네스 출력과 어긋난다. 13검사 중 9건이 다르고
2건이 실질적이다.

- **`#7`** — 계획서 `Risk 문면 1` · 실측 `Risk 문면 2`. 두 문면 검사(`구조적`·`unknown`) 중 하나가
  나중에 빠져 출력이 `1` 이 되면 **계획서 기대와 일치한다.** 층위 3 항체가 거짓 통과를 승인하는
  방향으로 서 있다.
- **`#11`** — 계획서 `# 기대:`·`# 음성:` 이 `기준선=HEAD` 방식을 계약으로 싣고 있는데, 그 방식은
  미커밋 상태에서 rc 0 으로 조용히 통과해 구현 단계에서 폐기됐다(§Issues 4). 인용된 실패 문자열
  `#11 FAIL: 기준선 HEAD 사본이 통과했다` 는 하네스에 존재한 적이 없다.

**계획서 본문을 고치지 않는다.** 고치면 `plan_hash`
(`sha256:6ca308f16c08651368066b2f257845e7fe4dcf7051357fd6cfa67a22516de93d`)가 움직여
`mccp-plan-codex`·`mccp-implement-codex` receipt 2종이 함께 stale 이 되고, 재앵커는 `/mccp:plan`
재실행 없이는 불가하다. 문면 정정은 이 절이 정본이고 구조적 잔여는 이월
`id=60m3-plan-expected-drift` 로 올린다.

### 실측 출력 정본 (2026-08-27 재실행 · 13검사 rc 0)

```
#1 ok  기준값 7/7 축자 일치 (양방향) · 로컬 prod ref server=이동 site=이동 admin=부재 · era prod A0/B102 stg수록 A0/B150 (경계 유도 Amax=2025-12-31T09:34:00+09:00 Bmin=2026-01-02T09:38:46+09:00) · template 없음
#2 ok  prod-only 102 양방향 등가 · 필드 축자 102/102 · server 51 site 27 admin 24 (절제목=행수=파일)
#3 ok  stg-only 155 = 수록 150 + 미수록 5 · 양방향 등가 · 조인 축자 150/150 · server 64 site 33 admin 53 · 미수록 2열 (empty 1 planning-only 4)
#4 ok  재유도 server 51/64 site 27/35 admin 24/56 = prod-only 102 stg-only 155 · releases.yaml 등가 3/3 · 문서 등가 3/3 · locked SHA 로만 해석 (로컬 prod ref 미사용)
#5 ok  커밋앵커 보유 축 1 (policy-candidates.git.jsonl 2870행 ∩ prod-only 102 = 자기행 102 · 외부 0) · 축 부재 5 (comments.server.jsonl comments.site.jsonl comments.admin.jsonl policy-candidates.code.jsonl policy-candidates.runtime.jsonl) · commits 인덱스 6190 ∩ 102 = 0
#6 ok  tag 0/0/0 · replace 0/0/0 · 문면 3/3
#7 ok  Evidence 계수 51↔64/27↔35/24↔56 유도 일치 · Risk 문면 2 · M3 Outcome 문면 3 · M3 in-progress plan실재 · 2 pending 2r complete 2b in-progress
#8 ok  신설 표제 {F-10 F-11 F-12} == 계획서 열거 · 6항목 정본 순서 3/3 · 기준선 9 → 현재 12
#9 ok  신설 5 (…) · 미해소 1 덧붙임 (60m2b-refcount-measurement-point) · 발행 차단 2 열림 (60m1-sha-unresolvable 60m1-adjudication-unproven) · docs/99-deprecated 발행 0 · 차단 집합 유도 m1 2원소
#10 ok  변동 키 {fixtask.findings_headings} == 기대 · 유도 근거 findings 표제 9→12 · index 3키 불변 (index.entry_count=56 index.doc_count=55 index.tree_sha256=84e35f99…)
#12 ok  --help 13개 · 계획서 마커 13개 · 집합 동일 · 알 수 없는 이름 rc1
#13 ok  완주 12/12 · 번호 집합 1..12 (자기 #13 제외)
```

`#11` 은 이 반영으로 출력이 바뀐다 — 개정본 실측은 §Validation Results 표에 싣는다.

### `verify.sh --check`

구현 보고서가 `완주 rc 미확인` 으로 남긴 자리를 리뷰에서 돌려 **rc 0** 을 얻었다. 단
`check PASS` **문면은 미관측**이다 — 세 번 다 리다이렉트 포착이 0바이트였다(600초 foreground
초과 시 백그라운드 전환에서 fd 를 잃는다). rc 0 이 PASS 를 함의한다는 것은 소스 연역이고
(`verify.sh` 3084~3114행 `do_check` 에 `printf 'check PASS'` 를 건너뛰는 rc 0 경로가 없다) 관측이
아니다. 이 저장소 규약 *"출력을 보지 않고 종료코드만 보는 명령은 게이트가 아니다"* 기준으로는
게이트 미달이며 그 사실을 숨기지 않는다.

---

## `/mccp:milestone-close` 반영 (2026-08-28)

마일스톤 3 을 `complete` 로 전이했다. 그 과정에서 앞 절이 미확인으로 남긴 자리 하나가 닫혔고
게이트 하나가 개정됐다. 정본 판정 기록은 `.claude/milestone-closures/60-history-deprecated-3.md`.

### 1. `verify.sh --check` 완주 — 관측으로 닫힘

앞 절 §`verify.sh --check` 는 rc 0 은 얻었으나 `check PASS` **문면 미관측**을 게이트 미달로
적어 두었다. 원인은 결함이 아니라 포착 방식이었다 — 600초 foreground 초과 시 백그라운드
전환에서 fd 를 잃어 리다이렉트가 0바이트였다.

stdout(정본 종단행)과 stderr(진행 로그)를 **각각 다른 파일로** 받고 persistent 워처로 완주시켜
포착했다. 실행 출력 그대로:

```
VERIFY_RC=0 stdout_bytes=12090 stderr_bytes=3050
VERIFY_STDOUT_TAIL: … findings/12-index-runtime.md 형식 전환 유예 …|check PASS|
VERIFY_PASS_LINE observed
```

앞 절의 소스 연역(`do_check` 에 `printf 'check PASS'` 를 건너뛰는 rc 0 경로가 없다)이 옳았음이
확인된 것이지, 연역이 관측을 대신한 것이 아니다. **이 저장소 규약 기준으로 이제 게이트다.**

### 2. `#7` 개정 — 전이 위임과 자기 결박의 모순

계획서 §NOT Building 은 전이를 `/mccp:milestone-close` 에 명시적으로 위임한다:

> **PRD 의 마일스톤 3 Status 를 이 계획서가 `complete` 로 올리지 않는다.** 전이는
> `/mccp:milestone-close` 소관이다.

그런데 같은 계획서의 게이트 `#7` (c) 는 M3 행이 `in-progress` 일 것을 요구했다. **위임을
이행하는 순간 자기 게이트가 붉어지는 구조**다 — 층위 2(주장 ≠ 검사). 앞의 어떤 라운드도
이 자리를 못 봤다: 게이트를 전이 **전** 상태에서만 돌렸기 때문이고, 그 상태에서는 `#7` 이
초록이라 모순이 드러나지 않는다.

M1 선례가 반대 방향이다 — `m1.gates.mjs` 1241 행이 자기 행에 `complete` 를 요구한다.
`#7` 만 어긋나 있었다. 그 형태로 맞추되 **주장을 약하게 하지 않으려고 산출물 실재를 함께
물렸다** — `complete` 인데 발행이 없는 상태는 M2 `check9` 와 같은 사유로 거부다.

| | 개정 전 | 개정 후 |
|---|---|---|
| Status 이빨 | `!== "in-progress"` → die | `!== "complete"` → die |
| 산출물 이빨 | 없음 | `!exists(DOC)` → die |
| 출력 | `M3 in-progress plan실재` | `M3 complete plan실재 산출물실재` |

두 이빨 반사실. 원본은 `trap` 으로 복원하고 양성 재실행까지 확인했다:

```
CF1 rc=1 : #7 FAIL: 마일스톤 3 Status 가 complete 가 아니다 — in-progress
CF2 rc=1 : #7 FAIL: 마일스톤 3 Status=complete 인데 그 산출물이 실재하지 않는다 — docs/90-history/03-divergence.md
RESTORE rc=0 : #7 ok  … M3 complete plan실재 산출물실재 · 2 pending 2r complete 2b in-progress
```

**receipt 체인 무영향.** `planAwareMarkdownHash` 는 plan `.md` 단일 파일만 해시하고
(`scripts/receipt/hash.js` 174~175 행) `gates.mjs` 는 사정거리 밖이다. plan body 는 안 건드렸다.

**M3 행을 무는 다른 소비자 0건.** `m1.gates.mjs`·`m2b.gates.mjs` 는 `3` 행을 참조하지 않고,
`verify.sh` 2021 행의 마일스톤 표 판독 대상은 `prd00.norm`(`00-protocol`)이다.

### 3. 전이 후 13검사 재실행 — 전건 rc 0

```
#7 ok  Evidence 계수 51↔64/27↔35/24↔56 유도 일치 · Risk 문면 2 · M3 Outcome 문면 3 · M3 complete plan실재 산출물실재 · 2 pending 2r complete 2b in-progress
#13 ok  완주 12/12 · 번호 집합 1..12 (자기 #13 제외)
```

나머지 11검사 출력은 앞 절 표와 축자로 같다 — 이 전이가 발산 축 값을 하나도 안 건드렸다는
뜻이다.

### 4. 닫지 않은 것

**적대 리뷰는 여전히 0라운드다.** `MCCP_CODEX_DISABLED=1` 이 사용자 전역 설정 4 행에 있고
워크트리 `codex-policy.json` 이 `codex_disabled=true` 로 봉인돼 있다. 대체 경로 L2 패널·
santa-loop 은 Agent 툴이 필요한데 이 세션은 금지다. **세 문 다 사용자 소관이라 이 창이 못
연다.** 전이는 그 사실 위에서 내려진 판정이고 closure doc 이 미완 목록을 그대로 싣는다.

계획서 §Validation 의 `# 기대:` 가 `#7` 실 출력과 한 칸 더 벌어진다. plan body 는 `plan_hash`
앵커라 안 고치고, 그 드리프트는 이미 이월 `id=60m3-plan-expected-drift` 가 진다.
