Version Packages - #109
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@cosyte/ccda@0.0.14
Patch Changes
bdd551e: Settle the CCD required-section (SHALL) set against the normative C-CDA R2.1 Schematron: it is six sections, and the parser and builder now agree on it.
buildCcdanamed five SHALL sections for a CCD (including Vital Signs) whilerequiredSectionKeys("ccd")named four (excluding it). The live consequence was an asymmetry: a built CCD always carried a Vital Signs section, butparseCcdastayed silent when a third-party CCD lacked one. Both halves now name the same six, read off the CCD (V3) errors rule of the normative Schematron published by HL7: Allergies and Intolerances (CONF:1198-30662), Medications (-30664), Problem (-30666), Results (-30670), Social History (-30688) and Vital Signs (-30690). Procedures (-30668) and Plan of Treatment (-30686) sit in that template's warnings rule as SHOULD, so neither is asserted.Those six CONF ids are scoped to the R2.1 stamp: the rule they live in matches only a
ClinicalDocumentwhose CCDtemplateIdcarries@extension="2015-08-01". SosocialHistoryandvitalSignsare asserted only against an R2.1-stamped document. An R1.1-origin CCD (the same root with no extension, the condition that raisesTEMPLATE_EXTENSION_ABSENT) keeps exactly its previous reading of Allergies, Medications, Problems and Results. That is not a claim that R1.1 omitted the other two; there is no R1.1 Schematron in hand, and narrowing the original four would be as unsourced as broadening them.requiredSectionKeysandmissingRequiredSectionsboth take an optional{ r21Stamped: false }for the unstamped reading, and the newRequiredSectionOptionstype is exported. The stamp is detected the way the Schematron's context predicate is written, existentially: a document is R2.1-scoped when any of its document-leveltemplateIds carries the root together with@extension="2015-08-01", so the common dual-stamped backward-compatible shape (both the extension'd and the baretemplateId) is read correctly whatever order the two appear in.What changes for you:
requiredSectionKeys("ccd")andmissingRequiredSections("ccd", ...)now includesocialHistoryandvitalSigns. An R2.1-stamped CCD that lacks either now raises aREQUIRED_SECTION_MISSINGwarning it previously did not. This is a warning, never a fatal, so nothing stops parsing. R1.1-origin CCDs are unaffected.buildCcdanow always emits a Social History section for a CCD, as a spec-clean emptynullFlavor="NI"shell when nosmokingStatusis supplied. That shell is conformant and invents no clinical fact: the Social History Section (V3) requires onlycode,titleandtext, and its Smoking Status entry is SHOULD, not SHALL. It has no entries-required template variant, so the shell still carries exactly the template the CCD SHALL constraint names.smokingStatusemits the Social History section exactly once, as before.Document types whose SHALL set excludes Social History, such as the Referral Note, are unchanged: they still emit it only when populated.
a0fba0a: Emit the Medications section under its own
2014-06-09version stamp, so a CCD built with medications stops failing CONF:1198-30664.The six CCD SHALL sections do not share one version stamp, and the builder assumed they did. Each assert in the normative C-CDA R2.1 Schematron's CCD (V3) errors rule names a
@rootand an@extension, as a pair. Five are2015-08-01: Allergies (…22.2.6.1), Problem (…22.2.5.1), Results (…22.2.3.1), Social History (…22.2.17) and Vital Signs (…22.2.4.1). Medications (…22.2.1.1) is2014-06-09. R2.1 revised that section at the earlier stamp and never re-issued it at the later one: the Schematron carries section rule contexts for both Medications roots (…22.2.1and…22.2.1.1) at2014-06-09and zero rule contexts for either root at2015-08-01.medicationsSectioncalledsectionElementandemptySectionwithout an extension argument, so both took the builder'sR21default and stamped…22.2.1.1with2015-08-01. That pair is unsatisfiable by any rule in the IG, so every CCD and every Referral Note this builder produced failed its own document type's Medications assert, populated or empty: a CCD fails CONF:1198-30664, a Referral Note CONF:1198-30923. Both call sites now pass a namedMED_SECTION_EXT. The two asserts are byte-identical in theirtestXPath, both requiring…22.2.1.1at2014-06-09, and differ only in the rule context that selects them, the CCD's…22.1.2against the Referral Note's…22.1.14, so the section template's identity is document-type independent and one fix corrects both;editCcdarebuilds sections through the same function and inherits it.This changes the emitted bytes on every document carrying a Medications section, so a consumer keyed on the exact old
root+extensionpair stops matching. It is not a breaking API change: this package's own parser,sectionForTemplateRootand the editable-section table all match on the root alone, so parse, edit, section lookup and round-trip are unaffected, and no conformant consumer could have been keyed on a stamp the IG does not define. The parse fixtures and both docs samples that carried the same non-existent stamp were corrected with it, including thequickstartsample that labels itself "Clean, spec-conformant input" while carrying a pair no rule in the IG defines; the serializer snapshot moves by exactly that one attribute, which is the round-trip fidelity check doing its job. Note that the executable docs gate could not have caught either, because section recognition matches the root alone.Why a root-only test never caught this: the pre-existing assertion checked for
2.16.840.1.113883.10.20.22.2.1.1with no stamp, and passed throughout. The new tests assert the pair for all six SHALL sections, and additionally assert the2015-08-01pair is absent, so a reverted default reds instead of passing vacuously. Five of the eleven tests touching this are red at the previous commit and six are green there as controls, the five non-Medications SHALL rows plus the round-trip re-parse.Scope, stated rather than implied. This closes that one CONF for a populated document. It does not upgrade the package's general conformance claim: nothing in CI validates an emit against the Schematron, so every CONF id this code cites remains mechanically unenforced, and "a built document round-trips with zero warnings" still does not mean "a validator would pass it". A CCD with no medications emits the entries-optional root only, because declaring entries-required with zero entries violates that template's own "SHALL contain at least one entry", so such a document still fails CONF:1198-30664 (a Referral Note in the same state fails CONF:1198-30923, never -30664). That is inherent to having no medications rather than a residue of this change, and it applies equally to Allergies, Problems, Results and Vital Signs.
What landed for enforcement is a transcription of the six asserts with the source artifact's sha256 recorded next to it, not a Schematron run. A real harness needs an XPath engine, correct
sch:extendsexpansion and first-rule-wins semantics, and the.schis deliberately not vendored, so it stays its own slice. Getting rule-context semantics wrong inside a harness would be worse than having none: the assert behind this defect sits in anabstract="true"rule that carries no context at all, and reading it without following the concrete rule that extends it is the same misreading that produced the bug.