Known limitations
-
A subject override withholds and warns; it never models the third party. There is no accessor for an entry another subject governs: it is reachable only through
toString(). And because presence is the trigger, a document that repeats the patient as an entry subject loses those entries from the record-target read paths. Both are deliberate, and the second is the accepted cost of never guessing that a declared subject "is really the patient". -
Fourteen entry families (so far): Problems / Medications / Allergies / Results / Vital Signs / Immunizations / Procedures / Encounters / Social-History smoking status / Plan of Treatment / Functional Status / Mental Status / Family History / Past Medical History are extracted; any remaining sections still carry only identity and narrative.
-
UCUM validation is grammatical, on a curated atom subset: the validator checks that a unit is well-formed UCUM (case-sensitive prefixes/atoms,
.//terms,[…]and{…}forms) against a curated table of the prefixes and atoms that appear in lab Results and Vital Signs, not the full UCUM atom registry. A valid but uncurated atom may read asNON_UCUM_UNIT; the raw unit is always preserved, so nothing is lost. -
LOINC deprecation is a curated set:
checkLoincDeprecationflags a curated list of known deprecated LOINC codes, not every deprecation in the LOINC release. As with all code-system checks, this is recognition only: membership validation needs a licensed terminology service. -
A terminology adapter is consulted at five coded slots only:
problem,medication,allergen,route,vaccine. Results/Vital Signs LOINC codes, procedure, encounter, and family-history codes, the planned-item codes for the five variants whosecodeis the planned act (a planned medication'scodeis the drug and a planned immunization's is the vaccine, so those two go to themedicationandvaccineslots), the smoking/functional/mental status values, the allergy propensity type, and the reaction/severity/criticality observations are never handed to it. Within the five, the checks apply to the slot's primary coding; alternate codings in<translation>are preserved but not slot-checked. A clean run means those five slots passed, not that the document was terminology-verified. -
Required-section (SHALL) validation under-warns, and every type says by how much: CCD and Care Plan report
traced-complete; the other nine structured types reporttraced-partial, naming the SHALL sections they do not assert and why; Unstructured Document reportsnot-applicablebecause it carries no section; no type reportsuntraced. Progress Note, Procedure Note, Operative Note, and Diagnostic Imaging Report assert nothing, because every SHALL section their template names is either outside the recognized catalog or a choice. A document of atraced-partialtype can still be missing a section its type requires and parse clean: readrequiredSectionStatus(documentType)rather than treating a quiet parse as a conformance result. -
Editing is whole-section, across twelve kinds: Functional Status and Mental Status are buildable but not editable (each takes three separate content lists), as are the Referral Note's narrative-only Assessment and Reason for Referral sections. There is no entry-level append (a
replacerebuilds the section from your typed input, dropping unmodeled detail in it), no section removal, and noAPND/XFRMrelationship: an edit stampsRPLConly. -
Serializer re-emits a parsed document; the builder constructs one:
serializeCcda/toString()faithfully re-emit a parsed document (the spec-clean emit half of Postel's Law). To construct a document from scratch,buildCcdaemits a spec-clean CCD, Referral Note (documentType: "referralNote") or inpatient Discharge Summary (documentType: "dischargeSummary") with the US Realm header. A CCD always carries its six SHALL sections (Problems, Allergies, Medications, Results, Vital Signs, and Social History), plus Immunizations, Procedures, Encounters, Functional Status, Mental Status, Past Medical History, Plan of Treatment, and Family History emitted only when populated (none is a CCD SHALL section); a Referral Note instead specializes the header and always emits Problems, Allergies, Medications, Reason for Referral, Assessment, and Plan of Treatment, emitting Results, Vital Signs and Social History only when you supply them; and a Discharge Summary specializes the header with its own SHALL set (Allergies, Hospital Course, Discharge Diagnosis, Plan of Treatment) plus thecomponentOf/encompassingEncounterframe its template requires, an encounter period and a discharge disposition, each emitted verbatim when supplied and as an explicitnullFlavor="UNK"when not, never derived from another date in the document. A Discharge Summary emits Problems and Medications only when you supply them, the medications in the Medications Section (it does not emit the Discharge Medications Section). Input one type carries is refused, never dropped:hospitalCourse,dischargeDiagnoses, andencompassingEncounterthrow on a CCD or a Referral Note, andassessmentandreasonForReferralthrow on a Discharge Summary. (A CCD still ignoresassessmentandreasonForReferral, as it always has.) To change a section of a document you already parsed, useeditCcda. The remaining nine document types are not implemented. "Spec-clean" here means well-formed, correctly-templated, and round-tripping throughparseCcdawith zero warnings, for all three types. A Discharge Summary's Hospital Course section (CONF:1198-30522) is an IHE PCC template the parser recognizes by its root but does not assert as required, so a reparse will not report it missing:pnpm conformanceis what checks that it is there. Every entry emits theSHALL-cardinalityeffectiveTimeits C-CDA R2.1 template requires: the Problems/Allergies concern acts + observations, the Medication ActivityIVL_TSduration, and the Results/Vital Signs organizers + observations. When the caller supplied a time it is used; when aSHALLrequires the element but no time is known the slot isnullFlavor="UNK"(satisfying the cardinality without inventing a clinical time, read back as absent), the same fail-safe as the header'sSHALLaddr/telecomand the never-guesseddose/route. The reaction/severity/criticality sub-observations' optional (0..1, non-SHALL)effectiveTimeis not emitted. -
A Functional Status Organizer is written only when it carries a self-care activity. The R2.1 template SHALL contain a Self-Care Activities (ADL and IADL) observation as well as a Functional Status Observation, so
BuildCcdaFunctionalStatusOrganizertakesselfCareActivities(the activity assessed ascode, the ability observed asvalue, eachnullFlavor="UNK"when you supply none). Pass no activity and the organizer is not written: its findings are emitted as standalone Functional Status Observations, all of them present and read back unchanged, and the returned document carriesMISSING_SELF_CARE_ACTIVITYsaying the grouping, its categorization code and itseffectiveTimewere dropped. The builder will neither invent an assessment nobody performed nor stamp a template the document does not satisfy. -
Vendor profiles tolerate, they never relax safety: a
CcdaProfileonly downgrades the non-safety-critical deviations it expects (re-badgedPROFILE_QUIRK_APPLIED, flaggedexpected); it can never tolerate a dose, allergen, unit, identity, or wrong or missing code system warning (refused atdefineCcdaProfile()time) and never changes an extracted value. BesidesccdaProfiles.default, which tolerates nothing, two built-ins ship (ccdaProfiles.smartScorecard,ccdaProfiles.legacyR11), each grounded in a cited public source; named per-vendor profiles await a real vendor-attributed grounding document.