---
task_id: task-2949
title: 실손 지식 전수강화 + 근거봉인 (전수 OCR·전수 비교 매트릭스·출처 tier 정직마킹·fail-closed 게이트)
team: dev2 (오딘)
scope: task
date: 2026-08-13
status: 완료 (머지 대기 — merge_policy=tiered, 머지는 ANU)
active: false
---

# task-2949 — 실손 세대 지식 전수강화 + 근거봉인

## 0. 결론 요약

- 자료 **18장 전수 vision OCR 완료 (18/18, FAIL 0)**. 기존 task-2947 OCR은 KB 16장을 2개 파일로 압축한 것이라, **페이지 단위 전수 판독은 이번이 최초**.
- **자료 간 전수 비교 매트릭스 130셀(10행 × 13열)** 작성. 충돌 **17건 전수**를 지식 JSON `conflicts[]`에 반영(양쪽 값 보존, 1차 출처 우선).
- 출처 **정직 마킹**: tier1 = 1건(협회 기준표)만. **A2(변천사)는 출처 표기가 아예 없어 tier=null 유지 — 추정 승격 안 함.**
- `primary_source_verified` **10개 레코드 전부 false** → 고객 자동판정 경로 **hard-block 상태**(fail-closed).
- 테스트 **silson 173 passed**, 전체 서버 스위트 **1715 passed / 3 skipped / 신규 실패 0**.
- 커밋 `fbff8ca` (base main `1b64f99`). **머지 ≠ 활성화**, ACTIVE=false.

---

## 1. 자료 실사 — 지시문 "19장" vs 실제 18장

| 조 | 파일 | 장수 |
|---|---|---|
| A1 | `5세대vs유병자vs노후실손.png` (★1차 출처) | 1 |
| A2 | `변천사&보장안하는손해.jpg` | 1 |
| KB | `총정리(KB손보)/KakaoTalk_20250808_122716321{,_01..._15}.png` | 16 |
| **계** | | **18** |

지시문은 19장이라 했으나 디렉터리 전수 조사 결과 **18개 파일**뿐이다. 19번째를 임의로 만들지 않았다.
전 파일 sha256 지문을 `logs/source_sha256.txt`에 고정했고, 작업 종료 후 재계산 결과 **18/18 일치**(원본 무수정 확인).

---

## 2. 전수 OCR (누락 0)

- 1이미지 = 1호출, 아누 vision(claude CLI). 3개 배치 병렬. **18/18 status=OK, FAIL 0**.
- 산출: `teams/dev2/task-2949/ocr_full/*.md` (frontmatter: slug / source_file / sha256 / ocr_model / ocr_at)
- 처리 로그: `logs/batchA.log`, `batchB.log`, `batchC.log` (이미지별 status·bytes·표수·소요초)

### 2-1. 판독불가 갭필

| 구분 | 건수 |
|---|---|
| 갭필 전 판독불가 | 33토큰 / 22항목 |
| 완전 해소(확정) | **8건** |
| 부분 해소(문구 대부분 복원) | 14건 (전 페이지 하단 고지문) |
| 최종 미해소 | **6글자** |

- 확정 예: KB11 비급여특약 공제금액 → `1회당 2만원 또는 보장대상의료비의 30%중 큰 금액 공제 후 보상` (6배 확대, 2회 이상 독립 판독 일치). KB13(4세대)의 `3만원`과는 **세대 차이에 따른 별개 값**이며 상충 아님.
- 미해소 사유(사실): 원본 595×842px(A4 72dpi), 고지문 글자 높이 **약 7px**. 업스케일은 정보량을 늘리지 못함. 다중 프레임 합성·언샤프 마스크 모두 시도했으나 이득 없음.
- **KB 총정리 16장은 하단 고지문상 "사내교육용 자료 — 고객 제시·교부 금지, 보험안내자료 사용 금지"** 자료임이 판독으로 확인됐다. 고객 대면 활용 시 별도 검토가 필요하다.

### 2-2. tier1 근거 각주 충돌 해소

