Comprendre et références · Comprendre

La vue orientée problème

The chart is otherwise organised by data type: a prescriptions tab, a labs tab, a background tab. Answering "what are we treating, and with what?" then means holding two lists in your head and crossing them yourself.

The Synthèse tab does that crossing — and it is called the synthesis because it is the synthesis: the chronological stream next to it is now simply the Fil (feed). The model this tab renders — the four lists, the hierarchy, the provisional status — is argued in the problem list architecture; this page is about the surface.

It is the single owner of the problems. The background tab used to show current problems and past history through the older MedicalHistoryItem model — two surfaces reading and writing the same Conditions through different lenses, which is how a chart acquires two truths. Background now keeps only what it alone holds: allergies, home medication, and the reconciliation that needs both. Nothing was lost in the move: diagnoses posed by workflows land in the persistent list, and past history is the fourth list.

Why, in measured terms

Semanik et al. (JAMIA Open, 2021) compared a problem-oriented presentation with the classic type-oriented one on synthesis tasks: −15.9 % time, errors 3.4 % against 7.7 %, and perceived usability up (SUS +17.2). Grouping around the problem does work the reader was doing from memory.

What the layout has to make readable

Three things, without a sentence of explanation — and each of them is a decision the code carries, not decoration:

The separation of the four lists, stay first. Reading order is stay, active, multidisciplinary, history: the first question of anyone opening an inpatient chart is why is this patient here, and what are we working on? The persistent list, which governs the prescriptions without motivating the stay, reads immediately after. That order lives in PROBLEM_LISTS and is protected by a test, because it is a reading decision, not an implementation detail.

Their visual separation cannot be hue: the palette has exactly three semantic ones (accent, urgent, validation) and list membership is none of them. So each list is marked by the stroke of its rule, and each stroke encodes something true: solid accent for what is active and persistent, dashed for what is bounded by the stay, neutral for what is not a medical diagnosis, dotted for what is no longer under active management.

When the stay is over and stay problems remain, the list's criterion gives way to a call for a decision, in the amber the app uses for "something is expected of you here": they are flagged, never reclassified in silence — see the stay lifecycle.

Consequence to expect on an existing chart: the stay list starts empty. Conditions written before this model carry no marking, and legacy encounter-diagnosis Conditions are persistent problems — the old model used that code to mean "confirmed current problem" — so they read as active, which is right. Marking the focus of a stay is a gesture (+ on the stay list), not a migration.

The organ system as a left column, not a heading. Sixteen stacked subheadings would cost in height what the view is meant to save. Problems align in one reading column, system names forming a rail of markers to their left. Below 760 px the rail becomes a heading — 150 px of column leaves nothing for the problem itself.

The categories and the classifier are the paper's (architecture); what belongs to the view is the choice of one heading when a problem matches several, by reading order. Stated there as a layout convention, because the paper publishes no tie-break.

Sharing. One creatinine belongs to renal function, to heart failure and to antibiotic dose adjustment at once. Rendered naively, the same result under three problems reads as three measurements, so every shared item is marked and its tooltip names the other carriers. The marking is deliberately quiet — a muted glyph, no chip, no count: the reader only consults it in case of doubt ("is this the same creatinine, or a second measurement?"), so it must not compete with the analyte and its value, which is what the line is for. Same treatment for "this diagnosis replaced a hypothesis" and for the coverage acknowledgement, which is a toggle rather than two spelled-out labels: rare gestures and historical facts earn a glyph, not a sentence.

The same reasoning applies inside a single problem: an umbrella inherits its complications' items so that collapsing it hides nothing, but an item the umbrella already carries is not added a second time.

Many-to-many attachment

Kind How FHIR
Treatments Automatic, from the indication the selected regimen already carries MedicationRequest.reasonReference / reasonCode, matched by code first then label
Lab results Manual, one gesture per attachment, detachable from where it shows Condition.evidence.detail

Observation has no reason element in R4, so the link is carried on the problem side, where the specification puts it. evidence means "what supports": exact for a creatinine under renal failure, slightly stretched for a monitoring INR. We take the stretch rather than invent an extension — a third-party FHIR reader understands evidence and would not understand ours.

When a hypothesis is refined, its evidence is copied onto the replacement, not moved: the lab that supported the hypothesis supports the diagnosis, and without the copy the new diagnosis is born empty while the result is stranded on a problem that is no longer displayed. The copy is harmless precisely because attachment is many-to-many — the board then says it is the same item, not a second measurement.

A replaced hypothesis is ruled out, not resolved

This was a defect with clinical consequences, and it is worth stating plainly. precise() used to send the replaced hypothesis to past history marked resolved — which asserts that the patient had the disease and that it went away. Enter "myocardial infarction" as a hypothesis, refine it to "angina", and the chart came out carrying a past history of infarction that was never confirmed. An MI in the history changes decisions forever: secondary prevention, risk scoring.

So refuted exists as a status. It is a standard R4 verificationStatus code — the only one that says this is not the patient's condition — and it applies to any replaced hypothesis, whether frankly ruled out (infarction → angina) or merely narrowed (community pneumonia → bacterial pneumonia): in both cases the assertion carried by the old label is withdrawn, and the replacement is what the chart now asserts. A refuted problem appears in none of the four lists, because appearing in one is an assertion. It is not deleted: yesterday's reasoning is part of the chart, the audit points at it, and its trace reads on the replacement.

Correcting the code was not enough — the false past-history entries already written stayed false. pnpm --filter ehr-lab repair:refuted repairs exactly those and nothing else, on a signature that leaves no room for interpretation: a Condition referenced by another's supersedes extension and filed as resolved past history. By construction that is a replaced hypothesis. The script writes nothing without --write, because rewriting clinical facts is a decision, not a side effect.

Two footers: what is missing from the list, and what the list does not cover

Prescribed indications absent from the list. The chart already holds the answer: the prescriber recorded the indication, it was simply never entered as a problem. One row per indication (not per line) lists its drugs and carries a single +; adding it attaches all of them at once. Without a coding no button is offered — a problem entered from a bare label would no longer match indications by code, and the gap would come back in another form.

The unfiltered channel. A problem-oriented view is by construction a filter, and the acute-care risk is missing what you were not looking for. Everything in progress that no problem claims stays visible at the foot of the view, independent of which problem is being read, never collapsed. Data attached to no problem is a signal, not waste.

Honest limit: this channel currently shows "attached to nothing", not "abnormal". LabResult carries no reference range, and inventing thresholds would mean producing clinical knowledge of our own. Qualifying abnormality waits for a range from the device.

"No treatment attached" is judged on treatments

The highlight follows needsAttention, and three conditions narrow it, each because the wider version was wrong:

  • treatments only. An attached lab documents a problem; it does not treat it. Counting it would extinguish the signal with nothing prescribed.
  • treatable lists only (active, stay) and not resolved. A resolved past history item with no treatment is the definition of past history; flagging it would charge the reader for noise, and a signal one learns to ignore signals nothing.
  • not acknowledged. Watchful waiting, a treatment outside this order set: the acknowledgement lets the chart say so, and the problem leaves the highlight without disappearing.

That acknowledgement is a clinical decision, not a display preference: author, time, traced in both directions, belonging to the chart rather than to the user who made it. In FHIR it rides on the Condition as an extension whose value is an Annotation — the standard type already carries authorReference and time, so nothing had to be invented.

Neither gap raises an alert: both are frequent, individually mostly benign, and would burn the interruption budget for nothing (see the clinical alert doctrine). They are carried by layout.

A stopped line stays visible under its problem, struck through and labelled — greyed without the word, it is indistinguishable from a badly-contrasted active line — and does not make the problem treated. Discharge prescriptions are excluded entirely: they are what the patient leaves with, not what the stay treats.

An uncoded problem is labelled as such. It is accepted (better than nothing) but invisible to the view and to decision support alike, which is the condition that drops prescribing correctness to 33.5 % in the Amsterdam trial.

The gestures, and where the guardrails live

Editable at every transition — admission, discharge, service change — by anyone, every write traced. That is Connect Care's governance position, taken as-is and argued in the architecture page.

One drawer carries the five modifications of a problem (label, code, list, status, umbrella) rather than five buttons per row: what must stay light is the reading of the list; a rare gesture can afford one more click. Alongside it, refine on a hypothesis, acknowledge where coverage is in question, + per list, and attach/detach on a lab.

Prescribe from the problem sits there too — it is the gesture that closes "no treatment attached" exactly where the gap is shown. The indication is stated from the start, so the line created attaches itself to this problem on reload. Offered only where isTreatable holds: prescribing from a resolved past-history item or from a multidisciplinary concern makes no sense, and the same predicate drives the coverage highlight, so the two cannot disagree.

The guardrails are the domain's (canMoveTo, canParent, precise), and the form never offers more than the domain permits: the list select holds only reachable destinations, and is disabled with its reason when the only destination is the current one — a select that leads nowhere reads as a fault. The same rules are re-checked in the use case, so a hand-made request gets the same refusal with a readable message.

Three asymmetries worth naming:

  • Recoding yes, un-coding no. An uncoded problem is flagged in order to be coded, not so that its code can be removed.
  • Leaving the list is two different clinical acts, and conflating them is what put a never-confirmed infarction in a patient's history. An established diagnosis that is no longer managed goes to past history, resolved — and it is the existence of that destination that makes cleaning possible at all, without which 97.8 % of actions on a list are additions. A hypothesis is ruled out: never confirmed, so not past history. The button says which one it is doing.
  • Neither is a deletion. What was written stays in the chart.

refuted is deliberately absent from the status select: ruling out is a gesture, not a setting. It has its own button, because the problem then leaves every list and a dropdown does not say that.