# Implementation Report: 사실 인덱스 · 코드 축 — 마일스톤 5b (`tests.jsonl`) · r3

**Plan**: `.claude/plans/insuniverse-docs-11-index-code-m5b-r3.plan.md` (아카이브하지 않았다 — 아래 참조)
**Decision**: `insuniverse-docs-11-index-code-m5b-r3`
**Branch**: `feat/index-code`
**착수 기준 커밋**: `cc3baf85`
**상태**: **차단** — 산출물은 생성됐고 5b 소유 검사는 전부 통과했으나, 마일스톤 5a 계약 결함 2종이
정식 게이트를 통과 불가로 만든다. `Status` 를 `complete` 로 넘기지 않았다.

## Summary

`tests.jsonl`(58행)과 그것을 만드는 무의존 Node 스크립트 2개를 만들었다. 판정 규칙은 하나도 다시
적지 않았고 어휘·hop·skip·선택·호출 맥락 판정을 전부 마일스톤 5a 모듈에서 import 한다. 열거 형태는
재열거기(`verify-tests.mjs`)와 **동형**이며, 그 동형이 드러낸 5a 계약 결함 둘이 산출을 차단했다.

## Assessment vs Reality

| Metric | Predicted (Plan) | Actual |
|---|---|---|
| Complexity | Medium | Medium-High — 열거 동형 요구가 파서 3종(워크플로·Dockerfile·skip 개소)의 재현을 강제했다 |
| 행 수 | 목표 아님 (`--report` 가 정본) | **58** (server 39 · site 19 · admin 0) |
| Files Changed | 4 | 4 (계획 목록 그대로) |
| Validation | 전부 통과 예정 | **1/2 게이트 실패** — 3자 대조 통과, `--file` 하위 검사 실패 |

## Tasks Completed

| # | Task | Status | Notes |
|---|---|---|---|
| 0 | 스캔 소스·착수 전제 못박기 | 완료 | 0-0·0-a~0-g 전부 생성기 안에서 돈다 |
| 1 | `build-tests.mjs` | 완료 | selftest **30건** PASS (로컬 리뷰 흡수로 26 → 30) |
| 2 | `--report --json` 계약 | 완료 | 22키 정확 집합 |
| 2b | `check-tests-crosscheck.mjs` | 완료 | 복합 게이트. selftest **24건** PASS (19 → 24) |
| 3 | `tests.jsonl` + 큐레이션 | 완료 | `gap` **17항목**(계획 14 + 신규 3) |
| 4 | findings + 이월 | 완료 | 발견 41~55 · §2 요청 8행 · 새 §4 이월 10건 |

## Validation Results

| Level | Status | Notes |
|---|---|---|
| 0-e preflight | PASS | `CONTRACT_VERSION === 2` 등호 · 픽스처 12종 토큰 집합 · probe 3종 |
| 0-0 리비전·작업트리 게이트 | PASS | 3저장소 HEAD == manifest (site·admin 체크아웃 복원 후) |
| 생성기 `--selftest` | PASS | **30건** |
| 복합 게이트 `--selftest` | PASS | **24건** (음성 픽스처 직교 두 갈래 포함) |
| 픽스처 mutation 검사 | PASS | 클램프·3자 대조·분포 재집계를 각각 제거하면 B-17a/B-24 · C-16 · C-18 이 **깨진다** |
| **3자 대조** (report · 독립 재스캔 · JSONL) | **PASS** | `test_files` · `skip_evidence` · `outside_allowlist` 전부 정확 일치 |
| **`verify-tests.mjs --file`** | **FAIL (3건)** | 전부 admin 벤더 Dockerfile 1파일 — 아래 |
| 재현성 (2회 생성 `diff`) | PASS | 빈 출력 |
| PRD 무변경 (unstaged·staged·기준커밋 3중) | PASS | |
| 마일스톤 1~4 회귀 selftest | PASS | 3/3 |

