Skip to content

Non-subject value stratifier — scalar expression support (#909)#1030

Open
lukedegruchy wants to merge 6 commits into
mainfrom
ld-20260511-non-subject-stratifier-expression-scalar-failing-test
Open

Non-subject value stratifier — scalar expression support (#909)#1030
lukedegruchy wants to merge 6 commits into
mainfrom
ld-20260511-non-subject-stratifier-expression-scalar-failing-test

Conversation

@lukedegruchy
Copy link
Copy Markdown
Contributor

@lukedegruchy lukedegruchy commented May 11, 2026

This branch closes the remaining gap for issue #909: a stratifier with a non-subject (non-boolean) population basis and a scalar (non-function) component expression must evaluate the expression in subject context and apply that single value to every resource for the subject. The previously failing regression test for the continuous-variable + scalar-stratifier combination now passes, and test coverage is extended so all four (basis × expression-type) quadrants of #909 are exercised at multiple levels.

  1. Fix MeasureMultiSubjectEvaluator.getResourcesForSubjects for MEASUREOBSERVATION populations: previously the helper ran normalizePopulationKey on the population's Set<Map<inputResource, outputValue>> entries, producing String.valueOf(map) strings instead of real resource IDs, which left every continuous-variable stratum with a null measureScore when the stratifier was scalar.
  2. Add a regression test fixture and ContinuousVariableResourceMeasureObservationTest.continuousVariableObservationEncounterBasisNonFunctionStratifier exercising the failing path end-to-end on a continuous-variable Encounter-basis measure.
  3. Add direct unit coverage of all four Allow Subject Based Stratifier for Non-Subject Population Basis #909 scenarios against MeasureMultiSubjectEvaluator via a new Issue909 nested class, including a MEASUREOBSERVATION population in case 2 so the fix is pinned at the unit level (the test fails without the fix).
  4. Add an end-to-end rejection test (cohortBooleanValueStratFunctionStratifierInvalid) plus fixture that exercise the existing upstream validator path for case 3 (subject basis + CQL function = error), which had no test before.
  5. Harden MeasureStratifierTest.ratioResourceValueStratAge with per-stratum score assertions (it previously only asserted stratum count, and would have passed even before the fix).

…basis CV measure

When a CONTINUOUSVARIABLE Encounter-basis measure uses a Patient-context scalar
expression as its stratifier component criteria (e.g. `define "Age":
AgeInYearsAt(end of "Measurement Period")`) instead of a CQL function taking
the population resource, the engine routes through the scalar-fallback
NON_SUBJECT_VALUE path. Group-level aggregation is correct, but stratum
measureScore is never computed and the stratum-level measure-observation
population is missing both the cqfm-aggregateMethod and the
extension-aggregationMethodResult extensions.

Adds a self-contained dataset (10 patients, 12 encounters - identical to the
ContinuousVariableObservationEncounterBasis fixtures) and a failing test
mirroring continuousVariableResourceMeasureObservationEncounterBasisAvg, where
the only meaningful difference is the stratifier expression form. No
production fix in this commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Formatting check succeeded!

MeasureMultiSubjectEvaluator.getResourcesForSubjects previously ran
normalizePopulationKey on MEASUREOBSERVATION subjectResources, but those
entries are Set<Map<input, output>> — yielding String.valueOf(map)
garbage instead of real resource IDs. Scalar non-subject stratifiers on
continuous-variable measures ended up with bogus
resourceIdsForSubjectList, no intersection with the Map keys in
downstream stratum scoring, and a null measureScore per stratum. The new
MEASUREOBSERVATION branch flattens Map.keySet() through
normalizePopulationKey, mirroring getPopulationResourceKeySet:929-938.
The regression test added in b0155b4 now passes. Also drops a stray
logger.info("1234: ...") debug statement from the same method.

Test coverage for the four #909 scenarios:

- Case 1 (non-subject + function): already covered.
- Case 2 (non-subject + scalar): CV regression test now green; hardens
  MeasureStratifierTest.ratioResourceValueStratAge with per-stratum
  score assertions (was stratum-count-only).
- Case 3 (subject + function = error): new
  MeasureStratifierTest.cohortBooleanValueStratFunctionStratifierInvalid
  plus a CohortBooleanValueStratFunctionStratifier.json fixture pin the
  InvalidRequestException from
  FunctionEvaluationHandler.validateStratifierExpressionTypes.
- Case 4 (subject + scalar): already covered.

Adds direct unit coverage of all four cases against
MeasureMultiSubjectEvaluator via a new nested Issue909 class in
MeasureMultiSubjectEvaluatorTest. The case-2 unit test exercises a
MEASUREOBSERVATION population so the fix is pinned at unit level.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lukedegruchy lukedegruchy changed the title Add failing regression test for non-function stratifier on Encounter-… Non-subject value stratifier — scalar expression support (#909) May 13, 2026
@lukedegruchy lukedegruchy marked this pull request as ready for review May 13, 2026 19:04
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant