Skip to content

Clinical section-boundary provenance

openmed.clinical.sections.provenance validates the relationship between normalized clinical section ranges and their source offsets. It is a structural audit aid, not a medical device, compliance certification, or clinical decision guarantee.

Validate section ranges

Ranges use half-open character offsets. Top-level ranges are expected to be ordered, non-overlapping, and to cover the source document:

from openmed.clinical.sections.provenance import validate_section_provenance

source = "HPI: synthetic cough.\nPLAN: synthetic follow-up."
plan_start = source.index("PLAN")
report = validate_section_provenance(
    source,
    (
        {"id": "hpi", "start": 0, "end": plan_start},
        {"id": "plan", "start": plan_start, "end": len(source)},
    ),
)

assert report.valid
print(report.to_json())

The validator also accepts SectionSpan values and objects with start and end attributes. Set require_coverage=False when validating a partial view of a document.

Validate source-map references

Source-map entries can be supplied directly on a range or through a local mapping keyed by section id or input index:

report = validate_section_provenance(
    source,
    (
        {"id": "hpi", "start": 0, "end": plan_start},
        {"id": "plan", "start": plan_start, "end": len(source)},
    ),
    {
        "hpi": {
            "source_start": 0,
            "source_end": plan_start,
            "source_ref": "src-a",
        },
        "plan": {
            "source_start": plan_start,
            "source_end": len(source),
            "source_ref": "src-b",
        },
    },
    require_source_map=True,
)

The source map is local caller-supplied data; the validator never downloads or resolves one. A repeated reference must resolve to the same source range. Source ranges are checked for ordering, overlap, bounds, and optional supplied content hashes. When no explicit map is supplied, ordinary source-indexed ranges use deterministic identity references.

Parent containment and privacy

A child range can name a parent with parent_id. The child must be contained by that parent's normalized range. Parent definitions may also be supplied via the parent_sections= argument.

Explicit numeric parent IDs take precedence over positional fallback. Supplied content hashes must use sha256:<64 lowercase hex>; invalid values produce an invalid_source_hash finding without copying the rejected value into the report.

Reports contain only structural offsets, category/code values, counts, and SHA-256 hashes. They do not copy labels, identifiers, source-map references, or section text. report.to_json() and report.write_json(...) are deterministic for identical inputs. Findings such as gap, overlap, outside_parent, and source_map conflicts can be reviewed without exposing the source document.