Files
HealthLog/CHANGELOG.md
T

846 KiB
Raw Permalink Blame History

Changelog

[Unreleased]

[1.30.21] — 2026-07-19

Dose reminders land on the right hour across a clock change.

  • A reminder on a clock-change day now fires at the time you set. The conversion from your local time to a real instant read the timezone offset at the moment the scheduler happened to run, not at the time the dose was actually due. On the autumn change in a timezone that observes one, a 20:00 dose could resolve to 19:00 when the scheduler ticked before the change. Two days a year, and only in timezones that change their clocks — but a dose reminder should never be an hour off. Nothing stored changed; the same schedule now produces the correct instant.
  • A duplicate pending dose was possible on those same days. The reminder projector, the worker and the intake write derived the instant separately and could disagree on the change day, which broke the matching that keeps them on one row.
  • The next-dose day label could show the wrong day when your device timezone differs from the one in your profile, because the offset was applied twice. The two copies of that label — in the card and in the table — are now one.
  • The tests could not have caught any of this: they used times with no timezone attached, so the day boundary could not be distinguished from a UTC one, and the suite ran only in one host timezone. They now state their timezone explicitly, cover both clock changes, and the suite is pinned to match the build.

No breaking changes.

[1.30.20] — 2026-07-19

  • A restore now refuses when the backup file names a different account than the backup record. The restore target was read from inside the encrypted file rather than from the record the operator selected, so a file claiming a different account would have been written into that account instead — while the audit entry recorded the one the operator picked. Both values were already available at that point; they are now compared, and a mismatch is refused and recorded with both.

No breaking changes.

[1.30.19] — 2026-07-19

Switching a module off now holds everywhere.

  • Three surfaces ignored your module switches. The per-topic endpoints have always honoured them, but the sync feed still sent cycle data, the FHIR export still returned the full record including the insurance number, and the dashboard summary still built glucose and sleep cards — all regardless of whether those modules were on. Each now honours the switch: the sync feed leaves the cycle rows out, the FHIR export refuses the same way the health-record export already did, and the summary omits the cards. Nothing is deleted — turning a module back on finds the history complete, and the sync feed picks up where it left off rather than skipping what changed while it was hidden.
  • Two assistant features reached a provider without a consent record. The follow-up questions after saving your profile, and the assistant's own nudges, both sent data to a provider without checking whether consent was on file — and could fall back to the server-wide key. Both now check first and fall back to their non-generated text when consent is absent. The follow-up questions also moved to the same reservation-based spend accounting everything else uses; a self-hoster on their own key is no longer measured against the operator's daily ceiling.
  • The check that was supposed to catch the module gaps accepted a helper being imported as proof that a gate existed. It now pins which module each surface must check and names the tests that exercise a disabled one.

No breaking changes to the web app. The native client may see a 403 from the FHIR endpoints and absent cards where a module is off — see the coordination note.

[1.30.18] — 2026-07-19

Health data and credentials no longer reach the logs or the backups.

  • Cached responses are encrypted at rest. A write endpoint's response is kept for 24 hours so a retried request cannot run twice. Those responses echo what was just saved — cycle notes, mood text, allergy reactions — and were stored unencrypted, in a column that lands in every backup. They are now encrypted like every other stored health field. If encryption is unavailable the response is simply not cached, rather than being written in the clear.
  • Diagnostic log entries are scrubbed at the point they are written. Two of the places that build a log entry did not run the redaction the others did, so an outbound request that timed out could put a notification bot's credential into the logs verbatim.
  • A failed AI request no longer quotes what the provider sent back. Some providers echo the request they rejected, which on this path contains the prompt and the health figures in it. The log entry now names the kind of rejection instead of quoting the response, which answers the same diagnostic question without carrying the content.

Operator note: no action required, and no configuration change. Log lines and backups written before this release may contain the values described above.

No breaking changes.

[1.30.17] — 2026-07-19

API tokens now enforce their scope.

  • A token minted for medication intake is refused outside the ingest endpoint. Previously any valid token reached every authenticated route regardless of the scope it carried, so a token handed to a third-party automation could read the full-account backup export, lab results, measurements and the assistant. A route that accepts a narrow-scope token now has to name that scope; a route that names none accepts browser sessions and the app's own full-access tokens only. Tokens issued to the web session, the native client and the MCP connector are unaffected.
  • Revoke and re-issue any token you handed to a third party. A token that could reach the backup export should be treated as having had that reach for its whole lifetime, not only from the moment it was noticed.
  • The generic "create API token" button is gone from settings. The token it minted never worked for the medication intake it advertised — the ingest endpoint also requires a per-medication grant that this button never issued — while reaching everything else. Tokens are issued per medication from the medication's own API-endpoint toggle, which grants exactly that one medication. Existing tokens stay listed and revocable.
  • MCP connector tokens are now bound to the MCP endpoint alone. They previously also passed on read-only REST requests. No connector flow used that.

No breaking changes to the web session, the native client, or the MCP connector.

[1.30.16] — 2026-07-19

Stops an ongoing loss of resting heart-rate history.

  • Resting heart rate is preserved again for accounts without a device-supplied resting figure. Older heart-rate readings are condensed on a schedule to keep the database small, and a resting value is derived and stored before the raw readings go. The check that decides whether an account already has its own resting data was matching the derived values it had written itself, so from the second run onward it concluded the data was already there and stopped deriving — while the raw readings it derives from were still being cleared. Each run lost another day's resting figure permanently. The check now looks only at readings the account actually supplied.
  • Days already affected cannot be reconstructed; from this release forward, nothing further is lost.

No breaking changes.

[1.30.15] — 2026-07-18

Generated health texts now come in the language you set.

  • French, Spanish, Italian and Polish accounts get their assessments in their own language. Every locale other than English previously fell back to the German instruction set, so those four either read German text or — where the pipeline narrowed them earlier — English text. Insight cards, the per-metric assessments, derived scores, the biomarker card, the period narrative and the assistant's tone settings all now follow the account's own language, with the wording rules that were already translated for each of the six languages. German and English output is unchanged, character for character.
  • The language instruction is the last thing the model reads, rather than being buried before the metric-specific section that follows it.
  • Under the hood: one shared resolver replaces the scattered English-or-else-German branches, and the locale now survives the whole generation path instead of being narrowed on the way in. Stored texts for the four languages regenerate on their next scheduled run; German and English keep reading exactly the rows they already had.

No breaking changes.

[1.30.14] — 2026-07-18

The workouts page joins the pages that paint on first load.

  • The workouts list opens with the sessions already there. It was the last high-traffic surface still fetching its rows after the page mounted, so it showed a loading skeleton first and filled in a moment later. The list is now read on the server and handed to the page populated, the same way the dashboard, insights, medications, and coach pages already work. The list logic moved into a shared read so the page and the API endpoint go through one cached, deduplicated pass instead of two.
  • API docs: the heart-rate bucket example matches what the server accepts. The aggregated heart-rate externalId was documented with an hourly example from its first version; the contract has been 10-minute buckets since v1.30.7. The description, the example timestamp, and the min/max field notes now describe the shipped contract.

No breaking changes.

[1.30.13] — 2026-07-18

More pages that paint on first load.

  • The insights, medications, and coach pages open with their content already there, the same way the dashboard now does — their above-the-fold data is read on the server and handed to the page populated, instead of a shell that fills in after a second round of requests. Nothing that would trigger AI work is pre-run: the daily briefing and the coach's own reads stay on-demand as before.

No breaking changes.

[1.30.12] — 2026-07-18

Faster medication reads.

  • The dashboard's medication section stays fast as your log grows. Its reads now use dedicated indexes instead of scanning the full intake history on every load, so a long history no longer slows down the daily view.

No breaking changes.

[1.30.11] — 2026-07-18

Native single sign-on.

  • The iOS app can sign in through your identity provider (OIDC SSO). Until now, single sign-on only worked in the browser — the native app couldn't complete it, which locked native users out entirely on an SSO-only instance. The server now supports a native sign-in handoff (an in-app authorization flow that returns the app's normal token, never a cookie), so the app can offer SSO once it adopts the flow. Existing password and passkey sign-in are unchanged. Multi-factor sign-in still applies, and an SSO session never satisfies a step-up prompt — those still require your own second factor.

No breaking changes.

[1.30.10] — 2026-07-18

Localized insight text, and a richer workout view.

  • Correlation insights now read in your language. The "this tends to go with that — a pattern worth watching, not a cause" lines under a metric were always written in English; they now render in your interface language (German, Spanish, French, Italian, Polish), with the association-not-causation framing preserved in each.
  • A workout you open shows more of what was recorded. The detail view now draws the session's heart-rate curve over time, its route as a clean line, the time spent in each effort zone, per-kilometre splits, and how it compares to your own average for that sport — all from data already synced, with no new connection. Anything a given workout didn't record simply isn't shown.

