# Milestone Closure — 70-viewer-9

## Milestone

- ID         : 70-viewer-9
- Name       : 생성기 진입 계약 봉인
- PRD        : `.claude/prds/insuniverse-docs-70-viewer.prd.md` (Delivery Milestones 9행)
- Plan       : `.claude/plans/insuniverse-docs-70-viewer-m9.plan.md`
- Status     : done
- Closed at  : 2026-09-04T07:23:52.681Z
- Closed by  : /mccp:milestone-close (run_id=cefa9d5a-6f71-4536-8c38-0d71a417de72)
- HEAD       : `bed5f745cde591b6e937013e0b7f6788bfcf09bc`

## Acceptance Condition

사용자가 `/goal` 에 넘긴 조건 원문:

> M9 (생성기 진입 계약 봉인) 종료 조건 확인. (1) check-all 이 12/13 이고 유일한 붉음이 #1 receipt plan_hash stale, (2) M9 Acceptance 가 지는 게이트 #3~#13 전건 초록, (3) lint-plan.mjs rc 0, (4) working tree clean. 전부 맞으면 종료. 또는 3 turn 후 중단.

## Goal Loop Result

조건 4건 전건 충족. 실측 출력은 아래 §측정 회차.

**(1) `check-all` 12/13 · 유일한 붉음이 `#1`** — stderr 전문이 2행이고 그 둘이 전부다:

```
#1 FAIL: receipt plan_hash 불일치 — receipt sha256:823ac5f3ca498… ≠ 현재 본문 sha256:b0455c48907cb…
check-all FAIL: 12/13 (실패: #1) — 전건 실행 후 집계
```

`#1` 은 이 마일스톤의 §Acceptance 13행이 지는 게이트가 아니다 — 그 절은 `#3`~`#13` 만 인용한다.
귀속과 처방은 아래 §창 안 붉음.

**(2) §Acceptance 가 지는 게이트 `#3`~`#13` 전건 초록** — 각 검사가 낸 판정 줄:

```
#3 ok  CANON 유도 1곳(publish.mjs) · 소비 3곳 [build-docs.mjs · anchor-freshness.mjs · gate.mjs] 전건이 유도값 참조 · 정본 이름 문자열 리터럴 소비처 0건(주석 제외 · 후보 3종 [anchor-freshness.json docs/viewer/build docs/viewer/build/anchor-freshness.json]) · isCanonTarget·stripLongPrefix 파일시스템 호출 0건(소스 재열거) · 판정 표본 24종 전건 일치(종류 2종 · 어휘 밖 종류는 이름 있는 실패) · assertNotCanon 은 안 죽는 fail 뒤에도 반환하지 않는다(fail 1회 후 던짐) · 비정본에서는 fail 0회
#4 ok  정본 표적 3형태 전건 rc=1 [--out 미지정(기본값이 정본) · --out 절대 · --out 저장소 상대] · 거절 문면에 게이트 진입 · live 최상위 바이트 불변(65파일 대조) · 발행 좌표 생성 0건(기존 2종 그대로) · 비정본 --out 은 보호 발행 rc=0 (승격 5건 == 소유 5종) · --staging-internal 경로 rc=0
#5 ok  정본 표적 2형태 전건 rc=1 [--out 미지정(기본값이 정본) · --out 명시 정본] · 거절 문면에 게이트 진입 · 정본 JSON 바이트 불변(c0c72c901f3a) · 비정본 --out rc=0 이고 schema anchor-freshness@1 · --selftest rc=0
#6 ok  gate build rc=0 · 프로브 10건 선행 통과 · 호출 로그 anchor → build-docs · 소유 6종 승격 6건 · 앵커 조인 1522건(항목 566) · digest fence 3회 · 거절 문면 0건
#7 ok  같은 정본을 가리키는 철자 20종 전건 rc=1 (절대 · 저장소 상대 · 후행 슬래시 · . 구간 · .. 왕복 · 대소문자 · 확장 길이 접두 · 장치 접두 · 8.3 단축명 · 중복 --out 마지막 승리) · env 단독 변형 2종 전건 rc=1 이고 live 바이트 불변 · --staging-internal 토큰만 주고 표적을 정본으로 준 호출 rc=1 · 반대 순서(마지막이 비정본)는 rc=0 — 전부 거절하는 구현이 아니다 · 정본 밖 8.3 모양 rc=0 · 정본 밖 확장 길이 접두 2종 판정 통과 — 거절이 정본 부모 밖으로 안 샌다
#8 ok  build-docs.mjs 사용 예 6줄 · 진입 1줄 · anchor-freshness.mjs 사용 예 5줄 · 진입 1줄 전건 추출 · 실행 결과 봉인 거절 0건 · 두 블록에 gate.mjs build 진입 2줄
#9 ok  앞 창 하네스 6종 재열거(m2 m3 m4 m5 m6 m8) · 정본 표적 생성기 호출 0건 · merge-base 2926a6f1 대비 변경 파일 4건 == 결박 파일 4건 · 변경 행 전건이 결박 11자리 안 · 그 밖 변경 행 0
#10 ok  §Delivery Milestones 9행 실재 · Status 셀 in-progress · *Status: 토큰의 마일스톤 9 어휘 in-progress · 두 값 일치 · 표 5열 헤더 불변 · §부록 B ia-doc@1 위임 행 sha256 불변(5cf0a3cff605) · §Success Metrics 첫 표 바이트 불변 · 개정 이력 1행 추가
#11 ok  인수 표기 대상 1행(70m6-child-cli-bypasses-single-entry) 표기(ABSORBED-M9) 실재 · id= 토큰 보존 · 행당 id 1개(전 행 151건 재열거 · 중복 0) · 이 창의 신규 행 5건 전건이 인수처 명시(70m9-gate-entry-requires-repos-root 70m9-canon-seal-blind-to-path-aliases 70m9-prev-window-regression-cost-compounds 70m9-generators-bound-to-publish-at-load verify-prd-count-stale-after-40-archive) · fixtask 코호트 무변동(계수 43 · 집합 양방향 차집합 0)
#12 ok  gate build 재생성 rc=0 · m2 를 재생성 전에도 1회(게이트 진입 분기 확인 — 지운 3종이 전건 되살아났다 · 그 실행의 붉음 0건 전건 이 창의 경로만 냄) · 재생성 후 m2 완주 17s · m3 완주 81s · m4 붉음 1 254s · m5 붉음 1 40s · m6 완주 861s · m8 완주 3069s · 앞 창 6종 전건 완주(측정 실패 0 · 상한 3600s/하네스) · 출력에 거절 토큰 0건 · 붉음 전건이 기준선 토큰 차감 후 귀속됨 · 범위 축 0건 · 형제 축 2건 · 의미 축 0
#13 ok  사각지대 11축 — 생성기 파일 분할 · 읽기 측 원자성 · 타 호스트 락 회수 · 모호 상태 · 게이트 진입이 독자에게 지우는 `--repos-root` 비용 · findings 신설 · ownership 등재 · 산출물 커밋 판정 · 한국어 검색 정밀도 · actor 축 커버리지 · CI 도입 · 제3자 문서의 문면 인용 · 경로 별칭 · §NOT Building 항목과 이름 대조 9/9 (양방향 차집합 0) · 게이트 고유 축 2건(계획서 §NOT Building 에 대응 없음) · 계수 리터럴 0건
```

`#12` 의 형제 축 2건은 같은 실행이 이름으로 낸다 — 이 창의 경로를 하나도 안 낸 붉음이다:

```
형제 축 m4 #14 경로: (없음) — §6 의 services-only 문서군 계수가 재열거 8 와 일치하는 값이 없다 — 실린 계수 [9 5 6 5 14 4 0 20 2 3 3 22 6 20 9 4 9 5 4 129 129]
형제 축 m5 #1 경로: (없음) — 기준선에 뷰어 루트가 이미 있다 — 5건
```

**(3) `lint-plan.mjs`** — rc 0, 출력 없음.

**(4) working tree** — `git status --porcelain` 0행. 락 진입 전과 락 안에서 각 1회.

## 측정 회차 (스탬프 전)

| 회차 | 시점 | 대상 | 결과 |
|---|---|---|---|
| 1 | 락 진입 전 (HEAD `bed5f74`) | `git status --porcelain` · `git branch --show-current` | clean · `70-viewer` |
| 2 | 락 진입 전 | `insuniverse-docs-70-viewer-m9.gates.mjs check-all` | **rc 1 · 12/13** — 붉음 `#1` 하나. 아래 §창 안 붉음 |
| 3 | 락 진입 전 | `lint-plan.mjs <m9 plan>` | rc 0 |
| 4 | 락 진입 전 | `docs/_meta/verify/verify.sh --check` | **rc 1** — 창 밖 · 선재. 아래 §창 밖 붉음 |
| 5 | 락 안 | `git status --porcelain` | 0행 |

