← AI in Austere Medicine Project
Release Notes · August 2026
EdgeCDSS
Version 4.1
A hardening release. No new clinical features — ten fixes to the safety plumbing, every one of them found by reading the field logs rather than the test results.
Project 01 · Active · MIT License
135Field Queries Audited
14Session Days Reviewed
10Fixes, Each Pinned By a Test
105Offline Regression Tests
Overview
Version 4.0 shipped a two-pass safety architecture: deterministic checks before generation, a semantic validator after it. Version 4.1 is what happened when we stopped trusting that description and audited what the system had actually done in the field — 135 logged queries across 14 session days, plus 26 structured feedback entries from providers.
The architecture held at detection. It leaked at enforcement. The validator saw the problems; the plumbing underneath it threw the warnings away. Every change below closes one of those gaps, and every one carries a regression test built from the exact log line that exposed it.
Detection → Enforcement → Log
A safety system is only as strong as the weakest of these three. Version 4.0 was strong at detection and assumed the other two. In 4.1 the verdict the validator reached, the verdict the provider is served, and the verdict written to the audit log are one value, produced in one place — identical by construction rather than by convention.
What's new in 4.1
Patient context resets at the patient boundary
- The finding. Patient context accumulated across every turn of a conversation with no notion of the patient changing. A 6-year-old's 34 kg was carried into an adult casualty presenting after an IED blast, and a dose was calculated against it. The validator flagged the result; a false-positive override released it anyway.
- The fix. The system now detects a patient boundary — an explicit phrase, a presentational opener, a contradicting age or weight, or 30 minutes of inactivity — and clears weight, age, and access before dosing anything.
- Every reset is announced in the response. Both failure directions are now visible to the provider: a missed boundary is the original defect, and a false boundary destroys a confirmed weight mid-resuscitation. The medic can see the second one happen.
- The reset is applied per turn as the conversation is replayed, not once at the end — the server is stateless and rebuilds context from the full history on every request, so a reset applied any later is silently undone on the next one.
- The web portal gains a NEW PATIENT button that clears the history the server replays, not merely the visible transcript.
- Measured across all 135 logged queries: 9 boundaries fire, all 9 genuine, zero false positives.
The safety gate can no longer disagree with itself
- The finding. The logging path derived its verdict independently of what was actually served. Nine hand-written false-positive overrides each released a response and discarded the validator's issue list, while the log recorded the record as UNSAFE with no issues attached. The provider got a clinical answer; the audit trail said it was blocked; the reason was gone. Two of eleven logged unsafe events had this shape, and nothing recorded which override fired, so the audit could not attribute them.
- Overrides now downgrade instead of releasing. A fired override serves the response with a human-review banner, preserves the validator's objections in the log, and records itself by name.
- The served verdict and the logged verdict are now the same value, returned from one place instead of re-derived at the call site. The invariant — a served response can never be logged unsafe — is pinned over a 216-case matrix.
- No structured issue means fail closed. When the validator returns an unsafe verdict with nothing structured to reason about, there is nothing for an override to be a false positive of, and the gate blocks rather than pattern-matching against the validator's free-text prose.
The dose contract is enforced when it is empty
- The finding. Deterministic dose verification — the check that catches a generated dose the code never authorised — was skipped entirely when Python had computed no dose candidates. That is precisely the state that means no dose was authorised at all: no confirmed weight, nothing to check against, and a language model at its most likely to invent a number. The check read that as "nothing to check."
- An empty contract now hard-blocks every canonical dosing line, for adults as well as pediatric patients — the net that existed below this check only covered pediatrics. The block names the drug, the dose, and the empty contract, and no override can downgrade it.
- Hard-coded doses are out of the protocol block. A maintenance dose written into the guidance text reached the model without ever passing the contract. The drug and the sequencing stay; the number is gone, and a test now fails if any protocol string reintroduces one.
Retrieval and routing
- Ventilator-settings questions no longer return an intubation drug bundle. A bare substring match on "ventilator" dispatched them into the rapid-sequence-intubation pre-gate before vent settings were ever considered — a request for settings came back as ketamine, rocuronium, and post-intubation sedation. Genuine post-intubation phrasings still route to RSI; the settings intent is diverted out.
- The clinical router matches whole words. Substring matching against an alias table with 44 short keys meant any query containing patient silently appended "physician assistant" to the retrieval search, and dka pulled in "ketamine". Across the audited corpus this removed 143 spurious matches on 80 of 135 queries — with no aliases deleted, since at word boundary the short keys fire only when actually typed.
Observability
- Session logs gain pipeline latency, the name of any override that fired, whether a patient boundary reset, and a synthetic-traffic tag — stamped with a schema version so older entries are never misread as new ones.
- Test traffic is now distinguishable from field traffic. The clinical suite fires at the live endpoint by design, and 48 of the 135 audited entries — over a third of the corpus — turned out to be two test runs that had been indistinguishable from real provider use.
- That tag is self-declared by the caller and deliberately load-bearing on nothing: it is log hygiene, not a security control, and a test asserts the pipeline behaves identically with and without it.
Deployment safety
- A mistyped tuning value can no longer prevent startup. One numeric setting was read at import time, so a typo in it — a stray unit, a trailing space — would stop the service from starting, leave the health endpoint unanswered, and put a fanless device behind an outbound-only tunnel into a reboot loop with no way back in. Bad values at all three numeric settings now fall back to the default and say so out loud, because a silently ignored setting is its own failure.
How this was found
Not from the test suite. The test suite passed. Every finding above came from reading 135 real query logs line by line, cross-referenced against provider feedback, and each one was reproduced against the shipped code before a fix was written. Where the audit's own conclusions turned out to be wrong under that scrutiny, the correction is recorded in the repository and pinned by a test so it cannot be quietly re-assumed.
The working rule for the release: one fix, one commit, one regression test — plus a mutation check on every one, where the fix is reverted, the named test is confirmed to fail, and the fix restored. The offline suite that resulted runs 105 tests in about two and a half seconds with no network, no API key, and no vector database.
Known boundaries
This release trades helpfulness for fail-closed behaviour, and one case is worth naming. A provider asking about status epilepticus with no weight on file now receives a safety hold where a weight-free protocol answer would have served them better. That is the intended direction of the trade, but it is a real regression in usefulness and is being watched in post-release feedback. Separately, the single most frequent provider complaint — that the system declines questions outside its trauma guideline corpus — is not addressed by 4.1 and remains open.
EdgeCDSS is decision support, not a decision-maker. It is a research prototype evaluated with simulated and synthetic scenarios only — not validated for clinical use and not for patient care decisions. Language generation currently requires connectivity to a cloud model; the generation layer is deliberately swappable, and a cross-model comparison (OpenAI / Claude / Gemini) is planned. A fully offline on-device model remains the research goal (Project 02).
The lesson
Audit your logs. Not your test results — your logs. The gap between what a system is documented to do and what it has actually done is where the incidents live, and it is only visible in the record of real use.
Research prototype — not validated for clinical use — not for patient care decisions — simulated and synthetic scenarios only — do not enter patient names, dates of birth, or identifying information into any system on this site. All code is open source under the MIT License. Technologies and services used include NVIDIA Jetson, OpenAI, Cloudflare, Starlink, ElevenLabs, GitHub, Cursor, Claude, Google Gemini, Visual Studio Code, FastAPI, and ChromaDB; provider names identify components used by the project and do not imply endorsement, sponsorship, or affiliation. AI in Austere Medicine Project 2026.