mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
docs(planning): phase-D reconcile report + v1.5 backlog seed + STATE.md update
Captures the v1.4.16 phase-D reconcile outcome: - 1 of 3 CRITICAL fixed inline (C3 on-surface comparison toggle). C1 + C2 deferred to v1.4.17 with documented rationale (root cause: /insights + dashboard preview need API surface changes that exceed reconcile scope). - 9 HIGH fixed (a11y tap targets, i18n leak, security redaction, feedback rate-limit, fallback chain enabled flag, medication comparison caption); 11 deferred. - 7 of 8 simplify-yes applied. - v15-backlog.md seeded with deferred items + Product-Lead C.1-C.11 roadmap + v1.6+ follow-on initiatives. Final verification green: typecheck 0, lint 0 errors, test 1539/1539, integration 59/59. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5f7b9d8652
commit
54bbc68eff
4 files changed
+483
-84
No files matched your search
+36
-8
@@ -470,14 +470,42 @@ Last update: 2026-05-09T23:12:52+02:00
|
||||
|
||||
## 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`
|
||||
- [x] code-reviewer (0 CRITICAL, 8 HIGH, 9 MED, 10 LOW)
|
||||
- [x] security review (0 CRITICAL, 2 HIGH, 5 MED, 3 LOW)
|
||||
- [x] design / UX review (Apple Health benchmarking lens) — 3 CRITICAL,
|
||||
8 HIGH, 22 MED/LOW
|
||||
- [x] senior-dev review (0 CRITICAL, 3 HIGH, 9 MED/LOW)
|
||||
- [x] simplify (8 apply-yes / 2 apply-no)
|
||||
- [x] Product Lead — state of app, biggest items, v1.5 roadmap,
|
||||
follow-on initiatives
|
||||
- [x] Reconcile applies CRITICAL/HIGH inline
|
||||
- Detailed report: `.planning/phase-D-reconcile-report.md` +
|
||||
`phase-D-product-lead-review.md`
|
||||
|
||||
### Status block — Wave D reconcile
|
||||
|
||||
- 2026-05-10T03:20+02:00 — Wave D complete on origin/main.
|
||||
- **CRITICAL**: 1 of 3 fixed inline (C3 on-surface comparison
|
||||
toggle, commit `6e74d38`); 2 deferred to v1.4.17 with documented
|
||||
rationale (C1 + C2 — both require new API surfaces, root cause
|
||||
"scope-completion-without-route-wiring").
|
||||
- **HIGH**: 9 fixed inline (`5f7b9d8`, `6863ecb`, `fb12f09`,
|
||||
`c3451a4`, `2f057f4`, `5661439`); 1 already-fixed (code-review
|
||||
H1 — reviewer mis-read source); 11 deferred to v15-backlog.md.
|
||||
- **Simplify**: 7 of 8 apply-yes landed (commit `f3025a8`); F1 +
|
||||
F8 are apply-no flagged for Marc.
|
||||
- **Product-Lead review** stands as-is; IS the strategic v1.5 plan.
|
||||
- **Verification**: `pnpm typecheck` 0 errors, `pnpm lint` 0
|
||||
errors / 12 pre-existing warnings, `pnpm test` 1539/1539,
|
||||
`pnpm test:integration` 59/59. format:check is not in CI; my
|
||||
new files prettier-formatted.
|
||||
- **Backlog seed**: `.planning/v15-backlog.md` is the v1.5
|
||||
milestone planning input.
|
||||
- **Reconcile commits**: `c0c1284` planning refresh, `6e74d38`
|
||||
C3, `c3451a4` H1+H2+H6+H7 a11y, `2f057f4` H3 i18n leak,
|
||||
`fb12f09` security H1+H2, `5661439` H4 design, `f3025a8`
|
||||
simplify, `6863ecb` H5+H6 code-review, `5f7b9d8` H2
|
||||
code-review.
|
||||
|
||||
## Phase E — Release v1.4.16
|
||||
|
||||
|
||||
@@ -1,100 +1,152 @@
|
||||
# Phase D — Reconcile report (v1.4.15)
|
||||
# Phase D — Reconcile report (v1.4.16)
|
||||
|
||||
Reviewer: phase-D reconcile agent (sequential after the 5 parallel
|
||||
reviewers).
|
||||
Inputs: `phase-D-{code-review,security,design,senior-dev,simplify}-findings.md`.
|
||||
Constraint: charts visual style stays Dracula; chart-DATA changes
|
||||
already done in v1.4.15. No new dependencies. Pre-commit hooks must
|
||||
run; no `--no-verify`, no `--no-gpg-sign`.
|
||||
Reviewer: phase-D reconcile agent (sequential after the 6 parallel
|
||||
reviewers + Product-Lead).
|
||||
Inputs: `phase-D-{code-review,security,design,senior-dev,simplify,
|
||||
product-lead-review}-findings.md`.
|
||||
Constraint: charts data-presentation can change in v1.4.16; visual
|
||||
style stays Dracula. No new dependencies. Pre-commit hooks must run;
|
||||
no `--no-verify`, no `--no-gpg-sign`.
|
||||
|
||||
Verdict: 0 CRITICAL across all five reviewers. 13 HIGH + 6 simplify-yes
|
||||
items triaged below.
|
||||
Verdict: 1 of 3 CRITICAL fixed inline (C3 on-surface comparison
|
||||
toggle). 2 of 3 deferred to v1.4.17 with documented rationale.
|
||||
9 HIGH fixed, 12 deferred. 7 of 8 simplify-yes applied.
|
||||
|
||||
---
|
||||
|
||||
## Simplify — autonomous-yes (6 items)
|
||||
## CRITICAL — status per finding
|
||||
|
||||
| # | Description | Result |
|
||||
| --- | --- | --- |
|
||||
| F3 | drop `inspectCodexSlugCache()` (test-only diag) | applied |
|
||||
| F4 | drop `TEST_CONSTANTS` re-export in `channel-state.ts` | applied |
|
||||
| F5 | drop `RejectKind` type alias in `retry-policy.ts` | applied |
|
||||
| F6 | drop misleading "fallback" comment on exhaustive switch in `achievements.ts` | applied |
|
||||
| F7 | drop unreachable `default:` arm in `stateBadgeFor` | applied |
|
||||
| F10 | export `isWithingsRefreshReauthFailure` and dedupe inline classifier in `/api/withings/status` | applied |
|
||||
### C1 — `/insights` does NOT mount the polished `<InsightAdvisorCard>` / grid / RecCard / ConfidenceMeter / Feedback. **DEFERRED**
|
||||
|
||||
**6 applied, 0 reverted.** All landed in commit `cd3b890`
|
||||
(`refactor(v1.4.15): apply simplify-review safe suggestions`).
|
||||
Wider-than-reasonable-scope-tonight. The `/insights` page consumes 7
|
||||
distinct per-status endpoints (`/api/insights/{general,blood-pressure,
|
||||
weight,pulse,bmi,mood,medication-compliance}-status`) returning text-
|
||||
only payloads. Mounting `<InsightAdvisorCard>` requires either
|
||||
rewriting all 7 status endpoints to return the
|
||||
rationale+confidence+citation rich shape, OR migrating the page to
|
||||
consume `/api/insights/generate`'s comprehensive payload directly.
|
||||
Same v1.4.17 migration the senior-dev review and code-review (H3)
|
||||
flagged.
|
||||
|
||||
**Workaround applied:** v1.4.16 release notes / Marc-Brief MUST phrase
|
||||
the polish components as "groundwork for v1.4.17 user-facing rollout"
|
||||
rather than headline UX. Screenshots of the unmounted advisor card
|
||||
surface do NOT belong in v1.4.16 marketing material. Logged to
|
||||
`v15-backlog.md` from-design section.
|
||||
|
||||
### C2 — `<InsightsCardPreview>` (dashboard insights tile) has zero live imports. **DEFERRED**
|
||||
|
||||
Same root cause as C1. Mounting on `/` requires a new GET endpoint
|
||||
exposing `User.insightsCachedText` + cache-aware staleness markers
|
||||
(the existing `/api/insights/generate` is POST mutation-only).
|
||||
Logged to `v15-backlog.md`.
|
||||
|
||||
### C3 — Comparison toggle has NO on-surface control (buried 3 clicks deep). **FIXED**
|
||||
|
||||
Commit `6e74d38` `fix(design): on-surface comparison toggle on
|
||||
dashboard + insights (C3)`. New `<CompareToggle>` segmented control
|
||||
(None / Vormonat / Vorjahr) mounted next to dashboard greeting and
|
||||
on `/insights` page hero. Persists via the same
|
||||
`/api/dashboard/widgets` PUT the Settings section uses, with
|
||||
optimistic update + cache invalidation. 44 px tap targets,
|
||||
focus-visible ring, role=group + aria-label, EN+DE i18n. 6 SSR
|
||||
tests pin segment count, persisted-active state, tap-target floor,
|
||||
EN+DE labels, and ARIA shape.
|
||||
|
||||
---
|
||||
|
||||
## HIGH triage
|
||||
## HIGH — triage table
|
||||
|
||||
| # | Reviewer | Finding | Decision | Commit / reason |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| code-review H1 | code-review | restore catch surfaces raw Prisma error | DEFER | admin-only leak; v1.4.16 |
|
||||
| code-review H2 | code-review | mood `tags` schema permissive | DEFER | edge-case round-trip of corrupted backup |
|
||||
| code-review H3 | code-review | mood-chart aggregation test divergence | DEFER | charts visual constraint — touches `src/components/charts/**` |
|
||||
| code-review H4 | code-review | tour sessionStorage not user-scoped | DEFER | multi-account only; single-tenant unaffected |
|
||||
| design H1 | design | tour focus-trap missing | FIXED `6465412` | a11y, B-agent code, ~30 LOC |
|
||||
| design H2 | design | tour DE copy overflow | FIXED `6465412` | added `max-h-[80vh] overflow-y-auto` to card |
|
||||
| design H3 | design | tour backdrop button has no focus ring | FIXED `6465412` | a11y, ~1 LOC |
|
||||
| design H4 | design | 32 px buttons in B1/B3/B5 surfaces | DEFER | cross-cutting `button.tsx` design-system bump; v1.4.16 sweep |
|
||||
| design H5 | design | Withings error overflow | FIXED `66d2e07` | added `min-w-0 break-words`, ~5 LOC |
|
||||
| senior-dev H1 | senior | `src/app/page.tsx` 1031 LOC split | DEFER | refactor scope, mid-marathon risk |
|
||||
| senior-dev H2 | senior | `integrations-section.tsx` 883 LOC split | DEFER | refactor scope |
|
||||
| senior-dev H3 | senior | adopt git worktrees per agent | DEFER | process change for next marathon |
|
||||
| senior-dev H4 | senior | `MockAIProvider` DEFAULT_RESPONSE drift | FIXED `79bb167` | low risk, ~10 LOC |
|
||||
| # | Source | Finding | Action | Commit |
|
||||
| --- | ----------- | -------------------------------------------------- | ---------------------------------------------------------- | --------- |
|
||||
| H1 | code-review | feedback-aggregator bucket-key collision | **already-fixed** (reviewer mis-read; SOH `\x01` in code) | n/a |
|
||||
| H2 | code-review | FallbackChainCard discards `enabled` flag | **fixed** | `5f7b9d8` |
|
||||
| H3 | code-review | Strict B5b/c/d AI features dark in production | **deferred** → v1.4.17 (route migration) | n/a |
|
||||
| H4 | code-review | findRecommendationsMissingRationale always-empty | **deferred** → v1.4.17 | n/a |
|
||||
| H5 | code-review | feedback endpoint had no rate-limit | **fixed** | `6863ecb` |
|
||||
| H6 | code-review | feedback over-broad cache invalidation | **fixed** | `6863ecb` |
|
||||
| H7 | code-review | comparison overlay shifts current data forward | **deferred** (needs upstream-fetcher audit) | n/a |
|
||||
| H8 | code-review | seedKey race in ai-section | **deferred** | n/a |
|
||||
| H1 | security | meta + action.details not redacted at admin egress | **fixed** | `fb12f09` |
|
||||
| H2 | security | `/api/admin/audit-log` raw `details` returned | **fixed** | `fb12f09` |
|
||||
| H1 | design | rec-feedback thumbs 28×28 px | **fixed** | `c3451a4` |
|
||||
| H2 | design | rec-card chevron 24×24 px | **fixed** | `c3451a4` |
|
||||
| H3 | design | trend-card aria-label hardcoded English | **fixed** | `2f057f4` |
|
||||
| H4 | design | medication-compliance no compareBaseline overlay | **fixed** (caption added) | `5661439` |
|
||||
| H5 | design | InsightsPageHero gradient too faint | **deferred** → v1.4.17 visual sweep | n/a |
|
||||
| H6 | design | Chart range tabs 36×~28 px | **fixed** | `c3451a4` |
|
||||
| H7 | design | Medication CSV raw `<input type="checkbox">` | **fixed** (Switch + min-h-11) | `c3451a4` |
|
||||
| H8 | design | DE fallback-chain row Pixel-5 overflow | **deferred** (premise partly mistaken — buttons icon-only) | n/a |
|
||||
| H1 | senior-dev | `src/lib/ai/` 19 flat files architectural pressure | **deferred** → v1.4.17 | n/a |
|
||||
| H2 | senior-dev | `<InsightAdvisorCard>` 690-line god-component | **deferred** → v1.4.17 | n/a |
|
||||
| H3 | senior-dev | `<RecommendationCard>` approaching size | **deferred** → v1.4.17 | n/a |
|
||||
|
||||
**5 HIGH fixed, 8 HIGH deferred.**
|
||||
|
||||
Plus `d947563` for prettier-sweep on the touched files.
|
||||
**Tally: 9 HIGH fixed, 1 already-fixed (mis-read), 11 deferred to v15-backlog.md.**
|
||||
|
||||
---
|
||||
|
||||
## Final verify status
|
||||
## Simplify-yes — applied
|
||||
|
||||
- `pnpm typecheck`: 3 pre-existing errors in
|
||||
`src/lib/__tests__/dashboard-layout.test.ts` (lines 89/102/114 →
|
||||
`DashboardWidgetId` narrow-string mismatch). Reproduces on a clean
|
||||
`git stash` of the working tree per STATE.md A4 / B-mobile / C3
|
||||
attribution. Not introduced by this reconcile.
|
||||
- `pnpm lint`: 0 errors, 11 warnings (all pre-existing
|
||||
`_unused` parameters in dev / monitoring routes).
|
||||
- `pnpm format:check`: 41 files with pre-existing class-order /
|
||||
line-length warnings outside reconcile scope. Touched files
|
||||
reformatted in `d947563` so the reconcile diff itself is clean.
|
||||
- `pnpm test`: **1047 / 1047 passing.**
|
||||
7 of 8 apply-yes findings landed in commit `f3025a8`
|
||||
`refactor(v1.4.16): apply simplify-review safe suggestions`:
|
||||
|
||||
- F2 — `confidenceContext` config-bag dropped from `generateInsight()`.
|
||||
2 confidence-wrapper tests rewritten to test parsed-payload path.
|
||||
- F3 — `aiRecommendationRationaleSchema.referenceId` speculative
|
||||
optional dropped.
|
||||
- F4 — `applyLastWorkingCache` doc-comment trimmed.
|
||||
- F5 — `<RecommendationFeedback>` re-uses canonical
|
||||
`RecommendationFeedbackRequest` types.
|
||||
- F6 — `formatRelativeTime` doc-comment trimmed (stale polyfill claim).
|
||||
- F7 — `<RecommendationCard>` 26-line slot-architecture header → 4-line
|
||||
WHY.
|
||||
- F9 — `pickProviderType` mis-anchored PROMPT_VERSION paragraph
|
||||
removed.
|
||||
- F10 — `legacy-payload.ts` `UnknownRec` interface inlined.
|
||||
- F12 — `<ConfidenceMeter>` 20-line band-policy header → 3-line WHY.
|
||||
|
||||
(F1 + F8 are apply-no — both flagged for Marc's call. Logged to
|
||||
v15-backlog.md "from-simplify" section.)
|
||||
|
||||
**0 reverts.** All landed cleanly with full test suite green per-step.
|
||||
|
||||
---
|
||||
|
||||
## v1.4.16 backlog
|
||||
## Final verification
|
||||
|
||||
Severity-grouped, file:line, terse:
|
||||
[`/Users/marc/Projects/HealthLog/.planning/v1416-backlog.md`](./v1416-backlog.md).
|
||||
Run after all reconcile commits land. See "Final verification" status
|
||||
block at the bottom of this document for actual numbers.
|
||||
|
||||
Folds: 8 deferred HIGH + 7 code-review MEDIUM + 7 security MEDIUM/LOW
|
||||
+ 11 design MEDIUM/LOW + 8 senior-dev MEDIUM + 8 senior-dev LOW + 4
|
||||
simplify-no items + 3 process / meta items. Two single most
|
||||
impactful entries to fast-track in v1.4.16:
|
||||
Cleanup note: removed orphan `src/components/settings/thresholds-
|
||||
settings-section.tsx` (untracked leftover from B6's renaming refactor —
|
||||
was blocking typecheck against the new layout).
|
||||
|
||||
1. **dispatcher legacy Telegram migration** (`M4` code-review) — the
|
||||
on-the-fly migration unwinds B3's hard-reject auto-disable on every
|
||||
send; effectively reverts B3 for any user with legacy Telegram
|
||||
config still on `User.telegramBotToken`.
|
||||
2. **AI strict schema route migration** (`M6` senior-dev) — finishes
|
||||
what C1 started; retires `.passthrough()`; deletes legacy
|
||||
`insightResultSchema`.
|
||||
Untracked dotted-segment route directories (`src/app/api/export/
|
||||
{measurements,medications,mood}.csv/`, `full-backup.json/`) are
|
||||
pre-existing v1.4.16 leftovers from B7's plain-segment pivot. Left in
|
||||
place — not in scope for reconcile, but flagged for v1.4.17 cleanup.
|
||||
|
||||
---
|
||||
|
||||
## Pointer
|
||||
## Pointer to v15-backlog.md
|
||||
|
||||
- Backlog: `.planning/v1416-backlog.md`
|
||||
- Findings sources: `.planning/phase-D-{code-review,security,design,senior-dev,simplify}-findings.md`
|
||||
- Commits this phase (5):
|
||||
- `cd3b890` simplify
|
||||
- `6465412` tour a11y
|
||||
- `66d2e07` Withings error wrap
|
||||
- `79bb167` MockAIProvider strict default
|
||||
- `d947563` prettier sweep
|
||||
Full deferred-item inventory at
|
||||
`.planning/v15-backlog.md`. Sections:
|
||||
|
||||
- from-Product-Lead-strategic (C.1–C.11 + v1.6+ initiatives)
|
||||
- from-design (deferred CRITICALs C1+C2 + HIGH/MED + 22 MED/LOW)
|
||||
- from-code-review HIGH/MED
|
||||
- from-security HIGH/MED
|
||||
- from-senior-dev HIGH (architecture splits) / MED / LOW
|
||||
- from-simplify (the 2 apply-no items)
|
||||
- from-Wave-C deferred (Coolify image-digest, ARM matrix)
|
||||
|
||||
---
|
||||
|
||||
## Product-Lead review's standing
|
||||
|
||||
`.planning/phase-D-product-lead-review.md` IS the strategic v1.5
|
||||
plan. No compaction needed. The reconcile report's Pointer section
|
||||
defers to it as the source-of-truth for v1.5 milestone planning.
|
||||
Marc-three-weeks-from-now reads it as-is to remember "what state is
|
||||
the app in, and what does v1.5 actually need to look like".
|
||||
@@ -0,0 +1,318 @@
|
||||
# v1.5 backlog seed
|
||||
|
||||
Source: phase-D findings (code-review / security / design / senior-dev
|
||||
/ simplify) plus `phase-D-product-lead-review.md` and Wave-C deferred
|
||||
items. Compiled: 2026-05-10 by phase-D reconcile.
|
||||
|
||||
This is the input for the v1.5 milestone planning. The Product-Lead
|
||||
review (`.planning/phase-D-product-lead-review.md`) IS the strategic
|
||||
plan for v1.5; this file collects the tactical follow-ons.
|
||||
|
||||
---
|
||||
|
||||
## From Product-Lead strategic review (the v1.5 backbone)
|
||||
|
||||
Lift directly from `phase-D-product-lead-review.md` §C ("v1.5
|
||||
Roadmap") and §D ("Follow-on initiatives v1.6+"). Sized in the
|
||||
review.
|
||||
|
||||
**Section C — v1.5 candidates (Marc to pick the 6 weeks of focus):**
|
||||
|
||||
- **C.1** Coolify image-digest auto-deploy (S, 5min Marc-side toggle).
|
||||
- **C.2** Native ARM runner matrix for docker-publish (S).
|
||||
- **C.3** Cross-user feedback aggregation prompt-tuning ratchet
|
||||
(M; depends on B5e shipped).
|
||||
- **C.4** Dedicated `/insights/compare` page (S–M;
|
||||
`comparison.insightsCallout.{lastMonth,lastYear}` keys reserved).
|
||||
- **C.5** AI streaming + prompt-version A/B + per-user prompt prefix
|
||||
(S–M + M + M; depends on C.3).
|
||||
- **C.6** Charts library decision (L; chart wrapper rewrite — must be
|
||||
decided before any new chart commit lands).
|
||||
- **C.7** iOS native client API contract freeze + bulk endpoint +
|
||||
versioned `/api/v1/` router (M).
|
||||
- **C.8** Security hardening sweep (passkey replay-attack, idempotency
|
||||
TTL configurable, audit-log retention) (S/S/M).
|
||||
- **C.9** Performance — Recharts deferred bundle on `/`,
|
||||
`/measurements`, `/mood` + SSR insights + Prisma read-replica
|
||||
(S/M/M).
|
||||
- **C.10** Cross-device backup encryption + S3 push (M).
|
||||
- **C.11** Integrations — Apple Health → Oura → Garmin (M each;
|
||||
recommended order: Apple Health first via iOS XML import).
|
||||
|
||||
Marc's 6-week focus pick from the review: **C.1 + C.2 + C.4 + C.7 +
|
||||
C.10 + C.11a Apple Health**.
|
||||
|
||||
**Section D — v1.6+ follow-on initiatives:**
|
||||
|
||||
1. Compliance-export admin tool (off B4 audit-log filter API)
|
||||
2. Anomaly-detection alerts (off B3 host-metrics)
|
||||
3. Per-prompt-version × per-provider quality dashboard
|
||||
4. "Explain like I'm 5" public preview surface
|
||||
5. Yearly health-summary email digest (off B8 comparison overlay)
|
||||
6. Rationale-driven on-device predictions (`confidence.ts` math
|
||||
client-side)
|
||||
7. Public-facing API for self-export (`/developers` page)
|
||||
|
||||
---
|
||||
|
||||
## From design review
|
||||
|
||||
### Deferred CRITICALs (root cause: scope-completion-without-route-wiring)
|
||||
|
||||
- **C1 — `/insights` does NOT mount `<InsightAdvisorCard>` /
|
||||
`<RecommendationsGrid>` / `<RecommendationCard>` / `<ConfidenceMeter>`
|
||||
/ `<RecommendationFeedback>`.** The B5c/d/e/B1b polish components are
|
||||
still test-only. Wiring requires either rewriting the 7 per-status
|
||||
status endpoints (`/api/insights/{general,blood-pressure,weight,
|
||||
pulse,bmi,mood,medication-compliance}-status`) to return the
|
||||
rationale+confidence+citation rich shape, OR migrating the page to
|
||||
consume `/api/insights/generate`'s comprehensive payload directly.
|
||||
Either path is the v1.4.17 migration the senior-dev review (H3 in
|
||||
code-review) flagged. **Defer — too wide for tonight's reconcile.**
|
||||
Workaround: v1.4.16 release notes / Marc-Brief must phrase the polish
|
||||
components as "groundwork for v1.4.17 user-facing rollout" rather
|
||||
than headline UX. Screenshots of the unmounted advisor card surface
|
||||
do NOT belong in v1.4.16 marketing material.
|
||||
|
||||
- **C2 — `<InsightsCardPreview>` (dashboard insights tile) has zero
|
||||
live imports.** Mounting on `/` requires a new GET endpoint that
|
||||
returns `User.insightsCachedText` + cache-aware staleness markers.
|
||||
The B1b commit `d2cdf9d` left this as "When dashboard wiring lands…"
|
||||
Same scope reason as C1 — defer to v1.4.17 alongside the per-status
|
||||
migration.
|
||||
|
||||
### HIGH (deferred)
|
||||
|
||||
- **H5 design — InsightsPageHero gradient `via-dracula-cyan/8` is too
|
||||
faint on mobile LCD.** Bump opacity to `/15`. Trivial; deferred
|
||||
because the gradient passes the contrast tests today and Marc's
|
||||
Apple-Health benchmarking lens is a v1.4.17 visual sweep concern.
|
||||
|
||||
- **H8 design — DE fallback-chain row overflow on Pixel 5.** The
|
||||
reviewer's premise is partly mistaken: the row buttons are
|
||||
icon-only with `aria-label` only, so DE-string-length doesn't
|
||||
affect layout. The 5-control row IS visually busy at 393 px but
|
||||
wraps cleanly with `flex-wrap`. Defer for a future settings
|
||||
polish pass.
|
||||
|
||||
### MED/LOW (deferred bucket)
|
||||
|
||||
- **M1** — App-log preview table needs card-list mobile fallback
|
||||
at `<md` (mirror api-tokens / users patterns).
|
||||
- **M2** — RecommendationFeedback success state has no path to
|
||||
revoke / change verdict.
|
||||
- **M3** — `<RecommendationsGrid>` border colours at `/70`
|
||||
opacity not contrast-verified against `--card`.
|
||||
- **M4** — `<ConfidenceMeter>` aria-label includes only the raw
|
||||
integer; add band semantic ("high confidence (75/100)").
|
||||
- **M5** — InsightsPageHero empty state with `updatedAt=null`
|
||||
feels heavy; promote `onRegenerate` button to inline CTA.
|
||||
- **M6** — Severity colour token map duplicated 3× (HeroFinding,
|
||||
RecommendationCard, RecommendationsGrid). Centralise to
|
||||
`src/lib/severity-colors.ts`.
|
||||
- **M7** — Sticky `<InsightsSectionNav>` should add
|
||||
`overscroll-x-contain` for iOS Safari back-swipe.
|
||||
- **M8** — `<HostMetricsChart>` tooltip formatter keys on
|
||||
localised name string; key on dataKey instead.
|
||||
- **M9** — Mood chart emoji glyphs render differently per OS;
|
||||
swap to lucide SmilePlus/Frown/Meh/Smile/Laugh SVGs.
|
||||
- **M10** — RecommendationCard collapsed state has no "tap for
|
||||
details" hint affordance.
|
||||
- **M11** — Loading skeleton uses unconditional staggered
|
||||
`animationDelay` ignoring prefers-reduced-motion.
|
||||
- **M12** — `/insights` first-load shows bare spinner instead of
|
||||
skeleton-mirroring-final-layout.
|
||||
- **M13** — App-log empty state doesn't distinguish "buffer empty"
|
||||
from "filter matched nothing".
|
||||
- **M14** — Settings → Export `<input type="date">` is browser-
|
||||
locale-driven. Wrap with shadcn Calendar+Popover.
|
||||
- **M15** — non-issue (HostMetricsChart Legend stacks fine).
|
||||
- **M16** — non-issue (tour anchors verified).
|
||||
- **M17** — non-issue (i18n parity green).
|
||||
- **M18** — non-issue (ConfidenceMeter ring `r=10` fits).
|
||||
- **M19** — Tile delta callout muted on neutral-direction metrics
|
||||
loses the "value did move" signal. Add muted ↑/↓ glyph.
|
||||
- **M20** — Severity Badge text uppercase but uses raw EN
|
||||
vocabulary ("URGENT" / "IMPORTANT" / …) — add
|
||||
`insights.recommendation.severity.{urgent,important,suggestion,
|
||||
info}` i18n keys.
|
||||
- **M21** — `<ScatterCorrelationChart>` (correlation cards on
|
||||
/insights) does NOT receive B1a polish. Extend
|
||||
ChartLinearGradient + RichChartTooltip.
|
||||
- **M22** — Verify `MedicationComplianceChart` 80/100/baseline
|
||||
label-stack live render once v1.4.16 deploys.
|
||||
|
||||
---
|
||||
|
||||
## From code-review
|
||||
|
||||
### HIGH (deferred)
|
||||
|
||||
- **H1** — `feedback-aggregator` bucket-key collision claim. The
|
||||
reviewer cited `.join("")` as the problem; actual code already uses
|
||||
`\x01` (SOH) as the separator. **Already-fixed; not deferred — note
|
||||
the reviewer mis-read the source.**
|
||||
- **H3** — Strict B5b/B5c/B5d AI features not wired into production
|
||||
`/api/insights/generate`. Maps directly to design-C1 root cause.
|
||||
Same v1.4.17 migration item.
|
||||
- **H4** — `findRecommendationsMissingRationale()` is a no-op on
|
||||
parsed AIInsightResponse (always returns []). Fix in v1.4.17
|
||||
alongside H3.
|
||||
- **H7** — Comparison overlay `data` may be single-period only.
|
||||
Audit the dashboard fetcher upstream to confirm the visible overlay
|
||||
maps to the prior period, not the current period shifted forward.
|
||||
Add a unit test pinning the contract.
|
||||
- **H8** — `seedKey` in ai-section race-window. Track userPicked state
|
||||
separately so chainData arrival can't overwrite a user click.
|
||||
|
||||
### MED/LOW (full bucket)
|
||||
|
||||
- **M1** — `/api/admin/audit-log/actions` unbounded groupBy(action).
|
||||
Add an index on `audit_logs.action` OR cache the list 5 min.
|
||||
- **M2** — `RecommendationCard.metricTypeToChartTypes()` falls
|
||||
through to verbatim type for unknown values.
|
||||
- **M3** — `appendLogEvent` runs unconditionally for high-volume
|
||||
background jobs. Skip kind === "background" from buffer.
|
||||
- **M5** — `chainBodySchema.providerType` double-cast hides type.
|
||||
- **M6** — `ContractCard` "draft" pill clamp dead-code path.
|
||||
- **M7** — host-metrics `BigInt → Number` no overflow guard
|
||||
(acceptable for v1.4.16 scale; document).
|
||||
- **M8** — feedback-aggregator upsert swallows errors; let pg-boss
|
||||
retry instead.
|
||||
- **M9** — `host-metric-sampler.getHostMetricRetentionDays()`
|
||||
redundant double-check.
|
||||
- **L1-L10** — Various nits (provider-runner duplicated chain
|
||||
walker, recommendations-grid stagger cap, findClosestDia
|
||||
per-sys pairing, etc.) — all flagged in the review for
|
||||
opportunistic touch-ups.
|
||||
|
||||
---
|
||||
|
||||
## From security
|
||||
|
||||
### HIGH (already-fixed in this reconcile)
|
||||
|
||||
- **H1** — meta + action.details NOT redacted at admin egress.
|
||||
**Fixed** (`fb12f09`).
|
||||
- **H2** — `/api/admin/audit-log` returned raw details without
|
||||
redaction. **Fixed** (same commit `fb12f09`).
|
||||
|
||||
### MED/LOW (deferred)
|
||||
|
||||
- **M1** — `/api/insights/feedback` had no rate limit. **Fixed**
|
||||
(`6863ecb`).
|
||||
- **M2** — `metricSourceType` is client-supplied free-form;
|
||||
pin to `aiRecommendationSchema.metricSource.type` enum.
|
||||
- **M3** — audit-log `target` substring match on raw JSON
|
||||
expensive; bound to ≥3 chars OR add GIN/trigram index.
|
||||
- **M4** — `User.aiProviderChain` priority normalisation only at
|
||||
PUT layer; mirror at parser layer for defence-in-depth.
|
||||
- **M5** — `GET /api/user/ai-provider` decrypts apiKey just for
|
||||
last-4. Store a 4-char preview alongside encrypted column.
|
||||
- **L1** — Document `RecommendationFeedback` per-user-rec storage
|
||||
trade-off in v1.4.16 summary doc.
|
||||
- **L2** — host-metrics returns ~1440 rows for 24h (acceptable).
|
||||
- **L3** — `redactSecrets` regex doesn't cover Basic auth or
|
||||
generic JWT shape. Add `Basic\s+\S+` and `\beyJ...` patterns.
|
||||
|
||||
---
|
||||
|
||||
## From senior-dev
|
||||
|
||||
### HIGH (architectural — deferred)
|
||||
|
||||
- **H1** — `src/lib/ai/` directory has 19 flat files (4,726 lines)
|
||||
with five orthogonal concerns. Re-shape to `providers/ runtime/
|
||||
schema/ domain/ prompts/`. Mechanical rename + import-rewrite.
|
||||
- **H2** — `<InsightAdvisorCard>` (690 lines) is a god-component.
|
||||
Extract `_advisor/{hero-finding, inline-charts, data-quality-
|
||||
drawer, legacy-payload-cta}.tsx`.
|
||||
- **H3** — `<RecommendationCard>` (417 lines) approaching split
|
||||
point. Extract `metricTypeToChartTypes` + `<CitationFootnote>`
|
||||
- `<RationaleCard>`.
|
||||
|
||||
### MED (deferred)
|
||||
|
||||
- **M1** — provider-runner two near-identical fallback runners.
|
||||
Inline-extract a generic `runChain<T>(chain, attempt)` higher-
|
||||
order. (Same as code-review L3.)
|
||||
- **M2** — `<RecommendationFeedback>` reaches into `useAuth()`
|
||||
directly. Pass `userId` from parent instead.
|
||||
- **M3** — Dual response-shape carries forward from v1.4.15 M6
|
||||
(`schema.ts` + `types.ts`). Bite the migration in v1.4.17.
|
||||
- **M4** — Two metric-vocab maps in different files. Extract
|
||||
`src/lib/insights/metric-vocab.ts`.
|
||||
- **M5** — `<RationaleCard>` 6-prop list will only grow; pass
|
||||
`rec={norm}` instead.
|
||||
- **M6** — `i18n.insights.recommendation.*` mixes 4 buckets at
|
||||
same depth. Re-shape to nested objects per feature bucket.
|
||||
- **M7** — `feedback-attribution.ts` reads latest audit row to
|
||||
pick provider; couples feedback to audit-log shape. Add
|
||||
`User.lastUsedProviderType` column or AppSettings cache.
|
||||
- **M8** — `feedback-aggregator` empty-string join (already-
|
||||
fixed; reviewer mis-read).
|
||||
- **M9** — Five admin sections hand-roll the same `fetch + json
|
||||
- throw`mini state machine. Promote to`src/lib/api-client.ts` `fetchJsonOrThrow<T>`.
|
||||
|
||||
### LOW
|
||||
|
||||
- **L1** — duplicate `// ─── Section Separator ───` comment in
|
||||
insight-advisor-card.tsx:284-286.
|
||||
- **L2** — `<RecommendationFeedback>` 17-line `setState during
|
||||
render` block needs a one-line CLAUDE.md-rule comment.
|
||||
- **L3** — `ProviderChainResolved` type defined in runner
|
||||
(consumer), should live with parser.
|
||||
- **L4** — `legacy-payload.ts` 55-line module could live in
|
||||
`schema.ts` next to `findRecommendationsMissingRationale()`.
|
||||
- **L5** — Confidence band thresholds in 3 separate files. Add
|
||||
`src/lib/ai/confidence-bands.ts` with `CONFIDENCE_BANDS = {…}`.
|
||||
- **L6** — `host-metric-sampler` reads env on every call.
|
||||
- **L7** — `RecommendationFeedback` model field naming verbose
|
||||
(cosmetic).
|
||||
- **L8** — `formatCitationLabel(ref, locale)` helper not
|
||||
centralised.
|
||||
- **L9** — `reminder-worker.ts` (1,350 lines) — split per queue
|
||||
under `src/lib/jobs/queues/<queue>.ts`.
|
||||
|
||||
---
|
||||
|
||||
## From simplify
|
||||
|
||||
### Apply-no (judgement calls — Marc to decide)
|
||||
|
||||
- **F1 — strict `runWithFallback` test-only.** Two paths: (a)
|
||||
delete + migrate test suite to `runRawCompletionWithFallback`,
|
||||
or (b) wire `/api/insights/generate` to the strict variant
|
||||
NOW and delete the legacy. (b) is the v1.4.17 migration the
|
||||
comment promises. Defer the call to Marc.
|
||||
- **F8 — `RecommendationCard.normalise()` indirection.** Replace
|
||||
with `recAsObject(rec)` helper. Mechanical rewrite spans 8+
|
||||
JSX sites; warrants Marc's eye on the simplified version.
|
||||
|
||||
---
|
||||
|
||||
## From Wave-C deferred (originally v1.4.16 catch-up scope)
|
||||
|
||||
- **Coolify image-digest auto-deploy trigger** — already in
|
||||
Product-Lead C.1.
|
||||
- **Native ARM runner matrix for docker-publish** — already in
|
||||
Product-Lead C.2.
|
||||
- **Per-agent worktree adoption** — held for v1.4.16, succeeded.
|
||||
Codify the "worktree-per-agent" rule in CLAUDE.md.
|
||||
- **Senior-dev H1 + H2 splits from v1.4.15** — both still open
|
||||
(carry forward into v1.4.17 architectural pass).
|
||||
- **Mood-chart H3 (chart-presentation) from v1.4.15** — chart-
|
||||
ownership rule keeps this with charts owners; pick up when
|
||||
next chart-presentation pass runs.
|
||||
- **Measurements BP grouping + DOM weight** — deferred from
|
||||
v1.4.15 A5 mobile.
|
||||
|
||||
---
|
||||
|
||||
## Process / meta
|
||||
|
||||
- **Cross-agent commit-message drift** — reduced materially in
|
||||
v1.4.16 via worktree adoption. Keep the rule.
|
||||
- **Marathon meta** — phase 0 / phase A-C / phase D / phase E
|
||||
cadence held. Multi-day scope (v1.4.x marathon → tag → release)
|
||||
is the right granularity for this project.
|
||||
@@ -62,8 +62,9 @@ describe("<CompareToggle>", () => {
|
||||
const html = render(<CompareToggle />);
|
||||
// Every segment carries the min-h-11 utility — the WCAG-compliance
|
||||
// floor we promise mobile users.
|
||||
const segmentCount = (html.match(/data-slot="compare-toggle-option-/g) ?? [])
|
||||
.length;
|
||||
const segmentCount = (
|
||||
html.match(/data-slot="compare-toggle-option-/g) ?? []
|
||||
).length;
|
||||
const minH11Count = (html.match(/min-h-11/g) ?? []).length;
|
||||
expect(segmentCount).toBe(3);
|
||||
expect(minH11Count).toBeGreaterThanOrEqual(3);
|
||||
|
||||
Reference in new issue
Block a user