Korean Case Law → AKN Judgment

This document fixes the first case-law emission contract. It is implemented in src/kr2akn/case/ and validated against the OASIS akomantoso30.xsd.

1. Input

Two Korean Law Open Data targets are supported:

Target Root Main fields
prec PrecService 판례정보일련번호, 사건번호, 사건명, 법원명, 선고일자, 사건종류명, 판결유형, 판시사항, 판결요지, 판례내용, 참조조문, 참조판례
detc DetcService 헌재결정례일련번호, 사건번호, 사건명, 종국일자, 사건종류명, 결정요지, 전문, 참조조문, 참조판례, 심판대상조문

Raw snapshots:

data/raw/prec/<case_id>/<timestamp>/response.xml + meta.json
data/raw/detc/<case_id>/<timestamp>/response.xml + meta.json

2. Intermediate model

CaseDocument:

Field Notes
meta CaseMeta
issues 판시사항
summary 판결요지 / 결정요지
full_text 판례내용 / 전문
ref_articles 참조조문
ref_cases 참조판례
target_articles 심판대상조문 (detc)
sections[] CaseSection(kind, heading, text)
refs[] CaseRef(kind, raw, href, ...)
case_header packed 43/64-bit header

Section mapping

Marker / field AKN section
판시사항 arguments (heading=판시사항)
판결요지 / 결정요지 background (heading=판결요지)
【주문】 / [주문] decision
【이유】 / [이유] motivation
【원고...】, 【피고...】, 【원심판결】, 【청구인】 introduction
【상고이유】, 【항소이유】 arguments
unknown marker background
no markers motivation

The XSD's judgmentBodyType is a sequence of judgmentBlock groups (minOccurs=1 maxOccurs=unbounded), so multiple sections are valid.

3. 43-bit case header

[63:57] court_id   7b
[56:50] year       7b  (year - 1947)
[49:41] case_code  9b
[40:21] serial_no  20b
[20:9]  N          12b
[8:0]   M          9b
  • Identity = header >> 21 (caseId43).
  • year: 1947–2074. Two-digit years use the deterministic rule 47..99 → 1900+yy, 00..46 → 2000+yy.
  • serial_no: 1..1,048,575.
  • N: sentence count (capped at 4,095). The splitter protects citation dates (2023. 5. 18.), decimals, common Latin abbreviations (No., pp., cf., ...), and ellipses, and strips line-leading list markers (1., 가., ①) before counting. Terminal punctuation inside curly/corner quotes (“...”, 「...」) or a straight double-quoted span does not split the surrounding sentence. It counts all emitted sections (판시사항, 판결요지, 본문), not only full_text.
  • M: reference count (capped at 511). It counts all emitted passiveRef and jurisprudence entries.
  • Overflow is lossless in kr:caseHeader:
    • sentenceCountTotal / sentenceOverflow / sentenceBlockCount;
    • referenceCountTotal / referenceOverflow.
  • The packed values are emitted in meta/proprietary/kr:caseHeader together with the raw strings.

Registries

  • src/kr2akn/registries/courts.v1.json — frozen ("frozen": true, 2026-10-29).
  • src/kr2akn/registries/case_codes.v1.json — frozen ("frozen": true, 2026-10-29), 345 codes.

The court registry was reconciled against the published court jurisdiction list. IDs are append-only and must never be renumbered. Retired IDs 53 (김해지원), 58 (여수지원), 73 (광주지원), and 80 (김제지원) were not current courts and are reserved; they must not be reused. 시·군법원 and 등기소 are out of scope.

  • court_id is a dense 7-bit index (0–127), not the “top 2 bits = tier” encoding from Amendment 1. The 32-courts-per-tier limit cannot represent all Korean district courts and their branch courts. Tier is still available via the registry (tier field) for a 128-bit mask.
  • The registry covers the Supreme Court, Constitutional Court, high courts, Patent Court, district courts, their branch courts, family courts and their branch courts, administrative courts, and rehabilitation courts. New courts are appended without renumbering existing IDs.
  • case_code is a dense 9-bit ordinal (0–344) assigned in the published case-code list order. Existing IDs are never renumbered; new codes receive the next unused ID. Treat the value as opaque.
  • Only the Korean 사건부호 (가단, 가합, 카합, 헌마, ...) is stored. The court's three-digit code and the law.go.kr six-digit case-type codes are deliberately not stored: the three-digit list does not cover Constitutional Court cases and does not fit 9 bits, and the law.go.kr code is a case-level type rather than a prefix code. See docs/case-codes.md.
  • CaseCodeRegistry is a flat map keyed by the Korean code. resolve(code) looks it up directly; there is no category/index composition.
  • kr:caseHeader records caseCode (the 9-bit ordinal) and caseCodeRaw (the Korean prefix). The full case number remains in FRBRWork/FRBRnumber and FRBRalias name="caseNo".
  • kr2akn emit-case is strict by default: an unknown court or case code raises a parse_error. Use --allow-unknown to fall back to 127/511 and set unknownCourt/unknownCode in kr:caseHeader.
  • kr:caseHeader records registryVersion, courtRegistryFrozen, codeRegistryFrozen, and registryFrozen (true only when both are frozen) so a consumer can tell which registry revision produced the packed value.