회차 2~4 가 락 진입 **전**인 것은 `goal-phase-guard` 가 goal 구간의 Bash 를 default-deny 로 막기
때문이다. 이 창에서도 실측했다 — 락 안에서 로그 파일을 읽으려 한 호출이
`BLOCK — Bash no allowlist match (default-deny during goal-phase)` 로 떨어졌고, `git status` 만
허용 목록을 통과했다. 회차 5 는 회차 1 과 같은 HEAD · 같은 clean 트리다.

첫 실행은 턴 경계에서 죽었다(`status: killed`, `#8` 까지 기록하고 중단). 재실행은 새 로그 이름으로
Monitor persistent 아래에서 완주시켰다 — 같은 로그에 writer 가 둘 붙는 것을 피한다.

## 창 안 붉음 — `#1` receipt plan_hash stale

```
#1 FAIL: receipt plan_hash 불일치 — receipt sha256:823ac5f3ca498… ≠ 현재 본문 sha256:b0455c48907cb…
```

**이 창 귀속이다.** `.claude/notes/insuniverse-docs-70-viewer-m9.md` 270 행이 이미 **대가**로
기록해 두었다 — 관측 9b(`#9 FAIL: m4.gates.mjs 가 기준선과 바이트가 다르다`)를 사용자 판정으로
흡수하면서 §Files to Change 에 m6 하네스를 UPDATE 로 더했고, 그 편집이 `mccp-plan-codex` receipt
봉인(`2926a6f1`) 뒤였다. 계획서와 receipt 는 같은 커밋 `b920879` 에 함께 들어갔으므로 이 붉음은
커밋 시점부터 참이었고, 종결이 새로 만든 것이 아니다.

이 창에서 재봉인하지 않은 이유 셋:

1. `cli.js write --gate mccp-plan-codex` 는 intent gate 가 막는다. 경로는 `/mccp:plan` 재실행뿐이다.
2. receipt 는 추적 파일이라(`git ls-files` 적중) 같은 슬러그 재발급을 `assertNoTrackedOverwrite`
   가 막는다. 새 슬러그로 봉인해도 `#1` 은 `m9.gates.mjs` 56 행의 리터럴 경로
   `.claude/receipts/mccp-plan-codex/insuniverse-docs-70-viewer-m9.json` 를 읽으므로 **그것만으로는
   초록이 되지 않는다** — 하네스도 함께 고쳐야 하고, 그러면 `mccp-implement-codex` 가 연쇄로
   stale 이 된다.
3. M9 §Acceptance 13행 중 `#1` 을 인용하는 행이 0건이다. 이 게이트는 기준선 위생 검사이고
   마일스톤의 종료 조건이 아니다.

**인수처는 `/mccp:pr` 창이다.** 그 게이트가 이 receipt 에 fail-closed 이므로 거기서 재봉인을
피할 수 없다. 그때까지 stale 로 두는 것이 이 저장소의 관례다 — 봉인된 판정을 사후에 옮기지 않는다.

## 창 밖 붉음 — 이 마일스톤 귀속 아님

`docs/_meta/verify/verify.sh --check` 가 rc 1 이고 결정적 stderr 는 M8 종결과 같은 한 줄이다:

```
문서 PRD 를 5종 추출하지 못했다 — .claude/prds/ 파일명 규약이 바뀌었다
```

같은 파일이 `.claude/prds/` 에서 `insuniverse-docs-([2-6]0-[a-z-]+)\.prd\.md` 로 뽑은 행수를
리터럴 `5` 와 비교한다. 이 창의 기준선 `2926a6f` 에서도, 종결 시점 `bed5f74` 에서도 매칭 수는
**4 로 같다** — 이 창이 한 건도 안 움직였다. 원인은 M8 종결이 이미 이름으로 남긴 형제 창
`6f1365e`(40축 PRD 를 `archived/` 로 이동)이고, 정규식 `[2-6]0` 이 70축을 애초에 안 센다.

`.claude/plans/codex-findings-backlog.md` 에는 이 창이 이미 행을 넣었다 —
`verify-prd-count-stale-after-40-archive` 이고 `#11` 이 그 행의 인수처 명시를 검사한다.

**스탬프 후 회차는 이 문서에 적지 않는다.** 적는 순간 이 문서의 sha256 이 움직여 PRD 스탬프가
자기를 가리키지 못한다. 표 9행을 `complete` 로 뒤집은 상태의 `check10 --expect complete` 재실행
결과는 이 문서 밖 — 사용자에게 닫는 보고에 있다.