No migration. No breaking changes.

[1.30.9] — 2026-07-18

Faster dashboard first load.

  • The top card and the charts paint with their data on first load instead of flashing empty and then filling in. The daily summary and the charts' 31-day series are now read on the server and handed to the page already populated, so there's no wait for a second round of requests after the page appears. The welcome/summary card, likely the slowest thing to show before, now lands with the first paint.

No migration. No breaking changes.

[1.30.8] — 2026-07-18

Hardening for the new heart-rate upload validation.

  • A malformed bucket timestamp is rejected, not silently misfiled. A bucket whose time rolled over (a 24:00, an impossible day) is now refused rather than stored under a non-standard key, where it would have failed to merge with a re-post and could land on the wrong day.
  • The per-window low/high is sanity-checked before it counts. A window's low and high are kept only when they are in a plausible range and sit either side of the average; a glitched reading no longer skews the day's high/low band. The average is always kept.

No migration. No breaking changes.

[1.30.7] — 2026-07-18

Groundwork for a tidier heart-rate history.

  • The server accepts a 10-minute aggregated heart-rate upload. A watch records heart rate every few seconds, and uploading one row per raw sample fills the measurements list with the same value repeated many times a minute. The server now takes one row per 10-minute window — its average, with the low and high of the window — and the within-day pulse curve reads it directly, so the detailed 10-minute chart and the elevated-at-rest note are preserved. The de-duplication reaches the list once the mobile app sends the aggregated shape; existing per-sample history is unaffected and reconciles itself over time.
  • The daily high/low reflects the true spread. A day built from 10-minute windows now reports the real intra-window extremes, not the range of the averages.

No migration. No breaking changes.

[1.30.6] — 2026-07-18

Accessibility pass.

  • Heatmaps read to a screen reader. The mood and medication-compliance grids now expose each recorded day — its date and value — through a hidden day list, so the per-day figures are no longer reachable by pointer only. The chart looks exactly the same.
  • Small labels meet the minimum size. Muted meta text across settings, admin, the coach panel, and the insights cards is lifted off the sub-text-xs sizes; tabular figures and chart chrome are unchanged.
  • A couple of section headings. Two metric-page sections became proper headings, so heading navigation lands where it should.

No migration. No breaking changes.

[1.30.5] — 2026-07-18

Making a shipped feature findable, and a sync-status fix.

  • ECG has a home you can reach. Recordings now have their own page in Insights, a pill in the Heart group that appears once you have a recording, and links to it from the resting-pulse and heart-rate-variability pages. Before this they were reachable from a single spot, and a deep link into the overview could land before the section had drawn. The page is unchanged in substance — the same non-diagnostic, device-attributed view.
  • The "last synced" time stops lagging. A sync driven by an incoming update now records the connection's last-success time straight away, instead of leaving it frozen until the next full poll — so the Settings status and the assistant's integration read reflect a sync that already happened.

No migration. No breaking changes.

[1.30.4] — 2026-07-18

The read-only assistant connector now reaches the full record.

  • More of your data is readable. The connector gained direct reads for nutrition and vitamins, the intraday pulse curve, and stored ECG recordings, plus discovery for a set of device metrics that were collected but not advertised — wrist temperature, cardio recovery and load, day and workout strain, sleep score, breathing disturbances, fall count, the six-minute-walk distance, stair speeds, and energy expenditure. They can now be compared and baselined by name.
  • Correctness. Heart-rate variability resolves whether the source records the SDNN or the RMSSD flavour, so a ring- or strap-only account is no longer reported as having none. A workout logged by two devices is counted once, matching the workouts list — this also corrects the figure the coach sees.
  • Exposure stays deliberate. The mental-health screeners and the environmental signals remain off the connector by construction; a metric is only readable once it has been named for it.

No migration. No breaking changes.

[1.30.3] — 2026-07-18

Follow-up fixes from a full quality re-check of the app.

  • Correctness reaches every surface. The timezone, window, and grain fixes now also cover the coach's correlations, the per-metric cards, and the period narrative (they had kept an older copy). Daily insight cards roll over at your own midnight, not a fixed one. Personal records that a second device had inflated are re-derived on the next start, so a genuine record can be set again.
  • The metrics catalog shows a loading state and a retry on error, instead of briefly reading as "not tracked".
  • Small. One shared info popover, larger tap targets on the view toggles, a notch-safe height fix on the coach history page, and a few wording and translation gaps closed (a body-composition caveat, study citations, the backup scope note).

No breaking changes.

[1.30.2] — 2026-07-18

More audit-backlog fixes.

  • Coach history is fully reachable. The conversation list pages through your whole history and search runs on the server (by title), instead of only the first ~20 loaded chats.
  • Navigation and flows. A document links to the lab values it produced; the two "Recovery" pages are named distinctly and cross-linked; mood, mental wellbeing, and mood insights link to each other; the nutrients card moved out of "Source priority"; the onboarding checklist and tour no longer point at dead ends; asking the coach from a metric or a plan carries that context in.
  • Correctness. Correlations, the intraday chart, achievements, and the nutrients overview now bucket days by your own timezone and lead with the most recent data; a multi-source day is no longer counted twice.
  • Performance. The workouts list caches its de-duplication per filter, so paging through a long history is quick.

No migration. No breaking changes.

[1.30.1] — 2026-07-18

Polish and small fixes.

  • Mobile. Coach and document text wraps instead of overflowing; the intake history is a card list on small screens instead of a sideways-scrolling table; tap targets meet the minimum size; two dialogs became bottom sheets; the workout detail header stacks cleanly.
  • Feedback. Loading skeletons match the content that replaces them (no more layout jump), and the Today priority-card actions show a pending state and can’t fire twice on a double-tap.
  • Remembered choices. A chart’s time range and the measurement type you last logged are remembered; a coach chat deletes with an Undo; a backdated dose can be undone; lab panels get “Save & add another”; pull-to-refresh works on more pages (and a scroll-position bug that made it fire anywhere is fixed).
  • Consistency, accessibility, wording. Spacing and contrast tidied, more empty states use the shared component, headings and focus rings improved, a few German phrasings corrected, the daily line reads more calmly, and several explanations gained their guideline citation.

No migration. No breaking changes.

[1.30.0] — 2026-07-18 — Quality pass

A broad correctness, performance, and polish release, plus two new features. Nothing new is required of you; existing data is untouched.

Added

  • Document summaries. An uploaded document can get a short plain-language summary, generated once at upload and stored encrypted. It runs only when the external-AI document reading you already opted into is on, and never touches older documents.
  • Efficacy chart, readable. The medication efficacy chart scales its axis to the data (a real trend no longer looks flat), gains a “% since start” view, and the history tab reaches your full intake history, not just the last 90 days.
  • A metric catalog. A quiet “All metrics” view lists everything HealthLog can track and which device supplies each — so a metric you don’t have data for stays out of your daily views but is still discoverable in one place.

Fixed — correctness

  • The number shown matches reality. The workouts and measurements lists now lead with the most recent entries (a long history no longer hid recent days), and a metric recorded by two devices on the same day is counted once, matching the dashboard — instead of being summed twice.
  • Strava workouts carry their real sport (cycling, running, …) — like WHOOP already did — with a history backfill, and back-to-back rides no longer collapse into one.
  • Personal records and correlations no longer double-count multi-source days or mix per-reading and daily-total values.

Fixed — medical safety

  • The hypoglycemia alert now uses your own glucose unit; the doctor-report PDF states your own timezone; the crisis card offers Austrian and Swiss lines, not only German ones; and resting-pulse labels drop clinical-verdict wording for calmer, neutral framing.

Fixed — the daily view

  • The Today view is faster (its heaviest reads are now cached instead of recomputed on every refresh) and updates immediately after you log a measurement, mood, or water — not only medication.
  • The intraday heart-rate chart no longer draws a continuous shape across gaps in sparse data, and shows how many readings it’s based on. A failed load shows a retry instead of an empty state.

Fixed — onboarding, dates, consistency, accessibility

  • Connecting a device no longer dead-ends on a fresh account, and the setup steps (including the callback URL) are shown up front.
  • A date from a previous year now shows the year, everywhere it’s displayed.
  • Contrast, chart colours in the light theme, and a handful of duplicated components were tidied; keyboard access and headings improved on several surfaces; the insights and settings menus are grouped more sensibly.

Changed

  • A fuller backup. The full backup now also includes lab results, illness episodes, allergies, family history, workouts, and a documents list. What isn’t included (raw document files, workout GPS/heart-rate detail) is stated plainly.

Performance

  • The Today digest and the insights cards read through the pre-aggregated tier instead of scanning raw rows; batch imports write in one pass.

Two migrations (0250, 0251). No breaking changes.

[1.29.5] — 2026-07-17

