# notes: insuniverse-docs-30-contracts-limits — 마일스톤 7

계획서: `.claude/plans/insuniverse-docs-30-contracts-limits-m7.plan.md`
하네스: `.claude/plans/insuniverse-docs-30-contracts-limits-m7.gates.sh` · 같은 이름의 `.gates.mjs`

이 파일이 구현 라운드의 리뷰 원장이다. 계획 본문에 쓰면 `mccp-plan-codex` receipt 가 stale 로
떨어진다 — 계획서 §Files to Change 가 그 이유로 이 파일을 선언했다.

## Codex Implementation Review

- 호출: `node C:/Users/madsc/.claude/plugins/cache/mccp/mccp/1.33.1/scripts/lib/codex-invoke.js adversarial-review`
  (fail-closed Bash wrapper, v0.2.2 · `--timeout-ms 900000` · `--json`)
- 라운드 수: 1 (`MCCP_REVIEW_SINGLE_PASS=deadline_pressure` 가 캡을 1로 고정 — `effectiveRoundCap`
  출력 `{"cap":1,"pinned":true,"pinnedBy":"single-pass"}`)
- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent` (`deriveGateVerdict` source=structured)
- 합치 결론: **Codex 가 발화했고 HIGH 4건을 냈다. 하나가 실측으로 참이어서 구현 규칙에 흡수됐고,
  셋은 계획서가 이미 판정해 봉인한 축의 재제기다.** 흡수된 하나(F0)는 계획서 결함이 아니라
  계획서가 조건절로만 남겨 둔 자리의 **구현 시점 저작 결정**이다 — 계획서 §필드 결속 표의
  컨테이너·CI 부류 행이 FAIL 조건을 *"`build-args` 가 그 이름을 넘기는데 유도값이 비면"* 으로
  이미 조건화해 두었고, Codex 가 짚은 것은 그 조건이 **거짓인 원소가 실재한다**는 사실이다.
  그 원소의 기본값을 무엇으로 적을지가 이 라운드가 정한 것이다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F0 컨테이너·CI 부류 유도 규칙이 `SCHEDULER_TYPE` 이 쓰지 않는 배포 경로를 상정한다 | HIGH | ACCEPT_NOW | 6 | **실측으로 참이다.** 동결 head `4d798f55` 의 `.github/workflows/api.yml` 126행이 `build-args` 로 넘기는 것은 `RUN_MODE=api` **하나뿐**이고, `SCHEDULER_TYPE` 은 226행의 task-def env 주입에서만 값을 받는다. 계획서의 FAIL 조건 자체는 조건절이라 깨지지 않는다 — 그러나 *두 게이트를 같은 경로로 유도한다* 고 읽으면 `SCHEDULER_TYPE` 의 기본값을 지어내게 된다. 구현은 두 원소를 **갈라서** 유도한다: `build-args` 가 그 이름을 넘기면 그 값이 기본값이고, 넘기지 않으면 `ARG` 에 기본값이 없으므로 이미지 `ENV` 는 **빈 문자열**이며 그 사실을 그대로 적는다. `우선순위` 는 두 원소 모두 *태스크 정의 env 주입 → 이미지 `ENV`* 로 적는다 — `SCHEDULER_TYPE` 은 그 앞자리가 유일한 실질 출처다. 계획서 편집 없음 |
| F1 생성 인덱스가 여전히 정본 분류를 지배한다 | HIGH | REJECTED | — | **계획서가 판정해 봉인한 축이다.** §Task 2 (b) 가 `env-gates.yaml` 을 *어휘와 집합 이름만* 읽도록 이미 좁혔고, G4 가 그 집합과 두 정본의 차집합이 정확히 `RUN_MODE`·`SCHEDULER_TYPE` 임을 실측했다 — 그 차이가 **우주 밖 부류의 정의 자체**다. 권고대로 `gate_observed` 를 동결 루트 스캔으로 재계산하는 것은 두 번째 추출기를 신설하는 것이고 이 마일스톤 범위 밖이다. 게다가 분류는 인덱스 단독으로 서지 않는다 — 검사 `#10` 이 우주 밖 전건의 앵커가 실제로 `.ts`/`.tsx` **밖**인지 독립으로 물고, `#5` 가 두 정본 재열거와 문서 집합을 3자 대조한다. CLAUDE.md §0 *전제 부정형* |
| F2 `O_EXCL` 이 golden 분모를 마일스톤 기준 SHA 에 결박하지 않는다 | HIGH | REJECTED | — | **같은 축이 계획 리뷰 R4 F1 · R5 에서 두 번 판정됐다.** 배타 생성은 *진행 중 재실행이 분모를 갱신하는* 경로를 막으려는 것이고 그 범위에서 정확히 작동한다. 권고(receipt `base_sha` 에서 golden 을 읽어 대조)는 `docs/_meta/verify/**` 를 분모로 끌어들이는데 §Files to Change 의 **건드리지 않는 것** 이 그 경로를 명시적으로 닫았다. *스냅샷이 일반 파일 연산으로 여전히 쓰기 가능하다* 는 지적은 참이나 그것은 모든 추적 파일에 해당하며 게이트가 아니라 커밋 이력이 드는 축이다. CLAUDE.md §0 *이미 내려진 결정* |
| F3 `conditional-enabled` 에 구조화된 status 근거가 없다 | HIGH | REJECTED_BY_DESIGN | — | **계획서 §Open Questions 첫 항이 이 자리 그대로다**(G14). 권고는 *소유자 승인 구조화 필드 신설* 인데 UI12 가 문서 형식 계약의 비소유를 선언했고 INV6·B3 이 같은 방향이다. `evidence_grades` 는 `13-relation-contract` 가 세운 계약이고 이 PRD 는 소비자다. 지금 계획은 출처를 서술과 `limitations` 로 들고 검사 `#7` 이 **변수명·환경·관측 분류 3쌍**을 정본에서 재유도해 문서 주장과 대조한다 — 구조화 필드는 없지만 결속은 자기 단언이 아니라 외부 대조다. 형식 계약을 여는 창이 정할 일 |

