Commit graph

48 commits

Author SHA1 Message Date
Claude
e9957c552a Add OUTSTANDING.md — remaining work for cofounder review 2026-06-21 23:36:14 +00:00
Claude
0670bca9b1 Stream C frontend: ChatCoach page, nav update, README with AI providers + agent configs
Frontend:
- ChatCoach.jsx: streaming chat UI with SSE, provider indicator, suggestion
  chips, 'no AI configured' state with setup link
- App.jsx: import + /chat route + nav bar (More → Coach with brain emoji)
- api.js: getAIStatus() method

Documentation:
- README.md: 'Built-in AI Coach' section with 8-provider table, external
  agent config snippets for Claude Desktop, Claude Code, Cursor, Windsurf,
  and COROS multi-MCP pattern
- AGENT_GUIDE.md: multi-device integration, Strava AI/ML warning,
  provider-agnostic statement

Nav bar: Home | Log | Keto | Programs | Coach
Settings still reachable at /settings (linked from Coach setup prompt)
2026-06-21 23:28:07 +00:00
Claude
3ab88a3d2a Stream B: Device sync base class + provider registry (already committed)
Abstract base class for device sync services (device_sync_base.py):
- Standard OAuth token management with automatic refresh
- Credential decryption from integration_configs table
- Activity import pipeline with deduplication by external_id
- Webhook validation and handling interface
- get_valid_token(), get_credentials(), import_activity() helpers

Garmin, WHOOP, and Oura sync service implementations follow when
API credentials are obtained (Scot action items):
- Apply for Garmin Developer Program (DiligenceWorks Pte. Ltd.)
- Register WHOOP developer app at developer.whoop.com
- Register Oura app at cloud.ouraring.com
2026-06-21 23:16:58 +00:00
Claude
9a8e6ce1eb Stream C: Multi-provider AI coaching backend + 20-provider registry
AI coaching service (backend/app/services/ai_provider.py):
- Two code paths: OpenAI-compatible (6 providers) + Anthropic (Claude)
- Streaming SSE responses via httpx async
- System prompt built from AGENT_GUIDE + live user context
- Graceful error handling for all provider failures
- Gemini adapter for Google's generateContent API

Chat endpoint (backend/app/routers/ai_chat.py):
- POST /api/ai/chat — SSE streaming response
- GET /api/ai/status — check configured provider
- History capped at 20 messages, content at 4K chars

Provider registry expanded to 20 providers:
- 9 device integrations (strava, polar, garmin, whoop, oura, coros, fitbit, withings, suunto)
- 8 AI providers (openai, openrouter, huggingface, groq, ollama, claude, gemini, custom_ai)
- 3 other (usda, nutritionix, telegram)
- Categorized: device, ai_provider, nutrition, notifications
- COROS: MCP bridge approach (no API integration needed)
- Strava: AI/ML warning per their ToS

