Records the three additional root causes uncovered after the first
e2e fix landed: desktop-only specs leaking into the mobile project
plus the missing `/api/dashboard/widgets` stub in onboarding-flicker
spec.
Wave C dispatch closed: integration + e2e workflows green again
(YAML-parsed-as-integer ENCRYPTION_KEY plus tour-overlay click
interception); 5 of 8 deferred HIGH items applied (H3 charts skipped
per ownership, H1/H2 senior splits deferred); 3 of 5 deferred MED
mobile items applied (BP grouping + DOM weight deferred to v1.5);
docker-publish hang root-cause was qemu-arm64 SIGILL — dropped arm64
from platforms; Coolify image-digest auto-deploy documented + deferred
to v1.5 with concrete plan.
`pnpm test` 1303/1303, `pnpm test:integration` 53/53 locally,
typecheck clean, lint 12 pre-existing warnings.
Hard-fail cascade across the configured chain landed on origin/main
across four atomic commits. Runner caches the last working provider
(1h TTL) so a 401 on a lapsed Codex OAuth doesn't burn a round-trip
on every reload for the next hour. Settings -> AI surfaces a small
read-only summary of the chain; full management UX is owned by B2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apple-Health-style polish lands across all dashboard chart wrappers
in v1.4.16: gradient fills, 90-day personal baseline, rich tooltips
with delta-vs-baseline, 600 ms first-render animation respecting
prefers-reduced-motion, sparse-data empty state. Mood chart picks
up emoji glyphs at every data point; medication chart picks up the
gradient + rich tooltip on top of A6's existing target/threshold
reference lines.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
STATE.md gets the four B6 commits + audit doc link + status block.
phase-B6-report.md was the v1.4.15 doctor-report report; rewritten
for the v1.4.16 phase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Five atomic commits + one hijacked-by-B3 commit landed the consolidated
/settings/export route, four /api/export/* endpoints, and the full test
coverage. AdvancedSection slimmed to the danger-zone-only surface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
STATE.md now records the three commits that landed B4 (audit-log
filtering / pagination / CSV export, app-log preview surface, sidebar
entry) and the per-process ring-buffer + redaction-on-egress contract
the in-memory log preview is built on.
`.planning/phase-B4-report.md` overwritten — the file from v1.4.15
covered the achievements UI, which moved to a different phase letter
in v1.4.16. New report captures B4's actual scope, the coordinator
stash-race that landed commit 1's code under
`8ac5602 docs(planning): Wave-A verification gate report + STATE
update` instead of its own message, and the verification numbers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Host-load chart above /admin/system-status renders the last 2h of
load1, memory %, and disk-IO % from a per-minute pg-boss sampler.
Schema migration 0032_host_metric, /api/admin/host-metrics endpoint,
HostMetricsChart component (Recharts wrapper, next/dynamic from the
consumer), system-status section wired with the chart on top, EN+DE
i18n keys, 13 unit + 6 integration tests.
Three commits landed cleanly under their own titles (db, jobs, api);
the chart + wiring + i18n got absorbed into another agent's commit
due to a parallel-agent staging race during the verification gate's
stash/restore loop. Functionally everything is on origin/main.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Local clean-clone verification confirms Wave-A introduced no
regressions: typecheck/lint/unit/integration all green at origin/main
HEAD `94c748d`. CI Security & Quality consistently passes; the failing
Integration tests + e2e workflows are pre-existing infrastructure issues
(failure shape identical at v1.4.15 release commit `0985c93`), not
Wave-A source regressions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 atomic commits on origin/main land the curated reference bundle,
schema validation, prompt injection, citation-coverage logging and
the UI footnote. PROMPT_VERSION bumped to 4.16.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A7: rate-limit raised to 10/h via INSIGHTS_RATE_LIMIT_PER_HOUR + per-
status `audit_logs` cache rows evicted on every successful generation
so the dashboard insight card and the insights-page status cards
never disagree. Source landed inside the cross-agent A6 commit;
attribution noted on origin/main.
A8a: geo helper decodes via arrayBuffer + TextDecoder('utf-8') and
sends Accept-Language: de,en;q=0.5 so umlauts roundtrip cleanly. 7-
city regression test pinned (Nürnberg/München/Düsseldorf/Köln/Würzburg
/Bückeburg/Weißenfels) plus eszett, plus a Content-Type-without-
charset case, plus an Accept-Language assertion. No other ASCII-fold
surfaces in src/ — `git grep` confirmed the geo helper was the only
one.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A2 — BD-Zielbereich now reports 50% for Marc's actual production data
(was 0% under v1.4.15 narrow-band semantics). Root cause + fix in
.planning/phase-A2-A6-report.md.
A6 — medication chart matches BP/weight chart pattern: 7d-trend chip
in header + target-range visualization (100% goal + 80% threshold).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A4: "7-Tage-Trend" everywhere, slope30 fallback for sparse metrics.
A5: API enum drift fixed (achievements widget), empty strip hidden.
A8b: split-half mean delta supplements per-week rate on long ranges.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A1 — sidebar admin entry mirrors Settings (no sub-item expansion).
A3 — /admin/api-tokens mobile card-list (no horizontal overflow).
Both shipped on origin/main as 77fe256 + 277a5aa.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the Settings entry pattern verbatim: the global sidebar's Admin
entry is now a single link with no sub-item expansion at any route.
v1.4.15 A1 had gated the expansion behind `onAdminPage`, but Marc
re-flagged it — the in-shell `<AdminShell>` already provides per-section
nav inside the page, so the global sidebar duplicating it on `/admin/*`
was unwanted UX. Removing the entire `{onAdminPage && <ul>...</ul>}`
block also kills the perceived link between the gravatar dropdown and
sidebar state — they're independent concerns now.
Tests updated:
- `sidebar-nav.test.tsx` — every admin-route case now asserts ONLY the
single `/admin` link is present, never sub-route links.
- New e2e spec `sidebar-admin-no-expand.spec.ts` covers (a) /admin/* shows
one link, no sub-list; (b) clicking Admin from /dashboard navigates
without flashing sub-items; (c) opening the gravatar user-menu does
not expand sidebar admin sub-items.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the phase-C5 detailed report and appends the C5 status block to
STATE.md so the v1.4.15 marathon log reflects 13 empty-state surfaces
shipped across admin, feature pages, insights and dashboard.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
i18n coverage audit: 0 gaps closed (locale files already in perfect
parity by the time C4 ran sequentially after Batch 2). Audit
converted to a quality-assurance sweep — extended
i18n-locale-integrity.test.ts with 5 new assertions (empty values,
key-equals-value-in-both-locales, TODO/FIXME markers).
Detailed report: .planning/phase-C4-report.md
Audit deep-dive: docs/audit/v1415-i18n-coverage.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Marks Phase B5 (onboarding tour first-run) complete in
`.planning/STATE.md` and adds the detailed
`.planning/phase-B5-report.md` per the marathon convention.
All four atomic feature commits already on `origin/main`:
db5a49d, e57fc0a, 8215e25, fa1c6a6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two-commit C2 phase complete:
- `34c967c` (sibling agent's `feat(achievements)` message — shared-cwd
race carried my `docker-publish.yml` + `.env.example` +
`docs/audit/v1415-auto-deploy.md` hunks; same pattern A2/A4/B1/B-mobile
documented). Trigger Coolify deploy after GHCR push via Bearer-protected
webhook URL.
- `ad350fe` clean, my files only via `git commit -o`. New
`POST /api/internal/deploy-webhook` validates `X-Deploy-Webhook-Secret`
(timing-safe), audit-logs `system.deploy.{success,failure,unknown}`,
fans `SYSTEM_ALERT` to admins on failure (reuses
`dispatchNotification`).
This commit only touches the planning report + state log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Status block + detailed report for v1.4.15 Phase B2 (Withings +
moodLog sync robustness). All four criteria green on origin/main:
- 4db72a8 status UI + IntegrationStatus table
- b290a77 refresh-token reauth wiring
- 604dff0 admin Telegram alert >=3 consecutive
- 2fbf56d audit-log entry on every failure
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase B3 (notification reliability) shipped via 87a40fd + a3c0130:
auto-disable on hard reject, exponential backoff with give-up after
5 transient failures, and the Settings → Notifications channel-
status UI. STATE.md status-block + .planning/phase-B3-report.md
describe the implementation, tests, and the two parallel-agent
shared-cwd commit-race incidents encountered during the phase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Five fixes for dashboard analytics shipped in phase A4 of the v1.4.15
marathon. The detailed report at .planning/phase-A4-report.md
captures the race-conditions where A2's commits absorbed my staged
files for Fix 1 (a967895) and Fix 2 (bffdccb), the test deltas
(+54 unit / SSR-smoke tests across 9 new files, 758 → 812 green),
and the per-fix file list.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to 9f80040 — that commit restored the STATE.md A1 status
block but the report file was missed during staging (it was untracked
and the parallel-agent storm of the moment swapped indexes between my
`git add` and `git commit`). This commit adds the actual
`.planning/phase-A1-report.md` so the cross-link in STATE.md resolves.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase A1 (nav conditionals + sidebar context-awareness) shipped four
atomic fixes earlier this session — see commits 85aa15b, 786b395,
73afae0, bde167d, c63e4de. The matching planning entries were
overwritten by a sibling agent's rebase mid-session; this commit
restores the A1 status block under STATE.md and adds the detailed
`.planning/phase-A1-report.md` that the agent contract requires.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pivot STATE.md + ROADMAP.md from the completed v1.4.14 marathon (live in
prod at /api/version=1.4.14, image digest 0ced46004a54) to the v1.4.15
scaffold: phases A1-A5 (quick fixes), B1-B6 (bigger features), C1-C5
(hardening including AI/Codex hallucination-resistance and Coolify
auto-deploy), D (multi-agent QA), E (release).
v1.4.14 entries archived in-place; docs/audit/v1414-summary.md remains
the canonical release record. Phase-0 report at
.planning/phase-0-report.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Marc-Brief (DE) at the top with what shipped, what's fixed, perf
deltas; below it the commit-by-commit landing report, deferred items,
CI/prod state, Codex-OAuth resolution, and the v1.4.15 backlog seed.
STATE.md flipped to finished.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- typecheck/lint/test/format clean (modulo the chart test file
blocked by Marc constraint — pre-existing)
- integration suite green after the test-isolation fix in the
preceding commit (10/10 consecutive runs)
- build + e2e blocked by the documented Node-25 Reflect.get bug
on this workstation; CI Docker (Node 22) is canonical and
Phase-3 already records 41/41 e2e specs green there
- format sweep on .planning/*.md + e2e/measurement-flow.spec.ts
to clear the warnings Phase 6 reconcile listed as
pre-existing-out-of-scope
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The v1.5.0 release was redirected to v1.4.14 because it is bugfix-heavy
with only additive features, so semver-patch is the correct increment.
Rename the v15-* audit notes and the v15-1 backlog accordingly, and log
the docs/landing rebrand (commits 06bc616 docs, 92c6588 landing) under
Phase 9 in STATE.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 5 closed: /admin a11y test reactivated and clean, top-10
friction audit filed at docs/audit/v15-ux-friction.md, three v1.4.6
deferred items shipped (trend-arrow metric-aware, remove saved AI
key, semantic mood/feedback tokens), plus two inline friction fixes
(dashboard quick-add disambiguation, /admin nav landmark).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Result: 41/41 active specs green locally (Node 22, fresh DB);
3 skipped — the mobile-only viewport spec on the desktop project
(× 2) and the /admin a11y test parked as test.fixme until Phase 4b
ships.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captured Playwright+PerformanceObserver perf metrics against prod
(/api/version=1.4.13) at 2026-05-09T14:14Z. Top 2 wins shipped
inline (Recharts deferred-import on /insights, checklist queries
gated on post-onboarding state); Recharts replacement deferred to
v1.5.1 because v1.5 forbids new deps.
Wins: bb2b1de + 519e36e. Audit doc: 41fa203.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Picks up the prettier line-wraps the v1.5 phase-1 planning docs and
codex-protocol-spec.md missed, and brings the redact.ts + insights
generate route test into the project's standard form. No behaviour
change — pnpm format:check now passes clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Default model slug fix (gpt-5 → gpt-5.3-codex) on commit 5df74f7
makes the chatgpt.com backend accept HealthLog's Codex requests on
Marc's ChatGPT-Plus account; spec §7a updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reset .planning/STATE.md and .planning/ROADMAP.md for the v1.5
overnight marathon. STATE.md tracks 12 phases (0–11) with empty
checkboxes; phase 0 marked done. Capture phase-0 sanity report at
.planning/phase-0-report.md (git status clean, recent commits, CI
status, /api/version=1.4.12 — one tag behind HEAD because the
v1.4.13 GHCR build is still in_progress; phase 1 owns the force-pull
verification). ROADMAP.md condenses the 12-phase plan with the
time-runs-short minimum (1+2+7+8) for shipping v1.5.0.
Previous milestone (v1.4.6) summary preserved as a one-line link to
docs/audit/v146-summary.md at the top of STATE.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "Connect with ChatGPT" button never actually completed an OAuth
flow. The implementation hit `chatgpt.com/authorize` and
`chatgpt.com/oauth/token`, which are not OAuth endpoints — ChatGPT
silently rendered its normal web app, dropped our params on the
floor, and the user landed on a regular logged-in chat session with
nothing else happening. There was no error and no callback, which is
why the regression survived multiple releases.
The canonical issuer for ChatGPT-OAuth is `auth.openai.com`. The
official `openai/codex` CLI confirms this in
`codex-rs/login/src/auth/manager.rs` and `codex-rs/login/src/server.rs`.
The flow is also slightly more involved than a vanilla PKCE
authorisation:
1. PKCE authorize against `auth.openai.com/oauth/authorize` with the
`openid profile email offline_access api.connectors.read
api.connectors.invoke` scope set, plus `id_token_add_organizations`
and `codex_cli_simplified_flow` flags so the resulting `id_token`
carries the ChatGPT-subscription claims.
2. Token exchange against `auth.openai.com/oauth/token` (form-
urlencoded body, NOT JSON) yields `{ id_token, access_token,
refresh_token }`.
3. **Second token exchange** with grant
`urn:ietf:params:oauth:grant-type:token-exchange`, swapping the
`id_token` for an OpenAI API key (`requested_token=openai-api-key`).
This key bills against the ChatGPT subscription rather than a
separate API plan — exactly what the v1.2/v1.3 design intended.
4. HealthLog stores the API key in `codexAccessTokenEncrypted`
(re-purposing the existing column to avoid a migration) and the
OAuth refresh token in `codexRefreshTokenEncrypted`. When the
key is about to age out we refresh + re-exchange transparently
before the next request.
The downstream provider is now a regular `OpenAIClient` tagged with
`providerType: "codex"` so logs and analytics still distinguish
ChatGPT-subscription billing from plain BYOK. The bespoke
`codex-client.ts` (which hit the chatgpt.com/backend-api/codex/responses
endpoint with the OAuth access token) is still on disk for now so the
prisma columns and the provider tag stay stable, but is unreferenced
by the active path.
The public Codex CLI client ID `app_EMoamEEZ73f0CkXaXp7hrann` is
shipped as a default; operators who registered a private OAuth app
with OpenAI can override via `CODEX_OAUTH_CLIENT_ID`. The
`isCodexOAuthConfigured()` gate is a no-op now because the default
always has a value, so the UI surface no longer silently hides the
"Connect with ChatGPT" button.
Tests cover the new shape end-to-end: PKCE generation, the
authorize-URL parameters, the form-encoded token exchange, the
api-key exchange, the refresh path, and the encrypt/decrypt
round-trip. The provider integration test is updated to expect a
`providerType: "codex"` OpenAIClient instead of the legacy
`CodexClient`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Marc-facing morning brief at the top, full per-finding list,
deferred-to-v1.5 backlog, production state, docs/landing sync log,
and the multi-agent QA reconciliation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>