Skip to content

fix(training): neutralize volume trends - #2324

Merged
Asherlc merged 4 commits into
mainfrom
issue-2113-neutral-training-trends
Jul 30, 2026
Merged

Asherlc merged 4 commits into
mainfrom
issue-2113-neutral-training-trends

Conversation

@Asherlc

@Asherlc Asherlc commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • replace the unsupported isProgressing judgment with server-owned descriptive volume direction
  • render increasing, decreasing, and stable exercise-volume trends with explicit neutral text and one neutral chart color
  • rename the Strength section to describe exercise volume rather than imply that more load is inherently desirable

Validation

  • pnpm vitest run --project unit packages/server/src/repositories/strength-repository.test.ts packages/server/src/routers/strength-stress.test.ts packages/web/src/components/ProgressiveOverloadCards.test.tsx (59 passed)
  • pnpm --dir packages/server exec tsc --noEmit
  • pnpm --dir packages/web exec tsc --noEmit
  • pnpm exec tsc --noEmit
  • pnpm --dir packages/web exec storybook build
  • targeted Biome and cspell checks

Platform parity

Mobile has no progressive-overload query or rendering surface, so there is no native production behavior to change. The descriptive contract remains available to any future consumer.

Local environment evidence

The broad pnpm test run passed the changed tests and produced no assertion failure before an unrelated Compose wrapper test stalled for 3:05 in docker compose ... port db 5432. The runner was stopped with exit 130 without retry or workaround; the unresolved local daemon evidence is recorded in docs/production-incident-baseline.md. Exact-head CI is authoritative for the full suite and DB shards.

Fixes #2113

Summary by Sourcery

Neutralize strength progressive-overload volume trends by replacing the boolean progression judgment with a descriptive server-owned trend and updating the web UI to present volume direction neutrally.

New Features:

  • Expose an explicit trend field (increasing, decreasing, stable) in the progressive overload server response for each exercise.
  • Display exercise weekly volume direction in the Strength training tab using neutral text labels and a single chart color instead of positive/negative indicators.

Enhancements:

  • Rename the Strength progressive overload section and empty-state copy to describe exercise volume trends rather than imply desirability of load changes.
  • Add a TDD plan document outlining the neutral strength volume trends change and its validation strategy.

Documentation:

  • Document the neutral strength volume trend behavior and scope in a new superpowers plan file.
  • Record a local Docker daemon Compose-port stall as unresolved evidence in the production incident baseline, clarifying CI as the authoritative validation gate.

Tests:

  • Expand server unit, router, and stress tests to assert the new descriptive trend contract and serialization.
  • Add web component tests for ProgressiveOverloadCards to verify neutral styling, explicit trend text, and consistent chart coloring.
  • Update Storybook fixtures to match the new progressive overload trend contract.

Chores:

  • Adjust type definitions and interfaces across server and web to remove the isProgressing flag in favor of the new trend type.

Summary by cubic

Replaces the boolean progression judgment with a server-owned trend and updates the Strength UI to neutral text and a single blue chart color, with slopes formatted in the user’s units. Fixes #2113.

  • Refactors

    • Server: ProgressiveOverload now exposes trend (increasing | decreasing | stable) and removes isProgressing; strength.progressiveOverload returns trend and exports ProgressiveOverloadTrend.
    • Web: ProgressiveOverloadCards shows “Increasing/Decreasing/Stable X kg/lb/week” with an absolute slope in the selected units, one neutral sparkline color, and no arrows; section retitled to “Exercise Volume Trends” with neutral empty-state copy.
    • Tests and Storybook updated; router and stress tests expect trend; new component test verifies neutral styling and unit formatting.
  • Migration

    • Replace uses of isProgressing with trend.
    • Show the absolute slopeKgPerWeek with a direction label, formatted in the selected weight units; do not infer desirability from color or icons.

Written for commit a173e1f. Summary will update on new commits.

Review in cubic

Replace the unsupported progression judgment with descriptive server-owned direction because no exercise goal or plan context exists.\n\nRefs #2113
Copilot AI review requested due to automatic review settings July 30, 2026 00:18
@cursor

cursor Bot commented Jul 30, 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.

@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

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.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 48 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: 58b069e8-42d4-47ce-9f2c-785b5ccc3ad8

📥 Commits

Reviewing files that changed from the base of the PR and between 9e06a07 and a173e1f.