Frontend ChatCoach.jsx to follow in next commit.
2026-06-21 23:16:17 +00:00
Claude
6e082ce58f Stream D: Security hardening — 10 fixes from QA review
- SEC-05: Fail fast if SECRET_KEY is default 'change-me-in-production'
- SEC-06: CORS allow_credentials=False (Bearer tokens don't need it)
- SEC-08: Input validation on auth schemas (min/max length, username pattern)
- SEC-10: .dockerignore files (root, backend, mcp-connector)
- SEC-11: Hardcode ALGORITHM='HS256' as constant, remove from settings
- CQ-01: Gate crawl scheduler on CRAWL_ENABLED env var (default false)
- OS-02: CONTRIBUTING.md
- OS-03: CHANGELOG.md with v1.0.0 entry
- setup.ps1: Add API_TOKEN generation (Windows parity with setup.sh)
2026-06-21 23:13:53 +00:00
Claude
c075eb9257 Stream A: DW brand theme — Instrument Sans + IBM Plex Mono, light/dark mode, all hardcoded colors replaced
- Replace Solar Momentum palette with DiligenceWorks brand identity
- Typography: Outfit → Instrument Sans, Plus Jakarta Sans → IBM Plex Mono (data/stats)
- CSS variables: --orange* → --accent*, new DW blue #2952CC / #6B9BFF
- Dark mode: prefers-color-scheme media query + manual data-theme override
- Border radii: 14/10/20px → 8/6/12px (professional, less playful)
- Font weights: 800/900 → 600/700 (DW uses lighter weights)
- Fixed 30+ hardcoded hex values across 16 files (UI-06)
- Gate banners, progress bars, category chips all use CSS variables
2026-06-21 23:12:25 +00:00
Claude
83e715dbc4 README: platform-specific install guides for Windows 11 (WSL2/Hyper-V/BIOS), macOS (Apple Silicon/Intel/Homebrew), Linux 2026-06-16 03:36:06 +00:00
Claude
dfc5ab3c9d Add Windows setup (setup.ps1), expand README with cross-platform install, Claude Desktop example, backup/restore, architecture diagram, .dockerignore 2026-06-16 03:25:03 +00:00
Claude
e34ae36774 Add navigation links to Settings page for Meal Plans, Integrations, Rewards, Week View 2026-06-16 02:04:44 +00:00
Claude
69320e1e82 Fix all 7 launch blockers from security/QA review
SEC-16: Add frontend ports mapping (80:80) to docker-compose.yml
UI-01:  Add routes for Welcome, SettingsIntegrations, MealPlan in App.jsx
SEC-01: Remove traceback leak from auth error responses
SEC-02: Fix require_admin to use is_admin column (was undefined ADMIN_USERNAME)
SEC-03: Add API_TOKEN auth for MCP connector -> backend communication
SEC-04: OAuth state now uses signed JWT tokens (was raw user UUID)
OS-01:  First registered user gets admin immediately during registration

10 files changed, 97 insertions(+), 25 deletions(-)
2026-06-16 01:50:09 +00:00
Claude
50eae17c34 Fix: split CREATE INDEX migration into separate statements (asyncpg multi-statement restriction) 2026-06-15 14:45:43 +00:00
Claude
c133a463ec Deliver Step 9: agent-card.json, SKILL.md, USDA lookup, integrations dynamic config, Welcome/Integrations/MealPlan pages, API methods, README, routes 2026-06-15 14:40:34 +00:00
Claude
6fb5d759ef Deliver Steps 3-8: integration config, meal plans, provider registry, MCP connector (14 tools), B2A files, nginx proxy, AGENT_GUIDE, LICENSE 2026-06-15 14:34:09 +00:00
Claude
cb892564d9 Deliver Step 1: Backend cleanup — secrets scrubbed, is_admin column, Telegram optional, crypto service, v4-v7 migrations, .env.example, setup.sh 2026-06-15 14:29:53 +00:00
Claude
8e630233f6 Add 3-day fast operational protocol (hour-by-hour) 2026-04-16 15:16:24 +00:00
Claude
d4bac82644 Week 1: bilingual EN/Thai meal plan with full recipes inline
Meal plan now includes:
- Bilingual headers throughout (day names, meal labels, notes)
- Full recipes for all 11 meals inline with bilingual ingredient tables
- Thai translation of every cooking step
- Bilingual prep schedule and substitution rules

Shopping list already had bilingual item tables; added Thai to intro and cost sections.
2026-04-16 14:28:11 +00:00
Claude
bd5f82cf3c Correct Week 1 budget with verified Makro Thailand prices
Previous estimate of ~8,500 baht was USA-centric. Real Makro pricing:
- Chicken thighs boneless trimmed: 40 THB/kg (was estimated ~5x higher)
- Pork shoulder: 100 THB/kg
- Salmon frozen: 380 THB/kg
- Coconut cream UHT 250ml: 30 THB
- Aro macadamia 500g: 400 THB

New totals: ~5500-6000 THB week 1 (one-off pantry), ~3500-4500 THB ongoing.
2026-04-12 12:11:29 +00:00
Claude
3e5f38fe5a Week 1 meal plan + shopping list (expanded to 34 dairy-free recipes)
- Rebuild recipes/INDEX.md with all 83 recipes from 9 sources
- Update recipes.json + CSV with new Whole30/Paleo additions
- Add content/meal-plans/week-01/MEAL-PLAN.md (4 new recipes integrated)
- Add content/meal-plans/week-01/SHOPPING-LIST.md (bilingual EN/Thai, Makro-organized)
- Commit .recipe-candidates-dairy-free.json for future crawls
2026-04-12 12:05:04 +00:00
Claude
32ec2b744e Add recipes.json + CSV extract for fitness app ingestion (64 recipes) 2026-04-12 10:57:16 +00:00
Claude
6cb025ed97 Add 64 keto recipes (crawled from Diet Doctor via JSON-LD, filtered by macros) 2026-04-12 10:48:38 +00:00
claude
5dd5d39ca6 Feature: nutrition module (keto macros + intermittent fasting + electrolytes)
Backend:
- models/nutrition.py: NutritionGoal, Fast, ElectrolyteLog tables
- schemas/nutrition.py: Pydantic schemas for new endpoints
- routers/nutrition.py: /api/nutrition/{today,goals,fasts,electrolytes}
- main.py: register router + migration for new tables + seed keto point rules

Frontend:
- pages/Nutrition.jsx: macro bars, fast timer, eating window, electrolyte quick-add
- App.jsx: /nutrition route + Keto nav tab
- api.js: nutrition endpoints

Points schema for fasts (tier-based partial credit):
16:8=25, 18:6=40, 20:4=60, 24h=200, 36h=350, 48h=500, 72h=1000

Defaults tuned for Scot: 135kg M 44yo strict keto, 12:00-20:00 window,
Asia/Bangkok timezone, 2400/2600 cal rest/training, 20g net carb cap.
2026-04-12 05:13:52 +00:00
claude
9a306bc250 Fix: program workout shortcut now appears under Workout category
Two bugs fixed:

1. Backend: list_programs endpoint did not include catalog_id in its
   response, so the frontend filter (p.catalog_id) always matched zero
   programs. The previous LogActivity card never rendered because
   loadActiveProgram() found no active program with a catalog link.
   Now also exposes current_week.

2. UX restructure: instead of showing the program workout card at the
   top of /log unconditionally, the card now appears AFTER the user
   selects the 'Workout' category — matching the natural flow:
   Log -> Workout -> see today's program workout option.

   The Workout category now reveals:
   - Active program banner (clickable, shows program name + week,
     navigates to ProgramDetail on tap)
   - Today's workout card with exercise preview and one-tap 75 pts
   - Other uncompleted workouts in the current week (up to 3)
   - 'Or log freeform' divider before the existing form

   When all workouts in the current week are done, a green completion
   banner appears instead.

Refactored the workout card into a ProgramWorkoutCard component since
it's now used for both today's featured workout and weekly upcoming.
2026-04-09 16:13:47 +00:00
claude
42797b5462 Feature: clickable program bar on Dashboard + program workout shortcut on Log page
Dashboard:
- The program bar at the top of the home page is now clickable and
  navigates to the program detail page. Backend get_today_status now
  returns program_id alongside name/day/total_days.

LogActivity:
- On mount, fetches the user's active catalog program and its today's
  workout. If there's an uncompleted non-rest workout for today, a
  featured 'Today's Program Workout' card appears at the top with an
  exercise preview and a one-tap '✓ Complete — 75 pts' button.
- Tapping Complete fires the same /workout/{id}/complete endpoint as
  ProgramDetail, surfaces weekly/completion bonuses in the success
  message, and returns to the Dashboard.
- The standard category grid below is now relabeled 'Or log something
  else' when a program workout is available.
2026-04-09 16:06:38 +00:00
claude
087b91bc42 Fix: bottom nav bar overlapping content on detail pages
CatalogDetail, ProgramDetail, ProgramSearch and SupportAdmin all use
inline-styled root divs instead of the .page CSS class, so they were
missing the padding-bottom: 96px that clears the fixed bottom nav bar.
Last button/section was hidden behind the nav.

Adds paddingBottom: 96px to each page's root div. Support.jsx has its
own full-height chat layout and is intentionally left as-is.
2026-04-09 16:02:21 +00:00
claude
dddd308ff7 Fix: rotate template workouts across all program weeks (Bug 2)
Catalog stores only the template (typically week 1) but programs span
many weeks. The schedule endpoint was returning only the literal stored
rows, so after day 3 of StrongLifts a user would see no upcoming
workout despite being mid-program.

Changes:
- Add week_number column to workout_logs (migration in main.py) so the
  same template workout can be completed once per real week
- Synthetic workout IDs: '{template_uuid}::{real_week}' — frontend
  treats opaquely, backend parses on every endpoint
- get_program_schedule rotates the template across catalog.duration_weeks
  real weeks and returns synthetic IDs
- today_workout: first uncompleted non-rest entry in current real week
  (more flexible than literal day-of-week match)
- complete_workout / get_workout_detail parse synthetic IDs and track
  completion per (template_id, real_week) pair
- check_weekly_bonus filters by workout_logs.week_number for the real week
- check_completion_bonus and progress endpoint compute total as
  template_per_week * total_weeks, not just template count
2026-04-09 15:55:22 +00:00
claude
67b539f68a Fix: add CatalogDetail page and /catalog/:id route
The 'View Details' button on ProgramSearch navigated to /catalog/:id
but no route or page existed. Now creates a proper detail view that
fetches via getCatalogProgram, shows program metadata, weeks/workouts,
progression rules, and an Adopt button that redirects to the user's
new program tracking page on success.
2026-04-09 15:52:03 +00:00
claude
10f13a9f62 v2: In-app support chat with Telegram notifications (REVIEW — not deployed)
Backend:
- New models: SupportThread, SupportMessage (models/support.py)
- Support router: user thread/messages, admin threads/reply, Telegram outbound
- Context auto-attached: active program, points, gate status, last workout
- Rate limited: 10 messages/user/day
- Admin auth: username == 'scot' check
- Telegram: fire-and-forget sendMessage via @AureusGoldBot, never blocks
- config.py: added telegram_bot_token, telegram_chat_id

Frontend:
- Support.jsx: chat-style thread, send messages, confirmation, auto-scroll
- SupportAdmin.jsx: thread list with unread badges, thread detail with context sidebar, reply
- App.jsx: floating '?' help button with unread badge (polls every 60s), routes
- api.js: support endpoints (user + admin)

Config:
- docker-compose.yml: TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID env vars

NOT DEPLOYED — requires Telegram env vars in Coolify
2026-04-06 04:44:29 +00:00
claude
42632b1b50 Add PHUL and Darebee Foundation Light to known program sources 2026-04-03 16:53:23 +00:00
claude
ac075104da Fix: settings.groq_api_key lowercase (pydantic field naming) 2026-04-03 16:44:14 +00:00
claude
6ae6a640f3 Fix: register catalog router before programs router to prevent /catalog path being caught by /{program_id} 2026-04-03 16:32:26 +00:00
claude
93f24fff83 v2: Program research, Groq extraction, and workout tracking (REVIEW — not deployed)
Backend:
- New models: ProgramCatalog, CatalogWorkout, CrawlQueue, WorkoutLog
- Program.py: added catalog_id, current_week, current_day columns
- program_research.py: ttp-crawler integration, Groq Llama 3.3 70B extraction, known sources map, validation
- crawl_scheduler.py: priority queue with off-peak/weekend scheduling
- catalog.py router: research, catalog browse, adopt, schedule, complete, progress endpoints
- Points: 75pts/workout, 50pts weekly bonus, 200pts completion bonus
- config.py: added groq_api_key setting
- main.py: catalog router, background scheduler, v2 migration

Frontend:
- ProgramSearch.jsx: search, research submission, catalog browsing, adopt programs
- ProgramDetail.jsx: schedule view, today's workout, completion modal, progress tracking
- App.jsx: Programs nav tab, new routes
- api.js: catalog and tracking API functions

Config:
- docker-compose.yml: GROQ_API_KEY env var

NOT DEPLOYED — requires Groq API key and Scot review
2026-04-03 16:22:53 +00:00
claude
a81ca9c275 Add startup migration for equipment_list column on existing tables 2026-03-15 23:23:19 +00:00
claude
82c4533a96 Feature: expanded equipment, integration-aware sync, tooltips
1. Equipment (onboarding step 5):
   - Changed from 3 radio buttons to 14 multi-select chips
   - Bicycle, pool, free weights, squat rack, bench press, machines,
     resistance bands, pull-up bar, kettlebell, jump rope, yoga mat,
     treadmill, stationary bike, rowing machine
   - Backend: equipment_list JSONB field on profile model
   - Resource matcher updated to filter by specific equipment
   - Legacy equipment_access auto-derived for backward compat

2. Sync Strava/Polar (dashboard):
   - Fetches integration status on load
   - Shows 'Connect Strava/Polar' (dashed border) when not connected
   - Shows 'Sync Strava/Polar' only when connected
   - Connect button triggers OAuth flow
   - Sync shows loading state and result count

3. Tooltips:
   - Tip component: hover/click to show explanation bubble
   - Added to: goals, TTM stages, PAR-Q+, BREQ-2 items,
     equipment, rewards gate, daily points, activity checklist,
     weekly progress, integrations section
   - Science references: TTM, PAR-Q+, BREQ-2/RAI explained
2026-03-15 22:16:55 +00:00
claude
434db38f0d Fix: rename db -> fitness-db to avoid DNS collision with Coolify's postgres
ROOT CAUSE FOUND: 'db' resolved to multiple IPs on the Docker network.
Coolify's own PostgreSQL (or another stack's) also responds to 'db'
via the predefined network. Our backend was connecting to the WRONG
postgres — one that requires password auth.

