Skip to content

[DQ-11] Lead with plain-language training labels - #2400

Merged
Asherlc merged 7 commits into
mainfrom
codex/issue-2084
Aug 2, 2026
Merged

Asherlc merged 7 commits into
mainfrom
codex/issue-2084

Conversation

@Asherlc

@Asherlc Asherlc commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • lead training metric headings, chart labels, and mobile cards with plain-language terminology
  • keep formulas, model names, server explanations, and sources in accessible expandable details
  • centralize shared training terminology for web and mobile parity

Validation

  • 80 focused web/mobile tests
  • training, web, and mobile typechecks
  • Biome, review-scenario, and web-story coverage checks

Closes #2084

Summary by Sourcery

Lead training metrics with shared plain-language labels while moving technical model details into expandable explanations across web and mobile.

New Features:

  • Introduce centralized TRAINING_TERMINOLOGY definitions for key training metrics used in web and mobile.
  • Add expandable method explanation components on web and mobile for training models and estimates, including workload ratio, polarization, monotony, power models, grade-adjusted pace, and estimated max.

Enhancements:

  • Update training charts, tables, cards, and headings to use consistent plain-language labels and descriptions instead of technical names by default.
  • Refine chart tooltips, empty states, and error messages to align with new terminology and emphasize descriptive context over classifications.

Tests:

  • Expand and adjust web and mobile tests to cover new terminology, collapsible method details, and updated chart labels, subtitles, and table headers.

Summary by cubic

Leads training metrics with plain-language labels across web and mobile, moving model names and formulas into “How this is calculated” details. Centralizes terminology in @dofek/training/terminology and applies it across power, strength, pace, workload, and distribution views, aligning with issue #2084.

  • New Features

    • Added @dofek/training/terminology entries for intensity distribution, workload ratio, normalized power, sustainable power, short‑burst reserve (W′), polarization, monotony, grade‑adjusted pace, and estimated 1‑rep max.
    • Web: Collapsible MethodExplanation added and applied to Power Curve (shown as “Sustainable power model” with CP/W′ details), Estimated single‑rep strength, Grade‑adjusted Pace, Polarization Trend (“Easy‑to‑hard balance”), Training Monotony (“Training variety” and “Weekly load strain”), Workload Ratio, and the Insights intensity donut; Activity Variability table now shows “Effort‑adjusted power (W)”.
    • Mobile: Introduced TrainingMethodDetails; updated TrainingDistributionCards and StrainScreen to lead with plain labels, keep server explanations in a disclosure, and align error titles with plain terms.
    • Units: Added POWER_UNIT_LABEL and WORK_UNIT_LABEL in @dofek/format/units and used in charts, tables, and tooltips.
    • Docs: Recorded an Infisical OIDC timeout blocking the Mobile Metro bundle CI, with the follow‑up run linked.
  • Refactors

    • Renamed series, axes, headers, and messages to plain terms (e.g., “Easy‑to‑hard balance”, “Training variety”, “Weekly load strain”, “Reference balance level”) and hid technical names by default.
    • Updated cycling, endurance, hiking, and strength routes to lead with plain labels; moved method/source details into expandable sections.
    • CI: Excluded packages/training/src/terminology.ts from coverage and mutation checks.

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

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added plain-language labels and descriptions across training, strength, cycling, hiking, and endurance insights.
    • Added expandable calculation explanations with optional technical details and source links.
    • Added “About” information for chart methodology and server-provided explanations.
  • Improvements
    • Updated chart labels, tooltips, subtitles, and empty states for clearer understanding.
    • Simplified technical model names and kept advanced calculation details hidden until requested.
    • Standardized terminology across web and mobile training views.

Move model names and formulas into accessible details across web and mobile.\n\nCloses #2084
Copilot AI review requested due to automatic review settings August 2, 2026 09:38
@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.

@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 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 Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR centralizes training terminology across web and mobile surfaces. Plain-language labels appear by default. Technical names, formulas, explanations, and sources are available through expandable web sections or mobile alerts. It also adds a Mobile Metro CI incident record.

Changes

Training terminology and disclosures