| 판독 | 결과 |
|---|---|
| task-2947 1차 | `※ 손해보험협회 공시실` |
| task-2949 1차 | `※ 손해보험협회 공시자료` |
| **확대 블라인드 재판독 3회(6·8·12배, sonnet+opus)** | **`※ 손해보험협회 공시실` 전원 일치** |

→ `공시자료`는 **오독(REFUTED)** 으로 판정. 봉인본에는 1차 판독 줄을 축자 보존하고 바로 아래 정정 블록을 명시했다(근거 경로 포함).

---

## 3. 자료 간 전수 비교 매트릭스 (★ 핵심 산출물)

**130셀 = 10행 × 13열** (2세대를 표준화 Ⅰ/Ⅱ/Ⅲ 3행으로 분할). 빈 셀 0, 중복 0.

| agree | conflict | only_A1 | only_A2 | only_KB | absent |
|---|---|---|---|---|---|
| 46 | **17** | 25 | 1 | 6 | 35 |

두 계열 이상이 값을 가진 셀 63개 중 **17개(26%)가 충돌**이다.

### 충돌 17건 (레코드별)

| 레코드 | 건수 | 항목 |
|---|---|---|
| GEN1_2003_10 | 5 | deductible, payout_rate, upper_grade_room, coverage_limit, excluded_coverages |
| GEN2_STD1_2009_08 | 2 | deductible, excluded_coverages |
| GEN2_STD2_2013_01 | 3 | deductible, payout_rate, waiting_period |
| GEN2_STD3_2015_09 | 3 | deductible, waiting_period, excluded_coverages |
| GEN3_2017_04 | 3 | deductible, coverage_limit, excluded_coverages |
| GEN4_2021_07 | 1 | coverage_limit |
| **계** | **17** | |

- 전부 `{field, primary, secondary[], resolution: primary_wins, note}` 형식으로 기록. **대표값은 1차 출처(A1 > A2 > KB) 우선**, 반대편 값도 원문 그대로 보존.
- 기존 task-2947 충돌 5건은 field 범위가 더 좁았고(예: `excluded_coverages/치매`) 전부 신규 항목의 부분집합이라 병합했으며, **원형은 `prior_record`에 그대로 보존**(유실 0).
- 대표값(레코드 본문 필드)은 **한 건도 바꾸지 않았다** — 프로그램으로 바이트 동등 검증.

### 중대 발견 5건

1. **MRI 특약 한도 200 vs 300** — A2는 `MRI 200`, KB는 **서로 다른 3개 페이지(KB02·KB11·KB13)에서 독립적으로 300만원**. 규칙상 대표값은 200이나 근거 수는 KB가 우세. 4세대는 A2가 `좌동`이라 충돌이 그대로 전파. **→ 회장 판단 필요**
2. **2세대 표준화Ⅲ 면책기간 임계값 275일 vs 365일** — A2 `275일 이후 90일 / 275일 이내 365일` vs KB10 `365일 초과 → 90일 / 365일 이내 → 365일`. **소진기간 275~365일 구간에서 지급 판정이 갈린다**(고객 영향 직접).
3. **A2에 '표준형' 유형이 통째로 없음** — KB는 1~3세대 전 구간에 표준형/선택형 2종을 기재하나 A2는 사실상 한 유형. 표준화Ⅱ에서 A2 `표준 20%` vs KB07 `표준형 80%`로 같은 축의 값이 정반대(자기부담률 vs 보장률로 읽힐 여지가 있으나 원문에 정의가 없어 해석하지 않음).
4. **A1과 A2/KB의 커버리지가 완전 배타적** — A1은 1~4세대를 전혀 다루지 않고, A2/KB는 5세대·노후·유병력자를 전혀 다루지 않는다(KB 16장 언급 0건). 이 3개 상품의 **25셀은 교차검증 자체가 불가능한 단일 출처**다.
5. **4세대 면책기간 값이 어느 자료에도 없음** — A2의 해당 셀 내용이 `보험료차등제`(행 라벨과 불일치), KB11/KB13 표에는 해당 열 자체가 없음.

### 기존 OCR 대비 delta

