Release v1.37.19 - #793
Merged
Merged
Conversation
- Singular variants for the bulk-delete toast and confirm dialog (measurements + mood); the call sites branch on a count of one. - Consent confirm buttons shortened so they no longer overflow the small button on phones. - Workouts empty-state CTA is source-neutral instead of assuming an iPhone with Apple Health. - "Pills" is no longer a navigation term in a medication app: DE says Navigations-Chips, EN chips, PL chipy; ES/FR/IT subtitles align with their own established terms. - Health-score insufficient hint drops the translationese and fixes the pronoun. - Side-effect tag helper uses the established Stimmungs-Tags term. - Success toasts that are single fragments lose the terminal period (37 keys, all locales). - Integration pill parked state short enough to survive truncation. - The iPhone-managed reminder badge carries a short label; the full sentence moved to a helper line below instead of clipping mid-word.
- Vorsorge dashboard tile title joins the dashboard heading ladder (titleAs=h2 like its sibling tiles). - A user's own note on the mobile measurement card renders in the foreground colour; user data is never muted. - The compact Vorsorge list row expresses its density on the Card instead of overriding the content slot's padding with an off-scale step. - The AI-consent card holds its space with a skeleton while the receipt loads instead of popping in and shifting the section below.
…e unread analytics columns - The daily Coach sweep now charges each ignored day against surfaceCount and auto-dismisses at three — the cap the schema comment promised since v1.22 but nothing enforced. - The welcome gate compares the stored disclaimer acknowledgment version against the current one, so revised disclaimer text re-prompts; /api/auth/me carries the version for the client. - slope90 and anomalyCount leave the analytics wire: slope90 had no reader anywhere (computed on every request, in SQL twice), and the slim path could never compute anomalyCount (it always reported 0). anomalyCount stays as an in-process field on summarize() for the insights feature builder, which is its only real consumer.
… dead settings slugs - The Coach verbosity picker is disabled while the concise tone forces brief, with a hint saying so, instead of a live control that silently does nothing. - A fresh document upload flashes its new row like the duplicate path always did; the settle decision is a pure exported helper with a test. - /about gains its two inbound links: the /privacy footer and a Settings→About credits row (the GeoLite2 EULA wants the attribution reachable from the running app). - The eight settings slugs shadowed by permanent redirects (the seven layout children + sharing) leave the slug registry: no more prerendering unreachable pages, no dead component wirings, and the SectionPlaceholder fallback that could never render is gone. The redirects, section components, and layout-hub subpages are unchanged.
…he medication wire A medication whose slots carry different doses (a whole tablet in the morning, a half at noon — #219) was consumed correctly but reported wrongly: the wire shipped only the raw nullable per-slot column (clients had to derive the inheritance), stockDosesRemaining divided by the medication-level units alone, and no runway figure existed outside the low-stock push. - Every schedule now carries resolvedUnitsPerDose, resolved server-side exactly like the intake consumption resolver. - stockDosesRemaining divides the units pool by the schedule-weighted average units per dose. - runwayDays (whole days of supply under the slot-aware burn rate) rides the list AND detail payloads; the detail GET also gains the stock aggregates the list already had. - The low-stock engine runs the same slot-aware math, so the push and the wire cannot disagree; the web cards, table, and detail Übersicht prefer the server figure over their client estimate. - OpenAPI regenerated with the new fields.
… DTO
- MedicationIntakeEvent declares the full row both intake responses
actually return: autoMissed, attributionSource, injectionSite,
doseTaken, inventoryConsumption, externalId, updatedAt, syncVersion,
deletedAt were served but undeclared.
- GET /api/medications/{id}/intake is published (query schema, paged
envelope); the spec only knew the POST while the client-facing
history list has consumed the GET since v1.4.37.
- WorkoutListEntry's sportType/startedAt/endedAt/durationSec become
nullable, matching the DTO — declaring them non-null was a
strict-decoder bomb for the Swift client.
- OpenAPI regenerated.
- The provider-chain walker now checks the day's recorded spend against OPERATOR_COST_CAP before invoking an operator-funded admin-* entry. A request whose primary provider runs on the user's own key reserves under the generous user-plan ceiling; a fallback hop (or health-ledger reorder) onto the operator's key could then spend past the operator's cap unchecked. An exhausted cap skips the candidate like a failed hop. - summaryState PENDING gets a giver-upper: the detail serialiser degrades a PENDING older than an hour to UNAVAILABLE (which offers the manual generate action), and an hourly reaper persists the same heal following the orphan-ImportJob reconcile precedent — a job dead past its retry budget no longer leaves the sheet saying "generating" forever.
The six measurement routes carried eight copy-pasted rollup-recompute + status-invalidate blocks — the documented two-ended failure class waiting for the next surface to remember one leg and forget the other. All of them now call afterMeasurementMutation (the helper the deletion fix introduced), and the two write surfaces that bypassed the hook entirely join it: the nightly Recovery/Stress/Strain score rows and the PHQ-9/GAD-7 assessment projection now recompute their (type, day) bucket on the tick that writes them.
…vault probes - The measurement-reminder tick claims its slot in the record-event ledger BEFORE any provider egress (the documented claim-first pattern from reminder-dedup.ts); a crash between dispatch and the nextDueAt advance can no longer double-send. - mood-entries/bulk classifies a lost P2002 race as the duplicate it is (with the winning row id) instead of a skip carrying a raw Prisma message — the row IS stored, the racing twin wrote it. The workouts batch already re-derives per-entry status from RETURNING. - The vault list's content-index and thumbnail probes ride the same Promise.all as the link loads: four independent grouped queries, no serialized round-trips on a 4s-polled list.
…d on zone change - The restore summary counts practitioners, encounters, the three link tables, and vaccinations — restored in full since 08-01 but absent from the report, so a file carrying visits or an Impfpass read as if those sections were empty. - A portable export that cannot open a field's ciphertext still nulls it fail-soft, but now names the loss in the file's own decryptFailures manifest — an export with a lost emergency note is no longer byte-identical to one where the note was never written. - A timezone change enqueues the medication-compliance re-fold: the rollup keys its rows by the local day minted under the OLD zone, and the coverage probe compares counts, not keys, so nothing else could notice the stale bucketing.
- account-sharing polls the offline persister's own IndexedDB store for the flushed snapshot instead of sleeping past the debounce. - The record-session-fence cases poll for the observable halves of their setups (the switch round-trip landing, the exit switch being issued); the one remaining fixed window is a documented absence-assertion grace with nothing to poll on. - The documents suite's two remaining sleeps are named for what they are: a focus-dance grace the outer document cannot observe, and the long-press gesture duration itself. - The inventory-date fixtures derive their printed expiry from now instead of a fixed 2027 date that would silently flip the fixture to expired when the calendar catches up.
…l-time stats - The tiered AI context's band reader now falls back to a live grouped aggregate when a rollup band is empty (the module doc promised replace-with-fallback from day one; only the replace half existed), so a coverage-miss or never-folded YEAR partition no longer hands the model empty history. Far-from-UTC users get the day-grain band keyed on their own calendar (the same ±3h guard the correlation readers carry). - The slim analytics slice splices measurements older than the 5-year fold window into its all-time count/min/max/mean: the rollup tier only covers the window, so "all time" silently truncated for long histories while the live fallback told the truth. A type whose only rows are pre-fold no longer reads as never logged.
- The record-settings contract, slug-list, and section-frame tests follow the slugs that left the registry (layout children resolve their headings from the layout namespace, like production). - The orphaned settings.sections.<module>.title/description keys leave all six locales; the reverse-coverage guard flagged them the moment their nav entries stopped existing. - The operator-cap ledger read fails open on a read error — the reservation layer still meters against the same ledger, and a transient blip must not take the fallback chain down. - The reaper queue joins the subsystem surface; its healed count and the sweep's nag_dismissed join the job-fact vocabulary. - The intake-event contract fixture carries the full row the resource now declares; the workouts empty-state test asserts the source-neutral cue; the persister poll gates on rendered content first.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second wave of the systematic QA pass: the P2 package.
Headline: medication stock understands per-slot doses end to end. The remaining-doses figure weighs each slot by its resolved dose, the API carries resolvedUnitsPerDose per schedule plus runwayDays on list and detail, and the low-stock engine runs on the same arithmetic so push and wire cannot disagree.
Also in this wave: the operator budget cap applies when the provider chain falls back onto an operator key; a document whose summary job died heals to an honest unavailable state after an hour, backed by an hourly sweep; the coach reminder sweep caps nagging at three mornings; disclaimer acknowledgement is versioned; restore reports written counts for every section including practitioners, appointments and vaccinations; the portable export names decrypt failures; timezone changes re-fold the compliance statistics; the all-time summary includes readings older than five years and the AI context falls back to live data on missing bands; measurement reminders claim their notification slot before sending; the intake-event and workout list API descriptions match the real wire; copy and layout polish across all six languages; the six measurement routes share one post-write helper; residual fixed sleeps in the e2e suite poll on real conditions and the expiry fixtures no longer age.
Every behaviour fix carries a recorded watched-red test. No migrations. OpenAPI changes are additive.
Battery: typecheck, lint, unit (21367 passed), format:check, integration (202 files, 1845 passed), production build all green in the working tree.