# 계약 초안 — `sourced_delta` 가 **세 가지를 한 칸에** 담고 있다

> **초안이다. 구현 없음.** §2-3c 유료 1회(2026-08-30, 논리 42)가 드러낸 것을
> 적고 선택지를 올린다. §10 기대값은 **안 건드린다**. 결정은 사용자 몫이다.
>
> ★2판 — Codex BLOCK 3건을 반영했다. 1판에서 내가 **증거보다 세게** 쓴 곳이
> 있었다(아래 §3 의 「완결성」 · §5 의 b2 · §4 의 충돌 범위).

## 1. 무엇이 났나

§2-3c 아홉 축이 **전부 `unresolved`** 로 닫혔다 — 맞음 0 · 어긋남 0 · 미확정 9.
검색 **전** route 는 아홉 축 모두 `research×6` 만장이었다(새 계약대로).
갈린 자리는 **sourced delta** 하나다.

## 2. 왜 — 한 칸이 세 가지를 겸하고 있다

| | 물음 | 무엇에 관한 것인가 |
|---|---|---|
| ① `sourced_delta` | 목표 시대·지역의 실물이 기본값과 **다른가** | **세상 사실** |
| ② `research_completeness` | 꼭 알아야 할 구별점을 **다 찾았는가** | **이번 조사의 상태** |
| ③ operational decision | 그래도 **조사를 건너뛸 것인가** | **사람의 정책** (시간·우선순위) |

섞여 있으면 이렇게 무너진다:

- **①이 yes 인데 ②가 미완이면 통째로 `unresolved`** 가 된다 → 「조사가 필요하다」를
  이미 출처로 확인해 놓고도 그 사실이 사라진다.
- **①을 못 정한 것이 ③의 근거로 쓰인다** → 「못 찾았으니 조사 안 해도 된다」로 읽힌다.
  계약이 명시적으로 막은 자리다(「A=no 는 **차이가 없다는 긍정적 출처**가 있을 때만」).

## 3. ★★②를 지금 코드로는 **잴 수 없다** (1판 정정)

1판에서 나는 「필수 gap 0 = 다 찾아봤다 = `complete`」라고 적고
「검색을 더 잘해도 안 나온다」까지 썼다. **증거보다 세다** (Codex).

**왜 못 재나 — 필수 구별점 목록을 결과 모델이 같은 응답에서 스스로 만든다.**
어려운 구별점을 통째로 빼면 「필수 gap 0」이 나온다. 저장 기록이 그대로 보여준다:

| 축 | required claim | optional claim | 필수 gap | optional gap |
|---|---|---|---|---|
| `fb7a883f/P01` 자전거 체인 | 1 (neutral · 구조) | 2 | 0 | 2 |
| `fb7a883f/P03` 손전등 | **0** | 2 | 0 | 2 |

손전등은 **required claim 이 하나도 없다.** 「다 봤다」가 아니라
**「무엇을 봐야 하는지도 이 응답이 정했다」**이다.

★그래서 ②는 아홉 축 **전부 `unknown`** 이다. `complete` 로 세려면
**사전에 잠근 expected discriminator set** 과 그것을 덮었는지 보는 gate 가
있어야 한다. 지금은 없다.

## 4. ★★충돌은 **구별점 단위**로 접어야 한다 (1판 정정)

1판은 「충돌이 하나 있으니 그 대상은 unresolved」로 두고 「대상 단위냐 claim
단위냐」를 열어 뒀다. **그 갈래 자체가 틀렸다** (Codex). `97375a4b/P03` 을 보면:

```
diff claim  required  family=재질            종이 승차권이었다 (금속 토큰과 구별)
diff claim  required  family=표기·종류       국민학생용·중고생용·대학생용으로 구분
diff claim  optional  family=수량·묶음 단위   10장 묶음으로 유통
conflict gap 필수     ← **묶음 형식**이 낱장 뭉치였나 연속 인쇄였나
```

충돌은 **묶음** 하나에 관한 것인데, 그것이 **재질·표기**의 차이 근거까지
지우면 안 된다. 그래서:

> **`sourced_delta` 는 discriminator 단위로 접는다.
> 같은 discriminator 의 yes/no/conflict 만 서로 막는다.**

★**계약에 없는 칸이 하나 필요하다.** 지금 gap 의 `discriminator` 는 자유
문자열이고 claim 은 `discriminator_family` 를 따로 갖는다 — **둘을 구조적으로
결속할 칸이 없다.** 위 판정은 사람이 글자를 읽어 가른 것이지 코드가 가른 것이
아니다. 그 결속 칸을 계약이 요구해야 한다.

## 5. 아홉 축 (저장 기록 · 무료 진단)

> ★**acceptance 가 아니다.** 규칙 후보를 진단한 것이다.
> ①규칙: 유효하고 **같은 구별점에서** 충돌 없는 `supports_difference` claim 이
> 하나라도 있으면 yes · 미발견은 **no 가 아니다**.

