Releases: MBombeck/HealthLog
v1.21.0 — Date-format preference, a far more connected Coach, and broad correctness work
A feature release. The Coach reaches every data domain on demand, surfaces the cross-metric patterns the analytics tier discovers, opens in context from any screen, and speaks on one shared set of safety thresholds. Dates render in a chosen format everywhere. Two additive migrations (0192, 0193); no breaking changes.
See CHANGELOG.md for the full list. Holistic wiring/cohesion/correctness verification passed; 11452 unit tests + integration (incl. the now-resolved regression parity test) green.
v1.20.2 — Hardening across insights, safety flags, and integrations
A patch release. A broad hardening pass over the server tier and the AI surfaces — a few correctness and safety fixes, a numerical hardening of the trend tier, and several smaller robustness and cost improvements. No schema changes.
Fixed
- The symptom journal's "sustained fever" flag — which can raise an urgent prompt to seek care — now counts only consecutive calendar days, so a sparse series of isolated febrile entries no longer trips it.
- Insight generation reads only the window its 30-day comparisons need instead of a full per-metric history; generating insights on a long-history account is markedly faster, on both the page request and the overnight pre-generation.
- Photo and PDF scanning is no longer offered for text-only reasoning models that cannot read an image, so a scan fails clearly up front instead of erroring at the provider.
- A notification channel whose stored configuration cannot be read now disables itself immediately with a precise reason, instead of retrying a permanent error. This surfaces during an encryption-key rotation gap.
- The Coach cancels its in-flight model call when the browser tab disconnects mid-answer.
- Local-OCR text structuring reserves a budget proportionate to its real cost instead of the larger vision-scan ceiling, and refunds cleanly on a failed read.
- The admin diagnostic endpoints return a 422 for a malformed query string instead of a 500.
Changed
- The trend regression (slope, r² and variability) is composed from mean-centered sums, which removes a floating-point cancellation on long, near-flat windows and keeps the rollup result in line with the live computation.
Added
- The lab-report review screen marks low-confidence rows so an uncertain reading is easy to spot before it is saved.
v1.20.0 — Coach on-demand retrieval, deeper recovery insight, Fitbit, leaner data tier
Coach answers from on-demand retrieval (a small base context plus tools it calls for the exact figures a question needs); the recovery-gap reads the symptom journal and adds sleep context and is relapse-aware; Fitbit connects experimentally over the classic Fitbit Web API; the trend tier serves slope and variability without a live scan; and several built surfaces (sleep, steps, glucose, preventive care) are discoverable by default. Two additive migrations (0190, 0191); no breaking changes. Full notes: https://github.com/MBombeck/HealthLog/blob/main/CHANGELOG.md
v1.19.2 — recovery-gap symptom signal, resilience tile, long-range charts, richer device + Telegram data
The recovery-gap reads the illness journal's symptom curve; an Oura resilience tile; hourly heart-rate min/max; multi-year chart ranges render the full history; numeric Telegram measurement capture; telegram_chat_id made unique. Full notes: https://github.com/MBombeck/HealthLog/blob/main/CHANGELOG.md
v1.19.1 — Coach flow, sleep and mood polish, navigation, recovery-gap
Coach opens on a fresh chat by default with an always-visible conversations entry and a typing indicator; the health snapshot is sent once per conversation; a sleep average-per-night card; full mood-colour saturation; clearer settings/sidebar navigation; the recovery-gap names the driving vital. Full notes: https://github.com/MBombeck/HealthLog/blob/main/CHANGELOG.md
v1.19.0 — Coach context, leaner AI pipeline, new device signals, interactive reminders, wider self-hosting
Coach lab-value context + deep-link, AI-pipeline restructure, Withings ECG (verdict + waveform), Oura cardiovascular age + resilience, server-authoritative inventory, dense SpO2 consolidation, hourly heart-rate contract, sleep-debt rewrite, cycle UI overhaul, multi-range chart fix, interactive Telegram mood logging, Unraid/Portainer self-hosting templates. Full notes: https://github.com/MBombeck/HealthLog/blob/main/CHANGELOG.md
v1.18.10 — data-loss fix, measurement consolidation, grounding, full-page Coach
A correctness-and-polish release. It closes a silent data-loss path and a stalled measurement-consolidation job, hardens AI output grounding, and acts on a broad round of UI feedback. Two additive migrations (a covering index and a labs setting); no breaking changes.
Fixed
- Editing one field of a cycle or condition-journal day entry no longer wipes an encrypted note that cannot be decrypted with the current key — the stored value is preserved untouched unless that field is explicitly changed.
- The nightly consolidation of cumulative metrics (walking/running distance, flights climbed, active energy) no longer aborts on the first conflicting day, so raw per-sample history collapses to daily values as intended. A one-time compaction of the existing backlog runs after deploy.
- The daily briefing refreshes when regenerated, and the home screen reflects a saved tile layout without a manual reload.
- The Coach dictation button reports when speech input is unavailable instead of doing nothing.
Added
- The Coach has a full-width page (no panel-within-a-panel), reachable conversation history, and a clean new-chat start.
- Scan a lab report without a vision model: optional on-device OCR (off by default) reads the image in the browser and sends only the extracted text to the configured AI provider, then the same mandatory per-row review applies. The labs "Add" action now offers "scan a document" or "add a value manually".
- Withings sleep now records heart rate, respiratory rate, blood oxygen, sleep HRV, and the sleep score (previously discarded at sync).
- Oura VO2max is recorded, and the VO2max tile is shown on the dashboard by default.
Changed
- Preventive-care cards show the cadence on the metric row rather than beside the heading, and the heading opens the measurement history filtered to that metric.
- The danger zone and the daily-briefing card match the rest of the surface; the feedback tool is marked deprecated; the preventive-care and labs settings follow the standard section layout.
- Lab values: delete moved to the value's detail view, the overview tags are quieter, and the reference-range confidence is surfaced when a new biomarker is created.
- Location lookups default to the online resolver; the offline database is optional.
- Mobile: the full-page Coach composer stays clear of the bottom navigation, long navigation labels stay readable, and touch targets meet 44 px.
Performance and integrity
- Blood-pressure in-target and grade read identically whether served warm or cold (one canonical source per day).
- A per-session statement timeout stops a single stuck query from holding a connection; a soft-delete-aware measurements index; the all-time fallback scan is bounded.
Security
- Daily-briefing numbers are checked against the underlying signals; the Coach reply is screened for fabricated values or dose instructions; the period narrative is grounded before it is stored; the metric status cards state precomputed trends rather than re-deriving them.
API
- The labs OCR capability response carries a
mode(vision or text) and a new local-OCR preference; additional measurement types are recorded server-side. All additive and back-compatible.
v1.18.9 — Coach surface, lab-report scanning, fresher dashboards
A broad UI and data release. It adds two migrations (both additive and nullable — qualitative lab results and Coach token columns) and three additive, back-compatible API changes (see the note below).
Added
- Coach opens on a calm new-chat surface: a centred greeting and a single composer, then each answer streams in word by word with a soft fade, a collapsible thinking disclosure, and a quiet per-message footer showing the tokens used and the model. The quick-access drawer is unchanged.
- Scan a paper lab report. With an AI provider connected, upload a photo or PDF and the reader proposes the measurements and biomarkers it finds. Every row goes through a mandatory review — confirm, edit, or discard each one, with duplicate and reference-range hints — and only what you confirm is saved. The uploaded file is held in memory for the read alone and is never stored.
- Record a qualitative lab result — positive/negative or another text value — where a number does not apply.
- Sort lab values alphabetically, and delete a biomarker directly from the labs list and detail views.
- VO2max shows on the dashboard by default, and Oura's VO2max reading is now ingested alongside the existing sources.
Changed
- The labs surface defaults to the list view, and its tiles share the medication-card layout. The labs and condition-journal settings now follow the same section pattern as the rest of Settings.
- Preventive-care cards read the last-completed date as "today"/"yesterday" and the next due date as a discreet "today" (green) or "overdue" (orange), and drop the small trend strip.
- Sleep-debt and chronotype sit side by side, and the daily-briefing card aligns with the surrounding type.
Fixed
- The dashboard reflects new readings without a hard refresh: an added or background-synced measurement now refreshes the home snapshot — including on Withings and Apple Health sync, and on returning to the tab.
- The condition journal opens quickly again. The cross-episode correlation runs only when an entry's analysis is opened, and the typical-recovery-gap insight appears only when there is enough real data to support it.
- The latest-report area shows its age and, when no AI provider is connected, points to where to connect one, instead of presenting an old report as current.
- The Coach quick-access icon uses a softer tone.
API
- The Coach stream's
doneframe now carries an optional tokenusage, and a Coach message can carrytokensUsedandmodel; an optionalreasoningframe is reserved. NewGET/POST /api/labs/ocr/{capability,extract,commit}endpoints; rows committed from a scan carrysource: "OCR". All additive and back-compatible.
v1.18.8 — coded condition and lab terminology in the health-record export
An additive, export-only release that closes the FHIR-coding asks from the iOS client. No migration, no API contract change.
Changed
- Condition resources for journal entries carry a SNOMED CT category coding per illness type (infection, allergy, injury, mental health, autoimmune, chronic, other) alongside the user's free-text label. These stay broad categories, not diagnoses — the patient-reported, unconfirmed guard rails are unchanged. No ICD-10: a category-level entry would be a chapter range, not a billable code, so SNOMED-only is the honest choice.
- Lab Observations now emit a LOINC code and a canonical UCUM unit for the common biomarkers (HbA1c, lipid panel, ferritin, TSH, vitamin D, creatinine, eGFR, liver enzymes, CRP, fasting glucose, hemoglobin), resolved through an analyte alias table. An unrecognised analyte, or a unit that does not match the canonical UCUM symbol, keeps the honest text-only behaviour rather than asserting a code it cannot validate.
v1.18.7 — dashboard, Coach and insights polish
A broad UI, insights, and AI-efficiency release. It ships three additive database migrations and two client-facing contract changes (Coach budget responses arrive as a stream error rather than a 429; the measurement-reminder push carries the reminder id).
Added
- The daily briefing surfaces signals of the day and leads with one present-focused nudge; the Coach reads your illness state and Rest Mode, links the relevant guide, and works from a tiered view of your history. Dictate to the Coach by voice.
- The share-link section is back as its own Settings entry — mint a time-boxed, revocable, read-only link for a clinician — now with a passphrase second factor carried in a QR code (the public view stays locked until the passphrase is verified). Links created before this release keep working without one.
- Labs, preventive care, and the condition journal each have their settings as a proper section of the Settings shell.
Changed
- Far fewer AI requests per cycle: per-metric status assessments are batched into one call, prompt construction is consolidated to one shared source, and the daily briefing varies its wording day to day while findings stay stable.
- The Coach interface is rebuilt around a calm, centred reading column; the health-score rings are flattened; integration cards follow one layout. Settings cards share one primitive and touch controls meet a 44px target on phones.
- The local-AI private-host switch accepts an explicit host allowlist instead of an all-or-nothing flag.
Fixed
- A medication's supply now updates on the next read after adding a container or a new medication.
- The daily briefing no longer goes stale, and the sleep assessment no longer prompts to connect an AI provider when one is already connected.
Security
- The Coach budget gate reserves spend atomically before each request; new share links require a passphrase stored only as an HMAC hash and verified in constant time behind a rate limit; session and challenge tables are indexed on expiry; the development key-padding fallback fails closed unless the environment is explicitly development or test.
Migration
- Three additive migrations (session/challenge expiry indexes, a daily-briefing reroll marker, the nullable share-link passphrase hash). The entrypoint runs them automatically; no backfill, no downtime.