- A02(변천사)는 두 독립 OCR이 **전 셀 완전 일치**, A01도 값 전건 일치(각주 1건만 상이). → **충돌 17건은 OCR 오류가 아니라 자료 간 실제 내용 차이**임이 확인됐다.
- 판독 충돌 27건(26건 KB) 중 **의미가 뒤집히는 중대 7건**: KB14 `제외` 유무(차등제 대상 정반대), KB09 점(모반) `만 6세 미만` vs `태아`, KB09 시력교정술 개정 전/후 배치 뒤바뀜, KB09 건강검진, KB13 주사치료 약제 목록, KB11 도수치료 제외 시술, KB03 병실료차액.

---

## 4. 출처 정직 마킹 (구조화 5필드 + tier)

`sources_registry` 18항목 신설. 각 항목: `source_id / publisher / doc_title / as_of / ref` + `source_tier` + `tier_basis` + `primary_verification` + `image_sha256` + `drive_file_id` + `upload_status`.

| tier | 건수 | 근거 |
|---|---|---|
| **1** | 1 (A1) | 이미지 각주 원문 `※ 손해보험협회 공시실` |
| **2** | 16 (KB) | KB손해보험 제작 2차 자료 (관리번호 `작성교육-25-03-02`) |
| **null** | 1 (A2) | **출처 표기 없음 → 추정 승격 금지** |

- `as_of` **18건 전부 null** — 어느 이미지에도 기준일/작성일이 없다. 파일시스템 타임스탬프로 대체하지 않았다.
- **`primary_source_verified`: true 0 / false 10**. tier1인 A1조차 `primary_verification.verified=false`인데, 각주에 **기관명만 있고 문서명·공시항목·URL·조회일자가 전무**해 협회 공시 원문과의 대조가 불가능하기 때문이다. 기관 귀속은 되지만 **1차 원문 대조 증명은 아니다.**
- 이 값을 억지로 true로 만들지 않았다. 결과적으로 고객 자동판정 경로는 **전 레코드 차단** 상태다.

---

## 5. 활성화 fail-closed 게이트

`server/silson/gating.py` 신설.

- `SILSON_KNOWLEDGE_ACTIVE` 미설정/`0`/`false` → 비활성(**기본값이 차단**)
- `SILSON_ACTIVATION_APPROVED_BY` 비어 있으면 활성 불가 (**회장 단독 승인 표식**)
- `assert_customer_auto_path(profile)` — 비활성이거나 `primary_source_verified=False`면 예외
- 호출자가 `{"primary_source_verified": True}`를 실어 보내도 통과시키지 않는다. 플래그는 **차단 방향으로만** 신뢰하고 최종 판정은 항상 지식 데이터에서 재계산 → dict 하나로 우회하는 구멍 차단.
- **기존 공개 API는 한 줄도 변경하지 않았다**(`classify.py`/`knowledge.py`/`analysis_bridge.py` 무수정). 기존 94 테스트가 무수정 통과하는 것이 근거.

---

## 6. 근거봉인

- 봉인 OCR 18장 → `server/silson/data/sources/ocr/*.md` (PII 스캔 **마스킹 0건** — 자료에 개인정보 없음)
- `manifest.json`: items 18, `ocr_sha256` 재계산 **18/18 일치**, 재실행 시 **바이트 동일(멱등 확인)**
- 비교 매트릭스 `comparison_matrix.json` repo 편입(입력과 바이트 동일 146,037B) + sha256 manifest 기록
- **Drive 업로드는 실행하지 않았다** → `drive_file_id: null`, `upload_status: "PENDING"` 18건. 코드 경로(`--upload-drive`)와 dry-run만 준비. 가짜 ID를 넣지 않았다.
  - 업로드 경로는 P0-1 준수 확인(공개권한 생성 코드가 main에서 이미 제거됨 — 소유자 전용 비공개).
  - **실행은 회장 승인 후.**

---

## 7. 검증 결과

