The Crosswalk You Cannot Finish
Yesterday’s piece ended on a promise. Having measured what happens when copies of the same judgment disagree, we wrote that most of the apparent disagreement was vocabulary rather than contradiction, and that this “needs a crosswalk, written once”. That is the kind of sentence vendors use to make a defect sound like a chore.
So today we wrote it. We enumerated every distinct value in the procedure field of our own PRC judgment corpus and tested each one against a reference the data carries internally: the procedure code inside the case number on the same record. The result is not the tidy lookup table the word implies. It is 405 rows in four mutually incompatible encodings, of which 104 can be written with confidence and 26 cannot be written at all — and those 26 cover more than a fifth of the records. The conclusion is not that our crosswalk is big. It is that the crosswalk is the wrong instrument, and the field should be derived rather than reconciled.
procedure value is already populated, 80.15 per cent of the 21,393,940 records whose procedure value is blank. The cause is correlated missingness — blank case numbers are 305 times denser in the blank slice — and it applies to the rule in this article too, which we have not yet re-run conditionally. Read any figure below as an overall rate, not as the rate on the records that need the fallback. See The Fallback Is Thinnest Exactly Where You Need It.What is actually in the field
The procedure field is supposed to say what kind of proceeding produced the document: first instance, appeal, retrial review, enforcement. Across our corpus it holds 405 distinct values, and sorting them by shape rather than meaning already tells you the crosswalk will not be a rename.
| Encoding | Distinct values | Share of a 10,000-record random sample | Example, glossed |
|---|---|---|---|
| Chinese phrase | 295 | 61.5% | “civil first instance”, “enforcement implementation” |
| Short numeric code | 49 | 24.3% | 1, 2, 3, 4 |
| Empty string | 1 | 13.9% | — |
| Four-digit code | 44 | 0.4% | 0301, 0302, 1001 |
| Neither | 16 | <0.05% | see below |
Three encodings and a hole. The phrase vocabulary and the four-digit code both distinguish civil first instance from criminal first instance; the short numeric code does not. That asymmetry decides most of what follows, because a crosswalk can only be written at the granularity of its coarsest side.
The sixteen values in the last row are the cheapest possible test of whether anyone has ever looked at this field. One is a fragment of JavaScript source — the eight characters ion(){$(, the tail of a function(){$( declaration — and it is the stored procedure value of 14,363 records. Another reads, in full, “1 = first instance”: the legend of the numeric code list, leaked into the data it was meant to explain, on 15 records. A third is the word “test”, on 31 records; four more are bare punctuation; five are criminal sentencing factors that belong to a different field.
Together the sixteen cover 14,515 records, so none of it is load-bearing. But the legend is worth keeping: it is the only documentation of the numeric scheme anywhere in our data, and we found it by accident while counting junk.
Which batch speaks which language
Encodings do not mix evenly. By ingest batch, the field is close to monolingual — with two instructive exceptions.
| Batch | Records | Phrase | Numeric | Four-digit | Empty | Distinct values |
|---|---|---|---|---|---|---|
| Batch 1 | 40,705,653 | 58.4% | — | — | 41.5% | 265 |
| Batch 2 | 39,341,140 | — | 100.0% | — | — | 13 |
| Batch 3 | 27,339,429 | 99.9% | — | — | 0.1% | 41 |
| Batch 4 | 8,291,857 | 100.0% | — | — | — | 114 |
| Batch 5 | 8,023,196 | 93.1% | — | 6.9% | — | 89 |
| Batch 6 | 4,826,358 | 94.0% | — | 6.0% | — | 79 |
| Batch 7 | 4,414,931 | — | — | — | 100.0% | 1 |
Batch 2 is the whole of the numeric scheme: 39,341,140 records, thirteen values, no phrases. Batch 7 — the same batch whose court field contradicts its own case numbers on a third of testable records — has an empty procedure on every record. Batches 5 and 6 are internally bilingual, carrying phrases on 93 to 94 per cent of records and four-digit codes on the rest, which kills the convenient assumption that vocabulary can be assigned per batch. It has to be assigned per record.
The crosswalk, and how much of it can be written
To test a value without trusting any other stored field, we used the case number. A PRC case number issued under the 2016 numbering reform carries an explicit procedure code — MIN CHU for civil first instance, MIN ZHONG for civil appeal, ZHI for enforcement, XING GENG for a sentence adjustment. We have used the same string as a province validator; here it validates the procedure. For each of the 405 values we drew up to 500 records at random and asked how concentrated the parsed codes were.
| Tier | Meaning | Values | Share of a 10,000-record random sample |
|---|---|---|---|
| A — exact | Resolves to one case-number code on ≥95% of testable records | 104 | 28.3% |
| B — class only | Resolves to one procedural class, but not to one code | 29 | 33.5% |
| C — lossy | Dominant class between 80% and 95% | 18 | 16.2% |
| D — unmappable | No class reaches 80% | 26 | 22.0% |
| Too rare to test | Fewer than 30 testable records | 228 | <0.05% |
Read the two ends together. 228 of the 405 values — more than half the crosswalk’s rows — are too rare to verify, and together they cover just 1,835 records. 263 appear on 100 records or fewer; 110 appear exactly once. A crosswalk is priced by rows, a corpus by records, and those two numbers point in opposite directions: most of the writing effort goes to values that will never change an answer, which is exactly where a tired analyst guesses.
Tier A is also smaller than it looks, because it is mostly synonym folding. Its 104 values collapse onto only 44 distinct case-number codes, 24 of which are reached by more than one spelling. The sentence-adjustment code is reached by eleven values across three encodings; the special-procedure code by thirteen. Two values differing only in word order — “restore enforcement” and “enforcement restored” — carry 245,710 and 179,791 records and mean the same thing.
The four-digit code is the best-designed vocabulary in the corpus
It is also the rarest. The 44 four-digit values are structured — first two digits a case family, last two a procedure within it — and decoded against the case numbers of the records carrying them, the families come out clean.
| Prefix | Family | Example | Resolves to | Agreement |
|---|---|---|---|---|
01 | Jurisdiction | 0101 | criminal jurisdiction | 100% |
02 | Criminal | 0201 / 0202 | criminal first instance / appeal | 99% / 100% |
03 | Civil | 0301 / 0302 | civil first instance / appeal | 99% / 99% |
04 | Administrative | 0401 / 0402 | administrative first instance / appeal | 99% / 99% |
05 | State compensation | 0501 | compensation first instance | too rare |
08 | Judicial sanctions | 0801 | sanction review | 100% |
09 | Preservation | 0901 | property preservation | 100% |
10 | Enforcement | 1001 / 1005 | enforcement / enforcement objection | 77% / 83% |
11 | Bankruptcy | 1101 | bankruptcy petition | 66% |
This is a real code list, close to the official case-family taxonomy, and the only encoding here from which both the family and the procedure can be recovered without consulting anything else. It covers 843,268 records. The phrase vocabulary covers vastly more and reaches the same expressiveness only by convention, and only when the phrase is one of the verbose ones.
What the numeric scheme actually encodes
The leaked legend told us 1 means first instance. The case numbers confirm it and add what the legend omitted: among records carrying 1 whose case number is testable, 96 per cent are first-instance proceedings, split across civil, criminal and administrative. 2 is appeal on 96 per cent, again across all three families. The numeric scheme is a clean one-axis vocabulary: it encodes the instance and says nothing about the case family.
That makes the crosswalk one-directional. A phrase always maps to a number; a number maps back only with a second field, and the field it needs — case type — is exactly the one that in this batch stores something else entirely. This is why 33.5 per cent of sampled records sit in tier B: not because the value is dirty, but because it is honestly coarser than the vocabulary you want to express it in.
Below the four codes that carry mass, the scheme falls apart quietly. 3 is a genuine ambiguity rather than an error: it covers both the review of a retrial application and the retrial itself, and no class reaches 80 per cent. The remaining 45 numeric values carry between one and 3,716 records each and come from a different batch with a different meaning again — there 5 is non-litigation administrative review on 94 per cent of records and 7 is sentence adjustment on 99 per cent. Two numeric schemes, no version marker, one field.
The values that cannot be mapped at all
| Value, glossed | Encoding | Records | Most common code | Dominant class |
|---|---|---|---|---|
| “enforcement implementation” | phrase | 22,798,071 | enforcement, 77% | enforcement, 89% (tier C) |
| (empty) | — | 21,393,940 | enforcement, 49% | enforcement, 54% |
4 | numeric | 9,641,805 | enforcement, 56% | enforcement, 77% |
| “other” | phrase | 2,561,414 | enforcement, 30% | enforcement, 32% |
| “civil adjudication supervision” | phrase | 374,414 | retrial review, 64% | retrial review, 64% |
| “non-litigation enforcement review” | phrase | 360,835 | admin. non-litigation review, 71% | 68% |
| “retrial” | phrase | 139,409 | retrial review, 42% | 49% |
The pattern is not randomness. Each of these is a true umbrella term: a word the source system used correctly for a group of proceedings the case-number vocabulary keeps apart. “Enforcement implementation” covers first, preservation and restored enforcement; “retrial” covers both reviewing a retrial application and conducting the retrial; 4 covers enforcement and sentence adjustment, both post-judgment work.
You cannot fix an umbrella term with a lookup table, and pretending otherwise is worse than leaving it alone: a row mapping “retrial” to the retrial-review code would be wrong on 51 per cent of the records it touches, silently, with no null to warn anyone. That is where a well-meaning normalisation pass does more damage than the mess it replaces.
The other field: correct, and still unusable
The companion field, caseType, fails differently. Checked against the case number on the same record it is right: agreement ran from 96.3 to 99.5 per cent across the four batches we tested. Its 32 values are nevertheless three word-lists.
- The long form — the official eleven-category taxonomy: “civil case”, “enforcement case”, “non-litigation preservation review case”, and so on.
- The short form — six values: civil, criminal, administrative, enforcement, compensation, other. It cannot express eight of the eleven categories the long form names.
- The document type — in one batch of 39,341,140 records the field holds judgment, ruling, mediation, notice or decision instead of a case category. A query for civil cases returns nothing from that batch, and not because it has no civil cases.
Then the trap. The short form’s “other” value carries 5,888,436 records, which reads as the residual bucket for categories the short vocabulary cannot name. We drew 1,000 at random and read the code out of each record’s own case number: 59.3 per cent are ordinary civil cases, mostly civil first instance — a category the short vocabulary names perfectly well. 17.3 per cent are enforcement, 3.6 per cent criminal; only 17.9 per cent had no readable case number.
So “other” is not a category. It is a missing-value marker that got a category’s name, and any evaluation filtering it out to tidy a distribution discards millions of ordinary civil judgments while believing it removed noise.
What to do instead: derive, don’t reconcile
The stored procedure value is a compressed, versioned, occasionally corrupted account of something the record already states exactly — in a string every court is obliged to get right, because it is how the court finds its own file. So stop reconciling the field. Read the case number, and use the field only where the case number cannot be read.
| Route | Share of a 10,000-record random sample |
|---|---|
| A. Case number yields a procedural class | 96.9% |
| B. Stored procedure value maps to a class (tiers A + B) | 61.8% |
| Either route | 97.3% |
| Residual: neither route | 2.72% |
Two checks make that table trustworthy rather than merely convenient. Where both routes fire and the stored value is tier A, they disagree on 0.46 per cent of records, so the crosswalk is not fighting the case number where it applies. And the residual is diagnosable: 203 of the 272 residual records have no case number at all, and most of the rest are real case numbers that a single-case regex cannot read — consolidated enforcement orders covering a range of dockets, plus a few records where a fragment of stylesheet markup landed in the case-number field, the same scraper failure that produced the JavaScript above.
One implementation detail is worth more than it sounds. A parser expecting a case number to end in digits reads 90.4 per cent of our sample; teaching it the sub-docket suffix Chinese case numbers may carry — the equivalent of “no. 490, part three”, present on 6.84 per cent of records — raises that to 97.2 per cent. Seven points of coverage behind one regex, and a vendor who has not fixed it will report a lower ceiling for this technique than it has.
The pre-2016 half needs a second parser, and here honesty costs something. Old-format case numbers do encode the instance, but through court-local abbreviations rather than a national code list: in one 800-record sample we saw the same civil-first-instance idea written dozens of ways, each prefixed by a court’s own contraction of its name. 97.7 per cent of those prefixes still yielded an instance, but the vocabulary is open-ended by construction, so this parser is never finished. It is a maintained asset, not a solved problem.
The protocol, compressed
- Derive procedure and case family from the case number, with one parser per numbering era and a sub-docket-suffix rule.
- Use the stored value only as fallback, and only for values in tiers A and B.
- Never map a tier-C or tier-D value. Emit a null and count it — an umbrella term mapped to its most common member is the error class that leaves no trace.
- Treat “other” as missing, not as a category, in any vocabulary where you have not proved otherwise on a random sample.
- Publish the residual. Ours is 2.72 per cent of a 10,000-record random sample, and its composition, not its size, is what a buyer should ask about.
A measurement note that changed twelve verdicts
Our first pass took the first 500 records the index returned for each value. That is not a sample; it is a walk through whichever segment happens to be first, and in a corpus assembled from batches, segment order correlates with batch. Re-running with an explicit random seed changed the tier of twelve of the 405 values, one of them completely: “non-litigation enforcement review” looked like a clean 89 per cent match to property preservation in the ordered sample, and was 71 per cent administrative non-litigation review — a different family — in the random one. Publishing the first pass would have meant a crosswalk row wrong for the plurality of its records.
This is the third time in ten days that an ordered read produced a plausible, publishable, wrong number here. The rule now applies without exception: every per-value composition figure is drawn with a stated random seed, and every ratio is computed with the total-hits cap disabled. As a cross-check, the shape shares measured by aggregation over every record (61.6 / 24.6 / 13.3 / 0.5 per cent) and over the 10,000-record random sample (61.5 / 24.3 / 13.9 / 0.4) agree to within half a point.
What we are not claiming
We measured no other corpus, so nothing here ranks anyone against anyone; every defect described is ours. The case number is a strong validator, not an oracle: it records the procedure the issuing court assigned, so a mis-docketed matter carries the error through, and it cannot check a cause of action at all. Tier assignments are sample-based, so the 95 per cent boundary will move a handful of borderline values under a different seed — which is why we publish the boundary and not only the verdict. And we have changed nothing: normalising this field would alter results for anyone already joined against current values, so it belongs in a change log with notice, not a quiet overwrite. Today’s output is a measurement and a protocol, not a migration.
For anyone evaluating a Chinese case law corpus, including ours, this reduces to four questions that are cheap to ask and impossible to answer vaguely. How many distinct values does your procedure field hold, in how many encodings? Which are umbrella terms, and what do you emit for those? Does your case-type field ever hold a document type instead? And what fraction of records can you assign a proceeding to without trusting the stored field at all? We have answered all four on our own data, failures included.
Ask us the four questions.
SinoVerdict licenses PRC judgment data to teams building legal AI — bulk delivery, a REST API and an MCP endpoint over a 160M+ record corpus, English-indexed, with every record stamped with the batch it came from and the known defects written down before anything is signed. Records carry the court’s own case number as a stable identifier, which is what makes the derivation above runnable by you rather than only by us. Write to chenjiaxin@wenshucha.com or use the form.
Request trial accessFrequently asked questions
In ours, 405. They are not 405 variants of one vocabulary. They fall into four encodings that do not share a granularity: 295 Chinese phrases, 49 short numeric codes, 44 four-digit codes and one empty string, plus 16 values that are neither, including a fragment of JavaScript source that appears on 14,363 records. In a random sample of 10,000 records drawn on 8 September 2026, 61.5 per cent carried a phrase, 24.3 per cent a short numeric code, 13.9 per cent an empty string and 0.4 per cent a four-digit code. The distinct-value count is dominated by rarities: 263 of the 405 values appear on 100 records or fewer, and 110 appear exactly once.
Partially, and the honest answer has three tiers. Validating every value against the procedure code carried inside the case number on the same record, 104 of the 405 values resolve to exactly one case-number code, and those 104 fold onto only 44 distinct codes, so most of the crosswalk is synonym folding. Another 29 resolve to a procedural class but not to a single code: the numeric value 1 is first instance on 96 per cent of testable records, but it does not say civil, criminal or administrative, so it cannot be inverted back to the phrase vocabulary. 18 are lossy at the class level and 26 resolve to nothing at all. Weighted by records, in a 10,000-record random sample those tiers cover 28.3, 33.5, 16.2 and 22.0 per cent.
Because its problem is vocabulary, not correctness. Checked against the case number on the same record, case type agreed on 96.3 to 99.5 per cent of testable records across the four batches we tested on 8 September 2026. But the field speaks three word-lists: the official eleven-category long form, a six-value short form, and, in one batch of 39,341,140 records, the document type rather than the case category, so that batch says ruling or judgment where every other batch says civil case or criminal case. A filter written against one word-list silently returns nothing from batches that speak another.
Not in ours. The short case-type vocabulary has an 'other' value carried by 5,888,436 records. We drew a random sample of 1,000 of them and read the procedure code out of each record’s own case number: 59.3 per cent are ordinary civil cases, most of them civil first instance, 17.3 per cent are enforcement and 3.6 per cent criminal. Only 17.9 per cent had no readable case number. That value is not a residual category; it is a missing-value marker wearing a category’s clothes, and excluding it drops millions of ordinary civil judgments without warning.
Derive the field instead of crosswalking it. A PRC case number issued after the 2016 reform contains a procedure code directly, and pre-2016 numbers encode the instance in a court-local abbreviation. In a 10,000-record random sample taken on 8 September 2026, the case number yielded a procedural class on 96.9 per cent of records; the stored procedure value yielded one on 61.8 per cent. Using the case number first and the stored value only as a fallback covered 97.3 per cent, leaving a residual of 2.72 per cent, of which 203 of 272 records had no case number at all. Where both routes fire and the stored value maps to exactly one code, they disagree on 0.46 per cent. Measured 11 September 2026, that overall rate splits by need: a cruder nine-code version of the same derivation reads 95.36 per cent of the records whose stored procedure value is populated and 80.15 per cent of those where it is blank, because blank case numbers are 305 times denser in the blank slice.