Back to Developer Logs

Build Log — February 4, 2026

Build Log — February 4, 2026

Context / Focus for Today

Ground-up rework of how paces flow through the entire stack. Hardcoded pace values are gone — everything now uses zone references derived from the athlete's profile. 19 PRs merged, new single-day record.


Things I Got Done Today

Pace System Overhaul — Zone References Replace Hardcoded Paces

The big theme today: a ground-up rework of how paces flow through the entire stack. Hardcoded pace values are gone — everything now uses zone references derived from the athlete's profile.

  • PR #271 fix: add pre-computed pace reference tables to AI system prompts — Marathon/Half/10K/5K lookup tables so the LLM never has to do division
  • PR #273 fix: add pace lookup tables + server-side goal pace computation — server-side Goal Pace pre-computation in both streaming and non-streaming routes
  • PR #274 fix: remove all hardcoded paces from plan engine workouts — effort-based labels replace magic numbers
  • PR #276 feat: add structured_data normalizer for AI-generated workouts — server-side safety net that infers pace targets from athlete profile when AI omits them
  • PR #277 fix: infer missing pace targets in structured workout data — normalizer classifies step intensity from label/phase
  • PR #278 fix: replace 'none' targets on workout steps with actual pace — handles Haiku outputting target: { type: "none" } explicitly
  • PR #279 fix: pass marathon pace to normalizer to fix wrong pace targets — marathonPaceSecPerMile extracted from A-race event
  • PR #280 fix: plan engine workout days, frequency, and pace derivation
  • PR #281 feat: switch plan generation from hardcoded paces to zone references
  • PR #282 fix(ai): use zone references instead of hardcoded paces for running
  • PR #284 fix: add id and kind to workout steps for proper zoneRef preservation
  • PR #285 fix: preserve zoneRef in plan engine workout conversion

Bug Fixes

  • PR #266 fix: cap long run distances, progressive taper, race week handling — distance caps + progressive taper protocol
  • PR #268 fix: add distance caps to create_workouts + steer AI to plan engine for multi-week plans
  • PR #269 fix: replace chat input with auto-resizing textarea — grows up to 4 lines, Enter sends, Shift+Enter for newlines
  • PR #272 fix: replace chat input with auto-resizing textarea (clean follow-up)
  • PR #270 fix: improve Garmin sync error handling — automatic retry on OAuth token expiry, better error messages

Other

  • PR #275 blog: daily log for February 3, 2026
  • PR #283 fix: force light mode on landing page and refine UI

Direct Commits

  • feat: open dashboard as modal instead of separate page
  • feat: add mouse wheel scrolling to navigate between months
  • feat: add staggered slide-in animation for calendar workouts
  • fix: slow down calendar workout animation timing
  • fix: prevent pace settings from being overwritten on new devices
  • fix: use correct X brand logo and add Discord logo in footer
  • Swap hero image to TT bike triathlete + add plus.unsplash.com to CSP

Commits Today

  • 19 PRs merged — new single-day record
  • Major: Complete pace system overhaul (12 PRs)
  • Major: Server-side normalizer for AI workout validation
  • Fix: Distance caps, chat input UX, Garmin error handling
  • UX: Modal dashboard, mouse wheel month nav, staggered animations

Notes / Observations

  • Never trust LLMs with arithmetic. Pre-compute lookup tables and validate server-side.
  • Tool schemas don't carry implicit guidance. Switching from JSON fallback to tool calling changes what the AI outputs — the examples in prompts don't transfer. Always add a server-side safety net.
  • Zero hardcoded paces remain in the plan engine or AI prompts. Everything derives from athlete zones/profile.
  • Calendar UX polish: Modal dashboard, mouse wheel month navigation, staggered slide-in animations for workouts.

Momentum Score: 10 / 10

New single-day PR record with 19 PRs merged. The pace system went from "hardcoded magic numbers scattered everywhere" to "fully zone-referenced with server-side validation." Every workout now derives paces from the athlete's profile. The server-side normalizer catches any AI omissions — a proper safety net. Calendar UX improvements shipped alongside the core fixes. Peak productivity day.