- Deferred to backlog: 0 → `.claude/plans/codex-findings-backlog.md` 미변경
- Open Questions: 없음 (§0 auto-CRITICAL 목록 — 보안 경계 · 원자적 상태 · 스키마 파손 — 에 해당 0건.
  F3 이 *스키마* 어휘를 담으나 그것은 형제 소유 **문서 형식 계약**이고 코드 스키마가 아니며,
  계획서가 이미 Open Question 으로 열어 둔 자리다)
- Codex session 참조: threadId `01a05a4b-07f9-7fa0-8a7f-e8327ee9f436`

### Security Reviewer

해당 없음. 이 마일스톤의 변경은 마크다운 문서 1건과 게이트 하네스 스크립트뿐이고 UI11 이 코드
수정을 범위 밖으로 뺐다 — 인증·암호·비밀값·입력 검증 코드에 닿는 diff 가 0이다. 문서가 열람 토큰
강제 게이트를 **서술**하지만 그 관문 코드를 편집하지 않는다. 마일스톤 6 receipt 도 같은 자리에서
`security_skipped: false` 다.

### Design Review

`impeccable-detect --mode implement` 가 `skill_available=1 · design_signal=0 · silent_skip=1
(reason=no-signal)` 을 냈다. 렌더링 표면 변경이 없으므로 critique 루프와 라우팅은 돌지 않고
receipt 에 `--impeccable-silent-skip --impeccable-silent-skip-reason no-signal` 로 남는다.

## 구현 라운드 관측 — `# 음성:` (c) 행의 기록

`.gates.sh` 가 (c) 로 표시한 행들은 하네스가 서야 관찰된다. 2026-09-01 구현 라운드가 실제로
돌린 관찰을 그 파일의 해당 행에 `(c→실측)` 로 적었고, 아래는 그 요약이다. 전건 rc=1 이며 각
사본은 실행 뒤 바이트 동일로 복원됐다(사본 대조로 확인).

| 검사 | 겨냥한 오답 | 관찰된 실패 |
|---|---|---|
| `#11` | 완료 상태에서 착수 모드를 부른다 | `표 7행 Status='complete' (기대 'in-progress')` · **`#1` 은 0건 실행** |
| `#11`·`#12` | 완료 상태 × 스냅샷 부재 | 스냅샷이 **다시 만들어지지 않았다** — 쓰기가 가드 뒤에 있다 |
| `#2` | 특수 명령이 arity 판정을 우회한다 | 인자 계약 8건 전건 기대 종료코드 (rc 64 여섯 · rc 1 하나 · rc 0 하나) |
| `#7` | 확보 환경을 운영으로 바꿔 적는다 | `확보 환경 'stg' 가 본문 서술에 없다 — 이름만 맞고 환경이 비었다` |
| `#8` | 식 기본값을 없음으로 적는다 | `기본값 문서 '—' ≠ 재유도 'dayjs()…'` |
| `#9` | 두 패턴을 거꾸로 읽는다 | `#12` 프로브 6건이 양방향으로 뒤집힌다 |
| `#10` | 우주 밖을 모호한 서술로 흐린다 | `스캔 우주 밖이라는 긍정 표기가 없다` |
| `#13` | 기획·부록 서술에 게이트 이름을 적는다 | `부록 417행: 서술에 대문자 언더스코어 토큰이 있다` |
| `#14` | 미배포 사실을 지운다 | `앵커 blame 이 미도달인데 limitations 에 그 사실이 없다` |
| `#15` | 서비스 열을 위조한다 | `site 열 '강제 지점' ≠ 앵커 재구성 '—'` |
| `#16` | 없는 SHA · 다른 날짜를 적는다 | `연혁 SHA 가 동결 저장소에 없다` · `연혁 날짜 2026-07-25 ≠ … 2026-07-24` |

## 구현이 계획서 관측을 정정한 자리

**계획서 §GROUND 는 관측 기록이지 규범이 아니다.** 하네스는 계수를 리터럴로 담지 않고 매 실행에
정본에서 다시 유도하므로, 아래 둘은 계획서를 고치지 않고 여기 사실로 남긴다(UI11).

- **G8 의 미도달 집합은 셋이 아니라 넷이다.** 계획서는 `CAR_VIEW_ADMIN_IDS`·`ENABLE_TREAT_CAR`·
  `INHOUSE_CAR_CANARY` 셋을 적었는데, 동결 head 에서 앵커를 다시 찾아 blame 을 걸면
  `DISEASE_PDF_HIDE_NAME_AGENCY_ID` 도 미도달이다(blame `9d3ccff7`). **이 차이를 만든 것이
  정확히 G5 축 1 이다** — 생성 인덱스가 그 게이트의 독출을 `analyze.service.ts` 1313행으로
  적는데 그 행의 blame 은 `bcb456af` 이고 도달이다. 실제 독출인 1268행의 blame 이 미도달이다.
  인덱스 앵커를 베끼면 도달 판정이 뒤집힌다는 것이 이 마일스톤 방법론 축의 실측 증명이며,
  검사 `#14` 는 그 넷을 매 실행에 이름으로 낸다.
- **`#3` 의 lint 호출 형태는 상시 게이트와 같아야 한다.** 초판 구현이 `--root` 없이 불러 rc 2
  (`--root 가 필요하다`)를 받았다 — **아무것도 검사하지 않는 종료코드**다. `verify.sh` 1553행이
  실 문서에 거는 형태(`--root <루트> --strict-refs`)로 맞췄다. 종료코드만 보고 `0|1` 로 받는
  게이트였다면 이 자리가 조용히 지나갔다.

## 저작 중 잡힌 하네스 결함 둘

둘 다 **문서를 쓰기 전에** 재유도 출력을 눈으로 대조하다 나왔다. 하네스만 믿고 문서를 먼저 썼으면
문서와 검사가 같이 틀려 양방향 대조가 통과했을 자리다.

- **기본값 유도가 문자열 안의 콤마에서 잘렸다.** 공급자 풀 기본값이 콤마를 담은 문자열인데 초판
  스캐너가 깊이 0 의 콤마를 종결로 읽어 절반만 냈다. 문자열 리터럴을 건너뛰도록 고치고 변이
  프로브 2건(`#12`)으로 못박았다.
- **미설정 동작 술어가 줄바꿈된 삼항 조건을 놓쳤다.** 환자명 가림 게이트는 조건이 세 줄에 걸쳐
  있고 `? false` 가 그다음 줄이다. 한 줄 끝의 `?` 만 보는 초판 술어가 이 자리를 `기본값 대체` 로
  잘못 접었다 — 실제 결과는 가림이 걸리지 않는 `통과` 다. 창을 넓혀 고치고 변이 2건을 걸었다.

## 로컬 리뷰 흡수 (`/mccp:code-review` 로컬 모드, 2026-09-01)

봉인 뒤 자문 리뷰 1패스. CRITICAL·HIGH 0, MEDIUM 3 · LOW 6 이고 **전건 흡수**했다. 흡수는 매 건
반사실로 검증했다 — 수정 전 사본에서 검사가 붉어지는지 실제로 돌렸다(CLAUDE.md §4).

| 라운드 | A | B | 층위 | 흡수 | 기각 |
|---|---|---|---|---|---|
| local-1 | `code-review` 로컬 | (없음 — 자문 모드) | 7 · 2·8 · 1 · 5 · — · — · — | 9 | 0 |

| id | 지적 | 층위 | 반사실 |
|---|---|---|---|
| M1 | `#12` 의 축 수가 리터럴 `16` 이라 자기 검사 밖이다 | 7 | `rejects(…)` 1행 지운 사본이 **15축 돌며 16축 출력**. 고친 뒤 같은 사본이 `15축` |
| M2 | 유도기 셋이 파일의 첫 독출만 보고 `deriveGate` 가 `anchors[0]` 만 쓴다 | 2·8 | 둘째 자리 유도값에 접미를 붙인 사본이 `#8 FAIL: … 독출 자리마다 default 가 갈린다 — …:95='""' · …:199='""_MUT'` rc=1 |
| M3 | 인증 분당 관문의 예외·폴백에 두 번째 무력화 조건이 빠졌다 | 1 | 동결 blob 35행 `if (this.perMin <= 0 \|\| !this.redis) return true;` · 46행 `if (!id) return true;`. 문서가 값 축만 들었다 |
| L1 | `check-all` 이 `#1` 을 `seal` 로 못박아 착수 조합을 표현 못 한다 | 5 | `--expect` → 모드 결박. `--expect bogus` rc=64 · `--expect in-progress` 가 `#11` 에서 rc=1(쓰기 전 가드 유지) |
| L2 | `boundName` 의 죽은 식 | — | `return t[1];` |
| L3 | `known_gates` 파서 둘이 fail 메시지만 빼고 바이트 동일 | — | 한 함수 + 라벨. 독립성은 파서가 아니라 분모가 든다 |
| L4 | 계획서 §Codex Adversarial Review 가 `지적 16건` 과 `열두 지적` 을 같은 문단에 쓴다 | — | **고치지 않는다** — 리뷰 절 편집이 `plan_hash` 를 움직여 봉인을 stale 로 만든다. 표 합계 16(3·3·3·2·1·1·1·2)이 정본이고 `열두` 는 R5 시점의 낡은 수다. 기록으로만 |
| L5 | `.gates.sh` `#14` 음성이 `13종 중 셋` 이라 현재 출력(`4종/15종`)과 어긋나 보인다 | — | 분모 차이(`gate_observed` 13 ↔ `known_gates` 15)를 그 행에 명기 |
| L6 | `dbPriorityKey` 의 마이그레이션 폴백이 파일 전문 `includes` | 6 | 게이트 이름을 담은 **행이 대체를 선언하는지** 로 좁힘. 근거의 하중은 이름의 실재가 아니라 그 자리의 선언이다 |

**봉인된 축 재제기 0건.** golden 스냅샷의 기준 SHA 결박(R4 F1·R5·Implement F2) · 인덱스 지배
(Implement F1) · 구조화 status 근거(Implement F3)는 이 리뷰가 `out_of_scope` 로 분리했다.

## `#10` 과 `#13` 의 계약 충돌 — 실측으로 드러나 해소

`#10` 초판은 우주 밖 블록이 스캔 우주를 **확장자 리터럴로** 명시하기를 요구했다. 그 블록은
`## 부록` 안에 있고 `#13` 이 그 절의 서술에서 파일 확장자를 금지한다 — **어느 문서도 둘을 함께
만족시킬 수 없다.** `#10` 의 (b) 를 소스 루트 키 이름과 파일 종류 낱말로 고쳤다. 명시의 하중은
확장자 철자가 아니라 우주의 정의이며, 두 어휘 모두 `#13` 을 지난다. 근거는 하네스 `check10`
주석에 그대로 적었다.

## Codex PR Review — 라운드 1