📒 Files selected for processing (11)
  • docs/production-incident-baseline.md
  • docs/superpowers/plans/2026-07-29-neutral-strength-volume-trends.md
  • packages/server/src/repositories/strength-repository.test.ts
  • packages/server/src/repositories/strength-repository.ts
  • packages/server/src/routers/router.integration.test.ts
  • packages/server/src/routers/strength-stress.test.ts
  • packages/server/src/routers/strength.ts
  • packages/web/src/components/ProgressiveOverloadCards.stories.tsx
  • packages/web/src/components/ProgressiveOverloadCards.test.tsx
  • packages/web/src/components/ProgressiveOverloadCards.tsx
  • packages/web/src/routes/training/strength.lazy.tsx

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.

@sourcery-ai

sourcery-ai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Server and web training strength volume trends are changed from a binary ‘isProgressing’ judgment to a descriptive trend direction, and the UI is updated to render neutral text and chart colors while documenting the validation and incident context.

Sequence diagram for neutral exercise volume trend delivery

sequenceDiagram
  actor User
  participant StrengthTab
  participant strengthRouter
  participant StrengthRepository
  participant ProgressiveOverload
  participant ProgressiveOverloadCards

  User->>StrengthTab: open Strength tab
  StrengthTab->>strengthRouter: progressiveOverload({ days })
  strengthRouter->>StrengthRepository: getProgressiveOverload(days)
  StrengthRepository->>ProgressiveOverload: new ProgressiveOverload(exerciseName, weeklyVolumes)
  StrengthRepository->>ProgressiveOverload: toDetail()
  ProgressiveOverload-->>StrengthRepository: { exerciseName, weeklyVolumes, slopeKgPerWeek, trend }
  StrengthRepository-->>strengthRouter: ProgressiveOverloadRow[]
  strengthRouter-->>StrengthTab: ProgressiveOverloadRow[]
  StrengthTab->>ProgressiveOverloadCards: render ProgressiveOverloadCards({ exercises })
  ProgressiveOverloadCards->>ProgressiveOverloadCards: trendLabel(trend)
  ProgressiveOverloadCards->>SparklineChart: SparklineChart({ values })
  SparklineChart-->>User: neutral blue volume trend chart
Loading

File-Level Changes

Change Details Files
Replace boolean progression judgment with descriptive trend direction in the strength progressive overload domain and API contract.
  • Introduce ProgressiveOverloadTrend union type with increasing/decreasing/stable values.
  • Replace ProgressiveOverload.isProgressing getter with trend getter derived from slopeKgPerWeek.
  • Update ProgressiveOverload.toDetail to serialize trend instead of isProgressing.
  • Adjust ProgressiveOverload unit tests to assert trend values for positive, negative, and zero slopes.
  • Update StrengthRepository progressive overload query tests to assert trend === 'increasing' instead of isProgressing === true.
packages/server/src/repositories/strength-repository.ts
packages/server/src/repositories/strength-repository.test.ts
Update TRPC strength router types and tests to use descriptive trend direction in the progressiveOverload response.
  • Export ProgressiveOverloadTrend type from repository and reuse it in ProgressiveOverloadRow.trend.
  • Change ProgressiveOverloadRow interface to include trend: ProgressiveOverloadTrend instead of isProgressing: boolean.
  • Update router integration test to expect trend field and validate it is 'increasing' with positive slope.
  • Update strength router stress test to assert trend === 'increasing' for sample data.
packages/server/src/routers/strength.ts
packages/server/src/routers/router.integration.test.ts
packages/server/src/routers/strength-stress.test.ts
Render exercise volume trends neutrally in the Strength web UI, using descriptive text and a single neutral sparkline color instead of positive/negative styling.
  • Remove isProgressing prop from SparklineChart and stop using statusColors for danger vs success.
  • Configure sparkline series to always use chartColors.blue for line and area styles.
  • Replace up/down arrow glyph and accent/red conditional styling with a simple exercise name header.
  • Display trendLabel(exercise.trend) and absolute slope as neutral text-muted kg/week description.
  • Update empty state copy to 'No exercise volume trends' and rename Strength tab section title/subtitle to focus on exercise volume trends.
  • Adjust Storybook fixture exercises to use trend field values instead of isProgressing.
packages/web/src/components/ProgressiveOverloadCards.tsx
packages/web/src/components/ProgressiveOverloadCards.stories.tsx
packages/web/src/routes/training/strength.lazy.tsx
Add web unit tests to enforce neutral volume trend rendering and stable trend labeling.
  • Mock DofekChart to introspect the chart option and capture series color.
  • Verify Increasing/Decreasing text labels, absence of arrow glyphs, and use of text-muted styling.
  • Assert that sparkline charts for increasing and decreasing trends both use chartColors.blue.
  • Verify that a zero slope with trend 'stable' renders as 'Stable 0.0 kg/week' with muted styling.
