# 구현 기록: ops-30 · 층 3 · M1 국소성 검증

**Plan**: `.claude/plans/ops-30-reconcile-m1.plan.md`
**Branch**: `ops-30-reconcile`

이 파일은 `/mccp:prp-implement` Phase 2.5 게이트 산출물이다. 계획서 본문에 쓰지 않는다 —
계획서를 고치면 `mccp-plan-codex/ops-30-reconcile-m1` receipt 의 `plan_hash` 가 그 자리에서
어긋나 방금 봉인한 체인이 stale 로 떨어진다.

## 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) · `--impeccable-available`
- 라운드 수: **1** — 라운드 캡이 `MCCP_REVIEW_SINGLE_PASS=deadline_pressure` 로 1 에 pin 돼 있다
  (`effectiveRoundCap` 출력: `{"cap":1,"pinned":true,"pinnedBy":"single-pass"}`)
- Codex verdict: `needs-attention` (structured `.result.verdict`)
- 합치 결론: 6건 중 **4건이 실물 대조에서 사실이고 이 사이클에서 닫힌다**(F1·F2·F4·F6).
  1건은 계획이 봉인한 결정과 정면으로 어긋나 반려하고(F5), 1건은 21번째 토큰을 요구해
  `Task 3 Gate` · `ops/reconcile/_harness/m0.sh 303행` 의 토큰 집합 크기 20 결박을 깨므로
  이월한다(F3). 두 반려·이월 다 사유를 대고 대기열에 올린다.

### YAGNI Triage

| Finding | Severity | Verdict | Why |
|---|---|---|---|
| F1 golden 을 상호 일관되게 다시 쓰면 회귀 오라클이 자기일관성 검사로 약해진다 | HIGH | ACCEPT_NOW | 사실이다. `m0.sh` 5a·5b 는 계수만 문다. 앵커 이설이 바꿔도 되는 필드를 **필드 단위로** 못박고, 나머지(`kind`·`text`·`value`·`confidence`·`grade`·`supersedes` · 원장의 `target`·`verdict`·`basis`·행 순서)는 M0 시점 리터럴로 m1.sh 가 단언한다 |
| F2 6대상 골격이 `ledgerRow` 와 호환되지 않고 db 변형은 `OPS_RC_TARGET_SHA_DRIFT` 로 먼저 죽는다 | MEDIUM | ACCEPT_NOW | 실물 확인: `ops/reconcile/reconcile.mjs` 627행이 원장 대조 **전에** wire `row_sha` 를 문다. db 의미 필드만 바꾸면 계획한 `OPS_RC_STALE_PRESENT` 에 도달하지 못한다. `ledgerRow` 에 order 인자를 더하고(기존 호출은 `TARGET_ORDER` 전달), db 변형 case 는 그 행의 `row_sha` 만 재봉인한다 |
| F3 진술 색인 탈락 행을 계수만 하면 손상 색인도 `verdict ok` 가 된다 | HIGH | DEFER_TO_BACKLOG | 지적 자체는 사실이나 fail-closed 로 닫으려면 **21번째 토큰**이 필요하다. 계획서 Task 3 Gate 가 신설을 금지하고 `ops/reconcile/_harness/m0.sh` 303행이 크기 20 을 못박으며 6d 전수 대조가 새 토큰마다 음성 fixture 를 요구한다 — 셋 다 앞 창 봉인이다. 생산 트리는 그 파일의 소유 게이트(ops-20 `--check`, 실측 rc 0)가 이미 막고, 층 분리(UI1)상 진술 스키마 판정은 ops-30 의 일이 아니다. 회부 `F-OPS-30-S6` 으로 올린다 |
| F4 사람용 진단문은 쌍 집합을 무손실로 복원할 수 없다 | MEDIUM | ACCEPT_NOW | 실물 확인: `stalePresent` 는 ` · ` 로 잇고 진입점이 `replace(/\s+/g," ")` 로 접는다. 코드 변경 없이 닫는다 — 진단문이 이미 `${stalePresent.length}건` 을 싣고 있으므로 m1.sh 가 그 선언 건수와 **파싱된 쌍 개수의 일치**를 단언한다. 접혀서 줄어드는 거짓 통과가 그 자리에서 죽는다 |
| F5 국소성 검사가 외부 소유 코퍼스의 현재 행 수에 결박된다 | MEDIUM | REJECT_YAGNI | 계획이 봉인한 결정이다 — Acceptance 가 `143 · 2870 · 49 · 647` 을 명시하고, `ops/reconcile/_harness/m0.sh` 18~24행이 같은 결박을 **의도**로 적으며 재현 절차(봉인 커밋 detached checkout)까지 규정한다. "계수 없는 통과는 공허 통과" 가 그 근거다. 지적이 제안하는 `> 0` 은 리터럴 등식에 포함되므로 강화가 0 이다. 일회용 성질은 한계 마커 `F-OPS-30-M1L4` 로 남긴다 |
| F6 리비전 대조의 두 불변식이 빈 교집합·누락 투영에서 공허하게 참이다 | HIGH | ACCEPT_NOW | 사실이고 UI6(*"조용한 0건은 통과가 아니다"*) 정면이다. 비용이 거의 없다 — `common > 0` · `unknown 0` · `common + left_only == left_rows` · `common + right_only == right_rows` 를 더하고, 리비전은 7자 약칭이 아니라 전체 SHA 로 결박한다(`e852c234…` · `26aeb9fa…` · `41ca4faa…`, 셋 다 `git rev-parse` 로 실재 확인) |

