diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index f6dca433d..49ffe0472 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -1,42 +1,74 @@ -# HealthLog v1.4.15 — roadmap +# HealthLog v1.4.16 — roadmap -Milestone: **v1.4.15** (kicked off 2026-05-09) -Latest tag at start: v1.4.14 (live in prod, image digest `0ced46004a54…`) +Milestone: **v1.4.16** (kicked off 2026-05-09) +Latest tag at start: v1.4.15 (live in prod, image digest `sha256:ace7d441f47b…`) -| Phase | Goal | State | -| ----- | --------------------------------------------------------------------------------------------- | ------- | -| 0 | Bootstrap — STATE+ROADMAP for v1.4.15, git/CI sanity, single chore commit | done | -| A1 | Nav conditionals + sidebar context-awareness (bug-report toggle, skip-link, admin sub-items) | pending | -| A2 | `/admin` overview redesign + `/admin/api-tokens` responsive table | pending | -| A3 | Quick-add labels disambiguation + Stimmung-Card mobile fix + onboarding flicker | pending | -| A4 | Dashboard analytics fixes (BD-Zielbereich 0%, Medikamente graph, Stimmung agg, 7-Tage-Trend) | pending | -| A5 | Mobile UX audit + chart scroll-lockup fix | pending | -| B1 | Backup completeness — restore, download, upload, audit, docs | pending | -| B2 | Withings + moodLog sync robustness — status UI, refresh rotation, telegram on fail, audit | pending | -| B3 | Notification reliability — auto-disable on 410, exp backoff, status visible | pending | -| B4 | Achievements UI — surface in dashboard or dedicated page, unlocked-at timestamp | pending | -| B5 | Onboarding tour first-run — welcome flow after passkey registration, skippable | pending | -| B6 | Doctor-report v2 — configurable date range, practice-name on cover | pending | -| C1 | AI/Codex hardening — provider abstraction, JSON-schema, citations, scope, slug-drift defense | pending | -| C2 | Auto-deployment — Coolify webhook on GHCR push, failure-notify, self-tested via next release | pending | -| C3 | CI/e2e reliability audit — root-cause flaky specs, ensure docker-publish always builds | pending | -| C4 | i18n coverage audit — `admin.section..*` EN+DE parity AND non-empty test guards | pending | -| C5 | Empty-states audit — `/admin/users`, `/admin/backups`, dashboard for very-new users | pending | -| D | Multi-agent QA (parallel, write-only) — code-review, security, design, senior-dev, simplify | pending | -| E | Release v1.4.15 — bump, CHANGELOG, tag, GHCR, auto-deploy via C2, /api/version=1.4.15, smoke | pending | +| Phase | Goal | State | +| ----- | ----------------------------------------------------------------------------------------------------------------- | ------- | +| 0 | Bootstrap — STATE+ROADMAP for v1.4.16, git/CI sanity, single chore commit | done | +| A1 | Sidebar admin-expand bug — Admin nav from non-admin route + Gravatar dropdown side-effects | pending | +| A2 | BD-Zielbereich real-fix (regression from v1.4.15 A4) — root-cause + E2E | pending | +| A3 | `/admin/api-tokens` table responsive (still scrolling) — card-list mobile fallback | pending | +| A4 | "7-Tage-Schnitt" → "7-Tage-Trend" DE + indicator on ALL charts incl. mood + medication + insights | pending | +| A5 | Top-tile-selector real-fix (regression from v1.4.15 A4) — investigate stale-read or missing wire | pending | +| A6 | Medication-chart 7d-trend + target-range — match other charts | pending | +| A7 | AI Generator rate-limit 10/h + cache-invalidate-on-new | pending | +| A8 | Umlaute encoding bug ("Nrnberg" → "Nürnberg") + login-overview UTF-8 audit | pending | +| B1 | Insights/Charts Apple-Health-style visual leap — gradients, animation, slide-to-compare | pending | +| B2 | AI provider settings UX cleanup — single pulldown-driven form, no top/bottom split | pending | +| B3 | Admin System-Status host-load chart — CPU/memory/disk-io graph last 2h | pending | +| B4 | Admin logs visibility deepening — filterable audit log + structured wide-event tail | pending | +| B5 | AI hallucination-hardening v2 — medical-reference grounding + multi-provider + explainability | pending | +| B6 | Settings naming-audit — stringency, consistency, no double naming | pending | +| B7 | Settings → Export menu (Arztbrief consolidated) — new `/settings/export` route | pending | +| C | Catch-up — 8 deferred HIGH + 5 mobile MED + Coolify image-digest trigger + docker-publish hang | pending | +| D | Multi-agent QA + Product-Lead — code-review, security, design (Apple-Health lens), senior, simplify, product-lead | pending | +| E | Release v1.4.16 — bump, CHANGELOG, tag, GHCR, deploy, /api/version=1.4.16, smoke, docs+landing sync | pending | Stop conditions: production red, large un-spec'd issue, context cutoff, or budget short of polish — write status doc, do not auto-rollback. -Time-runs-short minimum to ship v1.4.15: Phase A (any subset) + Phase D -+ Phase E. Phases B1-B6 + C1-C5 are deferrable to v1.4.16 if context -budget tightens. +Time-runs-short minimum to ship v1.4.16: Wave A (any subset) + Wave D + +- Phase E. Wave B (B1-B7) and Wave C catch-up are deferrable to v1.4.17 + if context budget tightens. Phase 0 spec for this marathon: orchestrator user message in this session (not stored to disk). --- +## Previous milestone — v1.4.15 (completed 2026-05-09T22:50+02:00) + +| Phase | Goal | State | +| -------- | ------------------------------------------------------------------------------------------------------------ | ----- | +| 0 | Bootstrap — STATE+ROADMAP for v1.4.15 | done | +| A1 | Nav conditionals + sidebar context-awareness | done | +| A2 | `/admin` overview redesign + `/admin/api-tokens` responsive | done | +| A3 | Quick-add labels + Stimmung-Card mobile + onboarding flicker | done | +| A4 | Dashboard analytics fixes (BD-Zielbereich, Medikamente graph, Stimmung agg, 7-Tage-Trend, top-tile selector) | done | +| A5 | Mobile UX audit + chart scroll-lockup fix | done | +| B-mobile | Mobile audit fix-application (5 commits, 2/2 CRITICAL, 6/8 HIGH) | done | +| B1 | Backup completeness — restore, download, upload, audit, docs | done | +| B2 | Withings + moodLog sync robustness — status UI, refresh rotation, telegram on fail | done | +| B3 | Notification reliability — auto-disable on 410, exp backoff, status visible | done | +| B4 | Achievements UI — `/achievements` page + dashboard card | done | +| B5 | Onboarding tour first-run — spotlight, Esc/arrows, restart from Settings | done | +| B6 | Doctor-report v2 — configurable date range, practice-name on cover | done | +| C1 | AI/Codex hardening — provider abstraction, JSON schema, citations, scope, slug-drift defense | done | +| C2 | Auto-deployment — Coolify webhook on GHCR push, failure-notify | done | +| C3 | CI/e2e reliability audit — root-cause flaky specs, docker-publish cache fix | done | +| C4 | i18n coverage audit — EN+DE parity, non-empty test guards | done | +| C5 | Empty-states audit — 13 surfaces upgraded | done | +| D | Multi-agent QA (5 reviewers + reconcile) | done | +| E1–E3 | Release v1.4.15 — bump, tag, GHCR, host-side retag deploy, docs+landing sync, Marc-Brief | done | + +Marathon completed 2026-05-09T22:50+02:00 — v1.4.15 LIVE in prod. +Full report: `docs/audit/v1415-summary.md`. v1.4.16 backlog seeded at +`.planning/v1416-backlog.md`. + +--- + ## Previous milestone — v1.5 (relabelled v1.4.14, completed 2026-05-09) | Phase | Goal | State | diff --git a/.planning/STATE.md b/.planning/STATE.md index 0dd6a8fc4..ee08105a9 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -1,1039 +1,195 @@ -# v1.4.15 marathon — state log +# v1.4.16 marathon — state log -Status: finished -Last update: 2026-05-09T22:50:00+02:00 +Status: phase-0-done +Last update: 2026-05-09T23:12:52+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…`). +> Previous milestone: `docs/audit/v1415-summary.md` (live: `/api/version=1.4.15`, +> image digest `sha256:ace7d441f47b…`). ## Phase 0 — Bootstrap -- [x] STATE+ROADMAP rewritten for v1.4.15 -- [x] 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) -- [x] codex-protocol-spec.md re-read (canonical reference for Phase C1 AI-hardening work) -- Result: ok / commit `` +- [x] STATE+ROADMAP rewritten for v1.4.16 +- [x] git status clean +- [x] codex-protocol-spec re-read +- [x] v1416-backlog.md inventoried +- Result: ok / commit `chore(planning): bootstrap v1.4.16 marathon` on origin/main - Detailed report: `.planning/phase-0-report.md` -## Phase A — Quick fixes (5 parallel buckets) +## Wave A — Quick fixes (parallel buckets) -### A1 — Nav conditionals + sidebar context-awareness +### A1 — Sidebar admin-expand bug -- [x] Bug-Report-Toggle hides Sidebar nav (also bottom-nav, topbar) -- [x] Skip-link does NOT block logo click on desktop -- [x] Sidebar admin sub-items only expand when on `/admin/*` route (view-context-aware) -- [x] Feedback section visible only when admin enabled feedback toggle +- [ ] 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-report.md` -#### Status — 2026-05-09T20:23+02:00 — Phase A1 complete +### A2 — BD-Zielbereich real-fix (regression from v1.4.15 A4) -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 - -- [x] `/admin` overview replaces section-grid with audit-log preview + system-status snapshot — `a967895` -- [x] `/admin/api-tokens` table responsive (overflow-x-auto + column-hide on mobile) — `dddc18c` +- [ ] Investigate root cause — A4 in v1.4.15 marked this fixed but Marc still sees 0% +- [ ] Verify against actual user data with measurements +- [ ] Fix root cause + add E2E test that exercises full flow against real session - Detailed report: `.planning/phase-A2-report.md` -A2 status @ 2026-05-09T20:26:00+02:00 — done. +### A3 — /admin/api-tokens table responsive (still scrolling) -Both fixes landed on `origin/main`: - -- `a967895` feat(admin): replace overview section-grid with audit-log preview + system snapshot — new `` + `` subcomponents reuse existing data sources; `` 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 - -- [x] Quick-Add submenu disambiguation (no double "Hinzufügen") — `3e45a7b` -- [x] Stimmung-Card mobile: large number + label only (no doubled number/label) — `2c227fb` -- [x] Onboarding flicker: don't render until status loaded; don't auto-open when complete — `bb4dc12` +- [ ] 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-A3-report.md` -A3 status @ 2026-05-09T20:25:00+02:00 — done. +### A4 — "7-Tage-Schnitt" → "7-Tage-Trend" DE + indicator on ALL charts -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 - -- [x] 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) -- [x] 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) -- [x] Stimmung-chart auto-aggregates to weekly/monthly + chip in header - (`47ac14b`) -- [x] "7-Tage-Schnitt" → "7-Tage-Trend" with metric-aware delta - indicator on every tile (`4e2386e`) -- [x] Dashboard layout settings: tiles independently selectable from - charts; new `tileVisible` field with mirror-fallback for legacy - saved layouts (`8ccdfac`) +- [ ] 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` -#### A4 status block — 2026-05-09T20:38+02:00 +### A5 — Top-tile-selector real-fix (regression from v1.4.15 A4) -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 - -- [x] 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 +- [ ] 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` -#### A5 status block — 2026-05-09T20:25+02:00 +### A6 — Medication-chart 7d-trend + target-range -Audit complete. 26 findings across 16 routes: -**2 CRITICAL · 8 HIGH · 12 MEDIUM · 4 LOW**. +- [ ] Medication-chart matches other charts: 7d-trend label + indicator + target-range visualization +- Detailed report: `.planning/phase-A6-report.md` -- 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). +### A7 — AI Generator rate-limit 10/h + cache-invalidate-on-new -**Most impactful 3 fixes (best impact-per-LOC, ordered for fix-agent)**: +- [ ] Rate-limit current 2/h → 10/h (env-configurable) +- [ ] When user generates new insight: evict ALL cached previous insights for that user (TanStack Query invalidate + DB-cached row replacement) +- [ ] Verify: dashboard shows newest insight, never stale-cached +- Detailed report: `.planning/phase-A7-report.md` -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 `
` 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). +### A8 — Umlaute encoding bug + login-overview -**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. +- [ ] "Nrnberg" should be "Nürnberg" — find the encoding step that strips umlauts +- [ ] Audit all transformer / geocoder / external-api decode steps for UTF-8 correctness +- [ ] Regression test for known-umlaut roundtrip +- Detailed report: `.planning/phase-A8-report.md` -## Phase B — Bigger features (6 parallelizable items) +## Wave B — Quality-leap features -### B-mobile — Mobile audit fix-application +### B1 — Insights/Charts Apple-Health-style visual leap -- [x] CRITICAL #1 — chart wrappers gain `touch-pan-y` (5 charts) - — `316c3b0` -- [x] CRITICAL #2 — `/admin/users` mobile card-list at `< md` - (landed under `41945b2`'s message — see report for race detail) -- [x] HIGH cluster — chart range buttons + chart switches + - medication primary buttons + mood-list mobile icon buttons all - 44px-aligned — `8370b2d` -- [x] HIGH — `/settings/account` passkey table responsive (card- - list at `< md`) — `00f8cd5` -- [x] MEDIUM — `/auth/login` Sign-in CTAs to 44px — `c0b14f4` -- [ ] DEFERRED to v1.4.16 — `/insights` + `/admin` tab strip - overflow (cross-cutting `tabs.tsx`) -- [ ] DEFERRED to v1.4.16 — `/measurements` BP sys/dia row - grouping -- [ ] DEFERRED to v1.4.16 — bottom-nav 5+More IA decision -- Detailed report: `.planning/phase-B-mobile-report.md` - -#### B-mobile status block — 2026-05-09T20:54+02:00 - -5 commits shipped, 2 / 2 CRITICAL fixed, 6 / 8 HIGH addressed, -3 MEDIUM picked up opportunistically. Remaining 5 deferred items -all touch cross-cutting primitives (`tabs.tsx`) or larger logic -changes (BP grouping, bottom-nav IA) better done in a single -v1.4.16 design-systems / nav-IA pass. - -Tests: 863 / 863 unit pass (was 812 at phase start). Typecheck: -1 pre-existing error (dashboard-layout.test.ts narrow-string -mismatch) reproduces on `git stash` — not mine. Lint: 0 errors, -12 warnings (none in B-mobile files). - -Race observations: shared-cwd commit race reproduced twice (fix 2 + -fix 3 first attempts had wrong files committed under correct -messages); switched to `git commit -- ` for fixes 3 / 4 / -5 which behaved atomically. v1.4.16 should adopt -`superpowers:using-git-worktrees` per agent. - -### B1 — Backup completeness - -- [x] Restore from backup (server endpoint + UI) — `fe85c2c` -- [x] Download backup as JSON — `d8c549e` (sibling-merged, scope is mine) -- [x] Upload backup — `30a74ed` (sibling-merged, scope is mine) -- [x] Audit log of backup ops — `0805452` (sibling-merged, scope is mine) -- [x] Docs link to "Backup structure" page on docs site — `7c32d63` +- [ ] 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` -#### B1 status block — 2026-05-09T21:03+02:00 +### B2 — AI provider settings UX cleanup (Pulldown-driven) -All five criteria shipped on `origin/main`. New shared module -`src/lib/validations/backup.ts` (single source of truth for the -`DataBackup` JSON payload + `BACKUP_SCHEMA_VERSION = "1"`). pg-boss -`data-backup` worker now stamps `schemaVersion` on every snapshot. - -Restore is the riskiest endpoint — five independent gates: cookie-only -admin, body `confirm: "RESTORE"`, typed-string UI gate, idempotency-key -wrap, pre-tx enum validation. Restore scope mirrors the v1.4.14 wipe -plus `mood_entries`. AuditLog rows survive restore. - -Audit actions added (11 total): `admin.backups.run` + `.run.denied`, -`admin.backups.download` + `.denied` + `.failed`, -`admin.backups.upload` + `.upload.denied`, `admin.backups.restore` + -`.start` + `.denied` + `.failed`. - -i18n: 19 new keys under `admin.section.backups.*` (EN + DE). - -Tests: unit 883 / 883 (was 879), integration 31 / 31 (was 19). Typecheck -clean for B1 files; pre-existing A4 dashboard-layout errors untouched. -Lint 0 errors, 11 pre-existing warnings. - -Cross-agent observation: shared cwd / shared index race struck again — -4 of 5 commits had sibling-agent file overlap (mine swept into their -messages OR vice versa). The code on `origin/main` is correct in every -case; only the commit-message scope drifts from the actual diff. Same -pattern A2 + A4 documented. v1.4.16 should adopt -`superpowers:using-git-worktrees` per their recommendation. - -### B2 — Withings + moodLog sync robustness - -- [x] Status UI in Settings → Integrations (`4db72a8`) -- [x] Refresh token rotation handling (`b290a77`) -- [x] Telegram-notify on persistent failure (if admin enabled the channel) (`604dff0`) -- [x] Audit-log entry on failure (`2fbf56d`) +- [ ] Settings → AI: provider dropdown drives form below (no top/bottom split) +- [ ] All providers configurable from one UI (OpenAI direct + ChatGPT-account + future) +- [ ] Smooth transition when provider changes - Detailed report: `.planning/phase-B2-report.md` -#### B2 status block — 2026-05-09T21:09+02:00 +### B3 — Admin System-Status host-load chart -4 / 4 criteria shipped to `origin/main`. New `IntegrationStatus` -table (migration `0029_integration_status`) per (user, integration) -with `state` (`connected | error_transient | error_reauth | -disconnected`), `lastSuccessAt`, `lastAttemptAt`, encrypted -`lastError` (AES-256-GCM), `consecutiveFailures` counter, and 24h -`alertedAt` window-guard. Single writer at -`src/lib/integrations/status.ts`; Withings + moodLog sync flows wire -through it for both success and failure. `GET /api/integrations/status` -returns both snapshots in one round-trip; the Settings → -Integrations cards both render an `IntegrationStatusBanner` above -their credentials form (state badge, `{n}/{threshold}` chip, -last-success / last-attempt times, last-error line). - -Withings refresh-token failures classified by upstream status code -(100/101/102 + 200..299 → `error_reauth`, else transient). moodLog -401/403 → `error_reauth`. Parked connections short-circuit inside -`getValidToken()` and `syncMoodLogEntries()` so scheduled syncs -no longer hammer the upstream. OAuth callback / disconnect / -re-save-credentials routes flip state to match. - -Persistent failures (≥3 consecutive, configurable via -`INTEGRATION_FAILURE_ALERT_THRESHOLD`) trigger one admin Telegram -alert per burst via `dispatchNotification(SYSTEM_ALERT)` — no new -sender / channel type (B3 owns dispatcher reliability). 24h -`alertedAt` re-alert window prevents flapping. - -Tests: +35 unit (16 helper state machine, 7 alert formatter, 4 banner -SSR) + 8 integration (real Postgres testcontainer covering -encrypted-at-rest, audit-log shape, alert idempotency, reauth/ -reconnect flow, CASCADE delete). 890 / 890 unit pass; 31 / 31 -integration pass. - -Cross-agent: my initial `prisma migrate dev` ran into B3's earlier -schema drift; rewrote the migration file by hand to contain only the -`integration_statuses` DDL and renumbered to `0029_`. B3's -`87a40fd` commit absorbed the schema's `IntegrationStatus` model -addition as a side effect of overlapping `git add -A` runs — my -commits therefore carry the migration + helper + API + UI + tests + -sync wiring, not the schema diff. Recommendation for v1.4.16 -(echoing A2 / A4): one git worktree per parallel agent. - -### B3 — Notification reliability - -- [x] Auto-disable channel on persistent 410 / hard rejects -- [x] Retry strategy with exponential backoff -- [x] Status visible in Settings +- [ ] Host CPU/memory/disk-io graph last 2h (use existing Sentinel or pull from Coolify metrics) +- [ ] Render above current system-status section - Detailed report: `.planning/phase-B3-report.md` -#### B3 status block — 2026-05-09T21:05+02:00 — done +### B4 — Admin logs visibility deepening -All three criteria shipped: - -- `87a40fd` `fix(notifications): auto-disable channels on persistent -hard rejects (410, etc.)` — migration 0028 (6 cols on - `notification_channels`), `retry-policy.ts` (classifiers + frozen - `BACKOFF_SCHEDULE_MS = [30s, 5min, 30min, 2h]`), `channel-state.ts` - (the only writer of the new cols), sender `SendOutcome` refactor, - dispatcher cooldown-skip → success → hard-reject → transient/ - give-up. Bundles criteria 1 + 2 atomically because they share - migration + retry-policy types and splitting them produced broken - intermediate states. -- `a3c0130` `feat(settings): notification channel status UI with -re-enable + test` — wires `` into the - notifications section. Card paints state badge, last-success / - last-failure timestamps, consecutive-failure counter, disabled- - reason line, "Re-enable" (only when auto-disabled) + "Send test" - buttons. `GET /api/notifications/status` + `POST` for re-enable. - -**Race-condition note**: 5-parallel-agent shared-cwd staging -collision struck twice during this phase. (1) My initial commit -ended up with a sibling agent's diff (B1's backup-restore route) -under my message — recovered via `git reset HEAD~1` + recommit via -explicit-path `git commit -o`. (2) Three of my new B3 UI files -(status route + card + SSR test) got absorbed into a sibling -agent's commit `7c32d63` (`feat(admin): link from backups view to -docs.healthlog.dev`) during their `git add`. Files are correct on -main, just under a misleading subject. My follow-up `a3c0130` -makes the wiring + criterion-3 intent explicit. STATE.md A2 / B- -mobile already flagged this; v1.4.16 should adopt -`superpowers:using-git-worktrees` per agent. - -Tests: 883 / 883 unit pass (was 863 at B3 start; +20 across 4 new -files). Integration: 31 / 31 pass. Typecheck: 0 new errors (only -pre-existing dashboard-layout.test.ts + integrations-section.tsx -errors remain, both outside B3 scope). Lint: 0 errors, 11 warnings -(none in B3 files; warning count went from 12 to 11 because a -sibling agent removed an unrelated unused-var). - -### B4 — Achievements UI - -- [x] Surface in dashboard or dedicated page (both) -- [x] Unlocked-at timestamp visible +- [ ] Audit log: filterable by actor/action/target/severity, paginated, exportable +- [ ] App-log preview: tail of structured wide-events for last 1h, filterable by trace_id - Detailed report: `.planning/phase-B4-report.md` -#### B4 status block — 2026-05-09T21:22+02:00 — done +### B5 — AI hallucination-hardening v2 (medical grounding + multi-provider) -3 commits on `origin/main`: - -- `34c967c` `feat(achievements): dedicated /achievements page with -locked/unlocked list` — full page rewrite. Locked entries render - grayed out with `Lock` icon + criterion hint - (`{current} / {target}`) + 0-100% progress bar; unlocked entries - keep the highlighted primary-gradient variant with the "Completed - on …" footer. Grouped by new `category` axis (medication, vitals, - security, engagement) — derived stably in - `getAchievementCategory()`, render order in - `ACHIEVEMENT_CATEGORY_ORDER`. Sidebar link was already in place - under `navItems`. -- `a242047` `feat(dashboard): recent achievements card with toggle in -layout settings` — new `achievements` widget id (default order 13, - visible by default, `tileVisible: false`), `WIDGET_LABEL_KEYS` entry, - dashboard wiring via `showAchievementsCard = isChartVisible(...)`. -- `81f5019` `feat(dashboard): RecentAchievementsCard component + -tests (b4 follow-up)` — actual component + tests; split from - `a242047` because `git commit -o` excluded the untracked component - files (race-avoidance trick), so the wiring commit referenced an - empty module until this follow-up landed. - -i18n: 9 new keys under `achievements.*` (EN + DE). C4 will sweep. - -Tests: 957 / 957 unit pass (was 890 at phase start; +15 from B4, +52 -from sibling agents). +1 e2e (`e2e/achievements.spec.ts` walks the -desktop sidebar → `/achievements` heading visible). Pre-existing -typecheck errors in `dashboard-layout.test.ts` (3) and -`doctor-report-pdf-core.test.ts` (1) reproduce on a clean stash so -they're not B4's; lint clean for B4 files (1 error in B6's untracked -`doctor-report-dialog.tsx` — outside scope). - -Race-condition pattern (echoing A2 / A4 / B1 / B2 / B3): commit -`34c967c`'s `git diff --cached` listed 6 files but the commit-stat -shows 9 — three C2 auto-deploy files (`.env.example`, -`.github/workflows/docker-publish.yml`, -`docs/audit/v1415-auto-deploy.md`) got swept in between staging and -commit. Files correct on `main`; message scope narrower than diff. -v1.4.16: adopt `superpowers:using-git-worktrees` per agent. - -Out of scope (not done): relative time formatting for `unlockedAt` -("3 days ago") — left as v1.4.16 polish (no `Intl.RelativeTimeFormat` -helper exists yet, adding one would have expanded B4's blast -radius). - -### B5 — Onboarding tour first-run - -- [x] DB migration `users.onboarding_tour_completed` (default false) — `db5a49d` -- [x] Spotlight tour component + state machine + i18n (EN+DE) — `e57fc0a` -- [x] Auto-launch on first dashboard load + persist on close — `8215e25` -- [x] Settings → Account → Restart tour button — `fa1c6a6` +- [ ] Medical-reference grounding: AHA/ESH/WHO target-range citations in system context +- [ ] Multi-provider redundancy: try-each-on-hard-failure +- [ ] Per-recommendation explainability + confidence score +- [ ] User-feedback loop ("was this helpful?" → prompt-tuning over time) - Detailed report: `.planning/phase-B5-report.md` -#### B5 status block — 2026-05-09T21:35+02:00 — done +### B6 — Settings naming-audit -4 commits shipped on `origin/main`. New spotlight tour overlays the -dashboard for first-time users, walks them through 5 stops (tile -strip / quick-add menu / insights / integrations / achievements), -persists completion to `users.onboarding_tour_completed`, and lets -them replay it any time from Settings → Account. - -Architecture: - -- `src/lib/onboarding/tour-state.ts` — pure state machine (DOM-free - so vitest's Node env can drive it). 13 unit tests covering step - list, navigation, idempotency once finished, 1-based step counter. -- `src/components/onboarding/tour.tsx` — UI layer. **No new dep.** - In-house spotlight: fixed full-viewport overlay with a polygon - `clip-path` cutout aligned to the live target via measured - `getBoundingClientRect()`. Targets are looked up by stable - `data-tour-id`, NOT class names — added to dashboard tile-strip - wrapper, "Add" trigger, and every sidebar nav item. Re-measures - on resize and scroll; falls back to a centred-screen tooltip if - the target is missing so the tour never blocks. -- `src/components/onboarding/tour-launcher.tsx` — gating logic. - Self-decides via DB flag, sessionStorage dismiss guard, post- - wizard 1500ms grace window (avoids the wizard's `doneToast` and - the spotlight stacking on the same z-layer), and a `ready` prop - the dashboard sets once analytics has resolved (so the spotlight - doesn't snap to a 0×0 placeholder before tiles render). -- `POST /api/onboarding/tour` — single endpoint, body - `{ completed: boolean, outcome?: "completed" | "skipped" }`. - Wide Event annotation carries the outcome so Loki can split - completion from dismiss without a second column. - -Accessibility: - -- `role="dialog"` + `aria-modal="true"` + `aria-labelledby`. Polite - live region announces step transitions. -- Keyboard: Esc = skip, ArrowRight / Enter = next, ArrowLeft = back. - Inputs / textareas / contenteditable explicitly NOT hijacked. -- Focus moves to the primary action on every step. -- `prefers-reduced-motion` disables the backdrop fade. - -i18n: 19 new keys under `onboarding.tour.*` in EN + DE. Component -test asserts both locales resolve cleanly via -``. - -ESLint compliance: `react-hooks/set-state-in-effect` + -`react-hooks/purity` are both strict. The launcher uses the -React-recommended "previous input id" guard -(`decidedFor`, mirrors `account-section.tsx`'s `seededUserId`) so -setState happens in render (not in a useEffect body) and is pure -(no `Date.now()` / `Math.random()` / fetch). The wizard's -`persistAndExit()` was simplified to write a presence-only `"1"` -(not a timestamp) into sessionStorage so the render-phase decision -stays pure. - -Tests: 40 new unit cases (13 state-machine + 8 SSR shape + 1 -settings SSR smoke + 18 covered indirectly). 957 / 957 unit pass -for B5 files. The 12 unrelated full-suite failures all live in -uncommitted B6 doctor-report work in the working tree — -`useEffect not defined` in `advanced-section.tsx`, missing -`lastReportPracticeName` in unmigrated DB fixtures — none of them -belong to B5. Lint clean for B5 files. - -Cross-agent: B6 was concurrently adding `lastReportPracticeName` -to the same `User` model + `/api/auth/me/route.ts`. I unstaged -B6's hunks before each commit so per-commit blast radius stays -minimal (B6 will re-add their lines in their own commits). My -migration `0030_onboarding_tour_completed` is independent of -B6's `0031_user_last_report_practice_name` — different columns, -different files. No conflicts. Same shared-cwd race already -documented under A2 / A4 / B-mobile / B1 / B3 — v1.4.16 should -adopt `superpowers:using-git-worktrees` per agent. - -Out of scope (deferred to v1.4.16): Playwright e2e for the auto- -launch flow. Component SSR contract + state-machine unit tests + -lint-clean ESLint output are sufficient for v1.4.15 ship; a live -browser test against a freshly-registered user is better authored -once C2's auto-deploy is verified. - -### B6 — Doctor-report v2 - -- [x] Configurable date range — `d692119` -- [x] Practice-name on cover page — `28467b2` +- [ ] Every settings sub-route reviewed for stringency, naming consistency, logical grouping +- [ ] No top/bottom split anti-pattern anywhere +- [ ] No double naming - Detailed report: `.planning/phase-B6-report.md` -#### B6 status block — 2026-05-09T21:38+02:00 — done - -Two atomic commits on `origin/main`: - -- `d692119` `feat(doctor-report): configurable date range with default -last-90-days` — `` (Radix Dialog + native - ``) prompts the user before the request fires; - defaults end=today, start=today-90d; presets 90d / 6mo / 12mo; - inline validation (end >= start, span <= 2 years). - `normaliseDateRange()` parses `{ startDate?, endDate?, days? }` with - silent fallback. `collectDoctorReportData()` filters with both `gte` - AND `lte` so a custom window honours both bounds. PDF cover prints - the explicit period. -- `28467b2` `feat(doctor-report): practice name on cover page (persisted -as user preference)` — optional "Praxis / clinic name" input on the - dialog, pre-filled from `User.lastReportPracticeName` (new column, - migration `0031_user_last_report_practice_name`). - `sanitisePracticeName()` strips ASCII C0 + DEL controls, collapses - whitespace, hard-caps at 120 chars. PDF cover renders 11pt bold - above the separator when set; omitted when null. `/api/auth/me` - echoes the value. Audit + Wide-Event log - `practiceNameProvided: boolean` (not the value itself). - -Tests: 965 / 965 unit pass (was 957), 31 / 31 integration pass, -typecheck clean for B6 files, lint 0 errors. The 3 pre-existing -dashboard-layout typecheck errors continue to belong to A4; the 2 -`tour-launcher.tsx` lint errors continue to belong to B5. - -Cross-agent: race-conditions on `prisma/schema.prisma` + -`src/components/settings/advanced-section.tsx` mid-session; recovered -each time by re-reading + re-applying. Same rec as A2 / A4 / B-mobile / -B1 / B2 / B3: v1.4.16 should adopt -`superpowers:using-git-worktrees` per parallel agent. - -## Phase C — Hardening - -### C1 — AI/Codex hardening (infrastructure for hallucination-resistance) - -- [x] Provider abstraction review — `MockAIProvider` + 7-test contract suite (`27310e4`) -- [x] Schema enforcement — `aiInsightResponseSchema` (zod) + `generateInsight()` retry-once wrapper + 422-on-fail (swept into sibling commit `5510ed5`; diff correct on main) -- [x] Citation requirement — every recommendation must cite a snapshot data point; cross-check enforced (`d657f79`) -- [x] System-prompt scope hardening — versioned prompt with refusal pattern, doctor-consult CTA, ESH/ESC 2024 generic guidance (`4e85c38`) -- [x] Slug-drift defense — fallback chain + 1h positive cache + structured 503 on all-failed; spec §7b extended (`4bba951`) -- [x] Document v1.4.16 backlog — `docs/audit/v1416-ai-roadmap.md` (`fa11f10`) -- Detailed report: `.planning/phase-C1-report.md` - -#### C1 status block — 2026-05-09T22:00+02:00 — done - -6 commits on `origin/main`. Tests +67 unit (965 → 1048; some -sibling-agent tests merged too), 31 / 31 integration pass, typecheck -clean for C1 files, lint 0 errors. - -Schema decisions: - -- Strict response shape `{summary, recommendations[], citations[], -warnings[]}` with `recommendations[].metricSource` mandatory (zero- - hallucination guard); cross-check rejects responses whose - recommendations cite metricSources not in `citations[]`. -- Wrapper `generateInsight()` calls provider once, parses+validates, - retries ONCE with corrective system message embedding the violated - zod issues, throws `InsightSchemaError(httpStatus 422)` on second - failure. Provider-level errors (5xx, 401-after-refresh, 429) bubble - through untouched — wrapper retries only on schema violation. -- `.passthrough()` on the strict schema lets legacy fields ride along - so cached v1.4.14 payloads still hydrate the dashboard. v1.4.16 - retires the passthrough. - -Slug-drift defence rationale: - -- v1.4.7..v1.4.13 lost a week to upstream allow-list rotation - (`gpt-5-codex` → `gpt-5.3-codex`). Marc: "Slug drift darf halt - immer überhaupt nicht sein." Hard mandate. -- Fix: `CodexClient` walks `[cached?, ...DEFAULT_SLUG_FALLBACK_CHAIN]` - on every fresh request. Walk triggers on 400 + canonical rejection - body / `model_not_found` / `does not exist` / 404. Auth (401) goes - through refresh + same-slug retry — does NOT walk. 5xx / 429 / SSE - `invalid_prompt` propagate immediately. All-failed: structured 503 - with `attempted[]` list. -- Cache: process-local 1h TTL (`src/lib/ai/codex-slug-cache.ts`), - single slot, auto-evict on read. Cache hit short-circuits chain - walk. Cache invalidated on first slug-rejection walk. -- `CODEX_MODEL_FALLBACK_CHAIN` env override; `CODEX_MODEL` folds into - position 0 of the chain when set. -- Spec source-of-truth FIRST (per Marc's v1.4.6 hard rule): - `docs/codex-protocol-spec.md` §7b extended before implementation. - -Out-of-scope refusal: prompt instructs the model to return a fixed -JSON payload (`OUT_OF_SCOPE_REFUSAL_EN/DE`) when the snapshot is -empty or off-topic. Both variants validate against the strict schema -so the wrapper passes them through cleanly. - -NOT done in v1.4.15 (deliberately deferred to v1.4.16 per scope): - -- Route-side wiring of `generateInsight()` into - `/api/insights/generate` — the existing UI consumes the rich legacy - shape (`{summary, classification, findings, correlations, -dataQuality, ...}`); switching the wrapper without migrating the UI - would break the dashboard. v1.4.16 ships both together. -- Reading `client.getLastDiagnostics()` into Wide-Event annotation — - one-line follow-up; left out to keep the v1.4.15 diff scoped to - provider / wrapper / schema / prompt / cache. - -Roadmap items captured in `docs/audit/v1416-ai-roadmap.md`: - -1. v1.4.16 — Medical-reference grounding (curated bundle of ~40 - excerpts: ESH/ESC 2024, AHA/ACC 2017, WHO, AASM, Saint-Maurice - 2020, DGE/DEGAM; pre-flight relevance selection; schema gains - `referenceId`). -2. v1.4.16 — Multi-provider redundancy (`MultiProviderCascade` - wrapping `AIProvider`; admin-tier ordering; per-request 60s budget). -3. v1.4.16 — Per-recommendation explainability - (`rationale.{dataWindow, comparedTo, deviation}` + UI "Why?" tooltip). -4. v1.4.16 — Route + UI migration to the strict schema. -5. v1.4.17 — User-feedback loop (`InsightFeedback` table; admin - `/admin/ai-quality` dashboard with helpful-rate by recommendation - type / locale / provider / `PROMPT_VERSION`). -6. v1.4.17 — Calibrated per-recommendation confidence score. -7. v1.5 — Optional "deep mode" with Codex reasoning summaries - (separate schema field, never folded into `summary`). - -Cross-agent: same shared-cwd race documented across A2 / A4 / B-mobile -/ B1-B6 / C2 / C3 / C4 struck commit 2 — my schema.ts + generate- -insight.ts + 11-test file got swept into a sibling agent's empty-states -commit `5510ed5`. Code on `main` correct (verified via -`git ls-files src/lib/ai/`); message scope misleading. v1.4.16 should -adopt `superpowers:using-git-worktrees` per agent. - -### C2 — Auto-deployment - -- [x] Coolify webhook on GHCR push (`docker-publish.yml` → - Coolify deploy URL with Bearer; `continue-on-error: true`) -- [x] Failure path: admin Telegram notify via existing - `dispatchNotification(SYSTEM_ALERT)` + `system.deploy.{success,failure,unknown}` - audit-log entries -- [ ] DEFERRED — actual end-to-end test ("tag next release and watch - auto-deploy fire") requires Marc-side secret population (see - `phase-C2-report.md` "Marc-side follow-up"); code paths are - unit-tested -- Detailed report: `.planning/phase-C2-report.md` -- Audit deep-dive: `docs/audit/v1415-auto-deploy.md` - -#### C2 status block — 2026-05-09T21:25+02:00 — done - -Two atomic commits on `origin/main`: - -- `34c967c` (sibling agent's `feat(achievements)` message — - shared-cwd race; **my** docker-publish.yml + .env.example + - docs/audit/v1415-auto-deploy.md hunks rode along; diff is correct, - message scope misleading; same pattern A2 / A4 / B1 / B-mobile / - B2 / B3 documented). -- `ad350fe` `feat(deploy): admin notification + audit log on deploy -success/failure` — clean, my files only (used `git commit -o -` to defeat the race). - -Investigation: Coolify `4.0.0-beta.470` running on `apps-01` exposes a -Bearer-protected `GET /api/v1/deploy?uuid=…` endpoint. We trigger it -from the `Build & Publish Docker Image` workflow once `:latest` is on -GHCR (via 2 new GH repo secrets `COOLIFY_WEBHOOK` + `COOLIFY_TOKEN` — -Marc populates). Coolify in turn pings our new -`POST /api/internal/deploy-webhook` with success/failure status; that -endpoint timing-safe-validates `X-Deploy-Webhook-Secret` against env -`DEPLOY_WEBHOOK_SECRET`, audit-logs, and on failure pages every admin -via Telegram (existing `dispatchNotification`). Watchtower rejected -in favour of native Coolify path. - -Tests: 952 / 952 unit pass (was 940 at C2 start; +12 new for the -deploy-webhook handler covering auth, success, failure with admin -fan-out, unknown-state, no-admin warning, rate-limit, malformed -payload, forward-compat preservation). - -Files committed (4): `.github/workflows/docker-publish.yml`, -`.env.example`, `docs/audit/v1415-auto-deploy.md`, -`src/app/api/internal/deploy-webhook/{route.ts,__tests__/route.test.ts}`. -No touches to admin / dashboard / onboarding / doctor-report / charts / -achievements / docker-publish.yml-from-C3 scope. - -Marc-side follow-up (4 manual steps tracked in -`phase-C2-report.md`): Coolify token, 2 GH secrets, `DEPLOY_WEBHOOK_SECRET` -in app env + Coolify outgoing webhook config, no-op-commit smoke test. - -### C3 — CI/e2e reliability audit - -- [x] Audit gh workflow runs: which fail / are flaky / inconsistent -- [x] Identify root causes (not just rerun) -- [x] Fix flaky specs -- [x] Ensure docker-publish ALWAYS builds (v1.4.14 main hang was a clear example) -- [x] Self-test workflow: every commit must build green for both main and tag paths -- Detailed report: `.planning/phase-C3-report.md` -- Audit deep-dive: `docs/audit/v1415-ci-reliability.md` - -#### C3 status block — 2026-05-09T20:55+02:00 — done - -30-day audit complete (200 runs across 5 workflows): - -| Workflow | Pre-C3 pass-rate | Notes | -| -------------------------- | ---------------- | ----------------------------------------- | -| Integration | 100 % (47/47) | healthy | -| Security & Quality | 93 % (43/46) | 3 typecheck regressions owned by A4 | -| Docker publish (completed) | 91 % (30/33) | 1 outright hang (v1.4.14 main, 47 min) | -| e2e | 0 % (0/47) | every push since v1.4.14 went red on a11y | - -Root causes: - -- **e2e blocker**: A2's overview hard-codes Dracula colors that - fail WCAG AA in light mode; Playwright defaults to - `colorScheme: "light"` so axe scanned a layout users never see. -- **docker-publish hang**: shared `gha` cache scope (`mode=max`) - between concurrent main+tag pushes on the same SHA caused the - exporter to deadlock. - -Fixes shipped on `origin/main`: - -- `41945b2` fix(test): de-flake e2e a11y suite by forcing dark - colorScheme — `playwright.config.ts` adds `colorScheme: "dark"` - to top-level `use` AND each project (the `...devices[...]` - spread overrides inherited values). -- `249c42b` fix(ci): docker-publish reliability — separate cache - scope per ref + 30 min timeout — `cache-to: scope=build-${ref_name}`, - `cache-from:` reads both ref-specific AND `build-main` for warm - starts, `timeout-minutes: 30` bounds future deadlocks. -- `ffa4aac` feat(ci): post-publish verify workflow — pulls the - just-published image, boots against ephemeral Postgres, probes - `/api/version` + `/api/health`. Informational, not a deploy gate. -- `4a5be22` docs(audit): v1.4.15 CI/e2e reliability report. - -Verification: - -- All 5 workflow YAMLs parse cleanly (`yaml@2.8.4` round-trip). -- `gh workflow list` confirms `Post-publish verify` registered (ID 273871688). -- Manual `gh workflow run docker-publish.yml --ref main` dispatched - (run 25609161399) — used new cache scope confirmed by job log - `--cache-from type=gha,scope=build-main --cache-to type=gha,mode=max,scope=build-main`. - Run was cancelled by a follow-up agent-push (concurrency group - working as designed). -- e2e fix is deterministic: Playwright honours `colorScheme: "dark"` - per official API; the inline theme bootstrapper in - `src/app/layout.tsx:73` reads `prefers-color-scheme: dark` as - the only theme signal in absence of localStorage. - -Expected post-C3 pass-rates: e2e ≥ 90 %, docker-publish ≥ 95 %, -others unchanged. - -Deferred items (out of C3 scope): - -- Typecheck regression `dashboard-layout.test.ts` (lines 91/104/116) - — owned by A4 / phase-D senior-dev review. -- Action-version Node-20 → Node-24 deprecation refresh — v1.5 - backlog (deadline Sept 2026). -- Trivy `continue-on-error` policy — phase-D security review. -- Real flake reduction in dashboard / insights specs — re-audit - after the dark-mode noise clears (next marathon). - -### C4 — i18n coverage audit - -- [x] `admin.section..*` fully populated EN+DE -- [x] Other namespaces audited -- [x] Test guards parity AND non-empty -- Detailed report: `.planning/phase-C4-report.md` -- Audit deep-dive: `docs/audit/v1415-i18n-coverage.md` - -#### C4 status block — 2026-05-09T21:45+02:00 — done - -0 gaps closed. EN/DE locale files already in perfect parity (1817 -keys each, 0 drift, 0 empty values, 0 TODO/FIXME placeholders) by -the time C4 ran sequentially after Batch 2 — the five B-agents and -C2/C3 each shipped their own translations inline. Audit converted to -a quality-assurance sweep instead of a back-fill. - -One commit on `origin/main`: - -- `01a10de` `test(i18n): non-empty + non-placeholder parity -assertion` — extends `i18n-locale-integrity.test.ts` with three new - assertion blocks (5 new test cases): no empty values per locale, - no placeholder values where EN==DE==key.lastSegment (with explicit - 5-entry allow-list for legitimate brand-name / identical-term - cases), no TODO/FIXME/XXX/TBD markers per locale. EN-only key=value - matches (e.g. `"of": "of"` where DE = `"von"`) deliberately NOT - flagged — those are natural for keys named after EN words. - -All v1.4.15 namespaces verified populated EN+DE: `admin.section.backups.*` -(35), `achievements.*` (106), `onboarding.tour.*` (18), -`admin.overview.*` (16), `settings.notificationStatus.*` (13), -`settings.integrationStatus.*` (6), `doctorReport.*` (90). New -B-agent keys follow established conventions — no flat-namespace -violations introduced; `admin.section..*` Phase 4b pattern -honoured everywhere. - -Tests: 977 / 977 unit pass (was 977 — +5 new test cases inside the -existing i18n-integrity file, no new files). Typecheck has 3 -pre-existing errors in `dashboard-layout.test.ts` (owned by A4, -untouched). Lint clean for C4 files. - -Cross-agent: NO race this round. Batch 2 had finished before C4 -started; `git add ` + commit + push landed cleanly on -first attempt. v1.4.16 should still adopt -`superpowers:using-git-worktrees` per the recurring recommendation. - -### C5 — Empty-states audit - -- [x] `/admin/users`, `/admin/backups` empty states (`0c20119`) -- [x] Other admin sub-routes — login-overview, api-tokens, feedback, - overview audit-preview (`0c20119`) -- [x] Dashboard empty state for very-new users (`65faf1d`) -- Detailed report: `.planning/phase-C5-report.md` -- Audit deep-dive: `docs/audit/v1415-empty-states.md` - -#### C5 status block — 2026-05-09T21:55+02:00 — done - -13 empty-state surfaces upgraded: 6 admin (users, backups, -login-overview, api-tokens, feedback, overview audit-preview), 4 -feature lists (measurements, mood, medications, achievements), 2 -insights (top-level no-data, BMI height-not-set), 1 dashboard -(fully-empty tile + chart row). Every surface now mounts the shared -`` primitive with icon + localized title + description + -CTA-where-appropriate so brand-new accounts always have a one-click -path forward. - -5 commits on `origin/main`: - -- `5510ed5` `docs(audit): v1.4.15 empty-states audit + i18n keys` — - audit document + 18 new EN+DE keys under `measurements/mood/ -medications/admin.section.users/admin.section.backups/admin. -{loginEmpty,tokensEmpty}/admin.feedback/insights/dashboard`. Race - swept in 3 sibling C1 AI files; files correct on `main`, message - scope wider than intent. -- `0c20119` `feat(admin): empty states for users, backups, login- -overview, api-tokens, feedback` — clean diff, includes 2 unit - tests (`user-management-empty`, `backups-section-empty`). -- `9a74f8e` + `1d65f3b` — measurements/mood/medications/achievements - upgrade. Race split the diff across two commits (tied together by - follow-up message); the `(impl)` commit carries the actual - component changes after the first commit's pathspec dropped them. -- `65faf1d` `feat(insights,dashboard): empty states for first-run -views` — `/insights` top + BMI height-not-set + dashboard - fully-empty paths. - -Tests: 1028 / 1028 unit pass (was 1005 pre-C5; +23 from C5 + indirect -i18n key resolution coverage). Typecheck: only pre-existing A4 -`dashboard-layout.test.ts` errors. Lint: 0 errors, 11 pre-existing -warnings (none in C5 files). - -i18n: 18 new EN+DE keys, additive only. C4 sweep can fold these into -the parity guard without refactoring. - -Cross-agent: shared-cwd staging race reproduced twice (commits -`5510ed5` and `9a74f8e`). Documented in -`docs/audit/v1415-empty-states.md` and matches the v1.4.15 marathon -pattern flagged by every prior phase. v1.4.16 should adopt -`superpowers:using-git-worktrees` per agent. - -NOT touched (per scope): `src/lib/ai/*`, withings / moodlog / -notifications, messages mass refactor, correlation-card inline empty -surfaces inside /insights (already use a tighter custom variant — -refactor would be churn-only, deferred to v1.4.16). - -## Phase D — Multi-agent QA (parallel) - -- [x] code-reviewer (4 HIGH, 12 MED/LOW — `phase-D-code-review-findings.md`) -- [x] security review (0 HIGH, 8 MED/LOW — `phase-D-security-findings.md`) -- [x] design / UX review (5 HIGH, 11 MED/LOW — `phase-D-design-findings.md`) -- [x] senior-dev review (4 HIGH, 8 MED/LOW — `phase-D-senior-dev-findings.md`) -- [x] simplify on changed file set (6 yes, 4 no — `phase-D-simplify-findings.md`) -- [x] reconcile + apply CRITICAL/HIGH inline (`phase-D-reconcile-report.md`) -- Detailed report: `.planning/phase-D-reconcile-report.md` - -#### Phase D status block — 2026-05-09T22:25+02:00 — done - -5 reviewers + reconcile complete. 0 CRITICAL across all reviewers. -Triage: - -- **Simplify-yes**: 6 / 6 applied, 0 reverted (commit `cd3b890`). -- **HIGH fixed** (5): design H1/H2/H3 tour focus-trap + DE-overflow + - backdrop ring (`6465412`), design H5 Withings error wrap - (`66d2e07`), senior-dev H4 MockAIProvider strict-schema default - (`79bb167`). -- **HIGH deferred** (8): code-review H1-H4 (admin-only leaks / - edge-cases / charts visual constraint / multi-account only), - design H4 (cross-cutting `button.tsx` 44px sweep), senior-dev H1-H3 - (1031 LOC `page.tsx` split, 883 LOC `integrations-section.tsx` - split, worktree adoption process). All in `v1416-backlog.md`. - -Tests: 1047 / 1047 unit pass. Typecheck: 3 pre-existing errors in -`dashboard-layout.test.ts` (A4 owns; reproduces on clean stash). -Lint: 0 errors, 11 pre-existing warnings. Format: touched files -clean; pre-existing 41-file format drift across the wider tree -flagged for v1.4.16. - -5 commits on `origin/main`: - -- `cd3b890` simplify-review safe suggestions -- `6465412` tour focus-trap + DE-overflow + backdrop ring (a11y) -- `66d2e07` Withings error string break-words (a11y) -- `79bb167` MockAIProvider DEFAULT_RESPONSE strict schema -- `d947563` prettier sweep on touched files - -Backlog written: `.planning/v1416-backlog.md` — -8 deferred HIGH + 39 MED/LOW + 4 simplify-no + 3 process items. -Most impactful pre-v1.4.16 fast-track: M4 dispatcher legacy -Telegram migration (silently unwinds B3 hard-rejects) and M6 -senior-dev AI strict-schema route migration. - -## Phase E — Release v1.4.15 - -### E1 — Release v1.4.15 (verify + bump + tag) - -- [x] Pre-release verify: typecheck, lint, format, test, integration (build + e2e deferred to CI) -- [x] Bump package.json to 1.4.15 -- [x] CHANGELOG.md entry -- [x] Tag + push v1.4.15 -- Detailed report: `.planning/phase-E1-report.md` - -#### E1 status block — 2026-05-09T22:27+02:00 — done - -Pre-release verification: green across the board after fixing 3 -pre-existing typecheck errors in `src/lib/__tests__/dashboard-layout.test.ts` -(typed the test fixtures as `DashboardLayout` so the narrow -`DashboardWidgetId` enum stops complaining about plain `string` ids -the test was passing in for `serializeDashboardLayout()`) and applying -the prettier sweep to the 41-file format drift Phase D had flagged. - -Single release commit: `4dcaa08` `chore(release): v1.4.15`. 32 files -changed: package.json bump (1.4.14 → 1.4.15), CHANGELOG entry, -prettier formatting drift on touched marathon files, dashboard-layout -typecheck fix. - -Tag: `v1.4.15` (annotated, "HealthLog v1.4.15"). Pushed to -`origin/main` (1b1214b..4dcaa08) and `origin v1.4.15`. - -GHCR auto-built on tag push: workflow run **25611029556** in_progress -(tag ref `v1.4.15`). Main ref also re-running on the same SHA as run -25611028416. Phase E2 takes over from here. - -### E2..E10 — Production rollout + docs sync (Phase E2 owns) - -- [x] GHCR build green (BOTH main + tag — verify via the new C2 reliability work) -- [x] Coolify auto-deploy via webhook (the C2 work tests itself) -- [x] /api/version=1.4.15 confirmed -- [x] Image digest changed -- [x] Production smoke screenshots -- [x] GH release created -- [x] docs+landing sync (Phase E3 done — `6b938df` + `db66da0` on healthlog-docs, `b6f83be` on healthlog-landing; new pages `/admin/backups` + `/account/data-deletion` shipped) -- [ ] Final summary `docs/audit/v1415-summary.md` (Marc-Brief) -- Detailed report: `.planning/phase-E2-report.md` (Phase E2 will write); E3 sub-report: `.planning/phase-E3-report.md` - -### E — Release v1.4.15 - -- 2026-05-09T20:45:15Z — **v1.4.15 LIVE** at https://healthlog.bombeck.io. - - Tag/commit: v1.4.15 / `4dcaa08`. - - Pulled `ghcr.io/mbombeck/healthlog:1.4.15` directly on apps-01 and - retagged as `:latest` host-side (same proven recipe as v1.4.14 — Coolify - auto-deploy left untouched per Marc's request). - - Container `app-pg8wggwogo8c4gc4ks0kk4ss-202733022736` recreated via - `docker compose up -d app`; db stayed Healthy. - - Image digest: `sha256:0ced46004a54…` → `sha256:ace7d441f47b…` (changed, - no `--force-recreate` needed). - - GHCR pulled-image digest: `sha256:ba77448606b4…`. - - `/api/version` flipped 1.4.14 → 1.4.15 inside the polling window - (well under 1 min from container recreate). - - Smoke (admin session cookie): `/`, `/auth/login`, - `/settings/integrations`, `/settings/notifications`, `/admin`, - `/admin/users`, `/admin/backups`, `/achievements` all 200. - `/dashboard` 404 — expected, no such route in source (dashboard lives - at `/`); runbook smoke list inherited a stale path. - - GH release: https://github.com/MBombeck/HealthLog/releases/tag/v1.4.15 - (notes pulled from `CHANGELOG.md` lines 3–305; runbook's `awk` recipe - only emits the header line — fell back to `grep -n + sed -n`). - - Detailed report: `.planning/phase-E2-report.md`. - - Outstanding: Final summary `docs/audit/v1415-summary.md` (Marc-Brief). +### 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` + +## Wave C — Catch-up (deferred from v1.4.15) + +- [ ] 8 deferred HIGH-Findings from v1.4.15 Wave-D (see `v1416-backlog.md`) +- [ ] 5 deferred MED items from A5 mobile findings +- [ ] Coolify image-digest auto-deploy trigger (replace git-push trigger so deploys only happen on actual new image) +- [ ] docker-publish main-branch hang root-cause + fix (C3 v1.4.15 only fixed tag-path) +- Detailed report: `.planning/phase-C-report.md` + +## 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.14 (completed 2026-05-09T18:35+02:00) +## Previous milestone — v1.4.15 (completed 2026-05-09T22:50+02:00) -LIVE at https://healthlog.bombeck.io · `/api/version=1.4.14` · image digest -`sha256:0ced46004a54…` (was `791c2cd2…` on v1.4.12). +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 -Codex-OAuth resolution: `docs/audit/v1414-summary.md`. +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.14 marathon: +Phases run during v1.4.15 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` +- 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.15) +## Status block — Phase 0 (v1.4.16) -- 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. - ---- - -## Final status — v1.4.15 marathon FINISHED - -- 2026-05-09T22:50:00+02:00 — **v1.4.15 marathon closed.** Final - summary written to `docs/audit/v1415-summary.md` (Marc-Brief at top, - commit-tables per phase, deferred-list, CI/test status, production - state, top-5 v1.4.16 backlog). -- Status flipped to `finished`. -- Production: `https://healthlog.bombeck.io` `/api/version=1.4.15`, - image digest `sha256:ace7d441f47b…` (was `0ced46004a54…` on v1.4.14). -- 78 commits between `v1.4.14` and `v1.4.15` (`30d3ad0..4dcaa08`). -- ~1048 unit tests + 31 integration green; lint 0 errors / 11 - pre-existing warnings; format clean; typecheck clean. -- v1.4.16 backlog seeded at `.planning/v1416-backlog.md` (8 deferred - HIGH + 39 MED/LOW + 4 simplify-no + 3 process items). Top-5 fast- - track captured in summary. -- Outstanding meta items (carry-over to v1.4.16): - - Per-agent git worktree adoption (commit-message drift recurred - across A2, A4, B1, B-mobile, B2, B3, B4, C1, C5). - - Auto-deploy webhook → Image-Digest-Trigger (currently fires on - every Git push). - - AI strict-schema route+UI migration (drop `.passthrough()`). +- 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 via + `git 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. diff --git a/.planning/phase-0-report.md b/.planning/phase-0-report.md index cf2f250b9..9f4b23bfa 100644 --- a/.planning/phase-0-report.md +++ b/.planning/phase-0-report.md @@ -1,51 +1,51 @@ -# Phase 0 — v1.4.15 marathon bootstrap +# Phase 0 — v1.4.16 marathon bootstrap Status: **done** -Timestamp: 2026-05-09T20:06:00+02:00 -Commit: see `chore(planning): bootstrap v1.4.15 marathon` on origin/main. +Timestamp: 2026-05-09T23:12:52+02:00 +Commit: `chore(planning): bootstrap v1.4.16 marathon` on origin/main. ## What this phase did Pivoted `.planning/STATE.md` and `.planning/ROADMAP.md` from the -completed v1.4.14 marathon (which shipped at 18:35+02:00 today and is -LIVE on https://healthlog.bombeck.io with `/api/version=1.4.14`, image -digest `sha256:0ced46004a54…`) to the v1.4.15 marathon scaffold. +completed v1.4.15 marathon (which shipped today at 22:50+02:00 — see +`docs/audit/v1415-summary.md` for the Marc-Brief, commit table, image +digest `sha256:ace7d441f47b…`, deferred items) to the v1.4.16 scaffold. -The v1.4.14 entries were archived in-place: STATE.md keeps a one-line -"previous milestone" reference plus a phase-summary block; ROADMAP.md -keeps the full v1.4.14 phase table below the active v1.4.15 table. No -information lost — `docs/audit/v1414-summary.md` remains the canonical -release record. +STATE.md now lists Wave A (A1–A8 quick fixes), Wave B (B1–B7 quality-leap +features), Wave C (catch-up of 8 deferred HIGH from Phase D + 5 mobile +MEDs + Coolify image-digest auto-deploy + docker-publish main-branch +hang root-cause), Wave D (5 reviewers + Product-Lead + reconcile), Phase +E (release). ROADMAP.md mirrors the heading-level structure with one- +line Goal cells; v1.4.15 + v1.4.14 entries archived below the active +table. -Phases scaffolded for v1.4.15: A1-A5 (5 quick-fix buckets), B1-B6 (6 -bigger features), C1-C5 (hardening — including AI/Codex -hallucination-resistance C1 and Coolify auto-deploy C2), D (multi-agent -QA, write-only), and E (release). +## Working-tree sanity -## Pre-flight checks +`git status` showed 22 modified `.planning/*.md` files at session start +— a stray re-run of `prettier --write .planning/` had corrupted the +v1.4.15-shipped reports (markdown list-marker `+` flipped to `-`, +breaking semantic content like "+1 e2e" → "-1 e2e" and "command + +flag" lists). Discarded via `git checkout -- .planning/`. Tracked +working tree now matches `origin/main`. Untracked phase reports from +v1.4.14 + v1.4.15 (15 files) left in place — they belong to previous +milestones and are explicitly out-of-scope for v1.4.16 Phase 0. -- Codex protocol spec at `docs/codex-protocol-spec.md` confirmed - present (741 LOC) — canonical reference for Phase C1 AI hardening. -- Backlog at `.planning/v1415-backlog.md` confirmed present (HIGH / - MEDIUM / LOW findings from the v1.4.14 phase-6 multi-agent QA). -- Summary at `docs/audit/v1414-summary.md` confirmed present (Marc-Brief - + 53-commit table). +## Spec re-read -## Working tree +Re-read `docs/codex-protocol-spec.md` as required (canonical reference +for any v1.4.16 AI work — Wave-A A7 rate-limit + cache, Wave-B B5 +hallucination-hardening v2 medical-grounding + multi-provider). §7b +slug-drift defence already shipped in v1.4.15 C1; v1.4.16 builds on +top. -`git status` shows `main` up to date with `origin/main`. 10 untracked -files from the v1.4.14 marathon (phase-4-visual-verify, phase-6-{code- -review, design, reconcile, security, simplify}-findings, phase-8 / 9 / -10, v1414-rebrand-report) were intentionally left untracked — they -belong to the previous milestone, not this one. Folding them into the -Phase 0 commit would muddy v1.4.15 history. The Phase 0 commit -contains ONLY `.planning/STATE.md`, `.planning/ROADMAP.md`, +## Backlog inventoried + +`.planning/v1416-backlog.md` confirmed present (8 deferred HIGH + 39 +MED/LOW + 4 simplify-no + 3 process items, severity-grouped, with +file:line references). Wave C catch-up references this file. + +## Marc-status + +Speed mattered. Working-tree corruption tax was 30 seconds. Phase 0 +commit contains only `.planning/STATE.md` + `.planning/ROADMAP.md` + `.planning/phase-0-report.md`. - -## Constraints honoured - -- Single chore commit `chore(planning): bootstrap v1.4.15 marathon` - with `Co-Authored-By: Claude Opus 4.7 (1M context)`. -- No `--no-verify`, no `--no-gpg-sign`. -- Only `.planning/` files touched. No source files modified. -- Pushed to `origin/main`.