### 차단 — 마일스톤 5a 계약 결함 2종

```
meta.ci_evidence[insuniverse-admin].invocations[26].id:
  앵커 행이 run / uses / test 를 포함하지 않는다:
  insuniverse-admin/public/_statics/adminLTE/Dockerfile:8 — 실제 등장 행: 12
meta.ci_evidence[insuniverse-admin].invocations[26]:
  working_directory 가 실재하지 않는다 — code
```

| # | 결함 | 근거 | 왜 5b 가 못 고치나 |
|---|---|---|---|
| 발견 54 | `ANCHOR_TOKENS.invocation` 이 소문자 `run` 인데 Dockerfile 지시어는 대문자 `RUN` | `verify-tests.mjs:151-155` vs 같은 파일 `:166-173`(잔여 쪽엔 대문자 `RUN` 이 이미 있다) · `boundedIncludes` 대소문자 구분 실행 확인 | `verify-tests.mjs` 편집은 5a 소유 (UI6 + 계획 Acceptance 가 FAIL 로 건다) |
| 발견 55 | Dockerfile `WORKDIR` 은 컨테이너 경로인데 `:677-682` 가 저장소 디렉터리 실재를 요구 | `WORKDIR /code` → `working_directory: "code"` · 저장소에 `code/` 없음 | 동일. 54 를 고쳐도 남는 **독립된 둘째 차단** |

**어느 생산자도 빠져나갈 수 없다**: `rescanInvocationsForRepo`(`:1843-1864`)가 그 호출을 만들고
`checkRescanParity`(`:448-472`)가 문서에 그것을 **요구**하는데, 싣는 순간 `--file` 이 거부한다.
`--rescan-invocations` 직접 호출로 재열거기 자신의 출력이 같은 레코드임을 확인했다.

## Files Changed

| File | Action | 규모 |
|---|---|---|
| `docs/_meta/verify/build-tests.mjs` | CREATED | 1,621행 |
| `docs/_meta/verify/check-tests-crosscheck.mjs` | CREATED | 559행 |
| `docs/_meta/index/tests.jsonl` | CREATED | meta 1 + 행 58 |
| `docs/_meta/findings/11-index-code.md` | UPDATED | 발견 41~55 · §2 8행 · 새 §4 이월 10건 |

게이트 산출물(계획 `Files to Change` 밖, 구현 파일 아님):
`.claude/notes/…-m5b-r3.md`(Implement-Codex 리뷰 기록) · `.claude/receipts/mccp-implement-codex/…json`

## Deviations from Plan

| # | 계획 문면 | 실제 | 왜 |
|---|---|---|---|
| 1 | 주석 스트리퍼로 m3 `blankCommentsSafe` 를 import | m2 `blankCommentsAndRegex` | 배달된 재스캐너가 그것을 쓴다(`verify-tests.mjs:41-45`). 다른 스트리퍼를 쓰면 skip 개소 좌표가 갈려 3자 대조가 그 자리에서 깨진다 |
| 2 | 0-a 파일 목록을 `git ls-files` 로 | `GIT_INDEX_FILE=<임시> git ls-files` (임시 인덱스 = `git read-tree <manifest head>`) | Codex R1 F2. 같은 명령·같은 pathspec magic, 인덱스만 불변 스냅샷. `git ls-tree` 는 `:(glob)` 미지원이라 14+11 목록 재구현을 강요한다 |
| 3 | 0-f `T` 를 `uses: ./…` 행에서 수집 | 값 판독을 `scalarValue` 동형(인용·주석 처리) | Codex R1 F1. 인용형 `uses: "./…"` 가 clamp 를 우회한다. `T` 는 검증기가 안 보는 생산자 전용 집합이라 parity 무영향 |
| 4 | — | 중첩 스칼라 phantom 을 **재현**하고 픽스처(`B-3`)로 고정 | Codex R1 F0. 마스킹은 5a 소유이고, 생산자만 고치면 parity 가 깨진다 |
| 5 | `outside_allowlist` 를 manifest `exclude_glob` 11 로 | 재열거기 walk prune 9 로 | 3자 대조 대상이라 목록이 다르면 필연 실패(admin 245 vs 0). 발견 52 · `gap` 16 · §2 (f) |
| 6 | `gap` 14항목 | **17항목** | 신규 15(중첩 스칼라) · 16(제외 목록 두 벌) · 17(`resolvable_scan_result` 의미) |
| 7 | Implement-Codex 리뷰를 plan body 에 | `.claude/notes/…` 에 | plan body 를 바꾸면 `mccp-plan-codex` receipt 의 `plan_hash` 앵커와 0-g baseline 이 함께 무효화된다 |