4. AKN skeleton

<akomaNtoso ...>
  <judgment name="대법원 2025다217842">
    <meta>
      <identification source="kr2akn">...</identification>
      <classification source="kr2akn">...</classification>
      <references source="kr2akn">
        <passiveRef href="urn:kr:law-name:..." showAs="..." eId="ref_1"/>
        <jurisprudence href="urn:kr:case:..." showAs="..." eId="ref_2"/>
      </references>
      <proprietary source="kr2akn">
        <kr:caseMeta .../>
        <kr:caseHeader .../>
      </proprietary>
    </meta>
    <header>
      <court><p>대법원</p></court>
      <p>2025다217842</p>
      <p>손해배상(기)</p>
      <p>2026-08-13</p>
    </header>
    <judgmentBody>
      <arguments eId="arguments_1"><heading>판시사항</heading><p>...</p></arguments>
      <background eId="background_2"><heading>판결요지</heading><p>...</p></background>
      <introduction eId="introduction_3"><p>...</p></introduction>
      <decision eId="decision_4"><p>...</p></decision>
      <motivation eId="motivation_5"><p>...</p></motivation>
    </judgmentBody>
  </judgment>
</akomaNtoso>
  • references must appear before proprietary in meta (XSD order).
  • passiveRef/jurisprudence allow showAs and eId.
  • ref (inline statute citation) does not allow showAs.
  • The decision date is promoted to meta/lifecycle + meta/temporalData, and judgmentBody carries period="#period_YYYYMMDD".

5. Case reference resolution

참조판례 is parsed into one CaseRef per case number. Korean citations that share a serial prefix are expanded:

65다1311, 1312       -> 65다1311 + 65다1312
2002다40098, 40104   -> 2002다40098 + 2002다40104

At emit time, CaseEmitter accepts a CaseIndex built from:

  • judgments already emitted under data/akn/prec and data/akn/detc;
  • the current batch of parsed cases (so references inside one --all run resolve too).

A resolved reference is emitted as the target judgment's FRBR Work URI:

<jurisprudence href="/akn/kr/judgment/42417199123"
    showAs="대법원 2021. 10. 14. 선고 2018다279217 판결" eId="ref_3"/>

If the case has not been emitted yet, the reference stays urn:kr:case:{percent-encoded case no}. The same optional index is passed to StatuteEmitter, so inline case citations in statutes can resolve to the same Work URI.

6. CLI

kr2akn fetch-case --case-id 624945 --target prec --data-dir ../data --oc "$LAWGO_OC"
kr2akn emit-case  --case-id 624945 --target prec --data-dir ../data --out-dir ../data/normalized --validate
kr2akn fetch-case --case-id 177507 --target detc --data-dir ../data --oc "$LAWGO_OC"
kr2akn emit-case  --case-id 177507 --target detc --data-dir ../data --out-dir ../data/normalized --validate

emit-case --all --target prec|detc processes every raw case under data/raw/<target>.

7. Validation status (2026-10-29)

  • prec/624945 대법원 2025다217842 — valid
  • prec/624943 대법원 2026다202771 — valid
  • detc/177507 헌법재판소 2022헌마1312 — valid
  • detc/57476 헌법재판소 2017헌바323 — valid (empty body fallback)

8. Known limitations

  1. The court and case-code registries are frozen. Strict mode protects against silently encoding a new court or code; new codes must be appended with an unused 9-bit ID.
  2. N is a deterministic rule-based sentence count, not a linguistic legal sentence segmenter. It handles citation dates, list markers, common abbreviations, ellipses, and punctuation inside quotation marks. A quoted sentence that ends with the period inside the closing quote can still merge with the following sentence.
  3. detc records with no 전문 emit an empty motivation paragraph so the judgmentBody remains XSD-valid.
  4. Case references resolve only when the target judgment is present in the runtime case index. Otherwise the stable urn:kr:case:... fallback is emitted.
  5. references does not yet distinguish active/passive citation semantics beyond the passiveRef/jurisprudence split.

9. Roundtrip

kr2akn akn2kr decodes an emitted judgment back into CaseDocument. kr:caseMeta and kr:caseHeader carry the Korean fields, while references keeps kr:caseNo, kr:court, kr:decisionDate, and kr:decisionKind so a decoded reference re-emits identically. kr2akn roundtrip checks canonical equality for every emitted judgment. See docs/roundtrip.md.