Doctrine Fact Claim Audit
Doctrine Fact Claim Audit rejects wrong fact counts and dead anchors without claiming comprehension or route completeness.
The write-up
Documentation about live
Documentation about a live system rots: counts and code citations go stale as the code moves, and a reader cannot tell a current number from one true only once. Documentation about a live system rots. A page says there are forty-seven of something, or cites a function in a named file, and both claims go stale as the code moves underneath them. A reader cannot tell a current count from a number that was true once and never rechecked.
Doctrine fact claim
doctrine_fact_claim_audit asks which factual claims on a page can be re-derived from source now and which have drifted, emitting a metadata-only record of counts, verdicts, and scope limits. doctrine_fact_claim_audit answers one question about a page of factual claims: which of them can be re-derived from source right now, and which have become untracked drift. It reads a small set of public fixtures, recomputes a bounded relation over them, and writes a result record that carries counts, verdicts, and scope limits but no copied source bodies.
Does not judge
It does not judge whether prose sounds true; it checks four concrete things: fact count, code-locus existence with anchor, route-graph edges pointing at known facts, and volatile numbers bound to assertions. The component does not read prose and judge whether it sounds true. It checks four concrete things: that a declared fact count matches the fact table, that every cited code location exists on disk with its quoted anchor present, that every route-graph edge points at a known fact, and that volatile numbers in current-state prose are bound to a fact assertion or surfaced as a blocking finding.
Purpose
A claim is a cache with no invalidation
A loose documentation claim is a cached value with no invalidation strategy: a bare number tells you nothing about how to recheck it, so stale claims persist unnoticed as code changes. A loose documentation claim is a cached value with no invalidation strategy. The number 47 sitting in a sentence tells you nothing about how to recheck it, or whether the file it references still exists. When the code changes, the sentence keeps asserting the old value and nobody notices.
Admissible only when bound to something recomputable
A claim is admissible only when bound to something recomputable: a bare number must tie to a fact assertion or get flagged, and cited paths are resolved on disk with anchors confirmed. This component makes a claim admissible only when it is bound to something recomputable. A bare number in a current-state section is not enough. It has to be tied to a fact assertion that records how the value is derived, or it gets flagged. Cited file paths are resolved on disk and their anchor text is confirmed present, so a plausible-but-dead reference becomes a typed finding instead of inert prose.
How it works
A fixture evaluator on the crown-jewel runner
The component is a public fixture evaluator whose SPEC declares four required inputs and source anchors, while the shared runner handles validation, record writing, and negative cases, and this module supplies the evaluator and mutator. The component is a public fixture evaluator built on the shared crown-jewel runner. SPEC is a CrownJewelSpec that declares four required inputs, fact_assertions.json, fact_dag.json, numeric_claims.json, and projection_protocol.json, plus the source manifest reference and the anchors each copied source body must contain. The runner handles manifest validation, result-record writing, negative-case execution, and scope-limit attachment. This module supplies the domain evaluator and the negative-case mutator.
evaluate checks count, loci, anchors, edges
evaluate compares the declared fact count to the table, resolves each fact's code locus and anchor on disk, and rejects graph edges whose endpoints are not known facts, each with a typed error. evaluate is the core pass. It loads the fact table and the route graph, then runs the numeric-claim check, then walks the fact rows. It compares expected_fact_count against the number of fact rows and records DOCTRINE_FACT_COUNT_MISMATCH on disagreement. For each fact it requires at least one code locus, resolves the relative path through _resolve_code_locus against the copied source bundle, reads the file, and confirms the declared anchor string is in the body. A missing file or a missing anchor becomes DOCTRINE_CODE_LOCUS_MISSING or DOCTRINE_CODE_LOCUS_ANCHOR_MISSING. It then builds the set of known fact ids and rejects any graph edge whose from or to endpoint is not in that set with DOCTRINE_FACT_DAG_DEAD_REF.
_evaluate_numeric_claims binds volatile numbers
_evaluate_numeric_claims imports the copied derived_fact_hologram.py and runs find_unbound_numeric_claims per case, treating a detector case as positive and blocking any unbound current-state number. _evaluate_numeric_claims handles the volatile-number check. It loads numeric_claims.json and imports the copied derived_fact_hologram.py body through _load_derived_fact_module, which resolves the module out of the exported bundle and reports DOCTRINE_NUMERIC_CLAIM_SOURCE_MISSING if the copied body is absent. It then calls that body's find_unbound_numeric_claims against each case. A detector case declares expect_unbound: true and must surface the stated section and number, so it is positive evidence. Any other case that leaves current-state numeric prose without a matching fact-assertion section is blocked with DOCTRINE_UNBOUND_NUMERIC_CLAIM and DOCTRINE_VOLATILE_NUMERIC_UNBOUND.
Pass requires an empty findings list
evaluate returns pass only when the findings list is empty, reporting the fact, code-locus, edge, and numeric-claim tallies in a metadata-only record that never embeds copied source. evaluate returns a status of pass only when the findings list is empty, along with the fact count, verified code-locus count, edge count, and the numeric-claim tallies. The status record keeps body_in_receipt: false and never embeds copied source text.
Negative cases mutate a fixture in memory
evaluate_negative_case applies one real defect to the positive fixture in memory and reruns evaluate, so the proof of each error code stays attached to the evaluator, not to fixture filenames. The negative floor is semantic, not label-trusting. evaluate_negative_case copies the positive fixture in memory, applies one real defect for the named case (wrong_fact_count bumps the expected count, missing_code_locus empties a fact's loci, dead_code_locus corrupts an anchor, dead_dag_ref repoints an edge, unbound_numeric_claim strips a case's asserted sections), writes the mutated payloads to a temporary directory, and reruns evaluate there. The expected error codes live in EXPECTED_NEGATIVE_CASES. Because the mutation happens after load, the proof stays attached to the evaluator rather than to fixture filenames.
| Function | Role |
|---|---|
run, run_doctrine_fact_bundle | CLI entrypoints; forward to the shared crown-jewel runner in fixture or exported-bundle mode |
evaluate | Loads the fixtures, checks fact count, code loci, anchors, and graph edges, returns the status record |
_evaluate_numeric_claims | Imports the copied source body and runs the volatile-number binding check per case |
_load_derived_fact_module | Resolves and imports derived_fact_hologram.py from the copied bundle |
evaluate_negative_case | Mutates the positive fixture in memory and reruns evaluate to prove each stable error code |
Diagram source & refs
Source refs
- facts + expected_fact_count
fact_assertions.json- edges
fact_dag.json- cases
numeric_claims.json
flowchart TD Facts["fact_assertions.json facts + expected_fact_count"] --> Eval["evaluate"] Dag["fact_dag.json edges"] --> Eval Numerics["numeric_claims.json cases"] --> Eval Eval --> Count{"count matches table length?"} Eval --> Loci{"path on disk + anchor in body?"} Eval --> DagRef{"edge endpoints are known facts?"} Eval --> Bound{"current-state numbers bound to a fact?"} Count -->|no| Block["typed blocking finding"] Loci -->|no| Block DagRef -->|no| Block Bound -->|no| Block Count -->|yes| Pass["metadata-only result record"] Loci -->|yes| Pass DagRef -->|yes| Pass Bound -->|yes| PassNegative cases
Five failure cases, five stable error codes
Five declared failure cases each derive a stable error code, while the positive run reports three facts, three code loci, two edges, and two numeric-claim cases including one detector. The fixture ships five declared failure cases and the component derives a stable error code for each. wrong_fact_count gives DOCTRINE_FACT_COUNT_MISMATCH. missing_code_locus gives DOCTRINE_CODE_LOCUS_MISSING. dead_code_locus gives DOCTRINE_CODE_LOCUS_ANCHOR_MISSING. dead_dag_ref gives DOCTRINE_FACT_DAG_DEAD_REF. unbound_numeric_claim gives DOCTRINE_UNBOUND_NUMERIC_CLAIM together with DOCTRINE_VOLATILE_NUMERIC_UNBOUND. The accepted positive run reports three facts, three verified code loci, two graph edges, and two numeric-claim cases of which one is the detector for the number 123 in a current-state section.
Prior Art Grounding
Provenance and fact-check metadata prior art
The design borrows from provenance modeling and structured fact-check metadata, keeping only the parts that apply to fixture fact counts, code-locus existence, anchors, graph references, and numeric binding. This component borrows shapes from provenance modeling and structured fact-check metadata. W3C PROV models entities, activities, and agents so a reader can assess how derived information was produced. Schema.org ClaimReview is a web pattern for recording a reviewed claim and its checking context. JSON Schema covers rejecting malformed or incomplete claim records, and SLSA provenance covers tracing an artifact back to its source. The component keeps only the parts that apply to public fixture fact counts, code-locus existence, anchor presence, graph references, and synthetic numeric binding cases.
Validation Result record Path
From microcosm-substrate, run against external output paths so the reader check does not churn tracked result records. From microcosm-substrate, run against external output paths so the reader check does not churn tracked result records:
What a pass confirms
A pass means the fact count, code loci, anchors, graph edges, numeric bindings, manifest digests, and five negative cases all agreed with the copied public basis. A pass means the fixture fact count, code loci, anchors, graph edges, numeric-claim bindings, manifest digests, and the five negative cases all agreed with the copied public basis. If the copied source bodies drift, refresh the exported bundle through its owning import lane before treating a bundle failure as a reader-page defect.
Scope boundary
Scope limit
The strongest supported claim
The strongest claim is that, over these fixtures, the component verifies fact count, code-locus existence with anchors, graph edges, and bound volatile numbers, with negative cases proving each rejection derives from the evaluator. The strongest claim the evidence supports: given these public fixtures, the component checks that a declared fact count matches its table, that every cited code location exists on disk with its anchor present, that every route-graph edge points at a known fact, and that volatile current-state numbers are either bound to a fact assertion or surfaced as a blocking finding. The five negative cases prove each rejection path derives a stable error code from the evaluator, not from a fixture label. Result records stay metadata-only.
What it refuses to claim
It is not a comprehension engine and judges no prose as true: it exports no private doctrine, mutates no source, promotes no axiom, and excludes launch, bounded to the public fixtures and copied bodies. What it refuses to claim: it is not a comprehension engine and does not judge whether prose reads as true. It does not establish a minimum read graph for the wider doctrine plane, does not export private doctrine, and excludes launch or hosted-public posture. The proof boundary is the synthetic public fixtures, the copied source bodies, their manifest digests and anchors, the metadata-only result records, and the named negative cases. The scope limit excludes source-file changes, candidate-axiom promotion, and any claim that these counts prove whole-system correctness.
Context & evidence
In short Doctrine Fact Claim Audit validates public doctrine fact assertions against declared sections, numeric claim gates, code-locus anchors, route DAG fixtures, negative cases, source-open body imports, and scope limits. It lowers claim strength to fixture truth: fact assertion, code-loci, and DAG evidence are checked, but the component does not become a comprehension engine, minimum-read graph, doctrine saturation proof, source-file changes lane, or launch-scope decision.
Scope limit Declared fact-assertion, code-locus, and DAG fixture truth gate only; no comprehension engine, no minimum-read-graph proof, no doctrine saturation claim, no source-file changes, no launch-scope decision, no publishing-scope decision, and no whole-system correctness.
Covers Doctrine Fact Claim Audit
Source
Source Source module: src/microcosm_core/organs/doctrine_fact_claim_audit.py · Design note · Source registry