Questionnaire Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-questionnaire |
|---|---|
| Status | draft (experimental) · 1.26.0 |
| Base | Questionnaire (constraint) |
| Source | FSH · JSON |
A Nexus EMR form definition: what it asks, what it produces, and where its answers land in the chart.
Overview
Forms carry contained prototypes of the resources they extract into, and are instantiated by cloning
those prototypes and filling them from the QuestionnaireResponse -- the same idea NexusTemplate
uses for letter templates and a Task uses for a suggested chart entry.
A form declares what it produces the way every other prototype-carrying resource in this
specification does: templateExtractBundle names a contained transaction Bundle, and its entries
are the prototypes. That is the same container NexusTemplate names with List.entry.item and a
suggested-resource Task names with input[suggestion].
Output that depends on the answers is expressed inside the Bundle, not outside it. Each
Bundle.entry carries a templateExtractContext expression naming the part of the response that
fills it. An entry whose context selects a repeating item is instantiated once per repeat; an entry
whose context matches nothing is removed. A repeating entry names its fullUrl by expression over
an extractAllocateId variable, because a single authored urn:uuid cannot distinguish iterations.
SDC's per-item templateExtract is deliberately not used here, though SDC blesses it and ships
the same demonstration form authored both ways. This is a narrowing, and it can be widened later
without invalidating anything written against this profile. The reason is that mixing the two leaves
a form with two prototype pools that cannot cite each other: a #id resolves against
Questionnaire.contained, so an item cannot name a prototype that lives as a Bundle entry, and an
entry cannot name one that lives loose in contained. One container removes the seam rather than
documenting it.
A form definition: what it asks, what it produces, and where its answers land in the chart.
This is the other half of QuestionnaireResponse.
The IG has profiled the answer set since 1.16.0 and never the form, so it could describe a completed
questionnaire but not the thing that produced one. The response profile says so itself: its
questionnaire element is "a canonical reference to a definition the IG does not govern -- for
external instruments that is correct and permanent; for WELL-authored forms it is a gap."
This is the template mechanism
A form, a letter template and a suggested chart entry are the same idea, and this profile is short because that is true.
Each is content carrying contained prototypes of what it produces, instantiated by cloning those prototypes, filling in what the definition could not know, and resolving the references between them. NexusTemplate says that for letters; a Task says it for a suggested chart entry; this says it for forms.
The container is shared as well as the idea. What differs is the wrapper that supplies identity, and what drives the fill:
| Wrapper | Names the Bundle with | Filled from | |
|---|---|---|---|
| Letter template | List |
entry.item |
the instantiation context |
| Suggested chart entry | Task |
input[suggestion] |
already filled in |
| Form | Questionnaire |
SDC's templateExtractBundle |
a QuestionnaireResponse |
A form is the only one whose output can depend on what a user answers, and that is expressed
inside the Bundle. Each Bundle.entry carries a templateExtractContext expression naming the
part of the response that fills it: an entry whose context selects a repeating item is instantiated
once per repeat, and an entry whose context matches nothing is removed. A repeating entry names its
fullUrl by expression over an extractAllocateId variable, because one authored urn:uuid cannot
distinguish iterations.
SDC's per-item templateExtract is deliberately not used here, though SDC blesses it -- and
ships the same demonstration form authored both ways, which is as clear a statement as a
specification makes that the two are one capability. Mixing them would leave a form with two
prototype pools that cannot cite each other, since a #id resolves against Questionnaire.contained
and a Bundle entry is not a contained resource. This is a narrowing rather than a judgement about
SDC, and admitting the item spelling later would invalidate nothing written today.
The mechanism is documented once, on the handbook's Templates page.
Why the position differs from QuestionnaireResponse
QuestionnaireResponse.item is deliberately unconstrained. Questionnaire.item is not. That is not
an inconsistency, it is the same rule applied to two different situations:
- A response may arrive from an external instrument whose item tree we do not govern. Constraining it would make conformant partner data non-conformant.
- A form definition in Nexus is one we authored, or one we translated inward at the boundary.
Nexus does not accept arbitrary foreign form definitions into the chart. External forms are translated into this shape on the way in — one generic format, ours. What is lossy in that translation is a declared question, not a silent drop; see What is not settled below.
Where the answers go
item.definition and item.code are the form-to-chart binding, and between them they replace what
a form system would otherwise express as a flat enum of EMR field names.
item.definition— the element an answer populates. R4 defines it as a reference to an ElementDefinition, so a binding may name an element of a Nexus profile and inherit that profile's constraints rather than restating them.item.code— what the question means. A question coded with the LOINC tobacco-smoking-status concept is recognisable as that question whichever form it appears on, which is what lets an answer become a clinical fact rather than form-specific text.
The requirements here come from a form model that names seventy EMR fields an answer can bind
to — demographics, problem list, allergies, medications, and a granular tobacco and substance
vocabulary. Every one is an element of a resource this IG already profiles, so the binding is a
path rather than a code. Expressed that way, the flattening compromises dissolve: a parallel
addr2* field enum is simply Patient.address[1].
Identity
url and version are both required here though 0..1 in R4.
A form is a definitional artifact: it is versioned, cached, and referenced by every response to it. A response to a form with no canonical cannot be interpreted beyond its own display text, and a response to an unversioned form cannot be interpreted at all once the form changes — the answers are against a shape nobody can reconstruct.
identifier is separate and optional: url is what this form is in Nexus, identifier is what
it was called in the system it was translated from, so a translation can be traced back.
The authoring rule
A prototype is valid base R4. The extracted resource is valid Nexus.
The same rule, in the same words, that templates follow. A prototype has no patient, because a form is about no one until it is answered, and base R4 already permits that. Where base R4 does require a value, supply a truthful one — the form's own date, its author — and expect it to be overwritten.
Do not invent sentinel values
A placeholder like 1900-01-01 or Patient/placeholder is syntactically valid, which is exactly
the problem: if the step that was supposed to replace it is missing, it survives into a real
chart and nothing downstream can distinguish it from a value someone meant.
dom-3 and dom-4 do real work here rather than rules invented for this profile: a stray prototype
nothing points at is already invalid, and a prototype cannot carry repository identity it has no
right to.
What is not settled
Named rather than buried, because each is a real requirement with no current home:
- Approximate date and duration. "About three years ago" is what patients answer, and R4
datecannot express it. A genuine clinical requirement with no FHIR datatype. - Body diagrams. Annotating an image has no item type;
attachmentcarries the result but not the interaction. - Note generation. Producing clinical text is a first-class output of a medical form system —
in the model this profile draws on, the note formatter is roughly the size of the scripting
engine, and sections carry
QUESTIONNAIRE | OBJECTIVE | ASSESSMENT | PLANsubcategories deciding what the patient sees versus what reaches the note. Nothing in FHIR Questionnaire addresses it. It is the same ruling as structured note sections and should be decided with it. - Expressions. Show/hide, formulas, prefill from prior answers, progress and validation are script in the source model. SDC expresses most of them in FHIRPath, which is specifiable and safe to accept where arbitrary script is not. Additive; not in this pass.
- The inbound translation contract. What happens to the lossy parts — embedded script, diagrams — when an external form is translated in.
- The item-type mapping. The source model's twenty item types are not mapped to R4
item.typeanywhere in this IG, which is whyitem.typeis left unconstrained here rather than bound. It is the largest thing a form implementer still has to reconstruct. It should be settled with the inbound translation contract above, because the same decision governs the item types that have no R4 equivalent.