| 게이트 | 결과 |
|---|---|
| OCR 18/18 산출, 누락 0 (sha256 1:1) | **PASS** |
| 비교 매트릭스 전 셀 채움 | **PASS** (130/130, 빈 셀 0) |
| 충돌 전수 기록 (매트릭스 17 == JSON 17) | **PASS** |
| `validate_bundle()` 문제 0 | **PASS** |
| silson 테스트 | **173 passed** (기존 94 무수정 + 신규 79) |
| 전체 서버 스위트 | **1715 passed, 3 skipped — 신규 실패 0** |
| 환각 0 게이트 | **PASS** — 매트릭스 286 value 전부 봉인 OCR 부분문자열(279 직접 + 7 합성), 불일치 0 |
| 게이트 fail-closed | **PASS** — env 미설정/승인자 없음/verified=false 3경로 전부 차단 |
| 허용 경로 준수 | **PASS** — 금지 경로 접촉 0 |

negative control 3종(환각값 주입 / 충돌 1건 삭제 / 출처 집합 변조)을 실제로 돌려 게이트가 **실제로 잡는지** 확인했다.

---

## 8. 잔여 리스크 · 회장 결정 필요 사항

### 결정 필요

1. **MRI 한도 200 vs 300** — 규칙대로면 대표값 200(A2)이나 KB 3개 페이지가 독립적으로 300만원을 기재. 어느 쪽을 대표값으로 확정할지.
2. **A1 tier1 판정의 한계** — 각주는 기관 귀속일 뿐 문서명/URL/조회일이 없다. 협회 공시 **원문 확보 + 수치 대조**를 별도 절차로 진행할지.
3. **활성화 여부** — 현재 ACTIVE=false, 전 레코드 차단. 활성화는 회장 단독 승인(`SILSON_ACTIVATION_APPROVED_BY`) 필요.
4. **Drive 업로드 실행 여부** — 원본 18장 비공개 업로드 후 `drive_file_id` 채우기.

### 리스크 (정직 기록)

- **봉인 OCR에 오독이 남아 있다.** 축자 보존 원칙상 판독 결과를 그대로 봉인했는데, 신규 페이지 단위 OCR이 일부 셀에서 기존 판독보다 나쁜 문자열을 냈다(예: KB03 공통사항 줄의 `치료치료`/`금여`/`전재지변`/`보사약품` — 2947 판독은 `치과치료`/`급여`/`천재지변`으로 더 정확). 매트릭스 secondary 값에 이 문자열이 그대로 들어가 있다. **추적은 가능하나 봉인본이 오류 없는 원문은 아니다.** → 후속 정밀 재판독 과제 권고.
- **미해소 판독불가 6글자** — 하단 고지문 일부. 해상도 물리 한계이며 고해상도 원본 재확보 없이는 해결 불가.
- **단일 출처 25셀** — 5세대·노후·유병력자는 A1에만 있어 교차검증이 구조적으로 불가능하다.
- **KB 자료의 사용 제한** — 사내교육용, 고객 제시·교부 금지 명시. 고객 대면 산출물에 KB 유래 수치를 쓰려면 별도 검토 필요.

---

## 9. 산출물 경로

**repo (InsuRo, 브랜치 `task-2949-silson-evidence`, 커밋 `fbff8ca`)**
- `server/silson/provenance.py` / `gating.py` / `tools/seal_sources.py`
- `server/silson/data/silson_generations.json` (sources_registry + primary_source_verified + conflicts 17)
- `server/silson/data/sources/{manifest.json, comparison_matrix.json, ocr/*.md ×18}`
- `server/tests/test_silson_provenance.py` (79 테스트)

**workspace**
- `teams/dev2/task-2949-contract.md` — 설계 계약서
- `teams/dev2/task-2949/comparison_matrix.{json,md}` — 전수 비교 매트릭스
- `teams/dev2/task-2949/ocr_delta.md` — 기존 OCR 대비 delta
- `teams/dev2/task-2949/ocr_full/*.md` — 전수 OCR 18장
- `teams/dev2/task-2949/logs/{batchA,batchB,batchC}.log`, `footnote_verification.md`, `gapfill.md`, `source_sha256.txt`
