Buyer’s question

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.

Scope, stated once. All figures were taken on 8 September 2026 against our own index. Value lists and per-value record counts come from aggregations that read every matching record with the total-hits cap disabled. Every per-value composition figure comes from a random sample of up to 500 records for that value, drawn with a stated random seed, not from the first records the index happened to return — see the measurement note near the end, which explains why that distinction changed twelve of our own verdicts. Corpus-level shares are stated as shares of a 10,000-record random sample (four seeds, 2,500 each) and are labelled as such; we publish counts within named slices rather than corpus-wide totals. Nothing here is a claim about any other provider’s data, because we measured none. Case numbers identify courts and dockets, not people. Informational content, not legal advice.
Update, 12 September 2026. The coverage figures below are measured on a whole-corpus denominator, and a buyer whose records are missing the stored field will not experience them. On 11 September 2026 we re-measured a deliberately cruder nine-code version of the same derivation and found it splits: 95.36 per cent of the records whose 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.

EncodingDistinct valuesShare of a 10,000-record random sampleExample, glossed
Chinese phrase29561.5%“civil first instance”, “enforcement implementation”
Short numeric code4924.3%1, 2, 3, 4
Empty string113.9%—
Four-digit code440.4%0301, 0302, 1001
Neither16<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.

BatchRecordsPhraseNumericFour-digitEmptyDistinct values
Batch 140,705,65358.4%——41.5%265
Batch 239,341,140—100.0%——13
Batch 327,339,42999.9%——0.1%41
Batch 48,291,857100.0%———114
Batch 58,023,19693.1%—6.9%—89
Batch 64,826,35894.0%—6.0%—79
Batch 74,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.

TierMeaningValuesShare of a 10,000-record random sample
A — exactResolves to one case-number code on ≥95% of testable records10428.3%
B — class onlyResolves to one procedural class, but not to one code2933.5%
C — lossyDominant class between 80% and 95%1816.2%
D — unmappableNo class reaches 80%2622.0%
Too rare to testFewer than 30 testable records228<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.

PrefixFamilyExampleResolves toAgreement
01Jurisdiction0101criminal jurisdiction100%
02Criminal0201 / 0202criminal first instance / appeal99% / 100%
03Civil0301 / 0302civil first instance / appeal99% / 99%
04Administrative0401 / 0402administrative first instance / appeal99% / 99%
05State compensation0501compensation first instancetoo rare
08Judicial sanctions0801sanction review100%
09Preservation0901property preservation100%
10Enforcement1001 / 1005enforcement / enforcement objection77% / 83%
11Bankruptcy1101bankruptcy petition66%

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, glossedEncodingRecordsMost common codeDominant class
“enforcement implementation”phrase22,798,071enforcement, 77%enforcement, 89% (tier C)
(empty)—21,393,940enforcement, 49%enforcement, 54%
4numeric9,641,805enforcement, 56%enforcement, 77%
“other”phrase2,561,414enforcement, 30%enforcement, 32%
“civil adjudication supervision”phrase374,414retrial review, 64%retrial review, 64%
“non-litigation enforcement review”phrase360,835admin. non-litigation review, 71%68%
“retrial”phrase139,409retrial 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.

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.

RouteShare of a 10,000-record random sample
A. Case number yields a procedural class96.9%
B. Stored procedure value maps to a class (tiers A + B)61.8%
Either route97.3%
Residual: neither route2.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

  1. Derive procedure and case family from the case number, with one parser per numbering era and a sub-docket-suffix rule.
  2. Use the stored value only as fallback, and only for values in tiers A and B.
  3. 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.
  4. Treat “other” as missing, not as a category, in any vocabulary where you have not proved otherwise on a random sample.
  5. 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 access

Frequently asked questions

How many distinct values does the procedure field hold in a merged Chinese case law corpus?

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.

Can procedure codes from different ingest batches be mapped onto one another?

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.

Why does the case type field disagree less than the procedure field?

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.

Is an 'other' bucket in a legal metadata field safe to ignore?

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.

What is a safer way to normalise procedure metadata across merged batches?

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.