openmrs-module-querystore
#68 Patient-record read API and context slice
- Size
- +4,675 / -104 · 60 files
- Tests
- API 525 · OMOD 53 · 0 failures
- CI
- Java 8 / 11 / 17 / 21 green
- Review
- Three maintainer rounds so far; every thread has a reply
- State
- Mergeable
Documentation · OpenMRS integration · updated 15 September 2026
If you maintain or follow the OpenMRS chart-search modules, this page is for you. It lists what our three open pull requests change, why they are proposed in a particular order, and what has been reviewed so far. Nothing on this page is merged yet; it describes branches under review and the tests that check them.
In plain words
QueryStore is the OpenMRS module that indexes a patient's records so they can be searched and read back quickly. ChartSearchAI is the module that answers a clinician's question about a chart using a language model, either one bundled with the module or an optional external service (Med Agent Hub). The ChartSearchAI ESM is the piece of the OpenMRS web interface that shows the question, the answer, the records it drew on and the checks that ran.
The changes let ChartSearchAI use either answer source through one shared set of rules, and give QueryStore one well-defined way to hand over a patient's records with an honest statement of whether the set is complete. They are proposed in the order below because each depends on the one before it: the backend compiles against types the QueryStore change adds, and the interface renders events the backend change defines.
openmrs-module-querystore
openmrs-module-chartsearchai
openmrs-esm-chartsearchai
QueryStore #68
QueryStore takes on record projection, dates, completeness and question-aware selection. It does not compose prompts and knows nothing about models; that stays with the module asking.
GET /ws/rest/v1/querystore/patientrecord in three modes: the full chart by patient; a ranked top-K by patient and q, or q alone; a context slice with mode=context.Get Patients privilege. Unknown modes and malformed typed parameters return 400.webservices.rest.maxResultsAbsolute ceiling: an oversized limit is clamped, a ranked window that would extend past the ceiling returns 400, and links carry the effective page size.Cache-Control: private, no-cache, must-revalidate; the full chart also carries an ETag for revalidation.chartTruncated comes only from the backend's explicit signal: an Elasticsearch size limit, failed shard, timeout or early termination; a MySQL per-table read failure; a Lucene per-index failure or an index the enumerator could not open.projectionComplete reports the deployment-wide bootstrap state; a failed lazy projection for one patient is disclosed on the read instead of returning an empty chart marked complete.clinicalDate and dateKind (clinical_event, administrative, unknown) beside the sort date, so a temporal consumer never reads an administrative date as an event.date_kind; the architecture record carries the re-bootstrap advisory for deployments indexed before the fields existed.getContextSlice(patient, question, request) returns tier-tagged records: mandatory clinical core, recency anchor, typed completeness, similarity.chartSnapshotId (the same complete-chart fingerprint the full read publishes), sliceId, effectiveTypes and temporalApplied; a consumer combining a ledger with a later slice must match the snapshot.interpret=true adds typed and temporal cues; lab-panel expansion and stopword stripping run in the store, and words that carry clinical meaning (negation, status, laterality, body site) are protected.QueryStoreService implementations keep working unchanged.ChartSearchAI #157
The bundled model stays the default for a fresh installation. Med Agent Hub is a separately configured option, never a silent fallback. ChartSearchAI keeps authorization, prompt assembly, sessions, audit and persistence in either case.
ClinicalAnswerProvider with bundled and hub implementations; a registry driven by chartsearchai.providers.enabled (default bundled).GET /providers lists enabled providers with readiness and a reason when unavailable; a picker is requested only when more than one is enabled.POST /chat/new, GET /chat, POST /chat/stream; a restored session hydrates the same lifecycle the live stream produced.patient, session, request_id, require_product_profile, context), answered as completion chunks mapped onto the turn events.GET /models relays hub product profiles.ChartSearchAI ESM #23
The interface half of the backend change. Low-confidence, edited, rejected and withheld output stays visible for a person to review; nothing important lives only in a tooltip.
/chat/stream.Review ledger
| Round | Pull request | Threads | Answered | Commits |
|---|---|---|---|---|
| 5 to 6 Aug 2026 | QueryStore #68 | 10 | 8 Sep 2026 | 8dc6ef9 and the paging remediation: strict mode, typed-parameter 400s, chartTruncated on the plain read, per-backend completeness overrides |
| 9 Sep 2026 | QueryStore #68 | 7 | 14 Sep 2026 | d675fe9 Lucene enumerator skip disclosed · 3057478 failed cold touch disclosed · 1b1c995 laterality stopwords · ba6bfc1 dead overloads · d8c1e17 live page ceiling and paging docs · d10e9e4 architecture-record corrections |
| 15 Sep 2026 | QueryStore #68 | 5 | 15 Sep 2026 | 69e12fe incomplete-read warning names its cause · 87619c4 body-site stopwords · 936bee7 unused constructors · cfced36 cache headers and the property-pinned ceiling test |
| none yet | ChartSearchAI #157 · ESM #23 | 0 | Automated review only | Awaiting the maintainer; #157 resyncs when #68 publishes |
Each thread carries a reply naming the commit and, where behaviour changed, the test that failed before the fix; threads are left open for the maintainer to resolve. For the two September rounds, every behaviour change was covered this way. Review is ongoing, and later rounds may find more.
Not carried, by decision
Nine earlier pull requests from May and June were closed on 14 September 2026, each with a note pointing at its successor. Most of their content lives on in the three above in a different shape; two ideas were set aside on purpose and are listed first.
#22, #25. Replaced by provider selection and hub product profiles; the bundled engine is configured through global properties.
#20. Prompt-prefix reuse is deferred in the dual-provider roadmap and returns as its own change.
#19. Reverted to the typed bridge; the paired build proves the pinned pair instead.
#21. Privileges are declared in config.xml; role binding is a deployment concern.
#72. Superseded by direct typed consumption of the context slice.
ESM #11, #10, #9. Superseded by the provider picker, the hub-profile picker and the turn lifecycle.
Sources: the three pull requests, their continuous-integration results, and the integration branches as read on 15 September 2026. The merge sequence, acceptance criteria and iteration log live in the upstream merge roadmap; the requirements authority remains the dual-provider parity roadmap in the project documentation.
This page describes what is proposed, not what is decided: the maintainers of these repositories review and merge on their own schedule, and the branches may change in response. Test counts and continuous-integration results are the checks named above and nothing more; this page makes no claim about clinical validation or about how the software performs in a deployment.