Skip to content

Walkthrough

The headline answer is the start, not the end. This walkthrough drills past it using the bundled conformance fixtures - the same FHIR bundles every implementation is tested against. Each one is a small, deliberate scenario.

Every command runs from the repo root and uses the Rust CLI; the JavaScript engine and the interactive demo produce the same results.

Fixture Demonstrates
six-month-fully-vaccinated An on-schedule infant: up to date for age, not yet fully vaccinated
behind-for-age-toddler Primary doses given, 12-month visit missed → behind for age
out-of-schedule-doses Doses too early / too late → labelled, not counted
unmatched-doses A 5-in-1 and an unknown code → surfaced, not dropped
mmr-both-doses One product class, two series → allocated correctly
duplicate-echo Same jab recorded twice → duplicate detected
dose-number-mismatch Recorded dose number wrong → date order wins, flagged

Conformance: which series are satisfied

Drop --format status and the default report shows conformance per series - the heart of the engine. For the on-schedule 6-month-old:

cargo run --manifest-path rust/Cargo.toml --quiet --bin greenbook -- \
  evaluate rules/schedule-uk-2026-01-01.toml rules/product-map-uk-snomed-dm.toml \
  conformance/fixtures/six-month-fully-vaccinated.json --evaluated-at 2026-04-29
Up-to-date status: UP_TO_DATE_FOR_AGE
Fully vaccinated:  no (strict: every eligible series complete)

By series:
---------
  [COMPLETE   ] 6-in-1 (3/3 due, 3 total) - up to date
      - ok              2025-12-24  dose 1  (1mo 3w 4d)  [Infanrix Hexa vaccine (product)]
      - ok              2026-01-21  dose 2  (2mo 3w 2d)  [Infanrix Hexa vaccine (product)]
      - ok              2026-02-18  dose 3  (3mo 2w 6d)  [Infanrix Hexa vaccine (product)]
  [PARTIAL    ] MenB (2/2 due, 3 total) - up to date

Read the counts as valid / due (total). MenB is PARTIAL (2 of 3 doses) yet still "up to date" - its third dose is not due until 12 months, so it is not held against a 6-month-old. The booster series (Hib/MenC, Td/IPV) show no doses and no spurious flags, because conformance matches by product class: a 6-in-1 dose is never dragged into a booster series through shared antigens.

Behind for age

Take a toddler with the same infant doses but who missed every 12-month appointment:

# … conformance/fixtures/behind-for-age-toddler.json …
Up-to-date status: BEHIND_FOR_AGE

The infant series are still COMPLETE, but the series due at 12 months are now overdue, so the headline flips to BEHIND_FOR_AGE. The per-series breakdown is the catch-up worklist.

Outside the standard schedule

out-of-schedule-doses has a 6-in-1 second dose given a week too soon and a rotavirus dose given after its hard cutoff. Those doses are recorded but do not count, and each carries a reason:

      - OUT-OF-SCHEDULE 2025-12-31  dose 2  (...)  [Infanrix Hexa vaccine (product)]
          ! given before earliest_age ...

The engine does not call them "invalid" or hide them - they were real clinical events, labelled honestly as outside the standard schedule.

Unmatched doses

unmatched-doses contains a Pediacel 5-in-1 (gone from the 2026 schedule) and an unknown code. Neither is silently dropped:

Unmatched doses:
---------------
  - 2026-01-21  [Pediacel vaccine (product)]  (product class "5-in-1" has no series in this schedule version)
  - 2026-01-21  [Unknown investigational vaccine]  (unknown product code (not in the product map))

A 5-in-1 is unmatched against today's schedule; under historical versioning it conforms to a schedule version that actually asked for a 5-in-1 primary course.

Historical schedule selection

The rules/ directory now contains curated historical slices, not just the current schedule. List them with:

cargo run --manifest-path rust/Cargo.toml --quiet --bin greenbook -- \
  versions rules --country UK
2006-11-01  effective_to=2010-12-01  rules/schedule-uk-2006-11-01.toml
2010-12-01  effective_to=2013-05-07  rules/schedule-uk-2010-12-01.toml
2014-09-01  effective_to=2016-09-20  rules/schedule-uk-2014-09-01.toml
2026-01-01  effective_to=open        rules/schedule-uk-2026-01-01.toml

evaluate-auto builds an effective schedule for the patient by selecting each expected dose slot from the schedule version in force when that dose first became due. This is the feature that makes historical review tractable.

The bundled historical demo is a child born in November 2006 with one Pediacel 5-in-1 dose at two months:

cargo run --manifest-path rust/Cargo.toml --quiet --bin greenbook -- \
  evaluate-auto rules rules/product-map-uk-snomed-dm.toml \
  test-data/historical-pediacel-2006.json \
  --evaluated-at 2007-01-15 --verbose
Schedule version:  2006-11-01
Schedule rule:     dose slots are selected from the schedule version in force when each dose first became due; not-yet-due slots are projected from the version in force on evaluated_at

By series:
---------
  [PARTIAL    ] 5-in-1 (1/1 due, 3 total) - up to date
      - ok              2007-01-01  dose 1  (2mo)  [Pediacel (product)]
  [NONE       ] PCV (pneumococcal) (0/1 due, 3 total) - BEHIND

The child is not up to date overall, because a PCV dose was also due by the evaluation date. But the Pediacel dose itself is correctly matched to the 2006 5-in-1 series.

Point the same record at the 2026 schedule manually and you get the naive failure mode:

cargo run --manifest-path rust/Cargo.toml --quiet --bin greenbook -- \
  evaluate rules/schedule-uk-2026-01-01.toml rules/product-map-uk-snomed-dm.toml \
  test-data/historical-pediacel-2006.json --evaluated-at 2007-01-15
Unmatched doses:
---------------
  - 2007-01-01  [Pediacel (product)]  (product class "5-in-1" has no series in this schedule version)

That is the difference between projecting today's schedule backwards and evaluating the record against the schedule that existed at the time.

One class, two series; and duplicate echoes

Two cases that trip up naive tools:

  • mmr-both-doses - MMR is one product class serving two series (first and second dose). The engine allocates the recorded doses across the series' slots by date order, so both land correctly with no "extra dose" or "too early" flag.
  • duplicate-echo - the same physical jab recorded twice by two systems. Detected by the shared SNOMED procedure code; the earliest is kept, the rest reported:
Duplicate doses:
---------------
  - 2026-01-10  [Infanrix Hexa vaccine (product)]  (likely duplicate of 2025-12-24; same procedure code)

dose-number-mismatch is the related case: a dose recorded as "dose 2" that the dates prove is dose 1. Date order is authoritative; the recorded number is a cross-check that raises a soft flag rather than being trusted.

Coverage: which diseases are protected

Conformance asks "did they get the named doses?". Coverage asks the separate question "which diseases is the child protected against?", computed across the antigens of every product received. The reference engine reports conformance; the JavaScript engine and the interactive demo add a by_antigen coverage view.

The demo is the best place to see both at once: its dashboard lays out recorded doses → conformance by series → antigen coverage → headline status, side by side, for every fixture above - or for a patient you build yourself.

Open the interactive demo See the presentation