판정이 어디서 오는지, 끝까지 따라갈 수 있게.
이 페이지는 결과를 믿어 달라고 하지 않는다. 어떤 파일에서 어떤 연산으로 나왔는지를 적고, 같은 저장소에서 그대로 재현되게 해 두었다.
쓰는 사람을 위한 설명은 홈 에 있다. 여기서는 줄이지 않는다.
데이터 기준일 2026-08-03
01메커니즘
AI 는 판정하지 않는다. 조약을 구조화할 뿐이다.
생성형 AI 를 쓰는 이상 환각은 확률적으로 발생한다. PACT 는 발생률을 낮추는 데 기대지 않고 통과 경로를 막았다.
AI 는 빌드 타임에만 관여하고, 사용자의 판정에는 규칙 파일과 결정적 엔진만 참여한다. 두 레인 사이를 넘어가는 것은 서명·게이트를 통과한 JSON 파일 하나뿐이다.
빌드 타임 — 배포 전 1회
사용자 요청과 무관 · 오프라인
- 1데이터
조약 정본
국가법령정보센터 조약 제1613호 국문·영문 정본. 발췌가 아니라 전문을 파일로 보관한다.
- 2AI · LLM
AI 구조화
조건, 근거 문장, 그리고 그 문장이 원문 어디에 있는지(문자 인덱스)를 함께 출력하게 한다. AI 의 관여는 여기서 끝난다.
- 3기계 · 무인
스팬 검증
인용문이 원문의 그 인덱스에 문자 단위로 실재하는지 대조한다.
차단 · 불일치하면 AI 출력과 무관하게 그 조건을 폐기한다
- 4사람
검수 서명
검수자·자격·독립 여부를 규칙 파일에 기록한다.
차단 · reviewedBy 가 비면 컴파일러가 exit 1
- 5기계 · 무인
배포 게이트
채널별 요건을 다시 확인한다.
차단 · 작성자 = 검수자면 production 채널을 막는다
출력 · src/data/rules/*.json — 5개 규칙 · prototype 채널 · 제3자 검수 전
게이트를 통과한 규칙 파일의 바이트만 앱에 실린다
런타임 — 매 판정
사용자 기기 · 네트워크 요청 없음
사용자 입력
나라 · 목적 · 고용형태 · 기간 · 입주 예정일
규칙 엔진
순수 함수 · 결정적 · 같은 입력이면 같은 출력
권리 카드
근거 · 기한 · 담당기관이 붙은 것만
이 레인의 LLM 호출0· 근거가 없는 조건은 카드가 생성되지 않는다 · 입력값은 서버로 전송되지 않는다
번들 규칙이 스키마를 위반하면 앱은 그 카드를 조용히 숨기는 대신 즉시 실패한다 — src/lib/rules/load.ts 가 로드 시점에 던진다. 소리 없이 사라지는 카드가 잘못된 카드보다 위험하기 때문이다. 원문에서 확인할 수 없는 항목은 지어내지 않고 공식 확인사항으로 강등해 문의처를 붙인다.
02스팬 검증
인용문이 원문 그 위치에 있는지, 문자 단위로 대조한다.
아래 원문은 src/data/sources/kr-de-ssa-art7.txt 의 전문이다. 강조된 구간은 앱에 배포된 규칙 파일의 basis.span 값으로 이 페이지를 빌드할 때 실제로 잘라낸 것이다.
인덱스가 한 글자라도 어긋나면 강조는 인용문과 다른 문장을 덮는다.
Article 7 Compulsory coverage in case of detachment (1) When an employee who is employed in one Contracting State is sent by his employer to the territory of the other Contracting State in the context of that employment to perform services there for that employer, only the legislation on compulsory coverage of the first Contracting State shall continue to apply with regard to that employment during the first twenty-four calendar months as though the employee were still employed in the territory of the first Contracting State. If the detachment continues beyond the period specified above, the legislation on compulsory coverage of the first Contracting State shall continue to apply, if the competent authorities of both Contracting States or the institutions designated by them consent upon the joint request of the employee and the employer. (2) The provisions of paragraph (1) shall apply analogously to a self-employed person who ordinarily works in the territory of the Federal Republic of Germany when that person works temporarily in the territory of the Republic of Korea. (3) To a self-employed person who ordinarily resides in the territory of the Republic of Korea, the provisions of paragraph (1) shall apply analogously when that person works temporarily in the territory of the Federal Republic of Germany.
| 한국 회사 소속을 유지한 채 파견employment_home · span [61, 137] | MATCH |
|---|---|
| 일하러 가는 것 (취업·파견)purpose_work · span [186, 263] | MATCH |
| 파견 기간이 24개월 이하months_lte_24 · span [395, 439] | MATCH |
| 원문 sha256 대조623a6da596ed037946b22f8a8d54d3da… | MATCH |
이 대조는 처음부터 통과한 것이 아니다
조약 정본에서 AI 가 제안한 조건은 3건이었고, 첫 실행에서 스팬 검증을 통과한 것은 3건 중 1건이었다.
원인은 보관하던 원문이 조문 전문이 아니라 발췌였다는 것이다. AI 가 제공된 텍스트가 아니라 사전 지식에서 인용했고, 그 인용은 원문 어느 인덱스에도 없었으므로 폐기됐다.
정본 전문을 확보해 교체한 뒤 3건 중 3건이 통과했다. 폐기 이력은 지우지 않고 supersedes 에 남겼다.
스팬 검증은 treaty-span-verified 등급의 규칙에만 적용된다. 현재 5개 규칙 중 2개(파견 아웃바운드·인바운드)가 여기 해당한다. 나머지 3개는 조약이 아니라 공식기관 안내가 근거이므로 스팬 검증 대상이 아니며, 화면에서 근거 등급을 분리해 표시한다.
03근거
숫자마다 어떤 연산에서 나왔는지 적는다.
2,829 에서 4 까지 좁혀지는 각 단계에 어떤 필터가 걸렸는지가 아래에 있다. 원본 파일과 해시를 같이 적는 이유는, 우리가 센 파일과 검증하는 사람이 여는 파일이 같은 파일인지 확인할 수 있어야 하기 때문이다. 추정이나 보간으로 채운 값은 없다.
2,829
rows(bilateral_treaties.csv)
외교부 양자조약 현황 전체 · 227개 국가·국제기구
124
filter 체결대상국가 == "독일"
독일과 맺은 양자조약 전부
6
filter 분야 ∈ {사회보장, 영사·사증, 운전면허상호인정}
사회보장 2 · 영사/사증 4 · 운전면허상호인정 0
4
rules where country == "DE"
앱에 배포된 판정 규칙 — 조약 4건이 아니라 카드 4장
네 숫자는 저장소 루트에서 명령 네 줄로 그대로 재현된다 — 2,829 · 227 · 124 · 6
$ tail -n +2 public/data/bilateral_treaties.csv | wc -l 2829 $ cut -d, -f1 public/data/bilateral_treaties.csv | tail -n +2 | sort -u | wc -l 227 $ awk -F, 'NR>1 && $1=="독일"' public/data/bilateral_treaties.csv | wc -l 124 $ awk -F, 'NR>1 && $1=="독일" && ($2=="사회보장"||$2=="영사/사증"||$2=="운전면허상호인정")' \ public/data/bilateral_treaties.csv | cut -d, -f2 | sort | uniq -c 2 사회보장 4 영사/사증 # 운전면허상호인정 행은 출력에 없다 — 독일에 해당 조약이 없다 $ sha256sum public/data/bilateral_treaties.csv 10bcd1f34b281f8061414360db915f38014b3fd4e43207a629c32b1beabec27b
집계 결과
| 외교부 양자조약 현황 (전체) | 2,829건 |
|---|---|
| 체결대상 국가·국제기구 | 227개 |
| 체결대상국가 = 독일 | 124건 |
| PACT 도메인 분야 (독일) | 6건 |
| 독일 × 운전면허 상호인정 | 0건 |
| 사회보장협정 — 조약 원문으로 대조를 마친 국가 | 41 / 43 |
| 외교부 사증면제협정 체결현황 (행) | 154행 |
| 외교부 국가별 운전면허 상호인정 현황 (행) | 58행 |
사회보장협정 41 / 43
외교부 공식 43개국 중 41개국은 조약 원문으로 대조를 마쳤다. 나머지 2개국은 원문 대조가 끝나지 않아 이 숫자에 넣지 않았다. 세지 못한 것은 세지 못했다고 적는다.
운전면허 — 독일은 목록에 없다
외교부 운전면허 상호인정 데이터 27개국, 양자조약 운전면허 분야 20개국 어디에도 독일이 없다. 독일에서 한국 면허가 인정되는 근거는 협정이 아니라 독일 국내법(FeV 별표11)이다. 그래서 이 항목은 협정 기반 권리가 아니라 공식 확인사항으로 강등해 표시하고, 스팬 검증 대상이 아니라는 것을 화면에서 밝힌다. 데이터에 없는 것을 있다고 말하지 않는 쪽이 이 제품이 파는 값이다.
원본은 앱과 함께 배포된다. public/data/manifest.json 에 파일별 행 수 · sha256 · 수집일이 들어 있고, 데이터 기준일은 2026-08-03 다. 오픈API 응답은 스냅샷으로 고정해 같은 질의에 같은 결과가 나오도록 했다.
04전수 대조
테스트 몇 개를 통과했다가 아니라, 전 조합에서 이렇게 동작한다.
규칙 엔진이 순수 함수이고 입력 공간이 유한해서 전수 실행이 가능하다. 앱이 실제로 쓰는 코드를 꺼내, 경진대회 제출본에서 동결한 참조 구현과 같은 입력으로 돌려 판정을 대조했다. 표본이 아니라 전부다.
60,480
입력 조합
3 × 3 × 120 × 14 × 2 × 2
302,400
전수 판정 실행
입력 60,480 × 규칙 파일 5
0
참조 구현과 불일치
verdict · 조건 단위 ok 까지
3 / 3
경계값에서 판정이 갈림
90일 · 6개월 · 24개월
동등성 테스트 — 파일 1개, 테스트 12개 전부 통과. 참조 구현과 불일치 0건
$ npx vitest run test/engine.equivalence.test.ts Test Files 1 passed (1) Tests 12 passed (12) Duration 488ms
경계값에서 실제로 갈리는가
전 조합이 같은 결과를 내는 규칙도 전수 대조는 통과한다. 그래서 규칙이 값을 바꾸는 지점에서 판정이 실제로 달라지는지 따로 확인한다.
| 규칙 | 경계 | 이전 | 이후 |
|---|---|---|---|
| de.ssa.dispatch협정 제7조 파견 24개월 | months = 24 → 25 | applicable | official_check |
| de.license한국 면허 인정기간 6개월 | months = 6 → 7 | not_applicable | applicable |
| de.entry사증면제 체류 상한 90일 | days = 90 → 91 | not_applicable | applicable |
엔진 불변식
- 결정성
- 같은 입력을 두 번 넣으면 직렬화한 결과가 바이트까지 같다.
- 재현성
- evaluateAll 은 규칙 id 순으로 고정 정렬한다. 카드 순서가 실행마다 바뀌지 않는다.
- 조용한 실패 금지
- 알 수 없는 연산자를 만나면 통과시키지 않고 던진다. 판정이 소리 없이 사라지는 경로를 없앴다.
- 근거 필수
- 모든 조건에 basis 가 있어야 한다. 없으면 테스트가 실패하고 규칙은 배포되지 않는다.
참조 구현(test/reference/engine.reference.mjs)은 제출본에서 그대로 가져온 동결 사본이며 수정하지 않는다. 수정하는 순간 이 대조는 의미를 잃는다. 규칙 파일 6개 중 1개(v1.1.0)는 회귀 비교 전용이라 배포 목록에 넣지 않으므로, 앱에 실리는 규칙은 5개다.
05자기일관성
같은 조문을 다섯 번 읽혀, 매번 같게 읽는지 측정했다.
AI 는 판정하지 않는다. 조약 원문에서 규칙 초안을 뽑는 단계에만 쓰인다. 그 단계를 같은 조문에 K=5회 독립 호출해 조건별 합의율로 재고, 임계값에 못 미치면 기권해 공식 확인으로 강등한다. 기억이 아니라 원문을 읽는지, 없는 규정을 지어내지 않는지를 적대적으로 시험했다.
5 / 5
핵심 조항 합의
months ≤ 24 · 5회 모두 동일
0 / 5
기억 오염
24→36 교란본에서 옛 값(24) 출력
0 / 5
부재 환각
없는 기간 규정을 날조
0%
스팬 검증 오류율
τ ≥ 0.4 · 합의 임계값 적용 시
| 케이스 | 무엇을 보는가 | 결과 (K=5) |
|---|---|---|
| art7-baseline | 핵심 조항을 매번 같게 뽑는가 | months ≤ 24 · 5/5 |
| art7-perturbed-36 | 24→36 교란, 기억이 아니라 원문을 읽는가 | months ≤ 36 · 5/5, 옛 값 24 · 0/5 |
| art2-no-duration | 기간 규정이 없는 조문에서 날조하는가 | months 조건 · 0/5 |
이 페이지의 다른 증거는 결정적이라 바이트까지 재현되지만, 이 하나는 측정값이다 — LLM 출력이라 실행마다 표본이 다르므로 K회 독립 실행의 합의율로 본다. 산출물은 제출 평가 패키지의 out/consistency.json (provider: anthropic · 2026-08-05)에 기록돼 있고, 정답 세트(eval/gold.json)를 사람이 원문 대조로 검토한 뒤에야 이 수치를 쓴다. 임계값을 완전히 풀면(τ=0.2) 교란본에서 스팬 검증 실패가 1건 남는데, 이는 합의 임계값이 놓친 불량 조건을 기계적 스팬 검증이 잡아내는 이중 방어의 실증이다. 측정 대상은 ‘AI 가 원문을 일관되게 읽는가’이지 규칙의 법적 타당성이 아니며, 판정 경로에는 여전히 LLM 호출이 0건이다.
06배포된 규칙
독일 1개국. 규칙 5개. 제3자 검수 전.
시제품이다. 커버리지를 크게 보이게 만드는 대신 정확히 적는다. 아래 표는 앱에 실제로 번들된 규칙 파일에서 그대로 읽어 온 것이며, 화면에 뜨는 문구와 같은 값을 쓴다.
| 규칙 | 근거 등급 | 판정 조건 | 채널 |
|---|---|---|---|
| de.apostille v1.0.0아포스티유 — 공문서 국제 인증한국 서류를 현지에 낼 예정이면 아포스티유 대상이다. 개인의 체류조건이 아니라 서류의 성격으로 판정한다. | official-guidance공식기관 안내 · 스팬 검증 대상 아님 |
| prototype |
| de.entry v1.0.0장기체류·취업 허가체류 예정일수가 90일을 넘으면 사증면제 범위 밖이다. 필요한 체류허가의 종류는 목적과 개인 사정에 따라 달라져 앱이 정하지 않고 주한독일대사관 확인으로 넘긴다. | official-guidance공식기관 안내 · 스팬 검증 대상 아님 |
| prototype |
| de.license v1.0.0한국 운전면허 인정기간 · 독일 면허 전환한국 면허 인정기간과 독일 면허 전환. 조약이 아니라 독일 국내법이 근거라 근거 등급을 분리해 표시한다. | official-guidance공식기관 안내 · 스팬 검증 대상 아님 |
| prototype |
| de.ssa.dispatch v1.0.0한·독 사회보장협정 제7조 (파견에 있어서의 당연가입)한국 회사 소속을 유지한 채 24개월 이하로 파견되면 독일 연금 당연가입에서 벗어날 수 있다. 조약 원문에서 조건 3개를 추출해 스팬 검증까지 통과한 유일한 규칙이다. | treaty-span-verified조약 원문 · 스팬 검증 통과 |
| prototype |
| kr.ssa.dispatch.inbound v1.0.0한·독 사회보장협정 제7조 (한국 파견 외국인의 국민연금 적용 제외)한·독 사회보장협정 제7조 (파견에 있어서의 당연가입) — 방향 중립 조문 | treaty-span-verified조약 원문 · 스팬 검증 통과 |
| prototype |
제3자 전문가 검수 전이다
규칙 5개는 모두 제안자 자체 원문 대조를 거친 prototype 채널이다. 작성자와 검수자가 같으므로 독립 검수로 세지 않고, production 채널은 배포 게이트에서 막혀 있다. 앱 화면에도 같은 문구가 그대로 뜬다. 최종 판단은 국민연금공단 · 재외공관 · 현지 관할기관이 수행한다.
일부러 하지 않는 것
- 금액을 산정하지 않는다
- 급여·부담률·환율은 개인마다 다르고 앱이 검증할 수 없는 값이다. 절감액을 계산해 보여주지 않는다.
- 비자 종류를 정하지 않는다
- 90일 초과 체류가 필요하다는 사실까지만 판정하고, 어떤 체류허가인지는 재외공관 확인으로 넘긴다.
- 24개월 초과 계속적용은 판정하지 않는다
- 양국 권한있는 당국의 동의와 근로자·사용자 공동요청이 요건이다. 사용자 입력만으로는 확인할 수 없는 외부 사실이다.
- 쉥겐 누적 체류를 보지 않는다
- 이 규칙은 단일 연속 체류만 계산한다. 직전 쉥겐 체류 이력이 있으면 별도 확인이 필요하다.
- 건강·실업·산재보험은 다루지 않는다
- 협정 제2조상 이 협정은 연금제도에만 적용된다. 다른 보험은 적용 범위 밖이다.
- 면허 기한의 기산점을 분명히 한다
- 한국 면허 인정기간은 출국일이 아니라 독일 내 통상거소 설정일부터다. 앱은 그 날짜(move_in)를 기준으로 계산하고, 최종 인정 여부는 관할 면허청 확인으로 넘긴다.
확장은 새 국가의 원문을 넣고 같은 파이프라인(구조화 → 스팬 검증 → 검수 서명 → 배포 게이트)을 다시 도는 것이다. 규칙은 코드가 아니라 데이터이므로 국가를 늘리는 데 엔진을 고칠 필요는 없다. 다음 후보는 사회보장협정을 조약 원문으로 대조한 41개국 안에서 고른다.