Part III — System Architecture · Chapter 25
Epistemic Neutrality Masking (ENM)
Epistemic Neutrality Masking (ENM)
The model cannot flatter the user about a person whose name it does not know.
ℹPrerequisites▼
Before reading this chapter, you should be comfortable with: Chapters 11, 16 (LLM Extraction, Procedural Primitives). Masking happens between extraction and emission; it modifies claims before they are signed.
A caseworker writes: "The father appeared intoxicated." An extraction pipeline reads that sentence and produces a structured claim: "father was intoxicated." The hedge — "appeared" — has been stripped. The claim is now categorical where the source was conditional. If that categorical claim reaches a Canon Attestation, the attestation makes a statement about the world that its source does not support. The verifier will pass the attestation. The chain hash will be valid. The signature will verify. And the attestation will be wrong.
This chapter is about why that failure mode is common, how to prevent it at the data layer rather than the review layer, and what Epistemic Neutrality Masking looks like in practice.
At a glance
- ENM is not anonymization — ENM preserves the source layer verbatim; the extraction layer is modified by removing evaluative language. Entity names are not replaced; what is stripped or reclassified is the certainty level that extraction would otherwise silently assign to hedged, interpretive, or legally conclusory language.
- The four masking categories — hedge words, emotional/interpretive labels, legal conclusions, and intensifiers — map directly to the FRE 701/702 boundary: a hedge or label produces an
inferred_lowextraction that can support only a lay-opinion claim, while a legal conclusion produces aspeculativeextraction that requires a judicial finding or expert opinion before it can be attested. - Gaps must be disclosed: every claim that depends on an extraction that ENM could not fully neutralize carries amasked_entity_dependencygap entry in the Canon Attestation, making the pipeline's judgment calls visible to any verifier. ## Learning objectives By the end of this chapter you should be able to: 1. Apply the four-category masking taxonomy to a caseworker sentence, producing a structured extraction JSON with the correctcertainty_level,hedge_present,conclusory, andrequires_reviewfields. 2. Distinguish an observed claim from an inferred claim, and explain which certainty levels (observed,inferred_low,inferred_high,speculative) a given masked extraction permits a downstream claim generator to assign. 3. Explain the FRE 701/702 implication of allowing aninferred_lowextraction to appear in a Canon Attestation withobservedcertainty — what the legal consequence would be and how ENM prevents it at the data layer. 4. Document a gap in a Canon Attestation's claims array: specify whichobservation_idtriggered the gap, which masking category applied, and what a reviewer would need to do to resolve the ambiguity. ## What ENM is not ENM is sometimes confused with anonymization. It is not anonymization. Anonymization replaces identifying information to protect privacy. ENM addresses a different problem: it prevents a model's extraction from making factual claims that the source text does not support. The source text is preserved verbatim. The entity names are not replaced. What is stripped — or flagged and reclassified — is the certainty level that the extraction would otherwise silently assign. ENM is also sometimes confused with hallucination prevention. A hallucination is content that the model fabricates without grounding in the source. ENM addresses a subtler failure: content that is grounded in the source but stated with more certainty than the source warrants. "He appeared to be holding something" becomes "he was holding something." The source exists. The extraction is grounded. The claim is still wrong. Hallucination prevention is a model quality problem. ENM is a data architecture problem. You can solve ENM without improving the model at all — by enforcing, at the extraction layer, that the output schema cannot represent categorical certainty for observations drawn from hedged sources. ## The three-layer separation ENM separates every extracted observation into three layers, each with a different role and a different destination: Layer 1 — Source verbatim. The original text, unchanged, preserved in the chunk and in the Attestation's Witness block. No analysis touches it. Layer 2 — Structured extraction (masked). The model's output, subjected to the masking taxonomy before it is committed to any structured field. The extraction identifies entities, observable states, and the epistemic status of those states — not a binary "fact / not fact." It records the hedge if a hedge is present. Layer 3 — Inferred claims. Downstream analysis — typically L4 enrichment — generates claims from the masked extraction. Those claims carry an explicit certainty level drawn from the Chapter 11 vocabulary:observed,inferred_low,inferred_high, orspeculative. The claim's certainty level is bounded by the extraction's epistemic status. A hedged observation cannot produce anobservedclaim. The masking happens at the boundary between Layer 1 and Layer 2. The taxonomy describes what to do with each category of epistemic contamination. ## The masking taxonomy Four categories of language require treatment at extraction time. Hedge words. Language that signals the observer's uncertainty about what they are reporting: appeared, seemed, possibly, might, appeared to be, seemed like, I believe, it looked like. When a sentence contains a hedge word, the extraction setshedge_present: trueand records the raw hedge phrase in metadata. The extracted state is reclassified fromobservedtoinferred_low. The hedge phrase is not discarded; it is preserved in the extraction'sraw_hedgefield. Emotional and interpretive labels. Language that describes a person's internal state using a label rather than an observable: angry, aggressive, hostile, calm, distraught, upset, resistant. These are not observations; they are interpretations of observations. The observable events are the behavioral indicators from which the interpretation was drawn: raised voice, increased pace, tearfulness, arms crossed, refusal to respond. ENM reclassifies the label to the behavioral domain. "Father was angry" becomes{behavioral_indicator: "raised voice", hedge_present: false, raw_label: "angry"}if the behavioral indicator can be identified from context, or{behavioral_indicator: null, interpretive_label: "angry", hedge_present: false, requires_review: true}if it cannot. Legal conclusions. Language that carries a specific meaning in law: neglect, abuse, intoxicated, under the influence, abandoned, incompetent. These are not observational categories. They are conclusions that require either expert analysis (FRE 702) or formal legal determination. A caseworker writing "the child was being neglected" is expressing a professional judgment, not a physical observation. ENM flags any extraction that draws from legally conclusory language asconclusory: true, records the specific term, and requires that downstream claims citing this extraction be tagged with the source authority type (lay opinion, expert opinion, or judicial finding) before they can be used in an Attestation.
Intensifiers. Language that adds certainty without adding information: clearly, obviously, certainly, undoubtedly, of course. These words do not describe what the observer saw. They describe how confident the observer claims to be about what they saw. ENM strips them without a flag. A sentence with an intensifier is treated identically to the same sentence without one, because the intensifier contributes no factual content. Stripping "obviously" from "the father was obviously intoxicated" does not change the epistemic status of "the father appeared intoxicated" — but it removes false confidence from the extraction output.
Presidio: NER-Based Entity Masking (v0.2.0)
The masking taxonomy described above is enforced by rule-based pattern matching. In v0.2.0, the recommended NER backend for entity detection and PII masking is Microsoft Presidio, installed via:
pip install meridian-canon[presidio]
Presidio combines an AnalyzerEngine (entity detection using spaCy-based NER models) with an AnonymizerEngine (replacement and redaction). Out of the box, it recognizes: PERSON, LOCATION, PHONE_NUMBER, EMAIL_ADDRESS, DATE_TIME, US_SSN, CREDIT_CARD, IBAN, and more. In v0.2.0, Meridian-Cannon adds domain-specific recognizers for legal evidence contexts: - Wisconsin/Minnesota case numbers: \d{4}CF\d{6}, \d{4}JC\d{6}, \d{2}-CR-\d{2}-\d+ - Bates numbers (production sequences) - Bar numbers (attorney registration IDs) - DHS case identifiers The adapter is in meridian/findings/presidio_extractor.py:
from meridian.findings.presidio_extractor import make_presidio_masker, presidio_extract
# Make a masker callable:
masker = make_presidio_masker()
masked_text = masker(text) # EntityMasker callable
# Inspect what Presidio found before masking:
entities = presidio_extract(text)
# → list of (entity_type, matched_text) tuples
make_presidio_masker() is a factory that returns a callable EntityMasker. The same callable is compatible with the masker= parameter accepted by ENM's masking pipeline. When the presidio package is not installed, the pipeline falls back to the regex-only masker automatically — no configuration change is required.
The relationship to the masking taxonomy: Presidio handles entity identification (finding spans of text that are PII or legal identifiers). The four-category ENM taxonomy handles epistemic classification (hedge, emotional label, legal conclusion, intensifier). Both run at L4. Presidio runs first, annotating the chunk text with entity spans; the taxonomy rules then run over the annotated text, using entity boundaries to avoid splitting a person's name across a hedge classification boundary.
Before and after: three worked examples
The before column is the source sentence. The after column is the structured extraction ENM produces.
Example 1 — Hedged observation.
Source: "The mother seemed overwhelmed by the amount of paperwork."
Masked extraction:
{
"subject": "mother",
"observable_state": "emotional_state",
"hedge_present": true,
"raw_hedge": "seemed",
"behavioral_indicator": "overwhelmed by paperwork",
"certainty_level": "inferred_low",
"raw_label": "overwhelmed",
"conclusory": false
}
The word "overwhelmed" is borderline — it is an interpretive label, not a behavioral observation. ENM treats it as inferred_low because the hedge is already present, records the raw label, and does not fabricate a behavioral indicator from context. A downstream model would need the source sentence to infer what behavioral indicators were present.
Example 2 — Emotional label without hedge.
Source: "The father became hostile during the home visit."
Masked extraction:
{
"subject": "father",
"observable_state": "behavioral_indicator",
"hedge_present": false,
"raw_label": "hostile",
"behavioral_indicator": null,
"certainty_level": "inferred_low",
"conclusory": false,
"requires_review": true,
"note": "Emotional label reclassified; no behavioral indicator recoverable from sentence alone"
}
"Hostile" is an emotional label. There is no hedge, but there is no observable behavioral description either. ENM cannot reclassify to a behavioral indicator without more context. It sets requires_review: true and does not automatically promote the extraction to observed. A reviewer can add the behavioral indicators from adjacent sentences in the chunk.
Example 3 — Legal conclusion.
Source: "It was clear that the child had been neglected."
Masked extraction:
{
"subject": "child",
"observable_state": "condition",
"hedge_present": false,
"intensifiers_stripped": ["clear"],
"raw_term": "neglected",
"conclusory": true,
"conclusory_kind": "legal_conclusion",
"legal_standard": "Wis. Stat. § 48.02(12b) (definition of neglect)",
"certainty_level": "speculative",
"source_authority_required": "judicial_finding or expert_opinion"
}
"Neglected" is a legal conclusion. "Clear" is an intensifier, stripped without flag. The extraction sets conclusory: true, records the Wisconsin statutory definition this term invokes, and sets certainty_level: speculative — the highest level of uncertainty, because no physical observation can establish legal neglect without a formal determination. A downstream claim citing this extraction as its support would be blocked from claiming observed or inferred_high certainty. > ✻ Try This. > > Take this sentence: "The mother was clearly neglecting the child's needs." Apply the masking taxonomy step by step. > > Step 1: Identify intensifiers. Strip them. What is left? > > Step 2: Is "neglecting" an emotional label, a hedge, or a legal conclusion? Look at the Wisconsin definition in Wis. Stat. § 48.02(12b): neglect means "failure, refusal or inability on the part of a parent, guardian, legal custodian or other person exercising temporary or permanent control over a child to provide necessary care, food, clothing, medical or dental care or shelter so as to seriously endanger the physical health of the child." Is a caseworker observation "neglecting the child's needs" a physical observation, a professional judgment, or a legal conclusion? > > Step 3: Is there a hedge present? What certainty level does the masked extraction get? > > Step 4: What inference types — observed, inferred_low, inferred_high, or speculative — could a downstream model generate from this masked extraction? Which types are ruled out by the masking result, and why? ## FRE 701 and 702: the legal frame Federal Rule of Evidence 701 governs lay opinion testimony. A lay witness — a caseworker, a neighbor, a family member — may give opinion testimony that is (a) rationally based on the witness's own perception, (b) helpful to clearly understanding the witness's testimony or determining a fact in issue, and (c) not based on specialized knowledge within FRE 702's scope. Federal Rule of Evidence 702 governs expert opinion testimony. An expert may testify if (a) the expert's scientific, technical, or other specialized knowledge will help the trier of fact, (b) the testimony is based on sufficient facts or data, (c) the testimony is the product of reliable principles and methods, and (d) the expert has reliably applied the principles and methods to the facts of the case. The distinction matters for ENM because the type of opinion governs what claims can be built from it. "The father appeared intoxicated" from a caseworker is lay opinion under FRE 701 — the caseworker reports what they observed and inferred. It can support a claim at inferred_low certainty. "The father had a blood alcohol concentration of 0.18% at the time of the visit" from a toxicologist is expert opinion under FRE 702 — it can support a claim at observed certainty, provided the testing methodology meets Daubert standards. ENM flags this distinction at extraction time. The source_authority_required field in the extraction output records whether a claim requires lay opinion only, expert opinion, or a judicial finding. A downstream Attestation that tries to elevate an inferred_low extraction to an observed claim without the required authority type is violating the Canon schema — the claim's certainty level must be consistent with the epistemic status of its supports observations. > § For the Record — FRE 602. > > "A witness may testify to a matter only if evidence is introduced sufficient to support a finding that the witness has personal knowledge of the matter. This standard may, but need not, be met by the witness's own testimony." > > ENM enforces the computational analog of this rule at the data layer. A claim may be generated from an observation only if the observation is grounded in a verifiable source document, and the claim's certainty level is consistent with the epistemic status of the observation. FRE 602's requirement of personal knowledge becomes, in the extraction layer, the requirement that every observation be traceable to a specific chunk in a specific document, hashed and attested at acquisition. ## The running case: caseworker notes and the word "appeared" The parent in the 2026 TPR proceeding has four years of DHS case notes in the corpus. Those notes were written by four caseworkers over three years. The notes are written in a house style that blends behavioral observation with professional interpretation. A paragraph that begins "During the home visit" may contain factual statements ("three children were present"), hedged observations ("the home appeared cluttered"), emotional labels ("the father was agitated"), and legal conclusions ("the children appeared to be at risk of harm"). Without ENM, a pipeline that extracts structured claims from these notes will produce a mix of certainty levels that it cannot distinguish from each other. An extraction of "the children appeared to be at risk of harm" may produce the same structured representation as an extraction of "three children were present." The first is a hedged legal conclusion by a caseworker. The second is a count of observable persons. They are epistemically different by several orders of magnitude. With ENM, the extraction for "the children appeared to be at risk of harm" produces: - hedge_present: true, raw_hedge: "appeared" - conclusory: true, conclusory_kind: "legal_conclusion" - certainty_level: "speculative" (both a hedge and a legal conclusion) - source_authority_required: "judicial_finding" This extraction cannot be cited as support for an observed or inferred_high claim. It can be cited as background context, and it can be cited as evidence that the caseworker made a professional judgment — which is itself a fact of a different kind. The caseworker's judgment, as a judgment, is an observable event: on this date, caseworker B wrote this professional assessment. That meta-observation is observed. The content of the assessment is speculative. > ☉ In the Wild — The Cosby retrial, 2018. > > In the first Cosby trial (2017, hung jury), testimony about "inappropriate touching" was admitted without significant objection to the characterization. In the retrial (2018, conviction), the defense challenged "inappropriate" as a legal standard rather than a behavioral description. The word does not describe what happened physically; it describes a moral and legal evaluation of what happened. > > The trial court's ruling on this challenge — whether "inappropriate" was lay opinion (FRE 701) or a legal conclusion embedded in testimony — affected what the jury heard and how they were instructed to weigh it. > > ENM forces this distinction before the data reaches the courtroom. A system that, at extraction time, flags "inappropriate" as an interpretive label and requires a behavioral description from the source sentence is a system that surfaces the FRE 701/702 question before it becomes a motion in limine. The earlier the distinction is enforced, the less expensive it is to correct. ## ENM is not a sufficient condition for epistemic neutrality ENM catches four known categories of epistemic contamination: hedge words, emotional labels, legal conclusions, and intensifiers — linguistic patterns identifiable at the sentence level. The masking taxonomy is a ruleset, and rulesets are bounded by the categories they describe. ENM does not catch framing bias. A paragraph may contain ten observable events; if the pipeline extracts five and ignores five, the bias is in selection, not classification. ENM has nothing to say about selection. ENM does not catch ordering effects. A model that sees "the home appeared cluttered" before "the children were well-dressed and well-fed" weights those observations differently than one that sees them in reverse. ENM affects certainty level per extraction; it does not affect sequence. ENM does not catch inter-rater variability in the taxonomy itself. Whether "became hostile" is an emotional label (yes) or a behavioral observation (depends on what "hostile" means to the caseworker and reader) is a judgment call the masking rules make consistently but not always correctly. > ◆ Going Deeper — The gap between ENM and complete epistemic neutrality. > > The philosophical ideal of epistemic neutrality in evidence systems is well-described and practically unattainable. The closer analogue in the statistics literature is the concept of pre-registration: declaring your hypotheses, extraction rules, and analysis pipeline before seeing the data, so that selection bias and post-hoc rationalization are structurally impossible. > > ENM is the evidence system's approximation of pre-registration at the extraction layer. You define the masking taxonomy before you run the corpus through it. You commit to the rules in code and configuration, and the code runs the same rules on every sentence. You surface what the rules catch; you document what they don't catch in the masked_entity_dependency gap field. > > The masked_entity_dependency gap is the claim-level acknowledgment that a result depends on extraction choices that ENM cannot fully neutralize. If a claim was built from extractions that triggered the review queue (because no behavioral indicator was recoverable from a sentence), the claim carries a gap that says: "This claim depends on an extraction that required human review; the reviewer's judgment is part of the claim's provenance." That is not complete epistemic neutrality, but it is honest. > > The alternative — pretending the pipeline is neutral when it is not — is worse than acknowledging the limits. Courts and opposing counsel will find the limits. Better that your system surfaces them first. > ▼ Why It Matters. > > A Canon Attestation that passes all seven verification steps is, by design, treated as trustworthy evidence. Its chain hash is valid. Its signature verifies. Its witness content hashes match. A judge reviewing a motion to exclude will see a verified attestation and have no cryptographic basis to doubt it. > > ENM is the layer that prevents a verified-but-wrong attestation from reaching that judge in the first place. If a caseworker wrote "the father appeared intoxicated" and the extraction pipeline produced an observed certainty claim that "the father was intoxicated," the attestation will verify — and the claim will be false. No cryptographic protocol catches that failure, because the failure happened before the seal was applied. > > For a parent in a TPR proceeding, the difference between "appeared intoxicated" (lay opinion, FRE 701, inferred_low) and "was intoxicated" (asserted fact, observed) is not semantic. One is the caseworker's perception on a single date. The other is a finding. ENM enforces that distinction at the data layer, before the attestation is signed, before the exhibit is produced, before the motion is filed. ## Where ENM lives in the pipeline ENM runs at the L4 extraction stage, after chunking and before any claim is written. The pipeline sequence is: 1. Chunk the document (section-aware, not naive fixed-size — see Chapter 15). 2. For each chunk, run entity extraction to surface mentions of persons, organizations, and identifiers. 3. For each sentence in the chunk, run the masking taxonomy rules. Classify each extractable observation by its epistemic status. Write the masked extraction, not the raw model output, to the structured storage. 4. Run the claim generator against the masked extractions. The claim generator is constrained by the certainty levels already assigned: it cannot produce an observed claim from a speculative extraction. 5. Emit the Attestation. The Attestation's Witness block contains the source verbatim (Layer 1). The Attestation's Findings block contains the claim with its certainty level and its supports pointer to the extraction (Layer 2 → Layer 3 link). The gap inventory records any masked_entity_dependency gaps. The masking rules are in findings/runner.py and the per-extractor integration is in findings/email.py. The rules are loaded from a YAML configuration file at startup — consistent with the architectural decision recorded in the project memory: curated data tables belong in YAML, not hardcoded Python dicts. ## The gap field: surfacing what ENM can't fix Every claim in a Canon Attestation carries an optional gaps block. The masked_entity_dependency gap type is the ENM-specific entry point. It records: - Which extraction triggered the gap (by observation_id). - What category of masking was applied (hedge, emotional label, legal conclusion, intensifier, review queue). - The certainty level the masked extraction received. - Whether a human reviewer resolved the ambiguity, and if so, what they decided. This gap field is visible to the verifier in Step 7 (coverage assessment). It does not cause the attestation to fail Steps 1–6. But it tells the recipient — an opposing-counsel expert, a judge's clerk, a forensic auditor — exactly where the pipeline made judgment calls and what those calls were. Honesty about limits distinguishes a trustworthy system from a merely confident one. They are not the same thing.
PERSON and LOCATION mentions expressed without fixed syntactic patterns (e.g., informal references, nicknames, partial names in running text). - Five domain-specific recognizers were added for legal evidence contexts: Wisconsin/Minnesota case numbers (2024CF, 2024JC, 22-CR-24), Bates numbers, bar numbers, and DHS case identifiers. - Masking runs at L4 (enrichment), not L6 (emission): by the time a claim reaches the sealing step, the PII has already been removed from the structured output, so the sealed attestation never contains the original identifying text. - make_presidio_masker() returns a callable EntityMasker compatible with the masker= parameter in ENM's masking pipeline; swapping from the regex-only default to the Presidio backend requires only replacing the factory call. requires_review: true extraction would ENM produce for each? ### Core 3. Take the following caseworker note sentence: "During the visit on March 22, 2024, the father appeared to have been drinking and was unresponsive to questions about the children's school attendance." Apply the full masking taxonomy. Write the structured extraction JSON for each clause. How many distinct masked extractions does the sentence produce? What certainty levels do they carry? 4. Implement the intensifier-stripping step as a Python function. Input: a sentence string. Output: the sentence with intensifiers removed, plus a boolean intensifiers_present and a list stripped_intensifiers. Use a YAML configuration file for the intensifier list rather than a hardcoded list in the function body. 5. Apply the four-category masking taxonomy to this DHS caseworker note: 'Mother appeared disheveled and clearly unprepared for the visit, neglecting to bring any supplies for the child.' For each of the four masking categories, list which specific tokens or phrases fall under it. After masking, write the resulting canonical statement. Confirm that all factual content (the date of the visit, the absence of supplies) is preserved. ### Stretch 6. Using the ten-sentence corpus formed by the three worked examples in this chapter's "Before and after" section plus seven sentences of your own drawn from any public court document, run your ENM implementation with and without each masking category disabled — one category at a time. For each run, record how many tokens are removed or reclassified. Report which masking category removes the most tokens from the corpus overall, and which sentences are most affected. Document your findings as a table: masking category, tokens affected, sentences with the highest impact. 7. Design a schema extension for the entity_resolutions table (in schema/C0_entities_resolution.sql) that records, for each resolution, whether the resolved entity appeared in a sentence that triggered ENM masking. Why would this correlation be useful for audit purposes? 8. The masked_entity_dependency gap currently records a single masking category per extraction. Propose and implement a schema that allows multiple masking categories per extraction — a sentence may contain both a hedge and an emotional label. How should the certainty level be determined when two masking categories are present? ## Build-your-own prompt For your capstone matter: identify five documents in your corpus that contain caseworker, investigator, or agency professional notes. Apply the masking taxonomy manually to ten sentences across those documents. Record the masked extractions and the certainty levels. Then ask: if these extractions were used to generate claims in a brief, what certainty levels would the claims carry? Which claims would require a human reviewer to validate before they could be attested? The goal is to know, before the brief is filed, where your evidence chain is strongest and where it depends on interpretation. ## Further reading - Federal Rules of Evidence, Rules 601–606, 701–705. Available at uscourts.gov. Rules 701–702 govern the lay/expert opinion boundary that ENM enforces computationally. - Daubert v. Merrell Dow Pharmaceuticals, 509 U.S. 579 (1993). The Supreme Court's framework for admissibility of expert scientific testimony under FRE 702. - Greenwald, Anthony G., and Mahzarin R. Banaji. "Implicit Social Cognition: Attitudes, Self-Esteem, and Stereotypes." Psychological Review 102, no. 1 (1995): 4–27. The foundational paper on implicit bias as a category distinct from explicit endorsement — the conceptual underpinning for why emotional labels need to be reclassified rather than merely discounted. - Gelman, Andrew, and Eric Loken. "The Statistical Crisis in Science." American Scientist 102, no. 6 (2014): 460–465. On the relationship between pre-registration and result reliability — the statistical analog of ENM's pre-commitment to masking rules. - findings/runner.py and findings/email.py in this repository — the masking stage implementation. - meridian/findings/presidio_extractor.py — make_presidio_masker() and presidio_extract(). - Microsoft Presidio documentation: https://microsoft.github.io/presidio/ — analyzer and anonymizer architecture, custom recognizer patterns.
- Wisconsin Statutes § 48.02 — statutory definitions of neglect, abuse, and related legal conclusions relevant to the running case's TPR proceedings.
Next: Chapter 19 — The Five Challenge Types. How the refutation block works, and why every claim needs at least one challenger.