| # PLAN.md — MVP implementation tracker |
|
|
| This is the working tracker for the hackathon build. `PROJECT.md` explains the product |
| and architecture; `DECISIONS.md` records decisions. This file answers: where are we, |
| what is done, what is next, and what decisions are blocking implementation. |
|
|
| --- |
|
|
| ## Current status |
|
|
| **Current phase:** Phase 7 — Persistence / Phase 8 — Submission readiness |
|
|
| **Current task:** prove the local daily loop end to end, then configure/deploy the |
| optional Hugging Face Dataset persistence. |
|
|
| **Next decision gate:** decide the actual private Dataset repo id and Space secret |
| setup. |
|
|
| **Training-rule source:** `hypertrophy_app_training_rules.md`. |
|
|
| **Local app:** running at `http://127.0.0.1:7860` when started with: |
|
|
| ```bash |
| scripts/reset_server.sh |
| ``` |
|
|
| **Test command:** |
|
|
| ```bash |
| .venv/bin/python -m unittest discover -s tests |
| ``` |
|
|
| --- |
|
|
| ## Phase 0 — Project alignment |
|
|
| **Goal:** lock the MVP direction and hackathon strategy. |
|
|
| **Status:** Done |
|
|
| - [x] Read `AGENTS.md`, `PROJECT.md`, and `DECISIONS.md`. |
| - [x] Decide that the MVP includes text-first check-in extraction. |
| - [x] Decide that the parser may use a small model, but the engine remains deterministic. |
| - [x] Decide that the engine receives only structured data. |
| - [x] Decide storage path: interface first, local JSON first, Hugging Face Dataset later. |
| - [x] Add hackathon optimization goals to `PROJECT.md`. |
|
|
| --- |
|
|
| ## Phase 1 — Real MVP UI shell |
|
|
| **Goal:** make the first screen match the real daily loop before real parser/engine logic |
| exists. |
|
|
| **Status:** Done for first scaffold |
|
|
| - [x] Create runnable Gradio app. |
| - [x] Convert app to `gr.Blocks`. |
| - [x] Add `Today` tab. |
| - [x] Add natural-language check-in box as the main input. |
| - [x] Add editable structured fields for time, energy, sleep, soreness/constraints, |
| pain/injury, and mood/stress. |
| - [x] Show hardcoded session preview. |
|
|
| **Not done yet:** |
|
|
| - [x] Replace manual structured fields with parser-filled fields. |
| - [x] Replace hardcoded preview with engine output. |
|
|
| --- |
|
|
| ## Phase 2 — Core schema |
|
|
| **Goal:** define the shared data contract before parser, engine, logging, and persistence. |
|
|
| **Status:** Done for MVP schema |
|
|
| **Done:** |
|
|
| - [x] Decide schema implementation: Pydantic. |
| - [x] Create `training_coach/` package. |
| - [x] Add `CheckIn`. |
| - [x] Add `PainIssue`. |
| - [x] Add `ParsedCheckIn`. |
| - [x] Add `ContextSignal`. |
| - [x] Add `Exercise`. |
| - [x] Add anatomical `Muscle` enum. |
| - [x] Add `PrescribedSet`. |
| - [x] Add `PlannedExercise`. |
| - [x] Add `SessionPlan`. |
| - [x] Add `LoggedSet`. |
| - [x] Add `LoggedExercise`. |
| - [x] Add `SessionLog`. |
| - [x] Add model tests. |
|
|
| **Current models:** |
|
|
| - `CheckIn` |
| - `PainIssue` |
| - `ParsedCheckIn` |
| - `ContextSignal` |
| - `Exercise` |
| - `Muscle` |
| - `PrescribedSet` |
| - `PlannedExercise` |
| - `SessionPlan` |
| - `LoggedSet` |
| - `LoggedExercise` |
| - `SessionLog` |
|
|
| **Next tasks:** |
|
|
| - [x] Decide and add `LoggedSet`. |
| - [x] Decide and add `SessionLog`. |
|
|
| **Known future schema additions:** |
|
|
| - [ ] Exercise equipment, deferred until equipment availability/substitution matters. |
| - [ ] Supersets, drop sets, rest-pause, and other advanced set types, deferred until the |
| classic-set MVP works. |
|
|
| --- |
|
|
| ## Phase 3 — Small model parser |
|
|
| **Goal:** convert natural-language check-ins into validated `CheckIn` objects. |
|
|
| **Status:** Done for MVP parser |
|
|
| **Decision status:** |
|
|
| - [x] Choose local parser model: Ollama `qwen3:1.7B`. |
| - [x] Replace the Hugging Face Spaces Transformers parser with a GGUF llama.cpp path. |
|
|
| **Acceptance rule:** |
|
|
| - Local development/evaluation now prefers Ollama because quantized llama.cpp/Metal |
| inference is much faster on the Mac than local Transformers CPU/disk-offload. |
| - Current local parser default: `qwen3:1.7B`, chosen for MVP parser speed. |
|
|
| **Tasks:** |
|
|
| - [x] Add parser output schema with missing fields, structured follow-up items, display |
| follow-up questions, and context signals. |
| - [x] Create parser module. |
| - [x] Define strict JSON prompt/output format. |
| - [x] Fix parser keys and enum values through schema validation. |
| - [x] Validate model JSON into `ParsedCheckIn`. |
| - [x] Add optional local Transformers runtime wrapper. |
| - [x] Add parser backend selector for local Ollama vs Space llama.cpp runtime. |
| - [x] Add Ollama local runtime wrapper with JSON-schema structured outputs. |
| - [x] Add GGUF llama.cpp runtime wrapper for Hugging Face Spaces CPU deployment. |
| - [x] Run the model on one fixture and parse raw text into `ParsedCheckIn`. |
| - [x] Run the model against all acceptance fixtures. |
| - [x] Remove overfit fixture-shaped prompt examples. |
| - [x] Replace canned keyword follow-up triggers with LLM-proposed structured |
| `follow_up_items`. |
| - [x] Add deterministic cleanup for duplicate, already-answered, or unsupported |
| follow-up questions. |
| - [x] Add deterministic parser cleanup for obvious missing muscle mappings. |
| - [x] Remove stale/repetitive sleep follow-up questions when sleep hours and quality are |
| already known. |
| - [x] Add parser tests/fixtures under `tests/fixtures/`: |
| - [x] short time + poor sleep + low energy |
| - [x] soreness/pain constraint |
| - [x] ambiguous check-in requiring `unsure` or notes |
| - [x] adjacent context signal such as "yesterday I ran a 10k" |
| - [x] high energy + long session |
| - [x] Wire parser output into editable UI fields. |
|
|
| **Current parser evaluation result:** |
|
|
| - `Qwen/Qwen2.5-1.5B-Instruct` passed 1/5 acceptance fixtures on the first full local |
| run. |
| - Main failures: missed explicit "no pain", over-asked for sleep hours, produced |
| markdown code fences for some JSON, missed the 10k context signal, and added unrelated |
| pain notes. |
| - Local Transformers `Qwen/Qwen3-4B` was too slow on Mac because it offloaded to disk. |
| - Ollama `qwen3:8b` completed the same fixture run much faster and passed 2/5 under the |
| current strict exact-match evaluator. |
| - Ollama `qwen3:8b` produced valid schema-shaped JSON, but needs tighter fixed context |
| labels and a less brittle evaluator for free-text notes/follow-up wording. |
| - Context signal labels are now fixed enum values, and the evaluator now treats free-text |
| notes/follow-up wording semantically while keeping labels/enums/numbers strict. |
| - Ollama `qwen3:4b` is installed and passed 2/5 acceptance fixtures. Main failures: |
| missed mapping "tricep" to `triceps_brachii`, omitted follow-up questions for the 10k |
| context signal, and failed one semantically acceptable ambiguous-pain follow-up due to |
| evaluator wording. |
| - We no longer treat 5/5 one-shot fixture passing as the main goal. The product behavior |
| is now multi-round: parse what is clear, ask structured follow-up questions, then build |
| a session once the structured check-in is good enough. |
| - The Today UI now uses a chat-style check-in conversation and updates editable fields |
| after each message. |
| - Parser output is now wired into the editable Today UI fields. |
|
|
| --- |
|
|
| ## Phase 4 — Engine slice |
|
|
| **Goal:** build deterministic session plans from structured check-ins and history. |
|
|
| **Status:** Done for MVP spine |
|
|
| **Blocked by:** your training rules. |
|
|
| **Important rule:** no training logic gets invented by the agent. When engine work needs |
| a rule, it must come from you and be recorded in `DECISIONS.md`. |
|
|
| **Tasks:** |
|
|
| - [x] Decide MVP split and exercise list. |
| - [x] Decide exercise order. |
| - [x] Encode fixed 4-day template in `training_coach.engine`. |
| - [x] Preserve per-exercise rest targets in `PlannedExercise`. |
| - [x] Add unit tests for the fixed 4-day template. |
| - [x] Decide how to select today's training day. |
| - [x] Decide minimum completed-session fields for MVP logging. |
| - [x] Implement next-day state from completed session logs. |
| - [x] Add local JSON history storage. |
| - [x] Decide first readiness/time adaptation rules. |
| - [x] Implement readiness set/RIR modifiers. |
| - [x] Implement pain/injury exercise filtering using muscle tags. |
| - [x] Implement time compression from `time_available_minutes`. |
| - [x] Decide double-progression MVP load increment. |
| - [x] Decide double-progression rep range rule. |
| - [x] Implement double progression: add reps before load, then +1 kg and reset reps. |
| - [x] Implement pure Python `build_session_for_day(...)` entry point. |
| - [x] Add unit tests for every encoded MVP rule. |
|
|
| **Current fixed template:** |
|
|
| - [x] Day 1: Pullover, row, incline bench, incline fly, goblet squat. |
| - [x] Day 2: Skullcrusher, lateral raise, triceps extension, cable lateral raise, |
| barbell curl, hip thrust, standing calf raise. |
| - [x] Day 3: Incline bench, incline fly, row, pullover, Romanian deadlift. |
| - [x] Day 4: EZ-bar curl, lateral raise, hammer curl, cable lateral raise, triceps |
| extension, goblet squat, standing calf raise. |
|
|
| **MVP simplification:** |
|
|
| - [x] All exercise rests are normalized to 1 minute for now. |
| - [x] Double progression uses fixed +1 kg load jumps for now. |
| - [x] Single-rep template prescriptions become 5-rep ranges with the original rep target |
| as the middle value. |
| - [x] Pain filtering removes affected exercises instead of substituting replacements. |
| - [x] Time compression cuts later/lower-priority sets first. |
| - [x] Readiness modifies set count and target RIR. |
|
|
| --- |
|
|
| ## Phase 5 — End-to-end daily loop |
|
|
| **Goal:** check-in text produces a real deterministic session plan. |
|
|
| **Status:** Done for local MVP |
|
|
| **Tasks:** |
|
|
| - [x] Parser extracts `CheckIn`. |
| - [x] Parsed fields are visible/editable. |
| - [x] Engine builds `SessionPlan`. |
| - [x] UI renders session clearly enough to train from. |
| - [x] Keep explanation factual and based on engine output. |
|
|
| --- |
|
|
| ## Phase 6 — Logging |
|
|
| **Goal:** record what actually happened in training so the next session and double |
| progression have real history. |
|
|
| **Status:** Done for local MVP |
|
|
| **Tasks:** |
|
|
| - [x] Decide MVP completed-session shape for day tracking and progression. |
| - [x] Add performed-set logging UI. |
| - [x] Save actual reps/loads. |
| - [x] Save the completed training day number. |
| - [ ] Attach logs to the planned session/check-in. Deferred by the minimal-history MVP |
| compromise. |
| - [x] Derive next suggested day from the last completed day. |
| - [x] Add tests for log serialization. |
|
|
| --- |
|
|
| ## Phase 7 — Persistence |
|
|
| **Goal:** make training history survive restarts and deployments. |
|
|
| **Status:** Local persistence done; durable deployment persistence next |
|
|
| **Tasks:** |
|
|
| - [x] Create storage interface. |
| - [x] Add local JSON storage. |
| - [x] Add Hugging Face Dataset storage. |
| - [x] Load history on startup. |
| - [x] Append completed session logs. |
| - [ ] Prove restart survival. |
|
|
| --- |
|
|
| ## Phase 8 — Submission readiness |
|
|
| **Goal:** make the app demoable and optimized for the hackathon. |
|
|
| **Status:** Not started |
|
|
| **Tasks:** |
|
|
| - [ ] Deploy to Hugging Face Space. |
| - [ ] Add proof-of-use view from real logs. |
| - [ ] Write field notes. |
| - [ ] Record short demo video. |
| - [ ] Prepare submission copy. |
|
|
| --- |
|
|
| ## Phase 9 — Stretch |
|
|
| **Goal:** only after the MVP spine works. |
|
|
| **Status:** Not started |
|
|
| - [ ] Coach-style narration. |
| - [ ] Progress charts. |
| - [ ] Better parser model. |
| - [ ] Tiny Titan route. |
| - [ ] Research-reader. |
| - [ ] Fine-tuning. |
| - [x] llama.cpp route. |
| - [ ] Custom UI polish. |
|
|
| --- |
|
|
| ## Immediate next step |
|
|
| Prove the local spine with one manual end-to-end training loop, then implement durable |
| Hugging Face Dataset persistence so the deployed Space does not lose history. |
|
|
| Proposed starting point: |
|
|
| ```txt |
| messy check-in + local history -> adjusted session -> completed log |
| ``` |
|
|
| Use the app with a few intentionally messy check-ins and inspect whether the plan notes |
| explain every modification. |
|
|