PHASE 2 (Analytics) v2.0.1: design specification for the squad-level progression visualization. First-principles reasoning from the laws of physics, biology, the data the live stopwatch can capture, AND the VISION.md "feel" constraint.
User-confirmed direction across 2026-06-23 messages:
race time as compared to the swimmer personal best in their best event. ... for the sprinters the force velocity curve is a good resource."
swimmer be able to do to obchieve there objective. physics and biology are the only constraints along with what data we can capture in a session from the live stopwatch"
paddles, parachute etc can act as our force metric. also how are we going to package this for swim coaching so it doesn't detract from their intuition and taste (in the rick rubin sense) on the pool deck. Everything should be inservice of the feel. ... I want the coach to feel like they are levitating in term of the amount of coaching insights they are receiving—all without the working memory overload I and others feel while coaching."
| Constraint | What it gives | What it forbids |
|---|---|---|
| Physics | Propulsion-drag equation, F-v tradeoff, energy systems, SL is the dial for sprinters | Claims about F-v operating point without F data; SL/SR without stroke count |
| Biology | Alactic / glycolytic / aerobic boundaries, adaptation delay 2-6 weeks | Claims about VO2 max, lactate threshold, mitochondrial density without measurements |
| Stopwatch data | time per rep + rep_index + intensity + created_at + stroke + distance + gear | Claims about F, SL, SR, HR, VO2 — none captured |
| VISION.md "feel" | Information-rich effortlessness; zero added stress on pool deck; coach is the authority; data formalizes what coach knows; surfaced when needed, not fire-hosed | Dense swimlanes, confidence percentages, statistical jargon, anything that requires interpretation, anything that implies engine is smarter than coach |
Gear (paddles / parachute / pull buoy / fins / none) is the F-axis proxy on the F-V curve. Each gear shifts the swimmer's F-v operating point. No force sensor needed.
Verified live data (2026-06-23):
workout_sets.gear has 3 distinct values: none (12), NULL (5), paddles (1)
recorded_times.gear is none for all 432 rowsnot yet captured**. The capture-mechanics gap is the real blocker, not the data model.
The unlock: one-tap "gear for this set?" picker before each set's timing starts. One tap, zero in-flight friction. Coach picks none / paddles / pull buoy / fins / parachute (5 options). The recorded_times inherit the gear. After 6 weeks of real use, the F-v proxy is in the data.
The user's "levitating without working memory overload" requirement + VISION.md "information-rich effortlessness" = the squad view must be:
This rules out:
Squad — Tuesday 16 June, 7am
🟢 Alice Race ready at 50 Free
🟢 Bob Race ready at 50 Free
🟡 Charlie Building at 50 Free
🟡 Diana Building at 50 Free
🔴 Ethan Off pace at 50 Free — check in
🟢 Fiona Race ready at 100 Free
🔴 George Off pace at 100 Free
🟡 Hannah Building at 50 Back
🔴 Liam Off pace at 100 IM
🟢 Isla Race ready at 50 Back
⚫ Maya Quiet at 50 Free (no recent swims)
One row per swimmer. One signal. One color. One label. Tap-to-detail.
| If the swimmer is... | Signal | Color |
|---|---|---|
| Race-ready (gap-to-PB < 2% at form-stroke event) | "Race ready at <event>" | 🟢 Green |
| Building toward PB (gap 2-5%, improving trend) | "Building at <event>" | 🟡 Amber |
| Off pace (gap > 5%, declining trend) | "Off pace at <event>" | 🔴 Red |
| Not training this event recently | "Quiet at <event>" | ⚫ Gray |
Coach actions per signal:
| Coach question | What they see | Time to answer |
|---|---|---|
| "Who should I push at this meet?" | Green dots | 0.5 sec |
| "Who needs a check-in?" | Red dots | 0.5 sec |
| "Is the team on track this week?" | Count of green/amber/red | 1 sec |
| "Why is Ethan off pace?" | Tap Ethan → detail with trend chart, gear comparison (paddles vs no-paddles = F-v proxy), within-set pacing profile | 5 sec |
The squad view is the headline insight at a glance. The detail view is the supporting data behind the insight. The two are tiered: headline first, detail on demand.
For sprinters (form_stroke ≤ 100m):
same event (the F-v proxy the user identified)
For endurance (form_stroke ≥ 200m):
Section 2 is honest about labels. The sprint view shows "v_avg per rep" + "gear comparison" — not "F-v operating point," because we don't have F. The gear comparison IS the F-v proxy the stopwatch can derive.
The user's insight that resistance = force metric unlocks the F-v framing ONLY IF the data has gear populated. Today:
workout_sets.gear exists but has 3 distinct values (mostly none and NULL)
recorded_times.gear is none for all 432 rowsThe capture-mechanics fix:
Before each set's timing starts, the app shows one question: "Gear for this set?" with 5 options (none / paddles / pull buoy / fins / parachute). One tap. Then the timer runs.
The recorded_times inherit the gear from workout_sets via the existing join. After 6 weeks of real use, recorded_times.gear has 3-4 distinct values per swimmer, and the F-v proxy is real data the coach didn't have to manually enter.
This honors:
see (which is what they'd already see with their eyes)
The capture-mechanics fix is the single most important change in this design iteration. Without it, the F-v framing is aspirational. With it, the F-v framing becomes real stopwatch-derived data.
Once gear is populated, the per-swimmer detail shows:
Hannah — 50 Free, last 6 weeks
Gear comparison (50 Free, easy intensity):
No gear: 36.2s (n=12, CV 6.5%)
Paddles: 40.1s (n=4) ← +10.7% slower with paddles
Interpretation: Hannah's drag drop with paddles is high.
She's a good force generator; technique is OK. Coach
already knows this from watching her swim — the data
formalizes it.
The chart label is plain English. The interpretation is what the coach already knows. The data formalizes and digitizes it — that's the VISION.md "information-rich effortlessness" in action.
ALTER TABLE swimmers ADD COLUMN endurance_profile text;
-- Values: 'sprint' | 'middle' | 'distance' | 'open_water'
-- NULL = auto-detect from main_stroke distance
CREATE TABLE swimmer_goals (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
swimmer_id uuid REFERENCES swimmers(id),
stroke text NOT NULL,
distance int NOT NULL,
goal_time_ms int NOT NULL,
goal_event_date date,
goal_event_name text,
created_at timestamptz DEFAULT now()
);
CREATE TABLE intensity_weights (
intensity_label text PRIMARY KEY,
weight numeric NOT NULL
);
-- Defaults: T1 = 0.8, T2 = 1.0, T3 = 1.1, T4 = 1.2
-- Used for CTL/ATL/TSB (Bu's load model)
The swimmers.form_stroke column already exists but is barely populated. The swimmers settings UI needs a "Set form stroke" wizard for each swimmer, defaulting from main_stroke + best PB.
| Step | What | Effort | |---|---|---| | 1. Schema migration: endurance_profile + swimmer_goals + intensity_weights | ~80 lines SQL | | 2. swimmers.form_stroke UI in swimmers settings | Coach sets form stroke once per swimmer | ~80 lines | | 3. SquadSignalsViewModel — per-swimmer single-signal computation | Fan-out fetch + compute + label | ~120 lines | | 4. SquadSignalsView — one-screen list | Single column, color-coded rows, tap-to-detail | ~150 lines | | 5. Wire into Analytics tab as the new default landing | Replaces the current list | ~30 lines | | 6. Gear-capture mechanic — one-tap "gear for this set?" picker before timing | Unlocks the F-v proxy | ~150 lines | | 7. Per-swimmer detail's gear comparison view | Section 2 shows paddles vs no-paddles | ~100 lines |
Total: 5 new files + 1 migration + 2 edits, ~710 lines. ~5 hours of work. The gear-capture mechanic (#6) is the biggest unlock — without it, the F-v framing is aspirational.
For every component, the test is:
| Question | If no, redesign |
|---|---|
| Can the coach parse this in <1 sec while watching 24 swimmers? | Reduce complexity |
| Does this label use coach vocabulary (not statistical jargon)? | Use the coach's words |
| Does this respect the engine-can't-be-smarter-than-coach principle? | Strip any "AI recommends" framing |
| Does this surface ONLY when needed, not by default? | Hide behind a tap |
| Can this be dismissed/swiped away without action? | Add the dismiss interaction |
The squad view design above passes all five. The 3-row swimlane failed the first.
| We CAN defend from stopwatch + gear data | We CANNOT (yet) |
|---|---|
| Gap-to-PB% (gear-aware, F-v proxy) | F-v operating point (no F sensor) |
| Within-set pacing profile | SL / SR (no stroke count) |
| Within-session recovery | VO2 max (no gas analysis) |
| Across-week trend | Lactate threshold (no HR) |
| Polarization ratio (intensity distribution) | Force production (no F sensor) |
| Threshold pace trend (T3 intensity times) | Drag coefficient (no kinematic data) |
| Gear comparison (paddles vs no-paddles time) | "F-v profile" in the Samozino protocol sense |
| CTL/ATL/TSB (session volume × intensity weight) |
The squad view tells the coach what we can answer from stopwatch data, with labels in coach vocabulary. The detail view shows the gear comparison as the F-v proxy the coach can interpret from their own experience.
When the squad adds stroke count capture, the F-v framing extends naturally — add SL/SR to the gear comparison, show the (SL × SR) product over time. When they add wearables, add HRV-based recovery. When they add force sensors, add the real F-v profile. Each extension is a row in the detail view, not a redesign of the squad view.
squad views brainstorm (origin)
framing, the inspiration for sprint Section 2
calibration that the prediction engine uses
the "feel" constraint
race time as compared to the swimmer personal best in their best event. ... for the sprinters the force velocity curve is a good resource."
swimmer be able to do to obchieve there objective. physics and biology are the only constraints along with what data we can capture in a session from the live stopwatch"
paddles, parachute etc can act as our force metric. also how are we going to package this for swim coaching so it doesn't detract from their intuition and taste (in the rick rubin sense) on the pool deck. Everything should be inservice of the feel. ... I want the coach to feel like they are levitating in term of the amount of coaching insights they are receiving—all without the working memory overload I and others feel while coaching."
gear = 'none' for all 432 recordedtimes; gear-capture gap is the real blocker
/Users/nathanmaxwell/Documents/VS Code/Hydrolyze 2/VISION.md —"Information-rich effortlessness. ... The goal is zero added stress on pool deck."
Published and managed by TARS, an AI co-author built on Nathan's gbrain.