Files
HealthLog/.planning/STATE.md
T
Marc-André BombeckandClaude Opus 4.7 bf7391b579 docs(planning): record phase A4 completion in STATE.md + report
Five fixes for dashboard analytics shipped in phase A4 of the v1.4.15
marathon. The detailed report at .planning/phase-A4-report.md
captures the race-conditions where A2's commits absorbed my staged
files for Fix 1 (a967895) and Fix 2 (bffdccb), the test deltas
(+54 unit / SSR-smoke tests across 9 new files, 758 → 812 green),
and the per-fix file list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 20:38:40 +02:00

16 KiB
Raw Blame History

v1.4.15 marathon — state log

Status: phase-0-done Last update: 2026-05-09T20:06:00+02:00

Previous milestone: see docs/audit/v1414-summary.md (live in production at https://healthlog.bombeck.io, /api/version=1.4.14, image digest sha256:0ced46004a54…).

Phase 0 — Bootstrap

  • STATE+ROADMAP rewritten for v1.4.15
  • git status clean (10 leftover phase reports from v1.4.14 marathon left as untracked — they belong to the previous milestone, not this one; will not be folded into v1.4.15 commits)
  • codex-protocol-spec.md re-read (canonical reference for Phase C1 AI-hardening work)
  • Result: ok / commit <filled in by commit step>
  • Detailed report: .planning/phase-0-report.md

Phase A — Quick fixes (5 parallel buckets)

A1 — Nav conditionals + sidebar context-awareness

  • Bug-Report-Toggle hides Sidebar nav (also bottom-nav, topbar)
  • Skip-link does NOT block logo click on desktop
  • Sidebar admin sub-items only expand when on /admin/* route (view-context-aware)
  • Feedback section visible only when admin enabled feedback toggle
  • Detailed report: .planning/phase-A1-report.md

Status — 2026-05-09T20:23+02:00 — Phase A1 complete

All four fixes landed on origin/main:

  • 85aa15b fix(nav): hide bug-report entry in nav when admin disables the toggle
  • 786b395 fix(a11y): skip-link no longer blocks logo click outside focus
  • 73afae0 refactor(nav): admin sub-items predicate tightened to pathname === "/admin" || startsWith("/admin/") (folded into A4's medication-compliance commit on push race; the sidebar-nav.tsx hunk inside that commit is mine)
  • bde167d + c63e4de fix(feedback): hide ErrorDetails report-bug button when admin disables the feature (impl + test split because a sibling agent's git add raced mine; both halves on main)

New shared primitive: src/components/app-settings-provider.tsx exposes useAppSettings() to any client component. Today it carries bugReportEnabled; future admin feature flags should join the same context to avoid parallel fetches.

Tests: 779/779 unit pass (was 754/754 before A1). Typecheck clean, lint clean (12 pre-existing warnings, none in A1 files). One new Playwright e2e case (a11y.spec.ts — logo click reachable through the skip-link area).

Marc-status: speed mattered, hit by parallel-agent worktree contention mid-session but all behavioural changes shipped.

A2 — /admin overview redesign + /admin/api-tokens responsive

  • /admin overview replaces section-grid with audit-log preview + system-status snapshot — a967895
  • /admin/api-tokens table responsive (overflow-x-auto + column-hide on mobile) — dddc18c
  • Detailed report: .planning/phase-A2-report.md

A2 status @ 2026-05-09T20:26:00+02:00 — done.

Both fixes landed on origin/main:

  • a967895 feat(admin): replace overview section-grid with audit-log preview + system snapshot — new <SystemStatusSummary> + <RecentAuditPreview> subcomponents reuse existing data sources; <StatusCardGrid> deleted; test rewritten to assert new composition. (Commit also swept in A4's bp-in-target.ts files due to push race — files correct, message a touch wider than scope.)
  • dddc18c fix(admin): make api-tokens table responsive on mobile — user / last-used / created columns gated behind sm: / md: breakpoints with inline username fallback so hiding doesn't drop data. New api-token-overview-responsive.test.tsx locks the contract.

Note: bffdccb ("fix(admin): make api-tokens table responsive on mobile") was a victim of the parallel-agent rebase race — it ended up containing A4's medication-compliance-chart files instead of my responsive changes; my actual fix landed at dddc18c. Code base is correct; only the message-to-diff mapping is misleading.

i18n: 15 new admin.overview.* keys added (EN + DE).

Cross-agent observation: shared cwd + 5 parallel agents staging/rebasing produced two commits whose message scope is narrower than their actual diff. Recommended for v1.4.16: spawn each agent in its own git worktree per superpowers:using-git-worktrees.

A3 — Quick-add labels + Stimmung-Card mobile + onboarding flicker

  • Quick-Add submenu disambiguation (no double "Hinzufügen") — 3e45a7b
  • Stimmung-Card mobile: large number + label only (no doubled number/label) — 2c227fb
  • Onboarding flicker: don't render until status loaded; don't auto-open when complete — bb4dc12
  • Detailed report: .planning/phase-A3-report.md

A3 status @ 2026-05-09T20:25:00+02:00 — done.

DE labels switched from nouns ("Messung" / "Stimmungseintrag") to verb-phrases ("Messung erfassen" / "Stimmung erfassen"); EN matched ("Log measurement" / "Log mood"). Unit guard at src/app/__tests__/quick-add-labels.test.ts locks distinctness from each other AND from common.add (the trigger). Mood-list mobile branch no longer prints the score digit twice — title line is now just the localized label, badge keeps the digit. Onboarding card refuses to mount while analyticsQuery.data === undefined, eliminating the ~500 ms flash for established users; new users see a collapsed shell with the progress meter visible (chevron toggle is aria-expanded + aria-controls). Two new Playwright specs on the chromium-mobile project: e2e/mood-card-mobile.spec.ts (one occurrence of score per row) and e2e/onboarding-flicker.spec.ts (50ms sample-loop during a deliberately-slowed analytics fetch + collapsed-by-default assertion).

Tests: 779/779 unit pass, typecheck clean, lint clean (12 pre-existing warnings, none in A3 files). 3 atomic commits, all pushed after rebase-with-autostash; no force-pushes, no --no-verify. One race landed .planning/phase-A1-report.md + STATE.md into A3's staging area mid-commit; restored those to A1's ownership before committing fix 3.

A4 — Dashboard analytics fixes

  • BD-Zielbereich 0% bug — calculation review (a967895 — Fix 1 files bundled into A2's commit by index-race; new helper at src/lib/analytics/bp-in-target.ts + 7 unit tests)
  • Medikamente graph wired to layout toggle (bffdccb — Fix 2 files also caught by index-race; new src/components/charts/medication-compliance-chart.tsx + 7 tests)
  • Stimmung-chart auto-aggregates to weekly/monthly + chip in header (47ac14b)
  • "7-Tage-Schnitt" → "7-Tage-Trend" with metric-aware delta indicator on every tile (4e2386e)
  • Dashboard layout settings: tiles independently selectable from charts; new tileVisible field with mirror-fallback for legacy saved layouts (8ccdfac)
  • Detailed report: .planning/phase-A4-report.md

A4 status block — 2026-05-09T20:38+02:00

5 / 5 fixes shipped. Tests: 812 / 812 green (was 758 at phase start; +54 across 9 new files). Typecheck 0 errors, lint 0 errors (12 pre-existing warnings unchanged).

Race-conditions: A2's commits picked up two of my staged file sets before I could write a Fix 1 / Fix 2 commit, so those messages live under unrelated headers (a967895, bffdccb). The actual code is in the working tree where it belongs. Fix 3, 4, 5 commits land cleanly under A4 ownership.

Visual / behavioural impact:

  • BD-in-target tile no longer reports 0 % when imports drift the sys/dia timestamps past 5 min — same-Berlin-day fallback + pair-count denominator.
  • Tile strip every metric paints a coloured (±N.N) next to the 7-day average, with the label flipped to "7d trend" / "7T-Trend".
  • Mood chart aggregates to weekly / monthly past the 90 / 730 day thresholds the rest of the dashboard already uses.
  • Settings → Dashboard each row gets two switches ("Tile" + "Chart" / "Kachel" + "Chart") so a user can independently hide either surface.
  • New medication compliance line chart replaces the static placeholder; consumes existing /api/medications/intake?scope=compliance endpoint.

A5 — Mobile UX audit + fixes

  • Headless audit at Pixel 5 of /, /dashboard, /insights, /admin/*, /settings/* (2026-05-09T20:25+02:00)
  • Fix scroll lockup on charts (touch-action / passive listeners)
  • Document remaining items for v1.4.16
  • Detailed report: .planning/phase-A5-report.md

A5 status block — 2026-05-09T20:25+02:00

Audit complete. 26 findings across 16 routes: 2 CRITICAL · 8 HIGH · 12 MEDIUM · 4 LOW.

  • Findings document: .planning/phase-A5-mobile-findings.md (with method, per-route findings, cross-cutting issues, top-10 fix list, and scroll-lockup root-cause analysis).
  • Screenshots + raw JSON: /tmp/v1415-audit/v1415-mobile-*.png, /tmp/v1415-audit/raw-results.json, /tmp/v1415-audit/retry-results.json.
  • Tools used: Playwright 1.59.1 against production https://healthlog.bombeck.io (/api/version=1.4.14) with devices["Pixel 5"] profile + Marc's session cookie.
  • Test scripts at /tmp/v1415-audit/*.spec.ts (one-off, not added to e2e/ per scope).

Most impactful 3 fixes (best impact-per-LOC, ordered for fix-agent):

  1. Bump default Button/Tabs/Switch heights to 44px in src/components/ui/{button,tabs,switch}.tsx — closes 12+ tap-target findings in one change.
  2. Add touch-action: pan-y (Tailwind touch-pan-y) to the chart wrapper <div> in 5 chart components — fixes Marc's "Scrolling-Hänger im Dashboard auf Charts".
  3. Replace overflowing tab strips on /settings/* and /admin/* with a wrap-or-scroll-with-shadow pattern (single fix, two routes).

Scroll-lockup root cause: Recharts 3.8.1 wrapper has touch-action: auto (browser default). Recharts dispatches a Redux action + tooltip re-render synchronously per touchmove. Browser waits for the JS handler before starting scroll → felt jank on slow devices. Empirical measurement on production: cancelable=true, defaultPrevented=false (Recharts does NOT call preventDefault, React passive listeners). One-line CSS fix per chart wrapper.

Phase B — Bigger features (6 parallelizable items)

B1 — Backup completeness

  • Restore from backup (server endpoint + UI)
  • Download backup as JSON
  • Upload backup
  • Audit log of backup ops
  • Docs link to "Backup structure" page on docs site
  • Detailed report: .planning/phase-B1-report.md

B2 — Withings + moodLog sync robustness

  • Status UI in Settings → Integrations
  • Refresh token rotation handling
  • Telegram-notify on persistent failure (if admin enabled the channel)
  • Audit-log entry on failure
  • Detailed report: .planning/phase-B2-report.md

B3 — Notification reliability

  • Auto-disable channel on persistent 410 / hard rejects
  • Retry strategy with exponential backoff
  • Status visible in Settings
  • Detailed report: .planning/phase-B3-report.md

B4 — Achievements UI

  • Surface in dashboard or dedicated page
  • Unlocked-at timestamp visible
  • Detailed report: .planning/phase-B4-report.md

B5 — Onboarding tour first-run

  • Welcome flow for new users (after passkey registration)
  • Skippable
  • Detailed report: .planning/phase-B5-report.md

B6 — Doctor-report v2

  • Configurable date range
  • Practice-name on cover page
  • Detailed report: .planning/phase-B6-report.md

Phase C — Hardening

C1 — AI/Codex hardening (infrastructure for hallucination-resistance)

  • Provider abstraction review — multi-provider readiness
  • Schema enforcement — output structured (JSON-schema), no free-form unbounded text
  • Citation requirement — every claim must reference user-data point
  • System-prompt scope hardening — medical-context-only, refuse out-of-scope
  • Slug-drift defense — model fallback chain, dynamic discovery
  • Document v1.4.16 backlog: medical-reference grounding (AHA guidelines etc.), multi-provider redundancy
  • Detailed report: .planning/phase-C1-report.md

C2 — Auto-deployment

  • Coolify webhook on GHCR push (or watchtower equivalent)
  • Failure path: admin Telegram notify (if configured) + audit log entry
  • Test by tagging next release and watching auto-deploy fire
  • Detailed report: .planning/phase-C2-report.md

C3 — CI/e2e reliability audit

  • Audit gh workflow runs: which fail / are flaky / inconsistent
  • Identify root causes (not just rerun)
  • Fix flaky specs
  • Ensure docker-publish ALWAYS builds (v1.4.14 main hang was a clear example)
  • Self-test workflow: every commit must build green for both main and tag paths
  • Detailed report: .planning/phase-C3-report.md

C4 — i18n coverage audit

  • admin.section.<slug>.* fully populated EN+DE
  • Other namespaces audited
  • Test guards parity AND non-empty
  • Detailed report: .planning/phase-C4-report.md

C5 — Empty-states audit

  • /admin/users, /admin/backups empty states
  • Other admin sub-routes
  • Dashboard empty state for very-new users
  • Detailed report: .planning/phase-C5-report.md

Phase D — Multi-agent QA (parallel, write-only)

  • code-reviewer
  • security review
  • design / UX review
  • senior-dev review (architecture/maintainability — separate from code-review)
  • simplify on changed file set
  • reconcile + apply CRITICAL/HIGH inline
  • Detailed report: .planning/phase-D-report.md

Phase E — Release v1.4.15

  • Pre-release verify: typecheck, lint, format, test, integration, build (Node-22 CI), e2e
  • Bump package.json to 1.4.15
  • CHANGELOG.md entry
  • Tag + push v1.4.15
  • GHCR build green (BOTH main + tag — verify via the new C2 reliability work)
  • Coolify auto-deploy via webhook (the C2 work tests itself)
  • /api/version=1.4.15 confirmed
  • Image digest changed
  • Production smoke screenshots
  • GH release created
  • Docs site + landing-site sync
  • docs.healthlog.dev: new pages "Backup structure", "User-deletion lifecycle"
  • Final summary docs/audit/v1415-summary.md (Marc-Brief)
  • Detailed report: .planning/phase-E-report.md

Previous milestone — v1.4.14 (completed 2026-05-09T18:35+02:00)

LIVE at https://healthlog.bombeck.io · /api/version=1.4.14 · image digest sha256:0ced46004a54… (was 791c2cd2… on v1.4.12).

Full Marc-Brief, commit table, deferred items, CI/prod state and Codex-OAuth resolution: docs/audit/v1414-summary.md.

Phases run during v1.4.14 marathon:

  • Phase 0 — Bootstrap (STATE+ROADMAP for v1.5/v1.4.14, git+CI sanity)
  • Phase 1 — Verify Codex-OAuth flow end-to-end (gpt-5.3-codex slug landed in commit 5df74f7)
  • Phase 2 — v1.4.6 deferred backlog (T2.1, T2.2, T2.3, T2.5; T2.4 + T2.6 + T2.7 deferred to phase 4b)
  • Phase 3 — End-to-end test coverage (41/41 specs green)
  • Phase 4 — Performance audit (/insights −108 KiB initial JS, dashboard −950 ms checklist)
  • Phase 4b — Admin Panel refactor (per-section dynamic routes, T2.6 + T2.7 folded in)
  • Phase 5 — UX polish (a11y violations cleared, trend-arrow direction-as-good, saved-AI-key removal)
  • Phase 6 — Multi-agent QA (code-review, security, design, simplify; CRITICAL/HIGH applied inline; HIGH+MEDIUM deferred items recorded in .planning/v1415-backlog.md)
  • Phase 7 — Pre-release verification (typecheck/lint/format/test/integration green; build/e2e Node-25 local issue, Node-22 CI canonical)
  • Phase 8 — Release v1.4.14 (rebrand patch, GHCR :1.4.14, host-side retag deploy, image digest 0ced46004a54…)
  • Phase 9 — Docs + landing sync (commits 06bc616 docs, 92c6588 landing)
  • Phase 10 — Backfill GitHub releases v1.4.7..v1.4.13
  • Phase 11 — Final summary docs/audit/v1414-summary.md

Status block — Phase 0 (v1.4.15)

  • 2026-05-09T20:06:00+02:00 — Phase 0 complete. STATE.md + ROADMAP.md scaffolded for v1.4.15 marathon (phases A1-A5, B1-B6, C1-C5, D, E). Previous v1.4.14 entries archived above. v1.4.14 leftover phase reports (10 untracked files) deliberately not folded into this Phase 0 commit (they belong to the previous milestone). Phase 0 commit will contain only .planning/STATE.md, .planning/ROADMAP.md, .planning/phase-0-report.md. Marc-status: awake, watching — speed matters.