- 호출: `codex-runner.js --base origin/main` (PR-Codex 게이트, `--intent-reference-file` 로 UI1~UI15 동봉)
- 라운드 수: 1 (`MCCP_REVIEW_SINGLE_PASS=deadline_pressure` 가 캡을 1로 고정)
- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent`
- 합치 결론: **HIGH 2 · MEDIUM 2 중 하나가 실측으로 참이다.** 참인 하나(F3)는 계획서가 자기
  산문에서 이미 걷어낸 결함(Plan-Codex R2 F2)을 **산출 문서가 그대로 반복한** 자리이고, 그것을
  무는 검사가 하네스에 없었다. 나머지 셋은 계획서·문서가 이미 판정해 봉인한 축의 재제기다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F1 문서 밖 게이트 이름 누출을 의도적으로 성공 처리한다 | HIGH | REJECTED | — | **계획 리뷰가 같은 축을 이미 흡수·판정했다** (계획서 §Codex Adversarial Review F1 행). 범위 사실은 참이고 그 라운드가 검사 `#6` 의 제목·기대를 범위에 맞게 좁혔으며 범위 밖 등장 집합을 매 실행 출력에 관측으로 싣게 했다 — 이번 실행도 11건을 이름으로 냈다. *넓히라* 는 권고만 기각이며 사유는 그때와 같다: 범위를 넓히면 형제 PRD 배타 소유 문서를 고쳐야 하고 INV3·UI12 가 막는다. 근거 G9 가 그 형제 문서 목록을 이미 들고 있다 |
| F2 다른 축 소유인 정책 의미를 이 문서가 다시 정의한다 | HIGH | REJECTED | — | **전제 부정형이다.** 문서가 부록 서두에서 *"반복해 적는 것은 그 게이트가 무엇을 갈라놓는가"* 로 그 문장 형태를 정의했고, 15건 전건이 *"…가 이 한 자리에 걸린다"* 꼴이다 — 스케줄러가 실제로 무엇을 하는지는 적지 않는다. UI3 이 `미설정 시 동작` 을 요구하므로 그 서술을 링크로 대체하라는 권고는 UI3 를 깨고, UI15 가 넘기라 한 *도메인 의미* 와는 다른 층이다 |
| **F3 정본에서 유도해야 할 게이트 건수를 문면에 하드코딩했다** | MEDIUM | **ACCEPT_NOW** | 2 | **실측으로 참이고 자기모순이었다.** 부록 서두가 부류 크기를 한글 수사로 박아 두었고, 같은 계획서가 §정책 집합 에서 *"이 표는 이름을 열거하지 않는다 … (UI9 · INV4). 대신 각 부류의 유도 규칙을 적는다"* 로 그것을 금지했다. Plan-Codex R2 F2 가 계획서 산문에서는 같은 결함을 걷어냈는데 산출 문서가 반복했고, 무는 검사가 없었다. 서두를 집합 서술로 개작하고 `#13` 에 **정본에서 재유도한 크기를 금지 토큰으로 만드는** 축을 얹었다 — 자기 단언이 아니라 외부 대조다 |
| F4 기존 lint 에 위임하기로 한 배치·연혁 검사를 재구현했다 | MEDIUM | REJECTED | — | **위임은 실재하고 축이 겹치지 않는다.** `#3` 이 상시 게이트와 **같은 호출 형태**로 lint 를 돌린 뒤 위임 규칙 4종의 키트 선언 실재만 확인한다(재구현 아님을 그 주석이 명시). `#13` 이 무는 것은 배치가 아니라 *서술의 코드 심볼 부재* 이고 PRD 위험 표가 지목한 축이다. `#16` 이 무는 것은 열 구조가 아니라 *SHA 와 author date 의 git 대조* 이며, 형제 축도 같은 자리를 같은 형태로 세웠다 |

- Deferred to backlog: 0
- Open Questions: 없음 (auto-CRITICAL 목록 해당 0건)

### F3 흡수의 반사실

옛 문면(`정책 열셋 … 두 부류다`)으로 되돌린 사본에서 `#13` 이 rc=1 로 떨어진다:

```
#13 FAIL: 부록 서두 407행: 부류 크기를 문면에 실었다 — '두' 는 재유도한 값 확보 크기 2 이다 (UI9 · INV4)
```

복원 후 같은 검사가 rc=0 이며 금지 토큰 11종을 이름으로 출력한다. 사본 대조로 원본 바이트
동일 복원을 확인했다.

## 병합이 들여온 앞 창 회귀 — `#1` 이 붉다, 이 창의 변경 때문이 아니다

`origin/main` 병합 뒤 `#1` 이 `verify.sh --check rc=1` 로 떨어진다. 실패 지점은
`docs/_meta/verify/verify.sh` 1905 행 근처의 *문서 PRD 5종* 단언이고, 그 단언의 입력은
`.claude/prds/` 파일명이다. 착수점에서 5종이던 그 집합이 지금 4종이다 — 40축 PRD 가
`archived/` 로 옮겨졌고 정규식이 `[2-6]0` 이라 70축을 세지 않는다.

| 리비전 | 추출된 문서 PRD |
|---|---|
| 착수점 (`bf0e277^`) | 20 · 30 · 40 · 50 · 60 — 다섯 |
| `origin/main` | 20 · 30 · 50 · 60 |
| 병합 후 HEAD | 20 · 30 · 50 · 60 |

`origin/main` 과 HEAD 의 입력이 **같다** — 이 창의 diff 는 `.claude/prds/` 에서 자기 PRD 의
Status 행 하나만 고쳤고 파일 집합을 건드리지 않았다. 귀속은 main 의 `6f1365e` 다.

**이 창이 고치지 않는다.** `docs/_meta/verify/**` 는 계획서 §Files to Change 의 *건드리지 않는
것* 이 명시적으로 닫은 경로이고, 그 단언은 이 축이 아니라 저장소 공용 게이트가 소유한다. 나머지
15검사는 전건 초록이다.

## Codex PR Review — 라운드 2

- 호출: 같은 러너. `--focus` 에 **라운드 1 봉인 목록 3건을 원문으로 박았다** — 재제기 0건이다.
- 라운드 수: 1 (캡 고정 동일)
- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent`
- 합치 결론: **지적 3건 전건 신규이고 전건 실측으로 참이다.** 셋 다 동결 소스 또는 문서 자기
  내부와의 대조로 확인됐다. 라운드 1 이 닫은 축의 **잔여**를 두 건이 짚었다 — 하나는 새 검사가
  덮지 못한 문면 자리, 하나는 그 검사 matcher 자신의 구멍이다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F5 기업담당자를 허용목록 게이트의 적용 대상으로 잘못 표시함 | HIGH | ACCEPT_NOW | 1 | **동결 소스로 확인했다.** `car-view-admin.guard.ts` 27행이 기업 역할에서 곧바로 되돌려 보내고, 환경 허용목록 독출은 그 뒤 30행이다. 적용 범위 표는 그 칸을 적용으로 적었고 **부록의 같은 게이트 항목은 적용받지 않는다고 적어** 문서가 자기와 어긋나 있었다. 이 칸이 통과한 이유는 `#15` 가 서비스 열만 재구성하고 actor 열은 대조 밖이기 때문이며 그 사실은 `#12` 사각지대 목록에 이미 있었다. 형제 `03-contracts` 두 문서가 쓰는 `미적용` 토큰으로 고치고 세 토큰의 범례를 표 아래에 세웠다 |
| F6 게이트 개수가 새 검사 범위 밖에 여전히 하드코딩됨 | MEDIUM | ACCEPT_NOW | 8 | **두 갈래 다 참이다.** (a) 개요 절과 적용 범위 절 뒤의 산문이 값 확보 부류의 크기를 수사로 들고 있었다 — `#13` 의 서두 축이 두 절의 첫 항목 앞만 훑으므로 통과했고, 그 제외 구간은 `#12` 에 적혀 있었다. 해당 문면을 집합 서술로 고쳤다. (b) matcher 가 조사 결합형을 놓쳤다 — 이쪽은 사각지대가 아니라 **선언한 범위 안의 결함**이라 고쳤다(아래 반사실). 전 문서로 범위를 넓히라는 권고는 받지 않는다: 같은 토큰으로 전 문서를 훑으면 정당한 서술 스무 줄 남짓이 함께 걸리고, 그것은 이 저장소가 세 번 기각한 금지 목록 축이다. 제외 구간은 계속 `#12` 가 든다 |
| F7 숫자가 아닌 레이트리밋 값의 실행 경로를 잘못 기록함 | MEDIUM | ACCEPT_NOW | 1 | **동결 소스로 확인했다.** `certify-rate-limit.guard.ts` 31행이 `Number(...)` 로 값을 만들고 35행이 `0 이하 또는 연결 없음` 으로 되돌려 보낸다. 수가 아닌 값은 그 비교가 거짓이라 관문 조건이 참이 되지 않고, 연결이 있으면 카운터 증가와 만료 설정까지 실행된 뒤 임계 비교만 성립하지 않는다. 최종 결과는 미설정과 같으나 실행 경로가 다르며, 예외·폴백 표가 그 둘을 한 행으로 묶어 *조건이 참이 된다* 고 적은 것은 사실이 아니었다. 행을 둘로 가르고 부록 서술에도 그 차이를 적었다 — UI11 이 요구하는 사실 기록이다 |

- Deferred to backlog: 0
- Open Questions: 없음
- 봉인 축 재제기: **0건** (focus 결박이 그대로 작동했다)

### F6(b) 흡수의 반사실 — 앞 관찰이 덮지 못한 통로로 잰다

라운드 1 의 음성 관찰은 `정책 열셋 … 두 부류다` 를 심어 rc=1 을 봤지만, 실제로 걸린 토큰은
공백 뒤의 `두` 였고 `열셋은` 은 통과했다. 그래서 이번에는 **조사 결합형만** 심었다:

```
#13 FAIL: 부록 서두 413행: 부류 크기를 문면에 실었다 — '열셋' 는 재유도한 운영값 미확보 크기 13 이다 (UI9 · INV4)
```

수정 전 같은 입력은 rc=0 이었다. 복원 후 rc=0 이며 원본 바이트 동일 복원을 확인했다.

`#1` 을 뺀 열다섯 검사는 이 라운드 뒤에도 전건 초록이다.

## Codex PR Review — 라운드 3

- 호출: 같은 러너. `--focus` 에 기각 3건 · 흡수 4건 · 알려진 사각지대 4건을 원문으로 박았다.
- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent`
- 합치 결론: **지적 2건, 전건 신규이고 전건 참이다.** 재제기 0건이 세 라운드째 유지된다. 두 건 다
  **앞 라운드가 닫았다고 적은 자리의 잔여**를 짚었다 — 하나는 앞 라운드가 신설한 검사 자신의
  경계 결함, 하나는 앞 라운드가 가른 표 행이 여전히 모집단을 다 덮지 못한 자리다. 지적의 부류가
  *새 축 발견* 에서 *직전 수정의 정확성* 으로 옮겨왔다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F8 양의 소수·유한하지 않은 값의 상반된 동작이 누락됐다 | MEDIUM | ACCEPT_NOW | 6 | **동결 소스와 언어 사실로 확인했다.** 이 자리는 값을 정수로 만들거나 범위를 좁히지 않고 51행 비교에 그대로 쓴다. 0 과 1 사이 값이면 첫 카운터 1 이 이미 한도를 넘어 전면 차단이고, 유한하지 않은 크기면 어떤 카운터도 한도에 닿지 못해 한 번도 막지 않는다. 라운드 2 가 미설정·0 이하·수가 아닌 값 셋으로 갈랐는데 그 셋이 양수 쪽 모집단을 덮지 못했다 — 표본 ≠ 범위다. 두 행을 신설하고 부록 서술에도 적었다. **코드 판정은 하지 않는다**(UI11) |
| F9 조사 문자 클래스가 양쪽으로 틀렸다 | MEDIUM | ACCEPT_NOW | 8 | **실측으로 둘 다 참이다.** 문자 클래스는 토큰 뒤 한 글자만 받으므로 `열셋까지` · `열셋부터` · `열셋으로` 가 전부 false 였고, 동시에 `에서` 가 낱자로 흩어져 `두서가` 를 크기 2 로 오인했다. 권고대로 낱말 alternation 으로 고치면 `열셋이다` · `열셋이며` 같은 서술격 어미에서 다시 마른다 — **한국어 접미 목록은 수렴하지 않는 축**이므로 목록을 늘리는 대신 **꼬리 제약을 버렸다.** 앞 경계만 보고 뒤는 보지 않는다 |

- Deferred to backlog: 0
- Open Questions: 없음
- 봉인 축 재제기: 0건

### F9 흡수의 선택 — 목록을 늘리지 않고 축을 줄였다

세 판을 실측으로 비교했다.

| 판 | `열셋은` | `열셋까지` | `열셋이다` | `두서가` (오탐) | 서두 오탐 |
|---|---|---|---|---|---|
| 뒤가 한글이면 다른 낱말 (R1) | 놓침 | 놓침 | 놓침 | 없음 | 0 |
| 조사 문자 클래스 (R2) | 잡음 | 놓침 | 놓침 | **오탐** | 0 |
| 앞 경계만 (R3) | 잡음 | 잡음 | 잡음 | 오탐 | **0** |

셋째 판의 오탐은 원리상 남지만 **현재 서두 열몇 줄에서 0건**이고, 발생 시 해소는 검사 완화가
아니라 문면 개작이다. 실패 메시지가 어느 토큰인지 그대로 들므로 저자가 고칠 자리가 바로 보인다.
경계 양성 4 · 음성 2 를 `#12` 프로브 묶음으로 세워 회귀가 조용히 나지 않게 했다 — `#12` 출력의
프로브 총수는 배열 길이에서 나오므로 묶음을 지우면 그 수가 함께 준다.

### 라운드 1 관찰의 정정

라운드 1 이 `#13` 음성으로 적은 관찰은 실제로는 공백 뒤 `두` 로 걸린 것이고 같은 줄의 `열셋은`
은 통과했다. 라운드 2 의 관찰도 조사 한 글자 형태만 덮었다. 두 사실을 `.gates.sh` 의 해당 음성
행에 그대로 적었다 — **덮지 못한 축을 덮었다고 적어 두면 다음 라운드가 같은 자리를 다시 판다.**

`#1` 을 뺀 열다섯 검사는 이 라운드 뒤에도 전건 초록이다.

## Codex PR Review — 라운드 4

- 호출: 같은 러너. `--focus` 에 기각 3건 · 흡수 6건 · 사각지대 5건을 원문으로 박았다.
- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent`
- 합치 결론: **지적 3건, 전건 신규이고 전건 참이다.** 재제기 0건이 네 라운드째다. 세 건 다 직전
  두 커밋이 만든 자리를 겨눴다 — 둘은 **내가 이번에 새로 쓴 문장이 무조건문이라 틀린** 자리이고,
  하나는 **내가 이번에 세운 프로브 묶음이 한쪽 분기를 재지 못하는** 자리다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F10 저장소 조회 실패 시 상태 조회와 강제 경로가 발산하는 사실이 누락됐다 | MEDIUM | ACCEPT_NOW | 1 | **동결 소스로 확인했고 지적보다 넓었다.** 인용된 경로에 한 마디가 빠져 있어(`provider` 디렉터리) 그 경로로는 파일이 없으나, 실제 자리를 찾아 대조하니 주장은 참이다. 관리 화면이 부르는 자리는 조회 실패에서 환경 값으로 폴백하고 진료 편성이 부르는 자리는 무조건 꺼짐을 낸다. **게다가 미설정 기본값의 극성 자체가 반대다** — 앞엣것은 명시적 거짓이 아니면 켜짐, 뒤엣것은 명시적 참일 때만 켜짐이다. 그래서 행도 값도 없는 상태에서 같은 게이트가 읽는 자리마다 반대 답을 낸다. 예외·폴백에 두 행을 신설하고 부록 서술에도 적었다. **앵커에는 넣지 않는다** — 그 두 행은 게이트 이름 토큰이 아니라 설정 키 이름을 담아 `#4` 의 토큰 대조를 통과하지 못한다. 판정은 하지 않는다(UI11) |
| F11 새 전면 차단 행이 세는 자리의 장애를 숨긴다 | MEDIUM | ACCEPT_NOW | 6 | **내가 라운드 3 에 쓴 문장이 무조건문이라 틀렸다.** 그 자리의 예외 처리는 넘침 차단만 위로 다시 던지고 나머지 예외를 삼켜 요청을 통과시킨다 — 값이 무엇이든 그 요청은 막히지 않는다. *모든 요청이 막힌다* 는 세는 자리가 정상일 때만 참이다. 값 조건 행에 그 한정을 달고 장애 축 행을 따로 세워 **뒤엣것이 앞엣것을 덮는다** 고 명시했다. 부록 서술도 같은 형태로 고쳤다 |
| F12 경계 프로브가 숫자 분기의 회귀를 봉인하지 못한다 | MEDIUM | ACCEPT_NOW | 7 | **반사실로 확인했다.** 숫자 분기가 늘 거짓을 내도록 바꾼 사본에서 초판 여섯 프로브가 **전부 통과**한다 — 음성만 있고 양성이 없었다. 양성 둘과 뒤 경계 음성 하나를 더했고, 같은 반사실에서 이제 `#12` 가 rc=1 로 떨어진다. 검사 자신에 대한 주장에 검사가 없던 자리다 |

- Deferred to backlog: 0
- Open Questions: 없음
- 봉인 축 재제기: 0건 (네 라운드 연속)

### 반사실 셋

1. **숫자 분기 무력화** — `numeralHit` 의 숫자 가지를 `return false` 로 바꾼 사본에서
   `#12 FAIL: 2건 · 프로브6 숫자 양성: 'false' (기대 'true')`. 수정 전 같은 사본은 rc=0 이었다.
2. **서두에 숫자형 크기 주입** — `정책 13종은` 을 심으면
   `#13 FAIL: 부록 서두 …행: … '13' 는 재유도한 운영값 미확보 크기 13 이다`.
3. **서두에 고유어 서술격 주입** — `정책은 열셋이며` 를 심으면 같은 검사가 `'열셋'` 로 rc=1.
   접미 목록을 버린 판정이 서술격 어미도 무는 것을 여기서 확인했다.

전건 복원 후 rc=0 이며 원본 바이트 동일 복원을 확인했다. `#1` 을 뺀 열다섯 검사 초록.

### 종료 판정 — 다음 라운드가 마지막 확인이다

라운드별 지적 실질: R1 4건 중 참 1 · R2 3건 전건 참 · R3 2건 전건 참 · R4 3건 전건 참. 건수는
줄지 않았으나 **부류가 옮겨갔다** — R2 까지는 새 축의 발견이었고, R3 부터는 *직전 라운드가 만든
문장과 검사의 정확성* 이다. R4 의 셋 중 둘은 내가 R3 에 쓴 문장이고 하나는 R3 에 세운 프로브다.
이 부류는 흡수가 새 자리를 만드는 한 계속 나온다. 다음 라운드에서 **직전 커밋이 만든 자리에 대한
지적이 0 이면** 그것을 수렴으로 읽는다.

## Codex PR Review — 라운드 5

- 호출: 같은 러너. `--focus` 에 기각 3건 · 흡수 9건 · 사각지대 5건.
- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent`
- 합치 결론: **지적 2건, 둘 다 참이고 둘 다 라운드 4 가 새로 쓴 문장을 겨눴다.** 하나는 **내가
  쓴 서술이 사실이 아니었다** — 이 라운드에서 가장 무거운 것이고 아래에 정정으로 따로 적는다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F13 실제 설정 조립을 건너뛰어 미설정 발산을 잘못 기록했다 | HIGH | ACCEPT_NOW | 1 | **내 서술이 거짓이었다.** 라운드 4 가 *행도 값도 없으면 두 자리가 반대 답을 낸다* 고 적었는데, 설정 팩토리가 그 환경 값을 `=== 'true'` 비교로 조립해 **항상 불리언**을 만든다. 미설정이면 그 값이 거짓이므로 `!== false` 도 `=== true` 도 둘 다 거짓이고 두 자리의 답이 같다. 팩토리가 실제로 로드되는 것도 대조했다 — 앱 모듈이 그것을 `load` 에 싣는다. 그 행을 지우고 부록 문단에서 극성 주장을 걷어냈다. **남는 발산은 조회 실패 × 환경 값이 명시적으로 켜는 값일 때 하나뿐**이며 그 조건을 행과 서술에 못박았다 |
| F14 부분 실패가 영구 차단 상태를 남길 수 있다 | MEDIUM | ACCEPT_NOW | 6 | **참이다.** 세는 일이 증가와 기간 설정 둘로 나뉘어 있고 기간은 카운터가 처음일 때만 걸린다. 증가가 성공한 뒤 기간 설정이 실패하면 그 요청은 예외 처리로 통과하지만 카운터는 기간 없이 남고, 그 뒤로는 처음이 아니므로 기간이 다시 걸리지 않는다 — 정상 복구 뒤에도 그 식별자는 유한한 양수 한도를 계속 넘는다. 라운드 4 의 *완전히 열린 것처럼 동작한다* 는 그 요청 하나에만 참이었다. 행 하나와 문단 하나를 더해 **통과와 굳음이 같은 실패에서 나온다** 고 적었다 |

- Deferred to backlog: 0 · Open Questions: 없음 · 봉인 축 재제기: 0건 (다섯 라운드 연속)

### 정정 — 라운드 4 가 적은 사실 하나가 거짓이었다

라운드 4 표에 *미설정 기본값의 극성 자체가 반대다* 라고 적었다. **그것은 틀렸다.** 두 소비 지점의
비교 형태(`명시적 거짓이 아니면` 과 `명시적 참일 때만`)가 다른 것은 맞으나, 그 앞의 설정 조립이
환경 값을 불리언으로 확정해 넘기므로 미설정에서 둘의 답이 갈리지 않는다. 갈리려면 그 자리가
정의되지 않은 값을 받아야 하고 그것은 조립을 건너뛴 대역에서만 성립한다.

**이 라운드가 잡아낸 것은 내 흡수의 검증 부족이다.** 라운드 4 는 두 소비 지점의 소스만 읽고 그
사이에 있는 조립을 읽지 않았다 — 소비 지점 두 곳을 대조했다는 사실이 *그 값이 어디서 오는지* 를
대조했다는 뜻이 아니었다. 흡수의 반사실은 검사에만 걸었고 서술에는 걸지 않았다.

### 종료 판정 — 아직이다

라운드별: R1 4건(참 1) · R2 3건(참 3) · R3 2건(참 2) · R4 3건(참 3) · R5 2건(참 2). 내가 R4 끝에
적은 종료 조건은 *직전 커밋이 만든 자리에 대한 지적이 0* 이었고 R5 는 둘 다 그 자리였다 —
**수렴 아님.** 게다가 R5 는 앞 라운드의 거짓 서술을 잡았으므로 라운드를 더 도는 값이 실증됐다.

`#1` 을 뺀 열다섯 검사는 이 라운드 뒤에도 전건 초록이다.

## Codex PR Review — 라운드 6

- 구조화 verdict: `needs-attention` → 게이트 verdict `divergent`
- 합치 결론: **지적 1건, 참이다.** 세 라운드 연속으로 같은 자리 — 자동차 수집 게이트의 두 소비
  지점 비교 — 에서 내 서술이 틀렸다. 이번에는 한정을 좁힌 것이 오히려 거짓을 만들었다.

### YAGNI Triage

| Finding | Severity | Verdict | 층위 | Why |
|---|---|---|---|---|
| F15 관리 화면과 실제 수집은 조회 실패 없이도 발산한다 | HIGH | ACCEPT_NOW | 1 | **참이다.** 관리 화면이 부르는 자리는 이 게이트만 읽고, 진료 편성이 부르는 자리는 이 게이트가 켜진 뒤 카나리 게이트까지 읽어 **곱**을 낸다. 그래서 이 게이트가 켜지고 카나리가 꺼져 있으면 장애 없이도 갈린다. 앞 게이트를 켜짐으로 읽은 뒤 카나리를 읽다 실패해도 같은 처리가 꺼짐을 내므로, 라운드 5 가 단 *환경 값이 명시적으로 켜는 값일 때만* 이라는 한정도 거짓이다. 비교를 두 축으로 갈랐다 — 물음이 다르다는 축과 장애가 그 차이를 한 방향으로 더 벌린다는 축 |

- Deferred to backlog: 0 · Open Questions: 없음 · 봉인 축 재제기: 0건 (여섯 라운드 연속)

### 같은 자리에서 세 번 틀렸다 — 원인은 한 가지다

| 라운드 | 내가 쓴 것 | 왜 틀렸나 |
|---|---|---|
| R4 | 미설정이면 두 소비 지점의 기본값 극성이 반대다 | 소비 지점 둘만 읽고 **그 사이의 설정 조립**을 읽지 않았다 |
| R5 | 발산은 조회 실패 × 환경 값 명시적 켜기 하나뿐이다 | 두 함수가 **같은 물음에 답한다고 전제**하고 조건만 좁혔다 |
| R6 | (정정) 물음이 다르고, 장애가 그 차이를 더 벌린다 | — |

세 번 다 **두 값을 비교하기 전에 그 값이 무엇의 답인지를 먼저 세우지 않은** 것이 원인이다. 값
비교는 같은 물음 위에서만 뜻이 있는데, 앞 두 라운드는 함수 이름이 비슷하다는 이유로 그 전제를
건너뛰었다. 이번 서술은 조건이 아니라 **물음의 정의**부터 적는다.

이 자리는 계획서가 검사로 물지 않는 구간이다 — `#8`·`#9` 는 게이트의 선언 자리에서 기본값과
미설정 부류를 유도하고, 소비 지점 사이의 의미 대조는 `#12` 사각지대 목록의 *서술의 사실 여부*
에 든다. 그래서 이 축의 정확성은 검사가 아니라 리뷰가 들었고, 세 라운드가 실제로 그 일을 했다.

### 종료 판정

라운드별 실질: R1 1 · R2 3 · R3 2 · R4 3 · R5 2 · R6 1. 건수가 처음으로 내려왔고 남은 축이
하나로 좁혀졌다. 다음 라운드에서 **직전 커밋이 만든 자리에 대한 지적이 0** 이면 수렴으로 읽는다.

`#1` 을 뺀 열다섯 검사는 이 라운드 뒤에도 전건 초록이다.

## Codex PR Review — 라운드 7 (수렴)

- 구조화 verdict: `approve` · **지적 0건** · `codex_actionable_findings=false`
- 합치 결론(원문 요약): 직전 커밋의 두 행과 세 문단이 동결 기준점의 관리 조회 · 편성 조회 ·
  장애 폴백 제어 흐름과 정확히 일치하며 차단할 실질 finding 이 없다.

라운드 6 끝에 적은 종료 조건은 *직전 커밋이 만든 자리에 대한 지적이 0* 이었고 이 라운드가 그
조건을 만족한다. 봉인 축 재제기는 일곱 라운드 연속 0건이다.

### 라운드 원장

| 라운드 | 지적 | 실질(참) | 기각 | 층위 | 성격 |
|---|---|---|---|---|---|
| 1 | 4 | 1 | 3 | 2 | 봉인 축 재제기 셋 + 산출 문서가 계획서 금지를 반복한 자리 하나 |
| 2 | 3 | 3 | 0 | 1 · 8 · 1 | actor 칸 오기재 · 검사 범위 밖 문면 + matcher 구멍 · 실행 경로 오기재 |
| 3 | 2 | 2 | 0 | 6 · 8 | 값 모집단 누락 · matcher 가 양쪽으로 틀림 |
| 4 | 3 | 3 | 0 | 1 · 6 · 7 | 소비 지점 발산 · 내 무조건문 · 내 프로브의 분기 공백 |
| 5 | 2 | 2 | 0 | 1 · 6 | 내 서술이 거짓(설정 조립 미독) · 부분 실패의 sticky 상태 |
| 6 | 1 | 1 | 0 | 1 | 내 한정문이 거짓(두 함수가 다른 물음에 답함) |
| 7 | 0 | 0 | 0 | — | 수렴 |

**곡선의 성격.** 건수는 4→3→2→3→2→1→0 으로 단조롭지 않았지만 **부류는 단조롭게 좁혀졌다** —
봉인 재제기(R1) → 새 축 발견(R2·R3) → 직전 수정의 정확성(R4~R6) → 없음(R7). R4 이후 지적은
전부 *내가 직전 라운드에 쓴 문장이나 세운 프로브* 를 겨눴고, 그 부류가 마르자 라운드가 끝났다.

**검사가 못 든 것을 리뷰가 들었다.** 실질 12건 중 검사 축의 결함은 셋(matcher 두 번, 프로브
공백 한 번)이고 나머지 아홉은 **서술의 사실성** 이다. 그 축은 `#12` 사각지대 목록이 처음부터
*서술의 사실 여부* 로 이름 붙여 둔 구간이며, 이 루프가 실제로 그 구간을 갈았다.
