Salient Fields¶
Every profile in this IG can declare salient fields: the handful of values that ARE the resource when you only get a handful. A Slot is its status, start, end, and schedule. A Patient is a name, a birth date, an identifier. Salient fields write that judgment down, per profile, in the FSH -- instead of leaving it to every consumer to re-decide.
A salient field is a triple (plus one optional part):
| Part | What it is |
|---|---|
key |
The field's name as consumers see it (snake_case by convention) |
expression |
A restricted FHIRPath value expression that computes the value from the instance |
type |
The value's type (string, code, dateTime, ...) |
chart (optional) |
An alternate name to use when the field is rendered into a chart/LLM context |
They are declared at the StructureDefinition level (a repeating salient-field complex
extension), and every profile page in the FHIR reference shows its
set under the Salient fields tab.
What they drive¶
Salient fields are a contract consumed by machines, not documentation prose:
-
TypedFhir synthesized accessors. Each salient field becomes a first-class typed property on the profile's facade class (see the TypedFhir API tab on any profile page), in all three ports. Where the expression is invertible -- a plain navigation path -- the accessor gets a setter with validated write-back; where it is not (e.g. a union or a
join), it is read-only. -
Chart and LLM contexts. When TypedFhir renders a resource into a compact document view -- the shape handed to an LLM as context -- the salient fields are the attributes that surface, under their
key(orchart) names. This is the token-economy lever: a raw FHIR resource is hundreds of tokens of envelope around a few values; the salient set is the profile's own statement of which values those are. The raw FHIR remains the lossless substrate underneath -- salience selects, it never discards. -
This site. The Salient fields view on each profile page is generated directly from the declarations, so the site, the facades, and the LLM shapes can never drift apart.
How to define them¶
In the profile's FSH, insert one rule per field (the rulesets live in
rulesets.fsh).
Wrap the expression in [[ ]] so its parens and quotes survive the ruleset call:
* insert Salient(given_name, [[name.first().given.first()]], string)
* insert Salient(status, [[status]], code)
// rendered into charts/LLM contexts as `class` instead of `visit_class`:
* insert SalientAs(visit_class, [[class.code]], code, class)
Rules of the road:
- Stay inside the emittable subset. Expressions are restricted FHIRPath value
expressions: navigation paths,
first(),join(sep), and top-level unions (|). Anything fancier is rejected by the compiler and the field is marked unemittable -- declare a simpler expression instead. - One date concept is separate. The resource's effective date is declared with the
EffectiveDateruleset, not as a salient field -- every facade exposes it uniformly as$effectiveDate. snake_casekeys. They surface verbatim in LLM contexts and Python.- Regenerate after changing them:
npm run gen:all(and the-py/-cstwins) inbackend/lib/TypedFhir/ts; parity tests will catch a port that drifts.
What to pick¶
The test is editorial, not technical: if a clinician (or a model) saw only these fields, would they know what this resource says? Aim for the 3-8 values that answer that. Everything else stays reachable through the typed accessors and the raw FHIR.