packages/web/src/components/ProgressiveOverloadCards.test.tsx
Document the neutral strength-volume TDD plan and the local Docker Compose incident affecting test runs, without changing product behavior.
  • Add a superpowers TDD plan describing goals, scope, evidence, and tasks for neutral strength volume trends.
  • Append a production-incident-baseline entry explaining the local Docker daemon Compose port stall, its status, evidence, and validation strategy relying on CI.
docs/superpowers/plans/2026-07-29-neutral-strength-volume-trends.md
docs/production-incident-baseline.md

Assessment against linked issues

Issue Objective Addressed Explanation
#2113 Remove positive/negative visual status cues (up/down arrows, green/red colors) from training volume trends and replace them with neutral styling.
#2113 Represent exercise volume trends in a neutral, descriptive way across the API and UI (e.g., replacing boolean progression judgment with descriptive trend labels and neutral naming).

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

@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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Neutralize strength volume trends (server-owned trend + neutral UI)

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Replace boolean isProgressing with a server-owned trend (increasing/decreasing/stable) for
 volume direction.
• Render exercise volume trends neutrally in the Strength tab (no arrows, single chart color,
 updated copy).
• Update/extend server + web tests, Storybook fixture, and add supporting documentation/evidence
 notes.
Diagram

graph TD
  W["Web: Strength tab"] --> C["ProgressiveOverloadCards"] --> API(("tRPC strength.progressiveOverload")) --> R["Server: strength router"] --> SR["StrengthRepository"] --> PO["ProgressiveOverload.trend"]
  PO -- "trend + slope" --> C
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Compute trend client-side from `slopeKgPerWeek`
  • ➕ Avoids an API contract change; fewer server updates
  • ➕ Allows different UIs to pick their own wording
  • ➖ Duplicates logic across consumers; easy to drift
  • ➖ Harder to keep typed contracts consistent across surfaces
  • ➖ Still requires deciding and standardizing stable/increasing/decreasing somewhere
2. Keep `isProgressing`, but rename to a neutral boolean (e.g., `isIncreasing`)
  • ➕ Smaller payload and simpler UI conditional logic
  • ➕ Minimal change to existing code patterns
  • ➖ Still loses information (no explicit stable state) unless extended
  • ➖ Boolean semantics are brittle and invite value judgments in naming/styling
3. Introduce tolerance/goal-aware evaluation (e.g., deload vs progress)
  • ➕ Could produce genuinely meaningful “good/bad” or target-based guidance
  • ➕ Accounts for noise and small slope changes
  • ➖ Requires new domain modeling (goals/plan context) and product decisions
  • ➖ Higher scope and risk than needed for this issue

Recommendation: The PR’s approach (server-owned descriptive trend + neutral web rendering) is the best fit for the current domain constraints: the server can consistently classify slope sign (including an explicit stable case), and the UI can present direction without implying desirability. Client-side derivation and boolean renames were viable but either duplicate logic or under-express the stable state; goal-aware evaluation is out of scope without additional models.

Files changed (11) +208 / -48

Enhancement (3) +20 / -25
strength.tsUpdate strength router types to expose 'trend' +5/-2

Update strength router types to expose 'trend'

• Imports the new 'ProgressiveOverloadTrend' type and replaces the 'ProgressiveOverloadRow' boolean field with a typed 'trend' property. Keeps the router contract aligned with repository detail serialization.

packages/server/src/routers/strength.ts

ProgressiveOverloadCards.tsxRender trends neutrally (single color, no arrows, descriptive labels) +14/-22

Render trends neutrally (single color, no arrows, descriptive labels)

• Removes positive/negative arrow and status color styling and switches the sparkline to a single neutral blue color. Uses 'trend' + absolute slope magnitude with explicit labels (Increasing/Decreasing/Stable) and updates the empty-state copy to “No exercise volume trends.”

packages/web/src/components/ProgressiveOverloadCards.tsx

strength.lazy.tsxRename Strength section to “Exercise Volume Trends” +1/-1

Rename Strength section to “Exercise Volume Trends”

• Renames the Strength UI section title and subtitle to describe exercise volume direction without implying that increased load is inherently desirable.

packages/web/src/routes/training/strength.lazy.tsx

Bug fix (1) +8 / -4
strength-repository.tsReplace 'isProgressing' with 'trend' on ProgressiveOverload detail +8/-4

Replace 'isProgressing' with 'trend' on ProgressiveOverload detail

