Task Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-clinical-task |
|---|---|
| Status | draft · 1.26.0 |
| Base | Task (constraint) |
| Source | FSH · JSON |
A unit of work in the chart: who asked for it, who owns it now, what has been said about it, and which chart element it concerns. Inbox items, to-dos, follow-ups, a result that needs review -- deliberately one kind of work item.
FSH
The authored source of truth: resources/StructureDefinition-nexus-emr-core-clinical-task.fsh (edit on GitHub). One FSH file may define several related artifacts.
// StructureDefinition-nexus-emr-core-clinical-task.fsh
// A unit of work in the chart: who asked, who owns it now, what has been said, and which chart
// element it is about.
//
// ON THE SLUG. `nexus-emr-core-clinical-task` is this IG's one irregular profile id: every other
// core profile is `nexus-emr-core-<resourcetype>`. Renaming it to `nexus-emr-core-task` was
// prepared for 1.17.0 and deliberately NOT taken. The rename is cheap and correct on its own terms
// -- a profile canonical only becomes data if something writes it into `meta.profile`, and nothing
// does -- but it reaches out of the spec into application code that records the canonical as
// declarative metadata (`nexusEmrProfile` in the chart-module registry, read by nothing), and a
// spec release is the wrong vehicle for edits to other teams' files. If it is taken later it
// should be its own change, with those owners in it.
//
// WHAT A TASK IS FOR, and what it is not. It carries the WORK: the requester, the current owner,
// the conversation (`note`), and a reference to the chart element the work concerns (`focus`). It
// does NOT carry the clinical content. A completed form is
// a QuestionnaireResponse, an arriving document is a DocumentReference, an authored note is a
// Composition -- each one a resource in the chart that a task points at. That boundary is the
// ruling FHIR-31 asked for, and it is written out on `focus` below.
// SUGGESTED-RESOURCE TASK invariants. A task carries a suggested chart entry as a CONTAINED
// TRANSACTION BUNDLE -- the same prototype-graph mechanism a reusable template and an SDC form use.
// See the suggested-resource section below, and the handbook page for the narrative.
Invariant: nexus-sugg-1
Description: "A `suggested-resource` input SHALL reference a CONTAINED resource (a local #id reference). A suggested resource is never a first-class chart resource before someone accepts it."
Severity: #error
Expression: "input.where(type.coding.where(system = '../CodeSystem/nexus-task-input-type' and code = 'suggested-resource').exists()).all(value.reference.startsWith('#'))"
// The contained thing is a transaction BUNDLE, not a bare resource and not a List. dom-2 forbids a
// contained resource from containing anything, and `Bundle` is the one container exempt from it --
// it derives from `Resource` rather than `DomainResource` and has no `contained` element for the
// rule to find. So the suggested-resource Bundle keeps its own prototypes instead of scattering them beside itself,
// and a task may contain other things (its Provenance, an attachment) with no ambiguity about
// which resources are the suggested ones.
// OUTSIDE TypedFhir's emittable FHIRPath subset, and ALLOWLISTED rather than disabled. The
// expression uses `substring()`, `%resource`, `$this is <Type>` and the `in` membership operator;
// `src/ig/fhirpath.ts` compiles none of the four. The subset does support `where`, `exists`, `all`,
// `empty`, `matches`, `startsWith`, `count`, `not`, `implies` and the `value.ofType(T)` fold, so
// this is not a near-miss -- FHIR-58 adds the first three constructs, FHIR-75 the type test, and
// this rule needs both.
//
// IT SHIPS. `test:fhirpath` runs inside a required check and fails on an invariant it cannot
// verify, which is why an unverifiable rule needs an entry in `ts/test/lib/unverifiable-allowlist.ts`
// -- and that is the mechanism, not deletion and not commenting out. This rule was briefly
// commented out of the FSH instead, which removed it from the published StructureDefinition
// altogether: the HL7 validator and every conformant external validator stopped enforcing a SHALL
// that has nothing to do with our emitter's limits. Two sibling rules saying the SAME thing --
// `List:nexus-template-entry-is-contained-bundle` and
// `Questionnaire:questionnaire-extract-bundle-is-contained` -- were allowlisted and shipping in the
// same release, so the specification enforced "resolves to a contained Bundle" on a template and on
// a form, and nowhere on a Task.
//
// WHAT IS ACTUALLY MISSING is only OUR runtime check. Removing a rule from the specification to
// work around a limitation in our own emitter is the wrong direction: the published IG is read by
// implementers with real validators, and it should say what is true.
Invariant: nexus-sugg-2
Description: "A `suggested-resource` input SHALL resolve to a Bundle contained in this Task. The suggested resources are that Bundle's entries."
Severity: #error
Expression: "input.where(type.coding.where(system = '../CodeSystem/nexus-task-input-type' and code = 'suggested-resource').exists()).all(value.reference.substring(1) in %resource.contained.where($this is Bundle).id)"
// The suggested-resource Bundle is a TRANSACTION: accepting it writes its entries, and the per-entry request
// that says how is only meaningful on a transaction.
Invariant: nexus-sugg-3
Description: "A contained prototype Bundle SHALL be type `transaction`: instantiating it writes its entries, and `entry.request` is what says how each one is written."
Severity: #error
Expression: "contained.where($this is Bundle).all(type = 'transaction')"
// FOCUS POINTS OUTWARD, ALWAYS. `focus` names a resource that EXISTS IN THE CHART -- the report
// that arrived, the medication being discussed. It is never a contained resource and never a local
// reference, and stating that as prose left it inferrable rather than checkable.
Invariant: nexus-task-focus-not-contained
Description: "Task.focus SHALL NOT be a local (#) reference. Focus names a resource that already exists in the chart; contained content is referenced from `input`."
Severity: #error
Expression: "focus.reference.exists() implies focus.reference.startsWith('#').not()"
// The priority refinement degrades safely or not at all -- see the TaskPriorityDetail extension.
Invariant: nexus-task-priority-detail-1
Description: "When the priority-detail extension is present, Task.priority SHALL be `routine`, so a consumer that does not read the extension sorts the task as routine rather than mis-sorting it."
Severity: #error
Expression: "priority.extension.where(url = '../StructureDefinition/nexus-task-priority-detail').exists() implies priority = 'routine'"
// The correction vocabulary is statutory and narrow; the general one is neither. Both are in the
// required binding, because a binding cannot be conditional on a sibling element -- so this is what
// keeps them apart. One-directional on purpose: it stops a correction code appearing on ordinary
// work, and does NOT require a privacy task to avoid the general codes. `code` is 0..1 and most
// stored tasks predate the vocabulary entirely, so the converse rule would fail history rather than
// catch defects.
Invariant: nexus-task-bizstatus-scope
Description: "A correction business status SHALL only appear on a task filed under `privacy-request`. The correction lifecycle is the statutory record of a request to amend a chart; on any other task it is a status nobody can act on and a reader cannot distinguish from ordinary workflow state."
Severity: #error
Expression: "businessStatus.coding.where(system = 'http://hl7.org/fhir/uv/patient-corrections/CodeSystem/PatientCorrectionBusinessStatus').exists() implies code.coding.where(system = '../CodeSystem/nexus-task-code' and code = 'privacy-request').exists()"
Profile: NexusEmrCoreClinicalTask
Parent: Task
Id: nexus-emr-core-clinical-task
// TITLE vs ID. The display title is "Task Profile" while the id stays
// `nexus-emr-core-clinical-task`. That is deliberate and the asymmetry is the point: a title is
// display text referenced by nothing, so it costs nothing to correct, and "Clinical Task" sorted
// this profile away from the resource it profiles in the artifact index. The ID is a canonical
// URL, which is the half that can sit in stored data and in other teams' code -- see the note at
// the top of this file.
Title: "Task Profile"
Description: """
A unit of work in the chart: who asked for it, who owns it now, what has been said about it, and
which chart element it concerns. Inbox items, to-dos, follow-ups, a result that needs review --
deliberately **one** kind of work item.
It also carries **suggested chart entries**, content awaiting someone's acceptance. Read the
Overview before building anything that lists or displays tasks.
**A decision-support producer may tag the state of the content behind a suggestion.** A task
projected from decision-support content that was loaded without requiring clinical sign-off carries
`unsigned-draft` in `meta.tag` under the
[CDS Content Status code system](CodeSystem-nexus-cds-content-status.md). This profile does not
model or slice `meta.tag`: the element is open on every resource, and that marker belongs to one
producer rather than to the shape every clinical task conforms to. Read that code system for what
the tag asserts, and in particular for why an ABSENT tag asserts nothing at all -- it is not a
statement that the content was signed.
"""
// THE effective date for this profile (see the EffectiveDate / NoEffectiveDate
// RuleSets): one date concept per resource, declared here rather than guessed.
* insert EffectiveDate([[authoredOn]])
// SMART on FHIR exposure -- this resource is reachable by an app, and these are the
// permissions each operation costs (see SmartExposed + the SmartExposed RuleSet).
* insert SmartExposed(task)
* ^status = #draft
* insert NoResourceNoteExtension
* ^date = "2025-07-23"
* ^publisher = "WELLSTAR Technologies Corp."
* ^contact.telecom.system = #url
* ^contact.telecom.value = ".."
* ^purpose = "Provides a comprehensive FHIR Task profile for clinical workflow management within EMR systems, emphasizing clinical safety through explicit ownership -- narrowed to a named party, or held collectively by the clinic and visible to everyone -- and complete audit trails."
* ^copyright = "Copyright 2025 Nexus EMR FHIR Implementation Guide"
// Standards status: trial-use (promoted from experimental/draft)
* ^extension[+].url = "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status"
* ^extension[=].valueCode = #trial-use
// ========== CORE NEXUS EMR REQUIREMENTS (CLINICAL SAFETY) ==========
// Business identifiers -- recommended, not required, and NOT the task's identity.
//
// The inherited `1..*` floor was written for tasks that arrive from somewhere else, where an
// identifier is the only way to say which upstream record a task corresponds to. It does not
// survive contact with a task BORN IN THE EMR: a clinician typing a to-do into the chart has no
// external source system to be identified against, and the server-assigned id already answers
// "which task is this". Requiring a business identifier there forces a writer to mint a
// meaningless one, and a meaningless identifier is worse than none -- it looks like a key into
// something.
//
// TWO systems ARE named, for one population: a task a machine writes on its own behalf carries a
// business key, and that key is what stops a rule that runs nightly from filing the same task
// every night. WHICH system depends on WHICH producer -- NamingSystem/nexus-harness-key for the
// AI harness, NamingSystem/nexus-cds-key for a decision-support rule -- and they are separate
// because a producer searches its key and UPDATES WHAT IT FINDS, so a shared key space would let
// one producer's re-run overwrite the other producer's work item. See those NamingSystems for the
// key shapes and for the failure mode (a key derived from the run rather than from the gap changes
// on every execution, which is the duplicate it was meant to prevent). Human-created tasks are unaffected:
// no canonical system is mandated for them, and now none is required either.
// NOT Must Support, and the reason is that nothing mints one. `identifier` here is
// RECOMMENDED but not required, under no mandated system -- and since the instance-scoped
// scheme was retired (FHIR-71) no producer writes a business identifier onto this type at
// all. Must Support asserts that an implementer can be expected to populate an element;
// claiming it for one the specification neither mandates nor produces states a guarantee
// that is not being made. The element stays available and documented -- a writer with a
// source-system identifier should still carry it.
* identifier 0..*
* identifier ^short = "Business identifier(s) for the task (any system; machine-written tasks carry their producer's key)"
* identifier ^definition = "Business identifier(s) for task tracking and audit. A business identifier is RECOMMENDED but not required, and no specific canonical system is mandated: a task that originates in an external system should carry that system's identifier, while a task created inside the EMR has no external record to name and is tracked by the server-assigned id alone. A task a machine writes on its own behalf SHOULD carry an identifier under its own producer's key namespace -- ../NamingSystem/nexus-harness-key for the AI harness, ../NamingSystem/nexus-cds-key for a decision-support rule -- whose value is derived from the GAP the task addresses rather than from the run that produced it, so that re-running the producing capability updates this task instead of creating a second one. The two namespaces are deliberately separate: a producer searches its key and updates the task it finds, so a shared key space would let one producer's re-run overwrite the other producer's task."
* identifier ^comment = "Readers must tolerate a task with no identifier at all -- that is the ordinary shape of a task created in the chart, not a malformed record. For machine-written tasks the producer's business key is the idempotency contract: a producer searches `Task?identifier={its own key system}|{key}` before writing (`../NamingSystem/nexus-harness-key|{key}` for the harness, `../NamingSystem/nexus-cds-key|{key}` for a decision-support rule), updates the task it finds, and resolves that task when the gap it addresses no longer holds. Not sliced here: the element is left open, so adding the key is additive for every existing writer. A source system's own identifier SHOULD be carried alongside this one, flagged `use = secondary`. See [Carrying the raw code](../guide/patterns/raw-codes.md)."
// Task lifecycle state machine (from original Nexus EMR design)
* status 1..1 MS
* status ^short = "Where the task is in its lifecycle"
* status from NexusTaskStatusesVS (required)
* status ^definition = """
Where this task sits in its lifecycle. THESE ARE MEANINGS, NOT A PATH -- any state may follow any
other, and the ordinary cases prove it: `ready` straight to `completed` is a normal day's work, and
`accepted` back to `ready` is handing something back. What each code means is the specification;
the order is not.
- `draft` -- being composed. In nobody's list yet, and nobody is expected to act on it.
- `ready` -- actionable and in its owner's list. Where the owner is a CareTeam, it is in the
team's pool and nobody has claimed it. Where there is no owner at all, it is in EVERY user's
list: unassigned work is ready work that has not been narrowed to anyone yet.
- `accepted` -- claimed by its owner and not yet started. The point of a state between `ready` and
`in-progress` is CIRCULATION: claiming a pooled task moves `owner` from the team to the person
and takes it out of everyone else's view, which is a real event even though no work has started.
- `in-progress` -- actively being worked.
- `on-hold` -- deliberately parked: snoozed, or waiting on something outside this task. Distinct
from `ready` because a parked task should not read as awaiting action.
- `completed` -- the work was done.
- `cancelled` -- the work will not be done. This covers BOTH a proposal a human declined and a
proposal that became moot (its alternative was approved, or the gap closed on its own), which is
why `Task.statusReason` matters here more than anywhere else on this profile.
"""
* status ^comment = "The binding is a REQUIRED subset of R4 TaskStatus, not the base value set: `requested` (a second name for `ready`), `received`, `rejected`, `failed` and `entered-in-error` are excluded, each for a reason given on the value set. The one worth knowing is `rejected`: a declined proposal is `cancelled`, so declining something and it becoming moot no longer live in different states. `Task.statusReason` carries which of the two happened and SHOULD be populated whenever a proposal is cancelled -- without it the record cannot say whether a clinician considered this and said no."
// OWNERSHIP: `owner` records NARROWING, not presence.
//
// `owner` names the party responsible for the next action on this task. It is 0..1, and BOTH
// states carry meaning:
//
// * ABSENT -- the task is the responsibility of EVERY user in the clinic. Responsibility has not
// been narrowed to anyone. This is not "nobody owns it" and not "the owner is unknown": an
// unassigned task is the clinic's collective work, and it is the ordinary state of incoming
// work that has not yet been triaged.
// * PRESENT -- responsibility has been NARROWED to one named party: a person, a role, a standing
// team, or an agent.
//
// Assignment is therefore an act of narrowing. A task starts as everyone's and becomes someone's.
//
// THE CONSUMER OBLIGATION THAT MAKES THIS SAFE. An absent owner means "everyone's" only if
// everyone can see it without going to look. A system implementing this profile MUST surface
// unassigned tasks in the DEFAULT inbox view of every user -- present by default, not behind a
// filter, a tab the reader must select, or a saved search, and counted wherever outstanding work is
// counted. Without that, an absent owner degrades into exactly what a mandatory owner was written
// to prevent: work that exists, that no worklist shows, and that nobody is looking for. This
// obligation is part of the meaning of the element, not a UI preference.
//
// EXACTLY ONE, WHEN THERE IS ONE. `owner` never repeats. A task held by two parties is held by
// neither; the most recent transfer determines who holds it. A CareTeam owner does not weaken
// this: the cardinality is what buys accountability, not the target type, and `owner` is still a
// single reference when it names a nursing pool. A standing team holding the work is a true
// statement about who has it, and a member claiming it is a real ownership transfer with real
// Provenance. `groupIdentifier` names the batch or work stream a task belongs to; it is not the
// ownership mechanism.
//
// ONE SPELLING OF UNASSIGNED. An absent `owner` is the only way to say it. Do NOT introduce a
// sentinel owner to avoid an empty element -- an "unassigned" CareTeam seeded per tenant, or an
// Organization standing in for the practice. A sentinel reads as NARROWED to every consumer that
// tests whether the element is populated, which makes un-narrowed work indistinguishable from work
// a team is actually holding, and it puts two spellings of one state into the estate for every
// reader to reconcile from then on. Organization is not a permitted owner target, and this is one
// of the reasons.
//
// ================================ NOT SETTLED ================================
// THE CARDINALITY OF THIS ELEMENT IS UNDER ACTIVE REVIEW AND MAY CHANGE.
//
// Permitting an absent owner is new in 1.26.0. The competing position -- that every task must name
// an owner at the moment it is written, with a configured default standing in where the producer
// has nobody to name -- is held by product and has NOT been resolved. It is scheduled to be settled
// after the September 2026 demo.
//
// What would decide it: whether an obligation exists that every unit of clinical work name an
// accountable party at all times, and if so whether a work queue, a role or a standing team
// satisfies it. The relevant EMR certification language requires a task to carry "an assignee (a
// user or role)" -- which a CareTeam or PractitionerRole owner meets and which this profile's
// absent-owner state does not obviously meet.
//
// A PRODUCER THAT ALWAYS SETS owner CONFORMS UNDER EITHER OUTCOME. Build that way if you can.
// A CONSUMER MUST handle an absent owner today, and must keep the visibility obligation above
// whichever way the cardinality lands, because it is the reason the absent state is permitted.
// =============================================================================
* owner 0..1 MS
* owner only Reference(NexusEmrCorePractitionerRole or NexusEmrCorePractitioner or NexusEmrCoreCareTeam or Device)
* owner ^short = "Who holds this task now; absent means the whole clinic holds it"
* owner ^definition = """
Who is responsible for the next action on this task.
ABSENT -- responsibility has NOT been narrowed: the task belongs to every user in the clinic.
Unassigned work is collective work, not unowned work, and a consumer MUST surface it in every
user's default inbox view (see the element comment). This is the ordinary state of work that has
arrived and not yet been triaged, including work written by an external system that names no owner.
PRESENT -- responsibility is narrowed to exactly one party:
- An individual practitioner (the ordinary case)
- A practitioner role, when the capacity is what matters rather than the individual
(the on-call physician, the nurse covering a clinic)
- A CareTeam for group assignment - the sanctioned mechanism for pool/work-stream
ownership (e.g., a nursing pool): the team as a whole holds the work until a
member claims or completes the task. `groupIdentifier` remains available to name the
batch or work stream a task belongs to; it is not the ownership mechanism.
- Machine actors as first-class owners: a LOGICAL Device reference (Reference.identifier
under the producing registry's namespace -- ../NamingSystem/nexus-harness-graph
naming a harness graph, or ../NamingSystem/nexus-cds-rule naming a
decision-support rule -- with Reference.type = "Device"; the identifier need not resolve
to a Device resource on the server). Assigning a Task to a HARNESS GRAPH is additionally
the approve/resume contract: the harness watches for task-assignment changes and resumes
(or starts) the thread named by the thread-id extension. That contract is the harness's
own; assigning a task to a rule carries no such undertaking.
An absent owner is the ONLY representation of unassigned. A sentinel owner -- a per-tenant
"unassigned" CareTeam, or an Organization standing for the practice -- is a second spelling of one
state, reads as narrowed to any consumer testing whether the element is populated, and must not be
written.
NOT SETTLED (1.26.0): whether an absent owner is permitted at all is still open, and this element
may change in a future release. The competing position is that every task names an owner when it is
written, with a configured default owner where the producer has nobody to name. It is scheduled to
be settled after the September 2026 demo. A producer that always sets owner conforms under either
outcome; a consumer must handle an absent owner today.
"""
* owner ^comment = "The owner is responsible for the next action on this task. Ownership transfers with each significant action (forward, reply, assign-to-agent, claim-from-pool, etc.). When `owner` is ABSENT, responsibility has not been narrowed and rests with every user in the clinic: a consumer MUST show unassigned tasks in each user's default inbox view rather than behind a filter or a tab the reader must select, and count them wherever outstanding work is counted. That visibility is what makes the un-narrowed state safe; a consumer that hides it has not implemented this element. Assigning a CareTeam narrows responsibility to the team as a unit; accountability remains singular because the reference is still exactly one owner. Note the asymmetry with `note.author`, which CANNOT be a CareTeam or a PractitionerRole -- R4 does not permit either as an `Annotation.author` target, so a task owned by a team still has every turn authored by a person (see the Task Note profile). Reference.display SHOULD carry the human-readable name (person, team, or graph). NOT SETTLED (1.26.0): whether an absent owner is permitted at all is under review and may change in a future release -- see the element definition."
// Task intent -- narrowed to three codes, not pinned to one.
//
// BREAKING CHANGE from the fixed `#order` (see the CHANGELOG). The fix was right for the
// population it was written for: inbox items, follow-ups and to-dos really are orders, and
// pinning the value stopped a scatter of intents describing identical work. Suggestions were
// then modelled onto this same profile, and a suggested chart entry awaiting a clinician's approval
// is the one thing "not proposals or plans" excluded -- leaving `intent` unable to distinguish
// "assigned to you to do" from "awaiting your approval", the distinction it exists for.
//
// `intent` does NOT say whether a task carries a suggested resource. That is worth stating flatly,
// because an earlier revision of this profile treated it as though it did. A suggested-resource
// task is one carrying a CONTAINED prototype graph, and it can be raised at any of these three
// intents; conversely an ordinary inbox task is `#order` and contains nothing. The two questions
// are independent, and all four combinations occur.
//
// NOTE FOR READERS COMING FROM ServiceRequest: `proposal` there (on a referral, say) is the same
// word on a different resource and carries no relationship to this element. Nothing on a Task
// reads it, and the two never appear together.
* intent 1..1 MS
* intent from NexusEmrTaskIntentVS (required)
* intent ^short = "order (do this) | proposal (consider this) | option (one of these)"
* intent ^definition = """
What the owner is being asked to do with this task. Independent of whether the task carries a
suggestion.
* `order` -- the work is authorized and assigned; the owner is expected to DO it. Inbox items,
follow-ups and to-dos are orders, and a user sees them in a Tasks list. A suggested-resource
task MAY be an order, where the suggested entry is already authorized and the task exists to
get it recorded rather than decided.
* `proposal` -- something is being offered and takes effect only if the owner APPROVES it, which
flips this element to `order`, one-way. A user sees proposals in a Suggestions list rather
than a Tasks list, and that list membership is the whole practical meaning of this code. A
machine-extracted chart entry pending review is the usual case: the requester (a non-human
agent) has no authority to commit it.
* `option` -- this task is ONE OF A SET of alternatives, grouped by a shared `groupIdentifier`.
Accepting one moots the others, which are then cancelled rather than rejected. A
decision-support card offering three ways to close the same gap raises three tasks at
`option`, not three independent proposals.
"""
* intent ^comment = "A consumer branching on 'is this mine to do, or mine to decide?' reads `intent`, and a UI splitting a Suggestions list from a Tasks list is reading exactly this element. A consumer asking 'does this carry a suggested chart entry?' must NOT read it: read the contained Bundle, because an `#order` carrying a suggested resource is a real and ordinary shape. APPROVING a proposal sets this element to `order` and is one-way; it moves the task between lists and writes nothing to the chart. That is a different act from ACCEPTING the task (`Task.status`) and from INSTANTIATING its contained graph -- see the suggested-resource section for all three."
// Clinical priority
* priority 0..1 MS
* priority ^short = "How urgent the task is"
* priority from http://hl7.org/fhir/ValueSet/request-priority (required)
* priority ^definition = "Clinical priority level for workflow triage and routing."
* priority ^comment = "Used for inbox sorting and urgent task highlighting in UI. `routine` is the FLOOR of this vocabulary and the binding cannot be widened -- base R4 binds it REQUIRED, a profile may only strengthen a binding, and the element is a bare `code` with no second coding slot even if it could. A priority below routine therefore rides the `priorityDetail` extension below, under a rule that makes it safe to ignore."
* priority.extension contains TaskPriorityDetail named priorityDetail 0..1 MS
* priority.extension[priorityDetail] ^short = "A refinement finer than request-priority allows (currently: trivial)"
* priority.extension[priorityDetail] ^comment = "When present, `Task.priority` SHALL be `routine` (nexus-task-priority-detail-1). A consumer that does not read this extension therefore sees `routine`, the nearest true statement in the base vocabulary, and under-states the task rather than mis-sorting it."
// Patient context (strongly recommended; always present on chart-born tasks).
//
// This was `1..1` "for clinical safety", and the intent was right for the population in view:
// a clinical task whose patient link is missing IS a safety problem, and every task created from a
// chart carries one. But the profile also holds work that is genuinely about no patient -- restock
// the fridge, complete the cold-chain log, chase a fax line -- and a required `for` does not make
// those safer, it makes them unrepresentable, which pushes them into some other system where the
// EMR cannot see them at all. Relaxed to 0..1 with the expectation stated instead of enforced.
* for 0..1 MS
* for only Reference(NexusEmrCorePatient)
* for ^short = "Patient this task is about, when it is about one"
* for ^definition = "The patient this task concerns. Patient context is STRONGLY RECOMMENDED and is always set for a task created from a patient chart, because a clinical task whose patient link is missing is a safety problem. It is not required, because the profile also carries standalone work items -- administrative or practice-level to-dos -- that are about no patient at all."
* for ^comment = "When present the reference must be a NexusEmrCorePatient. Readers must tolerate its absence and treat a patient-less task as a standalone work item, not a malformed record; a surface that assumes `for` is populated will drop those tasks or fault on them. Never infer the patient from `focus` -- `focus` is the chart element the task is filed against, and a task can carry one without the other."
// Clinical encounter context
* encounter 0..1 MS
* encounter only Reference(NexusEmrCoreEncounter)
* encounter ^short = "Healthcare encounter during which task was created"
* encounter ^definition = "Links the task to the specific clinical encounter that generated it."
* encounter ^comment = "Provides clinical context for task creation and helps with documentation workflow."
// Task creation timestamp (REQUIRED for audit - enhanced vs MERT)
* authoredOn 1..1 MS
* authoredOn ^short = "When task was first created"
* authoredOn ^definition = "Timestamp when the task was initially created for complete audit trail."
* authoredOn ^comment = "Nexus EMR requires creation timestamp (1..1) vs MERT optional (0..1) for audit compliance."
// Task requester (REQUIRED for accountability - enhanced vs MERT)
* requester 1..1 MS
* requester only Reference(NexusEmrCorePractitionerRole or NexusEmrCorePractitioner or Device)
* requester ^short = "Who originally requested this task (person, AI graph, or decision-support rule)"
* requester ^definition = "The person or agent that initiated this task. THIS IS WHERE THE PRODUCER OF A MACHINE-WRITTEN TASK IS DECLARED, and a consumer telling producers apart reads this element and nothing else. Machine-created tasks (e.g. suggestions) use a LOGICAL Device reference: Reference.type = \"Device\" and Reference.identifier under the producing registry's namespace -- ../NamingSystem/nexus-harness-graph naming the AI-harness graph, or ../NamingSystem/nexus-cds-rule naming the decision-support rule. Two namespaces because two separately owned registries mint these values and either could mint the same string. The identifier need not resolve to a Device resource on the server -- it points into the producing registry. Granularity is the graph or rule (a name a clinician or auditor can recognize); per-agent trace stays with the producer."
* requester ^comment = "Nexus EMR requires requester (1..1) vs MERT optional (0..1) for clear accountability chain. Reference.display SHOULD carry the human-readable name. Ask \"was the requester a machine\" with `Reference.type = \"Device\"` and \"was this content machine-produced\" with the AIAST security label; read `identifier.system` only for WHICH KIND of producer, and expect the list of producing registries to grow. Do NOT infer the producer from `intent` (humans raise proposals) or from `groupIdentifier` (grouping is available to every producer)."
// Original content (REQUIRED for clarity - enhanced vs MERT)
// THIS IS THE ASK. `description` is the task's opening statement -- what is being asked, and why
// the task exists -- written by whoever created it and stable for the life of the task. The
// conversation that follows is `note`, which is what has been said SINCE and is not required.
* description 1..1 MS
* description ^short = "The ask: original task content, stable throughout lifecycle"
* description ^definition = """
Canonical task description that provides the core content and remains stable throughout the task lifecycle.
This is the ASK -- the statement of what is wanted and why the task exists. The turns that follow it
live in `note`, and a writer should NOT duplicate this text into `note[0]`: that puts the same
statement in two places and opens the conversation with something nobody said.
May include structured forms (lab requisition, referral, etc.) and supports Markdown formatting for rich content.
"""
* description ^comment = "Nexus EMR requires description (1..1) vs MERT optional (0..1) to prevent ambiguous work items. It is also what makes `note` optional: the ask is carried here, so a task with no conversation on it yet is complete rather than malformed."
// ========== MERT COMPATIBILITY ENHANCEMENTS ==========
// Task category -- the bin a task is filed under in a user's view.
//
// R4 calls this element "Task Type" and binds it at EXAMPLE strength to a vocabulary of actions
// taken on the focal resource (approve, fulfill, abort, replace, change, suspend, resume). That
// axis is not used here: a task that suggests a change to an existing resource names its target
// on `focus` and carries the suggested content contained, so the action is read off the task's
// shape. Coding it as well would let the two disagree.
//
// The bound vocabulary is a CATEGORY axis for organizing worklists, and it is expected to grow
// as more bins prove worth separating. It classifies for presentation: it does not define what a
// task is, and it makes no claim about what produced the task. The binding is EXTENSIBLE, so a
// deployment needing a bin this value set lacks carries its own coding without waiting.
* code 0..1 MS
* code from NexusTaskCodesVS (extensible)
* code ^short = "The category the task is filed under"
* code ^definition = "The category this task is filed under, so a view can sort tasks into bins. The vocabulary is expected to grow. The element is OPTIONAL -- most tasks in the chart predate this vocabulary and carry none, and readers must tolerate its absence rather than treat it as malformed. Extensible: a deployment whose category has no concept in the bound value set stays conformant under its own system."
* code ^comment = "THREE INDEPENDENT AXES, and this is only one of them. This element says what KIND of work a task is. Whether it carries a suggested chart entry is a different question, answered by whether it contains a prototype graph -- a `call`, an `appointment` and a `review-report` can each carry one. Whether it is authorized or awaiting a decision is a third, answered by `Task.intent`. An earlier revision of this vocabulary carried a `suggestion` code, which forced the second axis onto an element that holds one value and made the other eight categories unusable on a proposal. Read `Task.requester` for what produced the task; none of these codes say."
// Protocol and authorization references (MERT requirements)
* instantiatesCanonical 0..1 MS
* instantiatesCanonical ^short = "Formal definition of task (canonical)"
* instantiatesCanonical ^definition = "References to formal protocols, guidelines, or ActivityDefinitions that this task follows."
* instantiatesCanonical ^comment = "MERT requirement for protocol-based task execution."
* instantiatesUri 0..1 MS
* instantiatesUri ^short = "Formal definition of task (URI)"
* instantiatesUri ^definition = "URI references to external protocols, guidelines, or specifications."
* instantiatesUri ^comment = "MERT requirement for external protocol references."
// NOT must-support, deliberately -- see the note under `reasonReference`, which is the same case.
* basedOn 0..*
* basedOn only Reference(ServiceRequest or MedicationRequest or CarePlan or SupplyRequest)
* basedOn ^short = "Request fulfilled by this task (available, not must-support)"
* basedOn ^definition = "The request, order, or authorization that initiated this task."
* basedOn ^comment = "The ORDER this task carries out, and only an order: base R4 leaves this open to any resource, and this profile narrows it to the four request types, so `basedOn` cannot quietly become a second `focus`. Distinct from `focus` (the chart element the task is filed against) and from `encounter` (the visit it arose in). Available and typed, but not must-support -- populate it when a task genuinely fulfills an order, and do not synthesize one to fill the element."
// Task grouping.
//
// The shared value that says "these tasks were raised together". Its load-bearing use is the
// decision-support CARD: one evaluation produces several suggestions, and a reader that cannot
// recover the set will present them as unrelated proposals that happen to have arrived at the
// same moment. Every task from one card carries that card's identifier here, so the set is
// recoverable with a single `Task?group-identifier=` search and no parent resource has to exist.
//
// Grouping does NOT by itself say the members are alternatives -- a card may equally offer
// several things all worth doing. `intent = #option` is what says "pick one"; grouping says
// "these arrived together". Read them together.
* groupIdentifier 0..1 MS
* groupIdentifier ^short = "Shared identifier for tasks raised together (e.g. one decision-support card)"
* groupIdentifier ^definition = "Identifier shared by every task raised in one batch, so the batch is recoverable as a set. For suggestions produced by a decision-support service, this carries the CARD: all of a card's suggestions become sibling tasks with the same value here. Distinct from `Task.identifier`, which identifies THIS task (and, for machine-written tasks, the gap it addresses under the producing capability's key namespace)."
* groupIdentifier ^comment = "A DISPLAY GROUPING AND NOTHING ELSE: consumers MUST NOT read this element, or its absence, as a signal of which producer raised a task, because grouping is available to every producer -- a harness capability proposing several chart entries from one note is one evaluation raising a set exactly as a card is. Producer is declared on `requester`. Find the siblings with `Task?group-identifier={system}|{value}`. Grouping is orthogonal to `intent`: siblings are ALTERNATIVES only when they carry `intent = #option`, in which case accepting one normally cancels the rest. Where the group has no natural upstream identifier, any stable value the producer can regenerate will do -- but derive it from what the card is ABOUT, on the same reasoning as the business key, or a re-evaluation produces a new group for the same advice."
* businessStatus 0..1 MS
* businessStatus from NexusTaskBusinessStatusAllVS (required)
* businessStatus ^short = "Task business status"
* businessStatus ^definition = "Business-specific status information that supplements the standard lifecycle status. `status` answers where the task sits in its lifecycle; `businessStatus` answers whether anything about it needs a human's attention."
* businessStatus ^comment = "MERT requirement for additional status context beyond standard FHIR states. This element carries a lifecycle SUB-STATE of the task itself -- a second axis beside `status`, not a flag and not a category. ⚠ THE BINDING IS REQUIRED, and was extensible until 1.26.0. A sub-state this guide does not recognise is an ERROR, not a local extension: this element sits beside `status` and reads as status, a statutory correction outcome is recorded here, and an element carrying decisions of that weight cannot also be where a deployment parks arbitrary workflow state -- a reader cannot tell the two apart. A deployment that needs a sub-state this guide does not define gets it added to the bound value set, in a reviewed release; it does not mint one locally. TWO VOCABULARIES share the binding and they are NOT interchangeable: the general sub-states, and the statutory correction lifecycle, which `nexus-task-bizstatus-scope` confines to tasks filed under `privacy-request` -- a correction code on ordinary work is an error. See the Correction Task profile for the tighter shape those tasks declare. `needs-review` is DEPRECATED and inbound/legacy only: the workflow it was built for (a completed referral that a new message should resurface) is modelled as a NEW Task on the same ServiceRequest, because a completed task does not come back to life."
* statusReason 0..1 MS
* statusReason ^short = "Reason for current status"
* statusReason ^definition = "Captures why the task is in its current state, particularly for cancelled or failed states."
* statusReason ^comment = "Load-bearing on a CANCELLED PROPOSAL and close to required there in practice. `cancelled` carries two facts that used to be separate states: a human considered this and declined it, and this stopped being on offer (its alternative was approved, the care gap closed on its own). Those are different clinical records and only this element can now tell them apart, so a writer cancelling a proposal without a reason destroys information the model can no longer recover."
// ========== THE LINKED CHART ELEMENT ==========
//
// THE RULING THIS ELEMENT CARRIES (FHIR-31, "forms and inbox documents: where do they live").
// They live where every other clinical fact lives: as their own resource in the chart. A form
// is a QuestionnaireResponse, an inbox document is a DocumentReference, an encounter note is a
// Composition. What a task adds is the WORK -- who was asked, who owns it now, what was said --
// and a reference to the thing the work is about. The task does not contain the content and does
// not duplicate it.
//
// That answers the question the ticket actually asks. "Where do forms live" reads as a storage
// question and is really a boundary question: if the answer were "inside the task", every
// consumer that wants the form has to know about tasks, the form disappears when the task is
// completed, and the same document filed twice exists twice. Pointing at the chart element keeps
// one copy, visible to readers who never look at an inbox.
//
// TYPED, NOT `Reference(Resource)`. The old constraint admitted anything, which documents
// nothing and lets a writer point `focus` at a Patient or an Organization and still conform.
// The list below is the chart-element surface a task is about in practice: the first three are
// the overwhelming majority (form, inbox document, authored note), the rest are the orders and
// clinical entries a task routinely follows up. Add to it deliberately when a real workflow
// needs a type that is missing, rather than reopening it to `Resource`.
//
// `AllergyIntolerance` was added in 1.21.0, after the list had already shipped without it. The
// omission was not caught because the retire worked example -- the one the suggested-resource
// handbook leads with -- carries an identifier-only `focus`, and a reference with no `reference`
// and no `Reference.type` gives a validator no target type to check. It conformed by being
// unresolvable. A producer doing the ordinary thing and writing `AllergyIntolerance/123` would
// have been rejected by the example that taught them the pattern.
* focus 0..1 MS
* focus only Reference(NexusEmrCoreQuestionnaireResponse or NexusEmrCoreDocumentReference or NexusEmrCoreComposition or NexusEmrCoreCondition or NexusEmrCoreDiagnosticReport or NexusEmrCoreServiceRequest or NexusEmrCoreMedicationRequest or NexusEmrCoreObservation or NexusEmrCoreAllergyIntolerance)
* focus ^short = "The chart element this task is about (form, inbox document, note, ...)"
* focus ^definition = """
The patient-chart element this task concerns: the form that was completed, the document that
arrived, the note that needs signing, the problem being followed up.
Forms and inbox documents are NOT stored inside the task. A completed form is a
`QuestionnaireResponse`, an arriving document is a `DocumentReference`, an authored note is a
`Composition`, and the task points at it. One copy, in the chart, readable by consumers that
know nothing about task workflow.
**`focus` does NOT say what a suggested-resource task would write.** An earlier revision of this profile made it
the add-versus-update marker -- `focus` absent meant add, `focus` present meant update. That broke
on the first suggested-resource task that wanted to do both, because `focus` is 0..1. What each suggested resource
would do to the chart is now `entry.request` inside the contained prototype Bundle: `method` POST
to create, PUT to update, with the target on `request.url`, stated once per entry.
So `focus` on a suggested-resource task means what it means everywhere else on this profile: the
chart element the task is filed against. A suggested change to a medication may well name that
medication here, because that is what the task is about -- but it is `entry.request` that makes it
an update, and a reader must not infer one from the other.
Retiring an entry is the same shape: there is no delete in this chart, so a suggestion to withdraw
a resource is an update whose payload carries the entered-in-error status its own resource type
defines. `focus` names the target, the payload states the end state, and nothing here needs a
vocabulary of actions.
"""
* focus ^comment = "`focus` is what the task is ABOUT; `input` carries what the task NEEDS -- chiefly a contained machine-suggested resource. A reader looking for 'which chart element is this task on' reads `focus` and nothing else. Where a workflow genuinely spans several elements, `focus` names the one the task is filed against and the rest ride in `input`. ALWAYS A RESOURCE THAT ALREADY EXISTS IN THE CHART: never a contained resource, never a local `#` reference, enforced by nexus-task-focus-not-contained. On a suggested-resource task it does NOT say whether a suggested resource is created or updated -- that is `entry.request.method` inside the contained Bundle, stated per suggested resource, so one task can do both."
* reasonCode 0..1 MS
* reasonCode ^short = "Why task is needed (coded)"
* reasonCode ^definition = "Coded indication of why the task was created."
* reasonCode ^comment = "MERT requirement for coded task rationale. Where this code was mapped from a source system's own vocabulary, carry the raw coding alongside the mapped one, flagged `userSelected = true`. See [Carrying the raw code](../guide/patterns/raw-codes.md)."
// Execution and modification tracking (MERT requirements)
* executionPeriod 0..1 MS
* executionPeriod ^short = "Start and end time of execution"
* executionPeriod ^definition = "Expected or actual time period during which the task is to be or was executed."
* executionPeriod ^comment = "MERT requirement for task timing management."
* lastModified 0..1 MS
* lastModified ^short = "Task last modified date"
* lastModified ^definition = "Most recent timestamp when the task was modified."
* lastModified ^comment = "MERT requirement for modification tracking."
// Performer specifications (MERT requirements)
* performerType 0..* MS
* performerType ^short = "Requested performer type"
* performerType ^definition = "The type of performer (person, device, organization) required to complete the task."
* performerType ^comment = "MERT requirement for specifying required performer characteristics."
// Location and administrative context (MERT requirements)
* location 0..1 MS
* location only Reference(NexusEmrCoreLocation)
* location ^short = "Where task should be performed"
* location ^definition = "Principal physical location where the task is to be performed."
* location ^comment = "MERT requirement for task location specification."
* insurance 0..* MS
* insurance only Reference(Coverage)
* insurance ^short = "Associated insurance coverage"
* insurance ^definition = "Insurance coverage that is relevant to the performance of this task."
* insurance ^comment = "MERT requirement for insurance context."
// Task constraints (MERT requirements)
* restriction 0..1 MS
* restriction ^short = "Constraints on fulfillment tasks"
* restriction ^definition = "Constraints that apply to the fulfillment of the task."
* restriction ^comment = "MERT requirement for task execution constraints. `restriction.period` is where a DUE DATE lives: its end is the time by which the task should be completed, per the base definition, and it is the element an inbox sorts overdue work on. For a `privacy-request` task that due date is the STATUTORY RESPONSE DEADLINE -- an individual's request to access or correct their own record has to be answered within a period set by law, and no privacy-specific element exists or is needed to hold it. Do not write a due date on `executionPeriod`, which means when the work is being or was done: a deadline written there produces a task claiming to have been worked on a date in the future."
// ========== NEXUS EMR TASK RELATIONSHIPS ==========
// Task relationships for forking/branching (Nexus EMR workflow feature)
* partOf 0..* MS
* partOf only Reference(NexusEmrCoreClinicalTask)
* partOf ^short = "Parent task for sub-tasks and branches"
* partOf ^definition = "Reference to parent task when this task is part of a larger workflow or represents a sub-task."
* partOf ^comment = "Supports Nexus EMR workflow branching and task hierarchy."
// Clinical context and reasoning
//
// `reasonReference` and `basedOn` are AVAILABLE BUT NOT MUST-SUPPORT, which is a narrowing in
// 1.17.0. Must-support is a claim that a consumer of this IG will do something meaningful with a
// populated element, and this IG is not yet in a position to make that claim for either: no
// producer in scope populates them, and the chart surfaces that display a task read `focus`,
// `owner`, `requester`, `status`, `priority` and the due date. Advertising support the estate does
// not have has a specific cost -- it pushes producers to populate an element with the nearest
// resource to hand, which is how a `reasonReference` ends up pointing at the Patient.
//
// Both remain fully modelled and both remain TYPED (base R4 leaves each open to any resource), so
// a producer with a real order or a real clinical justification should populate them and will be
// held to the right target types. What would make them must-support: a consuming surface that
// reads them. Note the overlap with `focus`, which is the element to reach for first -- see the
// long note there for the `focus` / `input` division FHIR-31 settled.
* reasonReference 0..1
* reasonReference only Reference(Condition or Observation or DiagnosticReport or DocumentReference)
* reasonReference ^short = "Clinical reason for this task (available, not must-support)"
* reasonReference ^definition = "Reference to the clinical finding that justifies the task -- the condition being followed up, the abnormal result being chased, the document being actioned."
* reasonReference ^comment = "Why the task exists, pointing at a clinical resource; `reasonCode` carries the same fact as a code. Not the same as `focus`, which is the chart element the task is filed AGAINST: a task to review an abnormal potassium has that DiagnosticReport as its `focus`, and the Condition it relates to (if any) as its `reasonReference`. Never the Patient -- every task is about the patient, so that says nothing."
// Additional context and notes
// THE CONVERSATION LIVES HERE, AND ONLY HERE. `Annotation` carries author and time as well as
// text, so the repeats ARE the message thread -- the "who said what, when" that makes a reassigned
// task intelligible to the person who receives it. Ordered oldest-first by `time`.
//
// THE ASK IS `description`, NOT `note[0]`. The task's opening statement -- what is being asked, and
// why the task exists -- is `description`, which this profile requires (1..1) and which is stable
// for the life of the task. `note` is what has been said SINCE: the question that came with a
// forward, the answer that came back, the reason it was put on hold. A reader wanting "what is this
// task about" reads `description`; a reader wanting "what has been said about it" reads `note`.
//
// WHY 0..*, RELAXED 2026-08-21. An earlier revision of this profile made `note` 1..* and declared
// `note[0]` the opening ask, reasoning that a task with no note is work assigned with no statement
// of what is being asked. That reasoning was already answered by the element above: `description`
// is required here, and it IS the statement of the ask. Requiring a turn as well made every writer
// copy the description into `note[0]` to satisfy the cardinality -- the same statement in two
// places, and a thread that opens with something nobody actually said. A task nobody has commented
// on yet is an ordinary, correct state (newly created work), not a malformed record, and the model
// has to be able to represent it.
//
// The conversation runs the WHOLE LIFE of the task: extended at every handoff, still readable when
// the task is closed a year later and someone asks what happened. That continuity is why the turns
// live on the task itself rather than in resources that have to be gathered up, and why this
// element is must-support for every consumer that renders a task at all -- must-support is about
// handling the element when it is present, and an empty thread is a state a renderer must handle
// too.
//
// ONE MECHANISM, NOT TWO (ruled 2026-08-19). `Communication` is NOT used for the conversation on a
// task, in either direction, for either humans or agents. An earlier design paired every Task with
// Communication resources for its turns; that is superseded. The reasons, recorded so this is not
// re-litigated from scratch:
//
// * A turn is not independently meaningful. It exists in the task, is read in the task, and is
// handed over with the task. Containment-by-element matches that.
// * Atomicity. "Say something and hand it over" is ONE write: append a note, change `owner`.
// With separate Communication resources it is two writes needing a transaction Bundle, and a
// partial failure leaves either a turn nobody was handed or a handoff with nothing said.
// * No threading model is required. A single ordered repeating element IS the thread. The
// Communication profile's `inResponseTo`-vs-`partOf` threading question is explicitly
// unsettled and its ordering is reconstructed from timestamps; none of that arises here.
// * `Communication` is not in the subscribable type set, so a conversation built from it could
// not be watched directly. `Task` is.
//
// What is GIVEN UP by this ruling, stated plainly so nobody is surprised: an Annotation cannot
// carry `meta.security` (so the AI-authored label rides the TASK, not the individual turn), cannot
// be the target of its own `Provenance` (turns are not state changes, so `relevantHistory` is
// unaffected), and cannot carry structured attachments or citations (a turn is markdown text; an
// answer that must cite chart resources cites them from the Task, not from inside the turn).
// GRADUATION VALVE: if a consumer ever needs per-turn identity, search, or structured payload,
// turns can move to `Communication` ADDITIVELY -- the Task spine, its ownership, and its business
// identifier do not change.
//
// This is deliberately separate from `relevantHistory`, which is Provenance and records what
// HAPPENED to the task (created, forwarded, completed, and by which agent). Notes are what people
// SAID.
//
// `relevantHistory` is NOT PROFILED here as of 1.20.0, and the distinction above is why it does not
// need to be. It carried a Must Support flag and a "MERT requirement" note, and what that bought
// was a hand-maintained list of back-pointers to Provenance resources that a consumer can already
// find by searching Provenance for a Task target. Base R4 still defines the element and this IG
// does not forbid it -- the examples here still carry it, and a consumer writing it stays
// conformant. What is gone is the obligation to maintain the list. Conflating them loses the distinction between an audit trail and a conversation, and it is
// the audit trail that has to survive independently of whether anyone chose to comment.
* note 0..* MS
* note only NexusEmrTaskNote
* note ^short = "The conversation on this task, oldest first; the ask itself is `description`"
* note ^definition = """
The conversation on this task, oldest first, and one of the reasons this profile exists.
What is being asked, and why the task exists, is `description` -- required, stable for the life of
the task, and NOT repeated here. `note` is what has been said SINCE: the question that came with a
forward, the answer that came back, the reason it was put on hold. Both people and AI-harness
graphs author turns (see the [Task Note](../fhir/StructureDefinition-nexus-emr-task-note.md) profile,
which carries the rules for machine authorship).
No turn is required. A task nobody has commented on yet carries no note at all, which is the
ordinary state of newly created work rather than a malformed record. A writer should NOT copy
`description` into a turn to fill the thread: that puts the same statement in two places and opens
the conversation with something nobody said.
The thread runs the whole life of the task -- extended at every handoff, still readable when the
task is closed and someone asks a year later what happened. A task handed between people is only
intelligible to the receiver if that exchange travels with it, which is why the turns live on the
task rather than in separate resources that would have to be gathered up.
This is the ONLY conversation mechanism on a task. `Communication` is not used for task turns.
"""
* note ^comment = "Notes are what people SAID; `relevantHistory` is what HAPPENED (Provenance: created, forwarded, completed, by whom). Keep them apart -- the audit trail must not depend on anyone having chosen to comment. The ask is `description`, so a consumer showing \"what is this task\" reads `description` and one showing \"what was said\" reads every note; `note[0]` is the first thing said AFTER the task was created, not the ask itself, and a task may have no notes at all. Turns are typed to the Task Note profile, which requires an author and a time on every turn and defines how an AI-harness graph is named as author (R4 does not permit Device on Annotation.author, and a profile cannot widen it)."
// Task input: reference(s) to the chart element(s) this task is about -- a report,
// requisition, prescription, problem, etc. The value is an open Reference (a task may
// reference anything in the chart). input.type is left as a free-text label for now
// (no controlled vocabulary bound yet), EXCEPT the `suggestion` slice below, which is
// pattern-discriminated. Task.output is intentionally NOT modelled.
//
// THAT LAST SENTENCE IS WHY THE INPUT AND OUTPUT LABEL VOCABULARIES ARE ASYMMETRIC HERE, and the
// asymmetry is deliberate rather than an omission. `CodeSystem/nexus-task-input-type` is bound into
// this file twice over -- it is the discriminating pattern on the `input[suggestion]` slice below
// and it is named literally in nexus-sugg-1 and nexus-sugg-2. Its counterpart,
// `CodeSystem/nexus-task-output-type`, is referenced from nothing: an accepted suggestion names the
// chart resource it produced on `Task.output`, but the element itself carries no slice, no binding
// and no invariant here. The vocabulary is declared so the label's `Coding.system` resolves;
// declaring it does not model the element, and this release does not model the element.
* input 0..* MS
* input ^short = "Resource(s) this task NEEDS in order to be worked"
* input ^definition = "Reference(s) to what the task needs -- chiefly the contained machine-suggested resource, and any additional chart elements a workflow spans beyond the one it is filed against. NOT the element the task is about: that is `focus`, which is typed. May reference any resource."
* input ^comment = "Read `focus` to answer 'which chart element is this task on'; `input` never answers that question on its own. input.type is a human-readable label for now; a controlled chart-element vocabulary may be bound later. Non-reference input parameters are not supported -- use note/description for free text."
* input.value[x] only Reference(Resource)
* input.value[x] ^short = "The referenced chart element (any resource)"
// ========== SUGGESTED-RESOURCE TASKS (contained prototype Bundle) ==========
//
// TERMINOLOGY FIRST, because two nearby ideas have been confused for each other and the words are
// now deliberate:
//
// * A SUGGESTED-RESOURCE TASK is a task carrying a suggested chart entry as a CONTAINED
// TRANSACTION BUNDLE. It is defined by what it contains, and by nothing else.
// * A PROPOSAL is `Task.intent = #proposal`: something offered for a decision, which a user
// sees in a Suggestions list rather than a Tasks list. An ORDER is `Task.intent = #order`:
// authorized work.
//
// THE TWO ARE INDEPENDENT, and all four combinations are real: a proposal may or may not carry a
// suggested resource, and so may an order. Neither `Task.code` nor `Task.intent` answers "does
// this carry a suggested resource" -- the containment does.
//
// `suggestion` is not a CODE anywhere in this specification: no Task.code carries it and no code
// system defines one. The English word still appears; the term of art that stood for two ideas does not.
//
// THE PAYLOAD IS A PROTOTYPE BUNDLE, the same mechanism a reusable template and a form use:
//
// NexusTemplate (List) -- entry.item -> contained Bundle
// Task (here) -- input[suggestion] -> contained Bundle
// NexusEmrCoreQuestionnaire -- templateExtractBundle -> contained Bundle
//
// One container, three wrappers, and no second spelling anywhere: SDC's per-item `templateExtract`
// is prohibited on the form profile too. What a form has that a Task does not is entries whose
// CARDINALITY depends on the answers, expressed with `templateExtractContext` inside the Bundle.
// A Task's suggested resources are already filled in, so its entries are simply the ones authored.
//
// WHY A BUNDLE AND NOT A LIST OR LOOSE RESOURCES. dom-2: "If the resource is contained in another
// resource, it SHALL NOT contain nested Resources" (`contained.contained.empty()`, error severity,
// unchanged in R5). Anything contained in this Task is forbidden from containing anything itself,
// so a contained List could not hold the prototypes -- they would have to scatter as its siblings,
// with the List reduced to a manifest over them. `Bundle` is the one container exempt: it derives
// from `Resource` rather than `DomainResource` and has no `contained` element for the rule to find.
//
// WHAT THE TRANSACTION BUYS, beyond being legal:
//
// * `entry.request.method` is PER ENTRY. One suggested-resource Bundle can CREATE a Condition and UPDATE a
// MedicationRequest. An earlier revision put add-versus-update on `Task.focus`, which is 0..1,
// so a mixed suggestion was unrepresentable; `focus` is now free to mean what it always meant.
// * `type = transaction` states atomicity in the model rather than in prose: the suggested
// resources are written, or none of them are.
// * `entry.request.ifNoneExist` / `ifMatch` carry conditional writes, which is where idempotency
// belongs.
// * `entry.fullUrl` (a `urn:uuid`) is how prototypes reference each other -- ordinary transaction
// mechanics, and it sidesteps `#id`, which resolves against the ROOT resource and would be
// ambiguous for a graph sitting inside a Task.
// * Instantiating stops being an algorithm this specification describes and becomes an operation
// every FHIR server implements: fill the prototypes in and POST the Bundle.
//
// The suggested resources are NEVER written to the chart before someone accepts them. Consequences, by design:
//
// * Type-level queries cannot see it (confirmed empirically on both the WellServices store --
// MS FHIR Server for Azure 4.0.332 -- and Medplum 5.1.29). A `Condition?patient=` search
// returns asserted problems only, because a resource inside a contained Bundle has no
// independent existence to be returned. No consumer anywhere needs a "filter out suggestions"
// rule.
// * The spec's containment test is satisfied verbatim: containment is for content that "cannot
// be identified independently" (R4 2.3.0.8) -- a suggested resource has no independent identity BECAUSE
// no one has asserted it; identity is what acceptance mints.
// * dom-4/dom-5: the contained Bundle carries no versionId/lastUpdated and no security label.
// The AIAST (AI-authored) label rides the TASK.
// * The prototypes state the clinical fact their citations support and say NOTHING about review
// state, so acceptance simply writes them.
//
// THREE VERBS, all distinct, and conflating any two of them is the failure this paragraph exists
// to prevent:
//
// * APPROVE -- `Task.intent` #proposal -> #order. One-way. It moves the task from the
// Suggestions list to the Tasks list; it writes nothing to the chart.
// * ACCEPT -- `Task.status` -> #accepted. Claiming the work. Where the owner was a
// CareTeam, `owner` becomes the claiming person.
// * INSTANTIATE -- fill the prototypes in and write the Bundle. The one that writes, and the
// same verb and same operation as instantiating a template a user picked.
//
// A task may be approved without being instantiated (the order still has to be carried out), and a
// template may be instantiated with no task anywhere near it.
//
// TRACEBACK. Instantiating carries the producing capability's business identifier onto the resources
// it writes -- the same value, under the same key namespace (nexus-harness-key or nexus-cds-key),
// that the Task carries. The written
// resources cannot `basedOn` the Task (most basedOn value sets exclude Task), so traceback rides
// supportingInformation/Provenance plus that shared key, the one value present on both sides.
//
// DECLINING is `Task.status` #cancelled with `Task.statusReason` saying a human declined it; the
// Task and its contained Bundle are RETAINED, because what was offered and refused is part of the
// record. There is deliberately no `rejected` status -- see the status element.
//
// GROUPING. One decision-support evaluation may produce several proposals. They are siblings
// sharing a `groupIdentifier` (the card), each a task in its own right, and they are ALTERNATIVES
// only when they carry `intent = #option`. See that element.
//
// PRODUCER. `requester` -- not `code`, not `intent`, not `groupIdentifier` -- is where "what produced
// this task" lives, declared as a logical Device reference under NamingSystem/nexus-harness-graph or
// NamingSystem/nexus-cds-rule.
//
// Graduation valve (recorded so choosing containment is not read as foreclosing it): if a real
// consumer ever needs first-class suggested resources (CPOE, e-prescribing, external interop), the same
// Bundle can be written to the chart as stored content ADDITIVELY -- the Task spine and business
// identifiers do not change.
* obeys nexus-sugg-1 and nexus-sugg-2 and nexus-sugg-3 and nexus-task-focus-not-contained and nexus-task-priority-detail-1 and nexus-task-bizstatus-scope
* contained ^short = "The suggested-resource Bundle, plus anything else this task carries in-line"
* contained ^definition = """
On a suggested-resource task: a transaction `Bundle` holding the suggested resources as its entries,
referenced from the `suggestion` input. That containment is what MAKES the task a suggested-resource
task -- neither `Task.code` nor `Task.intent` says it.
The `Provenance` carrying the suggestion's citations is an ENTRY IN THAT BUNDLE, not a sibling of
it: a `urn:uuid` resolves only inside its own Bundle, so a Provenance beside the Bundle pointing at
an entry within it is a dangling reference. Being an entry also means the citations are written on
acceptance, which is the outcome AI attribution requires -- an accepted chart entry with no trail
back to the passage it came from is the thing those rules exist to prevent.
Anything else the task carries in-line -- an attachment born with it, having no independent
existence in the chart -- is contained beside the Bundle. There is no ambiguity about which
resources are suggested, because those are the Bundle's entries.
The prototypes inside it are fully typed resources that state the clinical fact their citations
support -- they carry NO pending-review marker of their own. Review state lives on the Task
(`Task.status` for the decision, `Task.intent` for what is being asked), so a prototype is
instantiable as-is rather than needing to be edited on acceptance. What each entry would DO to the
chart is `entry.request`: `method` POST to add, PUT to update, with the target on `request.url`.
Instantiating writes the Bundle; declining retains this Task (`status` cancelled, `statusReason`
saying a human declined) with the Bundle still contained, as the record of what was refused.
"""
* extension contains NexusEmrThreadId named threadId 0..1 MS
* extension[threadId] ^short = "Harness thread id (AI-created tasks)"
* extension[threadId] ^comment = "SHOULD be present on every harness-created Task. Assigning the Task back to an agent resumes this thread (the approve/resume contract). Never rendered in the UI."
* input ^slicing.discriminator[0].type = #pattern
* input ^slicing.discriminator[0].path = "type"
* input ^slicing.rules = #open
* input contains suggestion 0..1 MS
* input[suggestion].type = NexusTaskInputTypeCS#suggested-resource
* input[suggestion] ^short = "The contained prototype Bundle (local #id reference)"
* input[suggestion] ^definition = "References the transaction `Bundle` CONTAINED in this Task that holds the suggested resources. The reference SHALL be local (`#id`, enforced by nexus-sugg-1) and SHALL resolve to a Bundle contained in this same Task (nexus-sugg-2). Both are error severity. ONE reference, not one per suggested resource: the Bundle holds them all, as its entries."
* input[suggestion].value[x] only Reference(Bundle)
* input[suggestion].value[x] ^short = "Local reference (#id) to the contained prototype Bundle"