What a Knowledge Graph Found in 1,172 Cuban Charge Sheets That No Case File Could Show Alone
When a government charges more than a thousand political prisoners, does it charge them all the same way? We built a formal knowledge graph over Cuba's political-prisoner registry to find out. The answer is no. There are two distinct prosecutorial playbooks, and which one a prisoner receives is not predicted by their public visibility, IACHR protection status, or political affiliation. It is predicted, modestly but significantly, by the wave of protest during which they were arrested.
parseable charges
charges in corpus
recovered partition
fully reproducible
Cuba does not charge all protesters the same way. There are two distinct playbooks.
The Prisoners Defenders registry is the most comprehensive public record of Cuban political detention. We encoded every record into a formal knowledge graph and measured which charges tend to appear together across the entire population. Two clusters emerged. The government applies one set of charges to some protesters and a completely different charge to others. The two groups almost never overlap.
The natural assumption is wrong.
The obvious hypothesis: Cuba assigns the harsher playbook to prisoners who are more visible, more connected, or more politically organized. A well-known dissident gets the heavier charge. An unknown protester gets the lighter bundle. We tested this. It is wrong.
| Hypothesis we tested | Result | What the data showed |
|---|---|---|
| Well-documented prisoners get the heavier charge | NOT SUPPORTED | 28.6% vs 29.5% (n.s.) |
| IACHR-protected prisoners get the heavier charge | NOT SUPPORTED | 25.0% vs 30.5%, direction reversed |
| Politically affiliated prisoners get the heavier charge | NOT SUPPORTED | No significant association |
| Arrested during July 11 protests ? heavier charge | SIGNIFICANT | OR = 1.42, p = 0.027 |
The playbook a prisoner receives is not predicted by their public visibility, their IACHR protection status, or their political affiliation. It is predicted, modestly but significantly, by the wave of protest during which they were arrested. Charges applied not on the basis of individual conduct but on the basis of participation in disfavored political activity is what WGAD Category II describes.
We asked a blind algorithm to check our work. It found the same two playbooks.
A natural objection: maybe the analyst drew the boundary between the two playbooks in the wrong place. So we ran a separate test. We gave a standard grouping algorithm (Louvain community detection) the raw charge co-occurrence data and told it nothing about our hypothesis. Find the natural groups yourself.
Nine reproducible stages from raw HTML to formal submission.
Each stage is a separate Python script. Each script's output is saved and verifiable. Any reviewer can re-run any step against the same data snapshot and verify every number.
What the method measures, and what it does not.
This section exists for the technically skeptical reader. It states what the analysis actually measures, what its limits are, and how a reviewer can independently reproduce every step. Readers who accept the finding at face value can skip to §6.
Why co-occurrence is the right signal
A single prisoner's file tells you almost nothing about prosecutorial patterns. Any single charge is just a charge. Patterns become visible only by measuring which charges the state chooses to file together, across many cases, over and over. When the state pairs charge X with charge Y at a rate far above what independent selection would produce, that pairing is a prosecutorial decision. It is a fact about the state in its office of prosecutor, not about the underlying conduct of any one defendant.
We built a weighted undirected graph: nodes are charge types, edge weights are the number of prisoners charged with both. This graph is the primary analytical object. Every subsequent finding, from the two-playbook partition to the wave-based charge assignment, derives from measuring structure in this graph.
What Louvain and modularity actually measure
- Modularity Q
- A number between roughly −0.5 and 1 that measures how much denser the within-community edges are than would be expected under a random null model. Values above 0.3 are conventionally read as strong community structure. The recovered partition scored Q ? 0.47.
- Louvain algorithm
- A greedy modularity-maximizing partitioning algorithm (Blondel et al. 2008). Fast, well-studied, does not require the number of communities to be specified in advance. Standard tool for unsupervised community detection.
- Resolution ?
- A parameter controlling granularity: higher ? produces more, smaller communities; lower ? produces fewer, larger ones. We used the default (? = 1.0) and then swept ? from 0.3 to 3.0 as a stability check. The two-community partition was recovered at every resolution in the sweep, indicating the finding is not an artifact of parameter choice.
- Stability check
- Louvain is initialization-dependent. We ran it from 100 random seeds at ? = 1.0. All 100 converged on the same two-community partition. This is the "100/100" figure. It is a statement about the algorithm's behavior on this graph, not a proxy for accuracy on ground truth.
What "independent validation" here means, and what it does not
The 97.2% and 98.0% figures compare the algorithm-derived partition to the analyst-defined bundles (Contempt + Public Disorder + Assault + Resistance versus Sedición standalone). These are agreement rates.
They do not prove that the analyst-defined bundles are the correct doctrinal frame. They prove that an algorithm, given no prior knowledge, recovers the same partition the analyst drew from separate reasoning. When two independent methods converge on the same answer, the answer is more likely to be a feature of the data than an artifact of the analyst's framing. It is corroboration, not proof.
What we did not do
- We did not perform causal inference. The wave-based association (July 11 ? heavier bundle, OR = 1.42, p = 0.027) is a descriptive finding. Causal claims about state intent require evidence beyond this dataset.
- We did not analyze charges outside the canonical ChargeTypes. A subset of prisoners in the source data carry charges that were not normalized into the canonical type system; those cases were excluded from the community analysis. Coverage of the eight canonical ChargeTypes covers the great majority of political-persecution prosecutions in the corpus.
- We did not evaluate individual case merits. This is a corpus-level structural analysis. It is not a substitute for per-prisoner legal review, and no prisoner in the dataset is worse off or better off in law because of anything measured here.
- We did not measure sentence differentials counterfactually. The 5-to-7-year and 10-to-14-year figures are the observed sentence medians per bundle, not estimates of what any given defendant would have received had the state chosen the other bundle.
- We did not read minds. The finding is that the state applies different charge bundles to different arrest waves. Why the state does this, and whether the choice is directed from the top or emerges from local prosecutorial discretion, is beyond the reach of any co-occurrence analysis.
Reproducibility
Every stage of the pipeline is a separate Python script whose input and output are versioned. A reviewer can rebuild the corpus from the source URLs, apply the same tokenization, generate the same RDF triples, and re-run Louvain at any seed. The corpus snapshot, the parsed charge atoms, the community assignments, and the statistical test outputs are archived in the repository. If any number in this report cannot be reproduced from the archived materials, that is a bug and we will fix it.
UDHR and customary international law. Not the ICCPR.
Cuba has signed but not ratified the International Covenant on Civil and Political Rights. Most submissions to the WGAD about Cuba cite the ICCPR. Those citations are technically moot. Every legal argument in this project routes through the Universal Declaration of Human Rights and customary international law per WGAD Deliberation No. 9.
Draft submissions to three international bodies are complete: the UN Working Group on Arbitrary Detention (Categories II and III), the Inter-American Commission on Human Rights (American Declaration Articles XVIII, XXV, XXVI), and a stakeholder submission for Cuba's Fifth Cycle Universal Periodic Review in 2028. Nine verified WGAD Cuba opinions (2021 to 2025) anchor the submissions, including Opinion 63/2021 which establishes the "recurrent pattern" language the two-playbook finding directly supports.
A proof of concept for a class of capability.
Unstructured public records, in this case a website of prisoner profiles, can be converted into a formal knowledge graph that reveals corpus-level patterns invisible in any individual file. The two-playbook finding does not exist in any one prisoner's record. It becomes visible only when the entire population is analyzed together under a formal schema. That is the core value of structural intelligence: the pattern is in the corpus, not in the case.
The same approach applies to any domain where public records exist but are not structured for analysis: corporate registries, court dockets, sanctions lists, offshore leaks, campaign-finance filings. If the pattern interests you, or if you work in a domain where this kind of analysis could be useful, I would welcome the conversation.