Skip to content

Feature/s15 evaluation gaps - #26

Merged
manjula25 merged 7 commits into
mainfrom
feature/s15-evaluation-gaps
Jul 8, 2026
Merged

Feature/s15 evaluation gaps#26
manjula25 merged 7 commits into
mainfrom
feature/s15-evaluation-gaps

Conversation

@manjula25

@manjula25manjula25 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added a richer evaluation report with separate dev-labeled, held-out, and outreach sections.
    • Introduced clinician outreach tracking with JSON validation and a validation command.
    • Added support for held-out labels and bundle-based label derivation across care gap, risk, and SDOH views.
  • Bug Fixes

    • Improved handling for missing data and invalid outreach files, with clearer report output instead of failures.

manjula25and others added 7 commits July 8, 2026 21:28
… log)
Slice planning artifacts for S15, which closes sub-gaps 1 (no held-out
eval set) and 2 (0/16 clinician-validated labels) of the HL7 evaluation's
biggest-risk decomposition. Sub-gap 3 (Risk agent 9-FP rate) is reserved
for S16 with its own design-risk-calibration-v2.md.
- grill-evaluation-gaps.md: 6-question grill + derived Q7-Q9
(S15/S16 split, held-out set shape, labeling rules, eval-report shape,
CLI ergonomics, outreach log architecture, verification matrix,
out-of-scope)
- prd-s15.md: problem statement + 4-commit solution + 18 user stories +
D1-D11 implementation decisions + T1-T5 testing decisions + explicit
out-of-scope
- implementation-plan-s15.md: 4 atomic commits + Phase E verification +
rollback table + D1-D10 definition of done + open follow-ups
Engagement is NOT a verification gate; the slice ships the path (review:
render + review:apply already built in S14) and the tracking (outreach
log) without requiring a clinician to volunteer. Audit-trail-clean:
every commit is "wire an existing thing to a real output," same shape
as S14. S16 owns the Risk rubric work.
Co-Authored-By: Claude <noreply@anthropic.com>
…a.heldOutRows
Declares the 10 held-out patients (pop-0011..pop-0020) — already part
of generatePopulation()'s 500-patient cohort at
apps/api/src/fhir-data/population.ts:13 — as a labeled held-out set
in data/eval/labels.json via _meta.heldOutRows. Adds 10 label rows
with mechanically-derived labels (careGap, risk, sdoh) per the
existing _meta.labelingRules; actionPlanner is qualitative-only.
The held-out labels are a credible-enough apples-to-apples held-out
set for a POC: bundles are independently generated (deterministic
seed) and labels come from the same dev-interpreted labeling rules
as the dev-labeled 16. Held-out SDOH sub-metric will report 0 data
points because generatePopulation()'s buildSdohForIndex(i) only seeds
explicit AHC-HRSN screenings for i in {4, 9} (pop-0005 negative,
pop-0010 positive); rows without an AHC-HRSN Observation are unlabeled
(null) per _meta.labelingRules.sdoh. The Care Gap + Risk held-out
sub-metrics are populated (9/10 careGap-positive, 10/10 risk-low).
No agent or eval-harness changes; commit 3 will render the new rows
as a Held-out evaluation section in docs/eval-report.md.
Spec: prd-s15.md D2 + grill-evaluation-gaps.md §2 + §3
New apps/api/src/eval/labelFromBundle.ts exporting
labelFromBundle(bundle, dim): boolean | null. Pure function —
no I/O, no LLM. Mirrors the dev-interpreted _meta.labelingRules
(careGap: Condition → LOINC, risk: riskScoreFor ≥ 75, sdoh:
AHC-HRSN positive/negative/absent). Both the dev-labeled 16 and
the held-out 10 score against this single function.
Also exports the existing riskScoreFor() from population.ts
(no behavior change — pure mechanical exposure so this new module
can call it). The Risk branch derives (conditionCount, recencyHours)
from the bundle and delegates to riskScoreFor; tests stub the
import via jest.mock so they're deterministic.
No eval-harness wiring yet; commit 3 calls this from scripts/eval.ts.
Spec: prd-s15.md D4 + grill-evaluation-gaps.md §3
Co-Authored-By: Claude <noreply@anthropic.com>
…tion
Splits apps/api/src/scripts/eval.ts into two parallel patient loops
(dev-labeled baseline + held-out evaluation) plus a third Outreach
section. Adds --dev-only, --held-out-only, --no-live CLI flags.
Reuses eval/computeMetrics.ts (same function called twice). Status
disclosure now reports "N clinician-validated / 16 dev-labeled /
10 held-out" with three counts.
The held-out section uses labelFromBundle (commit 2) applied to
the 10 independently-generated bundles; the dev-labeled section
uses the existing _meta.labelingRules path (unchanged).
Spec: prd-s15.md D5 + D6 + grill-evaluation-gaps.md §4 + §5
Adds data/eval/clinician-outreach.json (initial empty invitations[])
+ apps/api/src/eval/outreachSchema.ts (pure validator) + 5 unit tests
+ apps/api/src/scripts/outreach-validate.ts (I/O script) + new
npm run outreach:validate. Extends apps/api/src/scripts/eval.ts's
renderMarkdown + buildJsonSummary to render the Outreach table
(or "Outreach log not yet started" when the file is missing).
Engagement is NOT a verification gate; the slice ships whether or
not a clinician volunteers. The Outreach table makes the gap
visible in docs/eval-report.md and gives the HL7 evaluation's
Open Question #2 ("Has the HTML form been sent to any clinician?")
a real answer from the artifact itself.
Spec: prd-s15.md D7 + D8 + grill-evaluation-gaps.md §6
Co-Authored-By: Claude <noreply@anthropic.com>
Phase E artifacts per docs/plans/caresync-ai/implementation-plan-s15.md
§Phase E. Documents the 5-row verification matrix (all pass), the
two mid-flight defects caught by sub-agents (POPULATION_SIZE=500 in
Commit 1, SDOH regex in Commit 2), and the 7 open follow-ups (most
owned by S16 or post-S15).
Also regenerates docs/eval-report.{md,json} with the S15 three-section
layout: Status line "0 of 26 clinician-validated / 16 dev-labeled /
10 held-out", Dev-labeled baseline (16 patients), Held-out evaluation
(10 patients), Outreach, Error analysis (dev-labeled + held-out),
Data-availability gaps combined. Outreach sub-object in the JSON
summary reads { fileExists: true, ok: true, errors: [], invitations: [] }
— the empty-state disclosure that makes the engagement gap visible
without gating the slice.
Verification matrix: 5/5 pass. TDD: 21 tests across 3 eval/ suites
(labelFromBundle, outreachSchema, computeMetrics, errorAnalysis);
3 round-trip tests in scripts/eval.test.ts; 300/300 tests across
46 suites in apps/api (full regression). npx tsc --noEmit clean.
Spec: prd-s15.md §7 (verification matrix) + grill-evaluation-gaps.md
§7 (verification matrix) + implementation-plan-s15.md §Phase E
Re-runs the HL7 rubric against the post-S15 state. P6 upgrades from
4 → 5 because the held-out section now renders with per-agent
sensitivity/specificity/PPV. All other pillars unchanged. P2 + P4
remain bounded by the engagement sub-gap (still 0 clinician-validated)
and the Risk agent 9-FP sub-gap (S16's scope, parallel-track).
Sources cite the regenerated docs/eval-report.{md,json} (commit
a56e93a, 2026-07-08T18:08:16Z) for the current eval state.
Co-Authored-By: Claude <noreply@anthropic.com>
@manjula25
manjula25 merged commit 5f27418 into mainJul 8, 2026
1 check was pending
@coderabbitai

coderabbitaiBot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6bfa6349-5313-455b-bc6f-20611be7f3d4

📥 Commits

Reviewing files that changed from the base of the PR and between b3771c0 and a43598e.

📒 Files selected for processing (20)
  • apps/api/package.json
  • apps/api/src/eval/labelFromBundle.test.ts
  • apps/api/src/eval/labelFromBundle.ts
  • apps/api/src/eval/outreachSchema.test.ts
  • apps/api/src/eval/outreachSchema.ts
  • apps/api/src/fhir-data/population.ts
  • apps/api/src/scripts/eval.test.ts
  • apps/api/src/scripts/eval.ts
  • apps/api/src/scripts/outreach-validate.ts
  • data/eval/clinician-outreach.json
  • data/eval/labels.json
  • docs/eval-report.json
  • docs/eval-report.md
  • docs/plans/caresync-ai/grill-evaluation-gaps.md
  • docs/plans/caresync-ai/implementation-plan-s15.md
  • docs/plans/caresync-ai/prd-s15.md
  • docs/plans/caresync-ai/review-s15.md
  • docs/plans/caresync-ai/verification-s15.md
  • reports/HL7-Challenge-Evaluation.2026-07-08-post-s15.md
  • tasks/todo.md

Walkthrough

This PR adds an S15 slice: a pure labelFromBundle function for careGap/risk/sdoh labeling, extends the eval harness (eval.ts) to support dev-labeled vs held-out cohorts with --dev-only/--held-out-only/--no-live flags, adds a clinician outreach log with schema validation and CLI script, seeds held-out patient labels, regenerates eval report artifacts, and adds extensive planning/verification/review documentation.

Changes

S15 Evaluation Slice

Layer / File(s)Summary
labelFromBundle pure labeling function and tests
apps/api/src/eval/labelFromBundle.ts, apps/api/src/eval/labelFromBundle.test.ts
Adds deterministic careGap/risk/sdoh label derivation from FHIR bundles with fixture-based unit tests covering rules, determinism, and null-handling.
Eval harness refactor for dev/held-out cohorts
apps/api/src/scripts/eval.ts, apps/api/src/scripts/eval.test.ts, apps/api/src/fhir-data/population.ts
Exports riskScoreFor, adds runHarness/EvalOptions, held-out label derivation, --no-live cache-only mode, and restructures markdown/JSON reporting into three sections; adds round-trip CLI flag tests.
Clinician outreach schema, validator, and CLI script
apps/api/src/eval/outreachSchema.ts, apps/api/src/eval/outreachSchema.test.ts, apps/api/src/scripts/outreach-validate.ts, apps/api/package.json, data/eval/clinician-outreach.json
Adds validateOutreach schema logic and tests, an outreach-validate CLI script, an outreach:validate npm script, and the initial outreach JSON artifact.
Held-out patient label seed data
data/eval/labels.json
Adds _meta.heldOutRows and 10 held-out patient label rows (pop-0011..pop-0020).
Regenerated eval report outputs
docs/eval-report.json, docs/eval-report.md
Updates report metrics, sections, and error analysis to reflect the new dev-labeled/held-out/outreach structure.
S15 planning, verification, review, and task documentation
docs/plans/caresync-ai/*, reports/HL7-Challenge-Evaluation.2026-07-08-post-s15.md, tasks/todo.md
Adds planning, PRD, verification, and review documents for the S15 slice, an updated evaluation report, and updated task tracking.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
participant CLI
participant runHarness
participant FhirReadService
participant labelFromBundle
participant runEval
participant OutreachValidator
CLI->>runHarness: run with flags (--dev-only/--held-out-only/--no-live)
runHarness->>runHarness: load labels + heldOutRows
runHarness->>FhirReadService: getPatientBundle(heldOutPatientId)
FhirReadService-->>runHarness: bundle
runHarness->>labelFromBundle: labelFromBundle(bundle, dim)
labelFromBundle-->>runHarness: expected label or null
runHarness->>runEval: runEval(labels, fhirService, db, noLive)
runEval-->>runHarness: scored results
runHarness->>OutreachValidator: readAndValidateOutreach()
OutreachValidator-->>runHarness: ok/errors + invitations
runHarness-->>CLI: markdown + JSON report
Loading

Poem

A hop through bundles, careGap in tow,
Held-out patients now join the show.
Outreach logs sit quiet and neat,
Schema-checked with tiny rabbit feet.
Three-section reports, flags held tight —
This bunny thumps twice: the tests all shine bright! 🐇✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/s15-evaluation-gaps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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

@manjula25