Appendix C - 6. Cross-source coherence lints

The Structure of Cross-source coherence lints — its shape at a glance:

The lint reads both sources and checks the declared relation between them. Agreement passes; any divergence fails the build.

flowchart LR
  A[(Source A)] --> G{Coherence lint}
  B[(Source B)] --> G
  G -->|relation holds| Pass([build proceeds])
  G -->|sources diverge| Fail([build blocked])

Accessible description: the coherence lint reads two independent sources and checks the declared relation between them — for instance, A's fields are a subset of B's. When the relation holds the build proceeds; when the sources diverge the build is blocked.

Projected from the catalogue entry validation-and-conformance / Cross-source coherence lints.

On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns

Intent

Intent — Lints that assert two or more independent sources agree (config record ↔ sample JSON, registry ↔ its consumers, enum ↔ its uses), catching drift between sources that each look valid on their own.

Motivation

Some invariants live between files: a config record and its sample JSON must list the same fields; a registry and its consumers must share the same keys; an enum and its handlers must stay in step. Each file is individually valid, so the bug is invisible per-file, but together they disagree. The canonical case: a new field on a config record that is missing from the sample defaults to false at deserialization and silently collapses batching to single-call in prod. The failure is cross-source drift, recurring whenever paired sources evolve independently.

Applicability

Structure

The Structure diagram appears at the top of this page.

Sample Code

A coherence lint is a relation checked across two sources read at lint time. Here the relation is subset: every field declared on a config record must appear in the shipped sample, or the missing field deserializes to a default and silently changes behaviour. A single-source lint can never catch this — the defect lives only in the disagreement.

import sys

def coherence(record_fields: set[str], sample_fields: set[str]) -> list[str]:
    """Relational invariant: every field on the config record must appear in the
    sample. A field present in code but absent from the sample deserializes to a
    silent default — the bug lives between the files, not in either one."""
    return [f"config field '{f}' missing from sample — will default silently"
            for f in sorted(record_fields - sample_fields)]

if __name__ == "__main__":
    # `fields_of` reads a source into its declared field set (record, sample, ...)
    findings = coherence(fields_of("config_record"), fields_of("config_sample"))
    for f in findings:
        print(f"DRIFT: {f}")
    sys.exit(1 if findings else 0)

Consequences

Example use within DocAble

Contents
© James C. Davis, 2026–present