Security

  • Hardened the same-origin redirect guard. A crafted relative post-login next path (e.g. /..//evil.com) passed the same-origin check but left a protocol-relative pathname that could re-resolve to a foreign origin when re-used in a redirect or client navigation. The guard now re-verifies the reconstructed path resolves on-origin and rejects it otherwise. Covers the OIDC callback and the password/passkey login redirect.

Fixed

  • OIDC login redirects use the operator app URL, not the request URL. Behind a reverse proxy that does not forward the original host, the login and callback routes built their browser redirects from the address the app was reached at inside the container, sending users to an unreachable internal URL after login. Every OIDC redirect is now built from the operator-set NEXT_PUBLIC_APP_URL, matching the convention the other integrations already use.

[1.29.4] — 2026-07-17

  • The workouts list shows the most recent first. The list was ordered oldest-first, so on a longer history the newest sessions never made the first page. It now leads with the latest workout.
  • Past-year dates show the year. A workout from a previous year now carries its year in the list, so a December date is never mistaken for this year's.

[1.29.3] — 2026-07-17

  • Hydration and micronutrients now have a home. Your fluid intake and the vitamins and minerals your device records get a surface. A water tile on the dashboard shows the day's total with quick-add amounts; a new Nutrients page under Insights shows hydration over the last month, caffeine when you record it, and the vitamins and minerals you actually have data for — each against its reference daily intake where that applies, shown as context, never as a verdict. Manual water entries and device-synced totals now coexist instead of overwriting each other. Sparse logging is never read as a deficiency.

    The nutrients tracking stays opt-in — enable it in Settings, or with the one-tap prompt on the page. Device-synced micronutrients flow once your client sends them.

One migration (0249). No breaking changes.

[1.29.2] — 2026-07-17

  • WHOOP workouts carry their real sport. WHOOP was the only source that didn't translate its activity into the app's own sport names, so WHOOP-tracked rides and runs landed unlabelled instead of as cycling or running. New and existing WHOOP workouts are now mapped, so your bike rides show up as cycling — history included. When the same session comes in from two sources, the canonical row now keeps the richest reading (heart rate, energy, distance) instead of dropping it.
  • Scroll back through the day's heart rate. The intraday heart-rate view gains a day navigator to step through previous days. The fine-grained history now stays for 90 days (was 14); older days show the coarser hourly shape.
  • Clear a card from Today. A milestone, a new ECG, or a tension note can be dismissed from the Today rail once you've seen it; the section tightens when the last one is gone. The cards that need an action stay until you act.
  • Vitals context moves into an info tap. The vitals tiles carry an (i) with the context — your reading against your personal range, and against your age where that applies — instead of a permanent caption. The VO₂ max heading no longer gets cut off.
  • Oura cycle phases feed the cycle tracker. Where your Oura connection provides cycle-phase data, it now fills the cycle tracker as a background source; your own entries always win.

Two migrations (0247, 0248). No breaking changes.

[1.29.1] — 2026-07-17

A round of fixes and small refinements from living with the daily view.

  • Today refreshes right after a dose. Logging or undoing a medication now updates the day's read immediately — the medication line no longer lingers on a stale count until the next reload.
  • A calmer Today hero. The extra score rings are gone; the hero keeps the one health-score ring and a tighter layout.
  • The Coach names the document you attached. Asking about a document now shows its title in the chat instead of a plain "1 document" count, and the attach menu stays within its popover on long labels.
  • A fresh install starts with tracking on. New installs now enable the tracking modules by default — you can still switch any of them off. The external-AI options and the daily push stay off until you turn them on.
  • Insights vitals lose the explainer line. The "your personal normal range is the median…" caption is removed from the baseline tiles.
  • Illness journal: set and edit the end. You can mark an episode's end date, clear it back to ongoing, and backdate the start. When nothing strayed from your personal range, the course section now reads a short settled line instead of appearing empty.
  • The morning refresh covers every sleep source. The refresh that folds last night's sleep into the day now triggers from Google Health, Fitbit, Oura, and Polar as well, not only Withings, WHOOP, and Apple Health. Each skipped refresh is now recorded so a stale morning read can be traced to its cause.

No new data is collected and there is no migration.

[1.29.0] — 2026-07-17 — A daily health companion

This release draws a line under a run of work that turns HealthLog from a place you record your health into one that meets you each day — and it completes that picture with the pieces that make it feel whole.

Over the last releases the dashboard gained a Today view that leads with the day's read, a health score that refreshes the moment last night's sleep syncs, a coach check-in when a plan is due for a look-back, and an optional morning note. Documents came closer to hand — the Coach opens beside them, you can bring several into a conversation, and lab values move between a document and your labs. This release adds the layer that ties it together:

  • Your heart's rhythm, in context. ECG recordings are no longer a page on their own — they're referenced where your resting heart rate and rhythm are discussed, always as the reading your device produced, never a reading of the app's own. A new recording surfaces gently in Today.
  • The shape of your day. Heart rate is now drawn across the day, not just as a daily number — so you can see it settle and climb. When it stays elevated while you're at rest and not moving, Today notes it plainly as possible tension, carefully and never as a verdict.
  • Quiet milestones. Reaching a steady stretch in your target range, or a new personal best, is marked with a calm moment — states you've reached, not streaks to keep, so there's nothing to break and nothing to nag.
  • One piece throughout. The Today view brings back the health rings you choose, each surface carries its metric's own calm colour, and the whole thing reads as one design rather than a stack of features.

Nothing new generates when you open the app — every daily surface reads the insight prepared overnight. No new data is collected; this makes more of what's already yours.

Four changes bring documents and your record closer together:

  • Ask the Coach opens beside your document. Asking about a document now opens the Coach in a side panel rather than jumping to a full page — expand it to full screen whenever you like, and it keeps its place.
  • Bring documents into a Coach chat. From the composer's "+", attach one or more documents — pick from your vault or upload a new one, at the start or mid-conversation — and the Coach answers grounded in them. A conversation with a document runs in its fenced mode: grounded in those documents only, with no access to your health data or tools, so nothing in an uploaded file can reach anything it shouldn't.
  • Lab values from a document, proposed for your labs. When a document you've had read looks like lab work, its values are detected and proposed — one tap to add them to your labs; they're never added without your say-so.
  • A lab scan is also kept. Scanning a lab report into your labs now also files the document in your vault (encrypted, like every upload) and links the two, so the reading and its source stay together.

Migration 0245 (attaching multiple documents to a conversation) accompanies this release; existing document chats carry over unchanged.

Three pieces turn the Today view into a daily loop:

  • A coach check-in. When a coach plan is due for a look-back, it surfaces as a calm card in Today with keep, adjust, or let-go — one tap. Letting go retires the plan quietly; silence never changes it.
  • A morning that reflects last night. The score and read are prepared overnight, but last night's sleep usually hasn't synced by then. Now, the moment it arrives, the sleep-dependent parts refresh on their own — so by the time you look, the day is up to date. Until sleep is in, Today says so plainly instead of showing a stale score.
  • An optional daily nudge. A once-a-day morning notification with the day's read, off by default and opt-in per channel under Notifications. It carries the refreshed digest when sleep is in, never repeats within a day, and is a calm note — never an alert.

All three read the digest prepared overnight; nothing is generated when you open the app.

With the Today view now leading the dashboard, the older opt-in hero card it replaced is retired, so the two never stack. The greeting stays, the tiles and charts are unchanged, and a layout stored with the old hero switched on simply ignores that setting — nothing to redo.

[1.28.53] — 2026-07-16 — A "Today" overview at the top of your dashboard

The dashboard opens with a Today view: your health score, the day's lead read, and a short "worth a look" list — a dose window that's open, an integration to reconnect, a check-up coming due — each a single tap to the right place. The familiar tiles and charts sit just below, unchanged.

It reads the insight that's already prepared overnight, so it loads instantly and never generates anything on open. When last night's sleep hasn't synced yet, it says so plainly and fills in the sleep-dependent parts once the data arrives, rather than showing a stale or empty score. This is the first piece of a single daily view that later surfaces — a morning refresh, an optional daily note — will all build on.

The dashboard gains tiles for readings that were synced and charted but never had a place on the home strip: heart-rate variability, blood oxygen, breathing rate, wrist temperature, and — for anyone with a body-composition scale — muscle mass, body water, and bone mass.

Each tile appears only once you have that reading, so nothing new shows up on an account that doesn't track it, and every tile can be toggled or reordered under Settings → Dashboard like the rest. Tapping one opens its detail view. Nothing changed in how the readings are stored or synced — this only surfaces what was already there.

[1.28.51] — 2026-07-16 — Chatting about a document lives in the Coach now

Asking the Coach about a document used to open a separate, half-finished chat panel that never showed up in your Coach history. It now opens the real Coach: the conversation appears in your Coach list like any other, marked with a small document badge and a "Chatting about: