P247 iOS Developer Brief: Weekly Performance Report

Goal

Add a Weekly Report area to the iOS app. This is now the main P247 product promise.

P247 should not feel like another daily readiness app. The iOS experience should show a clear weekly decision, the reason behind it, and what the athlete should change next.

Product Positioning

Primary message:

You already have the data. P247 tells you what to do next.

Weekly Report promise:

P247 connects Garmin, WHOOP, Oura, Strava, Apple Health and training context, then turns the noise into a weekly performance report. What is working, what is holding the athlete back, and what to change next.

New Backend Endpoints

GET /reports/weekly

Auth: Bearer token

Query:

GET /reports/weekly?end_date=2026-05-24

end_date is optional. If omitted, backend uses the latest dated metrics entry.

Response shape:

{
  "report_type": "weekly_performance",
  "week_start": "2026-05-18",
  "week_end": "2026-05-24",
  "main_decision": "Build carefully next week.",
  "top_pattern": "Recovery improved after the load dropped late in the week.",
  "what_improved": "Recovery markers improved late week.",
  "what_worsened": "No major worsening signal this week.",
  "training_load_summary": {
    "total_load": 745,
    "peak_day_load": 210,
    "daily_loads": {
      "2026-05-18": 80,
      "2026-05-19": 120,
      "2026-05-20": 180,
      "2026-05-21": 210,
      "2026-05-22": 75,
      "2026-05-23": 45,
      "2026-05-24": 35
    }
  },
  "recovery_trend": {
    "avg_sleep_hours": 7.2,
    "avg_hrv": 54.3,
    "avg_resting_hr": 51.3,
    "hrv_change": 4,
    "sleep_change": 0.7
  },
  "nutrition_risk": {
    "status": "incomplete",
    "message": "Nutrition data is too patchy to trust weekly fuelling calls.",
    "protein_days_logged": 4,
    "carb_days_logged": 0,
    "avg_protein_g": 145,
    "avg_carbs_g": null
  },
  "event_readiness": {
    "event_type": "hyrox",
    "checks": [
      "Check compromised running after heavy lower body work.",
      "Watch sled strength, grip fatigue, wall ball tolerance, and knee load.",
      "Keep threshold work sharp without stacking too many hard mixed sessions."
    ],
    "focus": "Hybrid strength endurance with controlled knee and grip fatigue."
  },
  "actions_next_week": [
    "Add one quality session, not a full week of extra intensity.",
    "Use the first two mornings to confirm HRV, resting heart rate, and sleep are moving together.",
    "Log protein and carbs on hard training days so P247 can separate poor recovery from poor fuelling."
  ],
  "confidence_level": "medium",
  "data_gaps": [
    "Nutrition data is missing or too patchy for confident fuelling calls."
  ]
}

POST /reports/decisions

Stores a recommendation and outcome as the athlete memory layer.

Request:

{
  "decision_type": "weekly_report",
  "reason": "Load rose while sleep fell.",
  "metrics_used": {
    "sleep_hours": 6.2,
    "training_load": 210
  },
  "recommended_action": "Pull back intensity for 48 hours.",
  "athlete_response": "Accepted",
  "outcome_after_3_7_days": "HRV recovered and next run felt better."
}

Response:

{
  "id": 1,
  "decision_type": "weekly_report",
  "reason": "Load rose while sleep fell.",
  "metrics_used": {
    "sleep_hours": 6.2,
    "training_load": 210
  },
  "recommended_action": "Pull back intensity for 48 hours.",
  "athlete_response": "Accepted",
  "outcome_after_3_7_days": "HRV recovered and next run felt better.",
  "decision_date": "2026-05-24T22:15:00Z"
}

iOS Screens

1. Weekly Report Tab

Add a Weekly Report tab or card in the athlete dashboard.

Top card:

Main decision

Example: Build carefully next week.

Subtext:

Top pattern

Example: Recovery improved after the load dropped late in the week.

Confidence chip:

High, Medium, Low

Week range:

18 May to 24 May

2. What changed section

Show two rows:

What improved: value from what_improved

What worsened: value from what_worsened

Keep this plain. Avoid charts first.

3. Training load section

Show:

Total load Peak day load Simple 7 day bar chart from daily_loads

If load values are all zero, show empty state:

No training load found for this week.

4. Recovery trend section

Show:

Average sleep Average HRV Average resting HR HRV change Sleep change

Use green for improving, amber for mixed, red for worsening.

5. Nutrition risk section

Show status chip:

ok watch incomplete

Show message below it.

If incomplete, prompt the user to connect or log nutrition.

CTA copy:

Log fuelling data

6. Event readiness section

Show event type and focus.

Then list checks from event_readiness.checks.

Supported event templates today:

HYROX Marathon Half marathon Ironman Triathlon Cycling Ultra General

7. Actions next week section

Show exactly three action cards from actions_next_week.

These are the most important items on the screen.

8. Data gaps section

Show only if gaps exist.

Copy:

What P247 could not see clearly

Then list data_gaps.

This makes the product feel honest and builds trust.

Interaction Requirements

  1. Pull to refresh should call GET /reports/weekly.
  2. If the athlete changes week, call GET /reports/weekly?end_date=YYYY-MM-DD.
  3. Cache the latest report locally for offline viewing.
  4. If API returns 404, show empty state:

Weekly report needs at least a few days of metrics. Sync Apple Health and training data, then check back.

  1. If API returns 401, send user to login.
  2. If API returns 400 for date, reset to latest week.

Decision Memory Logging

When the athlete taps an action or marks it accepted, call POST /reports/decisions.

Suggested decision types:

weekly_report training_adjustment recovery_protection fuelling_change event_readiness

Minimum payload on action tap:

{
  "decision_type": "weekly_report",
  "reason": "Weekly Report action selected.",
  "metrics_used": {
    "week_start": "2026-05-18",
    "week_end": "2026-05-24"
  },
  "recommended_action": "Add one quality session, not a full week of extra intensity.",
  "athlete_response": "Accepted"
}

Later, add follow up outcome capture three to seven days after the decision.

Prompt copy:

Did that change help?

Options:

Felt better No change Felt worse Skipped it

Send that result as outcome_after_3_7_days.

Design Notes

Make the Weekly Report feel like a coach briefing, not a metrics dashboard.

Order matters:

Decision first Reason second Actions third Charts after that

Avoid hiding the recommendation under data cards.

QA Checklist

  1. Weekly report loads with valid auth.
  2. Latest week loads when no end date is passed.
  3. Past week loads when end date is passed.
  4. 404 empty state works when no metrics exist.
  5. 401 sends user to login.
  6. Three action cards render cleanly.
  7. Data gaps render only when present.
  8. Decision action posts to /reports/decisions.
  9. App still shows Today tab and existing daily brief.
  10. Offline cache displays the last successful weekly report.