• Adds a 'ProgressiveOverloadTrend' union type and derives 'trend' from the slope sign (positive/increasing, negative/decreasing, zero/stable). Updates 'toDetail()' to expose 'trend' instead of a progression boolean.

packages/server/src/repositories/strength-repository.ts

Tests (4) +78 / -16
strength-repository.test.tsUpdate ProgressiveOverload tests to assert descriptive trend +9/-8

Update ProgressiveOverload tests to assert descriptive trend

• Replaces 'isProgressing' assertions with 'trend' expectations for positive, negative, and exact-zero slopes. Updates repository-level progressive overload expectations to match the new trend contract.

packages/server/src/repositories/strength-repository.test.ts

router.integration.test.tsUpdate router integration coverage for new progressive overload contract +3/-6

Update router integration coverage for new progressive overload contract

• Adjusts the integration test’s expected response shape to include 'trend' instead of 'isProgressing'. Verifies 'trend' and slope direction align for the seeded progressive overload case.

packages/server/src/routers/router.integration.test.ts

strength-stress.test.tsUpdate strength router stress test for descriptive direction +2/-2

Update strength router stress test for descriptive direction

• Updates the router stress test to assert 'trend: increasing' rather than 'isProgressing: true' alongside the regression slope check.

packages/server/src/routers/strength-stress.test.ts

ProgressiveOverloadCards.test.tsxAdd component tests for neutral trend rendering +64/-0

Add component tests for neutral trend rendering

• Adds jsdom tests verifying explicit Increasing/Decreasing/Stable text, absence of arrow glyphs, and consistent use of a single neutral sparkline color. Mocks the chart component to inspect serialized chart options deterministically.

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

Documentation (2) +99 / -0
production-incident-baseline.mdRecord local Docker Compose port-lookup stall during test run +32/-0

Record local Docker Compose port-lookup stall during test run

• Adds an incident entry documenting a local-only test stall in a Compose port lookup. Clarifies there was no assertion failure and that CI remains the authoritative validation gate for merge decisions.

docs/production-incident-baseline.md

2026-07-29-neutral-strength-volume-trends.mdAdd TDD plan for neutral strength volume trends +67/-0

Add TDD plan for neutral strength volume trends

• Introduces a scoped plan describing the motivation, accessibility references, contract changes, and test strategy for neutralizing volume trend presentation. Documents explicit non-goals (no desirability inference, no tolerance band, no mobile feature).

docs/superpowers/plans/2026-07-29-neutral-strength-volume-trends.md

Other (1) +3 / -3
ProgressiveOverloadCards.stories.tsxUpdate Storybook fixture to use 'trend' +3/-3

Update Storybook fixture to use 'trend'

• Migrates Storybook exercise fixtures from 'isProgressing' to 'trend' values for increasing and decreasing examples. Ensures stories remain representative after the contract change.

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

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Storybook previews for 03cb13ba are ready:

This comment updates automatically on each PR push.

@qodo-code-review

qodo-code-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Context used
✅ Compliance rules (platform): 183 rules

Grey Divider


Remediation recommended

1. Rounded slope misclassifies trend 🐞 Bug ≡ Correctness
Description
ProgressiveOverload.trend classifies direction using slopeKgPerWeek, which is rounded to 2
decimals, so small non-zero regression slopes can round to 0 and be serialized as "stable". This
contradicts the documented “exact-zero boundary / no tolerance” behavior and can hide real (small)
increases/decreases.
Code

packages/server/src/repositories/strength-repository.ts[R102-105]

