feat(measurement): add calculation-reference provenance to Measurement results - #98
feat(measurement): add calculation-reference provenance to Measurement results#98pacharanero wants to merge 2 commits into
Conversation
…t results Adds a top-level `provenance` object to every Measurement result, containing the growth reference actually used for calculation and the identity of the calculation engine that produced it (name, version, build commit). This is step 1 of the mitigation chain for hazard rcpch/digital-growth-charts-documentation#174, where chart curves and a measurement result were found to use different growth references. Downstream consumers (server, chart component) can compare this provenance against the intended reference to detect a mismatch before rendering. - Reports the exact reference supplied to the calculation, not an inferred or age-specific table selector. - Present on every successful Measurement, including the dates-error early-return path and fictional-child data (Measurement is the single construction point). - Engine version is read via importlib.metadata at import time; build commit defaults to "unknown" and is stamped by the release workflow. Closes #37
…ronological age chronological_percentage_median_bmi was computed with age=corrected_age, identical to corrected_percentage_median_bmi immediately above it. Both fields returned the same value for every BMI measurement, silently mislabelling the corrected-age result as chronological. Invisible whenever corrected and chronological age coincide (term birth, or a reference that resets/stops gestational correction), which is why existing fixtures did not catch it. Affects any UK-WHO/Trisomy-21/Turner child not born at exactly 40+0 weeks gestation, at every age, since those references retain correction throughout. Adds a regression test using a preterm UK-WHO child, asserting the two fields differ and each matches an independently computed expectation - the previous code could never fail this test. Hazard raised and scored (severity-minor, likelihood-medium, risk-level-2-acceptable) for CSO review: rcpch/digital-growth-charts-documentation#178
Additional testing: cross-repo, server-boundary evidenceBeyond this branch's own suite, I ran three further checks specifically to answer "does this change the API's observable contract" - relevant given the small additional error-handling fixes now on this branch ( 1. Full suite, current branch state, including the fixes above and their 27 new tests: 2. Symlinked this exact branch into 3. Built a broad input-sweep regression tool (now in Result: 16 of 878 cases changed. Every single one is exactly one field, Two of those 16 are worth calling out as evidence the fix is strictly safer, not just different: at chronological age exactly 0 (birth, post-term gestation), UK-WHO has no BMI reference data below 2 weeks. Before the fix, that field silently returned the corrected-age value instead of acknowledging the absence. After the fix it correctly returns No status code, field presence, field type, or any other value changed anywhere in the 878-case sweep. The API's observable contract, outside the one field this PR intentionally corrects, is unchanged. |
|
I have pulled this branch, run the tests and the jupyter notebook. It all looks good to me. |
mbarton
left a comment
There was a problem hiding this comment.
Thanks @pacharanero. I've also checked it out and made sure I get back the new provenance data in the quickstart notebook.
Just flagging this PR also closes rcpch/digital-growth-charts-documentation#178 as that's a bit lost in the PR thread
Summary
Adds a top-level
provenanceobject to everyMeasurementresult:This is step 1 of the sequential mitigation chain for hazard rcpch/digital-growth-charts-documentation#174, where chart curves and a measurement tooltip were found to use different growth references. Downstream steps:
provenance.api_server.Full decision record:
spec/growth-reference-provenance-contract.mdin the documentation repo (supersedes the flat top-levelreferencefield originally proposed in this issue).Details
growth_referenceis the exact value supplied to the calculation (self.reference), not an inferred or age-specific internal table selector.Measurement, including the dates-error early-return path, because it's added once at finalself.measurementconstruction.generate_fictional_child_data, which constructsMeasurementinternally.calculation_engine.versionis read viaimportlib.metadata.version("rcpchgrowth")at import time.calculation_engine.commitdefaults to"unknown"(rcpchgrowth/_build_info.py) and is stamped with the release commit SHA by.github/workflows/python-publish.ymlimmediately before build, so PyPI wheels/sdists carry real provenance while editable/dev installs report"unknown"honestly.Testing
New
rcpchgrowth/tests/test_provenance.py: all six public references, Trisomy 21 vs Trisomy 21 AAP distinguishability, Turner canonical spelling, provenance survives the dates-error path, and fictional-child propagation for all six references.Full suite: 145,040 passed, 1,700 skipped, 0 failed.
Closes #37