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>
16 KiB
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 digestsha256: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:
85aa15bfix(nav): hide bug-report entry in nav when admin disables the toggle786b395fix(a11y): skip-link no longer blocks logo click outside focus73afae0refactor(nav): admin sub-items predicate tightened topathname === "/admin" || startsWith("/admin/")(folded into A4's medication-compliance commit on push race; the sidebar-nav.tsx hunk inside that commit is mine)bde167d+c63e4defix(feedback): hide ErrorDetails report-bug button when admin disables the feature (impl + test split because a sibling agent'sgit addraced 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
/adminoverview replaces section-grid with audit-log preview + system-status snapshot —a967895/admin/api-tokenstable 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:
a967895feat(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'sbp-in-target.tsfiles due to push race — files correct, message a touch wider than scope.)dddc18cfix(admin): make api-tokens table responsive on mobile — user / last-used / created columns gated behindsm:/md:breakpoints with inline username fallback so hiding doesn't drop data. Newapi-token-overview-responsive.test.tsxlocks 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 atsrc/lib/analytics/bp-in-target.ts+ 7 unit tests) - Medikamente graph wired to layout toggle (
bffdccb— Fix 2 files also caught by index-race; newsrc/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
tileVisiblefield 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=complianceendpoint.
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) withdevices["Pixel 5"]profile + Marc's session cookie. - Test scripts at
/tmp/v1415-audit/*.spec.ts(one-off, not added toe2e/per scope).
Most impactful 3 fixes (best impact-per-LOC, ordered for fix-agent):
- Bump default Button/Tabs/Switch heights to 44px in
src/components/ui/{button,tabs,switch}.tsx— closes 12+ tap-target findings in one change. - Add
touch-action: pan-y(Tailwindtouch-pan-y) to the chart wrapper<div>in 5 chart components — fixes Marc's "Scrolling-Hänger im Dashboard auf Charts". - 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/backupsempty 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-codexslug landed in commit5df74f7) - 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 digest0ced46004a54…) - Phase 9 — Docs + landing sync (commits
06bc616docs,92c6588landing) - 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.