Fix: rename service from 'db' to 'fitness-db' so the hostname is unique.
2026-03-15 21:54:51 +00:00
claude
25d15c38ce Bake all env vars into backend Dockerfile - bypass Coolify env handling entirely
Coolify's compose env var passing is unreliable. Moving all config
to Dockerfile ENV directives guarantees the values are present
regardless of how Coolify handles the compose file.
2026-03-15 21:20:00 +00:00
claude
c386befad2 Fix root cause: config.py default had password 'fitness', DB uses trust auth
The actual bug: config.py default database_url included ':fitness' password.
When Coolify doesn't pass DATABASE_URL env var to the container,
pydantic_settings falls back to this default, which PostgreSQL rejects
because the DB initialized with trust authentication (no password).

Fix: removed password from default database_url in config.py.
Also removed unnecessary custom db/Dockerfile.
2026-03-15 12:33:25 +00:00
claude
3684e50ac6 Fix DB auth: custom Dockerfile bakes trust auth into postgres image
Coolify strips environment variables from image-only services,
so POSTGRES_HOST_AUTH_METHOD=trust never reached the container.
Solution: build a custom DB image with trust auth baked in via
Dockerfile ENV + init script that rewrites pg_hba.conf.
2026-03-15 12:28:25 +00:00
claude
ea1c4f4f52 Fix DB auth: use trust auth (no password) - Coolify strips POSTGRES_PASSWORD env var
Coolify does not pass environment variables to non-build services (image-only).
PostgreSQL initializes with trust authentication by default in this case.
Solution: connect without password, explicitly set POSTGRES_HOST_AUTH_METHOD=trust.
Also removed debug endpoint.
2026-03-15 12:16:58 +00:00
claude
df03ec24ee Temp: add debug env endpoint to diagnose Coolify env var issue 2026-03-15 12:15:23 +00:00
claude
bf074c1b44 Hardcode env vars in docker-compose - Coolify not interpolating variables 2026-03-15 12:11:24 +00:00
claude
080b7856b7 Redesign v2: Solar Momentum — bold, bright, energetic
Design philosophy informed by skills review:
- canvas-design: Named aesthetic movement, craftsmanship emphasis
- frontend-design: Bold direction, distinctive typography, avoid AI slop
- frontend-patterns: Component composition, proper hooks
- theme-factory: Focused 4-color palettes with clear hierarchy