+  get trend(): ProgressiveOverloadTrend {
+    if (this.slopeKgPerWeek > 0) return "increasing";
+    if (this.slopeKgPerWeek < 0) return "decreasing";
+    return "stable";
Relevance

●●● Strong

Team previously accepted fixes to avoid rounding before threshold comparisons; likely adjust trend
logic to use unrounded slope.

PR-#2236

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The server rounds the regression slope in slopeKgPerWeek, then trend compares that rounded value
to zero; this means near-zero non-zero slopes can be rounded to 0 and treated as stable, despite
the plan explicitly requiring an exact-zero boundary and no tolerance.

packages/server/src/repositories/strength-repository.ts[98-106]
docs/superpowers/plans/2026-07-29-neutral-strength-volume-trends.md[7-9]

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

### Issue description
`ProgressiveOverload.trend` currently determines increasing/decreasing/stable using `this.slopeKgPerWeek`, but `slopeKgPerWeek` is rounded to 2 decimals. This introduces an unintended tolerance: any raw slope in ~(-0.005, 0.005) rounds to 0, producing `trend: "stable"` even when the underlying regression slope is non-zero.

### Issue Context
The plan doc explicitly calls for using the existing *exact-zero* boundary and *not* inventing a stability tolerance. The current implementation violates that by basing the sign check on a rounded value.

### Fix Focus Areas
- packages/server/src/repositories/strength-repository.ts[98-115]

### Suggested fix
- Compute the raw slope once (e.g., `const rawSlope = linearRegressionSlope(this.#weeklyVolumes)`), then:
 - Derive `trend` from `rawSlope` (exact sign check; `rawSlope === 0` => stable).
 - Keep `slopeKgPerWeek` as the rounded presentation value (derived from `rawSlope`).
- Bonus (same refactor): avoid recomputing regression multiple times by deriving both `slopeKgPerWeek` and `trend` from the single `rawSlope` value (either by caching in `toDetail()` or via a private memoized field).

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


2. Hardcoded kg/week in cards ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
ProgressiveOverloadCards renders a user-facing unit string kg/week as a hardcoded literal. This
violates the requirement to centralize unit strings via shared formatting/i18n utilities.
Code

packages/web/src/components/ProgressiveOverloadCards.tsx[52]

+            {trendLabel(exercise.trend)} {formatNumber(Math.abs(exercise.slopeKgPerWeek))} kg/week
Relevance

●●● Strong

Unit-string centralization is commonly enforced; prior accepted changes replaced hardcoded units
with shared unit/formatter labels.

PR-#1963
PR-#2319

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 722048 requires user-facing unit markers to come from a shared formatter/i18n layer
rather than being embedded in UI string literals. The modified card text includes a hardcoded
kg/week literal.

Rule 722048: Centralize user-facing unit strings in a shared formatter or i18n layer
packages/web/src/components/ProgressiveOverloadCards.tsx[51-53]

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

## Issue description
The UI hardcodes the unit label `kg/week` in a user-facing string.

## Issue Context
The codebase already has shared unit conversion/formatting utilities (e.g., `useUnitConverter()` and `formatMeasurementText(...)`) intended to avoid duplicated unit literals and support different unit systems.

## Fix Focus Areas
- packages/web/src/components/ProgressiveOverloadCards.tsx[51-54]
- packages/web/src/components/ProgressiveOverloadCards.test.tsx[36-39]
- packages/web/src/components/ProgressiveOverloadCards.test.tsx[62-62]

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



Informational

3. ProgressiveOverloadCards test renders component 📜 Skill insight ▣ Testability
Description
ProgressiveOverloadCards.test.tsx renders the React component via Testing Library instead of
exercising exported builder functions and asserting on returned config objects. This violates the
required UI testing approach and can lead to brittle tests that depend on rendering details.
Code

packages/web/src/components/ProgressiveOverloadCards.test.tsx[R16-34]

+  it("describes volume direction without positive or negative status styling", () => {
+    render(
+      <ProgressiveOverloadCards
+        exercises={[
+          {
+            exerciseName: "Back Squat",
+            weeklyVolumes: [4800, 5100, 5450],
+            slopeKgPerWeek: 325,
+            trend: "increasing",
+          },
+          {
+            exerciseName: "Deadlift",
+            weeklyVolumes: [4200, 4050, 3900],
+            slopeKgPerWeek: -150,
+            trend: "decreasing",
+          },
+        ]}
+      />,
+    );
Relevance

● Weak

Very close precedent: team rejected refactoring UI tests to avoid rendering and instead test
exported builders/configs.

PR-#2278

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 722152 requires UI tests to call exported builder functions instead of rendering
components. The added test uses render(<ProgressiveOverloadCards ... />) which directly violates
that requirement.

packages/web/src/components/ProgressiveOverloadCards.test.tsx[16-34]
Skill: write-tests

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

## Issue description
The new UI test renders `ProgressiveOverloadCards` instead of testing exported builder functions (e.g., ECharts option builders) as required.

## Issue Context
Compliance requires UI component tests to call exported builder functions and assert on returned configuration objects, not render components.

## Fix Focus Areas
- packages/web/src/components/ProgressiveOverloadCards.test.tsx[16-46]
- packages/web/src/components/ProgressiveOverloadCards.tsx[11-29]

ⓘ 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/web/src/components/ProgressiveOverloadCards.tsx Outdated
Comment thread packages/server/src/repositories/strength-repository.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.

@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.

@Asherlc
Asherlc merged commit 35642f5 into main Jul 30, 2026
101 checks passed
@Asherlc
Asherlc deleted the issue-2113-neutral-training-trends branch July 30, 2026 01:18
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.

[TRAIN-05] Up arrows and green styling imply more load is always desirable

2 participants