| 축 | §10 기대 | ① sourced | ② 완결성 | 근거 |
|---|---|---|---|---|
| `97375a4b/P01` 쇠사슬로 묶인 기계식 요금통 | research | unresolved | **unknown** | diff 0 · 필수gap 4 |
| `97375a4b/P03` 고무줄로 묶인 종이 회수권 뭉치 | research | **yes** | **unknown** | diff 3(재질·표기 무충돌) · 충돌 1(묶음) |
| `0aea12c2/P01` 쇠사슬에 묶인 투명 요금통 | research | unresolved | **unknown** | diff 0 · 필수gap 4 |
| `0aea12c2/P03` 고무줄로 묶인 종이 회수권 뭉치 | research | **yes** | **unknown** | diff 1 · 필수gap 4 |
| `fb7a883f/P01` 낡은 자전거 체인 | non-research | unresolved | **unknown** | diff 0 · same 0 · required claim 1 |
| `fb7a883f/P03` 휴대용 손전등 | non-research | unresolved | **unknown** | diff 0 · same 0 · **required claim 0** |
| `fb7a883f/L01` 좁은 자전거 정비소 내부 | non-research | unresolved | **unknown** | diff 0 · 필수gap 2 |
| `fixture:hanbok` 한복 | non-research | unresolved | **unknown** | diff 0 · 필수gap 1 |
| `fixture:unbranded_car` 무브랜드 승용차 | non-research | **yes** ※ | **unknown** | diff 2 · 필수gap 1 |

```
①=yes         3축   ← 「조사가 필요하다」가 이미 출처로 확인됐다
①=unresolved  6축
②             9축 전부 unknown — 잠근 기대 구별점 목록이 없다
```

**※ 기대값과 부딪히는 축** — `무브랜드 승용차`(§10 음성)에 출처가
**시대 차이가 있다**고 답했다. ★**§10 기대값을 조용히 바꾸지 않는다.**
사용자 결정 사항으로 올린다.

★그리고 **「검색을 더 잘해도 안 나온다」는 아직 못 하는 말이다.** 자전거
체인·손전등이 그 자리처럼 보이지만, ②가 `unknown` 인 이상 「출판이 없어서」인지
「이 응답이 안 찾아봐서」인지 **못 가른다**.

## 6. 그래서 음성은 어떻게 서는가

**정직한 길은 하나 — 사람이 명시한 `operational exemption`.** 아래는 **아니다**:

- ~~`not_found` → `non-research`~~ — 못 찾은 것을 「차이 없음」으로 읽는 것
- ~~VLM/LLM 에게 「차이 없지?」를 묻는다~~ — 짐작을 다른 짐작으로 바꾸는 것
  (사용자 판정으로 두 번 기각)

## 7. 선택지 (결정 필요 — 구현 안 함)

| | 무엇 | 값 | 대가 |
|---|---|---|---|
| **A** | ①②③을 **칸으로 가른다**. `research_required` 는 ①=yes 로 서고, ②는 **하류(reference 생성)를 막는** 별도 상태 | 이미 확인한 「조사 필요」가 안 사라진다(지금 3축). §2-5.5 fail-closed 가 정확해진다 | 음성은 여전히 미확정 |
| **A2** | ①을 **discriminator 단위**로 접는다 + gap↔claim **결속 칸**을 계약에 넣는다 | 다른 구별점의 충돌이 멀쩡한 근거를 안 지운다 | 스키마 변경(팩 새 버전) |
| **A3** | **잠근 expected discriminator set** 을 두고 ②를 실제로 잰다 | ②가 `unknown` 을 벗어난다. 「출판이 없어서」와 「안 찾아봐서」를 가를 수 있다 | 대상 종류마다 기대 목록을 누가 만드나 — 사람 작업 |
| **B** | **operational exemption** 을 사람이 명시한다. 범위: **(b1) 대상별 손 지정** 또는 **(b3) 다른 기준**(시대 폭·소유자 종류 등) | 음성이 실제로 설 수 있는 유일한 길 | 범위를 넓히면 조사 구멍이 된다 |
| ~~b2~~ | ~~`referent_specificity=generic_class` 는 조사 제외~~ | — | ★**실측으로 기각.** 이번 주행에서 **아홉 축이 전부 `generic_class`** 다(양성 요금통·회수권 4축 포함, 표본 6개 중 `0aea12c2/P01` 만 5:1). b2 는 음성만 빼는 게 아니라 **양성도 전부 조사에서 뺀다** |
| **C** | §10 기대값을 다시 본다 | 무브랜드 차 축의 실제 출처 답과 맞출 수 있다 | **사용자 지정 축**이라 내 몫이 아니다 |

★A·A2·A3 는 계약 정리라 B 와 **독립**이다. B 없이도 양성 쪽 기록은 정확해진다.
★검색 지문·질의 손보기는 **이 결정 뒤**다.

## 8. 이 초안이 **말하지 않는 것**

- §3c 통과 — **아니다.** FAIL/미확정 유지다.
- 무료 replay 결과 — **acceptance 가 아니다.** 규칙 후보 진단이다.
- §10 기대값 변경 — **안 했다.**
- 「검색을 더 잘해도 안 나온다」 — ②가 `unknown` 이라 **아직 못 하는 말이다**.
