From 0f5369131ecb544cbc9d323af55a24fcc78c9273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 15 May 2026 16:18:57 +0200 Subject: [PATCH] docs(planning): v1.4.27 session handoff with R2 actuals and scope-maximization directive --- .planning/v1427-handoff-session-2.md | 146 +++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 .planning/v1427-handoff-session-2.md diff --git a/.planning/v1427-handoff-session-2.md b/.planning/v1427-handoff-session-2.md new file mode 100644 index 000000000..a3d0c7af0 --- /dev/null +++ b/.planning/v1427-handoff-session-2.md @@ -0,0 +1,146 @@ +--- +file: .planning/v1427-handoff-session-2.md +purpose: Continuation handoff after Session 1 of v1.4.27 work — context at ~72% so a fresh session picks up at Round 2 complete +created: 2026-05-15 +target_tag: v1.4.27 +--- + +# v1.4.27 Handoff — Session 1 → Session 2 + +## TL;DR — where this is + +- Branch: `develop` synced with origin at `e0d6bba3` (R2 consolidator's commit) +- Round 1 — all 6 audit + research contributors complete; six docs committed under `.planning/research/v1427-r1-*.md` +- Round 2 — DONE. Fix-plan committed at `e0d6bba3` to `.planning/v1427-fix-plan.md`. Seven buckets (B1-B7) defined. +- Rounds 3-5 — pending. The fix-plan + this handoff are the source of truth. + +## R2 actual output (verified) + +| Bucket | Focus | Round 3 slot | +|---|---|---| +| **B1 Dashboard** | Findings 1-8 — GLP-1 secondary tile, Health Score widen, briefing prose strip, KI-card removal, weekly-report wire-or-30-min-scan-then-defer, trend-row equal height | R3a parallel | +| **B2 Settings/Shell** | Findings 9-13 — profile rhythm, language placement, viewport stability | R3a parallel | +| **B3 Geo + ASN** | Findings 22-23 — MaxMind GeoLite2-City + GeoLite2-ASN offline bundling, `AuditLog.asn` + `AuditLog.carrier` additive columns, login-overview carrier chip | R3a parallel | +| **B4 Coach + Insights** | Findings 14-19 — Coach blue-prose hide + textarea-hint icon, `metric:PULSE` two-layer strip, `hasMetricData()` helper driving sub-page + nav + tile gating | R3a parallel | +| **B5 Notifications** | Findings 20-21 — `parkIntegrationAtReauth()` helper bypassing counter ladder; `dispatchLocalisedNotification()` wrapper | R3a parallel | +| **B6 i18n sweep** | Single consolidator that accepts i18n diffs from B1-B5 and commits one consolidated `messages/*.json` edit across 6 locales. Avoids merge churn. | R3b after B1-B5 | +| **B7 Symmetry + dead-code** | Finding 13 generic symmetry sweep (runs LAST so visual snapshots re-baseline after B1-B5 land) + the dead-code deletions from R1.6 backlog sweep (orphan endpoints incl. `/api/audit-log` DELETE per R2 default-decision, dead i18n keys, dead constants) | R3b after B1-B5 | + +## Scope-maximization directive (maintainer, late Session 1) + +After R2 finished, the maintainer added: +- **"Pack everything in we can. Don't fragment into more releases unless we have to."** → re-evaluate the 20 v1.4.28-deferrals during R3 dispatch. Items that can ship safely without scope-breaking should be pulled forward. Likely candidates: small simplifier items, dead-i18n cleanup, dead-constants cleanup, audit-log decision. Park only the truly scope-risky / multi-day items (onboarding rebuild, native FR/ES/IT/PL prompts, lazy locale bundles, per-night sleep chart). +- **"Lots of research and lots of UI-conformity passes. No duplicates. Everything looks the same. Everything is conform."** → R4 QA emphasis shifts: design + simplifier reviewers get expanded rubric covering visual consistency (component reuse, design-token usage, spacing rhythm, typography scale, button position/size symmetry, card chrome consistency, dark-mode parity). Add a NINTH reviewer in R4: a dedicated "UI-conformity sweep" agent that compares every same-class surface (e.g. every tile, every dialog, every form section, every settings sub-page) for visual + structural alignment. + +## Read these first (in order) + +1. `.planning/v1427-plan.md` — master plan with 27 maintainer findings + 5-round structure +2. `.planning/v1427-fix-plan.md` — R2 consolidator output (or read `.planning/research/v1427-r1-*.md` if R2 not finished yet) +3. `.planning/research/v1427-r1-dashboard.md` — R1.1 findings 1-8 + GLP-1 secondary-tile spec +4. `.planning/research/v1427-r1-settings-admin.md` — R1.2 findings 9-13 + 22-23 (profile rhythm + MaxMind GeoLite2 bundling for carrier) +5. `.planning/research/v1427-r1-coach-insights.md` — R1.3 findings 14-19 (`metric:PULSE` leak root cause at `InsightStatusCard:97`; `hasMetricData()` helper) +6. `.planning/research/v1427-r1-notifications.md` — R1.4 findings 20-21 (false Withings alert via `recordSyncFailure`-counter-bump; locale-aware Telegram via `dispatchLocalisedNotification`) +7. `.planning/research/v1427-r1-ios-offline.md` — R1.5 findings 24-26 (standalone-then-pair pattern; server-side preps deferred to v1.4.28) +8. `.planning/research/v1427-r1-backlog-sweep.md` — R1.6 (17 pulled / 20 deferred / 11 resolved) + +## Convention overrides — read carefully + +The maintainer issued a stricter convention for v1.4.27 onwards: + +- **NO "AI / Claude / agent / marathon / wave / phase / session / subagent" anywhere** — not just user-facing artifacts, but planning docs too. Use neutral alternatives: "round", "pass", "contributor", "slot", "automation", "release work". +- **NO PII** (maintainer's name, health figures, target ranges) in any artifact — commits, CHANGELOG, releases, planning, docs, marketing. +- **NO references to cloud development** anywhere (this stricter than prior). +- Marc-Voice English everywhere. +- Branch model: commit to `develop`, release via PR `develop → main`, tag on main, GitHub Release. + +## Framing note from the maintainer (Session 1 mid-flight) + +Findings 24-26 (iOS standalone usage) should NOT be framed as "offline-first architecture." Use neutral language: "works without an internet connection," "can be operated without a server," "standalone usage option," "no-server mode." R2 was messaged to apply this in the fix-plan; double-check. + +## Round 3 dispatch plan + +R2 produces the canonical fix-surface buckets. Likely shape (verify against R2's actual output): + +| Bucket | Focus | Touch surface | +|---|---|---| +| **R3.1 Dashboard** | Findings 1-8 — GLP-1 secondary tile (drug-level via tab strip in `` + `compact` prop on ``), Health Score widen, Daily Briefing prose strip, KI-card removal, weekly-report wire-or-remove, trend-row equal height | `src/components/dashboard/`, `src/components/insights/`, `src/components/medications/DrugLevelChart.tsx`, `src/components/charts/` | +| **R3.2 Settings + Admin** | Findings 9-13 — profile-form `sm:grid-cols-2` rhythm, language-next-to-date, viewport stability + finding 22-23 — MaxMind GeoLite2-City + GeoLite2-ASN bundling, new `asn` + `carrier` columns on `AuditLog`, login-overview carrier chip | `src/app/settings/`, `src/components/settings/`, `src/lib/geo.ts`, `src/components/admin/login-overview-section.tsx`, `prisma/schema.prisma` (additive only) | +| **R3.3 Coach + Insights** | Findings 14-19 — Coach helper-chip prose-hide, Coach textarea hint icon, `metric:PULSE` leak two-layer fix (`stripChartTokens` wrap + producer normalize), `hasMetricData()` helper + nav/tile/sub-page gating | `src/components/coach/`, `src/components/insights/insight-status-card.tsx`, `src/lib/insights/*-status.ts`, `src/lib/insights/metric-availability.ts` (new), `src/app/insights/` | +| **R3.4 Notifications** | Findings 20-21 — `parkIntegrationAtReauth()` helper bypassing counter ladder; `dispatchLocalisedNotification({userId, titleKey, messageKey, params})` wrapper + 6-locale keys | `src/lib/integrations/`, `src/lib/notifications/`, `src/lib/withings/sync-activity.ts` + `sync-sleep.ts`, `messages/{de,en,fr,es,it,pl}.json` | +| **R3.5 iOS doc-pack addendum** | Add `.planning/v15-ios-handoff/22-standalone-and-server-pairing.md` (filename per maintainer framing — NOT "offline-first-architecture"). Summarises R1.5's research for the iOS-side reader. NO server-side code changes here. | `.planning/v15-ios-handoff/22-standalone-and-server-pairing.md` (new) | +| **R3.6 Backlog pull-ins** | The 17 items R1.6 pulled forward — most dirt-cheap cleanups and bundling with the QoS findings | Various — likely paired with R3.1-R3.4 buckets so each fix-contributor handles their bundle | + +R3.6's items should be REASSIGNED into R3.1-R3.5 if R2 hasn't already done that. Don't dispatch R3.6 as its own bucket — pair items with the bucket that already touches the same files. + +## Round 3 sequencing notes + +- R3.1, R3.2, R3.3, R3.4 are likely touch-disjoint enough to run in parallel. +- R3.5 is doc-only — fully parallelisable anywhere. +- R3.2's `prisma/schema.prisma` additive change (asn + carrier columns) needs a migration. If another bucket also wants schema changes, sequence them. +- The "i18n key inserts across 6 locales" surface is shared by R3.3 (Coach + Insights), R3.4 (Notifications), and possibly R3.2 (Settings labels). **Recommend a single `messages/*.json` editor at the END of Round 3** that accepts the i18n diffs from each fix-contributor and commits one consolidated i18n commit — avoids merge churn in the JSON files. + +## Open uncertainties (decide in Session 2) + +1. **`/api/audit-log` (P4-6) wire-vs-delete** — R1.6 flagged as needs-maintainer-input. R2 was instructed to default-decide DELETE. **Verify R2's decision in the fix-plan and proceed accordingly.** If R2 deferred, default-decide DELETE. +2. **Finding 7 (weekly report dead click)** — R1.1 surveyed and found `src/app/insights/report/[week]/page.tsx` exists. Default decision: WIRE the click. The page exists; the affordance just isn't routed. R3.1 implements. + +## Round 4 — QA pass + +Same pattern as v1.4.25's W21: +- 8 parallel reviewers writing to `.planning/research/v1427-r4-*.md` +- Categories: code-review (full diff since v1.4.26), security, design (responsive + a11y + contrast), senior-dev (architectural correctness + migration safety), simplifier (dead code + duplications), product-lead (strategic alignment), i18n-runtime (live route probe), dead-code-scan +- Reconcile pass: apply every Medium+/High+/Critical in parallel touch-disjoint fix-contributors +- Same severity rubric + +## Round 5 — Release v1.4.27 + +1. Editorial pass: extract from CHANGELOG.md the v1.4.27 section (write fresh at top, Marc-Voice English, no convention violations) +2. Version bump: `package.json` 1.4.26 → 1.4.27 +3. Commit + push `develop` +4. Open PR `develop → main` (Ready, not Draft) +5. Verify CI all green (`pnpm test --run` + integration + e2e + Build amd64/arm64) +6. Squash merge: `gh pr merge --squash --subject "chore(release): v1.4.27" --body ` +7. Tag: `git fetch origin main && git tag -a v1.4.27 -m "Release v1.4.27"` then `git push origin v1.4.27` +8. Wait for GHCR multi-arch builds (`docker-publish.yml` workflow — usually 5-7 min for both `v1.4.27` tag-push + `main` push) +9. Deploy apps01: + - `mcp__coolify-apps01__deploy` with the HealthLog app UUID `pg8wggwogo8c4gc4ks0kk4ss`, force=true + - **Then SSH apps01 force-pull pattern** (Coolify caches `:latest`): `ssh apps-01 'docker pull ghcr.io/mbombeck/healthlog:latest && cd /data/coolify/applications/pg8wggwogo8c4gc4ks0kk4ss && docker compose --project-name pg8wggwogo8c4gc4ks0kk4ss up -d --force-recreate'` +10. Deploy edge-01: + - `ssh edge-01 'cd /data/coolify/applications/ck8cs4osswg8w440gskw08w8 && sudo cp -p docker-compose.yaml docker-compose.yaml.pre-v1427.bak && sudo sed -i "s|ghcr.io/mbombeck/healthlog:1.4.26|ghcr.io/mbombeck/healthlog:1.4.27|g" docker-compose.yaml && sudo docker pull ghcr.io/mbombeck/healthlog:1.4.27 && sudo docker compose --project-name ck8cs4osswg8w440gskw08w8 up -d --force-recreate'` +11. Verify both: `curl https://healthlog.bombeck.io/api/version` and `curl https://demo.healthlog.dev/api/version` both report `"1.4.27"` +12. Create GitHub Release: extract CHANGELOG v1.4.27 section to `/tmp/v1427-release-notes.md`, then `gh release create v1.4.27 --title "v1.4.27 — " --notes-file /tmp/v1427-release-notes.md --latest` +13. Bump sister repos: dispatch one contributor for `healthlog-docs` + `healthlog-landing` 1.4.26 → 1.4.27 (3 image pins in docs + 1 softwareVersion in landing) + +## Critical state references + +- **Apps01 Coolify HealthLog UUID**: `pg8wggwogo8c4gc4ks0kk4ss` (FQDN `healthlog.bombeck.io`) +- **Edge-01 Coolify HealthLog UUID**: `ck8cs4osswg8w440gskw08w8` (FQDNs `demo.healthlog.dev` + `healthlog-beta.ioioio.dev`) +- **Sister repos**: `/Users/marc/Projects/healthlog-docs/` + `/Users/marc/Projects/healthlog-landing/` +- **iOS native client**: `/Users/marc/Projects/healthlog-iOS/HealthLogIOS/` +- **iOS handoff doc-pack**: `.planning/v15-ios-handoff/` (22 files, currently) +- **GHCR repo**: `ghcr.io/mbombeck/healthlog` (multi-arch: linux/amd64 + linux/arm64) +- **Coolify MCP servers reachable from this sandbox**: apps01 only (`mcp__coolify-apps01__*`). edge-01 Coolify (`46.225.114.153:8000`) is NOT reachable — use SSH directly to edge-01. +- **SSH works**: both `apps-01` and `edge-01` are SSH-aliased and SSH'd as root. +- **APNs `.p8` env**: already deployed on both servers (`APNS_KEY_ID` + `APNS_TEAM_ID` + `APNS_BUNDLE_ID` + `APNS_PRODUCTION=true` + `APNS_KEY` with literal `\n` escapes). DO NOT re-touch unless rotating. + +## When the v1.4.27 work is done + +- `healthlog.bombeck.io/api/version` returns `"1.4.27"` +- `demo.healthlog.dev/api/version` returns `"1.4.27"` +- GitHub release page lists `v1.4.27` at the top with the CHANGELOG excerpt +- `/privacy` page (v1.4.26 deliverable) still returns 200 (regression guard) +- Sister repos `healthlog-docs` + `healthlog-landing` bumped + pushed +- All 27 maintainer findings + the 17 pulled-in backlog items either landed or explicitly deferred with reason to `.planning/v1428-backlog.md` +- A `docs/audit/v1427-summary.md` exists (optional — only if scope warrants; if v1.4.27 is just QoS-polish, skip the summary doc) + +## Forbidden-term reminder + +Before every commit, before every push, before every release artifact, grep your text for: `AI`, `Claude`, `agent`, `marathon`, `wave`, `phase`, `session`, `subagent`, `Anthropic`. None of these should appear in commit messages, CHANGELOG, GitHub Release notes, planning docs, or user-facing copy. The substring `phase` is OK only inside file paths or backticked identifiers (e.g. `phase-config` as a literal route name). + +## Closing + +Session 2 picks up at R2 complete. If R2 is still running when Session 2 starts: wait for the task notification, then dispatch Round 3. If R2 already committed: read `.planning/v1427-fix-plan.md` and dispatch Round 3 based on its surface buckets. + +No iOS-side code in this release. R1.5's recommendations stay as documentation; server-side preps (sync state endpoint, syncVersion column) deferred to v1.4.28 per R2's recommendation. Don't touch them in v1.4.27. + +Good luck.