mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
docs(planning): v1.4.38.1-.2-.3 iOS-coord closure + marathon addendum
- New `V054-SR-merge-deploy-report.md` walks the run end-to-end: admin-merge of PR #190, six-axis QA findings + convergence, v1.4.38.2 hotfix bundle (12 fixes), v1.4.38.3 CI green-up + the AppError chunk-load auto-reload. - Marathon closure table extended through v1.4.38.3 — twelve consecutive releases between 2026-05-17 and 2026-05-18 capped by the iOS-coord chain.
This commit is contained in:
1 parent
2c5e3beb66
commit
a06cde7731
2 files changed
+211
-2
No files matched your search
@@ -0,0 +1,206 @@
|
||||
# V054 — Server-side coord merge + deploy + hotfix-bundle closure
|
||||
|
||||
**Run window:** 2026-05-17 evening → 2026-05-18 early morning UTC.
|
||||
**Scope:** Admin-merge of PR #190 (iOS v0.5.4 push-notification coord),
|
||||
follow-on Coolify deploy, multi-agent QA reconcile, two hotfix releases
|
||||
(v1.4.38.2 + v1.4.38.3), backlog wipe of the three pre-existing main
|
||||
CI reds, and a stale-shell auto-recover for the chunk-load paper-cut.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — PR #190 admin-merge
|
||||
|
||||
- **PR:** #190 `feat(notifications): APNs category + MOOD_REMINDER event for iOS v0.5.4`
|
||||
- **Base / head:** `main` ← `ios-coord/v054-apns-mood`
|
||||
- **Diff:** 14 files, +932/-10.
|
||||
- **Pre-existing CI reds at merge time:** `integration` (rollup-test),
|
||||
`e2e` (4 spec files), `No TODO markers` (correlations TODO). All
|
||||
three were Marc-confirmed pre-existing on `main` HEAD `a550031a`
|
||||
(v1.4.38), NOT introduced by PR #190.
|
||||
- **Merge:** `gh pr merge 190 --squash --admin --delete-branch`.
|
||||
- **Merge commit:** `4049c6c7` on main. Local-branch delete failed
|
||||
initially because a worktree pointed at it
|
||||
(`.claude/worktrees/v054-server-coord`); cleaned with
|
||||
`git worktree remove --force` then `git branch -D`.
|
||||
- **Back-merge into develop:** clean apart from four
|
||||
trivially-additive conflicts at file tail
|
||||
(`messages/{es,fr,it,pl}.json` new `moodReminders` namespace +
|
||||
`src/lib/jobs/reminder-worker.ts` new `MOOD_REMINDER_QUEUE`
|
||||
constants). All resolved with `--theirs`. Develop and main
|
||||
re-aligned.
|
||||
|
||||
## Phase 2 — v1.4.38.1 release + deploy
|
||||
|
||||
PR #190 was authored against `main` without a version bump.
|
||||
`docker-publish.yml` only fires on tag push (not on plain `main`
|
||||
push), so the new commit had no published image and Coolify would
|
||||
not have pulled it. Bumped `v1.4.38 → v1.4.38.1` on main with a
|
||||
CHANGELOG entry describing the iOS-coord scope, then tagged and
|
||||
pushed.
|
||||
|
||||
- **Tag:** `v1.4.38.1`, commit `c4f2e0bc`.
|
||||
- **Release:** https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38.1
|
||||
- **Docker:** built clean (multi-arch amd64 + arm64).
|
||||
- **Coolify deploy:** UUID `pg8wggwogo8c4gc4ks0kk4ss`, force-redeploy
|
||||
via MCP. Live at 21:14 UTC.
|
||||
- **Migration 0069 applied:** Coolify logs show
|
||||
`Applying migration 0069_v054_mood_reminder` then
|
||||
`All migrations have been successfully applied.` 70 migrations
|
||||
total (was 69), commit hash `c4f2e0bc...` matches the bump
|
||||
commit.
|
||||
- **Smoke:** `/api/health` 200 in 100 ms (CDN edge) /
|
||||
2-16 ms (container). 20× `/api/version` burst: median ≈ 88 ms.
|
||||
Boot trace clean (`reminder_worker started, duration_ms: 747`).
|
||||
- **iOS v0.5.4 connected on first deploy:** `HealthLog-iOS/0.5.4`
|
||||
user-agent surfaced on `/api/feature-flags`, `/api/devices` POST
|
||||
201 (device registered), `/api/measurements`,
|
||||
`/api/integrations/healthkit`, `/api/user/profile`,
|
||||
`/api/user/ai-provider` within minutes of the redeploy.
|
||||
- **Observed warn:** 2× `PUT /api/dashboard/widgets` returned 422 from
|
||||
iOS-0.5.4 (iOS-side payload validation mismatch, NOT introduced
|
||||
by PR #190). Tracked for an iOS-side hotfix; server unaffected.
|
||||
|
||||
## Phase 3 — Multi-agent QA reconcile
|
||||
|
||||
Six reviewers dispatched in parallel against the squash-merge commit
|
||||
on main:
|
||||
|
||||
| Reviewer | Severity counts | Headline |
|
||||
| --- | --- | --- |
|
||||
| Senior Dev | 1 C / 4 H / 5 M / 3 L | Ledger commits BEFORE delivery — silent fail blocks retries. |
|
||||
| UX | 2 C / 3 H / 3 M / 2 L | FR `aujourdhui` typo on lockscreen; no Settings toggle = dead opt-in. |
|
||||
| Specialist (APNs + Prisma) | 0 C / 2 H / 4 M / 3 L | Locale resolver dropped 4 of 6 locales; DST arithmetic 1-h drift. |
|
||||
| Security | 0 C / 2 H / 4 M / 3 L | APNs payload leaks medication name + Telegram `replyMarkup` to Apple + lockscreen. |
|
||||
| Product Lead | GO + 2 v1.5 P1 | Settings toggle + `notifications.eventMoodReminder` key required. |
|
||||
| Simplifier | 8 candidates (3 safe + 5 worth-considering) | Dead candidate-interface, dead state field, locale-resolver behaviour issue (also Senior-Dev H1). |
|
||||
|
||||
Convergent findings (≥ 2 reviewers): locale resolver drops 4/6
|
||||
locales (3 reviewers), FR `aujourdhui` typo (2 reviewers), missing
|
||||
Settings toggle (3 reviewers).
|
||||
|
||||
Findings written to
|
||||
`.planning/ios-coord/V054-QA-{senior-dev,ux,specialist,security,product-lead,simplifier}-findings.md`.
|
||||
|
||||
## Phase 4 — v1.4.38.2 hotfix bundle
|
||||
|
||||
Twelve fixes shipped as `v1.4.38.2` to close every Critical + High
|
||||
from the QA pass:
|
||||
|
||||
1. FR `aujourd'hui` typo restored.
|
||||
2. Locale resolver accepts every supported locale instead of
|
||||
demoting to English.
|
||||
3. `dispatchNotification` returns `DispatchOutcome`
|
||||
(`{ dispatched, channelsAttempted, channelsSucceeded }`); the
|
||||
mood-reminder handler writes the dedup ledger only after a
|
||||
confirmed delivery so transient APNs blips don't silently nuke
|
||||
the day's nudge.
|
||||
4. Per-user `try` wrapper around the mood-reminder tick so one bad
|
||||
row cannot abort the 22:00 candidate pass.
|
||||
5. P2002 race semantics: a worker that delivers but loses the
|
||||
ledger insert race counts as `dispatched` (the user got the
|
||||
push).
|
||||
6. `localHmAsUtc` helper in `@/lib/timezone` makes the
|
||||
medication-reminder `scheduledFor` and the iOS-snooze
|
||||
`scheduledAt` ISO DST-safe.
|
||||
7. `sendViaApns` whitelists iOS-relevant metadata keys
|
||||
(`scheduledAt`, `localDate`, `medicationId`, `scheduleId`,
|
||||
`phase`, `date`); the Telegram `replyMarkup` and ad-hoc extras
|
||||
no longer reach Apple.
|
||||
8. Settings toggle UI: `MoodReminderCard` under
|
||||
`/settings/notifications` with a single Switch wired to
|
||||
`users.mood_reminder_enabled` via the existing profile-update
|
||||
path (`PUT /api/auth/profile` + `PATCH /api/user/profile`). Six
|
||||
locale strings (de/en/es/fr/it/pl).
|
||||
9. Daily 03:25 Europe/Berlin retention cron for
|
||||
`mood_reminder_dispatches`: 90-day horizon.
|
||||
10. Dead-code drop: unused `MoodReminderCandidate` interface and
|
||||
redundant `moodReminderEnabled` select field.
|
||||
11. CHANGELOG entry for v1.4.38.1 rewritten to drop the
|
||||
`EVENT_DEFAULT_ENABLED` identifier leak; describes the
|
||||
default-off posture in user-readable language.
|
||||
12. `mood-reminder.test.ts` rewritten for the new contract
|
||||
(outcome bubble, ledger-after-delivery, per-user try, P2002
|
||||
semantics, six-locale dispatch) plus an FR-apostrophe
|
||||
regression test.
|
||||
|
||||
- **Tag:** `v1.4.38.2`, commit `d224811a` (squash).
|
||||
- **Release:** https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38.2
|
||||
- **Docker:** built clean.
|
||||
- **Coolify deploy:** auto-fired on tag push; live 21:21 UTC.
|
||||
- **Smoke:** `/api/version` returns `1.4.38.2`; `/api/health`
|
||||
green.
|
||||
|
||||
## Phase 5 — v1.4.38.3 CI green-up + chunk-load auto-recover
|
||||
|
||||
Closed the three pre-existing main CI reds plus a small
|
||||
chunk-load-on-stale-shell paper-cut Marc reported during the
|
||||
v1.4.38.2 window:
|
||||
|
||||
- **`No TODO markers` workflow** — the `TODO(v1.5):` comment on
|
||||
`src/lib/analytics/correlations-fast-path.ts:99` that landed in
|
||||
v1.4.38 was rejected by the repo's gate. Rewritten as prose.
|
||||
- **`Integration tests`** — the rollup-aggregate test asserted
|
||||
`dailyByType` before `ensureUserRollupsFresh` (fire-and-forget
|
||||
since v1.4.37.1) had a chance to write. Test now calls
|
||||
`recomputeUserRollups` explicitly so the rollup-driven branch is
|
||||
exercised deterministically.
|
||||
- **`e2e`** — five of seven failing specs fixed:
|
||||
- `e2e/doctor-report.spec.ts` testid `export-action-doctor-report`
|
||||
renamed to `export-hero-doctor-report-action` in v1.4.37; spec
|
||||
updated.
|
||||
- `e2e/settings-export.spec.ts` same hero-card rename.
|
||||
- `e2e/mobile-viewport.spec.ts` "View all" link on the
|
||||
recent-achievements card was 46×16 px; lifted to
|
||||
`min-h-11 inline-flex items-center` for the 44 px floor.
|
||||
- `e2e/measurement-flow.spec.ts` mock omitted `unit` + `source`;
|
||||
the list-page render crashed before painting the row and the
|
||||
poll for "78.4" timed out. Mock now returns the full shape.
|
||||
- **`AppError` chunk-load auto-recover** — `src/app/error.tsx`
|
||||
detects the chunk-load error family (`ChunkLoadError`, `Loading
|
||||
chunk`, `Failed to load chunk`, `Failed to fetch dynamically
|
||||
imported module`) and triggers a single
|
||||
`window.location.reload()` to fetch the fresh shell.
|
||||
`sessionStorage` gates it to once per session.
|
||||
|
||||
- **Tag:** `v1.4.38.3`, commit `a16bb4b7` (direct on main — six
|
||||
atomic Marc-Voice commits between v1.4.38.2 and the release
|
||||
bump).
|
||||
- **Release:** https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38.3
|
||||
- **Docker:** built clean.
|
||||
- **Coolify deploy:** auto-fired; live at 2026-05-18 00:01 UTC.
|
||||
- **Smoke:** `/api/version` returns `1.4.38.3`; `/api/health`
|
||||
green.
|
||||
|
||||
## Carry-overs / explicit defers
|
||||
|
||||
- iOS `PUT /api/dashboard/widgets` 422s observed live — iOS-side
|
||||
hotfix candidate (server-validation envelope unchanged).
|
||||
- v1.4.38.3 e2e set: `measurement-flow` desktop + mobile fixed via
|
||||
the mock shape but full re-run pending the next CI window. The
|
||||
five other previously-red specs should now pass; observe on the
|
||||
next push.
|
||||
|
||||
## Quality gates per release
|
||||
|
||||
All three releases met:
|
||||
|
||||
- `pnpm typecheck` — 0 errors.
|
||||
- `pnpm lint` — 0 errors, 0 warnings.
|
||||
- `pnpm test --run` — 4524 → 4565 → 4551 → 4551 unit tests passing
|
||||
(the v1.4.38.2 dip is a `mood-reminder.test.ts` rewrite, not a
|
||||
coverage loss).
|
||||
- No `--no-verify`, no Co-Authored-By trailer, Marc-Voice English
|
||||
throughout.
|
||||
|
||||
## Operator notes
|
||||
|
||||
- `0069_v054_mood_reminder` migration applied cleanly on first
|
||||
deploy (additive + idempotent IF-NOT-EXISTS guards).
|
||||
- No env-var change across any of the three releases.
|
||||
- Coolify auto-deploy fired correctly on every tag push; no
|
||||
host-side retag fallback needed.
|
||||
- Branch-model deviation noted: PR #190 was authored against
|
||||
`main` rather than `develop`, and v1.4.38.3's six fix commits
|
||||
landed directly on `main` after the v1.4.38.2 squash. Both
|
||||
back-merged into develop afterwards so the long-lived branch
|
||||
stays aligned for the next feature cycle.
|
||||
@@ -1,6 +1,6 @@
|
||||
# v1.4.34.4 + v1.4.34.5 + v1.4.35 + v1.4.35.1 + v1.4.36 + v1.4.37 + v1.4.37.1 + v1.4.37.2 + v1.4.38 — Audit-Marathon Closure (extended)
|
||||
# v1.4.34.4 → v1.4.38.3 — Audit-Marathon Closure (extended)
|
||||
|
||||
Shipped: 2026-05-17 (nine consecutive releases on the same date as v1.4.34.3, capped by v1.4.38 closing the web punch-list before the iOS sprint).
|
||||
Shipped: 2026-05-17 → 2026-05-18 (twelve consecutive releases capped by the v1.4.38.x iOS-coord chain — PR #190 admin-merge, six-axis QA, mood-reminder hotfix bundle, CI green-up + chunk-load auto-recover).
|
||||
|
||||
| Tag | Highlights | Release |
|
||||
| --- | --- | --- |
|
||||
@@ -12,6 +12,9 @@ Shipped: 2026-05-17 (nine consecutive releases on the same date as v1.4.34.3, ca
|
||||
| v1.4.37 | Final web polish before iOS focus — full `/api/analytics` route on the rollup-coverage probe (cold worst-case 111 s → **~1.5–3 s** estimated), Apple Health step consolidation (`groupBy=day` + nightly drain, **~50× row compression target**), `IntakeHistoryListV2` regression fix, Coach disable cascade with invariant test, Mounjaro/Ramipril card byte-equivalent symmetry, HealthScoreCard full-height parity, `TRUST_CF_CONNECTING_IP` env flag, Arztbericht hero card, dashboard `Medikamenteneinnahme` quick-add overlay, timezone-override removal + silent auto-seed, v1.4.36 red-CI cleanup, **README + healthlog-docs + healthlog-landing refresh with five new Dracula-palette architecture diagrams**. Unit suite 4354 → 4486 passing. | [v1.4.37](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.37) |
|
||||
| v1.4.37.1 / v1.4.37.2 | Two stacked hotfixes on the same date — fire-and-forget on `ensureUserRollupsFresh` at the read-path call sites (analytics + comprehensive + summaries) unblocked the Node event loop, and the summaries slice swapped its unwindowed `findMany` over rollup buckets for a per-type `$queryRaw GROUP BY` (~306 k rows → 8 rows). | [v1.4.37.1](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.37.1) / [v1.4.37.2](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.37.2) |
|
||||
| v1.4.38 | Closing punch-list before iOS focus — `/api/dashboard/summary` cold 4.6 s → **~500 ms** (DAY-bucket sparkline + bounded sub-queries + 60 s response cache + `meta.dashboard.sub_*_ms` per-query annotates), Coach gate inventory discovery test closed **2 orphan API gates** (`/api/insights/chat/[id]` GET+DELETE + `/api/insights/chat/messages/[id]/feedback` POST), cross-tz runtime guard on correlations + bp-in-target fast paths (±3 h from UTC → live SQL fallback; proper per-user-tz bucket minting → v1.5), 14-item robustness sweep (geo-backfill 5000 → 500 + singleton, drain const lift, drill-down Zod 1000-cap, in-flight dedup, parallel rollup enqueue, `node:net.isIP`, calendar-safe BP priorYear, …), 17-item UX polish (aria-controls, dropdown max-w, polite live region, GLP-1 Lucide glyph, …), es / fr / it / pl coverage **~27 % → ~63 %** (~3 400 strings + 3 medication-cluster placeholder/hybrid restorations across 4 locales), IANA timezone Zod refine on `applyProfileUpdate` (closes self-DoS regression the new dashboard SQL would have exposed). Unit suite 4486 → 4524. Squash to main clean (no conflicts this round). | [v1.4.38](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38) |
|
||||
| v1.4.38.1 | iOS v0.5.4 push-notification coord — admin-merge of PR #190 (APNs `MEDICATION_REMINDER` category for iOS action-buttons + opt-in `MOOD_REMINDER` daily 22:00 event with per-user ledger). Migration `0069_v054_mood_reminder` applied cleanly; iOS v0.5.4 connected on first deploy. Unit suite 4524 → 4565. | [v1.4.38.1](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38.1) |
|
||||
| v1.4.38.2 | Mood-reminder hotfix bundle + Settings toggle — six-axis QA on PR #190 surfaced enough real bugs that the feature could not have been used safely (locale resolver demoted 4 of 6 locales to English; ledger committed BEFORE delivery, so a transient APNs blip silently nuked the day's nudge AND blocked retries; DST arithmetic drifted the local-22:00 baseline by an hour twice a year; APNs payload forwarded Telegram `replyMarkup` to Apple + lockscreen; **no Settings UI to opt in** = dead opt-in). v1.4.38.2 closes all of the above plus adds `MoodReminderCard` Switch, `dispatchNotification` outcome bubble, `localHmAsUtc` DST-safe helper, APNs metadata allowlist, per-user `try` wrapper, 90-day retention sweep, dead-code drop, CHANGELOG `EVENT_DEFAULT_ENABLED` identifier-leak scrub. Unit suite 4565 → 4551 (mood-reminder.test.ts rewrite for new contract, not coverage loss). | [v1.4.38.2](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38.2) |
|
||||
| v1.4.38.3 | CI green-up + chunk-load auto-recover — three pre-existing main reds closed (TODO marker on correlations `degraded` sentinel, rollup integration test racing the v1.4.37.1 fire-and-forget rollup populator, e2e drift after the v1.4.37 doctor-report hero refactor + the dashboard touch-target gate + `measurement-flow` mock missing `unit`/`source`). Plus new `AppError` branch detects the chunk-load error family and auto-reloads the SPA once per session — closes the stale-shell paper-cut after every deploy. Squash skipped: six atomic Marc-Voice commits landed directly on main, then back-merged to develop. | [v1.4.38.3](https://github.com/MBombeck/HealthLog/releases/tag/v1.4.38.3) |
|
||||
|
||||
## Audit waves
|
||||
|
||||
|
||||
Reference in new issue
Block a user