mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
chore(release): v1.34.0 — a failure looks like a failure, a number is yours or it says so
This commit is contained in:
1 parent
2bab06e323
commit
17e09345d2
3 files changed
+245
-25
No files matched your search
+155
@@ -2,6 +2,161 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.34.0] — 2026-07-28
|
||||
|
||||
Two things this release keeps saying to itself. A job, a sync, or a write
|
||||
that fails can no longer report success by falling off the end of a
|
||||
function. And a number the app grades you against is either yours or it
|
||||
says plainly that it is not.
|
||||
|
||||
### A failure now looks like a failure
|
||||
|
||||
Every background job in this codebase, all 104 of them across five queues,
|
||||
used to signal success by returning nothing. A handler that caught an
|
||||
error, logged a warning, and returned was indistinguishable from one that
|
||||
finished its work, so a queue could fail quietly for as long as it liked.
|
||||
Every handler now has to construct and return the outcome of what it did,
|
||||
and the type system enforces it: a handler that falls off the end no
|
||||
longer compiles. Retry behaviour was reviewed queue by queue rather than
|
||||
flipped in bulk, because a rethrow changes what runs, not only what shows
|
||||
up on a screen.
|
||||
|
||||
The same fix reached the surfaces you actually watch. Six integration
|
||||
cards and the lab import dialog used to key their tone off whether the
|
||||
network call itself succeeded, so a sync that imported nothing because
|
||||
every reading was refused still rendered a green tick, and a re-scan
|
||||
where every row turned out to be a duplicate raised a success toast for
|
||||
zero saved readings. They now render the outcome the server actually
|
||||
resolved: a tick only when everything landed, a warning when part of it
|
||||
did not, an error when none of it did.
|
||||
|
||||
### Grading you against your own numbers
|
||||
|
||||
The Health Score graded your weight against a target nobody set, silently
|
||||
computed from your height and never shown anywhere. If you had entered
|
||||
your own weight target on the targets page, the score ignored it. Both
|
||||
the targets page and the score now read the same target you actually
|
||||
set, and an account with no target of its own gets a plain trend reading
|
||||
instead of a number graded against a hidden goal. The score's weight row
|
||||
now says outright which of the two it used.
|
||||
|
||||
The Health Score itself is rebuilt on the same coverage-and-provenance
|
||||
contract the rest of the app's derived metrics already use. Every pillar
|
||||
now says what went into it and what did not, weights redistribute openly
|
||||
when a pillar has nothing to grade instead of quietly changing what the
|
||||
number means, and the card explains itself the way the other Insights
|
||||
cards do. Because both of these changes move the same number, they are
|
||||
explained once: the score carries a version marker, and the first delta
|
||||
you see after updating is suppressed rather than reported as a real
|
||||
day-to-day change, with a note on the card saying why.
|
||||
|
||||
Steps, active energy, distance, and flights now compare today's running
|
||||
total against what is typical for you at this same hour, not just
|
||||
against your latest reading, which never meant anything for a metric
|
||||
that only makes sense as a full day. It needs at least two weeks of your
|
||||
own history before it says anything, and until then it says so honestly
|
||||
instead of guessing from three days of data.
|
||||
|
||||
### What was asked for, and built
|
||||
|
||||
An account-defined custom metric can now feed the same correlation engine
|
||||
your built-in metrics already run through, so a value nothing else in the
|
||||
app tracks can be checked against your own outcomes rather than sitting
|
||||
in its own silo. Caffeine and nicotine join alcohol as taggable factors in
|
||||
that same engine. A correlation or crosstab finding can be dismissed once
|
||||
it has been looked at, and stays dismissed instead of recomputing itself
|
||||
back into view on every run.
|
||||
|
||||
Three facts about you, smoking status, alcohol pattern, and shift or
|
||||
rotating-schedule work, can now be recorded as dated, correctable entries
|
||||
rather than buried in free text, with their own switch for whether they
|
||||
reach the Coach's prompt at all.
|
||||
|
||||
The "worth a look" rail on the dashboard can now be trimmed to the kinds
|
||||
of item you actually want to see there. Turning a tile off there only
|
||||
hides it; it does not touch the medication reminder itself, which keeps
|
||||
firing on its own channel regardless of what the hero card shows.
|
||||
|
||||
### Two defects, found by people who read the code and the numbers
|
||||
|
||||
A workout synced from Google Health with a sport type the app's mapping
|
||||
table did not recognise lost that type outright and rendered as
|
||||
"Other," identical to a workout that genuinely had no category. The
|
||||
original label is now kept on the row, the same way three other
|
||||
providers already keep theirs; a full re-sync repairs workouts already
|
||||
written under the old behaviour.
|
||||
|
||||
A same-time baseline band for a metric that cannot go negative, such as
|
||||
step count, could report a lower edge below zero. One call site is now
|
||||
required to name which metric it is drawing a band for, so the floor
|
||||
comes from that metric's own declared range rather than being patched in
|
||||
by hand at each caller.
|
||||
|
||||
**Reminders for a multi-dose schedule stopped matching the dose they were
|
||||
meant for.** The reminder tick computed one window length for a whole
|
||||
schedule and applied it to every time slot in it, so a twice-daily
|
||||
schedule gave its first dose a ten-hour grace period nobody configured
|
||||
while a single-dose schedule with a narrow window escalated correctly but
|
||||
then had almost no room to register a dose logged late. Each slot now
|
||||
resolves its own window: an explicit per-dose override first, then the
|
||||
schedule's own grace setting, then the same default every other
|
||||
unconfigured dose gets, bounded so two doses in one day can never share a
|
||||
window.
|
||||
|
||||
A Fitbit workout kept only its canonical category and dropped the raw
|
||||
activity name and type id it arrived with, unlike every other provider
|
||||
this app syncs from. An unrecognised Fitbit activity had nothing left to
|
||||
diagnose it by. Both are now kept on the row, and carried through backup
|
||||
and restore the same way.
|
||||
|
||||
### The backup
|
||||
|
||||
Your custom metrics and their readings, and the encrypted health-profile
|
||||
facts above, are now carried by export and restore. Neither was before;
|
||||
a restore silently rebuilt an account without either and reported
|
||||
success. The hourly shape behind the same-time baseline is also carried,
|
||||
because past a short grace window it is the only copy of that curve
|
||||
anywhere. And the summary shown after uploading a backup now counts every
|
||||
record class it restores, including the nutrient day totals it was
|
||||
quietly leaving out of its own total.
|
||||
|
||||
### For operators
|
||||
|
||||
Four migrations. `0283` adds the intraday cumulative profile table,
|
||||
`0284` adds the effective-dated health-profile fact table and its
|
||||
inclusion enum, `0285` adds correlation-pattern identity, `0286` seeds
|
||||
the caffeine and nicotine mood tags. None deletes or rewrites a
|
||||
measurement.
|
||||
|
||||
### Credit
|
||||
|
||||
Reported by @lutzkind (#613, #614, #616, #617, #649, and a long run of
|
||||
earlier reports this release also carries forward). Reported by
|
||||
@tarantila, directly rather than on the tracker: the Google workout-type
|
||||
loss, and a below-zero baseline reading that turned out to affect
|
||||
other metrics once someone went looking. Built by @mathewcsims
|
||||
(Refs #662): the per-slot reminder window fix.
|
||||
|
||||
### Thank you
|
||||
|
||||
Eighteen people have opened a report or a request on this tracker so
|
||||
far, most of them owing this project nothing. @lutzkind alone has filed
|
||||
twenty-four, several arriving with the broken code path already traced.
|
||||
@tarantila reports straight to the maintainer and has twice turned one
|
||||
observation into a defect nobody else had found. This release carries
|
||||
what a good number of those reports and requests turned into. It is not
|
||||
all of them, and the ones still open are still open because they are
|
||||
waiting their turn, not because they were set aside.
|
||||
|
||||
@StefanIndustries sent this project its first money, ten euros, toward
|
||||
the yearly cost of keeping the iOS client on TestFlight without asking
|
||||
anyone to pay for it. The amount was never the point. Someone deciding
|
||||
this was worth something, and saying so, was not expected here.
|
||||
|
||||
More is welcome: an idea, a rough thought about how something ought to
|
||||
work, a screenshot of a number that looks wrong. Especially that last
|
||||
one.
|
||||
|
||||
## [1.33.2] — 2026-07-28
|
||||
|
||||
### The cycle-symptom fix in v1.33.1 did not work
|
||||
|
||||
+89
-24
@@ -1,7 +1,7 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: HealthLog API
|
||||
version: 1.33.2
|
||||
version: 1.34.0
|
||||
description: >-
|
||||
Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest.
|
||||
|
||||
@@ -7578,6 +7578,7 @@ paths:
|
||||
- STAIR_DESCENT_SPEED_BASELINE
|
||||
- SIX_MINUTE_WALK_BAND
|
||||
- TRAJECTORY
|
||||
- HEALTH_SCORE
|
||||
- SAME_TIME_BASELINE
|
||||
description: "Derived-metric id to compute (e.g. VITALS_BASELINE, FITNESS_AGE, VASCULAR_AGE_DELTA, HRV_BALANCE, BMI,
|
||||
READINESS). Closed enum: an unknown id 422s. Metrics whose compute has not yet landed return an
|
||||
@@ -27073,8 +27074,8 @@ components:
|
||||
properties:
|
||||
score:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
band:
|
||||
type: string
|
||||
enum:
|
||||
@@ -27085,15 +27086,78 @@ components:
|
||||
anyOf:
|
||||
- type: number
|
||||
- type: "null"
|
||||
confidence:
|
||||
$ref: "#/components/schemas/DerivedConfidence"
|
||||
composition:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- BLOOD_PRESSURE
|
||||
- GLYCAEMIA
|
||||
- ACTIVITY
|
||||
- SLEEP
|
||||
- ADIPOSITY
|
||||
- WELLBEING
|
||||
- FITNESS
|
||||
- LIPIDS
|
||||
deltaReason:
|
||||
anyOf:
|
||||
- type: string
|
||||
enum:
|
||||
- algorithm_changed
|
||||
- composition_changed
|
||||
- first_eligibility_window
|
||||
- below_noise_floor
|
||||
- no_previous_window
|
||||
- no_current_score
|
||||
- type: "null"
|
||||
scoreVersion:
|
||||
type: integer
|
||||
exclusiveMinimum: 0
|
||||
maximum: 9007199254740991
|
||||
bandSetter:
|
||||
anyOf:
|
||||
- type: string
|
||||
enum:
|
||||
- BLOOD_PRESSURE
|
||||
- GLYCAEMIA
|
||||
- ACTIVITY
|
||||
- SLEEP
|
||||
- ADIPOSITY
|
||||
- WELLBEING
|
||||
- FITNESS
|
||||
- LIPIDS
|
||||
- type: "null"
|
||||
restMode:
|
||||
anyOf:
|
||||
- type: object
|
||||
properties:
|
||||
active:
|
||||
type: boolean
|
||||
since:
|
||||
anyOf:
|
||||
- type: string
|
||||
- type: "null"
|
||||
episodeCount:
|
||||
type: integer
|
||||
minimum: -9007199254740991
|
||||
maximum: 9007199254740991
|
||||
required:
|
||||
- active
|
||||
- since
|
||||
- episodeCount
|
||||
additionalProperties: false
|
||||
- type: "null"
|
||||
required:
|
||||
- score
|
||||
- band
|
||||
- delta
|
||||
additionalProperties: false
|
||||
- type: "null"
|
||||
description: Personal health score summary (0..100 score, traffic-light band, week-over-week delta). Null on a
|
||||
rollup-coverage miss (it rides the thick phase alongside `extras`) and when no pillar is computable.
|
||||
Component breakdown is deliberately not serialised here.
|
||||
description: Derived cardiometabolic reference score summary. Null until at least three eligible domains include a
|
||||
measured physiological domain. Additive metadata names confidence, ordered composition, the worst-pillar
|
||||
band setter, score version, and why a delta was suppressed. Rest Mode annotates but never changes the score.
|
||||
scoreRings:
|
||||
description: "User-selected hero score rings (max 3, `selectedScoreRings` on the dashboard layout), resolved
|
||||
server-side: READINESS / RECOVERY_SCORE / SLEEP_SCORE via the derived engines (module-gated like
|
||||
@@ -27327,6 +27391,24 @@ components:
|
||||
≥36% instability flag; `advanced` is the disclosure tier — J-index (Wojcicki 1995) + LBGI/HBGI (Kovatchev
|
||||
hypo/hyper risk). All blocks are null when there are no readings; `advanced.jIndex` is null for a single-reading
|
||||
window.
|
||||
DerivedConfidence:
|
||||
type: object
|
||||
properties:
|
||||
score:
|
||||
type: number
|
||||
description: 0..100 confidence; feeds the shared coverage meter unchanged.
|
||||
band:
|
||||
type: string
|
||||
enum:
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
- draft
|
||||
description: Confidence band the meter renders.
|
||||
required:
|
||||
- score
|
||||
- band
|
||||
additionalProperties: false
|
||||
InsightsComprehensiveResponseEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
@@ -27987,6 +28069,7 @@ components:
|
||||
- STAIR_DESCENT_SPEED_BASELINE
|
||||
- SIX_MINUTE_WALK_BAND
|
||||
- TRAJECTORY
|
||||
- HEALTH_SCORE
|
||||
- SAME_TIME_BASELINE
|
||||
description: Echoes the requested derived-metric id (tags the union).
|
||||
status:
|
||||
@@ -28070,24 +28153,6 @@ components:
|
||||
- historyDays
|
||||
- missing
|
||||
additionalProperties: false
|
||||
DerivedConfidence:
|
||||
type: object
|
||||
properties:
|
||||
score:
|
||||
type: number
|
||||
description: 0..100 confidence; feeds the shared coverage meter unchanged.
|
||||
band:
|
||||
type: string
|
||||
enum:
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
- draft
|
||||
description: Confidence band the meter renders.
|
||||
required:
|
||||
- score
|
||||
- band
|
||||
additionalProperties: false
|
||||
DerivedProvenance:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "healthlog",
|
||||
"version": "1.33.2",
|
||||
"version": "1.34.0",
|
||||
"description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.",
|
||||
"license": "PolyForm-Noncommercial-1.0.0",
|
||||
"homepage": "https://healthlog.dev",
|
||||
|
||||
Reference in new issue
Block a user