# Milestone Closure — 3-02-failure-semantics

## Milestone

- ID         : 3-02-failure-semantics
- Name       : `02-failure-semantics.md`
- PRD        : `.claude/prds/insuniverse-docs-40-runtime-vendor-legal.prd.md` (Delivery Milestones 3행)
- Plan       : `.claude/plans/insuniverse-docs-40-runtime-vendor-legal-m3.plan.md`
- Status     : done
- Closed at  : 2026-08-26T04:38:03.928Z
- Closed by  : /mccp:milestone-close (run_id=5d50e235-b079-4f25-afe6-cc636788eb72)
- HEAD       : `be466bfeea67978a325682ebdd5fe4047fcf28b8`

## Acceptance Condition

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

> `.claude/plans/insuniverse-docs-40-runtime-vendor-legal-m3.gates.mjs all` 이 14/14 통과하고,
> `docs/06-vendors/02-failure-semantics.md` 만 읽고 treat 5 / non-treat 3 두 축의 성공·자료없음·실패
> 의미를 벤더별로 답할 수 있으며, "벤더 장애" 와 "자료 없음" 을 구별하는 신호와 그 도달 여부를
> 문서만으로 판정할 수 있다. 또는 20 turn 후 중단.

## Goal Loop Result

3항 전건 충족. 1 turn 에 수렴.

### 1) 게이트 14/14 — 통과

`node .claude/plans/insuniverse-docs-40-runtime-vendor-legal-m3.gates.mjs all` 최종 출력:

```
#0 ok M1 all 15/15 · M2 all 13/13 · 05-schedules 4문서 워킹트리 변경 0 · vendor-behaviors.yaml 벤더 8종 × 결과 3 + 라우팅 1 == 후보 인덱스 axis:vendor 25행 (제한 리더 수용 키 69개)
OK — 5개 파일, 위반 0 (--strict-refs)
#1 ok doc-kit lint --strict-refs 통과 (5개 파일)
#2a ok 후보 인덱스 axis:vendor 25행 = 벤더×결과 24 + 라우팅 1
#2b ok 문서 정책 id 집합 == 인덱스 id 집합 (편차 0)
#3a ok status 맵 25쌍 == 승계 16 + pending 유도 9 (편차 0)
#3b ok placement 맵 25쌍 == config.statuses 유도 배치 (편차 0)
#3c ok 본문 정책 0건 == 자격 0건
#4a ok 대조표 2개 · 헤더 7열 문자열 일치
#4b ok treat 벤더 5종 · non-treat 벤더 3종 == vendor-behaviors.yaml axis 집합 (편차 0) · 행수 15 / 9
#5 ok 24행 · 분류 기제 일치 24 · 인덱스 근거 일치 24 · 코드 수 일치 15 (non-treat 9행 대시) · 사각 재계산 일치 24 (없음 16 분류 부재 1 개념 부재 3 화면 미분기 4)
#6a ok 소비 사슬 7행 == 로케이터 7신호 (편차 0) · 생산 앵커 해석 7건 · 행 내용 대조 7건 · 소비 표면 수치 없음 7건
#6a 사각: 수치 금지는 **아라비아 숫자만** 본다 — 한글 수사('여섯')는 이 검사가 보지 못한다. 그 열에 수를 쓰지 않는다는 규약 자체는 사람이 지킨다
#6b ok 소비 계수 재계수 21칸 일치 (server 69 · site 28 · admin 42 합) · 제외 글롭 server:apps/api/src,libs 제외 :(exclude)**/*.spec.ts | site:front/src 제외 없음 | admin:src 제외 없음
#6b 사각: 계수는 토큰 단어 일치이므로 **도달의 상한**이다 — 다의어(site 의 category 는 게시판·강좌 파일에서도 잡힌다)와 주석 안 등장(admin 의 NO_DATA 1건은 주석행이다)이 함께 세어진다. 그래서 '도달' 은 계수가 아니라 벤더 축 전용 토큰 [NO_DATA isRetryableTreatError VENDOR_ERROR] 과의 파일 교집합이 정하고, **그 교집합은 양쪽 다 코드행만 본다** (site 축 파일 7개 · admin 축 파일 1개 · 주석으로만 걸려 축에서 뺀 파일 server 1개 · site 0개 · admin 0개)
#6b 사각: 코드/주석 판별은 행 안에서 토큰이 '//'·'/*'·'*' 뒤에 있는가로만 갈린다. 사각 둘이 **방향이 반대**다 — 문자열 리터럴 안의 '//' 를 주석 시작으로 오인하면 도달을 과소평가하고(fail-safe), 접두 마커 없는 블록 주석 속행은 코드로 세어 **과대평가한다**(fail-open). 뒤쪽은 이 판정을 뒤집을 수 있는 잔여 사각이며 게이트가 잡지 못한다
#6c ok 도달 재계산 7건 일치 (사용자 경로 1 · 진단 표면만 2 · 미도달 4)
#7a ok unknown_reason 보유 25건 (정책 25건 전건)
#7b ok pending 출신 9건이 게이트 부재 사유를 담는다 · assigned 16건이 인덱스 사유를 승계
#8 ok 앵커 29건 해석 · 행 내용 대조 29건 · 기대 집합 출처 인덱스 26건 / 하네스 리터럴 3건
#8 사각: 리터럴 3건(vendor:aligo:no_data vendor:smartro:no_data vendor:toss:no_data)은 **좌표 선택이 검사되지 않는다** — 인덱스 evidence 가 빈 행이라 유도 출처가 없고 하네스가 문서와 같은 값을 들고 있다. 해석 가능성만 검사된다
#9 ok 연혁 9행 · 인덱스 해석 9건 · 앵커 경로 접촉 9건 (앵커 경로 9종)
#10a ok 적용 범위 헤더 == config actors 5 + services 3
#10b ok 강제 지점 · 적용 범위 · 예외·폴백 id 집합 == 정책 집합 (편차 0) · 빈 칸 0 (200칸)
#10c ok 적용 범위 200칸 값 재유도 일치 (적용 55 · — 145) · site 도달 true · admin 도달 true
#11 ok --help 성공 · nosuchcheck rc=1 · 서브커맨드 17종 등록 · normAnchor 자기검증 8건 통과
#12a ok 격자 유도 24칸 == 표 A∪B 행 집합 (미커버 0 · 잉여 0)
#12b 사각: 라우팅 행 vendor:__dispatch__:fallback 1건은 격자 밖이라 부록·예외폴백이 진다 · 인덱스 evidence 빈 행 3건 · 코드 수 없는 축 9행
#13 ok 코드값 리터럴 1건 · 전건 허용 목록 [CF-12103] 안 · 목록 밖 0건 · 검사 패턴 4종 [CF-nnnnn Ennnn Innnn-nnn DOZN-100nnnn]
#13 사각: 패턴은 **표본이고 범위가 아니다** — 위 4종에 걸리지 않는 형태의 벤더 코드값은 이 검사가 보지 못한다
all ok 14/14 통과
```

`#0` 이 M1 회귀 15/15 · M2 회귀 13/13 과 `docs/05-schedules/**` 4문서 워킹트리 불변을 선행 검사하므로,
이 출력은 M3 창이 선행 두 마일스톤의 산출물을 건드리지 않았다는 진술을 함께 진다.

### 2) 두 축 × 3결과 벤더별 답변 — 문서만으로 가능

`docs/06-vendors/02-failure-semantics.md` 하나만 읽고 자기 검사한 결과. 두 대조표(`§응답 의미 대조 —
treat 축` 15행 · `§응답 의미 대조 — non-treat 축` 9행)가 분류 기제·인덱스 근거·코드 수·사각을 주고,
`§부록` 25블록이 각 결과의 의미와 사용자·관리자에게 보이는 것을 코드 심볼 없이 진다.

**자료없음 축이 세 값으로 갈린다** — 이것이 이 마일스톤이 겨냥한 오처리의 핵심이다.

| 축 | 벤더 | 자료없음 | 코드 수 |
|---|---|---|---|
| treat | codef | `분류 부재` — 자료없음 분류 0건, 미수록 코드가 미상 폴백으로 떨어지고 그 대상이 운영자 | 0 |
| treat | coocon · hyphen · inhouse · octover | `화면 미분기` — 분류는 있으나 사용자 화면에서 실패와 갈리지 않는다 | 1 · 6 · 1 · 1 |
| non-treat | aligo · smartro · toss | `개념 부재` — 벤더 API 에 조회 결과 없음이라는 개념 자체가 없다 | — (분류 기제 없음) |

`분류 부재` 와 `개념 부재` 를 같은 어휘로 접으면 안 된다는 것도 문서가 명시한다 — 앞은 넣을 코드가
있는데 안 넣은 것이고 뒤는 넣을 코드가 존재하지 않는다.

성공 축도 갈린다 — smartro 만 벤더 결과 코드를 보고 성공 여부를 재판정하고, aligo·toss 는 정상 응답을
곧 성공으로 접는다. 실패 축은 toss 결제요청 경로만 예외 대신 실패 상태 DTO 를 돌려주고 노출 허용
목록에 든 오류에 한해 벤더 문구를 그대로 전달한다.

### 3) 구별 신호와 그 도달 — 문서만으로 판정 가능

`§구별 신호 소비 사슬` 표 7행과 `도달` 열이 그 답을 진다. 판정은 문서의 주장이 아니라 게이트 `#6b`·`#6c`
가 동결 세 트리에서 재계수·재계산한 값이다.

- **봐야 할 신호는 `category` 다. `retryable` 이 아니다** — 자료없음의 재시도성이 거짓이고 입력 오류 ·
  인증번호 오류 · 미상도 전부 거짓이라 재시도 신호로는 자료없음과 실패가 갈리지 않는다.
- 도달: `retryable` 만 `사용자 경로`. `category` · `userMessage` 는 `진단 표면만`.
  `alimtalkMessage` · `audience` · `NO_DATA` · `PROVIDER_FAULT_CODES` 는 `미도달`.
- **결론 — 사용자 화면에서 벤더 장애와 자료없음은 구별되지 않는다.** 관리자 모니터에서만 갈리고,
  택소노미의 자료없음 값 자체는 관리자 화면에도 코드로 도달하지 않는다(`NO_DATA` 행 `미도달`).

`§연혁` 9행이 그 정체를 시간축으로도 진다 — 폴백 순서가 두 번 바뀌고 공급자가 다섯이 되는 동안
사용자 화면에 도달하는 신호는 하나 그대로였다.

### 이 창이 남기는 사각 (문서와 게이트 출력 양쪽에 자백돼 있음)

1. 소비 계수는 토큰 단어 일치라 **도달의 상한**이다 — 다의어(site `category` 23 중 상당수가 게시판·강좌)와
   주석 안 등장(admin `NO_DATA` 1건)이 함께 세어진다. `도달` 판정은 계수가 아니라 벤더 축 전용 토큰과의
   파일 교집합이 정하고 그 교집합은 양쪽 다 코드 행만 본다.
2. 코드/주석 판별의 사각 둘이 **방향이 반대**다 — 문자열 리터럴 속 `//` 오인은 fail-safe, 접두 마커 없는
   블록 주석 속행은 **fail-open** 이다. 뒤쪽은 게이트가 잡지 못하는 잔여 사각이다.
3. `#8` 리터럴 3건(non-treat 자료없음)은 좌표 **선택**이 검사되지 않는다 — 해석 가능성만 본다.
4. `#13` 코드값 패턴 4종은 표본이지 범위가 아니다.

## 종료 전이 반사실 — PRD 행을 `complete` 로 뒤집어도 하네스가 안 깨지는가

전이 **전에** 실측했다. M1·M2·M3 세 `gates.mjs` 에서 `PRD` 상수의 전 사용처를 열거한 결과:

- `m1.gates.mjs` — `PRD` 는 `### MVP` 절의 펜스 블록만 읽는다 (483·485·491·496·515행 · 검사 `#12`).
- `m2.gates.mjs` — 같다 (292·294·300·303·321·333행 · 검사 `#2`).
- `m3.gates.mjs` — `PRD` 상수 자체가 없다.

**어느 하네스도 `Delivery Milestones` 표 행이나 PRD 꼬리의 `*Status:` 토큰을 읽지 않는다.** 따라서
`insuniverse-docs-20-foundation-access-m1.gates.mjs check7` 부류의 두 자리 동시 전이 요구가 이 PRD 에는
없고, 표 행 하나만 뒤집으면 된다. `*Status: DRAFT` 꼬리 행은 그대로 둔다 — 마일스톤 4·5·6 이 `pending`
이라 PRD 자체는 아직 종료가 아니다.

## 계획서 본문 무편집 — receipt `plan_hash` 재검증

`hash-plan` 재계산값과 두 receipt 의 `plan_hash` 가 같다:

```
live plan_hash                       : sha256:02727ebee43e543a153e1fdd72669cc9f0764c6b6f97c44f5f2741bb534eeddc
mccp-plan-codex/...-m3.json          : sha256:02727ebee43e543a153e1fdd72669cc9f0764c6b6f97c44f5f2741bb534eeddc
mccp-implement-codex/...-m3.json     : sha256:02727ebee43e543a153e1fdd72669cc9f0764c6b6f97c44f5f2741bb534eeddc
```

계획서 §Acceptance 의 `(미검증)` 항목 중 "착수 후 계획서 본문이 편집되지 않았다" 가 이것으로 닫힌다.
이 closure 는 계획서 본문에 provenance 를 찍지 않고 PRD `## Milestone Closure Provenance` 표에 한 행을
더한다 — 계획서에 절을 덧붙이면 위 두 receipt 가 동시에 `stale` 로 떨어지고 `stale` 에는 우회 env 가 없다.

## 남는 `(미검증)` — 이 closure 가 닫지 않는 것

계획서 §Acceptance 의 나머지 `(미검증)` 항목은 이 종료로 닫히지 않으며 그 사실을 여기 남긴다.

- 주석 4벤더 표기와 코드 5종 중 어느 쪽이 옳은가 — 저장소 소유자 소관. 문서는 둘을 앵커와 함께 싣는다.
- 연혁 행의 커밋이 정말 응답 의미를 바꿨는가 — 게이트는 앵커 경로 접촉까지만 본다.
- `bash docs/_meta/verify/verify.sh --check` — 이 worktree 에 서브모듈 워킹트리가 없어 실행 불가.
- PRD P-2 의 배치 예측 정정 수용 여부 — 이월이며 PRD 소유자 판단.
- Codex·L2 패널 미실행으로 리뷰받지 않은 축 넷 (부록 전건 배치 판정 · 라우팅 행 소유 배분 · 소비 계수를
  구별 가능성의 오라클로 삼는 설계 · `#13` 패턴의 표본성). `MCCP_CODEX_DISABLED=1` 이 전역 설정에 살아
  있는 동안 하류 게이트도 같은 경로로 skip 된다 — backlog 이월 대상이다.

## Provenance

- Lock run_id        : `5d50e235-b079-4f25-afe6-cc636788eb72`
- Lock owner session : `unknown` (`CLAUDE_SESSION_ID` 미설정 — 이 세션은 최소 사양 모드다)
- PRD source         : `.claude/prds/insuniverse-docs-40-runtime-vendor-legal.prd.md`
- Plan source        : `.claude/plans/insuniverse-docs-40-runtime-vendor-legal-m3.plan.md`
- Detection signal   : `{"row":3,"name":"`02-failure-semantics.md`","plan":".claude/plans/insuniverse-docs-40-runtime-vendor-legal-m3.plan.md","status":"in-progress"}`
- mccp version       : 1.32.1
- Grammar response   : `goal-done:M3 벤더 응답 의미 두 축 분리 완료`