Layer / File(s) Summary
Shared terminology catalog
packages/training/src/terminology.ts, packages/training/src/terminology.test.ts
Defines and validates shared plain-language and technical terminology for training metrics.
Reusable web method disclosure
packages/web/src/components/MethodExplanation.tsx, packages/web/src/components/MethodExplanation.test.tsx
Technical names, calculation details, and sources are now hidden in a collapsible disclosure.
Mobile terminology and calculation alerts
packages/mobile/components/*, packages/mobile/app/(tabs)/strain.*
Mobile cards use shared labels and expose calculation details through alerts.
Web chart and route terminology
packages/web/src/components/*, packages/web/src/routes/training/*, packages/web/src/lib/hikingPaceCopy.ts
Web charts, tables, routes, and supporting copy use plain-language terminology with expandable technical explanations.
Production incident baseline
docs/production-incident-baseline.md
Documents the Infisical OIDC timeout that blocked Mobile Metro CI validation.

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

Sequence Diagram(s)

sequenceDiagram
  actor Athlete
  participant TrainingSurface
  participant TRAINING_TERMINOLOGY
  participant MethodExplanation
  Athlete->>TrainingSurface: View training metric
  TrainingSurface->>TRAINING_TERMINOLOGY: Read plain label and description
  TrainingSurface-->>Athlete: Show plain-language content
  Athlete->>MethodExplanation: Expand calculation details
  MethodExplanation-->>Athlete: Show technical name, details, and source
Loading

Assessment against linked issues

Objective Addressed Explanation
[DQ-11] Show plain-language labels before technical training terms.
[DQ-11] Provide formulas, methods, and technical names in expandable detail.

Out-of-scope changes

Code Change Explanation
Production incident baseline documentation (docs/production-incident-baseline.md:10-46) The linked issue covers training terminology presentation. This record documents an unrelated Mobile Metro CI network timeout.

Possibly related PRs

  • Asherlc/dofek#2222: Shares workload-ratio terminology changes but focuses on computation and risk semantics.
  • Asherlc/dofek#2231: Modifies the same mobile training cards and polarization/monotony disclosures.
  • Asherlc/dofek#2329: Adds related accessible disclosure patterns for technical explanations.

Suggested labels: area/web, area/mobile, type/feature

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is clear, imperative, and under 70 characters, but it does not use a relevant area prefix such as [web] or [mobile]. Add a relevant area prefix, such as [web], [mobile], or [web/mobile], while keeping the imperative wording and removing the issue key if needed.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch codex/issue-2084

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 Aug 2, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR standardizes training metric terminology across web and mobile, leading with plain-language labels in headings and charts while moving technical model details into centralized, expandable explanations and new shared utilities, and updates tests to assert the new UX and accessibility behavior.

Sequence diagram for mobile expandable training method details

sequenceDiagram
  actor User
  participant TrainingMethodDetails
  participant ChartDescriptionTooltip
  participant Alert
  participant openExternalUrl

  User->>TrainingMethodDetails: tap "About How this is calculated"
  TrainingMethodDetails->>ChartDescriptionTooltip: render(title, description)
  ChartDescriptionTooltip-->>Alert: alert(title, description, [{ text: Close }])

  User->>TrainingMethodDetails: tap source link
  TrainingMethodDetails->>openExternalUrl: openExternalUrl(source.url, sourceActionId)
Loading

File-Level Changes

Change Details Files
Introduce centralized training terminology constants and use them to lead with plain-language labels while keeping technical names and calculation details in expandable UI components.
  • Add TRAINING_TERMINOLOGY registry defining plain labels, descriptions, technical names, and details for key training metrics
  • Refactor mobile TrainingDistributionCards and StrainScreen to use TRAINING_TERMINOLOGY for intensity, polarization, monotony, workload ratio labels and descriptions
  • Refactor web endurance, cycling, hiking, strength routes and power-related components to use TRAINING_TERMINOLOGY for headings, subtitles, and axis labels
packages/training/src/terminology.ts
packages/mobile/components/TrainingDistributionCards.tsx
packages/mobile/app/(tabs)/strain.tsx
packages/web/src/routes/training/cycling.tsx
packages/web/src/routes/training/endurance.tsx
packages/web/src/routes/training/strength.lazy.tsx
packages/web/src/lib/hikingPaceCopy.ts
packages/web/src/components/ActivityVariabilityTable.tsx
packages/web/src/components/TrainingMonotonyChart.tsx
packages/web/src/components/PolarizationTrendChart.tsx
packages/web/src/components/EstimatedMaxChart.tsx
packages/web/src/components/PowerCurveChart.tsx
packages/web/src/components/WorkloadRatioChart.tsx
packages/web/src/components/StrainCard.tsx
packages/web/src/components/GradeAdjustedPaceTable.tsx
Introduce reusable method explanation components on web and mobile and wire training models to show technical details and sources in expandable sections instead of inline text.
  • Add TrainingMethodDetails component on mobile that uses ChartDescriptionTooltip and optional source link, and integrate it into intensity, polarization, and monotony cards
  • Extend web MethodExplanation to render inside a
    / with optional technicalName and source link
  • Use MethodExplanation in power, monotony, polarization, workload ratio, grade-adjusted pace, estimated max, and strain cards to expose model formulas, method choices, and references
packages/mobile/components/TrainingMethodDetails.tsx
packages/mobile/components/TrainingDistributionCards.tsx
packages/web/src/components/MethodExplanation.tsx
packages/web/src/components/PowerCurveChart.tsx
packages/web/src/components/TrainingMonotonyChart.tsx
packages/web/src/components/PolarizationTrendChart.tsx
packages/web/src/components/WorkloadRatioChart.tsx
packages/web/src/components/EstimatedMaxChart.tsx
packages/web/src/components/GradeAdjustedPaceTable.tsx
packages/web/src/components/StrainCard.tsx
Update tests to assert new plain-language labels, expandable technical details, tooltip wiring, and error/empty-copy changes across mobile and web training views.
  • Adjust mobile tests for TrainingDistributionCards and StrainScreen to check new labels, descriptions, Alert-based method details, and updated error messages
  • Update web chart/tests for power curve, monotony, polarization, workload ratio, estimated max, hiking pace, training insights, grade-adjusted pace, and activity variability to expect new terminology, details toggles, and copy
  • Mock ChartDescriptionTooltip in range-plumbing tests to expose description content for assertions
packages/mobile/components/TrainingDistributionCards.test.tsx
packages/mobile/app/(tabs)/strain.test.tsx
packages/web/src/components/PowerCurveChart.test.tsx
packages/web/src/components/MethodExplanation.test.tsx
packages/web/src/components/TrainingMonotonyChart.test.tsx
packages/web/src/components/chart-options.test.ts
packages/web/src/components/TrainingInsightsPanel.test.tsx
packages/web/src/components/PolarizationTrendChart.test.tsx
packages/web/src/components/EstimatedMaxChart.test.tsx
packages/web/src/routes/training/hiking.test.tsx
packages/web/src/routes/training/range-plumbing.test-helper.tsx
packages/web/src/components/GradeAdjustedPaceTable.test.tsx
packages/web/src/components/WorkloadRatioChart.test.tsx
packages/web/src/components/ActivityVariabilityTable.test.tsx

Assessment against linked issues

Issue Objective Addressed Explanation
#2084 Update training metric UI labels and headings to lead with plain-language terminology instead of technical terms (e.g., ACWR, W′, normalized power, polarization index, monotony, Minetti model, e1RM).
#2084 Keep formulas, methods, technical names, and sources accessible via expandable or secondary details rather than in primary headings or subtitles.
#2084 Centralize shared training terminology so web and mobile surfaces use consistent plain-language and technical labels for training metrics.

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

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

Channel pr-2400
Deep Link dofek://preview/pr-2400
Commit f17032b

To test on device:

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

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 f17032b6 are ready:

This comment updates automatically on each PR push.

@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): 190 rules

Grey Divider


Remediation recommended

1. Root cause lacks citation ✓ Resolved 📘 Rule violation § Compliance ⭐ New
Description
The Root Cause section asserts third-party service availability (app.infisical.com unreachable)
without an adjacent primary-source link. This violates the docs requirement to cite third-party
behavior claims and makes the incident writeup harder to audit later.
Code

docs/production-incident-baseline.md[R32-33]

+The GitHub-hosted runner could not reach `app.infisical.com` during OIDC
+authentication, so required mobile build secrets were never loaded.
Relevance

●●● Strong

Docs third-party behavior claims usually require adjacent primary-source citations; multiple
accepted precedents in same doc file.

PR-#2052
PR-#2214
PR-#2393

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1505719 requires added/modified third-party behavior claims in docs/ to include
an adjacent citation to a primary source. The Root Cause text asserts Infisical connectivity failure
without a nearby link in that section.

Rule 1505719: Cite third-party behavior claims in docs with primary sources
docs/production-incident-baseline.md[30-34]

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 incident entry’s Root Cause states that the GitHub runner could not reach `app.infisical.com` during OIDC authentication, but this third-party availability/behavior claim is not accompanied by an adjacent primary-source citation.

## Issue Context
A link to the relevant GitHub Actions job/log (already present in the Evidence section) should be included adjacent to the Root Cause claim as well (same paragraph or immediately following line), per the docs citation requirement.

## Fix Focus Areas
- docs/production-incident-baseline.md[30-34]

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


2. Static TRAINING_TERMINOLOGY unit test ✓ Resolved 📘 Rule violation ▣ Testability ⭐ New
Description
terminology.test.ts asserts the presence/content of a declarative constant object rather than
exercising runtime behavior that depends on it. This violates the guideline to avoid dedicated unit
tests for static config/metadata and prefer schema/lint-style validation instead.
Code

packages/training/src/terminology.test.ts[R6-9]

+    for (const entry of Object.values(TRAINING_TERMINOLOGY)) {
+      expect(entry.plainLabel).toBeTruthy();
+      expect(entry.plainDescription).toBeTruthy();
+      expect(entry.technicalName).toBeTruthy();
Relevance

●●● Strong

Team has accepted removing tests that only assert static declarative data/strings instead of
behavior.

PR-#1862

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 773534 prohibits adding unit tests whose primary purpose is asserting static
declarative config/metadata contents. The new test iterates over TRAINING_TERMINOLOGY and asserts
static fields/strings directly, without exercising any executable logic that uses this data.

Rule 773534: Avoid dedicated unit tests for purely declarative static config files
packages/training/src/terminology.test.ts[1-15]

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

## Issue description
`packages/training/src/terminology.test.ts` adds a unit test that primarily asserts the structure/content of a static metadata object (`TRAINING_TERMINOLOGY`). The compliance rule requests avoiding unit tests that restate declarative config/metadata, and instead enforcing correctness via schema validation, lint rules, or by testing executable behavior that consumes the metadata.

## Issue Context
The current test loops over entries and asserts fields are truthy and that `plainLabel`/`plainDescription` do not contain `technicalName`, which is essentially validating static content rather than behavior.

## Fix Focus Areas
- packages/training/src/terminology.test.ts[1-15]

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


3. Hardcoded W/kJ in copy ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
User-facing copy in PowerCurveChart and ActivityVariabilityTable hardcodes unit strings like W
and kJ directly in string templates/labels instead of pulling unit text from a centralized
unit-label/formatting mechanism. This violates the unit-string centralization requirement and risks
inconsistent unit formatting and harder future unit-text changes across the UI.
Code

packages/web/src/components/PowerCurveChart.tsx[153]

+            `Current fit: ${model.cp}W sustainable cycling power and ${Math.round(model.wPrime / 1000)}kJ short-burst power reserve.`,
Relevance

●●● Strong

Strong precedent enforcing centralized unit labels/formatters; hardcoded W/kJ likely flagged and
fixed for compliance.

PR-#1963
PR-#2319
PR-#2384

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 722048 requires user-facing unit strings to be centralized via a shared
formatter/i18n/constants layer. In PowerCurveChart, the added method-explanation text directly
appends W and kJ within a user-facing string, and in ActivityVariabilityTable the updated
column header includes a hardcoded (W) (via `${TRAINING_TERMINOLOGY.normalizedPower.plainLabel}
(W)`), demonstrating that unit strings are still being embedded directly in UI copy rather than
sourced from the approved shared mechanism.

Rule 722048: Centralize user-facing unit strings in a shared formatter or i18n layer
packages/web/src/components/PowerCurveChart.tsx[147-154]
packages/web/src/components/ActivityVariabilityTable.tsx[74-77]

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

## Issue description
User-facing copy currently hardcodes unit strings (e.g., `W`, `kJ`, `(W)`) inside interpolated strings and labels, but the compliance checklist requires all unit text to come from a centralized unit-label/formatting (formatter/i18n/constants) mechanism.

## Issue Context
- `PowerCurveChart` adds a method-details/explanation line that directly appends `W` and `kJ` in user-facing explanatory text.
- `ActivityVariabilityTable` renders a column header as `${TRAINING_TERMINOLOGY.normalizedPower.plainLabel} (W)`, which still embeds the unit string in UI text.

## Fix Focus Areas
- packages/web/src/components/PowerCurveChart.tsx[147-155]
- packages/web/src/components/ActivityVariabilityTable.tsx[74-86]

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

Previous review results

Review updated until commit f0d39a8

Results up to commit db02eec ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Hardcoded W/kJ in copy ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
User-facing copy in PowerCurveChart and ActivityVariabilityTable hardcodes unit strings like W
and kJ directly in string templates/labels instead of pulling unit text from a centralized
unit-label/formatting mechanism. This violates the unit-string centralization requirement and risks
inconsistent unit formatting and harder future unit-text changes across the UI.
Code

packages/web/src/components/PowerCurveChart.tsx[153]

+            `Current fit: ${model.cp}W sustainable cycling power and ${Math.round(model.wPrime / 1000)}kJ short-burst power reserve.`,
Relevance

●●● Strong

Strong precedent enforcing centralized unit labels/formatters; hardcoded W/kJ likely flagged and
fixed for compliance.

PR-#1963
PR-#2319
PR-#2384

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 722048 requires user-facing unit strings to be centralized via a shared
formatter/i18n/constants layer. In PowerCurveChart, the added method-explanation text directly
appends W and kJ within a user-facing string, and in ActivityVariabilityTable the updated
column header includes a hardcoded (W) (via `${TRAINING_TERMINOLOGY.normalizedPower.plainLabel}
(W)`), demonstrating that unit strings are still being embedded directly in UI copy rather than
sourced from the approved shared mechanism.

Rule 722048: Centralize user-facing unit strings in a shared formatter or i18n layer
packages/web/src/components/PowerCurveChart.tsx[147-154]
packages/web/src/components/ActivityVariabilityTable.tsx[74-77]

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

## Issue description
User-facing copy currently hardcodes unit strings (e.g., `W`, `kJ`, `(W)`) inside interpolated strings and labels, but the compliance checklist requires all unit text to come from a centralized unit-label/formatting (formatter/i18n/constants) mechanism.

## Issue Context
- `PowerCurveChart` adds a method-details/explanation line that directly appends `W` and `kJ` in user-facing explanatory text.
- `ActivityVariabilityTable` renders a column header as `${TRAINING_TERMINOLOGY.normalizedPower.plainLabel} (W)`, which still embeds the unit string in UI text.

## Fix Focus Areas
- packages/web/src/components/PowerCurveChart.tsx[147-155]
- packages/web/src/components/ActivityVariabilityTable.tsx[74-86]

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


Qodo Logo

Comment thread packages/web/src/components/PowerCurveChart.tsx Outdated
@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

qodo-code-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Lead training views with plain-language labels (web + mobile parity)

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Centralize training metric terminology and reuse it across web and mobile UI.
• Default charts/cards/tables to plain labels; move technical methods into expandable details.
• Update and expand tests to enforce terminology contracts and new disclosure behavior.
Diagram

graph TD
  Term["@dofek/training/terminology"] --> Web["Web training UI"] --> WebExplain["MethodExplanation"]
  Term --> Mobile["Mobile training UI"] --> MobileExplain["TrainingMethodDetails"]
  WebExplain --> Tests["Web/Mobile tests"]
  MobileExplain --> Tests
  Docs["Incident baseline doc"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Adopt i18n keys for terminology instead of constants
  • ➕ Sets up future localization and copy iteration without code changes
  • ➕ Encourages consistent copy governance across product areas
  • ➖ More plumbing (translation keys, fallback logic, extraction) for a copy-focused change
  • ➖ Harder to co-locate technical details + sources with the label in one typed object
2. Have the server supply user-facing labels/descriptions with payloads
  • ➕ Ensures clients always reflect the current canonical phrasing
  • ➕ Reduces duplicated copy across clients
  • ➖ Couples UI copy to API responses and increases payload/migration complexity
  • ➖ Harder to keep disclosure/UX behavior consistent when copy is remote-supplied

Recommendation: The chosen approach (typed shared TRAINING_TERMINOLOGY in a common package + platform-appropriate disclosure components) is the best fit for fast web/mobile parity and consistent phrasing. Consider migrating to i18n only if/when localization or copy experimentation becomes a priority; this PR keeps the surface area manageable while still preventing technical-name leakage via the contract test.

Files changed (34) +676 / -208

Enhancement (18) +405 / -129
strain.tsxUse shared terminology for workload/polarization/monotony copy and error titles +12/-3

Use shared terminology for workload/polarization/monotony copy and error titles

• Imports 'TRAINING_TERMINOLOGY' to drive user-facing error titles for polarization and monotony and enriches the workload tooltip with technical name + details when data exists. Keeps the primary UI copy plain while routing technical phrasing into the tooltip description.

packages/mobile/app/(tabs)/strain.tsx

TrainingDistributionCards.tsxSwitch distribution cards to plain terminology and delegate technical details to a shared component +65/-47

Switch distribution cards to plain terminology and delegate technical details to a shared component

• Replaces technical headings and in-card method text with plain labels/descriptions from 'TRAINING_TERMINOLOGY'. Introduces 'TrainingMethodDetails' to surface technical name, calculation lines, and sources without cluttering the default card UI.

packages/mobile/components/TrainingDistributionCards.tsx

TrainingMethodDetails.tsxAdd reusable mobile method-details disclosure component +57/-0

Add reusable mobile method-details disclosure component

• Creates a small component that composes 'ChartDescriptionTooltip' with a standardized title and a description block containing technical name + method lines. Optionally renders a source link via 'openExternalUrl' for citations.

packages/mobile/components/TrainingMethodDetails.tsx

terminology.tsIntroduce shared TRAINING_TERMINOLOGY for cross-platform training metric copy +74/-0

Introduce shared TRAINING_TERMINOLOGY for cross-platform training metric copy

• Adds a typed constant mapping training metrics to plain labels/descriptions plus technical names and calculation details (e.g., Karvonen model, ACWR, polarization index, Foster monotony, Minetti, e1RM). Designed for headings/series to use plain text while details panels/tooltips use technical context.

packages/training/src/terminology.ts

ActivityVariabilityTable.tsxRename normalized power column to plain terminology +2/-1

Rename normalized power column to plain terminology

• Imports 'TRAINING_TERMINOLOGY' and replaces the normalized power column label with the shared plain label for consistent UI wording.

packages/web/src/components/ActivityVariabilityTable.tsx

EstimatedMaxChart.tsxUse plain axis label and add expandable method explanation for e1RM +10/-1

Use plain axis label and add expandable method explanation for e1RM

• Replaces the y-axis title with the shared plain label for estimated max strength. Adds 'MethodExplanation' so the e1RM technical name and formula details are available on demand.

packages/web/src/components/EstimatedMaxChart.tsx

GradeAdjustedPaceTable.tsxAdd expandable method explanation to grade-adjusted pace table +7/-0

Add expandable method explanation to grade-adjusted pace table

• Introduces 'MethodExplanation' under the table to disclose technical method details and source link without placing them in primary copy.

packages/web/src/components/GradeAdjustedPaceTable.tsx

MethodExplanation.tsxRefactor MethodExplanation into an expandable <details> disclosure +29/-10

Refactor MethodExplanation into an expandable <details> disclosure

• Changes 'MethodExplanation' from always-visible paragraphs into a '<details>/<summary>' disclosure with optional 'technicalName' and optional 'source'. Preserves external link behavior while reducing default jargon density.

packages/web/src/components/MethodExplanation.tsx

PolarizationTrendChart.tsxRename polarization chart to plain labels and move technical context into disclosure +16/-7

Rename polarization chart to plain labels and move technical context into disclosure

• Replaces “Polarization Index” naming with plain “Easy-to-hard” terminology (axis, series, tooltips, headings) and updates empty messaging to be user-centered. Adds 'MethodExplanation' with technical name + details while keeping the main UI plain-language.

packages/web/src/components/PolarizationTrendChart.tsx

PowerCurveChart.tsxLabel power model plainly and add expandable explanation for CP/W′ fit +26/-15

Label power model plainly and add expandable explanation for CP/W′ fit

• Renames the fitted model curve series to a plain label and wraps the chart to include a 'MethodExplanation' section. Discloses CP and W′ technical names plus current fit details without showing them in the main chart legend by default.

packages/web/src/components/PowerCurveChart.tsx

StrainCard.tsxAdd method explanation disclosure for workload ratio context +7/-0

Add method explanation disclosure for workload ratio context

• Adds 'MethodExplanation' to keep workload ratio’s technical name accessible while continuing to show plain context in the card. Uses shared terminology for the technical name string.

packages/web/src/components/StrainCard.tsx

TrainingInsightsPanel.tsxReplace intensity donut heading/body with shared plain terminology +10/-3

Replace intensity donut heading/body with shared plain terminology

• Updates the intensity donut to display the shared plain label and description, and moves technical details + server explanation into the tooltip description string. This keeps the UI readable while retaining transparency on request.

packages/web/src/components/TrainingInsightsPanel.tsx

TrainingMonotonyChart.tsxRename monotony/strain chart to plain terminology and add method disclosure +25/-11

Rename monotony/strain chart to plain terminology and add method disclosure

• Replaces chart legend/axis/tooltip strings with shared plain labels for monotony and strain metrics, and updates empty messaging. Adds 'MethodExplanation' with technical name + details and keeps method/source accessible behind disclosure.

packages/web/src/components/TrainingMonotonyChart.tsx

WorkloadRatioChart.tsxAdd method explanation disclosure to workload ratio chart +12/-1

Add method explanation disclosure to workload ratio chart

• Wraps the chart in a container that includes 'MethodExplanation' with the ACWR technical name and the server-provided context description, keeping the main chart presentation plain.

packages/web/src/components/WorkloadRatioChart.tsx

hikingPaceCopy.tsSplit hiking pace copy into plain description + technical method details +10/-3

Split hiking pace copy into plain description + technical method details

• Uses shared terminology to set the hiking pace title and separates the subtitle description from the technical model name. Adds technicalName/methodDetails/source metadata for use in 'MethodExplanation'.

packages/web/src/lib/hikingPaceCopy.ts

cycling.tsxRephrase cycling training labels and hide estimate evidence details behind disclosure +34/-22

Rephrase cycling training labels and hide estimate evidence details behind disclosure

• Improves user-facing subtitles and labels to emphasize meaning over model names (e.g., effort-adjusted power wording, sustainable/short-burst labels). Moves estimate evidence method/source-workout details into an expandable “How this estimate is calculated” section.

packages/web/src/routes/training/cycling.tsx

endurance.tsxRename endurance sections to plain polarization/monotony terminology +7/-3

Rename endurance sections to plain polarization/monotony terminology

• Updates section titles/subtitles to use shared plain-language labels for training balance and variety, removing default emphasis on the underlying technical models.

packages/web/src/routes/training/endurance.tsx

strength.lazy.tsxRename strength tab section to plain estimated max terminology +2/-2

Rename strength tab section to plain estimated max terminology

• Updates the strength section title/subtitle to use a plain label (“Estimated single-rep strength”) and a clearer subtitle while removing default e1RM jargon.

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

Tests (15) +234 / -79
strain.test.tsxUpdate StrainScreen tests for plain labels and accessible model details +32/-8

Update StrainScreen tests for plain labels and accessible model details

• Renames assertions to expect plain-language metric labels and descriptions instead of technical model names. Adds coverage that server/model explanations are available via an accessible action (Alert) rather than default text, and updates error/empty-state messaging expectations accordingly.

packages/mobile/app/(tabs)/strain.test.tsx

TrainingDistributionCards.test.tsxCover mobile distribution cards disclosure behavior via Alert tooltip actions +70/-13

Cover mobile distribution cards disclosure behavior via Alert tooltip actions

• Updates tests to assert plain headings/descriptions for intensity distribution, polarization, and monotony cards. Verifies technical/server-provided explanations are hidden by default and retrievable through the “How this is calculated” affordance (Alert content).

packages/mobile/components/TrainingDistributionCards.test.tsx

terminology.test.tsAdd contract test preventing technical-name leakage into plain labels/descriptions +15/-0

Add contract test preventing technical-name leakage into plain labels/descriptions

• Introduces a test that asserts each terminology entry has required fields and that 'plainLabel'/'plainDescription' do not contain the 'technicalName'. This guards against regressions where technical jargon appears in primary UI copy.

packages/training/src/terminology.test.ts

ActivityVariabilityTable.test.tsxAssert activity table column uses plain power label +15/-0

Assert activity table column uses plain power label

• Adds a focused test verifying the table header uses the plain “Effort-adjusted power (W)” label and does not display “Normalized Power (W)”.

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

EstimatedMaxChart.test.tsxTest e1RM details remain collapsed while chart labels are plain +10/-0

Test e1RM details remain collapsed while chart labels are plain

• Adds coverage that the “How this is calculated” section exists and that e1RM technical phrasing is not visible by default, while the chart axis uses the plain strength label.

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

GradeAdjustedPaceTable.test.tsxEnsure Minetti technical details are not visible by default +4/-0

Ensure Minetti technical details are not visible by default

• Extends the table test to confirm Minetti references are present but hidden until expansion, and that “How this is calculated” is available.

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

MethodExplanation.test.tsxUpdate MethodExplanation tests for collapsed-by-default behavior +13/-12

Update MethodExplanation tests for collapsed-by-default behavior

• Switches the component test to verify '<details>' rendering, hidden content before interaction, and visibility after expanding. Also verifies the optional technical-name line and link attributes.

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

PolarizationTrendChart.test.tsxExpect polarization method details to be hidden until expanded +7/-5

Expect polarization method details to be hidden until expanded

• Updates tests to confirm the method text is only visible after expanding “How this is calculated”, matching the new disclosure behavior.

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

PowerCurveChart.test.tsxConvert PowerCurveChart test to DOM-based and assert plain model label +21/-19

Convert PowerCurveChart test to DOM-based and assert plain model label

• Reworks the test to mock 'DofekChart' and assert the fitted curve is labeled with a plain phrase. Also checks that “How this is calculated” exists and “Critical Power” is not visible by default.

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

TrainingInsightsPanel.test.tsxUpdate insights panel tests for plain intensity copy + hidden server explanation +18/-4

Update insights panel tests for plain intensity copy + hidden server explanation

• Adjusts tests to assert plain intensity distribution labels and descriptions and ensures server explanation is not directly rendered. Verifies the explanation remains accessible through the chart tooltip metadata.

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

TrainingMonotonyChart.test.tsxUpdate monotony chart tests for plain labels and disclosure behavior +9/-7

Update monotony chart tests for plain labels and disclosure behavior

• Adjusts tests to expand “How this is calculated” before asserting method text visibility and updates tooltip/series naming expectations (e.g., “Training variety”).

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

WorkloadRatioChart.test.tsxAssert ACWR technical name is hidden while disclosure control is present +3/-1

Assert ACWR technical name is hidden while disclosure control is present

• Extends the workload ratio chart test to confirm the disclosure section renders and that the ACWR technical phrasing is not visible by default.

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

chart-options.test.tsUpdate chart option tests for new polarization series names +7/-7

Update chart option tests for new polarization series names

• Renames expectations for polarization series and threshold/reference series to match the new plain-language naming used by the chart option builder.

packages/web/src/components/chart-options.test.ts

hiking.test.tsxEnsure hiking subtitle does not expose slope-cost model by default +5/-2

Ensure hiking subtitle does not expose slope-cost model by default

• Updates the test to assert the hiking pace subtitle uses plain meaning and does not mention Minetti unless expanded via method details.

packages/web/src/routes/training/hiking.test.tsx

range-plumbing.test-helper.tsxEnhance ChartDescriptionTooltip mock to expose description content for assertions +5/-1

Enhance ChartDescriptionTooltip mock to expose description content for assertions

• Updates the test helper mock to render a button with 'data-description', enabling tests to validate that technical/server explanations are still accessible via tooltips.

packages/web/src/routes/training/range-plumbing.test-helper.tsx

Documentation (1) +37 / -0
production-incident-baseline.mdDocument Infisical CI timeout blocking mobile Metro bundle validation +37/-0

Document Infisical CI timeout blocking mobile Metro bundle validation

• Adds an incident entry describing a GitHub runner network timeout to Infisical OIDC during CI. Captures symptoms, evidence, root cause, mitigation decision (rerun after recovery), and remaining risk.

docs/production-incident-baseline.md

@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 closed this Aug 2, 2026
@Asherlc Asherlc reopened this Aug 2, 2026
@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.

Comment thread packages/training/src/terminology.test.ts Outdated
Comment thread docs/production-incident-baseline.md Outdated
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 437b59e

@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

🤖 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 `@docs/production-incident-baseline.md`:
- Around line 42-45: Add a “### Follow-up Work” section to the incident record
after “### Remaining Risk,” documenting the action to rerun the workflow once
the Infisical OIDC request succeeds and the evidence to capture, including the
successful job URL and mobile Metro/dependent CI gate results.
- Around line 14-25: Add a “### Follow-Up Work” section to
docs/production-incident-baseline.md, following the existing incident details
and AGENTS.md requirements. Include a brief, actionable durable remediation for
the failed Build Mobile / Metro Bundle CI validation before merge.

In `@packages/web/src/components/MethodExplanation.test.tsx`:
- Around line 25-34: Update
packages/web/src/components/MethodExplanation.test.tsx lines 25-34 to assert the
technical name and at least one detail line with toBeVisible() after clicking
the disclosure trigger; update
packages/web/src/components/GradeAdjustedPaceTable.test.tsx lines 132-135 to
replace the toBeDefined() assertion for “How this is calculated” with
toBeVisible().

In `@packages/web/src/components/PowerCurveChart.tsx`:
- Around line 146-156: Update the conditional rendering around MethodExplanation
in PowerCurveChart to use modelCurveData.length > 0 instead of only checking
model, matching the condition used for the fitted model curve. Ensure the
Current fit disclosure is hidden when the fitted series is empty, including when
model.cp is 0, and add a regression case covering cp: 0.

In `@packages/web/src/components/StrainCard.tsx`:
- Around line 176-180: Remove the existing direct paragraph rendering
data.context.description near MethodExplanation in StrainCard, leaving the
description rendered only through MethodExplanation’s lines prop. Preserve the
disclosure’s existing technicalName and styling so the explanation appears only
after expansion.

In `@packages/web/src/routes/training/hiking.test.tsx`:
- Line 135: Remove the negative screen.queryByText(/Minetti/) assertion from the
hiking route test, while preserving the existing plain-language assertions.
Cover technical-detail availability with a positive assertion in the disclosure
component test instead.
🪄 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: fcdd56af-daec-4a71-9a85-2cef73c414b1

📥 Commits

Reviewing files that changed from the base of the PR and between 54aeb8b and 437b59e.

📒 Files selected for processing (34)
  • docs/production-incident-baseline.md
  • packages/mobile/app/(tabs)/strain.test.tsx
  • packages/mobile/app/(tabs)/strain.tsx
  • packages/mobile/components/TrainingDistributionCards.test.tsx
  • packages/mobile/components/TrainingDistributionCards.tsx
  • packages/mobile/components/TrainingMethodDetails.tsx
  • packages/training/src/terminology.test.ts
  • packages/training/src/terminology.ts
  • packages/web/src/components/ActivityVariabilityTable.test.tsx
  • packages/web/src/components/ActivityVariabilityTable.tsx
  • packages/web/src/components/EstimatedMaxChart.test.tsx
  • packages/web/src/components/EstimatedMaxChart.tsx
  • packages/web/src/components/GradeAdjustedPaceTable.test.tsx
  • packages/web/src/components/GradeAdjustedPaceTable.tsx
  • packages/web/src/components/MethodExplanation.test.tsx
  • packages/web/src/components/MethodExplanation.tsx
  • packages/web/src/components/PolarizationTrendChart.test.tsx
  • packages/web/src/components/PolarizationTrendChart.tsx
  • packages/web/src/components/PowerCurveChart.test.tsx
  • packages/web/src/components/PowerCurveChart.tsx
  • packages/web/src/components/StrainCard.tsx
  • packages/web/src/components/TrainingInsightsPanel.test.tsx
  • packages/web/src/components/TrainingInsightsPanel.tsx
  • packages/web/src/components/TrainingMonotonyChart.test.tsx
  • packages/web/src/components/TrainingMonotonyChart.tsx
  • packages/web/src/components/WorkloadRatioChart.test.tsx
  • packages/web/src/components/WorkloadRatioChart.tsx
  • packages/web/src/components/chart-options.test.ts
  • packages/web/src/lib/hikingPaceCopy.ts
  • packages/web/src/routes/training/cycling.tsx
  • packages/web/src/routes/training/endurance.tsx
  • packages/web/src/routes/training/hiking.test.tsx
  • packages/web/src/routes/training/range-plumbing.test-helper.tsx
  • packages/web/src/routes/training/strength.lazy.tsx

Comment thread docs/production-incident-baseline.md
Comment thread docs/production-incident-baseline.md
Comment thread packages/web/src/components/MethodExplanation.test.tsx
Comment thread packages/web/src/components/PowerCurveChart.tsx Outdated
Comment thread packages/web/src/components/StrainCard.tsx
Comment thread packages/web/src/routes/training/hiking.test.tsx Outdated
@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 commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Addressed the actionable CodeRabbit review in a2f6a59, merged current origin/main in fee5b85, and pushed 6fde14f.

  • PowerCurve disclosure now follows the fitted-series guard, with cp=0 regression coverage.
  • StrainCard keeps the server description only in the disclosure; visibility assertions cover the trigger/details.
  • Centralized W/kJ labels in @dofek/format/units and removed the static terminology metadata test.
  • Removed the negative Minetti assertion.
  • Added the incident root-cause citation and explicit Follow-Up Work section.
  • Updated the concurrent mobile test to assert disclosure accessibility after the origin/main error-card deduplication.

All nine inline threads have concrete replies and are resolved. Focused validation is green: 8 files, 57 tests.

@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 89b293c into main Aug 2, 2026
102 checks passed
@Asherlc
Asherlc deleted the codex/issue-2084 branch August 2, 2026 10:57
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.

[DQ-11] Technical training terms shown before plain-language meaning

2 participants