Skip to content

[DASH-05] Show dashboard baseline requirements and action - #2390

Merged
Asherlc merged 6 commits into
mainfrom
codex/issue-2107
Aug 2, 2026
Merged

Asherlc merged 6 commits into
mainfrom
codex/issue-2107

Conversation

@Asherlc

@Asherlc Asherlc commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a shared server-authored baseline progress contract with required observation days, observed-day counts, blocker state, requirement, summary, and action.
  • Surface the same waiting-for-baseline evidence in the web dashboard and mobile recovery health cards.
  • Derive observed-day counts from the daily metrics query and map recovery processing state into actionable baseline blockers.
  • Includes current origin/main at cf3ca9d7d (#2110).

Tests

  • pnpm test — 1,022 files passed; 15,634 tests passed; 2 files and 21 tests skipped by the repository suite.
  • Focused baseline/web/mobile/server suite — 175 tests passed.
  • Root, server, web, and mobile pnpm tsc --noEmit — passed.
  • Biome and repository lint policy checks — passed.
  • pnpm test:integration — blocked before tests because Docker could not create issue-2107_default: all predefined address pools are fully subnetted.
  • pnpm lint — code and policy stages passed; analytics SQL lint was blocked because ClickHouse at 127.0.0.1:61874 was unavailable.

Closes #2107

Summary by CodeRabbit

  • New Features

    • Added baseline progress indicators showing requirements, observed versus required days, summaries, and recommended actions.
    • Added guidance for collecting data, insufficient variation, missing values, synchronization, and sync errors.
    • Added server-provided resting heart rate trend labels, including “Waiting for baseline.”
    • Extended mobile and web health-status views to display baseline readiness details consistently.
  • Bug Fixes

    • Improved resting heart rate status calculations and handling of invalid or unavailable measurements.
    • Health statuses now reflect active data synchronization and processing errors.

Copilot AI review requested due to automatic review settings August 2, 2026 06:51
@Asherlc Asherlc linked an issue Aug 2, 2026 that may be closed by this pull request
@cursor

cursor Bot commented Aug 2, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Asherlc, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@sourcery-ai

sourcery-ai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR introduces a shared, server‑authored baseline progress contract, wires baseline processing status and observed‑day counts into health status computation, and surfaces baseline requirements/progress/action consistently across server, web dashboard, and mobile recovery cards, including a new resting‑heart‑rate trend label that respects baseline blockers.

Sequence diagram for baseline progress propagation to dashboard

sequenceDiagram
  actor User
  participant WebDashboard
  participant dailyMetricsRouter
  participant DailyMetricsRepository
  participant ProcessingRepository
  participant BaselineProgressService as baseline_progress_ts

  User->>WebDashboard: load Dashboard
  WebDashboard->>dailyMetricsRouter: dailyMetrics.trends
  dailyMetricsRouter->>DailyMetricsRepository: getTrends
  dailyMetricsRouter->>ProcessingRepository: status({ datasets: ["recovery"] })
  ProcessingRepository-->>dailyMetricsRouter: processingSnapshot
  DailyMetricsRepository-->>dailyMetricsRouter: trends
  dailyMetricsRouter->>BaselineProgressService: baselineProcessingStatus(processingSnapshot, "recovery")
  dailyMetricsRouter->>BaselineProgressService: buildDailyMetricHealthStatuses(trends, baselineRelative, processingStatus)
  BaselineProgressService-->>dailyMetricsRouter: healthStatus(with baselineProgress)
  dailyMetricsRouter->>BaselineProgressService: buildRestingHeartRateTrendLabel({ latest, average, baselineProgress })
  BaselineProgressService-->>dailyMetricsRouter: restingHeartRateTrendLabel
  dailyMetricsRouter-->>WebDashboard: { trends, healthStatus, restingHeartRateTrendLabel }
  WebDashboard->>DashboardEvidenceOverview: render trend with restingHeartRateBaselineProgress
  WebDashboard->>HealthStatusBar: render metrics with baselineProgress
Loading

File-Level Changes

Change Details Files
Introduce a reusable baseline progress model and processing-state mapping on the server, and embed it into all health status computations.
  • Add baselineProgress and related blocker/requirement/summary/action fields to the mobile dashboard contracts and health status metric schema.
  • Implement buildBaselineProgress and baselineProcessingStatus helpers to turn observed-day counts and processing repository snapshots into user-facing baseline progress state.
  • Extend health-status service inputs with observedDays and processingStatus, and ensure all status builders attach a baselineProgress object.
  • Create a resting heart rate trend label helper that prefers baseline blockers over numeric comparison.
packages/server/src/contracts/mobile-dashboard-contracts.ts
packages/server/src/services/baseline-progress.ts
packages/server/src/services/baseline-progress.test.ts
packages/server/src/services/health-status.ts
Plumb baseline processing status and observed-day counts through daily metrics and mobile recovery flows so all metrics can show accurate baseline readiness.
  • Extend DailyMetricsRepository trends queries and schema to return per-metric sample_count_* fields and test them in unit and integration tests.
  • Fetch recovery dataset processing status via ProcessingRepository in daily-metrics and mobile-dashboard routers, map it to BaselineProcessingStatus, and pass it into health status builders.
  • Update buildDailyMetricHealthStatuses and mobile recovery tab construction to include processingStatus and observedDays for all relevant metrics, including resting heart rate and body analytics.
  • Adjust cache key version and router output schemas to include the new restingHeartRateTrendLabel and baseline-related fields.
packages/server/src/repositories/daily-metrics-repository.ts
packages/server/src/repositories/daily-metrics-repository.test.ts
packages/server/src/routers/daily-metrics.ts
packages/server/src/routers/daily-metrics.test.ts
packages/server/src/routers/daily-metrics.integration.test.ts
packages/server/src/services/mobile-recovery-tab.ts
packages/server/src/services/mobile-recovery-tab.test.ts
packages/server/src/routers/mobile-dashboard.ts
packages/server/src/routers/mobile-dashboard.test.ts
packages/server/src/routers/body-analytics.ts
Update web dashboard components and health status wiring to consume server-authored baseline progress and trend labels rather than recomputing them client-side.
  • Switch web healthStatus helpers to reuse the shared HealthStatusMetric schema and type from the server contracts instead of a local zod definition.
  • Update Dashboard trend snapshot and DashboardEvidenceOverview to accept restingHeartRateTrendLabel and restingHeartRateBaselineProgress, and to render baseline requirement/progress/action when a blocker is present.
  • Change trendPositionLabel and restingHeartRateTone to use the server-provided trend label instead of computing it from latest/average values.
  • Update Dashboard and HealthStatusBar to pass through and display baselineProgress, and refresh tests and stories to expect the new fields.
packages/web/src/lib/healthStatus.ts
packages/web/src/lib/healthStatus.test.ts
packages/web/src/components/DashboardEvidenceOverview.tsx
packages/web/src/components/DashboardEvidenceOverview.test.tsx
packages/web/src/components/DashboardEvidenceOverview.stories.tsx
packages/web/src/components/HealthStatusBar.tsx
packages/web/src/components/HealthStatusBar.test.tsx
packages/web/src/components/HealthStatusBar.stories.tsx
packages/web/src/pages/Dashboard.tsx
packages/web/src/pages/Dashboard.test.tsx
Update mobile health status cards to show baseline requirements and progress, using the shared contract, and adjust stories/tests accordingly.
  • Replace the local HealthStatusMetric type in mobile components with the shared server contract type.
  • Render a baseline progress section on each card when baselineProgress.blocker is not null, including requirement, observed vs required days, summary, and action text.
  • Add styles for the baseline progress block and update stories to demonstrate ready vs collecting baseline states.
  • Extend tests to assert that baseline requirement/progress/action text from the server is rendered and that existing behavior (no client-side reinterpretation) is preserved.
packages/mobile/components/HealthStatusCards.tsx
packages/mobile/components/HealthStatusCards.test.tsx
packages/mobile/components/HealthStatusCards.stories.tsx

Assessment against linked issues

Issue Objective Addressed Explanation
#2107 Introduce a server-side baseline progress model that captures required observation days, observed-day counts, measurable variation, and baseline blockers (e.g., syncing, missing source data, still collecting, needs variation), and attach this to health status metrics.
#2107 Update dashboard and mobile UI to display baseline requirements, progress, and explicit user action when metrics are waiting for baseline or have insufficient data, instead of just "Waiting for baseline" or "Not enough data".
#2107 Ensure resting heart rate trend labeling on the dashboard uses server-authored baseline/trend information (including blockers) rather than only comparing latest vs. average values.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Asherlc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d1e03730-16f3-43e7-bdb7-f4fd954f7452

📥 Commits

Reviewing files that changed from the base of the PR and between 2d7be53 and 4b737ae.

📒 Files selected for processing (2)
  • packages/server/src/routers/daily-metrics.integration.test.ts
  • packages/server/src/routers/router-sql.integration.test.ts
📝 Walkthrough

Walkthrough

The PR adds server-calculated baseline progress and processing states to health-status metrics. It exposes sample counts and resting-heart-rate trend labels, then renders requirements, progress, summaries, and actions in web and mobile dashboards.

Changes

Baseline progress reporting

Layer / File(s) Summary
Contracts and observation counts
packages/server/src/contracts/..., packages/server/src/repositories/...
Adds the baselineProgress contract and validated metric sample counts used to calculate observed days.
Baseline evaluation and health status
packages/server/src/services/baseline-progress.ts, packages/server/src/services/health-status.ts, packages/server/src/services/*test.ts
Calculates blockers for missing data, insufficient observations, variation, syncing, and sync errors. Propagates progress data through health-status builders.
Server trend and recovery routing
packages/server/src/routers/..., packages/server/src/services/mobile-recovery-tab.ts, packages/server/src/services/*test.ts
Loads processing status, derives resting-heart-rate trend labels, and passes processing state into recovery health-status construction.
Web dashboard rendering
packages/web/src/components/..., packages/web/src/pages/Dashboard.tsx, packages/web/src/pages/Dashboard.test.tsx
Uses server-authored trend labels and renders blocked baseline requirements, observation progress, summaries, and actions.
Mobile health-status rendering
packages/mobile/components/...
Uses the shared metric contract and renders baseline-progress details for blocked metrics.

Estimated code review effort: 4 (Complex) | ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
Show baseline progress and requirements for “Waiting for baseline” states [#2107]
Show whether sync, time, missing source data, or variation blocks the baseline [#2107]

Possibly related PRs

  • Asherlc/dofek#1870: Shares processing-status and baseline-readiness behavior across dashboard surfaces.
  • Asherlc/dofek#1868: Provides related processing-status infrastructure consumed by baseline-progress logic.
  • Asherlc/dofek#2287: Shares health-status, recovery-tab, daily-metrics, and mobile-dashboard contract changes.

Suggested labels: area/server, area/web, area/mobile, area/db, type/feature, breaking-change

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is imperative, descriptive, under 70 characters, and has no trailing punctuation, but it lacks the required area prefix. Add an area prefix such as [web], [server], or [mobile] before the existing title.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Mobile Preview

Scan to open on device:

QR code for dofek://preview/pr-2390

Channel pr-2390
Deep Link dofek://preview/pr-2390
Commit eec0a5a

To test on device:

  1. Build and install the preview client: PREVIEW_CHANNEL=pr-2390 pnpm expo prebuild --clean -p ios
  2. Or tap deep link on an existing preview build: dofek://preview/pr-2390

Each PR gets its own channel. Build a preview client with PREVIEW_CHANNEL=pr-{N} to test.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Storybook previews for eec0a5a6 are ready:

This comment updates automatically on each PR push.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Show baseline progress requirements and actions in dashboard + mobile cards

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Add a shared server-authored baseline progress contract (requirements, counts, blockers, action).
• Compute exact observed-day counts from daily metrics and map processing state to baseline
 blockers.
• Render baseline progress evidence in web dashboard components and mobile recovery health cards.
Diagram

graph TD
  W["Web dashboard UI"] --> C["Mobile dashboard contracts"] --> HS["Health-status service"] --> BP["Baseline-progress service"]
  M["Mobile health cards"] --> C
  HS --> DM["Daily-metrics repo"] --> DB[("Metrics DB")]
  R["dailyMetrics router"] --> PR["Processing repo"] --> BP
  MD["mobileDashboard router"] --> RT["Mobile recovery tab"] --> HS
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Client-derived baseline progress
  • ➕ No new server contract fields; fewer server changes
  • ➕ UI teams can iterate on copy/layout independently
  • ➖ Duplicates baseline logic across web/mobile
  • ➖ Harder to keep copy + blocker mapping consistent
  • ➖ Requires clients to understand processing states and observation-count semantics
2. Expose baseline progress via a dedicated endpoint
  • ➕ Keeps dailyMetrics response smaller/unchanged
  • ➕ Allows separate caching/TTL and evolution for baseline UX
  • ➖ Extra request/latency and more wiring per client
  • ➖ More moving parts than embedding in existing healthStatus payload

Recommendation: Keep the current server-authored BaselineProgress embedded in HealthStatusMetric. It centralizes user-facing copy/blocker mapping, guarantees web/mobile consistency, and leverages existing health-status delivery paths. The main tradeoff (larger payload + broader schema impact) is mitigated by the cache key bump and strong test coverage.

Files changed (28) +852 / -99

Enhancement (11) +375 / -59
HealthStatusCards.tsxRender baseline progress evidence in HealthStatusCards +33/-32

Render baseline progress evidence in HealthStatusCards

• Switches HealthStatusMetric typing to the shared server contract and conditionally renders baseline requirement/count/summary/action when a baseline blocker is present.

packages/mobile/components/HealthStatusCards.tsx

mobile-dashboard-contracts.tsAdd BaselineProgress schema and embed into HealthStatusMetric +24/-0

Add BaselineProgress schema and embed into HealthStatusMetric

• Defines baselineProgress schema + blocker enum and makes baselineProgress required on healthStatusMetricSchema, exporting shared types for clients.

packages/server/src/contracts/mobile-dashboard-contracts.ts

daily-metrics-repository.tsAdd observed-day sample counts to the trends query output +11/-1

Add observed-day sample counts to the trends query output

• Extends trendsRowSchema with sample_count_* fields and updates the SQL CTE to COUNT per metric for exact observed-day counts.

packages/server/src/repositories/daily-metrics-repository.ts

daily-metrics.tsReturn restingHeartRateTrendLabel and pass processingStatus into health-status +32/-8

Return restingHeartRateTrendLabel and pass processingStatus into health-status

• Fetches processing snapshot, derives baseline processingStatus, includes it when building healthStatus, and returns a server-derived restingHeartRateTrendLabel.

packages/server/src/routers/daily-metrics.ts

mobile-dashboard.tsInject recovery processingStatus into mobile recovery tab load +6/-0

Inject recovery processingStatus into mobile recovery tab load

• Fetches processing snapshot for the recovery dataset and passes derived baseline processingStatus into loadMobileRecoveryTab.

packages/server/src/routers/mobile-dashboard.ts

baseline-progress.tsIntroduce baseline progress builder and processing-status mapping +99/-0

Introduce baseline progress builder and processing-status mapping

• Adds buildBaselineProgress() producing requirement/summary/action + blockers and baselineProcessingStatus() mapping processing snapshots to syncing/sync_error/null.

packages/server/src/services/baseline-progress.ts

health-status.tsAttach baselineProgress to all health statuses; derive RHR trend label +99/-7

Attach baselineProgress to all health statuses; derive RHR trend label

• Bumps cache key version, threads observedDays + processingStatus through health-status builders, attaches baselineProgress everywhere, and adds buildRestingHeartRateTrendLabel for server-owned RHR labeling.

packages/server/src/services/health-status.ts

mobile-recovery-tab.tsEnsure recovery tab computes RHR health status and threads processingStatus +24/-1

Ensure recovery tab computes RHR health status and threads processingStatus

• Adds optional processingStatus to context and ensures resting_heart_rate always has a status (from baselineRelative if present, otherwise from raw values), with processingStatus passed into health-status builders.

packages/server/src/services/mobile-recovery-tab.ts

DashboardEvidenceOverview.tsxRender RHR baseline progress evidence and trust server trend label +27/-10

Render RHR baseline progress evidence and trust server trend label

• Extends DashboardTrendSnapshot to include trend label + BaselineProgress, uses server-provided label for tone/position, and conditionally renders baseline requirement/count/summary/action for RHR.

packages/web/src/components/DashboardEvidenceOverview.tsx

HealthStatusBar.tsxRender baseline progress section when metric is waiting for baseline +14/-0

Render baseline progress section when metric is waiting for baseline

• Displays server-authored baseline requirement/count/summary/action in the expanded metric panel when baselineProgress.blocker is present.

packages/web/src/components/HealthStatusBar.tsx

Dashboard.tsxThread server RHR trend label and baselineProgress into dashboard evidence +6/-0

Thread server RHR trend label and baselineProgress into dashboard evidence

• Extends the dailyMetrics response schema with restingHeartRateTrendLabel, finds the RHR HealthStatusMetric to pass its baselineProgress into evidence UI, and forwards the server-provided label.

packages/web/src/pages/Dashboard.tsx

Bug fix (1) +1 / -0
body-analytics.tsAdd missing processingStatus field to body-analytics health status output +1/-0

Add missing processingStatus field to body-analytics health status output

• Ensures body analytics health status objects include processingStatus (null) to match updated downstream expectations.

packages/server/src/routers/body-analytics.ts

Refactor (1) +8 / -34
healthStatus.tsUse shared server health-status schemas/types instead of duplicating Zod +8/-34

Use shared server health-status schemas/types instead of duplicating Zod

• Replaces local Zod schema with imports from dofek-server/mobile-dashboard-contracts to keep web aligned with the server contract.

packages/web/src/lib/healthStatus.ts

Tests (12) +432 / -6
HealthStatusCards.test.tsxTest rendering of server-authored baseline requirement/progress/action +64/-0

Test rendering of server-authored baseline requirement/progress/action

• Adds a regression test asserting baseline requirement text, observed-day count line, summary, and action render when the status is waiting for baseline.

packages/mobile/components/HealthStatusCards.test.tsx

daily-metrics-repository.test.tsUpdate trends-row fixtures/assertions for sample_count_* fields +13/-0

Update trends-row fixtures/assertions for sample_count_* fields

• Extends test fixtures to include sample_count_* columns and asserts the SQL includes COUNT(...) projections.

packages/server/src/repositories/daily-metrics-repository.test.ts

daily-metrics.integration.test.tsIntegration test observed-day sample counts for baseline progress +12/-0

Integration test observed-day sample counts for baseline progress

• Adds an integration assertion that sample_count_* values match seeded daily-metrics coverage (e.g., 27 days).

packages/server/src/routers/daily-metrics.integration.test.ts

daily-metrics.test.tsMock processing repository and update router expectations +47/-0

Mock processing repository and update router expectations

• Mocks ProcessingRepository.status() and updates dailyMetrics router test expectations to include sample_count_* fields and restingHeartRateTrendLabel.

packages/server/src/routers/daily-metrics.test.ts

mobile-dashboard.test.tsMock processing repository and update recovery tab expectations +12/-0

Mock processing repository and update recovery tab expectations

• Adds ProcessingRepository mock and updates expectations so loadMobileRecoveryTab receives processingStatus (null/derived) in its context.

packages/server/src/routers/mobile-dashboard.test.ts

baseline-progress.test.tsAdd unit tests for baseline progress logic and processing-state mapping +132/-0

Add unit tests for baseline progress logic and processing-state mapping

• Covers missing-source, collecting, needs-variation, ready, and syncing/sync_error precedence; also tests baselineProcessingStatus mapping.

packages/server/src/services/baseline-progress.test.ts

health-status.test.tsUpdate tests for observedDays + baseline progress evidence +47/-0

Update tests for observedDays + baseline progress evidence

• Extends fixtures with sample_count_* fields and adds coverage that insufficient-data statuses include baselineProgress requirement/summary/action from the server.

packages/server/src/services/health-status.test.ts

mobile-recovery-tab.test.tsUpdate recovery-tab tests for processingStatus plumbing +4/-1

Update recovery-tab tests for processingStatus plumbing

• Adjusts expected calls to health-status builders and weight status to include an explicit processingStatus argument.

packages/server/src/services/mobile-recovery-tab.test.ts

DashboardEvidenceOverview.test.tsxTest server-authored baseline requirement/progress/action rendering in dashboard evidence +59/-5

Test server-authored baseline requirement/progress/action rendering in dashboard evidence

• Updates helper tests to use restingHeartRateTrendLabel and adds a UI test asserting baseline requirement/count/summary/action render when baselineProgress is blocked.

packages/web/src/components/DashboardEvidenceOverview.test.tsx

HealthStatusBar.test.tsxUpdate HealthStatusBar tests to include baselineProgress field +9/-0

Update HealthStatusBar tests to include baselineProgress field

• Adds baselineProgress to the canonical serverMetric fixture so tests align with the now-required contract.

packages/web/src/components/HealthStatusBar.test.tsx

healthStatus.test.tsUpdate schema parsing tests for baselineProgress requirement +20/-0

Update schema parsing tests for baselineProgress requirement

• Extends schema tests to validate that baselineProgress is required and correctly parsed for HealthStatusMetric.

packages/web/src/lib/healthStatus.test.ts

Dashboard.test.tsxUpdate dashboard tests for new dailyMetrics fields and baselineProgress +13/-0

Update dashboard tests for new dailyMetrics fields and baselineProgress

• Adds restingHeartRateTrendLabel to mocked trend rows and ensures health status fixtures include baselineProgress.

packages/web/src/pages/Dashboard.test.tsx

Documentation (3) +36 / -0
HealthStatusCards.stories.tsxAdd baselineProgress story fixtures for ready vs collecting states +24/-0

Add baselineProgress story fixtures for ready vs collecting states

• Introduces ready/collecting BaselineProgress examples and attaches them to Storybook metrics so baseline evidence can be previewed on mobile.

packages/mobile/components/HealthStatusCards.stories.tsx

DashboardEvidenceOverview.stories.tsxUpdate stories to include server-derived RHR trend label +3/-0

Update stories to include server-derived RHR trend label

• Adds restingHeartRateTrendLabel to story trend snapshots to match the new server-owned label contract.

packages/web/src/components/DashboardEvidenceOverview.stories.tsx

HealthStatusBar.stories.tsxAdd baselineProgress to HealthStatusMetric story fixtures +9/-0

Add baselineProgress to HealthStatusMetric story fixtures

• Extends the sample metric used in stories to include baselineProgress so story rendering matches the updated contract.

packages/web/src/components/HealthStatusBar.stories.tsx

@qodo-code-review

qodo-code-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 194 rules

Grey Divider


Action required

1. Wrong missing-data blocker ✓ Resolved 🐞 Bug ≡ Correctness
Description
buildBaselineProgress classifies any null current value as "missing_source_data" and emits a "No
<metric> data" summary, even when observedObservationDays indicates there is historical data in the
window. This can produce incorrect user guidance (e.g., telling users to connect a source) when only
the latest/current observation is missing.
Code

packages/server/src/services/baseline-progress.ts[R64-67]

+  } else if (observedDays === 0 || input.value == null) {
+    blocker = "missing_source_data";
+    summary = missingSourceSummary(input.label);
+    action = missingSourceAction(input.label);
Relevance

●●● Strong

Correctness issue likely; repo has accepted similar “null data shouldn’t imply missing source”
guidance in services.

PR-#2276

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Baseline progress treats value == null as "missing_source_data" regardless of observedDays.
Separately, the trends query can return sample_count_steps > 0 while intentionally nulling
latest_steps when the latest steps date doesn’t match endDate, and health-status passes both
fields into baseline progress for the steps metric—triggering the misleading "No Steps data" state.

packages/server/src/services/baseline-progress.ts[49-76]
packages/server/src/repositories/daily-metrics-repository.ts[240-288]
packages/server/src/services/health-status.ts[290-345]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`buildBaselineProgress()` treats `input.value == null` the same as `observedDays === 0`, setting `blocker = "missing_source_data"` and using the "No <label> data is available" copy. For metrics where the *current* value can be null while historical samples exist (e.g., steps when the latest sample isn’t on `endDate`), this yields misleading baseline progress messaging and actions.

### Issue Context
- Trends SQL can return non-zero `sample_count_steps` while `latest_steps` is forced to `NULL` unless the latest steps date equals `endDate`.
- Health status construction passes `value` and `observedDays` into baseline progress, so this mismatch becomes user-visible.

### Fix Focus Areas
- packages/server/src/services/baseline-progress.ts[56-76]
- packages/server/src/repositories/daily-metrics-repository.ts[240-288]
- packages/server/src/services/health-status.ts[290-345]

### Suggested fix
1) Change the missing-source branch to trigger only when `observedDays === 0`.
2) Add a separate branch for `input.value == null` (with `observedDays > 0`) that:
  - keeps an appropriate blocker (either reuse `missing_source_data` or `collecting`, but do **not** claim there is no data in the window), and
  - uses summary/action copy that accurately reflects "no current value available" (e.g., "No current <label> value is available yet" / "Sync <label> data again").
3) Add/extend a unit test for `observedDays > 0` with `value: null` to lock the intended messaging.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Generic Error thrown in router ✓ Resolved 📘 Rule violation ≡ Correctness
Description
The dailyMetrics.trends tRPC resolver throws a generic Error, which can surface to clients
without a semantic tRPC error code. This violates the requirement to throw TRPCError for procedure
failures so clients receive consistent, actionable error responses.
Code

packages/server/src/routers/daily-metrics.ts[R116-118]

+      if (!restingHeartRateStatus) {
+        throw new Error("Daily metric health status omitted resting heart rate");
+      }
Relevance

●●● Strong

Repo precedent: router procedures should throw TRPCError (semantic codes) instead of generic Error.

PR-#1110
PR-#2045

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 722038 requires that tRPC procedure failures throw TRPCError with semantic codes.
The added code in daily-metrics.ts throws a generic Error inside the dailyMetrics.trends
procedure when restingHeartRateStatus is missing.

Rule 722038: Use TRPCError with semantic error codes for all tRPC procedure failures
packages/server/src/routers/daily-metrics.ts[116-118]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A tRPC procedure (`dailyMetrics.trends`) throws a generic `Error` (`throw new Error(...)`) instead of a `TRPCError` with a semantic `code`.

## Issue Context
The compliance checklist requires that tRPC procedure failures be thrown as `TRPCError` so the client receives structured error codes/messages.

## Fix Focus Areas
- packages/server/src/routers/daily-metrics.ts[116-118]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread packages/server/src/routers/daily-metrics.ts
Comment thread packages/server/src/services/baseline-progress.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/web/src/pages/Dashboard.test.tsx (1)

499-530: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Assert the new overview contract.

The fixture supplies restingHeartRateTrendLabel, but the assertion does not verify that Dashboard forwards it. Add a resting-heart-rate healthStatus fixture with baselineProgress, then assert both trend.restingHeartRateTrendLabel and trend.restingHeartRateBaselineProgress.

As per coding guidelines, “changed behavior must have tests rather than being dismissed as pre-existing.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/pages/Dashboard.test.tsx` around lines 499 - 530, Update the
Dashboard test’s health-status fixture to include a resting-heart-rate entry
with baselineProgress, then extend the mockDashboardEvidenceOverview assertion
to verify trend.restingHeartRateTrendLabel and
trend.restingHeartRateBaselineProgress are forwarded from Dashboard.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/server/src/repositories/daily-metrics-repository.ts`:
- Around line 251-256: Update the sample_count_resting_hr aggregation in the
daily metrics query to count only resting_hr values greater than zero, using the
query’s conditional-count mechanism. Leave the other sample-count aggregations
unchanged.

In `@packages/server/src/services/health-status.test.ts`:
- Around line 137-161: Expand the recovery-processing regression coverage across
all four sites: in packages/server/src/services/health-status.test.ts:137-161,
add syncing and sync_error cases to buildHealthStatusFromSummary and assert each
expected blocker, summary, and action; in
packages/server/src/routers/daily-metrics.test.ts:37-46, make the processing
mock configurable and verify non-ready recovery status appears in returned
resting-heart-rate baselineProgress; in
packages/server/src/routers/mobile-dashboard.test.ts:154-163, verify the
normalized non-ready status is passed to loadMobileRecoveryTab; and in
packages/server/src/services/mobile-recovery-tab.test.ts:588-605, pass non-ready
status through the test context and assert every health-status builder receives
it.

In `@packages/server/src/services/mobile-recovery-tab.ts`:
- Around line 264-270: Update the label passed by buildHealthStatusFromValues
for the spo2 metric from the acronym-only text to “Blood Oxygen Saturation
(SpO2)”, preserving the existing metric, values, intent, and processingStatus.

In `@packages/web/src/components/DashboardEvidenceOverview.test.tsx`:
- Around line 16-30: Add null and undefined test cases for
restingHeartRateTrendLabel in the trendPositionLabel tests, using the existing
heart-rate inputs and expecting "Waiting for baseline". Ensure the tests cover
the fallback behavior when the optional label is absent.

In `@packages/web/src/components/HealthStatusBar.stories.tsx`:
- Around line 21-29: Add blocked-baseline Storybook coverage in
packages/web/src/components/HealthStatusBar.stories.tsx at lines 21-29 by
setting baselineProgress.blocker to a non-null value and providing visible
requirement, progress, summary, and action content. Also update
packages/web/src/components/DashboardEvidenceOverview.stories.tsx at line 26 so
restingHeartRateBaselineProgress.blocker is set and its baseline-progress
content is visible.

In `@packages/web/src/components/HealthStatusBar.test.tsx`:
- Around line 20-28: Add a blocked baseline-progress fixture in the
HealthStatusBar tests with a non-null blocker, then assert the rendered
requirement, observed/required day count, summary, and action for that state.
Keep the existing ready-state fixture and assertions unchanged, and target the
baselineProgress test setup and assertions covering the HealthStatusBar blocked
section.

---

Outside diff comments:
In `@packages/web/src/pages/Dashboard.test.tsx`:
- Around line 499-530: Update the Dashboard test’s health-status fixture to
include a resting-heart-rate entry with baselineProgress, then extend the
mockDashboardEvidenceOverview assertion to verify
trend.restingHeartRateTrendLabel and trend.restingHeartRateBaselineProgress are
forwarded from Dashboard.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 82930678-53aa-41bf-a3bb-d09c59af46e3

📥 Commits

Reviewing files that changed from the base of the PR and between cf3ca9d and 2d23ce9.

📒 Files selected for processing (28)
  • packages/mobile/components/HealthStatusCards.stories.tsx
  • packages/mobile/components/HealthStatusCards.test.tsx
  • packages/mobile/components/HealthStatusCards.tsx
  • packages/server/src/contracts/mobile-dashboard-contracts.ts
  • packages/server/src/repositories/daily-metrics-repository.test.ts
  • packages/server/src/repositories/daily-metrics-repository.ts
  • packages/server/src/routers/body-analytics.ts
  • packages/server/src/routers/daily-metrics.integration.test.ts
  • packages/server/src/routers/daily-metrics.test.ts
  • packages/server/src/routers/daily-metrics.ts
  • packages/server/src/routers/mobile-dashboard.test.ts
  • packages/server/src/routers/mobile-dashboard.ts
  • packages/server/src/services/baseline-progress.test.ts
  • packages/server/src/services/baseline-progress.ts
  • packages/server/src/services/health-status.test.ts
  • packages/server/src/services/health-status.ts
  • packages/server/src/services/mobile-recovery-tab.test.ts
  • packages/server/src/services/mobile-recovery-tab.ts
  • packages/web/src/components/DashboardEvidenceOverview.stories.tsx
  • packages/web/src/components/DashboardEvidenceOverview.test.tsx
  • packages/web/src/components/DashboardEvidenceOverview.tsx
  • packages/web/src/components/HealthStatusBar.stories.tsx
  • packages/web/src/components/HealthStatusBar.test.tsx
  • packages/web/src/components/HealthStatusBar.tsx
  • packages/web/src/lib/healthStatus.test.ts
  • packages/web/src/lib/healthStatus.ts
  • packages/web/src/pages/Dashboard.test.tsx
  • packages/web/src/pages/Dashboard.tsx

Comment thread packages/server/src/repositories/daily-metrics-repository.ts
Comment thread packages/server/src/services/health-status.test.ts
Comment thread packages/server/src/services/mobile-recovery-tab.ts
Comment thread packages/web/src/components/DashboardEvidenceOverview.test.tsx
Comment thread packages/web/src/components/HealthStatusBar.stories.tsx
Comment thread packages/web/src/components/HealthStatusBar.test.tsx
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

# Conflicts:
#	packages/mobile/components/HealthStatusCards.tsx
#	packages/server/src/contracts/mobile-dashboard-contracts.ts
#	packages/server/src/services/health-status.test.ts
#	packages/server/src/services/health-status.ts
#	packages/web/src/lib/healthStatus.test.ts
#	packages/web/src/lib/healthStatus.ts
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/web/src/pages/Dashboard.test.tsx (1)

499-499: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert forwarding of restingHeartRateTrendLabel.

The fixture supplies "below average", but the assertion at Line 518 does not verify that Dashboard passes it to DashboardEvidenceOverview. Add restingHeartRateTrendLabel: "below average" to the expected trend object.

As per coding guidelines, “changed behavior must have tests rather than being dismissed as pre-existing.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/pages/Dashboard.test.tsx` at line 499, Update the Dashboard
test’s expected trend object in the DashboardEvidenceOverview assertion to
include restingHeartRateTrendLabel: "below average", matching the fixture and
verifying Dashboard forwards the value.

Source: Coding guidelines

packages/server/src/services/mobile-recovery-tab.ts (1)

251-257: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Exclude non-positive fallback resting-heart-rate values.

buildHealthStatusFromValues() accepts every finite value. When baselineRelative has no resting-heart-rate metric, Line 254 forwards 0 and negative resting_hr values. DailyMetricsRepository.getTrends() treats only resting_hr > 0 as valid.

This fallback can display an invalid rate, overstate observedObservationDays, and complete a baseline prematurely. Filter fallback values with resting_hr > 0. Add a regression case with zero, negative, and positive values.

Proposed fix
-        values: hrvBaseline.flatMap((row) => (row.resting_hr == null ? [] : [row.resting_hr])),
+        values: hrvBaseline.flatMap((row) =>
+          row.resting_hr != null && row.resting_hr > 0 ? [row.resting_hr] : [],
+        ),

As per coding guidelines, “Write tests first; bug fixes require a failing regression test before implementation, and changed behavior must have tests.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/src/services/mobile-recovery-tab.ts` around lines 251 - 257,
Update the fallback values construction in the health-status flow around
buildHealthStatusFromValues to include only resting_hr values greater than zero,
matching DailyMetricsRepository.getTrends validation. Add a regression test
covering zero, negative, and positive fallback values, verifying only the
positive value contributes to the status and observation-day calculations.

Source: Coding guidelines

packages/mobile/components/HealthStatusCards.stories.tsx (1)

132-164: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Add baselineProgress to both story metrics.

HealthStatusMetric requires baselineProgress. The consumer in packages/mobile/components/HealthStatusCards.tsx reads metric.baselineProgress.blocker at Line 77. Without this field, the story can fail type checking and throw when Storybook renders it.

Add baselineProgress: readyBaselineProgress to both the HRV and Steps objects.

Proposed fixture fix
         explanation: "Heart Rate Variability (HRV) is above your baseline.",
+        baselineProgress: readyBaselineProgress,
       },
@@
         explanation: "Steps is close to your usual range.",
+        baselineProgress: readyBaselineProgress,
       },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/mobile/components/HealthStatusCards.stories.tsx` around lines 132 -
164, Update both the HRV and Steps metric objects in the story fixture to
include baselineProgress: readyBaselineProgress, matching the required
HealthStatusMetric shape and the consumer in HealthStatusCards. Leave the
existing metric values unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/mobile/components/HealthStatusCards.stories.tsx`:
- Around line 132-164: Update both the HRV and Steps metric objects in the story
fixture to include baselineProgress: readyBaselineProgress, matching the
required HealthStatusMetric shape and the consumer in HealthStatusCards. Leave
the existing metric values unchanged.

In `@packages/server/src/services/mobile-recovery-tab.ts`:
- Around line 251-257: Update the fallback values construction in the
health-status flow around buildHealthStatusFromValues to include only resting_hr
values greater than zero, matching DailyMetricsRepository.getTrends validation.
Add a regression test covering zero, negative, and positive fallback values,
verifying only the positive value contributes to the status and observation-day
calculations.

In `@packages/web/src/pages/Dashboard.test.tsx`:
- Line 499: Update the Dashboard test’s expected trend object in the
DashboardEvidenceOverview assertion to include restingHeartRateTrendLabel:
"below average", matching the fixture and verifying Dashboard forwards the
value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 850074a0-70d4-4a0e-a3c0-461e96b643fd

📥 Commits

Reviewing files that changed from the base of the PR and between 2d23ce9 and 2d7be53.

📒 Files selected for processing (24)
  • packages/mobile/components/HealthStatusCards.stories.tsx
  • packages/mobile/components/HealthStatusCards.test.tsx
  • packages/mobile/components/HealthStatusCards.tsx
  • packages/server/src/contracts/mobile-dashboard-contracts.ts
  • packages/server/src/repositories/daily-metrics-repository.ts
  • packages/server/src/routers/daily-metrics.integration.test.ts
  • packages/server/src/routers/daily-metrics.test.ts
  • packages/server/src/routers/daily-metrics.ts
  • packages/server/src/routers/mobile-dashboard.test.ts
  • packages/server/src/routers/router-sql.integration.test.ts
  • packages/server/src/services/baseline-progress.test.ts
  • packages/server/src/services/baseline-progress.ts
  • packages/server/src/services/health-status.test.ts
  • packages/server/src/services/health-status.ts
  • packages/server/src/services/mobile-recovery-tab.test.ts
  • packages/server/src/services/mobile-recovery-tab.ts
  • packages/web/src/components/DashboardEvidenceOverview.stories.tsx
  • packages/web/src/components/DashboardEvidenceOverview.test.tsx
  • packages/web/src/components/HealthStatusBar.stories.tsx
  • packages/web/src/components/HealthStatusBar.test.tsx
  • packages/web/src/components/HealthStatusBar.tsx
  • packages/web/src/pages/Dashboard.test.tsx
  • packages/web/src/pages/Dashboard.tsx
  • src/db/schema/core.ts

@codereviewbot-ai

codereviewbot-ai Bot commented Aug 2, 2026

Copy link
Copy Markdown

LGTM! 🚀

Summary of Review

  • Contracts & Schemas: baselineProgressSchema and baselineProgressBlockerSchema are correctly integrated into healthStatusMetricSchema and typed across server, web, and mobile contracts.
  • SQL & Repositories: sample_count_resting_hr in daily-metrics-repository.ts properly counts resting_hr > 0 matching representative value predicates.
  • Service Logic: baseline-progress.ts and health-status.ts handle sync states, missing data, observation counts, and variation checks cleanly without duplicate metric entries.
  • Router Integration: daily-metrics.ts throws semantic TRPCError with code INTERNAL_SERVER_ERROR as required for router procedure failures.
  • Testing: Comprehensive unit and integration test coverage is present across all modified services, repositories, routers, and components.

🤖 Reviewed by codereviewbot.ai - Catch bugs before your team does.

@Asherlc
Asherlc merged commit c1b0ab1 into main Aug 2, 2026
107 checks passed
@Asherlc
Asherlc deleted the codex/issue-2107 branch August 2, 2026 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DASH-05] Waiting for baseline omits requirements and user action

2 participants