- Deferred to backlog: **1** → `.claude/plans/codex-findings-backlog.md`
- Open Questions: **없음** — 미해결 `ACCEPT_NOW` HIGH/CRITICAL 0건. F1·F6 은 이 사이클의 구현
  요구사항으로 흡수됐고 F3 은 `DEFER_TO_BACKLOG` 라 R2 escalate 조건(ACCEPT_NOW × HIGH 잔여)에
  해당하지 않는다. 캡도 1 이다
- Codex session 참조: threadId `01a06059-03b3-7a33-8e7e-6d8b6b916dd0`

### Security Reviewer

> security-reviewer unavailable, skipped (auto-fallback): Agent tool forbidden by session
> operating rules; subagent_type security-reviewer cannot be dispatched.

이 마일스톤에 §0 auto-CRITICAL 카탈로그(보안 경계 · 원자적 상태 · 스키마 파손) 항목은 없다.
인접한 자리는 하나 — 하네스의 재귀 삭제 대상이다. `ops/reconcile/_harness/m0.sh` 가 이미
`SNAP_INSIDE_REPO` · 소유 표식(`.ops30-snapdir`) · `under_snap`(node `path.resolve` 접두 대조)
세 겹으로 닫았고, `m1.sh` 는 셸 glob 을 쓰지 않고 그 형태를 그대로 재사용한다.

### Design Review

> impeccable silent-skip: `skill_available=1` · `design_signal=0` · reason `no-signal`.
> 산출물이 node CLI 하위 명령과 bash 하네스뿐이고 렌더되는 UI 표면이 0건이다 — 계획서
> §Design Routing Guide 가 같은 사실을 미리 적는다. 탐지 사실과 함께 남긴다.

## 계획 대비 이탈

| # | WHAT | WHY |
|---|---|---|
| 1 | `m1.sh preflight` 의 부재 집합에서 `.claude/notes/ops-30-reconcile-m1.md` 를 빼고, 대신 **이름 있는 면제**로 둔다 | Phase 2.5 게이트 산출물(이 notes 파일 + `mccp-implement-codex` receipt)은 구조적으로 Task 1 보다 **앞선다**. 계획서 Task 1 Validate 의 부재 단언을 문면 그대로 두면 게이트가 자기 산출물 때문에 기준선을 못 뜬다. 부재 단언의 의도(*"M1 산출물이 하나도 없는 상태"*)는 M1 이 만드는 것 — `m1.sh` 밖 산출·findings 추가분 — 에 걸리므로, 면제는 이름을 대고 계수로 낸다 (`gate_artifacts_exempt <n>`) |