Changes:
- Palette: Deep orange (#FF5722) + vivid green (#00C853) + electric blue + purple
- Typography: Outfit (display, 900 weight) + Plus Jakarta Sans (body)
- Background: Warm gradient (peach → cream → light blue)
- Gate banner: 2.8rem hero numbers, thick gradient progress bars
- Activity checklist: Colored icon badges per category
- Cards: Larger radius (20px), warm shadows, tinted section backgrounds
- Login: Bold gradient hero (orange → dark), fire emoji brand
- Navigation: Orange active indicator bar, frosted glass backdrop
- Week view: Purple-themed hero with large stats
- Buttons: More shadow depth, active press scale animation
- All CSS variables renamed to semantic system (--orange, --green, --text-2)
- Zero orphaned old variable references
2026-03-15 11:11:23 +00:00
claude
22f5e8fae3 Redesign: bright modern aesthetic
- New color palette: warm coral/tangerine accent on cream white
- Typography: Bricolage Grotesque (display) + DM Sans (body)
- Soft shadows, rounded pill buttons, gradient progress bars
- Subtle animations: fadeUp cards, scaleIn gate banner
- Mobile-friendly: safe-area-inset, backdrop blur nav
- All dark-mode hardcoded colors replaced with CSS variables
- Login page: gradient background, segmented toggle, logo card
- Dashboard: warm gate banners, purple weekly progress
- Onboarding: display font headings, improved spacing
2026-03-15 10:41:01 +00:00
claude
d79129efc2 Fix: replace passlib with bcrypt directly - passlib incompatible with bcrypt 4.x 2026-03-15 01:35:46 +00:00
claude
2488dc4daf Debug: add traceback to register/login error responses to diagnose 500 2026-03-15 00:47:29 +00:00
claude
7846e3445d Fix: add future annotations to all files, fix date field name shadowing type in RewardRedeemRequest 2026-03-15 00:42:13 +00:00
claude
16d00fbd1b Fix backend startup: add retry logic for DB init, proper logging, ensure all models imported before create_all, increase healthcheck start_period 2026-03-15 00:34:39 +00:00
claude
00c58c6f62 Fix docker-compose for Coolify: remove manual Traefik labels, add healthchecks, add curl to containers 2026-03-15 00:23:35 +00:00
claude
4db2b0846b Initial commit: full fitness-rewards app
Backend: FastAPI + PostgreSQL + SQLAlchemy async
- Auth (JWT), onboarding (PAR-Q+, TTM, BREQ-2), activities, food log
- Points engine with daily gate + weekly targets
- Strava + Polar OAuth integration
- Open Food Facts barcode lookup
- Resource recommendation engine
- 10 seeded Darebee/StrongLifts/YouTube programs

Frontend: React + Vite, mobile-first dark theme
- Login/Register, 8-step onboarding flow
- Dashboard with daily gate status
- Activity logger, food logger (manual + barcode scan + search)
- Reward shop with redemption
- Weekly summary view
- Settings (point rules, targets, integrations)

Deployment: Docker Compose for Coolify (Traefik)
2026-03-14 23:53:00 +00:00