Tri-Training Progress Dashboard — Plan (v3)

Decisions (resolved)

  1. Calorie expenditure model: Both. Whoop kJ as primary (actual burn), TSS-based as secondary comparison line.
  2. Date range: Default to last 7 days with “show all” toggle.
  3. Race-day plans: Separate page — daily tracking dashboard only on main view.
  4. Hosting: Static files in the workspace files/ folder (already served as a static file server).
  5. Language: Python.
  6. Data architecture: Structured CSV datasets maintained daily — NOT parsing markdown files on every dashboard build. One-time migration script backfills historical data from existing markdown. Going forward, agents append one row per day to each CSV after writing their markdown logs.
  7. Static site tooling: Plain HTML + Chart.js. Single file, no build step.

Data Architecture (CSV-First)

Three CSV files, one per data domain. Each is the single source of truth for the dashboard. Located in files/analytics/data/.

1. nutrition.csv

ColumnTypeSource
dateYYYY-MM-DDfilename
caloriesintDaily Totals
calories_targetintDaily Totals
protein_gfloatDaily Totals
protein_target_gfloatDaily Totals
carbs_gfloatDaily Totals
carbs_target_gfloatDaily Totals
fat_gfloatDaily Totals
fat_target_gfloatDaily Totals
mealsintcount of meal sections

2. training.csv

One row per session (multiple rows per day possible).

ColumnTypeSource
dateYYYY-MM-DDtable row
disciplineswim/bike/run/otheremoji prefix
session_namestrSession column
duration_minintActual column (parsed)
tss_plannedintTSS column
tss_actualintActual TSS column
rpeintRPE column
statuscompleted/skipped/modified✅/❌/text
weekintWeek header

3. whoop.csv

ColumnTypeSource
dateYYYY-MM-DDfilename
recovery_scorefloatRecovery section
hrv_msfloatRecovery section
rhr_bpmintRecovery section
spo2_pctfloatRecovery section
sleep_performance_pctfloatSleep section
sleep_efficiency_pctfloatSleep section
sleep_time_minintSleep section (converted)
sws_minintSleep section (converted)
rem_minintSleep section (converted)
strainfloatStrain section
kjintStrain section
readinessGREEN/YELLOW/REDReadiness line

Daily update flow

Agent writes markdown log
  → Agent appends one row to the relevant CSV
  → Dashboard reads CSVs (no parsing needed)

The nutrition agent already runs daily. After writing files/nutrition/daily/YYYY-MM-DD.md, it should also append a row to nutrition.csv. Same pattern for Whoop reports. Training data is updated less frequently (weekly plan updates), so the training CSV gets updated when sessions are logged.

One-time migration

A Python script (scripts/migrate-to-csv.py) parses all existing markdown files and populates the three CSVs with historical data (Mar 10 onward). This runs once, then the CSVs are maintained incrementally.


What to Extract (Derived Metrics)

Computed at dashboard render time from the CSVs:

  • Calorie deficit/surplus = calories - whoop kJ
  • TSS-based expenditure estimate = sum(session TSS) * ~4.5 kcal (secondary line)
  • Protein compliance = % of days hitting protein target
  • Macro periodization = carb intake correlated with strain
  • Weekly training load = TSS by discipline (swim/bike/run)
  • Training completion rate = completed sessions / total sessions per week
  • Recovery trend = HRV and recovery score over time
  • Sleep quality trend = sleep performance over time
  • Strain vs recovery = high-strain days followed by appropriate recovery?
  • Fueling adequacy = calorie intake relative to Whoop kJ on training days

Dashboard Layout (Mobile-First, Single Screen)

Five panels stacked vertically, designed for phone screen (~375px wide). Default view: last 7 days with “show all” toggle.

Panel 1 — Recovery & Readiness (line chart + color band)

  • HRV trend line (primary) with recovery score color band (green/yellow/red background)
  • RHR as secondary line
  • Readiness indicator per day

Panel 2 — Calorie Balance (bar chart)

  • Daily vertical bars: intake vs Whoop kJ burn
  • Deficit/surplus shading + 7-day rolling average
  • TSS-based estimate as dotted comparison line

Panel 3 — Macro Compliance (horizontal stacked bars)

  • Protein/carbs/fat as % of daily target per day
  • Color coding: green (>90%), amber (70-90%), red (<70%)

Panel 4 — Training Load & Strain (dual-axis chart)

  • TSS bars by discipline (swim/bike/run)
  • Whoop day strain line overlay (right axis)
  • Weekly totals annotated

Panel 5 — Key Stats (summary cards, 2x3 grid)

  • Avg daily calorie deficit (kcal) — last 7 days
  • Protein hit rate (% of days >= target) — last 7 days
  • Total training hours — this week vs last week
  • Avg daily TSS — this week vs last week
  • Avg HRV — this week vs last week
  • Avg sleep performance — this week vs last week

Implementation Steps

  1. Migration script (scripts/migrate-to-csv.py) — one-time parse of all existing markdown → populate 3 CSVs
  2. CSV schema validation — simple Python check that CSVs have expected columns, no duplicate dates (nutrition/whoop), reasonable ranges
  3. Dashboard HTML (files/analytics/dashboard.html) — single file, Chart.js via CDN, reads CSVs via fetch, responsive mobile layout, 5 panels
  4. Agent integration — update nutrition agent to append CSV row after writing daily markdown log. Document the append format for Whoop and training agents.
  5. Taskfile entrytask dashboard:migrate (one-time) and task dashboard:open (serve/open)
  6. Test with current data — validate migration against all 17+ days across all 3 sources

Output Locations

  • Migration script: scripts/migrate-to-csv.py
  • CSV data: files/analytics/data/nutrition.csv, training.csv, whoop.csv
  • Dashboard HTML: files/analytics/dashboard.html
  • Plan (this file): .ai/projects/tri-training/analytics/plan.md