## Issues Encountered

1. **submodule 체크아웃 드리프트** — site HEAD 가 `ed183ca6`(manifest 는 `b9a90a42`), admin 작업트리에
   `package.json`·`package-lock.json` 수정. 사용자 승인 후 부모 저장소가 기록한 서브모듈 포인터
   (= manifest head 3종과 정확히 일치)로 복원했다. admin 변경은 `git stash` 로 남겼다
   (`stash@{0}: 5b 0-0 gate: rollup bump`). **`origin/stg` 로 맞추면 안 된다** — manifest 는 동결값이다.
2. **`receipt cli.js write` 가 전체 교체** — `--plan-conflict-escalated` 만 붙여 재호출했더니
   `codex_verdict`·`security_skipped`·`impeccable_silent_skip` 이 기본값으로 돌아갔다. 전 플래그를
   재전달해 복구했다. write 는 `fix-task.md` 도 템플릿으로 재생성하므로 fix-task 는 **write 뒤에** 적었다.
3. **plan-conflict 검출기 오탐** — `file-expansion` 신호가 브랜치 이력 220파일과 게이트 산출물을
   계획 목록과 대조해 `conflict:true` 를 냈다. 실질 차단은 그것이 아니므로 사유를 정직한 문면으로
   바꿔 `fix-task.md` 에 적었다.

## Design Grounding

N/A — 설계 트리거 미발화 (`impeccable-detect`: `design_signal:false` · `silent_skip:true`).
산출물에 렌더면이 없다(JSONL 1개 + 무의존 Node 스크립트 2개). Phase 3.6·3.7 완전 no-op.

## Tests Written

| Test | 건수 | 덮는 것 |
|---|---|---|
| `build-tests.mjs --selftest` | 26 | 블록 스칼라 4스타일 · **중첩 스칼라 동형** · **인용형 `uses`** · skip 열거·분류 · skip_status 상호 강제 · 러너 walk-up · **0-f 강등 대칭 4갈래** · `if:` 조건 잔여 · manifest fail-closed · 0-a 이중 확인 · `.env` 하드 제외 |
| `check-tests-crosscheck.mjs --selftest` | 19 | 어휘 배열 계약 · 계수 leaf 6종 거부 · `Set` 금지(중복·정렬) · **음성 픽스처 직교 2갈래** · 자식 실패 전파 |

## 로컬 리뷰 흡수 (2026-08-14)

`/mccp:code-review`(Local Review Mode) 가 5b 산출물 자체에서 HIGH 3 · MEDIUM 5 · LOW 8 을 냈다.
**차단(발견 54·55)과 무관한 회귀 방어 결함**이고 전부 같은 사이클에서 닫았다. 전문은
`.claude/reviews/local-m5b-r3-review.md`.

