mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28 KiB
28 KiB
v1.4.16 marathon — state log
Status: phase-0-done Last update: 2026-05-09T23:12:52+02:00
Previous milestone:
docs/audit/v1415-summary.md(live:/api/version=1.4.15, image digestsha256:ace7d441f47b…).
Phase 0 — Bootstrap
- STATE+ROADMAP rewritten for v1.4.16
- git status clean
- codex-protocol-spec re-read
- v1416-backlog.md inventoried
- Result: ok / commit
chore(planning): bootstrap v1.4.16 marathonon origin/main - Detailed report:
.planning/phase-0-report.md
Wave A — Quick fixes (parallel buckets)
A1 — Sidebar admin-expand bug
- Clicking Admin from non-admin route does NOT auto-expand sub-items (mirror Settings exact pattern)
- Gravatar dropdown does NOT trigger sidebar expansion side-effect
- Detailed report:
.planning/phase-A1-A3-report.md - Commit:
77fe256 fix(nav): admin sub-items don't expand from gravatar dropdown or admin-link clickon origin/main
A2 — BD-Zielbereich real-fix (regression from v1.4.15 A4)
- Investigate root cause — A4 in v1.4.15 marked this fixed but Marc still sees 0%
- Verify against actual user data with measurements (pulled from production apps-01 DB)
- Fix root cause + add E2E test that exercises full flow against real session
- Detailed report:
.planning/phase-A2-A6-report.md - Commit:
577d8dd fix(insights): BD-Zielbereich computes correctly for real measurement dataon origin/main - Root cause: v1.4.15 fix corrected the denominator but kept the ESH narrow-band predicate (
sysLow <= sys <= sysHigh AND diaLow <= dia <= diaHigh); Marc's normotensive readings (e.g. 117/79) were below sysLow=120 and so counted as OUT. Marc's actual production data: 0/10 paired readings in target under v1.4.15. Fix: change to one-sided ceiling semantics with hypotension floor (90 <= sys <= sysHigh AND 50 <= dia <= diaHigh); centralised inisBpReadingInTarget()shared by 6 call sites. Marc's data now reports 50% (was 0%).
A3 — /admin/api-tokens table responsive (still scrolling)
- Inspect current state on prod with Marc's session — overflow-x scrollbar visible
- Fix properly: card-list mobile fallback OR proper column-hide chain at xs/sm/md breakpoints
- Detailed report:
.planning/phase-A1-A3-report.md - Commit:
277a5aa fix(admin): api-tokens table no horizontal overflow on Pixel-5 viewporton origin/main
A4 — "7-Tage-Schnitt" → "7-Tage-Trend" DE + indicator on ALL charts
- DE i18n string rename everywhere (incl. tile-strip + chart subtitles)
- Trend indicator (+/-) appears for EVERY chart including mood + medication + insights
- Trend on "all" filter computes correctly (currently shows 0)
- Detailed report:
.planning/phase-A4-report.md
A5 — Top-tile-selector real-fix (regression from v1.4.15 A4)
- Investigate why settings save isn't reflected on dashboard
- Probably a query-cache stale-read OR the layout-config field isn't actually consumed by the tile-strip
- Fix + e2e test toggling visibility persists
- Detailed report:
.planning/phase-A5-report.md
A6 — Medication-chart 7d-trend + target-range
- Medication-chart matches other charts: 7d-trend label + indicator + target-range visualization
- Detailed report:
.planning/phase-A2-A6-report.md - Commit:
9b01c86 feat(charts): medication chart matches other charts (7d trend + indicator + target-range)on origin/main - Added
computeMedicationTrend7d()helper (split-half mean comparison, 14-day cap), trend chip in header (signed Δ-pp + arrow icon,up-goodsentiment colours), 100% goal ReferenceLine alongside the existing 80% threshold. 6 new unit tests pin trend computation. Cross-agent race note:9b01c86accidentally bundled A7'sINSIGHTS_RATE_LIMIT_PER_HOURwork — see report for details.
A7 — AI Generator rate-limit 10/h + cache-invalidate-on-new
- Rate-limit current 2/h → 10/h (env-configurable via
INSIGHTS_RATE_LIMIT_PER_HOUR) - When user generates new insight: evict ALL cached previous insights for that user (per-status
audit_logsrows forinsights.<scope>-status.<locale>are deleted;insights-card.tsxalready invalidates["insights"]on mutation success) - Verify: dashboard shows newest insight, never stale-cached (3 new test blocks: 10/h default, env override, sub-1 fallback, deleteMany call shape, cached-path skip)
- Detailed report:
.planning/phase-A7-A8a-report.md - Commit: source landed inside
9b01c86 feat(charts): medication chart matches other charts(cross-agent race — A6 worker pushed first and absorbed the staged A7 files). Code is verbatim what A7 wrote:resolveInsightsRateLimit(),evictPerStatusInsightCache(), the rate-limit message rewrite toMaximum ${limit} insight generations per hour., and the i18n flatten ("Bitte warte — du hast das stündliche Limit für Analysen erreicht."). All on origin/main.
A8 — Umlaute encoding bug + login-overview
- "Nrnberg" should be "Nürnberg" — geo helper now decodes via
arrayBuffer() + TextDecoder('utf-8')instead ofResponse.json(), so an upstream proxy that strips/rewrites theContent-Type: charsetparameter cannot poison the umlaut path - Audited all of
src/for ASCII-fold patterns (normalize("NFD"), slugify,[^a-zA-Z…]/gstrips,String.fromCharCode/charCodeAtdeburr): zero hits. The geo helper was the only surface - Regression test for known-umlaut roundtrip: 7 cities (Nürnberg, München, Düsseldorf, Köln, Würzburg, Bückeburg, Weißenfels) plus eszett + Content-Type-without-charset case + Accept-Language assertion (de;q=1, en;q=0.5)
- Detailed report:
.planning/phase-A7-A8a-report.md - Commit:
2da0703 fix(geo): preserve umlauts in city names (login-overview no longer renders "Nrnberg")on origin/main
Wave B — Quality-leap features
B1 — Insights/Charts Apple-Health-style visual leap (chart wrappers, first half)
- Benchmark against Apple Health, Withings Health Mate, Oura Ring
- Insights surface: gradient fills, animation, dynamic comparisons (better/worse), interactive tooltips, vertical slide-to-compare
- Charts: same level of polish — Recharts replacement allowed if quality bar requires
- Insights surface visualizes data, not just text-summarizes
- Detailed report:
.planning/phase-B1-report.md
B1a — Charts visual leap (chart wrappers only) — complete
- 2026-05-10T00:35+02:00 — B1a complete on origin/main.
- Primitives (
src/components/charts/{chart-gradient,chart-tooltip,chart-empty-state}.tsx) plussrc/lib/charts/reduced-motion.ts. 11 unit tests. - HealthChart (BP/weight/pulse/body-fat/sleep/steps wrapper):
LineChart→ComposedChart, gradient-filled<Area>per type, 90-day median personal-baseline<ReferenceLine>("Your normal" / "Dein Mittel"),<RichChartTooltip>with delta-vs-baseline, 600 ms ease-out animation respectingprefers-reduced-motion, sparse-data<ChartEmptyState>for <3 points. - MoodChart: same polish + emoji glyphs at every score (😖 🙁
😐 🙂 😄 mapped from 1..5) via Recharts
dotcallback; lavender gradient under the score line. - MedicationComplianceChart: same polish, purple gradient, rich tooltip with "−N pp vs. target" delta. A6's existing 80 % threshold + 100 % goal lines untouched.
- +23 net tests; full suite 1298/1299 (single pre-existing B6 fail).
- Commits on origin/main: primitives →
2611bb4(subject belongs to B5b due to a parallel-staging race; my 6 files + 7 i18n keys correct),74c2eb8 feat(charts): BP/weight/pulse polish (gradient, baseline, rich tooltip),901f44e feat(charts): mood chart polish with emoji glyphs at data points(also absorbed B5b'sprovider-runner.ts),8008613 feat(charts): medication chart polish (gradient + animation + rich tooltip)(clean). - Architectural deviation: brief asked for separate
blood-pressure-chart.tsx/weight-chart.tsx/pulse-chart.tsxfiles; the codebase has oneHealthChartwrapper used for all three families. Splitting would have been DRY-regressing — kept one wrapper, one commit covers all three. - "Optional targetWeightKg user-pref" on weight chart not added —
that's a Settings → Account field B6 owns; chart wrapper already
accepts a
valueBandsprop the dashboard can pass a target band through whenever the user-pref ships. - Detailed report:
.planning/phase-B1a-report.md
- Primitives (
B2 — AI provider settings UX cleanup (Pulldown-driven)
- Settings → AI: provider dropdown drives form below (no top/bottom split)
- All providers configurable from one UI (Codex / OpenAI direct / Anthropic / Local / Admin OpenAI)
- Form switch-renders dynamically when provider changes
- Detailed report:
.planning/phase-B2-report.md - Status block — 2026-05-10T01:15+02:00: B2 complete on
agent/b2-ai-provider-uxworktree, ready for fast-forward intoorigin/main. NewPUT /api/insights/provider-chain(5 unit tests + 2 integration tests). Refactored<AiSection>collapses the v1.4.15 top/bottom split per Marc'sfeedback_settings_no_split.md: one Pulldown drives a switch-rendered config card (Codex / OpenAI / Anthropic / Local / Admin OpenAI) and a<FallbackChainCard>reorders / toggles / removes / adds entries with arrow controls (no new dependency —dnd-kitnot inpackage.json). EN+DE i18n keys + 8 new SSR tests + 1 Playwright spec.pnpm test1316/1316,pnpm test:integration55/55, typecheck 0 errors, lint 0 errors. Worktree-isolated underagent/b2-ai-provider-uxso the parallel-running B5c agent on the rec-card surface can't bleed in.
B3 — Admin System-Status host-load chart
- Host CPU/memory/disk-io graph last 2h (in-process sampler — Coolify Sentinel had no clean read endpoint)
- Render above current system-status section
- Detailed report:
.planning/phase-B3-report.md - Commits on origin/main:
5d1ece1 feat(db): HostMetric model for host-load sampling,f1bd801 feat(jobs): host-metric sampler captures load + memory every minute, 7d retention,2877710 feat(api): /api/admin/host-metrics returns last 2h of host load + memory. Chart component + system-status wiring + i18n landed inside8d9f864 docs(planning): mark Wave-B B5a (medical-reference grounding) completedue to a parallel-agent staging race during the verification-gate stash/restore loop — files are correct on origin/main, just under a misleading subject. 8 sampler unit tests + 6 API integration tests + 5 chart component tests all green; i18n parity test green.
B4 — Admin logs visibility deepening
- Audit log: filterable by actor/action/target, paginated (25/50/100 per page), exportable as CSV
- App-log preview: tail of last 500 structured wide-events from per-process ring buffer, filterable by trace_id / level / action / time-window, JSON inspector modal
- Detailed report:
.planning/phase-B4-report.md - Commits:
8ac5602(audit-log API + UI — bundled with verification-gate planning commit due to coordinator stash race; my code, wrong commit subject),4cc3d8d feat(admin): app-log preview surfaces last 1h of structured events with filter + JSON inspector,6520ae4 feat(admin): sidebar entry for app-logson origin/main - Status block — 2026-05-10T00:11+02:00: B4 complete on origin/main. New
src/lib/logging/in-memory-buffer.ts(500-entry FIFO, FIFO eviction, redaction at API egress only). New/api/admin/audit-log/actionspopulates the action-dropdown viagroupBy. New/api/admin/app-logsroute +<AppLogPreviewSection>component +app-logsadmin slug +<AdminShell>entry. 51/51 B4 unit tests green; typecheck/lint clean on B4 surface. Sibling B7 brokenexport-per-typetypecheck failures predate this phase.
B5a — Medical-reference grounding
- AHA / ESC / ESH / WHO / DGE target ranges as system context (curated bundle in
src/lib/ai/medical-references.ts) - Citations link to source guideline in UI (
<CitationFootnote>opens in new tab) - Detailed report:
.planning/phase-B5a-report.md - Commits on origin/main:
27f3933 feat(ai): curated medical-reference bundle for citation grounding466b8b5 feat(ai): schema accepts validated referenceId pointing into the medical-reference bundle7fbfca6 feat(ai): system prompt includes curated medical references for citation grounding53aade9 feat(ai): post-validation logs citation-coverage rate per insight generationa66c128 feat(insights): citation footnote on recommendations with medical reference
- 5 atomic TDD-first commits, +44 net tests (15 bundle + 8 schema + 10 prompt + 15 coverage + 6 footnote − overlaps). PROMPT_VERSION bumped 4.15.0 → 4.16.0. Citation-coverage Wide-Event annotation observational in v1.4.16; B5c will flip to required for severity ≥ "important".
- Cross-agent worktree race captured B4 admin files into commit
a66c128and my commit-5 content intoaff9add(host-metrics-chart) — see report for detail.
B5b — Multi-provider redundancy
- try-each-on-hard-failure across configured providers
- Fallback ordering configurable per user
- Detailed report:
.planning/phase-B5b-report.md - Commits on origin/main:
2611bb4 feat(db): User.aiProviderChain for ordered fallback config901f44e feat(charts): mood chart polish ...(cross-agent race subject — actual diff includes the B5b runner + provider-chain resolver + route wiring; verified viagit show 901f44e)613d661 feat(settings): minimal display of active AI provider + configured chaind2bda42 test(ai): provider fallback covers happy path, hard-fail cascade, cache
- 4 atomic TDD-first commits. New module
provider-runner.tsexposes both a strictrunWithFallback()(for B5c migration) and a legacy-shaperunRawCompletionWithFallback()(consumed by the current route). Hard-fail policy: 401/403/429/5xx/transport cascade; schema 422 bubbles. Last-working cache: 1h TTL, in-process, per-userId. NewUser.aiProviderChain Json?column + migration0033. NewGET /api/insights/provider-chainendpoint feeds<ProviderChainSummary>(active + cached + configured chain) under Settings → AI; full management UX deferred to B2 per scope. EN+DE i18n parity green. Cross-agent race: commit 2 subject was hijacked by parallel B1a worker (mood-chart polish); my code IS on origin.
B5c — Per-Recommendation Explainability
- Each rec carries: WHY (what user-data triggered it), WINDOW (which time range was analyzed), CITATIONS (which medical guideline + which user metric)
- UI: expand-arrow on each rec → reveals the explainability card with mini-chart of the data window
- Schema enforces presence (extends v1.4.15 C1's strict schema)
- Detailed report:
.planning/phase-B5c-report.md
B5d — Confidence Score per Recommendation
- Each rec carries a 0-100 confidence score derived from: data sufficiency (n samples), recency, signal strength
- UI: visual confidence indicator (e.g., color-coded ring or 5-bar meter) per rec
- Below-threshold recs are tagged "Low confidence — based on limited data" rather than hidden
- Detailed report:
.planning/phase-B5d-report.md
B5e — User-Feedback Loop
- "War das hilfreich?" thumbs-up/down on each rec, persisted as RecommendationFeedback (new table)
- Aggregated feedback feeds into prompt-tuning: low-helpful patterns get a system-prompt addendum next generation
- Privacy: feedback is per-user; no cross-user training (offline only, opt-in for any aggregation)
- Detailed report:
.planning/phase-B5e-report.md
B6 — Settings naming-audit
- Every settings sub-route reviewed for stringency, naming consistency, logical grouping
- No top/bottom split anti-pattern anywhere (AI flagged for B2 — only known instance, out of B6 scope)
- No double naming (audit found no live duplicate; settings vs admin scope rule landed in CLAUDE.md)
- Detailed report:
.planning/phase-B6-report.md· audit doc:docs/audit/v1416-settings-audit.md - Commits on origin/main:
01a05e4 docs(audit): v1.4.16 settings naming + consolidation audita432cb2 refactor(settings): consistent naming + i18n key namespaceed0cfda refactor(settings): remove duplicate toggles, route to canonical ownerd914f76 test(settings): coverage for renamed/consolidated sections
- Status block — 2026-05-10T00:28+02:00: B6 complete on origin/main. Threshold component renames (
thresholds-settings-section.tsx→thresholds-section.tsxroute wrapper; oldthresholds-section.tsxinner editor →thresholds-editor-section.tsx<ThresholdsEditorSection>) align every section with the canonical<slug>-section.tsx<SlugSection>convention. Three muddy section descriptions rewritten in EN + DE (account,api,advanced);notifications.descriptionrewritten so the DE doesn't verbatim-copy the EN. Newsections-i18n-parity.test.tswalks everySETTINGS_SECTION_SLUGSentry and asserts both.title+.descriptionresolve in EN+DE and the DE differs from the EN. Settings tests 63/63 (was 40/40, +23 net). Typecheck 0 errors, lint 0 errors / 12 pre-existing warnings. Worktree-isolated underagent/b6-settings-auditso the sibling B1/B5b uncommitted state in the primary checkout couldn't bleed in. AI section top/bottom split (Marc's specific call-out) flagged for B2; flat-key hygiene PR flagged for post-v1.4.16.
B7 — Settings → Export menu (Arztbrief consolidated)
- New /settings/export route with consolidated UI: Doctor-report (PDF, configurable date range + practice name from B6 v1.4.15) + CSV/JSON exports (measurements/medications/mood per CLAUDE.md src/lib/export.ts)
- Properly designed: card per export type, clear preview + filter + download button
- Rename current doctor-report entry-point to live under /settings/export
- Detailed report:
.planning/phase-B7-report.md - Commits on origin/main:
621109c feat(settings): export-section consolidates doctor-report, CSVs, JSON backupa512650 feat(settings): /settings/export dynamic route wired into sidebar94c748d refactor(doctor-report): entry-point relocated under /settings/export226cac4 docs(planning): mark phase B3 (host-load chart) complete— absorbed the four/api/export/*route files + per-type unit tests + integration suite via a parallel-agent staging race during the verification gate's stash/restore loop. Code authored by me (Marc + Co-Authored-By Claude Opus), commit summary name belongs to B3.d5c8912 fix(export-section): point download buttons at the new plain-segment endpoints830b2b0 test(export): integration test points at the new plain-segment endpointse628f33 test(export): coverage for export-section + endpoints
- 5 cards rendered (Doctor Report PDF / Measurements CSV / Medications CSV with
optional intake-history toggle / Mood CSV / Full JSON Backup), each on its
own
data-testidso the e2e suite can target without relying on i18n labels. Mobile stacks;>=mdis a 2-column grid. AdvancedSection is now danger-zone-only. Routes use plain segments (/api/export/measurementsrather than.csv— vitest can't resolve dotted segments cleanly; the file extension lives inContent-Disposition). All four endpoints share the globalexport:<userId>10/h rate-limit bucket and write auser.export.<kind>audit-log entry. 10 unit + 9 integration + 2 e2e tests pin the contract.
B8 — Extended Comparison Views (Vormonat / Vorjahr)
- Each chart + tile + insight gets toggleable comparison overlay: "vs. last month" / "vs. last year"
- Visual treatment: dimmed historical line beneath current; delta callout (Δ +5%, etc.)
- Insights surface narrates the comparison ("Your average BP improved by 4 mmHg vs. last month")
- Mobile-friendly comparison toggle (not a fragile hover-only interaction)
- Detailed report:
.planning/phase-B8-report.md
Wave C — Catch-up (deferred from v1.4.15)
- CI Integration tests + e2e workflows pre-existing red since
d8c549e— both green from this phase forward - 5 of 8 deferred HIGH from v1.4.15 Wave-D (H1, H2, H4 code-review, H4 design, H3 senior in-use; H3 mood-chart skipped per charts/ ownership; H1+H2 senior splits deferred)
- 3 of 5 deferred MED from A5 mobile (tabs scroll, bottom-nav 5+More, system-status retry; measurements BP grouping + DOM weight deferred to v1.5)
- Coolify image-digest auto-deploy trigger — DEFERRED with v1.5
plan documented in
docs/audit/v1416-auto-deploy-fix.md(Marc- side UI flip is the 5-min realistic fix; MCP API doesn't expose the toggle) - docker-publish main-branch hang — root cause was qemu-arm64
SIGILL; dropped arm64 from the platforms list, v1.5 to re-add via
native
ubuntu-24.04-armmatrix - Bonus: B5a i18n parity for
insights.recommendation.{source,viewSource} - Detailed report:
.planning/phase-C-report.md
Status block — Wave C
- 2026-05-10T00:44:00+02:00 — Wave C complete on origin/main.
Worktree-isolated agent at
/Users/marc/Projects/HealthLog-conagent/wave-c-catchupshipped 11 commits without a single shared- cwd race. CI Integration green (5 successive successes), e2e in-progress at write time on0d08e33.pnpm test1303/1303,pnpm test:integration53/53 (afterpnpm db:generatefor B5b's newaiProviderChaincolumn),pnpm typecheck0 errors,pnpm lint12 pre-existing warnings.- CI fix:
fbcd106— quotedENCRYPTION_KEYYAML scalar (was parsed as integer 0) + seededonboarding_tour_completed = truein e2e global-setup so the spotlight tour overlay stops intercepting clicks across 9 specs. - HIGH H1:
fdac9e2admin restore-failed scrubs raw Prisma error. - HIGH H2:
7f1a4demoodEntry.tags refined to JSON-array. - HIGH H4 code:
2afe3c4tour-launcher sessionStorage scoped by user id. - HIGH H4 design:
b863e2c44 px tap targets on tour / backups / notifications. - i18n parity:
2a7ef72Quelle / Leitlinie translations. - MED tabs:
d7c2b2ahorizontal scroll on mobile. - MED bottom-nav:
072eee65+More with overflow sheet. - MED system-status:
65b4bf9Retry button. - Auto-deploy doc:
4be6465defer + v1.5 plan. - docker-publish:
cc0f343drop qemu-arm64.
- CI fix:
Wave D — Multi-agent QA + Product-Lead
- code-reviewer
- security review
- design / UX review (Apple Health benchmarking lens)
- senior-dev review
- simplify
- Product Lead — state of app, biggest items, v1.5 roadmap, follow-on initiatives
- Reconcile applies CRITICAL/HIGH inline
- Detailed report:
.planning/phase-D-report.md+product-lead-review.md
Phase E — Release v1.4.16
- Pre-release verify
- Bump package.json + CHANGELOG
- Tag + push v1.4.16
- GHCR build (verify both main + tag green; C3 v1.4.16 fix may finally help main)
- Coolify deploy
- /api/version=1.4.16 confirmed
- Production smoke
- GH release
- Docs site + landing site sync
docs/audit/v1416-summary.md(Marc-Brief)- Detailed report:
.planning/phase-E-report.md
Previous milestone — v1.4.15 (completed 2026-05-09T22:50+02:00)
LIVE at https://healthlog.bombeck.io · /api/version=1.4.15 · image digest
sha256:ace7d441f47b… (was 0ced46004a54… on v1.4.14).
Full Marc-Brief, commit table, deferred items, CI/prod state and
Phase-D reconcile detail: docs/audit/v1415-summary.md. Backlog seeded
to .planning/v1416-backlog.md (8 deferred HIGH + 39 MED/LOW + 4
simplify-no + 3 process items).
Phases run during v1.4.15 marathon:
- Phase 0 — Bootstrap (STATE+ROADMAP for v1.4.15)
- Phase A1–A5 + B-mobile — Quick fixes (nav, admin overview, quick-add labels, dashboard analytics, mobile audit + fix-application)
- Phase B1–B6 — Bigger features (backup completeness, Withings/moodLog robustness, notification reliability, achievements UI, onboarding tour, doctor-report v2)
- Phase C1–C5 — Hardening (AI/Codex schema + slug-drift, Coolify auto-deploy, CI/e2e reliability, i18n parity, empty-states audit)
- Phase D — Multi-agent QA (5 reviewers + reconcile; 0 CRITICAL, 5 HIGH fixed inline, 8 HIGH deferred to v1.4.16)
- Phase E1–E3 — Release (v1.4.15 tag, GHCR, host-side retag deploy, docs+landing sync, summary)
Marathon recurring meta: per-agent git-worktree adoption deferred to v1.4.16 (commit-message drift recurred across A2, A4, B1, B-mobile, B2, B3, B4, C1, C5).
Status block — Phase 0 (v1.4.16)
- 2026-05-09T23:12:52+02:00 — Phase 0 complete. STATE.md + ROADMAP.md
scaffolded for v1.4.16 marathon (Wave A: A1-A8, Wave B: B1-B7, Wave C
catch-up, Wave D multi-agent QA + Product-Lead, Phase E release).
Previous v1.4.15 entries archived above. Working tree was carrying
re-run-prettier corruption on 22 .planning/ files (markdown list-
marker
+flipped to-, breaking content) — discarded viagit checkout -- .planning/before scaffold; tracked files clean. Untracked v1.4.14/v1.4.15 leftover phase reports (15 files) left in place — they belong to previous milestones, not v1.4.16. Phase 0 commit contains only.planning/STATE.md,.planning/ROADMAP.md,.planning/phase-0-report.md. Marc-status: speed matters.
Status block — Wave A bucket-1 (A1 + A3)
- 2026-05-09T23:26:00+02:00 — A1 + A3 complete on origin/main.
- A1 removed the entire admin sub-list expansion from
sidebar-nav.tsx; the Admin entry now mirrors the Settings entry exactly (single link, no sub-items at any route, gravatar dropdown unaffected). Vitest + new e2ee2e/sidebar-admin-no-expand.spec.tscover the contract. Commit77fe256. - A3 swapped the api-tokens desktop
<table>for a real mobile card-list at <md (mirrors<UserManagementSection>). Nooverflow-x-autoinside the mobile container; long names + perm badges wrap within the card. New e2ee2e/admin-api-tokens-mobile.spec.tsasserts no page scroll at Pixel 5 with a worst-case payload. Commit277a5aa. - Verification:
pnpm typecheckclean,pnpm lint12 pre-existing warnings / 0 errors,pnpm test1056/1057 (the single failure is in A2'sbp-in-target.test.ts, out of bucket-1 scope).
- A1 removed the entire admin sub-list expansion from
Status block — Wave A bucket-3 (A4 + A5 + A8b)
- 2026-05-09T23:31:00+02:00 — A4 + A5 + A8b complete on origin/main.
- A4 "7-Tage-Trend" rename across DE/EN (
movingAverage7d,moodMA,trend7dShortall use the long form now), plussummaryToTrend7Delta()falls back toslope30whenslope7is null so sparser metrics like mood (logged < daily) show a delta number instead of dropping the indicator. Commit4df6dac. - A5 root-cause:
widgetIdEnuminsrc/app/api/dashboard/widgets/route.tswas missingachievements, so every PUT against the default layout 422'd silently and the toggle never persisted. ExtractedDASHBOARD_WIDGET_IDSas the single source of truth insrc/lib/dashboard-layout.tsand derived the Zod enum from it so the lists cannot drift again. Also hide the tile-strip wrapper when zero tiles are visible (Marc's "ganze Spalte breit, gleicher Höhe" constraint). Commit93e712d. - A8b chart trend on "All" filter rounded to ±0 because
per-week rate over multi-year windows falls below the
1-decimal display precision. Added pure
computeWindowTrend()helper atsrc/lib/analytics/window-trend.tsthat returns both the per-week delta and a split-half mean delta (second-half mean minus first-half mean) for windows ≥ 90 days. The chart now surfaces "Total +5.4 kg (6.7 %)" alongside the per-week rate on long ranges. 7 unit tests pin the helper. Commitaf77e5e. - Verification:
pnpm test1081/1081 (+32 net),pnpm typecheck0 errors,pnpm lint12 pre-existing warnings / 0 errors. Detailed report:.planning/phase-A4-A5-A8b-report.md.
- A4 "7-Tage-Trend" rename across DE/EN (
Status block — Wave-A verification gate
- 2026-05-10T00:08:00+02:00 — [x] Wave-A verification gate green, ready
for Wave B (gate-run sha
94c748d). Local clean clone passes typecheck (0 errors), lint (12 pre-existing warnings),pnpm test1153/1153,pnpm test:integration41/41. CI Security & Quality workflow consistently passes Wave-A commits. Integration + e2e CI workflows are pre-existing red (predate Wave A by hours; identical failure shape on v1.4.15 release commit0985c93); not a Wave-A regression.pnpm format:checkflags 34 .planning/docs/test files but is not in any CI workflow. Detailed report:.planning/phase-wave-a-gate-report.md.