| # | 지적 | 조치 |
|---|---|---|
| H1 | 복합 게이트의 위조 음성 픽스처(C-15·C-16·C-19)가 `crosscheck()` 를 부르지 않고 대조 논리의 **사본**을 시험했다 — 3자 대조를 지워도 초록 | 순수 대조부를 `compareSources()` 로 export 하고 생산 경로·픽스처가 같은 함수를 부른다. 정직한 입력 하나에 결함을 하나씩 주입하는 형태로 재작성(C-15~C-21). mutation 으로 무는 것 확인 |
| H2 | `runVerifier` 가 `json` 모드에서 자식 **비영 종료를 삼켰다** — `--rescan-candidates`·`--print-vocab-json` 이 죽으며 유효 JSON 을 뱉으면 그대로 통과 | 비영 종료를 기본 전파로 뒤집고 `--file` 만 `allowNonZero` 로 예외 명시. `json:true` + 비영 종료 픽스처(C-23) 추가 |
| H3 | 0-f 강등 픽스처 B-17a~d 가 클램프 식의 사본을 시험했다 | `clampSelect()` export, 생산 경로·픽스처 공유. mutation 확인 |
| M1 | `git ls-files` 가 기본 `core.quotePath=true` 라 비ASCII 경로(site 4 · admin 31 **실재**)를 C-인용으로 낸다 — 열거에서 조용히 빠지거나 `cat-file` missing 으로 중단 | `git()` 에 `-c core.quotePath=false` 못박고 실 git 저장소 픽스처(B-27)로 고정 |
| M2 | findings §1 표가 행 53↔54 사이 빈 줄로 쪼개져 54·55 가 헤더 없는 표로 렌더 | 빈 줄 삭제 · "41~53" → "41~55" 정정 |
| M3 | `invocation_discovery` 를 행 `ci_status` 에서 파생시켜 0-f 클램프가 그것을 움직였다 (계획 Acceptance 위반) | `deriveInvocationDiscovery(preClampAnyTrue)` 로 **클램프 이전** 판정에서만 파생. 오늘 값 불변(전 저장소 `undetermined`) · 픽스처 B-24~B-26 |
| M4 | `outside_allowlist` 의 97%가 벤더 번들인데 `gap` 16 이 규모를 안 적어 2,354 가 실제 신호로 읽힌다 | `gap` 16 에 규모 명시 (admin 245 중 238 · `_statics` 234 · `pdfjs-dist` 4) |
| M5 | 구현 노트가 "산출물에 소스 값을 싣지 않는다" 고 적었으나 잔여 `expression`·`callee` 는 소스 행 텍스트다 | 노트 서술 정정. 필드는 5a 계약이 form→필드로 못박은 자리라 뺄 수 없고, 오늘 잔여 0건이라 실제 유출은 없다 |
| L1~L8 | 죽은 코드 4종(`scanTargetPathspec` 재계산 · `channel` 맵 · `resolveRowRunner` 미사용 인자 · selftest 임시 dir) · `flag()` 값 무검증 · USAGE 누락 · 끝개행 없을 때 마지막 행 소실 · `compareItemSets` O(n²) | 전부 수정. `--selftest-dir` 은 크로스체크에서 제거(쓰지 않던 플래그) |

산출물 바이트 변화는 **`gap` 16 문면 하나**다 — 행 58 · `set_sha256` `f47b7c986b69…` · 전 행
`ci_status: undetermined` · `in_ci: null` 로 이전과 같다.

## Next Steps

- [ ] **선행**: 별도 correction 마일스톤(5a-fix-2)으로 발견 54·55 를 닫는다 — `ANCHOR_TOKENS.invocation`
      대문자 `RUN` 수용 + `working_directory` 실재 검사를 채널 조건부로. 픽스처도 같은 편집에서.
- [ ] 그 뒤 5b 재진입 — 생성기·복합 게이트·3자 대조는 재작업 대상이 아니다(전부 통과 상태).
- [ ] 사용자 결정 **A·B·C**(런타임 Outcome) 미결 — 산출물이 나온 뒤 Outcome 문면을 어떻게 닫을지.
- [ ] `admin` stash 복원 여부 결정 (`git -C ../../insuniverse-admin stash list`).
