Changelog

Recent updates and improvements.

newAugust 20, 2026

Version 1.1.6

**Build 145** · 20 August 2026 · · · The transition now says what is coming next "When I create a simulation without runs, the transition screen doesn't show which exercise comes next." The screen asked the wrong question: `activeRunCount == 0` — what the FORMAT has, not what THIS race contains. A Deadly Dozen Track whose runs you deselected in the planner still reports twelve. So the code fell through to nothing, and between two Labours you stood there with a timer, a READY button and no announcement. It is the same distinction the gate flow already carries: "has this race any runs" and "does run n exist" are two different questions. A run the variant does not have — or that your plan struck out — IS a station. The answer now lives in `RaceManager.upcomingStation`, where the state and the plan sit together, instead of being derived in the view. A struck-out station is stepped over rather than reported as nothing: deselecting one exercise must not swallow the announcement for the next. The run screen had a second, separate version of the same question. It was correct — but a copy is a second place to forget the fix. Both now ask the same source. **Build 145** · 20 August 2026 · · · An expression one Mac compiles and the other does not "The compiler is unable to type-check this expression in reasonable time" — building on the second Mac, with the release version of Xcode instead of the beta. `paceSessionData` ended in a long chain: `Array(…).compactMap { … }.enumerated().map { (i, t) in (i + 1, t.0, t.1) }`, four filters and two closures ahead of it, and finally an UNLABELLED tuple converting into the property's labelled tuple type. Exactly the shape the type checker solves in a second on one machine and gives up on at the next — different Xcode versions have different type checkers. It is written out as loops with explicit types now: the same thing for the reader, nothing left to infer for the compiler. Then the whole app target was measured with `-warn-long-expression-type-checking` rather than waiting for the next failure. The second worst case was real code and stood there TWICE verbatim: the same `filter.flatMap.filter.compactMap.min` chain — with an array `+` inside the flatMap and a `??` inside the compactMap — once in `raceBestTime` and once in `bestCombinedTime`, over two seconds each. Both now go through one `raceBest(for:)`, written as a loop. Eight expressions over 250 ms remain, the largest of them a `#Preview` — none anywhere near what fails. And then stopped looking at time, and looked at shape A second failure on the same Mac — `RacePlannerView.swift:837` — showed the measurement here is a weak proxy: that site had not appeared in my list at all. Wall-clock time on one machine says nothing about solver steps on another. So the search went structural, by shape rather than duration: large view body × many chained modifiers. Every modifier wraps the previous type, so a long chain is ONE deeply nested generic the type checker has to solve in a single go. The ranking confirmed the failing case and found four more — the worst being the app's root view: - `GridRaceApp.swift` — 266 lines, **28 modifiers** → five stages - `WorkoutBuilderView.swift` — 338 lines, 17 modifiers → three stages - `TrainingPlanViews.swift` — 184 lines, 20 modifiers → three stages - `GridRaceWatchApp.swift` (watch start screen) — 135 lines, 20 modifiers → three stages - `RacePlannerView.swift` — 280 lines, 16 modifiers → four stages Each stage is its own type-check unit. The rendered view is unchanged: same chain, named in the middle. Proven rather than assumed: modifier ORDER is meaningful, so all five chains were compared before and after position by position — **101 modifiers, the same set in the same order everywhere.** **Build 145** · 19 August 2026 · · · "Keep them" now actually keeps them — Monday to Wednesday stay "On the AI import I did say it should keep them, but it deleted the trainings from Monday to Wednesday of this week." Two holes between that button and the saved plan, and I built the first one myself yesterday. **The main fault.** Yesterday I stopped duplicate weeks by no longer prepending an archived week that overlaps the new plan — two rows for one calendar week was exactly what had been reported. But the archived row is the one carrying the training and the new one is empty, so leaving it out made Monday, Tuesday and Wednesday disappear. Formally the sessions were still in the archive, in the workout history and in the training load — but in the plan, where you look, they were gone. Completed days are now **written back into the new plan by date** rather than only moving to the archive. Whole: status, completion date, logged sets, RPE, notes and the linked race. And only where the new plan has nothing completed on that day — so the archive can never overwrite newer training. **The second fault, found in the same pass.** When you paste a revised week, `mergeWeeks` replaced the WHOLE week in one line, with no protection at all. Exactly the shape already documented and fixed for its neighbour `replaceDaysInActivePlan`; this is the copy beside it that nobody carried the fix across to — and it is the one the AI revision path actually runs through. It now replaces day by day, a completed day stays, and the message tells you how many were kept. · · · Analyse tab, continued Workout History is back in first place, and the 32 sections sit in named bands you can fold shut. **Build 145** · 19 August 2026 · · · The Analyse tab is tidied up 32 sections sat in a single column, all open at once, in an order that had grown rather than been chosen: four heart-rate cards stood between the race splits and the run cards, and three all-time tables sat among the per-race analyses. The families were always there; nothing had ever named them. They are now bands you can fold open and shut: **Race Analysis** - This race - Body & pace - Over time - Where you stand - How you respond - Body & volume - Workout History is back at the very top - The race ribbon moved to Race Analysis - The ribbon, pace progression and fitness can now be minimised too **Build 145** · 19 August 2026 · · · A simulation now counts in full towards the cardio curve "Yesterday I had a heart rate of 165 for 30 minutes in a simulation and cardio didn't move. This morning I jogged easy for 70 minutes and the curve goes up." The suspicion is right, and the backup shows it to the second. The Deadly Dozen half simulation on 18 Aug is 11.5 minutes of running at 132–168 bpm **and** 12.4 minutes of stations at 152–174. Only the running reached the cardio load: **27 TRIMP instead of 59**. The session lost 55 % of its load, and what it lost was the harder half. The cause is a half-finished conversion. The path that computes TODAY already counts stations, with a comment describing this exact bug. The path that rebuilds the HISTORY in bulk was never converted — and that is the path the curve is drawn from. Both now go through the same `stationTrimp`. No special case for strength was needed: TRIMP weights heart rate exponentially. A bench press at 110 bpm costs about 0.6 per minute; a devil press at 169 costs 2.6. The formula has always distinguished them — it was simply never asked. **Honestly:** even computed correctly, the easy jog remains the bigger cardio stimulus — 98 TRIMP against 59. TRIMP is duration times intensity, and 76 minutes is three times 24. The difference is that 59 is visible in the curve and 27 is not. Because the history is rebuilt, every past day containing station work shifts upward. · · · Auto-pause: you decide when It was a fixed twelve seconds. There is now a slider from 5 to 45 seconds under Training ▸ Running, with a line beneath it saying what the chosen number means. The value travels to the watch like every other setting. The step threshold scales with it: three steps in twelve seconds is really a RATE of a quarter step per second. Left fixed, a six-second window would have been far stricter and a thirty-second window far looser — the same setting would have meant two different rules at its two ends. The history buffer scales too: a fixed 20 s would have trimmed away exactly the baseline a 30-second window needs, and it would then have answered every question with "no steps". Closed at 5 seconds at the bottom: any shorter and the window cannot outlast the few seconds of thin detection when you raise your wrist to read the watch — the very first version's bug. · · · The heart-rate warning was stuck to the bottom edge of the screen "Why is the BPM warning not really integrated but a fixed banner at the bottom edge?" — because a brace was in the wrong place. Moving the section from the Racing page to the Heart Rate page closed the `Form` too early, so the section sat BESIDE the list rather than inside it. Two views side by side get stacked: the list fills the space and the section is pushed to the bottom edge. The page title hung off the section too. It is where it belongs now. **Build 145** · 19 August 2026 · · · Archiving locally instead of on the Cloud: the build number now lives in the project Xcode Cloud was assigning the build number itself; the project still said `1` everywhere. A local archive would have gone up as 1.1.6 (1) and been rejected, because 1 is not higher than 144. It is now **145**, on all four shipping targets in Debug and Release — if the app, the watch app and the two widget extensions disagree on the build number, App Store Connect rejects the upload as well. The eight test targets stay at 1; they never reach the archive. · · · Pace adaptation: an accepted suggestion made a fast target slower The detector was always careful — cardiac efficiency rather than raw pace, a real baseline of older sessions, at least five qualifying runs, a 10 % ceiling on the reading, half of it applied, clamped to the athlete's best-ever pace. The APPLY was not. It wrote ONE value into EVERY future block of that type. But one intensity routinely holds several targets: 4×1000 m at 5:10/km and 10×400 m at 4:45/km are both `vo2max`. The anchor was simply whichever block the plan listed first, so the faster one was rewritten to the slower one's improved pace: `@4:45` came out as 5:01, under a banner announcing an improvement. What is applied now is a **factor**, not an absolute pace. Every block scales from its own target, is clamped to best-ever individually, and can never come out slower. A twelve-week plan's deliberate progression survives instead of being flattened to one number. Three more holes closed in the same pass: - The ratchet - No time window - Mean, not median **Build 39** · 18 August 2026 · · · The race ribbon — races, simulations and training in one view Every recording of the same race shape is one bar, segmented in the order you actually ran it. All bars share one scale and one left edge, and the width IS the finish time — the fastest bar is visibly the shortest, and a segment that grew is a segment you can see grow. Tap one and it names itself and gives the time. The last bar is not a recording. It is **what your training says**: every station at the time it actually takes you in training, every run at your own race pace. "Does my training cover my race" finally has an answer in units where the question means something. Three rules, so that a comparison is one: - Same race shape only - The training bar is built from the newest recording - Races do not count as training - One point per session - The line is a rolling median over three sessions - Splits under 400 m no longer count, and neither does a race pace slower than 7:00/km. Zone 2 is allowed up to 9:00/km — tired legs are still an easy run. - Each series keeps its own colour. They used to be assigned by order, so a month without race-pace running swapped them silently. - The figure below is the trend value, not the last session — otherwise the number contradicts the line above it. · · · The written run analysis is withdrawn for now A German headline over English body text, and above it a generated verdict about a single run — the one card here that asserts rather than measures. It is hidden until the wording is trustworthy in both languages. · · · The duplicated weeks now actually go away Today's fix only stops NEW duplicates from being written. The existing ones were already on disk — and the next import would have archived the plan together with its duplicate rows and prepended all three again. The bug was propagating itself. Rows covering the same calendar week are now merged DAY BY DAY on load. Per date, the version that was performed wins; a day only one row knows about is carried over. Nothing performed is lost, nothing planned is lost, and the week stays trainable instead of being locked as history. · · · Four things off your list - A partial simulation's preview now shows what was actually planned - The breath coach is a beta and has to be switched on deliberately - A run is planned as time AND distance, and the pace falls out of the two - The Watch's HR warning - One tap on BACK rewound two sets - Checking off set 2 threw away the still-queued set 1 - A late set completion dragged the athlete back into a finished exercise - "Send to Watch" stayed hidden - A rest that simply ran out was never banked - The height profile and the climb belonged to the previous session - The hold screen read the whole workout history ten times a second - The BACK button after a transition did nothing - The predicted finish counted runs that do not exist - `/uploads` has never heard of `sport_type` - A `<Track>` with no points in it is not valid TCX - 201 means "accepted", not "it worked" - "Max HR" was the largest block AVERAGE - `RunStyle` existed twice, identical apart from whitespace. The "Alternative training" sheet still carried the whole run generator of the deleted Custom mode; nothing called `buildSession` any more. - A remote command's dispatch was written out twice — which is exactly why the dedupe guarded only one of the two channels. · · · Addendum: three race findings, adversarially confirmed The four findings I had left as "already fixed according to the architecture map" were checked again against today's code — one investigator and two skeptics each. Three were real. - The Watch started runs the variant does not have - In-race stations were counted and named against the full format list - The format pill took its name from the picker and its shape from the manager - Every snapshot now carries a revision - The HR warning is editable on the Watch again - The division travels both ways - The HR warning sits where you look for it - On HYROX nothing from the HR settings ever arrived - The HR warning saves as you change it - `Rounds 4` - Every block knows which round it is in - Prompt, grammar and example all know the token - `<n>cal` and `<n>s` / `<n>min` - A number with no unit follows the station - The measure comes from the registry now **Build 38** · 17 August 2026 · · · The AI plan import, actually run end to end once The prompt had been read, never answered. This time the whole chain ran for real — two target races, saved workouts AND planned simulations in one pass, prompt emitted, answered as the model, the answer fed through the importer. The first run came back with one warning per session. None of them was a real fault. - A title is allowed to be just a title - A sentence before the plan costs a warning, not the plan - "Each token exactly once" - Recovery belongs BETWEEN the repeats - The "STATIONS list above" - The grammar called itself "all valid tokens" and omitted three mandatory ones - The worked example is built for YOU - Two sessions on one day - Week numbers - Kilograms stay kilograms - Days until the race - A reference to a figure the prompt does not contain - Station times with their volume - No training history, no load block - Readiness 70 from zero signals - Race history - Simulations know their shape - The review prompt counted the PREVIOUS plan's weeks - "Replace weeks only" duplicated your history - The import button outlived its own parse - "Modify specific days" wrote on the validate tap - "Phase by phase" plus "specific days" was a dead end - "Plan looks good!" in green - Six warnings were English literals - The "sessions shorter than ordered" check - The equipment match - Cable machine - Found alongside - The three cards in "Why no built-in AI?" - A loaded simulation does not start as a "race" - A "Copy findings" button - Single lines - The reference tokens existed in the DSL alone - JSON now knows the references too - The examples in the prompt - The title - The "Compact format" switch is gone - JSON stays where it earns its keep - `activateImportedPlan` silently shifted the whole plan - The "Custom Start Date" field - `mergeWeeks` passed `startDate: nil` - The prompt - It is asked in the configure step - Defaulted to your next training day from today - The prompt says it out loud - The same date everywhere - The silent shift no longer fires - A discarded run took its GPS track into the next workout - A phantom workout after a HealthKit failure - "Save to Health" had no duplicate guard - The manual pause was never reset - Archived plans decoded all-or-nothing - Deleted sample races returned on the next launch - The "30 days" weight comparison - Plan compliance - GPS elevation gain - A backup merged race entries by the wrong id - iCloud receipt wrote around the store's own save - The activity detail forced **en_US** and baked "Today"/"Yesterday" in as literals — on a German device. - AVG PACE - Confetti and the success haptic **Build 37** · 16 August 2026 · · · A segment you did not do is not a result - "Bear Crawl nicht mehr gemacht, aber ist noch mit rein gekommen." - The flag existed already - All three totals counted skipped segments - The timestamps stay - The day knew, the week did not - A funnel now answers the question from both sources - Only a real race colours a week - And a simulation placed on several days finds its own day again - A switch on the "Your Library" card - `SimRef` is the second channel - An unknown id now says so - The saved-simulation filter existed in four hand-copied versions, two of them missing `!isSampleRace`. Now `RaceStore.simulationTemplates`. · · · The card decks now fit the card you are looking at - An HStack centres - The container now measures every page and takes the height of the one on screen - One carousel for both places - Six switches moved - The Watch keeps what belongs on the start line - The haptics switch really does apply to both devices now - Every settings save zeroed the Watch's target pace - Auto-station detection would have armed itself on the iPhone - The pace alert for training runs would have inherited the race target pace - The max-HR field on the Watch accepted input and discarded it - "Off" was drawn in the brand colour on three rows - Every readout on the Watch now says where it is set - "You have no idea what you are supposed to do." - Everything on the iPhone, including what happens on the Watch - What you read once no longer stands in the way - Expanded the first time, and the safety rule is card one - What stays on the screen is what is still useful after the tenth read - The breath coach is now also in Settings under "Apple Watch", beside the run display. One screen, two entrances. · · · One transition time, two totals - The simulation editor's summary hung its transition row on whether the format has a transition zone. For Deadly Dozen the answer is no — so it listed journeys and labours, called their sum the training duration and showed **53:37**, while the overview reported **1:06:37** for the same plan: thirteen minutes of walking, quietly counted three files away. The row now hangs on the TIME. · · · The breath coach can be planned with the simulation - Until now it existed only on the wrist, seconds before the start. It is now in the simulation planner — and **only there**, never in race planning. Two locks, because this is the one place it must stay quiet: the field is written only for a plan marked as training, and a race refuses to tick regardless. · · · Version 1.1.6 (Build 36) — 13 August 2026 · · · An automatic pause can now end automatically - The threshold was never the problem - The real cause was an echo - A detector one second old reports a standstill - And a report that was declined left the detector latched - The recovery jog is watched now - Why no test caught it - The height profile now belongs to the run, not the block - Headline ascent, descent and the curve are session-scoped now - Exactly one figure stays with the block: M/KM - Measured against 1.1.4 - Four highlights rather than three - Fifteen notes - `APP_STORE_1.1.5.md` - You had planned five rounds, and the editor said so nowhere - Now there is a frame around it with "5 rounds" over the top - Where the frame appears - Interval runs too - An edit in the round you see applies to all of them - While you tick sets, the rounds stay apart - Cards kept appearing without you saving anything - The reason was not an oversight but a double duty - Now there are two - On the Watch nothing changes - The cards already in there do not disappear by themselves — you can safely delete them, and no new ones will follow. · · · A deleted simulation now really disappears - Deleting was not the inverse of saving - It now distinguishes whose session it is - A mis-tap no longer becomes a session at all - The iPhone had no discard - A session labelled "0 min" showed a curve spanning 75 minutes - First: the card did not reload on switching - Second: the time window was borrowed - A match is now a proposal, not an answer - The tiles above it - On every session, across the whole app - The cause is a half-finished change - It now counts the gap to the next reading - Both counting sites now go through the same function, including the one feeding the AI prompt. A test asserts that credited time **can never exceed the span the readings cover** — precisely the one assertion that would have prevented this from the start. · · · Stations show their picture - The pictures were on disk all along - 22 mappings for Deadly Dozen, HYROX and DEKA - Rounds were capped at 5 - Rest between sets could not be set to 0 - The live preview read `dd_kb_goblet_squat`
improvedAugust 12, 2026

Version 1.1.5

**Build 34** · 12 August 2026 The settings screen is tidy - Seventeen sections sat on one single list - Now six doors instead of seventeen rooms - Reminders now sit with the thing they remind you about - The Watch run display moved from "Race Controls" to "Training & Runs" - Not a single switch changed behaviour; every section moved verbatim. · · · The Watch stops at the traffic light — and sets off again with you - If you stop during a run, the Watch now stops the clock by itself - Measured from steps, not from GPS - Five seconds without a step counts as standing - A pause you pressed yourself never resumes on its own - An automatic pause never swallows a button press - Switchable - Applies to run blocks in a workout only - If you were listening to music on the iPhone, the coaching still came out of the Watch - The Watch's only route to those headphones would be to take them - So the device that owns the headphones now speaks - It works with any headphones on the iPhone - Every doubt falls back to the Watch - No, this is not reserved for Apple - Found along the way and fixed in the same pass - The pause forgot which card you were on - The reason sits one level deeper - The horizontal page comes back too - The curve could never fall - The card now draws the elevation relative to the block start, with a sign - The scale spans the run's valley and peak instead of starting at zero, with a fine line at starting elevation as soon as you drop below it. A window under 10 m is not drawn any narrower — otherwise forty centimetres of air-pressure fluctuation on flat ground fill the whole card. - Without a barometer no profile is drawn at all - "Ø GRADE" was "M/KM" divided by ten - "DESCENT" had no German translation - Found along the way and fixed in the same pass - The progress glow stayed dark the whole way through a 10 km Zone 2 block - A block in progress now moves the ring with it - Simulations still landed on Strava as "Run" - The type now comes from a single place, across four callers: **pure run → Run, pure strength training → Weight Training, runs and stations mixed → HIIT.** The upload path speaks the older vocabulary (`Workout`), which is the only one it understands. - Pause a run and the info pages were gone - The run screen now stays put during a pause - Found along the way and fixed in the same pass **Build 33** · 11 August 2026 "My Workouts" and "My Simulations" are the same size - The left card was one line of text taller than the right one - The space for the second line is now **reserved**, not merely allowed. That puts the two count lines at the same height as well, and it holds at larger type sizes — which a fixed height would not. **Build 32** · 11 August 2026 Both widget extensions now have a privacy manifest - App and Watch app had one, the two widget extensions did not - Deliberately shorter than the app's - Verified in the built bundle, not assumed: both `.appex` carry the file, on iOS and watchOS. **Build 31** · 11 August 2026 "Target pace 12:17–13:20 /km" above a plan that says 5:00/km - The target pace was too slow by a factor of 2.5 - The same calculation sat in the Watch's live target pace - And twice a pace was compared against a lap time - On HYROX the lap is exactly one kilometre **Build 30** · 11 August 2026 The last labels: the Watch calls the race by its name - A loaded DEKA STRONG introduced itself as "DEKA FIT · 10× 0m" - The iPhone tracker announced "RUN 2" after every zone - The text export listed ten run lines for a run-less race **Build 29** · 11 August 2026 Logged past races now have stations too - Four Analyse cards stayed empty for every logged past race - The rule for de-duplicating a migrated race was written out by hand twice in the source **Build 28** · 11 August 2026 The rest of the variant axis: pace, preview, rest, leaderboard - The pace of a DEKA MILE was off by two thirds - A planned STRONG showed ten runs on the Watch - A zones-only race never got the planned rest - The leaderboard separated the variants and then measured them by the format's yardstick anyway - The ghost comparison and the target-time back-calculation **Build 27** · 11 August 2026 No more award for a shape that has no ladder - A DEKA STRONG took Elite, the Clean Sheet and the record all at once - The format's personal best fell for it too - The legacy bridge was gender-blind in a single line - Strava uploaded a run-less race as a 5 km activity - The planner showed "500 m" for a DEKA MILE **Build 26** · 11 August 2026 Addendum to the DEKA pass: one self-inflicted bug, and three dead ends - I had taken the division away from Deadly Dozen and ATHX - After a format switch no chip was marked - The plan field for the DEKA variant was dead code - A DEKA race started by hand on the Watch was always FIT - DEKA ULTRA is no longer selectable **Build 25** · 11 August 2026 DEKA now has a variant axis — and Deadly Dozen inherits a fix along with it - DEKA STRONG could not be run - The plan did not carry the variant at all - A race is only comparable with its own shape - DEKA teams had no gender - Every division is measured against the ladder of its own gender **Build 24** · 11 August 2026 DEKA run-through: half of what turned up applies to HYROX and Deadly Dozen too - The division picker on the Watch was free text - A shared store for all formats - "Plan vs Actual" always showed the run card empty — in German - The race shape knew only Deadly Dozen's variants - The station benchmark card counted roxzones as stations - Three cards resolved the division themselves - On the detail page, in the history and on the shared card, the raw id was shown **Build 23** · 11 August 2026 A half simulation no longer sets targets for a whole race - The damage was not in the suggestion, it was in accepting it - Now your order applies - And no longer linearly - Every row now names the volume its time comes from - A full target race was pre-ticked under half numbers - On ATHX the card offered to overwrite the organiser-fixed zone durations - A Deadly Mile was graded against all twelve labours - A second way around the funnel is closed **Build 22** · 11 August 2026 DEKA: one hour was labelled "World Class" - The ladder contradicted itself - And reality says the same - The zone targets were the realistic part - The marks are derived from the tiers, not written down beside them - Deadly Dozen is deliberately untouched **Build 21** · 11 August 2026 A race's stations now count towards the heart as well - A station's heart rate was recorded and cost nothing - Why nobody noticed - It is counted with the same guard as the runs - The curve is recomputed once **Build 20** · 11 August 2026 What a weight means is now written where you enter it - The app knew two meanings for one kilo figure and used the same word for both - Only the exception gets a label - A blanket "Total weight" would have been wrong twice over - The Watch and the iPhone contradicted each other on race day - The dialog that changes a station weight asked for "Weight (kg)" - Once, in the right place - Adjacent finding, fixed along the way **Build 19** · 11 August 2026 DEKA: the women were training with the 65+ weights - The official chart has four columns, and the second one is called "Female 14+ / Male 65+" - Looked up in the rulebook itself - Zones 2, 5 and 7 now know the youth values - The head of the file claimed weights that appear nowhere in the rulebook - Not yet covered and deliberately named **Build 18** · 11 August 2026 A strength exercise now counts with all its sets — and a simulation only once - Four sets were booked as one - The sets of previous sessions are backfilled - The same simulation stood twice in the day - Days already stored twice - "2 × 10 kg" instead of "10 kg" **Build 17** · 11 August 2026 A planned simulation opens the race flow — and the button says what it starts - The Watch had to guess which simulation was meant - A simulation now always opens the race flow - The START button says what it opens - Today tab: two buttons for the same thing, with an unrelated card between them **Build 16** · 10 August 2026 The result view now tells you what you actually did - "~37 min" after a workout that took 1:16 - Why the estimate is so far off is further down in my answer: it counts three seconds per rep, 90 seconds of rest between sets and **twenty** seconds between two exercises. So rests are counted — only the planned ones, not the real ones. - The exercise list shows sets and reps - Intensity curve: the exercise names were grey on red **Build 15** · 10 August 2026 Deletion pass: 1,290 lines, every one of them checked against its callers - Dead views (690 lines) - Dead manager APIs (84 lines) - Half of the "Quick Start" chain (15 lines) - The iOS dashboard widget inside the watchOS widget file (459 lines) - Left alone, because they are features and not corpses **Build 14** · 10 August 2026 Station training is real training now - It was the app's only training mode without a Health session - Heart rate comes from the live builder of a **running** `HKWorkoutSession`. Station training started none — so there was no value to subscribe to at all: no readings, no average in the result. - And the HR pill on the run screen read `trainer.currentHeartRate`, a property **nobody in the whole project ever wrote to**. It was always nil, the pill never appeared. - A station attempt now opens a real session - Only its own session is ended - Pause and resume are now passed through to the session, so the Health entry does not count a breather as work. **Build 13** · 10 August 2026 Elevation: a block value and a session value are two different numbers - The ascent card divided the whole session's ascent by the distance of a single block - On closer inspection the actual bug was a different one, and worse - On a Watch **with** a barometer the next measurement wrote the cumulative figure straight back. So the zeroing had no effect — and that is why it was never noticed. - On hardware **without** a barometer that very write-back is guarded and never fires. There the zeroing held, and the saved workout kept only the last block's ascent. **The same line, the opposite bug, depending on the wrist.** - Both quantities now exist side by side: `elevationGainMeters` stays the session, `blockElevationGainMeters` is derived from a baseline taken at the block change. The card takes the block value, because it divides it by the block distance. Three tests, one of them exactly the case I first fixed the wrong way round. **Build 12** · 10 August 2026 The units setting finally reaches the pace · A backfill could overwrite recordings - Anyone switching to imperial has so far turned kilograms into pounds and then gone on reading kilometre paces everywhere - Nothing changes for metric - The export and the text sent to the language model stay **deliberately** metric: there a fixed unit is worth more than the athlete's preference. The reasoning is written down in the code. - The HealthKit backfill could overwrite other recordings - And this afternoon's invariant confirmed once more: `Models.swift` is compiled on its own in the widget target, so `WeightFormatter` had to travel with it. The error duly appeared as "cannot find WeightFormatter in scope" — in the middle of `Models.swift`, on a perfectly ordinary build. **Build 11** · 10 August 2026 Four confirmed findings: two headers over gaps, an unreachable trophy, a calorie value - "Pacing Advisor" could stand over a gap - "HR Recovery" inevitably stood over a gap on ATHX - The trophy in station training could never appear - When editing a set afterwards, calories and level stayed put **Build 10** · 10 August 2026 Alternative training: "Quick" out, saved simulations in - Your saved simulations were not reachable from here - "Quick" gave way for it - Templates only, not recordings - The session that gets inserted stays linked to the simulation **Build 9** · 10 August 2026 - "Start on Apple Watch" now reads "Start again" for a session that has been completed **Build 8** · 10 August 2026 Three patterns instead of three individual cases The cross-check delivered not just findings but **repetitions**. A mistake that shows up three times is not threefold carelessness, it is a missing rule. All three are now in `CLAUDE.md`. - A funnel exists so that nothing goes around it - The workout history was the sixth bypass - Explicitly **not** a bypass: `RaceHistoryView` shows the demo races on purpose, with its own banner and delete button. Checked instead of assumed. - When you replace something, delete the half you replaced - A block value and a session value are not the same number - On the side: the last raw `print()` in the release build now goes through `Log.d` — the second one had disappeared with the old decoder anyway. **Build 7** · 10 August 2026 56 open findings cross-checked — 38 held up, 18 did not. Ten of those fixed. **The cross-check itself.** Every finding got a reviewer whose job was to **disprove** it: does the code really say that? Is the path reachable? Is it deliberate — this repo justifies its intentions in comments? And: was it already fixed today? 18 of 56 did not survive that. They stay in `BACKLOG_1.1.5.md` with the reasoning, so nobody reports them again. **Two buttons that discarded work now ask** - START on the Watch's workout page overwrote a session in progress - STOP in station training threw away the attempt just run - The kilometre split was the average since the block began - Calories were a flat 9 kcal per minute of total duration - The run card said "/mi" over a number in seconds per kilometre - The Weekly Digest counted the demo races as your history - The HealthKit permission texts came from the project file instead of the maintained `Info.plist` - A self-confirmed deload was shown as "Auto-deload active" - The distance in the generator preview read a UserDefaults key that nobody writes **Build 6** · 10 August 2026 The total time is now on the rest screens too - The set rest and the EMOM rest were missing the session's total time **Build 5** · 10 August 2026 The personal-best notification now says which day it came from - Fix: "New personal best: Bear Crawl" on a day without any bear crawls - A finding now carries the **date of the performance** it celebrates, separate from the moment of detection. The notification puts it first, **except** when the performance really was from today — then the date would be nothing but noise. - The pace part has no single date it could point to. It stays silent about it rather than guessing. - The new field decodes backwards-compatibly: a finding written before the field existed stays readable. Otherwise every stored record would have become unreadable — the rule for that has been in `CLAUDE.md` for a while. - And the detector now reads through `analysisRaces` - Six tests, among them the backwards compatibility and the "performance was today" case (no date line). **Build 4** · 10 August 2026 Three ways a session threw away work that was already done - Fix: after a crash the exercise ended at the next check mark - Fix: a skipped block lost its logged sets - Fix: the hold timer jumped to zero on every pause - Eight tests. The crash is genuinely re-enacted: one manager writes a checkpoint, a **second, fresh** manager restores from it — nothing survives except the file. - Two invariants in `CLAUDE.md`: state that `beginBlock` derives from the plan must be re-derived when restoring. And: anything that should survive a pause must not live in a watchOS view's `@State`. **Build 3** · 10 August 2026 The rest screen named the exercise that had just finished · The bezel no longer cuts through text - Fix: "Next" named the wrong exercise and the wrong set in a superset - The rest screen looked ahead to `plan.blocks[idx + 1]` and hard-coded the set to 1. But a superset runs by **alternating**, not in array order — the array neighbour is exactly the exercise you have just finished. And a superset partner the alternation comes back to already has sets behind it, so "set 1" is never right for it. - Your hunch about the third set is exactly right - The fix is a deletion - The glow bezel no longer cuts through text - So one of the two stops being opaque — the content: it **fades out before it reaches the line**. A little longer at the top, where the glow itself is strongest and the system clock sits. Fixed elements sit in the safe area and stay untouched; only what scrolls through the edge goes soft. One modifier for all screens (`grBezelSafe`), so it does not get reinvented per view. - The set timer shows digits only **Build 2** · 10 August 2026 Five stores did not survive a single corrupt record — and then wrote the loss to disk - The core - Workout library - PerformanceLog - Training day - Race segments - Station training history - `SurvivableDecoding` is the one answer to this - Nine tests - Learned along the way and written down in `CLAUDE.md` **Build 1** · 10 August 2026 1.1.4 is in review at Apple — from here on 1.1.5 is running - `MARKETING_VERSION` to 1.1.5 - No "What's New" for 1.1.5 until there is something to say - 30 German strings were marked as machine-translated - Left open: 259 entries carry `stale`. Some of them are marked wrongly, because the text sits inside a string interpolation and the extraction doesn't see it. Simply deleting them would therefore be a way to lose live strings — that needs a pass of its own.
improvedAugust 10, 2026

Version 1.1.4

**Build 10** · 10 August 2026 Die Muskel-Kurve zeigt endlich den einzelnen Tag · Drei stille Fehler im Belastungspfad - Deine Simulation von gestern *hat* gezählt — die Kurve konnte es nur nicht zeigen - Jetzt steht die Tagesarbeit als eigener Balken darunter - Und die Beschriftung log - Fix: Die einmalige Nachtragung konnte sich selbst abschalten, bevor sie etwas getan hatte - Fix: Nachträglich gefundene Herzfrequenz erreichte die Trainingsbelastung nicht - Die Neuberechnung sagt jetzt, wenn sie aufgibt **Build 9** · 10 August 2026 What's New misst jetzt gegen 1.1.3, nicht gegen den eigenen Beta-Verlauf - Fix: „Was ist neu" hat Fehler als behoben gefeiert, die es in 1.1.3 nie gab - Und deutlich kürzer - Dieselbe Korrektur in `APP_STORE_1.1.4.md` **Build 8** · 10 August 2026 Der Rahmen zählt Sätze und läuft nicht mehr zurück · Die Workout-Karte sagt endlich, was sie ist - Fix: Der Rahmen sprang zurück — bei Supersets - Gezählt wird jetzt **aufgezeichnete Arbeit**: erledigte Sätze gegen geplante, über den ganzen Plan. Abgeschlossene Blöcke und Satzergebnisse wachsen nur, also **kann** das Ergebnis nicht mehr fallen. Ein Block ohne Sätze — Lauf, Pause — wiegt eins und ist erledigt oder nicht; sein Fortschritt ist Distanz oder eine Uhr, kein Satz. - Die Rechnung liegt jetzt als reine Funktion vor und ist ohne laufende Sitzung prüfbar. Neun Tests, darunter der Superset-Rücksprung und die Übergabe zwischen laufendem und abgelegtem Satzspeicher, bei der genau einen Moment lang beide dieselben Sätze halten. - Fix: Der Rahmen war in den Rundungen unterschiedlich dick - Der Rahmen: härtere Kante unten, mehr Leuchten oben - Die Workout-Karte sagt jetzt, was sie ist - Fix: Warum bei manchen HYROX stand — auch wenn es Deadly Dozen war **Build 7** · 10 August 2026 Ein Plan-Import konnte deine Trainingshistorie löschen · Der Glow zählt jetzt Sätze - Der Fortschritts-Glow auf der Uhr rückt jetzt mit jedem abgehakten Satz weiter - Fix: „Bestimmte Tage ändern" hat abgeschlossene Wochen überschrieben - Ein absolvierter Tag ist eine Aufzeichnung, kein Plan - Die Datumsauswahl beginnt jetzt bei heute - Und du erfährst es - Der Vollersetzungspfad direkt daneben hat seit jeher auf abgeschlossene Einheiten geprüft und gefragt. Der Merge-Pfad tat beides nicht, und für ihn gab es **keinen einzigen Test**. Jetzt vier. - Was nicht verloren war und es auch nie war: die Rohdaten. Trainingsverlauf, Workout-Ergebnisse und Health sind eigene Speicher. Zerstört wurde die Rechenschaft des Plans über sich selbst — und daraus speisen sich jede Abschlussquote, jede Serie und jede Wochenzusammenfassung. **Build 6** · 9 August 2026 Supersets überlebten den KI-Import nicht · Simulation startet als Simulation · Reps-Bereich · Der Generator schrieb deine Auswahl zurück - Fix: Der KI-Import hat jedes Superset verschluckt — und die KI war unschuldig - Die **Einrückung entscheidet**, wo eine Gruppe endet — das ist die Grammatik und nichts kann sie ersetzen. Schreibt ein Modell die Kopfzeile und lässt die Mitglieder linksbündig, wie es in der Praxis passiert, werden die **nächsten zwei** gepaart **und du bekommst eine Warnung**, statt dass geraten und geschwiegen wird. - Eine Kopfzeile mit nur einer Übung darunter ist kein Superset — die Markierung wird wieder entfernt, sonst behandelt die Uhr sie als Gruppe von eins. - Eine Leerzeile beendet eine Gruppe, so wie sie einen Absatz beendet. - Und der Prompt sagt es jetzt unmissverständlich - Fix: Eine geplante Simulation wird auf der Uhr als Simulation gestartet, nicht als Workout nachgebaut - Neu: Wiederholungen sind beim Freien Krafttraining wählbar - Fix: Der Smart Generator hat deine Auswahl überschrieben - Fix: Sätze und Runden ließen sich mit gesetzter Zieldauer nicht ändern - Fix: Der KI-Bildschirm bot immer „30 min" an - Dazu die Diagnose, die ich mir gespart hätte, wenn ich geraten hätte: Der Verdacht lag auf dem Handbearbeitungs-Modus. Der war es nachweislich nicht — `manualBlocks` hat genau einen Schreiber, den „Übernehmen"-Knopf im Editor, und der KI-Bildschirm hat keinerlei Verbindung dorthin. **Build 5** · 9 August 2026 Meine Workouts & Läufe · Watch-Feinschliff · Hinweise für die KI · Store-Texte - „Meine Workouts" heißt jetzt „Meine Workouts & Läufe" - Beide Bibliotheken öffnen mit einem Knopf, der sagt was er tut - Watch: der große FERTIG-Knopf ist vom Trab-Bildschirm verschwunden - Watch: „Lauf fertig" heißt jetzt „Weiter" und steht unten - Watch: der Fortschritts-Glow beginnt unten in der Mitte - KI-Import: ein Feld für das, was kein Auswahlmenü fassen kann - Fix: Der KI-Import zeigte beim zweiten Öffnen noch die erste Konfiguration - Fix: Der Konfigurationsblock im KI-Import waren in Wahrheit drei Blöcke - Projektkonfiguration, beides schon lange falsch und beides bisher unbemerkt - What's New erscheint noch einmal - Neu: `APP_STORE_1.1.4.md` **Build 4** · 9 August 2026 Der Schlüssel, den ich in Build 3 gesetzt habe, gibt es nicht - Fix: App Store Connect hat Build 3 abgelehnt — wegen meiner eigenen Zeile - Der Absturz bleibt behoben - Und die Deklaration wird auf der Uhr gar nicht gebraucht - Der Guard akzeptiert jetzt nur noch `UIBackgroundModes` - Der Test hielt die falsche Annahme fest **Build 3** · 9 August 2026 Der Watch-Absturz bei Intervallen · Eine behaltene Aufzeichnung zählt jetzt überall - Fix: Die Watch-App stürzte eine Sekunde nach dem Start jedes Outdoor-Workouts ab - Und die Uhr darf es jetzt wirklich - Fix: Die Trab-Pause bekam den Stationsbildschirm - Fix: Der Höhenmesser hat sich auf den Hauptthread verlassen, statt auf ihn zu wechseln - Fix: Eine abgebrochene Simulation wurde im Start-Sheet wieder als Vorlage angeboten - Fix: Der Strava-Upload lief für eine behaltene Teilaufzeichnung nie an - Fix: Eine abgebrochene Aufzeichnung verlor ihren geplanten Renneintrag und ihren Namen - Fix: Der gesamte Analyse-Tab war für eine abgebrochene Aufzeichnung gesperrt - Fix: Im Rennvergleich war eine abgebrochene Aufzeichnung sichtbar, aber nicht auswählbar - Fix: Der Plan buchte die geplante statt der tatsächlichen Dauer - Fix: Ein nicht beendetes echtes Rennen öffnete kein Erholungsfenster - Fix: Der KI-Datenexport ließ abgebrochene Einheiten weg - Fix: Demo-Rennen wurden neben eine echte Teilaufzeichnung gesetzt **Build 2** · 9 August 2026 Deine Punchlist, komplett · Rennen zählen endlich für die Trainingsbelastung · Höhenmeter vom Barometer · Strava bekommt die Karte - Fix: Eine Simulation hat die Trainingsbelastung nie bewegt — kein einziges Rennen hat das je getan - Deine bisherigen Rennen werden einmalig nachgetragen - Nebenbefund, im selben Zug behoben: der Trainingsverlauf warf alles älter als 90 Tage weg - Ehrlichkeit auf dem Heute-Tab - Fix: Die Herzfrequenz wird durchgehend gelesen, nicht in 10-Sekunden-Mittelwerten - Fix: Eine Simulation ist kein Rennen mehr - Fix: Eine verkürzte Simulation beschrieb sich mit der vollen Vorgabe - Fix: Eine abgebrochene, aber gespeicherte Aufzeichnung wird jetzt behandelt wie eine abgeschlossene - Neu: Workout und Rennen speichern jetzt dasselbe - Die Zonenzeiten des Rennens werden nachträglich aus Health gerechnet - Fix: Die Herzfrequenz der Satzpause wurde dem folgenden Block angerechnet - Fix: `averageHeartRate` bedeutete je nach Pfad etwas anderes - Neu: HF-Nachholung auch für Workouts - Fix: Der KI-Prompt eines Rennens beschrieb die volle Vorgabe - Fix: Die Composite-Karte nahm halbvolumige Stationszeiten als Bestwerte - Fix: CSV-Distanzspalte, Überschrift des Pace-Diagramms und der „Lap Distance"-Stepper - Fix: Ein am iPhone getrackter Lauf hatte gar keine Herzfrequenz — und niemand holte sie nach - Neu: Deadly Sprint als DD-Variante - Neu: Der Abstieg wird gemessen, angezeigt und gespeichert - Fix: Halbes Volumen wurde an weiteren Stellen als volle Vorgabe ausgegeben - Fix: Die Durchschnitts-Pace wurde aus der offiziellen statt der gelaufenen Distanz gerechnet - Fix: Ein Stations-Rekord konnte nie ausgelöst werden - Neu: Die Stufe wird angezeigt und in neue Pläne übernommen - Fix: Die Renn-Erinnerung wird jetzt zentral gesetzt - Fix: Ein iPhone-getracktes Rennen hatte gar keine Herzfrequenz - Fix: „Simulation planen" auf dem Trainings-Tab tat gar nichts - Fix: Die konfigurierte Simulation verlor Titel und Portion - Ehrlicher: Die Last-Kachel auf „Heutige Aktivität" heißt jetzt „ca." - Watch: Der Glow liegt jetzt auf jedem Trainingsbildschirm — und die letzten zwei alten Fortschrittsbalken sind weg - Fix: Die letzte Wiederholungs- und Kilogramm-Zahl hinter der Übung war eine andere als die letzte - Fix: Höhenmeter beim Laufen kamen vom Treppenzähler - Fix: Der Lauf kam bei Strava ohne Karte an, mit zu wenigen Herzfrequenz-Punkten - Fix: Intervalle mit Trab-Pause - Fix: Der letzte Satz am iPhone hat die Uhr nicht weitergeschaltet - Geprüft und in Ordnung: Pausenzeiten gehen sehr wohl an die Uhr - Neu: Einen abgehakten Satz wieder öffnen - Fix: Das Alter wurde nicht gespeichert - Fix: Eine aus der Session-Ansicht gestartete Simulation hat das verknüpfte Rennen überschrieben - Fix: Die Renn-Erinnerung nannte das falsche Datum und eine Division, die gar nicht hinterlegt war - Neu: Eine gelaufene Simulation bleibt als Vorlage erhalten - KI-Pläne planen jetzt richtige Simulationen - Watch: Der Fortschrittsbalken ist weg — der Fortschritt liegt jetzt als dezenter Glow auf dem Rand - Fix: Die Aufzeichnungsprüfung hat deine Sprint-Simulation am vollen Feld gemessen **Build 1** · 6 August 2026 Die Rennvorhersage kannte deine Simulationen nicht · 39 englische Texte - Fix: Die Rennvorhersage hat die Stationen weggelassen und trotzdem eine Zielzeit ausgegeben - Fix: „Ein Rennen abschließen, um Benchmarks zu sehen" — neben acht abgeschlossenen Einheiten - Und wenn wirklich nichts da ist, sagt die Karte, was fehlt - Fix: 39 englische Texte quer durch die App **Build 1** · 29 June 2026 Watch Übungs-Detailansicht: Überlappungen oben & unten behoben - Zurück-Button überlappte den Übungstitel und die Navigationsleiste war überladen (Progress + Zähler + Timer + Herzfrequenz brachen neben die Systemuhr um). Die `.topBarTrailing`-Toolbar zeigt jetzt nur noch Progress-Balken + „x/y"-Zähler. - Timer und Herzfrequenz in eine kompakte Stat-Zeile direkt unter dem Übungsnamen verschoben (statt in die Navigationsleiste). - Titelzeile bekommt einen Top-Inset, damit der Übungsname garantiert frei vom Back-Button steht. - Notizen kollidierten mit dem Pause-Button: Ursache war `.frame(height: screenGeo.size.height)` — bei Supersatz-Badge/zusätzlichem Inhalt lief der Inhalt über und überlappte die Notizen. Jetzt `.frame(minHeight:)`, sodass höherer Inhalt scrollt statt zu überlappen. Watch ↔ iPhone Live-Workout: Sync- & Navigationsfehler behoben - Übung in der Watch-Übersicht antippen brach das ganze Training ab: In `WatchExerciseDetailView` ist die Übersicht eine TabView-Seite — `returnToWorkout()` rief `dismiss()` auf und verließ damit die komplette Workout-Ansicht. Jetzt wird per `onReturn` zurück zur Übungsseite gewechselt (`pageIndex = 0`). - Abgeschlossene Übungen in der Watch-Übersicht waren nicht mehr antippbar. Tap-Handler erlaubt jetzt das Antippen jedes Blocks (außer dem aktuellen) — abgeschlossene Blöcke werden über `jumpToBlock` wieder geöffnet (`completedBlockIds`/`superSetProgress`/`allBlockSetResults` für den Ziel-Block zurückgesetzt), sodass sie erneut bearbeitet/wiederholt werden können. - Satz auf dem iPhone für eine andere Übung abgehakt landete fälschlich beim aktuell auf der Uhr offenen Block (z. B. „pull down" abgehakt → erster Satz von „Nordic curl" abgehakt): `RemoteWorkoutCommand.setCompletion` enthält jetzt die `blockId`. `handleRemoteSetCompletion` springt auf der Uhr zuerst zur Ziel-Übung (`jumpToBlock`) und wendet den Satz dort an. Dedup-Hash nutzt jetzt `blockId` statt `currentBlockIndex`. - Auto-Ende des Trainings trotz übersprungener/übersprungener Übungen: Neue Hilfsfunktion `nextIncompleteBlockIndex(after:)` sucht den nächsten unfertigen Übungs-/Stations-/Lauf-Block (vorwärts, dann zurück zu früher übersprungenen/„vorbeigesprungenen" Blöcken). `finishBlock` und `skipBlock` beenden das Training automatisch erst, wenn wirklich alle Übungen abgeschlossen sind. Watch Workout-Ansicht: Progress Bar + Tile-Größen - Progress bar (Segmente/Balken), Block-Counter, Laufzeit und Herzfrequenz aus dem Scroll-Content entfernt und als Toolbar-Item (`.topBarTrailing`) in die Navigationsleiste verlegt — direkt neben dem Zurück-Button - Durch den frei gewordenen Platz: Tiles füllen mehr Höhe, Pause-Button und Notizen werden nicht mehr gequetscht - Haupt-Zahlen in KG-, Reps-, Distance- und Duration-Tiles: 20 pt → 22 pt - Stepper-Buttons (–/+) in allen Tiles: 24×16 → 26×18 pt, Icon-Schrift 10 → 11 pt Trainingsplan: Doppelte Übungen & lange Pausen behoben - ExerciseLibraryView: Custom-Übungen mit gleichem Namen wie eingebaute Übungen werden jetzt dedupliziert — kein doppelter Eintrag (mit und ohne Bild) mehr in der Übungsbibliothek - TrainingPlanManager `buildStrengthSession`: Extra-Pause nach Alternativ-Blöcken (`alternativeBlocks`) entfernt — Alt-Blöcke sind selbst getimete Übungssegmente und brauchen keine zusätzliche Ruhezeit - Überhang-Pause am Ende des Kraftübungs-Abschnitts wird jetzt vor dem Stations-Abschnitt entfernt, um keine konsekutiven Pausen durch den Übergang zu erzeugen - `mergeConsecutivePauses`: Zusammengefasste Pausen werden auf maximal 120 s (2:00) begrenzt — verhindert extreme Pausen (z. B. 4:30, 5:00) durch aufaddierte Alt-Block-Pausen - `buildAccessorySession`: Fallback-Pause bei fehlendem Equipment von 1200 s (20 min) auf 120 s korrigiert Watch Workout-Ansicht: Layout-Überarbeitung - KG/Reps/Distance/Time-Tiles kleiner (Hauptzahl 20 pt statt 24 pt, Stepper-Buttons 24×16 statt 26×18) - Done-Button (✓) und Pfeil-Buttons (<, >) schmaler (Höhe 28 pt statt 36 pt) - Notizen aus dem Inhaltsbereich entfernt und unterhalb des Pause-Buttons platziert (nur durch Scrollen sichtbar, voller Text ohne Kürzung) - ScrollView-Wrapper: Hauptinhalt füllt genau den sichtbaren Bildschirmbereich (GeometryReader), Notizen liegen initial unterhalb des sichtbaren Bereichs - Fortschrittsbalken-GeometryReader-Variable umbenannt (barGeo) um Konflikt mit äußerem GeometryReader zu vermeiden
improvedAugust 6, 2026

Version 1.1.3

**Build 27** · 6 August 2026 Die Laufanalyse hat den Prompt statt der Antwort gezeigt · „Dein letzter Lauf" konnte nie erscheinen - Fix: In der Laufanalyse stand unser eigener Prompt - Fix: „Dein letzter Lauf" konnte gar nicht erscheinen — drei Fehler übereinander - Fix: Überschriften ohne Inhalt - Fix: Fünf englische Platzhalter **Build 26** · 6 August 2026 Der Analyse-Tab, Karte für Karte gegen echte Daten geprüft · Stufennamen sagten die falsche Zeit · DEKA und ATHX kannten ihre Divisionen nicht - Fix: DEKA und ATHX haben die Kategoriewahl ignoriert - Fix: Der Name einer Leistungsstufe hat über die eigene Grenze gelogen - Fix: 48 englische Texte im Analyse-Tab - Fix: Deutsche Zahlen - Fix: Überschriften ohne Inhalt - Der Stufentitel bricht nicht mehr mitten im Wort **Build 25** · 6 August 2026 Die Analyse-Karte war unsichtbar · Feldverteilung: Laufen und Stationen ordneten Halbes gegen Ganzes ein - Die Karte „Dein letzter Lauf" hast du nirgends gefunden, weil sie nirgends war - Fix: Feldverteilung, Reiter Laufen und Stationen - Und wenn eine Zeit schneller ist als die schnellste je erfasste, wird sie nicht mehr eingeordnet - Kalorien: keine erfundenen mehr **Build 24** · 6 August 2026 Strava bekommt endlich die ganze Einheit - Fix: Die gelaufene Distanz kam nie im Ergebnis an - Fix: Zwei Stunden zu früh - Neu: Bleibt HealthKit stumm, baut die App die Datei selbst - Die Beschreibung trägt jetzt alles, was die Aktivitätsfelder nicht können **Build 22** · 6 August 2026 Der Generator hört wieder zu · Übungsbilder überall · Einmaliger Hinweis zu den Lauf-Ansichten - Fix: „Ich will Planks" ergab drei Übungen, die keine Planks waren - Das erklärt auch den zweiten Teil - Übungsbilder erscheinen jetzt auch im Smart Generator - Neu: einmaliger Hinweis zu den Lauf-Ansichten **Build 21** · 6 August 2026 Die Analyse sagt jetzt, was die Zahlen bedeuten - Neu im Analyse-Tab: „Dein letzter Lauf" - Warum das überhaupt geht - Was sie liest - Nichts davon schreibt eine KI - Sie schweigt lieber, als etwas zu behaupten - Fix: Die Zonenzeiten wurden nie gespeichert - Fix nebenbei **Build 20** · 6 August 2026 Die Zonen rechnen jetzt wie Apple - Die Herzfrequenz-Zonen folgen ab sofort der Herzfrequenz-Reserve - Das alte Modell bleibt wählbar - Die Umstellung greift überall gleichzeitig - Deine gespeicherten Werte überstehen das Update **Build 19** · 6 August 2026 Höhenmeter mit Live-Verlauf · Deine Pausen zählen wieder · Strava hängt nicht mehr fest - Höhenmeter sind drin — mit Verlaufskurve - Fix: Deine Pausen wurden verworfen - Fix: Strava hing über eine halbe Stunde - Fix: Die Werte auf den Lauf-Karten saßen versetzt - Fix: „ZURÜCKSETZEN" brach mitten im Wort - Fix: Das iPhone konnte die Watch-App nie starten - Neu: Die Einstellungen zeigen jede Lauf-Ansicht als Vorschau **Build 18** · 5 August 2026 Kurze Fehlstarts zählen nicht mehr mit · Die Kadenz-Karte ist befüllt - Aufzeichnungen unter zwei Minuten fließen in keine Statistik mehr ein - Gelöscht wird trotzdem nichts hinter deinem Rücken - Die Karte „Sechs Werte" ist jetzt befüllt und auswählbar - Die Höhen-Karte bleibt vorerst gesperrt, und zwar bewusst **Build 17** · 5 August 2026 Der Lauf-Bildschirm gehört den Zahlen · Vier Ansichten, die der Cloud-Compiler fast nicht mehr geschafft hätte - Der „Fertig"-Button ist vom Lauf-Bildschirm verschwunden - Damit sind die Zahlen deutlich größer geworden - Fix: Auf der Ziel-Karte stand „60:…" statt der Prognose - Unsichtbar, aber wichtig: **vier Ansichten waren dem Cloud-Compiler gefährlich nahe.** Die Rennhistorie brauchte allein **zwölf Sekunden** zum Typprüfen, dazu Wochenleiste (4,7 s), KI-Import (2,6 s) und Analyse-Tab (2,3 s). Xcode Cloud rechnet mit einem anderen Komplexitätsbudget als mein Rechner — zwei Builds sind daran schon gescheitert. Alle vier sind in kleinere Einheiten zerlegt; die Rennhistorie liegt jetzt unter 0,7 s. Am Verhalten ändert sich nichts. **Build 16** · 5 August 2026 Die Trainingshistorie ist wieder da · Der Lauf-Bildschirm nutzt endlich den Bildschirm - Fix: In der Historie standen nur noch Simulationen, keine Trainings mehr - Und es hätte fast echten Schaden gegeben - Fix: Auf dem Lauf-Bildschirm wurde die zweite Wertezeile mitten durch die Ziffern abgeschnitten - Der „Fertig"-Button war ein Fünftel des Bildschirms groß - Oben lagen 55 pt totes Schwarz - Damit passen auch größere Zahlen - Und die Block-Kachel zeigte „13…" statt „13 KM" **Build 15** · 5 August 2026 Der Lauf-Screen blättert und ist einstellbar · Verworfen heißt verworfen · Pausen zählen als Pausen - Fix: Die Werte auf dem Lauf-Bildschirm werden endlich in der Größe angezeigt, in der sie gesetzt sind - Deshalb zeigt die Karte jetzt weniger und dafür groß - Fix: Eine verworfene Simulation landete trotzdem in Apple Health - Fix: „Pause 0:00" nach einem Training mit Satzpausen - Fix: In der Satzpause stand die Übung, die gerade fertig war - Drei weitere Lauf-Ansichten sind jetzt echt befüllt: Zonen, Leistung und Laufform - Die Puls-Ansicht kennt jetzt Ø und Maximum der ganzen Einheit - Technisch: alle Messgrößen werden ab sofort **namentlich angefordert** statt sich auf die Voreinstellungen der Trainingsart zu verlassen. Der Renn-Pfad startet als Intervalltraining, wo Geschwindigkeit, Leistung und Laufform gar nicht erst erhoben worden wären. - Neu: Du stellst die Lauf-Ansichten selbst zusammen - Neu: der Lauf-Bildschirm blättert vertikal - Die Ziel-Karte erscheint nur, wenn der Laufblock überhaupt eine Zieldistanz hat - Ø-Pace, GPS-Anzeige, Zielpace und Höhenmeter sind eine Wischgeste weiter gezogen - Nebenbei: **volle Zeilenbreite statt Raster hätte es schlimmer gemacht.** Vier gestapelte Zeilen in dasselbe Höhenbudget ergeben 13,4 pt — weniger als heute. Apples Trainings-App kommt damit durch, weil sie weniger Werte zeigt **und scrollt**; diese Seite scrollt bewusst nicht, damit nichts springt, wenn mitten im Lauf GPS- oder Pulsdaten eintreffen. **Build 14** · 5 August 2026 Krafttraining ist kein Lauf · Die Kardio-Kurve erfand Ruhetage · Ein Screen für eine Einheit - Fix: Krafttraining landete auf Strava als „Lauf", nur wegen des Aufwärm-Laufs - Fix: „Keine HF-Daten verfügbar — Training muss in Apple Health gespeichert sein" bei einer Simulation, die Herzfrequenz aufgezeichnet hat - Fix: Die Kardio-Belastung hat zwei Wochen echtes Training zu Ruhetagen erklärt - Fix: „Keine Herzfrequenzdaten für diese Einheit verfügbar" — über einer Übungsliste, in der jede Zeile eine Herzfrequenz zeigt - Eine vergangene Einheit öffnet jetzt überall denselben Screen **Build 13** · 5 August 2026 Der Verlauf zeigt die Analyse mit · Zwei gleichwertige Karten · Kardio-Kurve fiel ab - Eine vergangene Einheit zeigt jetzt alles auf einmal: nochmal starten, was du gemacht hast, und die Analyse dazu - Der Verlauf im Trainings-Reiter enthält jetzt auch Simulationen - Neu: „Meine Workouts" und „Meine Simulationen" als zwei gleich große Karten - Fix: „Das Workout ist nicht mehr gespeichert und kann daher nicht wiederholt werden." - Fix: Die Kardio-Belastung fiel ab, weil meine Doppelzähl-Sperre von gestern zu grob war - Fix: Mein Zeilenumbruch im Tab-Label hat „Simulationen" verschluckt **Build 12** · 4 August 2026 Simulationen haben jetzt genau ein Zuhause - Der Reiter „Rennen" enthält nur noch echte Rennen - Der Simulationen-Button führt jetzt in die Übersicht - Die Auswertung absolvierter Simulationen liegt im Analyse-Reiter - Die Trainingshistorie ist nicht mehr gedeckelt - Das Tab-Label skaliert **Build 11** · 4 August 2026 Aus „Train" wird „Training + Simulationen" - Fix: „73 % Stationen" auf einer Simulation, bei der nur die Läufe abgewählt waren - Der Reiter heißt jetzt Training + Simulationen - Der Planer öffnet jetzt kurz - Die Übernahme ins erweiterte Bearbeiten braucht keinen Code - Neu: Vergangene Trainings - Neu: Simulationen vergleichen - „Teilsim" heißt jetzt „Teilsimulation" **Build 10** · 4 August 2026 Gerade Linien in allen Diagrammen · Herzfrequenz am richtigen Ort - Alle 62 Diagramm-Linien laufen jetzt gerade von Punkt zu Punkt - Zur Punktdichte - Fix: „Keine Herzfrequenzdaten für diese Einheit verfügbar" — obwohl durchgehend aufgezeichnet - Fix: „2x am Ausgangsgate tippen" lag hinter der Seitenanzeige **Build 8** · 4 August 2026 Abgebrochene Aufzeichnungen kommen jetzt wirklich an - Fix: Eine abgebrochene, gespeicherte Simulation war weiterhin nirgends zu sehen — mein Fix von gestern saß an der falschen Stelle - Fix: Der Plantag findet die Aufzeichnung - Fix: Und die Analyse lässt sich von dort auch öffnen - Neu: Was der Plan nicht vorgesehen hat, trägt er trotzdem ein **Build 7** · 4 August 2026 Vier Stationen, die nie Top 1 % waren · Der Planer zeigt den Ablauf · · · Vier Stationen auf „Top 1 %", die es nie waren - Fix: Eine einzelne Stationszeit wurde mit der Quote des ganzen Rennens hochgerechnet - Fix: Zeiten schneller als alles je Gelaufene bekamen einen Goldpokal - Neu: Das Rennen steht jetzt als eine durchgehende Liste da - Neu: Eine Zeile sagt, was du gebaut hast - Fix: Eine Simulation, deren Reduktion nie gespeichert wurde, setzt keine Bestzeiten mehr - Neu: Ein Schalter ganz oben im Simulations-Planer — Schnell oder Detailliert - Wichtig dabei: Der schnelle Weg fragt weniger, speichert aber nicht weniger - „Das ergibt" unter der Auswahl **Build 6** · 4 August 2026 Der Karten-Durchgang: 55 Befunde · Vier Simulations-Fehler · 104 Texte auf Deutsch · · · „Renegade Row" enthält „Row" · Doppelt verbuchte Trainingslast - Fix: Dreizehn Übungen fragten nach einer Maschinenstufe statt nach Kilogramm - Neu: Die Lastart ist am iPhone umstellbar - Fix: Jede in der App getrackte Einheit wurde doppelt in die Trainingslast gebucht - Fix: Zwei Trainingskarten maßen gegen Rennen, die es nie gab - Fix: „Std/Wo Ø" zeigte die letzte Woche, nicht den Schnitt - Fix: Acht Renn-Karten zeigten die Demo-Rennen als deine eigenen - Fix: Dieselben Karten kannten deine Division nicht - Fix: Die Rennzeit-Prognose zählte jede Wechselzeit doppelt - Fix: Wechselzeiten-Karte übersah die genauer aufgezeichneten Rennen - Fix: Halbsimulationen wurden als Vollleistung benotet - Fix: Jedes komplette Deadly-Strong- und Deadly-ERG-Rennen galt als Teilsimulation - Fix: Die Wechselzeit wuchs mit dem Stations-Arbeitsaufwand statt mit der Stationszahl - Fix: Der Zeit-Donut zählte gemessene Wechselzeiten doppelt - Fix: Die Deadly-Dozen-Zielzeit ließ jeden Wechsel weg - Fix: Rennvergleich rechnete mit eigenen Faktoren - Fix: „Stations-König" und „Eiserne Serie" verglichen über Divisionen hinweg - Fix: Segment-Pokale und die Aufzeichnungs-Prüfung maßen an Demo-Rennen - Fix: Der KI-Export beschrieb Halbsimulationen als volle Rennen - Fix: „Neuestes Rennen" im Export war nicht das neueste - Fix: Stations-Bestzeiten im Export zählten den Anlaufweg mit - Fix: Auch die „Beste Teile"-Karte maß Tor zu Tor - Fix: Eine reine Stations-Einheit galt als „erste Hälfte" - Die App spricht jetzt vollständig Deutsch - Fix: Der Pace-Rechner bot eine Bestleistung an, die niemand je gelaufen ist - Fix: Die Feldverteilungs-Tabs „Laufen" und „Stationen" widersprachen dem Tab „Gesamt" - Fix: Fast jede ehrliche Hälfte war nur als „Teil" beschriftet - Fix: Eine Simulation nur aus Übungen bekam trotzdem einen Lauf vorneweg - Fix: „Ab Station 6" startete mit Lauf 1 statt Lauf 6 - Fix: Ohne Läufe wurden gar keine Wechselzeiten aufgezeichnet - Fix: Eine abgebrochene, gespeicherte Simulation war nirgends zu finden - Neu: Abgebrochene Aufzeichnung als Teilsimulation übernehmen - Neu: Verwerfen fragt nach - Fix: 0 kg sprang auf den geplanten Wert zurück **Build 5** · 3 August 2026 Die Stufenfolge, die nur im Kommentar stand · Alle Paare zählen - Fix: Die neue Bestleistungs-Regel versprach eine Rangfolge und rechnete ein flaches Minimum - Alle Hälften-Paare zählen, nicht nur eins **Build 4** · 3 August 2026 Die Wechselzeiten fehlten in jeder Hochrechnung · Feldverteilung antippbar · Fitness-Karte war unerreichbar - Fix: Deine Wechselzeiten wurden in jeder Hochrechnung unterschlagen - Die zusammengesetzte Zeit enthält jetzt eine Wechselzeit-Zulage - Feldverteilung: antippen und halten - Feldverteilung steht jetzt über der Karte „Deine besten Teile" - Fix: Die neue Fitness-Karte war nicht auffindbar — weil sie in einer View lag, die nirgends angezeigt wird - Zwei Hälften werden jetzt gepaart statt einzeln verdoppelt - Fix: Labour-Bestzeiten waren nicht nach Division gefiltert **Build 3** · 3 August 2026 Die Fitness-Kurve sagt jetzt etwas · Fehlende Segmente werden aus dem Feld ergänzt · Charts, die nicht mehr aus der Karte laufen - Die Fitness-Kurve ist in die Trainings-Analyse umgezogen und sagt jetzt etwas - Segmente, die du noch nie gemacht hast, werden jetzt aus dem Feld ergänzt statt weggelassen - Fix: Der Körperfett-Chart lief unten aus seiner Karte heraus - Charts wachsen mit dem Zeitraum - Bei vielen Messpunkten verschwinden die Punkte - Fix: Die Feldverteilung rangiert keine Zeit mehr, die schneller ist als die schnellste je in dieser Division gelaufene - Fix: Die Feldverteilungs-Karte hat deine Zeiten nie nach Division gefiltert - Fix: Der KI-Export nannte für dieselbe Simulation drei verschiedene Zeiten - „Noch nicht gemessen" heißt jetzt wirklich noch nicht gemessen - Neu: Die App erkennt jetzt, wenn ein Gate-Tap nicht angekommen ist — und sagt, wie es wahrscheinlich war **Build 2** · 3 August 2026 Eine 32-Minuten-Halbsimulation stand als „Sub-50 (Elite)“ da · Auszeichnungen ohne Volumenprüfung · 30 deutsche Texte, die nie erschienen sind · Fitness-Kurve und Muskel/Fett-Trend - Neu im Analyse-Tab: eine Fitness-Kurve - Neu bei den Körperdaten: Muskel/Fett-Verhältnis mit geglättetem Trend - Fix: Die Feldverteilungs-Karte rechnete mit einem anderen Ermüdungsmodell als die Level-Karte - Fix: „+3 heute" in der Trainingslast-Karte stand auch im englischen Build auf Deutsch - Fix: Eine halbe Simulation galt weiter als volles Rennen — jetzt ist die eigentliche Ursache gefunden - Fix: 16 deutsche Übersetzungen konnten nie erscheinen - Die Karte „Deine besten Teile, zusammengesetzt" rechnete 4:42 für ein volles Rennen - Der Aufschlag auf die Summe deiner besten Teile wird jetzt an dir gemessen, nicht angenommen - Fix: Die Analyse verglich Deadly-Dozen-Rennen ohne Rücksicht auf die Division - Fix: Der Analyse-Tab rang eine halbe Deadly-Dozen-Simulation als „Sub-50 (Elite), Top 1,3 % des Feldes" ein - Neu: „Deine besten Teile, zusammengesetzt" - Fix: Eine abgeschlossene Simulation bot weiter an, geplant zu werden - Wer über die Karte „Plane diese Simulation" geht, plant sie jetzt auf diesen Tag - Die Transition-Gehzeit ist ein Schalter, kein Zähler - Simulationen sind Vorlagen, keine Termine - Neu: Aktionsleiste im Simulations-Planer - Fix: Die Workout-Liste bekam für dasselbe Workout immer neue Karten - Ein Tag mit mehreren Einheiten lässt sich jetzt durchblättern - Fix: Die Trainingsanalyse drehte sich unbegrenzt - Rennvergleich: Herzfrequenz pro Segment als eigene Zeilen - Fix: Die Herzfrequenz des letzten Segments war in jedem Rennen erfunden - Fix: Ein zurückgenommener Gate-Tap warf die Herzfrequenz des Segments weg - Fix: Sieben Auszeichnungen wurden ohne jede Volumenprüfung vergeben - Fix: Die Bestleistung auf der Dashboard-Karte kam ungefiltert aus dem Rennspeicher - Fix: Deadly-Dozen-Rennen wurden in den Analysekarten nicht nach Division gefiltert - Fix: 14 weitere Texte erschienen auch auf Deutsch englisch - Die Composite-Karte hat jetzt auch eine Obergrenze - App-Store-Screenshots nennen die Formate auf jedem Bild **Build 1** · 2 August 2026 Zone-2-Vorschlag von 5:09 · Pro-Käufer sahen Werbung für Gekauftes · Plan-Löschen war eine Sackgasse - Wer sein erstes Rennen plant, bekommt jetzt echte Startwerte statt Formatvorgaben - Fix: Die App schlug eine Zone-2-Pace von 5:09/km vor — schneller, als der Athlet je locker läuft - Fix: Die Karte behauptete „HR-Pace-Kopplung" und rechnete etwas anderes - Ein Puls-Deckel räumt die Altlast auf, ohne gespeicherte Läufe anzufassen - Kein Vorschlag springt mehr weit - „Stationen-Bestzeiten" zeigt für ATHX jetzt Zonenwertungen statt Zeiten - Fix: Die „YOUR LEVEL"-Karte wählte das ATHX-Referenzrennen nach der kürzesten Gesamtzeit - Fix: Die ENERGY-SPLIT-Karte zeigte für ATHX „Lauf 0:00 · 0 %" - Fix: Die Trophäe für eine Segment-Bestzeit erschien auf ATHX-Zonen - Fix: Das KI-Briefing bekam die ATHX-Zonendauern unter der Überschrift „Stations:" - Fix: VoiceOver las das ATHX-Format als „0 Runs, 0 meters each" vor - Fix: Auf der Uhr gab es für ATHX eine Pace-Zielvorgabe in min/km - Fix: „Auto-Ausfüllen aus Zielzeit" skalierte bei ATHX die festen Zonenfenster - Fix: Der Renn-Rechner bot ATHX an, kappte aber jede Zone bei 10:59 - Fix: Ein geplantes ATHX-Rennen zeigte in der Detailansicht einen erfundenen „Run 1" und nur die erste Zone - Fix: Die Puls-Kurve über das ganze Rennen zeigte bei ATHX nur eine von drei Zonen - Fix: ATHX-Zonen wurden weiter als Leistung gewertet - Fix: Der Analyse-Tab meldete für ATHX einen erfundenen Einbruch - Fix: Auf der Uhr vibrierte es drei Minuten nach jedem Zonenstart - Fix: In Health landete jedes Rennen unter einer HYROX-Kategorie - Fix: Ein exportiertes ATHX-Rennen bestand aus drei „Resting"-Runden - Fix: Die MetCon-X-Ergometer fragten nach Kilogramm - Fix: Die Endurance-Zone war mit „750 m" beschriftet - Fix: Live-Aktivität, Live-Tracker, Startblatt, Simulationskarte und die Renntag-Mitteilung - Rennen kommen jetzt mit einer echten Beschreibung bei Strava an - Fix: Strava bekam vom Rennen fast keine Pulsdaten - Fix: Der KI-Plan-Prompt beschrieb ein anderes Jahr - Fix: Jedes ATHX-Rennen wurde dem Modell als „Runs: 0:00" gemeldet - Fix: Der Smart-Generator zeigte bei ATHX Regler für Laufrunden und Lauf-Skalierung - Fix: Deadly-Dozen-Athleten mit Pro sahen ihre Stationen-Benchmarks nie - Fix: Die Feldverteilung erfand eine Kurve, wo keine Daten sind - Fix: Die Stationen-Bewertung maß sich an sich selbst - Fix: Demo-Rennen konnten Benchmark- und Prognosegrundlage werden - Fix: Die Formatauswahl der Uhren-Komplikation war für alle auf Deutsch - Fix: Die gestern eingebaute Plan-Sperre hat Löschen zur Sackgasse gemacht - Die Sperre ist ersatzlos raus, nicht repariert - Der Hinweis „Dein erster Plan war gratis…" im Assistenten fällt damit weg — er stimmte so nicht. **Build 1** · 28 June 2026 Trainingsdauer-Schätzung korrigiert `estimateBlockDuration` (TrainingPlanManager) und `estimatedDurationMinutes` (WorkoutPlan) haben bisher die Zeit für Krafteinheiten stark unterschätzt: - Stations- und Übungsblöcke berücksichtigten die Pause zwischen den Sätzen (`restBetweenSetsSeconds`) gar nicht — nur eine pauschal addierte Konstante (90 s flat statt `(Sätze–1) × Pausendauer`). - Stations-Blöcke ignorierten `exerciseSets.count` und verwendeten immer einen Fixwert von 180 s, egal ob 1 oder 3 Sätze. - Timed Exercises (`durationTargetSeconds`) wurden nicht berücksichtigt. Fix: Beide Funktionen berechnen jetzt: - `Sätze × Arbeitszeit/Satz` (aus `durationTargetSeconds`, Wiederholungen × 2,5 s, oder Default 50 s) - `+ (Sätze–1) × restBetweenSetsSeconds` (Pause zwischen Sätzen, Default 90 s) - `+ 20 s Setup/Transition` pro Block Ergebnis: 3-Satz-Übung (10 Wdh., 90 s Pause) = ~5 min statt ~3,75 min.
improvedAugust 1, 2026

Version 1.1.2

**Build 68** · 1 August 2026 Preise neu gesetzt · vier Stellen im Code sagten vier verschiedene Zahlen - Pro kostet jetzt 24,99 € einmalig statt 9 $, das Monatsabo 2,99 € statt 2 $ - Die kostenlose Testphase geht von 3 auf 7 Tage - Fix: Vier Stellen im Code nannten den Preis, und keine zwei stimmten überein - Fix: Die Testphasen-Länge stand als Text in der Paywall **Build 67** · 1 August 2026 Die Uhren-Komplikationen waren in keinem einzigen Build enthalten - Fix: „GritRace" tauchte in der Komplikations-Auswahl der Uhr nie auf - Warum sie nicht einfach eingetragen war - Damit funktionieren **Race Countdown** und **Last Race** auf dem Zifferblatt: Zifferblatt lange drücken → Bearbeiten → Komplikationen → GritRace. Der Countdown lässt sich beim Hinzufügen auf ein Format filtern. **Build 66** · 1 August 2026 Der Plan gehört dir · Paywall verspricht nur noch, was Pro wirklich freischaltet - Die Pro-Grenze liegt jetzt bei der Plan-Erstellung, nicht beim Weitertrainieren - Der Hinweis steht vor dem Tipp, nicht danach - Die Paywall hat drei Dinge verkauft, die jeder ohnehin hat - Fix: Die Paywall-Liste war nie übersetzt - Fix: Ein zurückerstatteter Kauf hätte Pro behalten — und ein gültiger hätte ihn verlieren können - Der KI-Import sichert sich selbst ab - Aufgeräumt: ein Kommentar, der eine lebende Funktion für tot erklärte **Build 65** · 1 August 2026 Gespeichertes Workout startete mit allem abgehakt · Supersatz-Satz einzeln · Laufansicht lesbar - Fix: Ein gespeichertes Workout startete mit fast allem abgehakt - Fix: Ein einzelner Satz bei einem Supersatz kam nicht auf der Uhr an - Fix: In der Laufansicht lag der Titel unter dem Zurück-Pfeil - Laufansicht lesbarer **Build 64** · 1 August 2026 Gestern erkannte Workouts standen am nächsten Morgen unter „heute" - Fix: Erkannte Workouts vom Vortag blieben stehen - Fix: „Zusätzliches Workout" hat sich das Workout nicht gemerkt **Build 63** · 31 July 2026 Belastungskurve lief flach · TSB ignorierte das Krafttraining · Einheiten in den Kacheln - Fix (Regression von heute): Die Belastungskurve lief über Tage schnurgerade - Fix: TSB ließ das Krafttraining komplett außen vor - Fix: „31" neben „2780" sah aus wie ein Rechenfehler **Build 62** · 31 July 2026 Warum manche Sätze abgehakt ankamen und manche nicht · Health-Distanz Anlass war: „manchmal werden welche abgehakt, manchmal aber nicht, obwohl auf der Uhr vollständig getrackt". Die Ursache ist keine verlorene Übertragung — die Uhr schickt jedes Mal den **vollständigen** Stand aller Sätze, und jeder Empfänger hakt davon immer die **ersten n** Zeilen ab. Ein Loch wie „Satz 2 abgehakt, Satz 1 nicht" kann daraus rechnerisch gar nicht entstehen. - Fix: Die Übungskarte hat den Stand der Uhr regelmäßig verworfen - Fix: Anzeigen war weiterhin Speichern - Fix: Der Live-Tab löschte bei jedem Aufruf alles Abgehakte - Fix: Ein in der Pause abgehakter Satz war für immer verloren - Fix: Health bekam die falsche Distanz **Build 61** · 31 July 2026 Das Gewicht der vorigen Übung wurde der nächsten vorgeschlagen · Fortschrittspfeil war unsichtbar · Übungsbilder auf der Uhr - Fix: 107 kg beim Thruster, obwohl du dort zuletzt 36 kg hattest - Fix: Anzeigen war gleichbedeutend mit Speichern - Fix: Der Fortschrittspfeil war unsichtbar, wenn er etwas zu sagen hatte - Neu: Übungsbilder auf der Uhr **Build 60** · 31 July 2026 Frauen wurden bei DEKA und ATHX gegen das Männerfeld gewertet · Watch: Name antippen startet nicht mehr - Fix: Bei DEKA und ATHX entschied die Reihenfolge der Liste über dein Geschlecht - Fix: Sieben Analyse-Abschnitte zeigten bei ATHX nur eine Überschrift - Watch: Auf den Workout-Namen tippen startet nicht mehr das Training **Build 59** · 31 July 2026 Ein nachgetragenes ATHX-Rennen war 0:00 und blockierte danach jede Bestzeit Weiter im ATHX-Durchgang, diesmal Nachtragen, Teilen, Export und die KI-Prompts. - Fix: Ein nachgetragenes ATHX-Rennen wurde als 0:00 mit drei übersprungenen Zonen gespeichert - Fix: Der KI-Prompt zur Rennanalyse widersprach sich selbst - Fix: Die Share-Karte druckte den Veranstalter-Zeitplan als Erkenntnis - Fix: Das iPhone-Widget zeigte eine formatfremde Bestzeit - Fix: Die Uhr bot ATHX ein Tempo in min/km an - Fix: Die Dynamic Island zeigte durchgehend ein Laufsymbol **Build 58** · 31 July 2026 ATHX auf der Uhr: die Zonen-Vorgabe war weg, sobald ein Plan geladen war Ein systematischer Durchgang durch alles, was bei ATHX blind von den Lauf-plus-Stationen-Formaten übernommen wurde. Vier bestätigte Fehler: - Fix: Die Uhr verlor die komplette Zonen-Vorgabe, sobald ein Rennplan geladen war - Fix: Ein geplantes ATHX-Rennen zeigte auf der Uhr „RUN 1" und nur eine von drei Zonen - Fix: Die Korridor-Erkennung lief in ATHX-Zonen und schnitt jeder Zone Zeit ab - Fix: Persönliche Bestzeit und Trend-Abzeichen auf einer ATHX-Gesamtzeit **Build 57** · 31 July 2026 ATHX: die Zielgewichte werden jetzt vorgeschlagen · und die App personalisierte bisher genau das Falsche ATHX ist die einzige Stelle in der App, an der die Last **nicht vorgegeben ist, sondern die Punktzahl ist**: Zone 1 sind drei selbst gewählte Maximalgewichte (Saison 2026: 1RM Strict Press, 3RM Back Squat, 5RM Deadlift). Trotzdem standen alle sieben ATHX-Zielfelder auf 0, ohne jede Vorbelegung — während die App gleichzeitig die 20- und 22-Minuten-**Zeitfenster** der Zonen aus der Rennhistorie „personalisierte", obwohl die der Veranstalter festlegt und niemand darin schneller wird. Genau verkehrt herum. - Neu: Vorschlag für die drei Kraftwerte - Sicherheitsregeln, weil hier eine Hantel drunter steht - Übungszuordnung als strikte Positivliste, niemals über Muskelgruppen - Neu: Ausdauer- und MetCon-Ziel aus dem letzten Rennen - Ehrlich leer statt erfunden - „Leere Ziele ausfüllen" statt „anpassen" - Fix: Die festen Zonenfenster werden nicht mehr personalisiert - Fix: Die Saison gehört zum Geltungsbereich des Vorschlags - Fix: Zwei tote Eingabefelder entfernt - Fix: Die Uhr zeigt die Zielwerte - Fix: Zwei Stellen fragten immer nach den Übungen der Saison 2026 **Build 56** · 31 July 2026 Der Zeitvorschlag gehörte zum falschen Rennen · Vorbelegung rechnet jetzt mit deinen eigenen Daten Anlass war: „Hier zeigt es nur den Vorschlag für HYROX an, obwohl Deadly Dozen ausgewählt ist." - Fix: Der Vorschlag wurde berechnet, bevor du das Format gewählt hattest - Fix: Stationszeiten wurden hochgerechnet, als würde eine halbe Simulation jede Station langsamer machen - Fix: Deadly-Dozen- und DEKA-Varianten wurden ignoriert - Fix: Demo-Rennen flossen in deine Vorbelegung ein - Neu: Vergleichbarkeit wird jetzt sauber getrennt - Neu: Neuere Ergebnisse wiegen schwerer - Neu: Trainingsdaten aus dem Gym zählen mit - Neu: Das Banner zeigt, worauf es sich stützt - Neu: Auch langsamere Zeiten werden angeboten - Neu: Die Planung öffnet mit deinem Format und deiner Division - Fix: Ein Preset warf deine gemessenen Zeiten weg **Build 55** · 31 July 2026 Vergleichszahl im Rennverlauf war falsch · Trainingsbelastung kannte nur den heutigen Tag - Fix: Die Vergleichszahl im Rennverlauf verglich Unvergleichbares - Fix: Ein Lauf von gestern tauchte in der Trainingsbelastung nicht auf **Build 53** · 30 July 2026 Live umplanen: Satz, Übungswechsel und Umbauen kommen sofort auf der Uhr an Anlass war „Satz live hinzufügen wird nicht synchronisiert — die Uhr bleibt bei 1 von 2". Dahinter steckte nicht ein Fehler, sondern eine ganze Kette. Ein systematischer Durchgang durch **jede** Änderung, die man während eines laufenden Trainings am iPhone machen kann, hat folgendes ergeben: - Fix: Satz hinzufügen kam nicht an - Fix: Die Uhr hätte die neue Satzzahl trotzdem nicht angezeigt - Fix: Ganze Kategorien von Änderungen wurden stillschweigend verschluckt - Fix: Übungswechsel war bei jedem von der Uhr gestarteten Training wirkungslos - Fix: Nach einem Übungswechsel erbte die neue Übung alles von der alten - Fix: Sätze wurden beim Zusammenführen nach Position statt nach Identität zugeordnet - Fix: Die laufende Übung löschen kostete alle geloggten Sätze - Neu: „Workout ändern" im Live-Tab - Fix: Wischen zum Löschen eines Satzes war tote Geste - Fix: Manuelles Deload aktualisierte die Ansicht nicht - Fix: Die Uhr vibriert nicht mehr beim Synchronisieren **Build 52** · 30 July 2026 Simulations-Planung sitzt wieder · Stoppuhr pro Satz auch ohne Uhr - Fix: Die Stationsliste in der Simulations-Planung war verschoben - Neu: Stoppuhr pro Satz auf dem iPhone **Build 51** · 30 July 2026 Build-Fix, zweiter Anlauf: die Modifier-Kette der Übungsansicht aufgeteilt Build 50 ist an derselben Fehlerklasse gescheitert, nur an anderer Stelle. Diesmal war es nicht ein einzelner Ausdruck, sondern die **gesamte Kette** an der Seitenansicht: Für den Compiler ist so eine Kette EIN Ausdruck, und mit den drei zusätzlichen Beobachtern aus Build 49 hat sie das überschritten, was der Cloud-Compiler noch auflöst. (Warum lokal nicht: Der harte Abbruch hängt nicht an einer Zeit, sondern am Komplexitätsbudget des Lösers — und das ist von Swift-Version zu Swift-Version anders. Lokale Zeitmessungen sagen das also nicht vorher.) - Fix: Die Ansicht ist jetzt in zwei Einheiten geteilt **Build 50** · 30 July 2026 Build-Fix: Compiler-Timeout in der Watch-Übungsansicht Build 49 ist in Xcode Cloud nicht durchgelaufen — an einer Stelle, die hier lokal noch kompilierte. Der Cloud-Rechner hat ein anderes, langsameres Xcode, und ein Ausdruck, der knapp an der Grenze des Typprüfers liegt, kippt dort. Inhaltlich ist an dieser Version nichts anders als an 49. - Fix: „Compiler kann Ausdruck nicht in vertretbarer Zeit prüfen" - Vorbeugend: Die Gewichtskachel ist jetzt ausgelagert **Build 49** · 30 July 2026 Name läuft wirklich durch · Kachel antippen funktioniert · Watch → iPhone auch ohne Abhaken - Fix: Der Name stand am Ende geparkt („nian Deadlift") statt durchzulaufen - Fix: In die Kachel tippen, um mit der Krone zu ändern, ging nicht mehr - Watch → iPhone: Der eingestellte Wert wandert jetzt sofort mit **Build 48** · 30 July 2026 Watch-Layout gerade · Wischen und Antippen wieder da · Feld antippen markiert die Zahl - Fix: Bei langem Übungsnamen war das ganze Watch-Interface verschoben und nichts antippbar - Fix: Hoch/runter wischen ging nicht, nur die Krone - Fix: Wischen zur Übersicht ging nicht - Fix: „Watch nicht mehr verbunden" mitten im Training - Fix: Fertig, Abbrechen, Pause überspringen und Zurück taten bei toter Spiegelung nichts - Feld antippen markiert die ganze Zahl (app-weit) - Sync erst beim „Fertig" der Tastatur - Fix: Im Live-Training fehlten die Sätze bei Übungen, die man nicht vorher geöffnet hatte **Build 47** · 30 July 2026 Name läuft durch statt Geste zu fressen · Krone scrollt verlässlich · „Synchronisiert" heißt angekommen - Watch: Der Übungsname läuft von selbst durch — und frisst die Wischgeste nicht mehr - Watch: Scrollen auf dem Trainingsbildschirm jetzt verlässlich - Fix: „Synchronisiert" stand da, bevor irgendetwas ankam - Fix: Generiertes Krafttraining zeigte im Editor nur einen Satz **Build 46** · 30 July 2026 Pausentag-Tausch funktioniert · Verschobenes wird wieder blau Ab hier archiviert Xcode Cloud jeden Push selbst und zählt die Build-Nummer pro Push hoch — die Nummer im Projekt ist für TestFlight nicht mehr maßgeblich. - Fix: Ein Workout auf einen Pausentag legen — die Pause verschwand nicht, sie versteckte sich - Fix: Verpasstes Workout verschoben — und der neue Tag blieb rot **Build 45** · 30 July 2026 Live-Sync steht · Satzanzahl planbar · Körpergewicht bleibt bei 0 · Satzdauer sichtbar - Fix: Ein auf dem iPhone getipptes Gewicht erreichte die Watch immer noch nicht - Fix: Abhaken auf dem iPhone kam bei toter Spiegelung nie an - Fix: Start vom iPhone zeigte auf dem Handy keine Übungen - Fix: Fünf „Fertig"-Knöpfe über der Tastatur, keiner tat etwas - Planung: Satzanzahl änderbar, Gewichte und Wiederholungen pro Satz - Körpergewichtsübungen starten bei 0 kg — endgültig - Watch: Satzdauer läuft jetzt sichtbar mit - Watch: Die Pause zeigt, was aufzulegen ist — auch vor einer neuen Übung - Watch: Puls auch in der Pause - Watch: Übersicht aus der Pause erreichbar - Watch: Warnung beim Abhaken mit 0 Wiederholungen - Watch: Keine Vibration mehr bei Sync-Ereignissen - Watch: Die Krone scrollt zuerst — Werte erst nach Antippen **Build 44** · 29 July 2026 Alles, was du einträgst, kommt dort an, wo du es einträgst Gebaut und archiviert wird wieder von Hand mit einem regulären Xcode auf dem zweiten Mac — Xcode Cloud kompiliert nur zur Kontrolle. Die Build-Nummer im Projekt zählt also weiter: 1.1.2 hatte in TestFlight zuletzt Build 43, hier ist 44. - Fix: Abhaken auf der Uhr schaltete nicht zur nächsten Übung - Fix: Ein auf dem iPhone getipptes Gewicht kam nie an der Uhr an - Fix: Die Uhr verwarf Änderungen bei Workouts ohne Plan-Einheit - Fix: Die Uhr zeigte weiter das alte Gewicht, obwohl das neue angekommen war - Fix: Der Trainingsbildschirm ließ sich manchmal nicht scrollen - Fix: Auf der Uhr geloggte Werte überlebten eine Änderung vom iPhone nicht - Fix: Eine Satz-Meldung ans Handgelenk konnte still scheitern - Fix: Pause auch ohne Vorgabe - Fix: Die Zahlen-Tastatur ließ sich beim Training auf dem iPhone nicht mehr schließen **Build 26** · 28 July 2026 Pause zwischen den Übungen · Zeit-Übungen passen wieder aufs Display · Live-Training zeigt die Übungen - Fix: Nach dem letzten Satz einer Übung gab es keine Pause - Watch: Zeit-Übungen passen wieder auf einen Bildschirm - Live-Training zeigt die Übungen jetzt auch auf dem iPhone - Ausrüstungs-Auswahl im Generator entfernt - Intensität und Lauf-Skalierung gehen bis 200 % **Build 25** · 27 July 2026 Die Uhr startet das Training, das du geschickt hast · Handbearbeitung im Generator bleibt · Training nachträglich hinterlegen · Workout wiederholen - Vibration: Stärke und Länge einstellbar — und der Schalter wirkt endlich überall - Ergometer werden jetzt auf Zeit getrackt — und ausgewertet - Neues Diagramm „Ergo" in der Verlaufs-Karte - Fix: Von Hand gesetzte Gewichte kamen immer wieder zurück - Zeit-Übungen auf der Uhr sehen jetzt aus wie alle anderen Übungen - Die Krone stellt die Ziel-Dauer - Fix: Der Generator warf deine Bearbeitung weg, sobald du die Intensität bewegt hast - Fix: Nach dem Bearbeiten wurden aus zwei Runden vier - Doppeltipp funktioniert jetzt auf jedem Trainingsbildschirm - Training nachträglich einem Tag hinterlegen — auch ohne geplante Einheit - Ein absolviertes Training wiederholen - Fix: „Auf Apple Watch starten" zeigte erst nichts und danach ein fremdes Training - Läuft bereits ein Training, wird gefragt statt getauscht - Fix: Ein Training ohne Übungen öffnet keinen leeren Trainingsbildschirm mehr - Fix: Ein eigenes Workout meldete sich als Plan-Einheit ab - Zurück-Knopf auf dem Bereitschafts-Bildschirm **Build 24** · 26 July 2026 Größere Icons · Muskelgruppen erkennbar antippbar · Simulation direkt an die Uhr - Fix: Bestehende Simulationen finden ihre Analyse wieder - Tipp auf eine gelaufene Simulation öffnet die Analyse - Körpermaße: Fehlmessungen fliegen aus den Trends - Fix: Die Analyse einer gelaufenen Simulation fehlte im Plan - Simulations-Analyse auch in der Heute-Ansicht - Der Plan-Generator trainiert jetzt die richtige ATHX-Saison - Fix: Die Uhr lief beim Tracken nicht rund - Fix: Kilogramm auf Liegestützen, Wiederholungen beim Plank - Fix: Bearbeitete Trainings blieben in der Heute-Ansicht unverändert - Halbe Rennen werden mit deinem eigenen Einbruch hochgerechnet, statt einfach verdoppelt - Fix: Zwei Schalter für dieselbe Entscheidung - Alle Diagramme sind jetzt ablesbar - Teilsimulationen verfälschen die Analyse nicht mehr — und sind jetzt standardmäßig draußen - Fix: Bestzeiten konnten von halben Simulationen gewonnen werden - ATHX 2027 ist da — und beide Saisons bleiben planbar - Die eigenen Icons sind größer - Muskelgruppen: man sieht jetzt, dass man tippen kann - Simulationen gehen direkt an die Uhr **Build 23** · 25 July 2026 Analyse durchgerechnet · Fortschritt wird erkannt · Simulationen zeigen ihren Inhalt - Die Trainingslast rechnete an drei Stellen still falsch - Die Zielzeit-Prognose las nur das letzte Rennen - Hochrechnungen aus Teil-Simulationen waren um einen ganzen Stationsblock zu hoch - Der Ermüdungsindex zählte Läufe mit, die nie stattfanden - Abbruchquote, Wochenvolumen und die Balance-Schwelle - Neu: Die App erkennt echte Fortschritte und meldet sich - Geplante Simulationen zeigen endlich, was drinsteht - Die Heute-Karte zeigte das Workout zerstückelt - Charts lassen sich endlich ablesen - Neu: Simulationen korrigieren die Pläne, die sie geprüft haben - Extern getrackte Kraft-Workouts zählten unabhängig vom Körpergewicht **Build 22** · 24 July 2026 Sätze kommen zuverlässig aufs iPhone · Blöcke sauber umsortieren - Fix: Sätze fehlten in der Live-Ansicht auf dem iPhone - Fix: Auch die gemessenen Werte gingen mit - Blöcke umsortieren: eigener Bildschirm statt Ziehen in der Liste **Build 21** · 23 July 2026 Train-Umbau · Creator-Erweiterungen · iPhone zeigt die Last · Countdown stimmt · Simulation mit Division - Simulation: Division wählbar, mit Vorschau - „Neu" im Rennen-Tab öffnet wieder die Planungsmaske - Gewichte und Distanzen lassen sich endlich bequem ändern - Fix: Die Plan-Karte nannte das falsche Format - Fix: Countdown, Renn-Chip und Datum widersprachen sich - Fix: Der Countdown im Home-Screen-Widget blieb stehen - Fix: Auf der Uhr ließ sich das KG-Feld nicht mehr anwählen - Fix: Bei Supersätzen drehte die Krone die Seite statt der Zahl - Uhr: Abhaken und Pause nach oben, Pfeile darunter - Fix: Der Generator plante Übungen ein, die nie ausgewählt waren - Neuer Knopf „Alle Übungen" - Bearbeiten wirkt jetzt zurück auf die Regler - Fix: Auf dem iPhone stand kein Gewicht und keine Stufe - Fix: Am Ergometer fehlte auf dem iPhone die Messgröße - Fix: Eine auf der Uhr gedrehte Stufe kam nicht am iPhone an - Rückgängig: Die Today-Ansicht zeigt wieder nur die heutigen Health-Workouts - Nachtragen per Langdruck auf den Tag - Auch abgeschlossene Tage sind noch verknüpfbar - Verknüpfen aus der Workout-Historie heraus geöffnet - Aus drei Zielen wird eines - „Sätze" und „Runden" bedeuten endlich das, was sie sagen - Fix: „Keine Läufe" plante trotzdem einen Lauf ein - Fix: „Vor jeder Übung" tat gar nichts - Laufrunden-Auswahl auf zwei sinnvolle Optionen reduziert - Übungen per Drag & Drop umsortieren - Der Generator rechnet endlich mit der Uhr **Build 20** · 22 July 2026 Last richtig erfassen · Verpasste Health-Workouts nachtragen - Ergometer fragen jetzt nach der Stufe, nicht nach Kilogramm - Mobility- und Band-Übungen ohne Gewichtsfeld - Klimmzüge, Burpees und Planks behalten ihr Kilo-Feld - Läufe zeigen die Weste, wenn eine vorgesehen ist - Eigene Übungen: Art der Last wählbar - Stufe im CSV-Export und bei Strava - Verpasste Health-Workouts lassen sich nachtragen - Nachtragen ohne Zeitlimit - Nachgetragenes verfälscht die Gegenwart nicht mehr **Build 19** · 21 July 2026 Train-Feinschliff · iPhone-Tracking interaktiv · Absturz beim Lauf-Start behoben - „Weakness Attack" und „Kraft" sind ein Modus geworden - Stationen erscheinen nicht mehr dreimal untereinander - GPS läuft jetzt auch bei gesperrtem Bildschirm weiter - Englischer Tab heißt „Analysis" - Eigene Format-Badges statt Platzhalter - Hinweis auf Unabhängigkeit - Kalorien als eigene Messgröße - Fix: Stationen und Träger wurden in Wiederholungen statt Metern erfasst - Fix: „40m" wurde als 40 Sekunden geloggt - Eigene Übungen: Wiederholungen, Sekunden oder Meter - Icons auch auf der Uhr - Eigene Icons für alle Stationen und Muskelgruppen - Alternatives Training öffnet zuerst deine eigenen Workouts - „Eigene" heißt jetzt „Schnell" - Fix: Titel „Alternatives Training" fehlte - Fix: Wochenbeschriftung im Volumen-Diagramm überlappte - Neues Screenshot-Motiv fürs Workout-Tracking - App-Store-Screenshots jetzt zweisprachig und mit Apple Watch - Sätze bleiben zusammen — keine Übungen mehr dazwischen - Laufrunden frei konfigurierbar - Wochenplan blätterbar - Freie Workouts tragen kein fremdes Format-Etikett mehr - Name und Format jederzeit änderbar - Intensität wirkt jetzt bei allen Zielen - Realistischere Zeitschätzung bei vielen Wiederholungen - Ziel-Modi erklären sich selbst - Keine Export-Compliance-Abfrage mehr bei jedem Upload - Fix: Intervall-Läufe waren viel zu kurz - Fix: Kilometer zählten das Traben nicht mit - Farbstreifen über den Renn-Karten passt jetzt zur Karte - Analyse/Training ohne Format-Auswahl - Start-Button sitzt auf Deutsch mittig - Generiertes Workout speichern - Alternatives Training startet mit dem Generator - Abfragen erscheinen mittig statt als Blase - Fix: Schwarzer Bildschirm nach Workout-Ende auf der Watch - Watch-Zusammenfassung mit echten Kennzahlen - iPhone zeigt Übungen bei Watch-Workouts - Geplante Sätze sofort sichtbar - Watch-Trainingsscreen kompakter - Hinweis vor dem Watch-Start - Fix (kritisch): App stürzte beim Start einer Lauf-Einheit auf dem iPhone ab - Timer-Kopf schrumpft beim Scrollen - Creator zeigt sofort, was sich ändert - Seilspringen & Co. laufen auf Zeit statt Wiederholungen - Dauer reagiert endlich auf den Intensitätsregler - Zeit/Dauer in den Stationsparametern - Keine doppelten Pausen mehr - iPhone-Tracking komplett überarbeitet - Watch: großes Pause-Ziel - Workouts löschen & Erstellungsdatum - Fix: Feldverteilung verschwand beim Wechsel der HYROX-Division **Build 18** · 18 July 2026 Dashboard-Feinschliff · Smart Generator vereinheitlicht · Sprachwahl - Readiness-Karte klar interaktiv - Y-Achsen ergänzt - Tagesempfehlung gekennzeichnet - Körperdaten-Charts scrollbar - Smart Generator vereinheitlicht - Dauer reagiert auf Intensität - Warm-up nur noch auf Wunsch - Pausen bei der Übung - Hinweis statt Rätselraten - App-Sprache wählbar - Fix - Fix (Watch) - Fix: Simulationen verknüpfen sich jetzt zuverlässig mit dem Trainingsplan - Fix: Simulation auf Trainingstag einplanen - Fix: Geplante Simulation verschwindet nach Abschluss überall - Fix: 15 fehlende UI-Refresh-Trigger - Rennvergleich grundlegend repariert & erweitert - Start-Button neu gestaltet - UI-Tests repariert - Wochenübersicht bleibt aktuell - Renn-Countdown-Fortschritt ohne Plan - Aufgeräumt - Fix: „Auf iPhone starten" führte ins Leere - Fix: „Plan erweitern" hätte den Plan ersetzt - Schneller: Workout-Verlauf & Übungs-Historie - Aufgeräumt (Train-Tab) - Wochentage endlich auf Deutsch - Fix: Plan-Import „Komplett ersetzen", Plan-Einstellungen und Verlauf-Wiederherstellung - Fix: Schwächen-Erkennung sah moderne Rennen nicht - Fix: Plan-Vorschau zeigte 0–1 Wochen bei nahen Rennen - Fix: Geplante Rennen erreichen die Watch jetzt sofort - Renntag-Checkliste repariert - Event-Kalender - Unter der Haube: 0 Compiler-Warnings - Einheitliche Typografie in der ganzen App (Phase 2) - Kein Wortumbruch mehr in der Readiness-Karte - Neues Interaktionsgefühl (Phase 1) - Watch: Heutige Simulation lädt automatisch - Analyse: Lauf-Paces & KI-Export korrigiert - Rennplaner: Vorschläge sehen jetzt alle Rennen - Fix: Muskel-Radar bei iPhone-Workouts leer - Live-Mitverfolgung: iPhone-Wärme & Ruckeln massiv reduziert - Unter der Haube - Goldener Schnitt im Layout - Watch: Druck-Feedback (Phase „Watch-Feel") - Mehr Bewegung (Phase „Motion") - Mutigere Optik — app-weit ausgerollt - Semantische Farbtokens konsolidiert - Watch: Workout-Lauf-Ansicht komplett neu - Watch: Ein Toast statt Overlay-Stapel - Watch: Einheitlicher Live-Header - Watch: Typografie auf die Skala - Session-Sheet aufgeräumt - Fix: Karten minimieren per langem Druck - Fix: Schwarzer Screen beim Abschließen - Smart Generator: Ziel-Dauer wählbar - Fix: Race-Week-Banner erschien nicht bei jeder Rennwoche - Fix: Überlappende Wochen-Labels im Volumen-Chart - Fix: Readiness-Verlauf lief über die Karte - Neues erstes Öffnen — ohne Modal-Stapel - Readiness-Karte ohne Daten - Format×Division-Audit — Kategorien werden endlich überall korrekt aufgelöst - Format×Division-Audit, Teil 2 - Fix: Verschwindende Häkchen in der Live-Mitverfolgung - Neue „Was ist neu"-Ansicht - App-Store-Screenshots - Readiness-Begründungen endlich auf Deutsch - Nachträglich in Health speichern - Fix: Workout fehlte in Apple Health - Übungsbilder freigestellt - Progress-Vergleich pro Satz - Watch: Zurück = Bearbeiten - Watch: Krone zuverlässig - Watch: Zeit-Übungen (Dead Hang & Co.) - Watch: HR-Ausfälle abgesichert - Muskelgruppen verfeinerbar - Strava-Upload robust - Fix: Planprogression nach rechts verschoben **Build 17** · 17 July 2026 Watch: Pausen-Screen & smarte Reihenfolge geplanter Rennen - Übersicht im Pausen-Screen erreichbar - Skip-Icon neben dem Timer - Smarte Reihenfolge geplanter Rennen (Watch) **Build 16** · 17 July 2026 Crash-Fix · Körperdaten-Charts · Free-Strength-Konfigurator überarbeitet - Crash beim Öffnen abgeschlossener Workouts behoben - Körperdaten-Charts lesbar gemacht - Free Strength – Equipment als Radio-Button - Free Strength – Sätze & Durchgänge statt Dauer - Grundübungen-Grid - Startgewicht in der Live-Vorschau - Vollständige Übungsliste - Reformierte Pausen-Logik **Build 13** · 16 July 2026 Workout-Generator: Klassische Langhantel-Lifts · Verpasste Einheiten · START-Button - Klassische Langhantel-Lifts im Generator - Tolerantes Equipment-Matching - Verpasste Einheiten automatisch markiert - START-Button zentriert **Build 12** · 14 July 2026 Session-Detail: Laufdistanz & Recovery-Blöcke zwischen Intervallen - Laufdistanz im Session-Detail - Recovery statt Pause zwischen Intervallen - Muskelgruppen-Redesign - START-Button in Tab-Leiste **Build 11** · 14 July 2026 UI-Overhaul: Mehr Platz, Race-Tab neu, Laufdistanz & Strava-Fix - Globales Spacing-Upgrade - Race-Tab (Upcoming) - Race-Tab (Simulationen) - PlannedRaceCard-Buttons - Free Create - WorkoutEditor Inline-Suche - Laufdistanz im Workout - Strava-Aktivitätstyp-Fix **Build 10** · 14 July 2026 Smart Workout Generator, AI Workout Import, Strength Profile - Smart Generate - AI Workout Import - WorkoutSuggestionEngine - Strength Profile - Geschätzte Gewichte - DSL-Erweiterung - Interne Refaktorierung: `mergeConsecutivePauseBlocks` und `filledWithDefaults(category:)` sind jetzt internal (nicht mehr private), sodass WorkoutGenerator diese teilen kann. **Build 9** · 13 July 2026 Race Tab Fusion: Races + Planner Werden Ein Tab - Race-Tab neu strukturiert mit drei festen Sektionen: **Upcoming → Simulations → History**. - Upcoming - Simulations - History - `RacePlanAdaptation`-Erkennungslogik aus `RacePlannerTabView` integriert: Banner wird oberhalb der betroffenen Rennkarte angezeigt, im thin-material-Stil mit Brand-Akzent (kein Grün mehr). Tap öffnet das Anpassungs-Sheet. - Toolbar-Add-Button zu **Menü** konsolidiert: „Plan Race" und „Log Past Race" als Menüpunkte; redundante Einzel-Buttons entfernt. - `RacePlannerTabView.swift` gelöscht - App-Tour-Overlay gelöscht - `GettingStartedSheet` erscheint nun direkt nach Abschluss des Onboardings – keine Tour-Zwischenstufe mehr. - `AppTourView.swift` gelöscht **Build 8** · 13 July 2026 Global START Sheet - Neuer globaler **START**-Button erscheint auf allen drei Haupt-Tabs: großer Vollbreite-Button (Forged-Gradient) unter der Readiness-Karte im Today-Tab; `play.circle.fill`-Symbol in der Toolbar des Train- und Race-Tabs. - Ein Tap öffnet ein Sheet mit **drei Startpfaden**: - Workout - Simulation - Race - Der „Quick Start\"-Button im Today-Quick-Actions-Bereich entfällt (ersetzt durch den globalen START-Button). - Simulationen werden mit `isPlannedTraining = true` gespeichert → PR-Ausschluss und Partiell-Filterung in Analyse bleiben korrekt. **Build 7** · 13 July 2026 Navigation: 4 Fixed Tabs + Train Tab - Tab-Leiste auf 4 feste Tabs reduziert: **Today · Train · Race · Analyse**. Kein kontextueller Planner-Tab mehr. - Neuer **Train**-Tab (ersetzt Plan): oben das heutige Session-Hero-Karte, darunter **Meine Workouts**-Raster (2 Spalten) mit „Neues Workout"-Zelle, Quick Workout und Workout Studio. Unten die kompakte Trainingsplan-Sektion (Wochenstreifen + „Vollständigen Plan anzeigen"), alle Plan-Aktionen (KI-Import, KI-Review, Deload, Neuerstellen, Rennen verknüpfen) ins Ellipsis-Menü (⋯) verschoben. - Bestehende Installationen - Session hinzufügen - App-Tour aktualisiert: Plan→Train, Races→Race; kein Planner-Schritt mehr. **Build 3** · 10 July 2026 Intervall-Training mit aktiver Erholung, entschlackter Erststart und mehrere Live-Workout-/Sync-Fixes. Neu: Aktive Erholung im Intervall-Training - Neuer Blocktyp „Recovery" (aktive Erholung = leichtes Traben/Gehen) neben der passiven „Pause". Zeitbasiert, wird auf der Uhr als leichte Bewegung getrackt (Pedometer/GPS aktiv), nicht als gestoppte Uhr, und zählt nicht als Arbeitsblock. - Workout-Builder: eigener Bereich „RECOVERY (EASY JOG/WALK)" mit Presets + Dauer-Editor. - DSL/AI-Import: `Recovery 90s` / `Recovery 2min` wird geparst; der KI-Prompt weist jetzt ausdrücklich an, zwischen Lauf-Intervallen aktive Erholung (nicht „Pause") einzufügen. Erststart / Onboarding - Erststart reduziert auf **eine** Intro-Seite (Story: die App entstand aus dem Wunsch, die Indoor-Pace ohne GPS zu sehen) → „Los geht's" direkt in die App. Keine Preise/Kauf-Buttons mehr im Onboarding, nur ein dezenter Hinweis, dass fast alle Funktionen kostenlos sind. - Format/Kategorie/Zielzeit werden jetzt über eine „App personalisieren"-Karte oben im Today-Tab abgefragt (nur für Neuinstallationen). Behobene Fehler — Trainingsplan - Generierte Kraft-Pläne haben jetzt eine Pause zwischen aufeinanderfolgenden Übungen/Stationen (vorher liefen Übungen ohne Rest hintereinander). - Geschätzte Trainingsdauer ist jetzt genauer: Sie wird nicht mehr künstlich auf das Zeitbudget gedeckelt, sondern spiegelt den echten Session-Inhalt wider (vorher teils deutlich zu niedrig). Behobene Fehler — Live-Workout / Watch↔Handy - Satz-Häkchen für bereits erledigte Übungen verschwanden zeitweise: Completion ist auf dem Handy jetzt innerhalb einer Session monoton (verschwindet nicht mehr durch verzögerte/partielle Updates). - Sekunden-Anzeige auf dem Handy stotterte/sprang, weil zwei Geräteuhren vermischt wurden — jetzt an die handy-lokale Empfangszeit verankert. - Handy wurde warm: Live-Updates gingen gleichzeitig über HK-Mirroring **und** WCSession — die WCSession-Strecke ist jetzt ein echter Fallback (nur wenn HK-Mirroring inaktiv). Zusätzlich Echo-Schleife gestoppt (Struktur wird nur bei echter Änderung zur Uhr gesendet, nicht bei Ergebnis-Rückschreibungen). - Sync-Konsistenz: das Handy folgt jetzt einem klar geordneten Live-Stream (Verwerfen verspäteter/doppelter Updates via Watch-`sentAt`). Behobene Fehler — Rennen / Format - Beim Live-Start aus einem geplanten Rennen werden die granulare Kategorie (`formatCategoryId`) sowie DD-/DEKA-Varianten korrekt übernommen (richtige Benchmarks, ATHX-MetCon-Gewichte, Analyse-Filter). - `includeRoxzone` wird in Plan-Gesamtzeit, Live-Plandelta, Segment-Rest und Predicted-Finish respektiert (Simulation ohne Roxzone rechnet nicht mehr mit Roxzone). - ATHX-Rennen liefern jetzt eine sinnvolle geplante Zielzeit (vorher 0). - Durchschnitts-Pace respektiert reduzierte Lauf-Distanzen (Half/Quarter/Custom-Simulationen). - Benchmarks/Badges nutzen die vollständige Format-Kategorie (Female/Team/Pro) statt eines generischen Platzhalters. Analyse / Herzfrequenz - Zone-2-Pace in der Progressions-Karte war teils viel zu langsam (z. B. 7:14 statt 5:40): der Ganzlauf-Durchschnitt aus Apple Health (inkl. Warmup, Gehpausen, Cooldown) wurde als Zone-2-Pace herangezogen. Jetzt zählen nur echte, pro Kilometer als Zone 2 klassifizierte Splits, und es wird der Median statt des Mittelwerts genommen (robuster gegen Ausreißer). - Max-Puls-Einstellung erweitert: neben manuell und „220 − Alter" gibt es jetzt „Meinen Apple-Health-Max nutzen" (höchste in den letzten 6 Monaten gemessene HF). Der Max-Puls steuert die HF-Zonen und damit u. a. die Zone-2-Einordnung — mit dem echten Wert werden die Zonen korrekt. Deadly Dozen Varianten - Gravierender Fehler behoben: Beim Planen einer „Deadly Mile" (und „Deadly Strong") wurden immer die normalen 12 Labours des Standard-Rennens angezeigt. Die Varianten haben jetzt ihre eigenen Segmente: Mile = Lunges + Burpee Broad Jump + Bear Crawl (je 400m) + 400m Run; Strong = 12 Labours ohne Runs. Durchgezogen über Planung, geplante Zielzeit, live gestartetes Rennen und Ergebnis-/Analyse-Ansicht. (ERG-Variante folgt separat.) - Deadly Mile: alle drei Bewegungs-Legs sind jetzt 400m und Körpergewicht (kein Zusatzgewicht), mit realistischen Default-Zeiten für die erste Planung (Burpee Broad Jumps als langsamstes Segment) → die geschätzte Gesamtzeit passt jetzt grob (~25–30 min für Einsteiger). - Uhr: ein live gestartetes Deadly-Mile-Rennen zeigt jetzt nur die 4 Segmente (nicht alle 12). Die zuletzt gewählte DD-Variante wird vom Handy zur Uhr synchronisiert, damit auch ein manueller DD-Start auf der Uhr die richtige Variante nutzt. Race-Planner - Angenommene Pace-Anpassung wird jetzt übernommen und für neue Planungen gespeichert (pro Format). Es wird nicht erneut gefragt — erst wenn du wieder schneller wirst, kommt ein neuer Vorschlag. Beim Annehmen passt sich die angezeigte Standard-Pace auch dann an, wenn nur die Einzel-Splits schneller wurden. - Deadly-Dozen-Simulation: die Erklärung zur Transition-/Gehzeit ist jetzt klarer (fürs Gym-Training gedacht; bei echten Rennen sind die Übergänge fest) und ein invertierter deutscher Satz wurde korrigiert. Widgets - Home-Screen-Widget zeigt jetzt die richtige Division: die Kategorie neben der Bestzeit gehört wieder zur echten Bestzeit (nicht mehr zur Division des nächsten Rennens). Die Division des nächsten Rennens steht jetzt separat im Countdown. - Neues, zusätzlich auswählbares Widget „Today & Recovery": zeigt das heutige geplante Training (inkl. „erledigt") und den aktuellen Recovery-/Readiness-Score. Sonstiges - Deadly Dozen: „Labours" wird nicht mehr fälschlich zu „Prüfungen" übersetzt — der Begriff bleibt „Labours". - Strava: manueller Re-Upload eines Rennens möglich (`force`). - Race-Planner: Stations-Simulationsblöcke korrekt zeitbasiert. - `loc.py` (Übersetzungs-Tool) findet die String-Katalog-Datei jetzt unabhängig vom Arbeitsverzeichnis. **Build 1** · 28 June 2026 Alternatives Training komplett überarbeitet + HR-Bugfixes AlternativeSessionSheet – Neues interaktives Formular - Sheet komplett neu gebaut analog zu „Einheit hinzufügen" (AddSessionSheet): kein KI-Generator mehr, volle manuelle Kontrolle. - Typ-Picker mit Sparkle-Marker für empfohlenen Typ (basierend auf dem bestehenden Trainingstag). - Run-Typ-Picker (Easy / Long / Tempo / Intervals) mit automatischer Intensitäts- und Dauervorbelegung. - Distanz-Stepper (0,5-km-Schritte, 0–42 km): synchronisiert Dauer automatisch anhand des typspezifischen Pace-Werts. - Dauer-Stepper (5-min-Schritte) und Intensitäts-Menü. - Notizfeld für Beschreibung. - Blöcke werden automatisch generiert: Easy/Long Run = 1 Zone-2-Block, Tempo = Warmup+Threshold+Cooldown, Intervals = Warmup + N×VO2max + 90s-Recovery + Cooldown, Strength/Conditioning = 3-Satz-Übungsblock, Recovery = Zone-2-Walk/Jog. - Action-Buttons: „Training ersetzen" / „Als Extra hinzufügen" / „Training entfernen (Ruhetag)". Stationsname-Bugfixes in AnalyseTabView + RacePlannerView (alle Formate) - AI-Export-Stationszeilen, Race-Comparison-Deltas, Transition-Chart-Labels, Planner-AI-Export: Raw-IDs (z. B. `dd_kb_farmers_carry`) werden jetzt via `RaceFormatRegistry` in lesbare Namen aufgelöst – gilt für HYROX, DD und DEKA. HealthKit / Herzfrequenz-Bugfixes (Watch) - `WorkoutSessionManager.startSession()` ruft jetzt `requestAuthorization()` vor dem HK-Session-Start auf (analog zu RaceManager) – verhindert silent failures wenn Berechtigungen beim ersten Workout-Start fehlen. - `HealthKitManager.startWorkout()` hat jetzt einen Retry-Mechanismus (1 s Verzögerung): schlägt die HK-Session fehl, wird automatisch einmal neu versucht.
improvedJune 29, 2026

Version 1.1.1

**Build 9** · 29 June 2026 iOS Home-Screen-Widget: jetzt im Widget-Picker sichtbar - Problem: Weder das Widget noch „GritRace" tauchten im iPhone-Widget-Picker auf. Ursache: Die einzige Widget-Extension war eine reine **watchOS**-Extension (`SDKROOT=watchos`, unter der Watch-App), zwar fälschlich in die iPhone-App eingebettet — aber eine watchOS-`.appex` läuft nicht als iOS-Widget, und der `#if os(iOS)`-Dashboard-Code wurde nie für iOS kompiliert. Zusätzlich fehlte komplett eine App Group. - Neues, isoliertes **iOS-Widget-Target `GritRaceWidgetiOS`** (Bundle-ID `com.MDos.GritRace.widget`) mit eigenem Ordner + file-system-synchronized group — zieht bewusst nicht die HealthKit-gekoppelte `Shared`-Schicht rein. - `GritRaceiOSWidget.swift`: „GritRace Dashboard"-Widget (systemSmall/Medium), eigener `@main`-WidgetBundle. - `WidgetModels.swift`: self-contained, decode-kompatible Mini-Modelle (`RaceFormatType`/`HyroxRace`/`RaceCategory`) — lesen exakt das von der App persistierte JSON. - App Group `group.com.gritrace.shared` - Falsche watchOS-`.appex`-Einbettung aus der iPhone-App entfernt; iOS-Widget korrekt in die iPhone-App eingebettet (PlugIns) + Build-Dependency. - Bugfix (nach erstem Test): Widget zeigte nur „Open". Zwei Ursachen behoben: - Kategorie kam aus der globalen Einstellung `gritrace.category` (Default „Open Men") statt aus den echten Rennen. Jetzt: nächstes geplantes Rennen → letztes Rennen → Einstellung (zeigt korrekt Doubles/DD/Solo). - Countdown war tot: App schreibt `gritrace.plannedRaces` als `[HyroxRace]`, das Widget dekodierte aber ein abweichendes `PlannedRaceInfo`-Schema → Decoding scheiterte still → immer PB-Fallback. Widget liest jetzt das echte `[HyroxRace]`-Schema. `PlannedRaceInfo` entfernt. - Bugfix (zweiter Test, Widget weiter leer): `RaceStore` schrieb die geladenen Rennen nur in Datei + `UserDefaults.standard`, **nicht** in die App Group — nur `persist()` (bei Mutationen) tat das. Eine bestehende Installation, die nur neu gebaut wird, hat den geteilten Container also nie befüllt → Widget leer. Neu: `mirrorToAppGroup()` spiegelt `savedRaces` + `plannedRaces` bei jedem `load()` und nach dem iCloud-Reconcile in die App Group und ruft `WidgetCenter.reloadAllTimelines()`. - Bugfix (dritter Test, falsche Daten): Das Widget leitete alles aus rohen Rennen ab und machte 5 Dinge falsch (PB/Last Race aus unvollständigem Training, rohe `formatCategoryId` statt Kategoriename, Goal vom falschen Format, falsches Datum). Neu: Die App baut einen **aufgelösten `WidgetSnapshot`** (`RaceStore.buildWidgetSnapshot`) und schreibt ihn in die App Group; das Widget rendert ihn nur noch. - PB/Last Race: nur echte, abgeschlossene Rennen (`isComplete && raceType == .race && !isPlannedTraining && !isSampleRace`). - Kategorie: `formatCategoryId` wird via `RaceFormatRegistry.categories(for:)` zum lesbaren Namen aufgelöst (keine rohe ID mehr). - Goal: nur, wenn `gritrace.goalTimeFormat` zum Format des nächsten Rennens passt — sonst ausgeblendet. - Datum: das echte Datum des nächsten geplanten Rennens. **Build 8** · 29 June 2026 Live-Workout: Satz-Häkchen-Sync robust gemacht - iPhone-Live-Training hakte einzelne Sätze nicht ab, obwohl sie auf der Watch getrackt waren (z. B. Satz 1 leer, Satz 2 grün). Ursache: Das iPhone bildete die Watch-`setNumber` direkt auf den Array-Index ab (`si = snapshot.setNumber - 1`). Bei verschobener Nummerierung (Supersatz-Round-Robin, Satz-Zurücknahme) traf der erste Row keinen Snapshot und blieb leer. - Fix (`PhoneWorkoutCompanionView.updateAnnotatedBlocks`): Snapshots werden jetzt nach `setNumber` sortiert und der Reihe nach auf die Satz-Rows gemappt (n-ter erledigter Satz → n-ter Row). Fallback: meldet die Watch den Block als komplett, werden alle Rows abgehakt. - Fix (`WorkoutSessionManager.goToPreviousSet`): Ein zurückgenommener Satz wird jetzt auch aus `allBlockSetResults` entfernt, damit keine veralteten/duplizierten Sätze mehr ans iPhone gesynct werden. Watch Übungs-Detailansicht: Header weiter aufgeräumt - Timer und Herzfrequenz aus dem Content in die Navigationsleiste verlegt (`.topBarLeading`) — sitzen jetzt zwischen Zurück-Button und Systemuhr. - Block-Progress („x/y" + schlanke Leiste) aus der `.topBarTrailing`-Toolbar in den Content-Header unter den Übungstitel verschoben — kein Gedränge mehr neben der Uhr. - `.navigationBarTitleDisplayMode(.inline)` gesetzt und Titel-Top-Padding entfernt — der große Leerraum über dem Übungsnamen ist weg. In-App „What's New" für 1.1.1 - Konsolidierter `case "1.1.1"` in WhatsNewView mit allen Highlights über alle Builds (Home-Widget, Watch-Sync, Watch-Layout, Alternativtraining, Plandauer, Stabilität) — EN + DE in Localizable.xcstrings. **Build 1** · 27 June 2026 iOS Home Screen Widget — GritRace Dashboard Neues Widget „GritRace Dashboard" für den iOS-Homescreen (systemSmall + systemMedium): - Small: Großer Countdown in Tagen bis zum nächsten Rennen, Format-Badge (H/DD/D/AX), Renndatum, Format-Akzentfarben-Gradient. Fallback auf Personal Best wenn kein Rennen geplant ist. Race Day zeigt „GO!". - Medium: Countdown-Spalte links + Stats-Spalte rechts mit Personal Best, Zielzeit-Vergleich (✓ under / to go), letztem Rennen und Kategorie. Trennlinie in der Formatfarbe. - Hintergrund: Dunkler Radial-Gradient in der jeweiligen Formatfarbe (Orange/Grün/Blau/Lila) für alle 4 Formate. - Gesamter iOS-Widget-Code mit `#if os(iOS)` gesichert — watchOS-Complications unverändert.
improvedJune 26, 2026

Version 1.1.0

**Build 1** · 26 June 2026 Deep-Audit Bugfixes (5 Bugs behoben) clearSessionCompletionState — fehlende Session-Felder - `clearSessionCompletionState()` hat bisher nur Block/Set-Ebene zurückgesetzt, aber `completedDate`, `completedDurationMinutes` und `readinessScoreAtCompletion` nicht gelöscht. - Das führte dazu, dass eine erneut gestartete Session veraltete Completion-Metadaten enthielt, die beim Abschließen mehrfach ausgelöst werden konnten. - Fix: Alle drei Session-Level-Felder werden jetzt genauso wie in `reopenSession()` zurückgesetzt. TrainingPlanViews — Falscher Button-Label bei übersprungener Session - Button für übersprungene Sessions zeigte „Mark as incomplete", rief aber `markSessionCompleted()` auf — hat die Session also als ABGESCHLOSSEN markiert, nicht als offen. - Fix: Label korrigiert zu „Mark Complete" mit passender SF Symbol-Ikone; `dismiss()` wird nach der Aktion aufgerufen. WorkoutSessionManager — Pedometer läuft nach EMOM-Rest-Abbruch weiter - `finishSession()` hat `stopTimer()` aufgerufen, aber NICHT `stopPedometer()`. - Beim Abbruch während EMOM-Rest-Phase lief der Schrittzähler unbegrenzt weiter. - Fix: `stopPedometer()` direkt nach `stopTimer()` in `finishSession()` ergänzt. StravaManager — Race Condition bei parallelen Upload-Aufrufen - Dedup-Check (`uploadedWorkoutIds.contains(...)`) und ID-Einfügung erfolgten asynchron — zwei gleichzeitige Aufrufe konnten beide die Prüfung passieren und dasselbe Workout doppelt hochladen. - Fix: Guard am Anfang von `uploadWorkout()` für `retryAttempt == 0`: wenn `isUploading` bereits `true`, wird sofort mit Fehler zurückgekehrt. Retry-Aufrufe (intern, `retryAttempt > 0`) umgehen den Guard korrekt. RaceStore — Sample-Rennen wurden in iCloud gespeichert - `syncToiCloud()` hat alle Rennen inklusive Sample-Daten kodiert — das hat die iCloud KV-Quota unnötig verbraucht und konnte echte Rennen durch Truncation verdrängen. - Fix: Nur echte Rennen (`!isSampleRace`) werden an iCloud übertragen. Truncation-Logik arbeitet ebenfalls nur noch auf echten Rennen.
improvedJune 26, 2026

Version 1.0.9

**Build 8** · 26 June 2026 Watch ↔ iPhone — Workout-Sync Bugfixes (5 Bugs behoben) Rest-Timer Synchronisation - `LiveWorkoutUpdate` trägt jetzt `restTimerEndDate: Date?` — den absoluten Endzeitpunkt des Rest-Timers auf der Uhr. - iPhone verankert seinen Countdown an diesem Datum statt an der übertragenen Restzeit, sodass Übertragungsverzögerungen (1–3 s) den Timer nicht mehr verschieben. - `RestTimerOverlay` wird bei jeder eingehenden Uhr-Aktualisierung neu synchronisiert (`.onChange(of: watchEndDate)`). - Wenn `restTimerDuration` in der ersten `LiveWorkoutUpdate` fehlt, wird `remaining` als Totalwert gesetzt — Fortschrittsbalken beginnt jetzt korrekt bei 0 % statt 100 %. Phantom-Completion / Ungewolltes Block-Vorspulen - `completeSet()` hat neuen Parameter `isRemote: Bool = false`. - Remote-Abschlüsse (iPhone → Uhr via `handleRemoteSetCompletion`) rufen `finishBlock()` und Superset-Rotations-Advance **nicht** mehr auf — die Uhr springt nicht mehr automatisch in den nächsten Block. - `confirmSet()` auf der Uhr prüft, ob der aktuelle Block bereits remote abgeschlossen wurde; in diesem Fall wird `finishBlock()` direkt ausgelöst, ohne ein zusätzliches Set-Ergebnis anzuhängen. Remote Set-Completion Dedup — Fehlende Block-ID im Hash - `handleRemoteSetCompletion` hash enthielt bisher nur Weight/Reps/Duration/SetIndex — ohne Block-Identifier. - Wenn zwei aufeinanderfolgende Blöcke dieselben Werte hatten, wurde der zweite Remote-Abschluss als Duplikat verworfen. - Fix: `currentBlockIndex` ist jetzt Teil des Hashes. Zurück-Navigation vom iPhone - Neuer `RemoteWorkoutCommand.goBack` — iPhone kann die Uhr anweisen, einen Satz zurückzugehen. - `ConnectivityManager.sendGoBackToWatch()` sendet den Befehl via HealthKit-Mirroring. - Neuer **← Go Back**-Button im Live-Begleiter (wird nur bei Übungsblöcken mit abgeschlossenen Sätzen angezeigt). DD-Analyse — Rennerkennung repariert - DD-Rennen wurden in der Analyse nie angezeigt, weil der Filter `formatCategoryId` prüfte — dieses Feld wird bei DD-Rennen nie gesetzt. - DD-Rennen speichern nur `ddCategory` (Solo/Pairs/Relay). Neues `ddCategory`-Property auf `DDDivision` bildet Detailkategorie auf Grobkategorie ab. - `completedRaces()`, `ddDivisionsWithRaces` und `autoSelectDivisions` nutzen jetzt `ddCategory` als Fallback. Schnellstart — Abgehakte Übungen beim Laden gespeicherter Workouts - `loadSavedWorkout()` wies Blöcke direkt zu — inklusive `isCompleted = true` vom letzten Training. - Fix: Completion-Flags und Actual-Werte werden beim Laden zurückgesetzt. **Build 7** · 23 June 2026 Renntempo — Korrekte Berechnung - `averageRunPace` berechnet jetzt Gesamtlaufzeit / Nennstrecke (400 m DD, 1000 m HYROX, 500 m DEKA). Bisher wurde die letzte GPS-Momentangeschwindigkeit bei Segmentende gespeichert, was bei Verlangsamung vor der Station zu einem zu langsamen Wert führte. - Betrifft alle Anzeigen: Renntempo im Trainingsplan-Wizard, Ø PACE in der Rennzusammenfassung, Analyse-Charts und wöchentlicher Digest. - `endCurrentSegment()` (watchOS): Schreibt jetzt ebenfalls die echte Durchschnittspace aus GPS-Segmentdistanz für neue Live-Rennen. Watch — Vorheriges Gewicht/Reps inline - Die Labels „Last: X kg" und „Previous: X kg" wurden aus der Übungsdetailansicht als separate Zeilen entfernt — sie haben den ✓-Button aus dem Bildschirm gedrückt. - Referenzwerte erscheinen jetzt kompakt (9 pt) direkt innerhalb der Kacheln, sodass keine zusätzliche Höhe entsteht. Körperdaten — HealthKit-Sync - Gewichts- und Körperfetthistorie wird jetzt automatisch aus der Health-App importiert. - Beim Öffnen des Körperdaten-Screens wird automatisch synchronisiert; roter Herz-Button für manuellen Re-Sync. - De-Duplizierung auf einen Eintrag pro Kalendertag; manuelle Einträge werden nie überschrieben. Trainingsplan — Kein doppelter Goblet Squat mehr - `buildStrengthSession` schließt jetzt Compound-Übungen aus Part 1 aus, wenn dieselbe Übung bereits als Focus-Station in Part 2 vorkommt (z. B. „Goblet Squat" + „dd_kb_goblet_squat"). AI-Importer — WorkoutRef Supersets korrekt importiert - Gespeicherte Workouts werden beim Import nicht mehr über DSL-Round-Trip verlustbehaftet konvertiert. Stattdessen werden Sentinel-Blöcke in einem Post-Parse-Schritt direkt durch die echten WorkoutBlock-Objekte ersetzt — Supersets bleiben erhalten. Trainingsplan — Rennfokussiert Icon - Icon für „Rennfokussiert" geändert von `flag.checkered` zu `figure.run`. Workout-Analyse — Intensitätsdiagramm - Liniendiagramm → Balkendiagramm mit Farbverlauf. - Pause-Blöcke werden ausgeblendet; nur aktive Übungsblöcke erscheinen. - X-Achsen-Labels um 45° gedreht für bessere Lesbarkeit. - Station-Prefixe (dd_kb_, hyrox_, …) werden aus den Labels entfernt. **Build 6** · 21 June 2026 Watch — Elapsed Time + Heart Rate on Exercise Screen - Elapsed total workout time and live heart rate now shown directly in the exercise tracking screen (weight/reps input view) so the user never has to leave that screen to see them. - Standard workout tracking screen made more compact so all content fits without scrolling. Analyse — DD Division Selection Fixed - DD division picker now appears with just 1 race (was incorrectly requiring 2+). - Division filter re-evaluates when race data loads from iCloud, so the correct division is selected on first open. - Always shows the picker and always filters by selected division, regardless of total race count. Skip Rest — iPhone → Watch Sync - Tapping "Überspringen" / Skip in the iPhone companion rest timer now sends a skipRest command to the Watch via HealthKit mirroring, stopping the Watch rest timer immediately. AI Import — Reps-Only Format Recognised - Lines formatted as "Exercise Name 10x" (number + x, no sets or distance) now correctly parse as an exercise block. Previously these lines were silently dropped, causing incomplete imports. Plan — Extends to Race Day - Off-by-one fix: training plan now always generates weeks up to and including race day. A race scheduled exactly on a Monday (7-day multiple from plan start) no longer falls one week beyond the generated plan. Plan Calendar — Planned Races Shown - WeekStripView now checks both targetRaces (multi-race plans) and the legacy raceDate field. Planned races are highlighted in the calendar strip on their correct day. Today Tab — No Horizontal Scroll - The main ScrollView is now explicitly vertical and its content has a fixed max-width, preventing any child card from making the whole screen horizontally scrollable. Performance — Faster Workout Opening - Opening a session detail sheet now triggers at most 1 disk write for block initialisation instead of one write per block (a 10-exercise workout: 10 writes → 1 write). - Plan history snapshots moved to a background thread so main-thread saves no longer block on directory listing and file reads. - Live-block list in SessionDetailSheet and LiveBlockEditorSheet cached as @State and refreshed only on plan mutations, not on every SwiftUI render pass. **Build 4** · 21 June 2026 Exercise Images — Full Display - All exercise thumbnails and detail images changed from scaledToFill to scaledToFit so the complete exercise/person is always visible instead of being center-cropped. - Applies to: card header thumbnails (32×32), library row thumbnails (44×44), exercise detail sheet header, workout search results, Plan Analyse view, Dashboard widgets. Watch — Race Day Auto-Load - On race day, the Watch app detects today's planned race and pre-loads it automatically so the user only needs to tap START. - Orange "RACE TODAY" banner shown instead of the regular green plan banner. - Auto-load is suppressed after the user manually clears the plan to prevent re-loading. Strava — Activity Type Fix - Strength workouts no longer uploaded as "Run". Root cause: Strava's async JSON upload was defaulting to Run type. Removed the JSON upload path; now uses the reliable manual activity creation with sport_type "WeightTraining". - Recovery sessions with no run blocks now correctly saved to HealthKit as traditionalStrengthTraining instead of running (which could trigger Strava's HealthKit auto-sync as a Run). - "Tracked with GritRace" in activity descriptions is now a tappable link: gritrace.app. Battery — Live Workout Optimisation (iPhone) - TimelineView update intervals reduced from 0.5s to 1s for the block and session elapsed timers (halves timer-driven renders). - Watch background data send rate reduced from 1 Hz to 0.5 Hz; block transitions, set completions and pause/resume still send immediately via the unthrottled path. - HK mirroring throttle and WCSession fallback throttle both updated to 2s to match. AI Plan Import — WorkoutRef Token System - Prompt now gives each fixed workout a UUID token. AI outputs one line (WorkoutRef <uuid>) instead of re-writing the full exercise block — prevents truncation and altered rep counts. - Parser expands tokens at import time; session title is set to the full workout name automatically. - If a UUID is not found (e.g. workout deleted), a visible inline comment is added instead of silently dropping the session. Plan Accuracy Fixes - All upcoming-race filters now compare at day granularity (startOfDay) instead of exact timestamp, preventing races scheduled for today from being treated as past. - buildMultiRaceWeeks uses upcomingTargetRaces (skips past target races) so multi-race plans no longer schedule around already-run races. - daysUntilRace never returns a negative value. - .onChange on RaceStore now detects in-place date edits, not just count changes.
improvedJune 19, 2026

Version 1.0.8

**Build 9** · 19 June 2026 Quick Workout — Watch Sync Overhaul - Auto-connect: when the first exercise is added and a Watch is paired, the plan is automatically sent to the Watch (no manual "Send to Watch" tap required). - Live block sync: adding exercises after the Watch has already started the workout pushes the updated block list to the Watch immediately via HK mirroring + WCSession fallback. - Watch-ended detection: when the Watch finishes the workout, the iPhone shows a "Save & Finish / Continue on iPhone" dialog instead of silently staying open. - Bug fix: `trainingPlanSessionId` is now stamped on Quick Workout plans, fixing a silent session-ID mismatch that caused all live block updates from iPhone → Watch to be rejected. Today Tab — Lighter Layout - Removed four cards that added clutter without value: stats row (completion %, sessions this week), Training Share button, Earned Badges card, and Fitness Trend card. - DashboardCard enum reduced from 12 to 7 cases; stale card IDs in UserDefaults are cleaned up on next launch. Race Sync Dialog — False Positive Fixed - The "Rennplan hat sich geändert" alert no longer appears incorrectly. Root cause: `checkTargetRaceSync` was triggering on planned races not yet in the plan (treated as "new races available"). Removed that check; dialog now only fires for actual date changes or deletions of target races. - Moved check to `.task` (after RaceStore has loaded) and re-runs on `store.races.count` change, so timing is reliable. AI Workout Builder — Custom Workouts Verbatim - Previously the prompt said "integrate them where they fit best", giving the AI freedom to ignore or rewrite selected workouts. - Prompt now says "COPY THESE VERBATIM — DO NOT change, combine, reorder, or replace any exercise." Exercises are formatted in DSL notation so the AI echoes them back parseable. - UI subtitle updated to reflect the actual behavior: "Selected workouts are copied into the plan exactly as you built them." **Build 8** · 18 June 2026 Station Time in Field Distribution — Gate-to-Gate Fix - `bestStationTime` now uses `race.totalStationTime` instead of summing `.stationSegments` (which only covers station-mode recording, not gate-to-gate). - Gate-to-gate races store stations as `.genericStationArea` segments; `totalStationTime` handles both modes. - Fixes the case where a gate-to-gate race showed 18:35 instead of the actual 23:33. - `bestRunTime` similarly simplified to use `race.totalRunTime`. AI Plan Import — Completed Race No Longer Listed - When re-opening the AI plan wizard, target races from the previous plan config are now filtered against `RaceStore.plannedRaces` (which excludes completed races). - Fixes the bug where a race you already ran (e.g. "DD Stuttgart") kept appearing in the race selection list. Dashboard Minimize Button — Badge Position Fix - The minus icon no longer overlaps the card's own expand/collapse chevron (top-right) or any header text (top-left). - Button now floats as a small badge just above the card's top-left corner (offset x:+6, y:−16), sitting in the 16pt gap between cards. **Build 7** · 18 June 2026 InfoTips — Simplified & Localized - Rewrote all InfoTip descriptions across RacePlannerView, RaceDetailView, RaceHistoryView, WorkoutBuilderView to be shorter and clearer. - Roxzone tip no longer uses the word "corridor" — uses "Roxzone" or format-specific name. - All new strings have EN + DE translations in Localizable.xcstrings. - InfoTip now uses `Text(LocalizedStringKey(text))` so all strings auto-localize. Watch Race Start — TransitionSetupView Refactor - Replaced two-step confirmationDialog + sheet flow with a single `TransitionSetupView` screen containing two clearly distinct toggles. - Toggle 1: Include Roxzone/Track Zone/Transition (time counted in race data vs. go straight to station). Default based on format's `hasTransitionZone`. - Toggle 2: Transition timer (live overlay timer at each transition). Default off. - Zone name adapts per format: HYROX → "Roxzone", DD → "Track Zone", DEKA → "Transition", ATHX → "Recovery". RaceSim Navigation Fix - Race simulations scheduled for today now always navigate to the Race Planner, never show workout start/stop buttons. - `TodaysWorkoutCard` gains an `onRaceSimTap` callback; the card shows "Open Race Planner" button for raceSim sessions. - Removed the separate raceSimButton from TodayTabView. Manual Segment Edit — Analysis Refresh Fix - Editing a segment's duration in RaceDetailView now cascades the time delta to all subsequent segments. - This keeps wall-clock `totalTime` (and all analysis cards) accurate after manual edits. Race Completion — Home Screen Card + Confetti - Completed real races on today's date now appear as a gold "RACE COMPLETE" card at the top of the home screen. - Confetti animation plays for 3 seconds on appear. - Tapping the card opens RaceDetailView directly. Race Name from Plan - After tracking a race started from a planned entry, the result now inherits the plan's name as `customName` instead of showing just the date. Strava Auto-Upload for Races - `StravaManager` gains `uploadRace(_ race: HyroxRace)`: generates TCX via `TCXExporter`, uploads to Strava's file endpoint. - Fallback to manual activity creation if TCX upload fails (retries once after 60 s). - Called automatically from `RaceManager.finishRace()` for real races (not training/sim) when Strava is connected. Field Distribution — Data-Driven Running & Station Curves - All three tabs (Overall, Running, Stations) now use real benchmark percentile data instead of fixed time fractions. - HYROX Solo (Open/Pro Men/Women): uses `HyroxSegmentProfile.runTotal` / `.workTotal` / `.total`. - Deadly Dozen: runs = sum of per-journey percentiles; stations = sum of per-labour percentiles. - HYROX Doubles: fraction-based fallback (no segment data available). - Previous DD running mean was ~16:30 for Pairs Men (wrong: 0.31 × total). Correct value is ~26:35 (sum of 12 journey p50 values). - DD division picker switched from `.segmented` to `.menu` style — full labels now visible, no more truncation. **Build 6** · 11 June 2026 iPhone Race — Crash Recovery Alert - After an app crash during a live race, the app now detects the saved recovery snapshot on next launch and shows an alert offering Resume or Discard. - Watch: Discard button now calls `RaceManager.discardRecoverySnapshot()` instead of manually removing two UserDefaults keys. Live Workout Companion — Local Timers & Staleness Detection - Block- and session-elapsed timers on iPhone now tick locally using time anchors sent by the Watch (`blockStartDate`, `sessionStartDate`), so the display stays smooth even when Watch updates are infrequent. - Staleness indicator: companion header turns gray after 15 s without a Watch update; turns yellow when the Watch reports paused. - `isPaused` flag added to `LiveWorkoutUpdate` — elapsed timers freeze when the Watch is paused. Live Workout Signals — Delayed-Delivery Guard - `sendWorkoutStartedSignal`: includes `sentAt` timestamp; receiver ignores signals older than 10 minutes, preventing a queued transferUserInfo from spuriously triggering a "workout started" state after reconnect. - `sendWorkoutEndSignal`: now carries the plan ID; receiver only clears live state if the ID matches the currently-active plan. Feedback Prompt — Snooze Fix - "Maybe Later" now stores a snooze timestamp; the prompt is suppressed for 14 days after snoozing. Previously it reappeared on every launch. - Feedback button correctly marks the prompt as seen AND opens the URL in one tap (was: only opened URL but didn't suppress future prompts). iPhone Race Finish — Pro Upgrade Prompt & Undo Cleanup - Pro upgrade sheet now appears 1.2 s after finishing a race (if `shouldShowProUpgradePrompt` is true). - Undo timer, button, and snapshot are now cleared immediately when the race transitions to `.finished`, preventing a stale undo button from appearing on the results screen. AI Plan Prompt — DSL Grammar Cheat-Sheet - A 27-line DSL grammar reference is now prepended to every AI prompt, giving the model a precise spec for block syntax, indentation, weights, paces, and run intervals. - Run pattern robustness rule updated to cover the `Run <n>x<dist>` interval form. DSL Parser — Tolerant Import - Invalid block lines no longer abort the entire import; they are now collected as warnings and skipped. The plan is returned with a `warnings` array. - If more than 10 lines are skipped, the parser suggests switching to Phase-by-Phase mode. - `importFromJSON` / `TrainingPlanImporter` return type updated to `Result<(plan:, warnings:), ImportError>`. UI Timers — RunLoop.common - All UI-driving timers now run on `RunLoop.main` in `.common` mode so they keep ticking while the user scrolls a list or drags a scroll view. - Affected timers: `undoTimer`, `cadenceSamplingTimer`, `autoDetectTimer`, `durationTimer` (RaceManager) and `displayTimer` (WorkoutSessionManager). Watch Entitlement — iCloud Key-Value Store - Added `com.apple.developer.ubiquity-kvstore-identifier` to the Watch App entitlements, enabling `NSUbiquitousKeyValueStore` for standalone Watch race persistence. Strava API — Breaking Changes & Enhancements - `disconnect()`: endpoint updated from `oauth/deauthorize` to `oauth/revoke`; token now sent in the JSON body instead of the Authorization header. - `uploadTCXFile()` / `createManualActivity()`: `type` / `activity_type` fields replaced with `sport_type` (Strava v3 breaking change); values updated to PascalCase (`Run`, `HIIT`, `WeightTraining`). - Mixed HYROX workouts (runs + stations) are now uploaded as `HIIT`; pure strength workouts upload as `WeightTraining`. - New `uploadWeightTrainingJSON()`: uploads strength-only workouts via Strava's structured JSON format with full set/rep/weight/duration data and `exercise_type` constants (e.g. `BARBELL_BENCH_PRESS`, `SLED_PUSH`, `WALL_BALL_SHOT`). Watch Settings — Division/Category Not Persisting - Fixed bug where changing the Solo/Pair division on the Watch did not update `RaceManager`. The Done button now writes the selected division to the format-specific UserDefaults key (`gritrace.ddCategory`, `gritrace.dekaCategory`, `gritrace.athxCategory`) in addition to the generic `gritrace.watchDivision` key. Training Load — TSB Expandable Chart - TSB (Form) metric tile is now tappable and expands to show a full TSB chart. - Chart shows positive TSB (green area, "Fresh") and negative TSB (red area, "Fatigued") with gradient line, zero rule, and today marker. - Legend explains Fresh / Fatigued zones; subtitle shows today's TSB value in green/red. Race Planner — Simulation Navigation Fix - "Zum Race Planner wechseln" from a training session that was saved as a simulation now reopens the existing simulation instead of creating a new blank plan. - A pre-generated `simulationRaceId` UUID links `TrainingSession.linkedRaceId` to `HyroxRace.id` at save time, so the link is consistent regardless of save order. - `TrainingSession` model: added `linkedRaceId: UUID?` field. Plan Progression Chart — Smaller, More Frequent Dots - Actual readiness dots reduced: normal `56 → 16`, current week `100 → 28`. - New small dots (`symbolSize: 9`, green) added to the planned readiness curve across all weeks (past and future), giving a denser dot pattern along the plan line. - Legend "Actual" circle updated to match the new smaller size. **Build 4** · 05 June 2026 Watch App Launch Hang Fix - Fixed Watch app silently failing to open after several days of use (no crash, just won't launch). Root cause: synchronous file I/O + JSON decoding during `RaceStore.init()` and `WorkoutSessionManager.init()` ran on the main thread during the first frame render. As race history and workout plans accumulated, the launch eventually exceeded the watchOS watchdog limit (~5 s) and the system silently killed the app. - `RaceStore.init()` now defers `migrateIfNeeded()` and `load()` to a Task. Races appear via @Published once decoded. - `WorkoutSessionManager.init()` now defers `loadPlans()` and `restoreFromCheckpointIfAvailable()` to a Task. Plans appear via @Published once decoded. Home Tab — Today's Workout Card Redesign - Exercise list is now always visible directly on the card (previously hidden behind a chevron that overlapped the card-minimize button). - Tapping the card header now opens the full session detail sheet. - Skip and Complete action buttons now show labels next to their icons for clarity. Workout Builder — Rep & Pause Fixes - Exercises added from the library now always seed a numeric rep suggestion parsed from the exercise default (handles "10", "8-12", "12 each side" etc.), so the card never shows an exercise with empty reps. - Consecutive pause blocks in builder-generated workouts are merged into one. The same merge is now applied when the block editor saves session changes (`updateSessionBlocks`) and when a session is updated manually, so duplicate rest blocks no longer appear after edits. Plan Import — Compact AI-Friendly DSL - New text format ("DSL") for importing AI-generated training plans, ~5× shorter than the equivalent JSON. Example: `== Week 1 (base) — Foundations` `Mon strength 60min moderate` ` Bench Press 4x8-10 @60kg rest90 — control descent` ` Run 5km @5:30 easy` `Thu rest` - Supports exercises (sets×reps or sets×seconds), runs (distance + pace + intensity), pauses, race-format stations, and supersets via `Superset:` block. - The existing JSON import still works — the importer auto-detects whether the input is JSON or DSL and routes to the right parser. Triple-backtick code fences from ChatGPT/Claude are stripped automatically. - Backed by 21 unit tests covering all block types, weeks, supersets, error cases, comments, and code-fence handling. AI Prompt Builder — Output Format Toggle - In the AI plan import flow, the prompt-copy step now has a "Compact format" toggle (default ON) with an inline explanation. ON = the prompt asks the AI to output in the new DSL; OFF = classic JSON. - The toggle changes both the human-readable instructions and the schema example appended to the prompt, so ChatGPT/Claude know exactly which format to produce. - Both formats remain fully supported by the importer — switching the toggle never breaks already-pasted plans. AI Prompt Builder — Stricter Guidance - Multi-race section now explicitly states the A/B/C priority is the athlete's user-assigned label and must NOT be reinterpreted by the AI (fixes feedback where Claude/ChatGPT downgraded a near-term user-tagged A-Race to "B/C" based on its own judgment). - "Generate the plan until the A-Race date" clarified to "until the LATEST listed race date" so the AI covers the whole multi-race window. - New DSL robustness checklist embedded in the prompt (one-line rule, indentation, weight/pace patterns, self-scan before returning). - For plans estimated over 8 weeks, the prompt now warns about typo risk and suggests pointing the user toward the "Phase-by-Phase" import mode before generating the DSL block. AI Plan Import — Configure & Paste Step Polish - The "Training Days / Week" number picker is replaced by a clickable weekday picker (Mon–Sun pills). Pre-fills from your existing plan's weekly schedule. The prompt now sends "Training days: Mon, Wed, Fri, Sat (4/week)" with an explicit rule that the AI must place sessions only on the chosen weekdays. - Paste step copy/labels are now format-neutral: "Paste the AI's response", "Validate Plan", "I have the plan →". The body text mentions both DSL and JSON, since the importer auto-detects either format. Phase-by-Phase paste copy was updated too. DSL Parser — Robustness for Real AI Output - Real ChatGPT/Claude plans surface notation we hadn't covered. Fixed so the following common forms now parse correctly: - `Pause 2min`, `Pause 45sec` — long-form duration suffixes - `Run 4x100m @4:30 hard`, `Run 5x1km @4:55 hard`, `Run 4x1.5km @4:55 hard` — interval syntax expands into N separate Run blocks - `Walking Lunges 3x16 @2x24kg` — paired-dumbbell weight now parses as per-hand kg (24, not misread as sets×reps) - `Farmers Carry 100m @2x24kg` — distance-based movements without sets×reps now parse as exercises with distance + weight - `Run 1km @4:50 hard` — `hard` intensity keyword is now recognized (treated as vo2max) - The exercise parser switched to token-based matching so weight tokens like `@2x24kg` can no longer be misinterpreted as a sets×reps token. - Error messages now say "Plan format error: …" instead of "Invalid JSON: …" — the previous wording confused users when a DSL plan failed to parse. - 8 new unit tests cover all the new patterns.
improvedMay 20, 2026

Version 1.0.7

**Build 12** · 20 May 2026 ATHX Zone-Specific Planning & Tracking - Race Planner: ATHX plans now include zone-specific targets (Strength weight progressions, Endurance distance goals, MetCon X time caps) with AI-generated periodisation. - Phone Race Tracker: ATHX live tracking shows zone-specific UI — weight inputs for Strength, distance tracking for Endurance, timer with cap for MetCon X. Zone scores saved automatically. - Plan Analysis: ATHX training plans show zone breakdown charts (Strength volume, Endurance distance trends, MetCon X time progression) instead of run/station analysis. - Today Tab: ATHX sessions display zone-specific detail (target weights, distances, time caps) instead of generic exercise lists. Granular Muscle Groups in Heatmap & Recovery - Muscle heatmap and recovery tracking now use fine-grained muscle groups (e.g. Front Delts, Rear Delts, Lateral Delts instead of just "Shoulders") for more accurate load distribution. - Training load calculations use granular muscle mapping for all exercise types. Watch Workout Controls Redesign - PAUSE button enlarged to equal width as DONE button — much easier to hit during workout. - DONE button now requires a 1-second long press to prevent accidental block skips. - Back and Overview buttons moved to a secondary row below. Cooldown Jump-Back Bug Fix - Fixed bug where Watch would jump from cooldown view back to the last exercise when Phone sends a block structure update during workout. - Cooldown block is now preserved when remote block updates arrive, preventing the view from resetting. - Fixed: `isCooldownBlock` flag now resets when a remote update replaces the current block, preventing session from ending prematurely. Backup v2 — Workouts & Performance Log - Backup now includes all saved workout results and performance log entries (previously only races and training plans). - Restoring a backup re-imports workouts, performance log, and triggers training load recalculation. - Fixed: Restoring a backup twice no longer duplicates workouts or performance log entries — merges by ID. - Fixed: Training load re-bootstrap now starts immediately after restore instead of waiting for user navigation. Exercise Defaults Always Saved - Exercise weight/reps values are now saved per exercise after every workout completion — regardless of whether tracked on Watch or iPhone, from a plan or quick workout. - Values are synced between Watch and iPhone so exercise defaults are consistent across devices. Plan Import — Date-Based Modification & Flexible JSON - "Modify Specific Weeks" replaced with "Modify Specific Days" — now uses two DatePickers (From/To) instead of week number pickers, so users can modify even just 2-3 days without replacing entire weeks. - "Validate & Replace" button: when modifying specific days, validation and import happen in one step — no extra "Import Plan" confirmation needed. - Day-level merge: `replaceDaysInActivePlan` only touches days within the selected date range. Days outside the range are preserved even within the same week. - JSON parser now accepts three formats: `{"weeks": [...]}` wrapper, a single week object `{"weekNumber": 1, "days": [...]}`, or a bare array of week objects. No more "Invalid JSON" when pasting a single week from AI output. - Fixed: Markdown code fences (`` ```json ... ``` ``) are now automatically stripped before parsing. AI output often includes these despite being told not to. - Paste step shows a merge mode indicator with the selected date range. - AI prompt for partial modification now includes: date range, current content of the days being replaced, surrounding week context, and a compact output example. - Manual JSON import sheet also gains a "Replace Weeks Only" toggle for the same workflow. ATHX HR Chart Fix - Fixed: Race detail HR chart used `max(1, runCount)` which created a fake run iteration for ATHX (0 runs). - Now uses the actual number of stations/zones for loop bounds. Translation Fix - Fixed "Back" button not translating to German in certain views. **Build 11** · 19 May 2026 Auto-Merge Overlapping HealthKit Workouts - When tracking a workout on iPhone while Apple Watch (or Garmin/Polar/COROS) simultaneously records a separate workout, the overlapping external workout is now automatically linked and hidden. - Detection: after a GritRace workout finishes, the app scans HealthKit for external workouts with >50% time overlap and links them to the GritRace result. - Workout History: linked external workouts are hidden from the list to avoid duplicates. GritRace workouts with merged HR data show a pink "HR Merged" badge. - Training Load: linked external workouts are excluded from TRIMP/strain calculations to prevent double-counting. - Data model: new `linkedHKWorkoutUUIDs` field on WorkoutSessionResult (backwards-compatible with existing saved data). **Build 7** · 19 May 2026 Watch App Crash Fix - Fixed Watch app crashing on launch due to `Task.detached` violating `@MainActor` isolation (`SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor` is enabled). - `refreshTodayWorkout()` in GridRaceWatchApp and `refreshCompletedSessionIds()` in TrainingViews now use `Task {}` instead of `Task.detached`, inheriting the MainActor context correctly. **Build 7** · 19 May 2026 ATHX UI Polish & Zero-Run Guards (continued) Race Planner — ATHX Display Fixes - Plan Summary hides the "Runs" row for ATHX (runCount=0); station label shows "Zones" instead of "Stations". - Forward Calculator (Pace → Time): run pace input card hidden for ATHX; breakdown shows "Zones" label. - Reverse Calculator (Time → Pace): shows "ESTIMATED ZONE TIME" header instead of "REQUIRED RUN PACE" for ATHX; run-related rows hidden. - AI Coach prompt now describes ATHX as "3 zones (no runs)" instead of "0×0m runs". Watch — ATHX Format Display - Format picker subtitle shows "3 Zones" instead of "0× runs · 0m" for ATHX. - Active format badge shows "3 Zones" instead of "0× 0m" for ATHX. Goal Time Estimation - ATHX goal time estimation no longer requires running pace data — estimates from zone time defaults alone, so users without run history still get auto-estimated goals. **Build 7** · 19 May 2026 ATHX UI Polish & Zero-Run Guards ATHX Race Comparison - New "Zone Scores" section in race comparison view: side-by-side Strength (kg), Endurance (m), and MetCon X (time) with bar charts and best-value highlighting. - New ATHXZoneCompareRow component for non-time value comparisons with accessibility labels. ATHX Race History Cards - Race cards for ATHX races now show Strength (kg), Endurance (m), and MetCon X (time) instead of run/roxzone/station stats. ATHX Share Cards - Share cards for ATHX races show zone scores (Strength kg, Endurance m, MetCon X time/DNF) instead of run/station stats. - Footer text shows "3 Zones · Strength · Endurance · MetCon X" instead of run/station counts. ATHX Log Past Race - New zone score input fields when logging ATHX races: 1RM Strict Press, 3RM Back Squat, 5RM Deadlift (Strength), Total Distance (Endurance), Completion Time + completed toggle (MetCon X). - Zone scores saved to race as ATHXZoneScores. ATHX Dashboard Benchmark - Performance Benchmark card now shows ATHX zone-level percentile tiers (Elite/Advanced/Intermediate/Beginner) based on average zone percentile, instead of returning nil. ATHX Race Planner - Goal pill label shows "Zones" instead of "Stations" for ATHX format. Zero-Run Guards (ATHX crash fixes) - AnalyseTabView: RunDriftPreview and RunDriftCard guard `runCount > 0` to prevent range crashes for ATHX (0 runs). - RaceComparisonView: run total row, run header section, and run detail rows all wrapped in `if fmt.runCount > 0`. TCX Export - ATHX distance now uses actual endurance meters from zone scores instead of format-level totalRunDistanceKm. - Run distance per lap returns 0 instead of 1000 for formats with no runs. Translations - New DE translations: "Endurance" → "Ausdauer", "MetCon X" → "MetCon X", "Zones" → "Zonen". - New localized strings: STRENGTH, ENDURANCE, METCON X, DNF, Strength Zone, Endurance Zone, MetCon X Zone, Total Distance, Completed (under time cap), 3 Zones description. **Build 7** · 19 May 2026 Full ATHX Integration & Phone Tracking Fixes Phone Workout Tracker Performance - Fixed significant lag when tracking workouts on phone only (no Watch): timer no longer re-renders the full exercise list every second. - Timer isolated into its own view (PhoneWorkoutTimerBar); blocks cached and only refreshed on planVersion changes. Rest Timer Fixes - Rest timer now continues counting in background: uses absolute end-date instead of countdown, syncs remaining time on foreground re-entry. - Rest timer no longer triggers between exercises within a superset — only fires after the last exercise in the group. TextField Reps Deletion Fix - Fixed bug where deleting reps (e.g. "11" → "6") was impossible because onChange triggered an update loop on every keystroke. Now only fires when the value parses to a valid number. ATHX-Specific Training Plan Generation - New periodized strength builder: Base (4×8 hypertrophy) → Build (5×5) → Peak (1RM/3RM/5RM race specificity) → Taper (3×5 maintenance). Includes Push Press + RDL accessories. - New MetCon X conditioning builder: full 6-movement circuit at category-specific loads (Ski-Erg, GTOH, Sandbag, BJO, Lunges, Burpee BJ) with phase-scaled training fractions (40–70%). - New endurance interval builder: alternating Run/Row at category swap distances (500m/750m/1000m) with phase-scaled interval counts. ATHX AI Coach Integration - AI prompt builder includes full ATHX-specific training guidance section (3 zones, periodization, zone transitions). - Coach system prompt updated to "elite functional fitness training coach specializing in HYROX, ATHX, DEKA, and Deadly Dozen." ATHX Race Detail View - New ATHX Zone Scores card: shows Strength (kg), Endurance (m), MetCon X (time) with color-coded percentile badges ("Top X%"). - AI analysis prompt includes zone scores with percentile breakdowns instead of empty run splits. - On-device race briefing (FoundationModels) uses zone-balance focus for ATHX instead of pacing consistency. - CSV export includes ATHX zone scores in meta header. - Summary cards hide "RUN" card for ATHX (runCount = 0). ATHX Achievement System - Elite Finish: all 3 zone percentiles ≥ 75%. - Advanced Finish: all 3 zone percentiles ≥ 50% (but not all ≥ 75%). - Clean Sheet: no zone below median (p50). Translations - New DE translations: "ATHX ZONE SCORES" → "ATHX ZONEN-ERGEBNISSE", "Endurance" → "Ausdauer", "MetCon X" → "MetCon X". **Build 7** · 18 May 2026 ATHX Games Format Integration - New race format: ATHX Games — a 2.5-hour structured fitness competition with 3 scored zones (Strength, Endurance, MetCon X). - Full ATHXFormat implementation with 15 categories: Lite / ATHX / Pro × Individual M/F + Pairs M/F/Mixed. - Category-specific weights, reps, and distances for all MetCon X movements (2026 season data). - Onboarding: ATHX category picker (Lite / ATHX / Pro) with descriptions in the setup wizard. - Race Calendar: 9 ATHX events for 2026 season (Dublin, Glasgow, Copenhagen, Birmingham, Barcelona, Marseille, Liverpool, Amsterdam, World Finals Lisbon). - Race Planner: zone-based time distribution using default zone durations (Strength 20min, Endurance 22min, MetCon X ~12min). - Log Past Race: ATHX category selection when logging ATHX races. - Training Plan: ATHX-aware run fraction (30%), division-by-zero protection for formats with no runs. - Station Trainer: ATHX zones available as trainable stations. - Watch App: ATHX category display and settings. - Widgets: ATHX format filter, color (purple), and recommendations. - Dashboard: graceful handling of ATHX in benchmark/weakness/recommendation cards (no benchmarks yet). ATHX Race Tracking (Zone-to-Zone Flow) - Race state machine now supports zone-only formats (no runs): starts directly in Zone 1 instead of Run 1. - Zone-to-zone transitions with official rest times: Feed Zone (10 min after Strength), Recovery Zone (30 min after Endurance). - Skip rest button works for ATHX: advances to next zone immediately. - Watch transition overlay shows "FEED ZONE" / "RECOVERY ZONE" labels and previews the next zone name. - iPhone transition overlay shows ATHX zone labels and next zone preview instead of "RUN N". - Predicted finish time calculation handles zone-only formats (no division by zero on runCount=0). - Race Sim in training plans: station count capped to actual format stations, run blocks skipped for ATHX. - Brick Run removed from ATHX peak phase training pattern. - Session description uses "aerobic base for race-day endurance" instead of "full 0 m of race-day running" for ATHX. ATHX Live Zone Scoring - New ATHXZoneScores model: tracks Strength (1RM Press + 3RM Squat + 5RM Deadlift → Total kg), Endurance (total meters), and MetCon X (completion time). - Zone score input during transition rest (Feed Zone / Recovery Zone): enter your scores while resting between zones. - Watch: compact +/- stepper input for lift weights (5 kg steps) and endurance meters (100 m steps). - iPhone: larger input with labeled rows per lift (2.5 kg / 5 kg steps), endurance meters, and real-time percentile badges. - Estimated percentile ranking: "~Top X%" badge based on benchmark data per category (Lite/ATHX/Pro × M/F). - Benchmark data for 6 category/gender combinations across all 3 zones (estimated from 2025/2026 season structure, easily updatable). - Zone score summary pill on Watch station area view (zones 2+) showing completed zone scores at a glance. - iPhone station area shows completed zone scores with percentile badges during zones 2 and 3. - MetCon X time auto-captured from zone duration on race finish. - Full score card on race finish screen: all 3 zone scores with individual lift breakdown, distance, time, and percentile estimates. - Zone scores persisted on HyroxRace (athxZoneScores field) — saved with race results and synced to paired devices. - ATHX-specific race day checklist: venue hints (indoor, lifting shoes, chalk) and zone recovery tips. - Share card hides roxzone stat for ATHX races. - ATHX category validation on onboarding Next button. **Build 7** · 17 May 2026 Auto-Station Detection Fix (Race Tracking) - Auto-station detection is now OFF by default — users must opt-in via Watch Settings. - Raised minimum run duration before auto-detect can trigger from 24s to 45s for DD/DEKA short runs. - Short-distance formats (<800m) now require 18s of continuous low cadence (was 12s) to reduce false triggers. - Added diagnostic logging when auto-detect fires (run number, duration, cadence) for future debugging. **Build 2** · 17 May 2026 Exercise Images Everywhere - Added 107 exercise images to the asset catalog (101 accessory exercises + 6 station-specific: Rowing, SkiErg, Devil Press, Overhead Carry, Front Carry, Sled Push/Pull). - Exercise thumbnails now appear in all views: workout cards, training plan sessions, quick workouts, workout builder, dashboard widgets, and the muscle group detail sheet. - Tapping an exercise name or image opens the exercise detail sheet with instructions, muscles, and equipment. Station Name Alias System - Centralized exercise resolution via `resolveExercise(named:)` and `exerciseImageId(for:)` in TrainingPlanManager. - 22 station name aliases map DD/HYROX/DEKA station names (e.g. "KB Farmers Carry", "Wall Balls", "Sled Push") to their matching accessory exercise for image display and detail sheets. - 8 station image overrides provide images for station-only exercises without accessory counterparts. Muscle Group Detail Sheet Rework - Tapping a muscle group now shows time-series progression charts instead of static bars. - Segmented time range picker (4W / 3M / 6M / 1Y / All). - Stacked bar chart showing weekly volume per detail muscle. - Individual trend lines per detail muscle with area charts and trend arrows. - Exercise list with thumbnails and tap-to-detail. Analyse Tab - Training history card moved to the top of the training stats section. Granular Muscle Group Heatmap - Added 17 detail muscles (e.g. Quadriceps, Hamstrings, Lats, Biceps, Triceps) that map to the 7 high-level muscle groups. - Exercise Library and Training Plan views show detail muscle tags (primary + secondary) on each exercise. - Fixed "Back" translation — was "Zurück" (navigation back), now correctly "Rücken" (body part). Run Flash Overlay on Watch - During run workouts on Apple Watch, a fullscreen flash overlay now appears on pace status changes (Good Pace / Too Slow / Too Fast) showing the current pace. - Kilometer milestones trigger a flash showing the km number, split pace, and current heart rate. - Flash auto-dismisses after 2.5 seconds with a smooth scale+opacity transition. Exercise Instructions - Every exercise in the library (101 total) now has a detailed step-by-step execution instruction. **Build 1** · 13 May 2026 Exercise Detail on Tap - Tapping an exercise name in a workout now opens the exercise detail sheet with description, instructions, target muscles, equipment, and an image placeholder. - Users can upload their own exercise photos for any exercise (not just custom ones) — images are stored locally. Strava Export Fix: HR, Cadence & Power - Fixed: Heart rate and other HealthKit data were missing from Strava uploads because the workout start time was mismatched (search used completion time instead of start time). - TCX exports now include running cadence (steps/min) and running power (watts) from HealthKit. - Calories and distance are now taken from the actual HealthKit workout instead of estimates. - Search window for matching HealthKit workouts expanded from ±5 to ±10 minutes. Muscle-Group Specific Recovery - Recovery estimation is now per muscle group instead of a single whole-body timer. - Exercises in completed sessions are resolved to their target muscles (primary = full recovery, secondary = 50%). - Running → legs + posterior chain + core; Race sim → all muscle groups. - If a muscle group is trained again before full recovery, remaining time is partially carried over. - Today tab shows individual recovery bars per muscle group, sorted by least recovered first. Z2 Pace Filter Applied Globally - The 8:00/km pace floor for Z2 classification is now enforced everywhere: classification, charts, averagePace(), bestPace(), progression cards, race predictor, and plan estimation. - Walking with elevated heart rate is always classified as warmup, never Z2.
improvedMay 11, 2026

Version 1.0.6

**Build 1** · 11 May 2026 Z2 Pace Now Based on Heart Rate Zones - Run intensity classification (Z2/Tempo/VO2max) is now based on actual heart rate data from HealthKit when available, using the user's configured HR zones. - Pace-based classification remains as fallback when no HR data exists. - Walking workouts are no longer classified as "Run" sessions — mapped to "Recovery" instead. - Z2 pace calculations cap at 8:00/km (480s) as additional safety net. - Fitness Trend chart filters tightened to exclude walking-speed data. Recovery Timer Merged into Tip Card - The recovery timer is now integrated into the recommendation ("Tip") card on the Today tab instead of being a separate card. - Shows a compact progress bar with remaining time below the daily training recommendation. - Removes visual clutter — one card for both training guidance and recovery status. Intensity Indicator (Read-Only) - The intensity picker in the session detail and editor views is now a non-interactive display instead of a changeable control. - Shows the planned intensity (Locker/Moderat/Schwer/Max) as a colored indicator for reference. Apply Workout Replacement to Entire Plan - When replacing a session with a saved or generated workout, the app now asks whether to apply the same replacement to all similar future sessions (same title/type). - Uses the same multi-select dialog as the exercise editor — pick which sessions to update, skip, or apply to all. No Consecutive Pause Blocks in Workouts - Fixed: strength/accessory sessions could have two pause blocks in a row (e.g. warmup activation + light set, or cooldown stretch + foam rolling). - Consecutive pause blocks are now merged into a single block with combined duration and joined descriptions. AI Import Day-of-Week Fix - Fixed: AI-imported plans had mismatched day labels when the import happened on a non-Monday (e.g. importing on Thursday caused "Monday" to show Thursday's date). - All three AI import paths (single JSON, phased JSON, multi-phase merge) now align the start date to Monday before assigning dates. - Existing broken plans are auto-corrected on load — `dayOfWeek` is now derived from the actual date during decoding, so no re-import is needed. Plan Week Alignment Fix - Training plan weeks now always start on Monday (Mon–Sun), regardless of the day the plan was created. - Existing plans are automatically migrated on launch — no need to recreate. - Race day is now correctly placed on the actual weekday in the plan after migration. - If the race date falls past the plan's last day after alignment, an extra week is appended automatically. Onboarding: Getting Started Flow - After the app tour, new users now see a "Getting Started" sheet with three guided actions: Create Training Plan, Log a Past Race, or Browse Upcoming Races. - "Create Training Plan" navigates to the Plan tab and opens the setup wizard; "Log a Past Race" opens the race logging view; "Browse Upcoming Races" navigates to the Races tab. - Updated final tour step text to transition smoothly into the Getting Started sheet. Smarter Plan Creation Defaults - Focus station pre-selection no longer picks stations when fewer than 2 races are logged — avoids misleading suggestions. - Weekly running km is now pre-filled from HealthKit data (4-week average, rounded to nearest 5 km) when creating a new plan. Recovery Timer - After completing a workout, a recovery estimate is calculated based on session type, intensity, duration, and readiness score. - A recovery timer card appears on the Today tab showing a circular progress ring (red → yellow → green), remaining time countdown, and session details. - Recovery state persists across app launches and auto-dismisses when fully recovered.
improvedMay 8, 2026

Version 1.0.5

**Build 8** · 08 May 2026 Progression Chart Redesign (Plan Tab) - Replaced the text-only progression card with a tabbed chart card: Pace / Strength / Load. - Pace tab: line + area chart of Zone 2 pace across the last 12 sessions, Y axis inverted (faster = higher), trend stat showing delta vs. early sessions (e.g. "+15s/km"), Latest / Trend / Best stats row. - Strength tab: scrollable exercise chip picker (exercises with ≥3 logged sessions auto-populated), weight progression line chart per session, Current / Gain / Sessions stats. - Load tab: bar chart of planned/completed training hours per week from the active plan, bars phase-coloured (Base / Build / Peak / Taper / Race Week), legend + average weekly hours stat. - Each tab shows a contextual empty state when no data is available yet. Field Distribution Chart Fixes (Analyse Tab) - Fixed chart drawing in a single flat colour despite the coloured legend — zones now fill correctly (elite / top-30% / mid / back) with opacity based on the athlete's position. - topPercent formula corrected: now properly gives small values (e.g. 3%) to elite athletes and large values to slower athletes. - Division picker is now selectable for HYROX (Open Men/Women, Pro Men/Women, Doubles, Mixed Doubles) in addition to Deadly Dozen. - Auto-detects the user's division from their most recent HYROX race on load; falls back to UserDefaults if no race is logged. Readiness Adaptation Improvements - Watch build failure fixed: GRNotificationCenter references in TrainingPlanManager.swift guarded with #if os(iOS). - Banner no longer re-appears multiple times per day (added shown-today gate via UserDefaults). - "Apply Suggestion" now pre-computes the adapted session before showing the banner — tapping the button commits it reliably; previously could fail silently for certain intensity combinations. - Banner now shows a plain-text description of the proposed change (e.g. "'Interval Run': 2 blocks removed, intensity → Moderate. ~45 min") so you can review before confirming. - Readiness thresholds updated to science-backed values: Green ≥70 (no adaptation needed), Yellow 55–69, Orange 40–54, Red <40. **Build 8** · 06 May 2026 In-App Notification System & Readiness Adaptation - New GRNotificationCenter: slide-in banner from top of screen (swipeable, auto-dismisses after 8s, supports action buttons). - Readiness Adaptation re-enabled: when HRV/sleep readiness is Yellow/Orange/Red, the app posts a banner asking "Adapt Training?" — you confirm before anything changes. No auto-adaptation. - Yellow (60-79): reduces volume ~20% and lowers intensity. Orange (40-59): replaces session with active recovery. Red (<40): rest day recommended. - After adapting, a second banner shows with a "Revert to Original" button so you can always go back to the planned workout. - Toggle in Plan Settings → Readiness Adaptation (off = no prompts, ever). - WorkoutBuilderView now shows a readiness refresh button (waveform icon) when a score is available. Bug Fixes & Stability - Fixed potential crash in performance chart date calculation (Calendar.date(byAdding:) now properly guarded instead of force-unwrapped). - Hevy CSV import now supports 9 date formats: ISO, US (MM/dd/yyyy), EU (dd.MM.yyyy), Asian (yyyy/MM/dd), and more — previously only 2 formats were tried, causing silent import failure for non-German/non-ISO exports. - Hevy CSV: when dates can't be parsed, shows a specific error message with the supported formats instead of a generic "empty plan" error. - AI plan prompt now correctly handles "no equipment" (bodyweight-only) and "full gym" cases — previously only the partial selection case was described to the AI. Race Day Placement Fix - Fixed race day not being blocked correctly for B-Race and C-Race weeks during plan generation. - B-Race weeks now properly block the race day and day before (previously only worked for A-Race weeks with `.raceWeek` phase). - C-Race (training race) weeks now block the race day itself but allow training the day before. - Fixes race appearing on wrong day after plan update/regeneration. AI Plan Import — Equipment & Priority Selection - Added equipment picker to the AI plan import configuration step. - Lets users select which equipment they have access to before generating the prompt. - Equipment info is included in the AI prompt so the generated plan only uses available equipment. - Added Training Focus picker (Race Focused / Hybrid / Muscle Building) to the AI import. - Priority is now described with clear instructions in the prompt (e.g., "Primary goal is muscle hypertrophy. Include dedicated strength/hypertrophy sessions..."). - Both settings prefill from existing plan config when available. Workout Import (Hevy CSV) - New CSV import for workouts from Hevy, Strong, FitNotes, and similar apps. - Flexible column detection — parses exercises, sets, weights, reps, RPE, and dates. - Creates completed sessions on the correct dates, grouped by workout name. - Accessible via Plan Detail → Menu → Import → "Import Workouts (CSV)". AI Plan Import — 3 Modes - New mode selector in the AI plan import flow: Full Plan, Phase by Phase, and Template + Progression. - Full Plan: existing one-prompt approach for capable models like Claude Opus. - Phase by Phase: separate prompts per training phase, paste each separately, app merges automatically. - Template + Progression: AI creates one template week per phase with progression rules, app auto-generates the full plan with weight/rep/pace increases. - Phase labels auto-calculated from plan duration. Run Performance Analysis - Added detailed running metrics to workout stats: Power (W), Cadence (spm), Stride Length (m), Ground Contact Time (ms), Vertical Oscillation (cm), VO₂max, HR Recovery. - New combined Run Performance Chart with HR, Pace, and Elevation layers — individually toggleable via pill buttons, normalized Y-axis with area marks for elevation. - On-device AI analysis (Apple Intelligence / FoundationModels) for running workouts: generates 8-section coaching report covering pace strategy, HR zones, elevation impact, running mechanics, and actionable recommendations. - New HealthKit methods: fetchElevationProfile, fetchPaceProfile, fetchRunningMetrics, fetchLatestVO2Max, fetchHRRecovery — all derived from workout route and statistics data. App Icon Fix - Fixed app icon for App Store: separate Light, Dark, and Tinted variants with correct backgrounds and no alpha channel. - Resolves App Store Connect rejection errors for missing icon, alpha channel, and missing dark mode variant. Workout Tracking Audit Improvements - Added dedup to handleRemoteSetCompletion: prevents double-processing if HK command replays (hash of weight/reps/duration/setIndex). - addExtraSet() now appends a matching ExerciseSet to the exerciseSets array, keeping it in sync with type.sets count. - jumpToBlock() resets superset progress and locked totals when jumping to a different superset group. - JSON encoding for live updates throttled to 1Hz (timer still ticks 4Hz for smooth UI counters). - LiveWorkoutUpdate now includes restTimerRemaining and restTimerDuration; iPhone companion view shows Watch rest timer overlay. - Session checkpoint for crash recovery: saves plan, block results, set data, and progress on every block transition and set completion. Auto-restores to paused state on next launch. - EMOM overall duration check: session auto-finishes when totalDurationMinutes is exceeded, preventing infinite EMOM loops. - HR samples collected during rest/transition phases are carried over into the next block's average (no longer lost between blocks). iPhone Exercise Defaults Display - When opening a session on iPhone, last-used weights/reps from ExerciseDefaultsStore are now applied to all exercise blocks. - New TrainingPlanManager.applyExerciseDefaults(sessionId:) mirrors the Watch-side toWorkoutPlan() logic: updates block-level weightKg/reps and per-set targetWeightKg/targetReps from stored defaults. - Only applies to planned/adapted sessions; already-completed sets (with actualWeightKg) are preserved. - Fixed: applyExerciseDefaults now only bumps planVersion when values actually change, preventing infinite re-render loops. Fix Superset Extra-Round Bug During iPhone Sync - Added superSetLockedTotalSets dictionary that records each superset block's total set count when first encountered during a workout. - Remote block updates (from iPhone edits or planVersion bumps) no longer change the set count mid-superset. - Locked totals are used in round-robin candidate checks, beginBlock() restoration, and handleRemoteBlockUpdate() reconciliation. - Enhanced: all blocks in a superset group are now locked on first encounter (not just the current block), preventing inflated set counts for not-yet-visited blocks. - addExtraSet() now updates superSetLockedTotalSets to keep the lock in sync. - Added lastRemoteBlockUpdateHash deduplication to prevent triple-processing of block updates from 3 delivery channels. - Fixes: doing a superset on Watch required extra rounds (e.g. 3 instead of 2) after any change on iPhone. Fix App Crash When Viewing Workouts - Removed initializeSetsIfNeeded() call from view body that caused infinite re-render loops when combined with applyExerciseDefaults. - Initialization and defaults application now runs once in .onAppear only. Strava Upload Improvements - "Tracked with GritRace" now appears at the top of the Strava description next to the workout name. - Added retry mechanism for TCX uploads: if TCX data is unavailable (HK hasn't synced from Watch yet), retries once after 90 seconds. - Fixes: auto-uploaded workouts were missing HR graphs because TCX upload failed before HealthKit data synced. Watch Exercise Defaults Fix - toWorkoutPlan() now applies ExerciseDefaultsStore values before sending to Watch. - Ensures last-used weight/reps from completed sessions appear as target values on the Watch, not the original plan values. - Per-set level: maps completed set data by set number for accurate per-set targets. - Fixes: Watch showed original plan weights (e.g. 8kg) instead of last-used weights (e.g. 24kg) for all exercises. Save Session as Workout - Long-press any session in the plan overview (both compact and detail view) → "Save as Workout" option. - Session detail sheet now has a "Save as Workout" button near the top. - Saves the session (with all exercises, sets, weights) to My Workouts for standalone reuse. - Name can be customized before saving; defaults to the session title. Alternative Training: My Workouts Integration - "Alternative Training" sheet now has a segmented picker: "Generate" (auto-generate) or "My Workouts" (pick a saved workout). - Saved workouts show Replace / Add Extra buttons inline for quick action. - Unified UX with the "Add Session" sheet which already had this pattern. AI Plan Import: Previous Plan Summary - When requesting a new AI plan, the prompt now includes a comprehensive summary of the previous/current plan. - Includes: plan duration, completion rate, session type breakdown, phase adherence, skipped session patterns. - Includes: run pace progression (zone2 + racePace), top 8 exercise weight progressions. - Instructs the AI to design a progressive follow-up plan based on strengths and weak areas. Fix Race Week Ghost Markers When Moving Races - markRaceWeeks() now clears all existing race week AND taper markers before re-marking, preventing ghost race weeks when a race date is moved. - Taper weeks now move with the race: A-Races get full taper + recovery, B-Races get mini taper + recovery, C-Races get marker only. - RacePlannerView alert now offers both "Update Races Only" (preserves progress, moves markers) and "Generate New Plan" (full re-periodization), matching PlanTabView and RacePlannerTabView. Exercise Weight/Reps Carry-Over Fix - Completing a training session now correctly propagates last-used weights and reps to all future sessions with the same exercises. - Fixed: adapted sessions were skipped during propagation — now included alongside planned sessions. - Fixed: UI did not refresh after propagation — planVersion is now bumped after both markSessionCompleted and updateSessionWithResults. - Added ExerciseDefaultsStore fallback in exercise card — "Last: X kg × Y" badge now appears even when PerformanceLog has no data, using the globally stored exercise defaults.
improvedMay 4, 2026

Version 1.0.4

**Build 11** · 04 May 2026 What's New View (1.0.4) - Added 6-item What's New screen for version 1.0.4: Strava Integration, Hardware Pause, Fitness Trends, Blank Training Plans, AI Plan Review, CSV Export & Share Cards. Fitness Trend — Rolling Windows & Timeframe Fix - Replaced ISO calendar-week grouping with rolling 7-day windows anchored to today. - Fixes the "weekly reset to zero" problem — every data point now covers exactly 7 days, the last window always ends today. - Charts now respond correctly to timeframe switching (4W/3M/6M/1Y) via explicit chartXScale(domain:). - Removed unit: .weekOfYear from Line/Area/Point marks so data plots at actual dates, not ISO-snapped positions. - HealthKit external workouts now fetched for 365 days (was 90) so 6M/1Y charts have data. - Readiness score history limit raised from 90 to 365 (ReadinessEngine + Models.swift saveHistory). - Breakdown table uses monthly aggregation for 6M/1Y (averaged per month, date format "Apr 26"). Badge Detail View - Tapping the Earned Badges card on the Today tab now opens a full detail sheet. - Shows all 7 badge types with icon, name, description, earned count, and which races earned each badge. - Unearned badges shown dimmed with locked styling. Badge Calculation Fixes - All 6 performance badges (Station King, Consistent Pacer, Elite Finish, Advanced Finish, Clean Sheet, Iron Streak) now require raceType == .race. - Training races with reduced volume can no longer trivially earn performance badges. - Iron Streak now verifies the race is actually part of the last-3 consecutive streak. **Build 6** · 03 May 2026 Hardware Pause (Crown + Side Button) - Pressing Crown + Side Button on Apple Watch now pauses/resumes workouts and races, matching native Workout app behavior. - Workouts: HKWorkoutSession state changes forwarded to WorkoutSessionManager via notifications. - Races: New RaceState.paused with full pause/resume support — timer stops, segment duration excludes paused time, total race duration adjusted. - Watch shows dedicated Paused screen (Resume + Stop) during race pause. - iPhone race tracker shows pause overlay with Resume button. - Live Activity shows "PAUSED" indicator. - Stopping a race while paused works correctly (restores state before ending segment). Per-Workout CSV Export - Each workout in history now has an "Export CSV" button for individual workout export. - Complements the existing bulk CSV export in the Workout History section header. Strava Auto-Upload Fix - Auto-upload from Watch now waits 60 seconds for HealthKit workout data to sync before uploading. - Previously auto-uploads had no time-series data because they fired before HKWorkout arrived on iPhone. Pace Alert Oscillation Fix - Pace coaching now uses hysteresis (wider threshold to enter off-target state, narrower to return on-target). - 15-second minimum cooldown between state changes prevents rapid toggling. - Applied to Watch (WorkoutSessionManager), iPhone run tracker (PhoneRunTrackerView), and iPhone phone run tracker (PhoneRunTracker). Elevation-Adjusted Training Load - TRIMP and strain calculations now factor in elevation gain (Minetti et al., 2002). - Elevation extracted from HKWorkout metadata (HKMetadataKeyElevationAscended) or flights climbed. - HR-based TRIMP: +3% per 100m gain (eccentric/neuromuscular load). No-HR estimation: +8% per 100m. - Power-based TRIMP unchanged (running power already captures elevation cost). Hiking vs Walking Separation - Hiking and walking now have distinct training load multipliers. - Hiking: TRIMP factor 1.0 / strain 0.8 (was 0.6 / 0.5). Walking: 0.5 / 0.4. Watch Elevation Tracking Fix - flightsClimbed now explicitly enabled on HKLiveWorkoutDataSource during workouts. - Previously the data source never collected elevation data — the handler existed but received no data. Strava TCX File Upload - Workouts now upload as TCX files with full time-series data (HR samples, GPS route, elevation, distance). - Strava displays HR graph, pace graph, elevation profile, and map instead of just a text summary. - Falls back to manual activity creation if no HealthKit workout data is available. - Workout route authorization (HKSeriesType.workoutRoute) added to HealthKit permissions. CSV Export - Export all completed workouts as CSV from the Workout History section header. - One row per set (or per block if no sets), with session/block/set-level columns. - Share via iOS share sheet. **Build 5** · 02 May 2026 Fitness Trend Card Redesign - New "Stat Stack" layout: three scannable rows (Run Pace · Z2, Readiness, Volume) each with sparkline, value, and delta. - Tap to open detailed Fitness Trend view with full charts, weekly breakdowns, and contextual insights per metric. - 4W/12W timeframe toggle. Fitness Trend Detail View (New) - Full charts per metric: LineMark for pace, AreaMark for readiness, BarMark for volume. - Weekly breakdown tables with per-week deltas. - Auto-generated insight cards (e.g. "Pace improving steadily", "Volume spike detected"). Share Card Redesign - Share cards now show the complete workout with all run + station segments, pace, time, HR, and best/worst indicators. - Auto-generated highlights: negative split, pace drop, even pacing, peak HR, station spread, roxzone percentage. AI Plan Review (New) - Export all training data (completed sessions, readiness, performance metrics, upcoming plan) as a structured prompt for external AI review. - Generate, copy, or share the prompt. AI is instructed that "no changes needed" is a valid answer. TodaysWorkoutCard Design Fix - Left accent bar now rounds its left corners to match the card's 20pt corner radius. Audio Coaching — State-Based Pace Alerts - Pace announcements now trigger only on state change (too slow → on target → too fast) instead of repeating every 60 seconds. - New "Back on target" announcement when returning to pace zone. - Applied to both Watch and iPhone run trackers. Audio Coaching — Music Ducking - Music is now automatically dimmed (ducked) during voice announcements instead of being interrupted. - Music returns to full volume after each announcement via AVSpeechSynthesizerDelegate. HR Zones — Age from HealthKit - HR zone calculation now reads date of birth from HealthKit when no saved config exists, instead of defaulting to age 30 (maxHR 190). - MaxHR computed as 220 − actual age. Strava Auto-Upload (Watch Workouts) - Watch workouts are now automatically uploaded to Strava when they arrive on iPhone (if Strava is connected). - Previously only iPhone-tracked workouts had a manual upload button. Strava Retroactive Upload - Any past workout can now be uploaded to Strava from the workout result view (Workout History, Plan Detail, Dashboard). - Shows upload status: pending, uploading, or already uploaded. Localization - Wrapped all new UI strings in String(localized:) for German/English support across FitnessTrendCard, FitnessTrendDetailView, ShareCardView, and AIPlanReviewSheet. **Build 3** · 02 May 2026 Watch: Distance & Time Tracking - Watch exercise view now supports all three tracking modes (Reps, Distance, Time) instead of only Reps. - Distance mode: Crown-adjustable meters input (5m steps), stepper buttons, long-press for manual entry. - Time mode: Crown-adjustable duration input (5s steps) showing MM:SS, stepper buttons, manual entry. - Previous set display adapts to show distance or time instead of reps when appropriate. - Tracking mode auto-detected from block's effectiveTrackingMode (explicit override, duration target, or name-based). Auto-Sync Today's Workout to Watch - When you edit today's workout in the Session Detail Sheet and tap Done, changes are automatically sent to the Watch (if paired). - Delivery-status toast: green "Synced to Watch" when Watch is reachable, orange "Changes queued" when offline. Strava Integration - New Strava section in Settings: Connect/Disconnect with OAuth2 authorization flow. - "Share to Strava" button in workout summary (WorkoutSessionDetailSheet) after completing a workout. - Uploads workout as a Strava activity with name, type, duration, distance, and detailed exercise breakdown. - Duplicate protection: tracks uploaded workout IDs to prevent double uploads. - Only GritRace-tracked workouts are uploaded — runs from Apple Watch's native app go through Strava's own Health sync. - URL scheme (gritrace://) registered for OAuth callback handling. **Build 2** · 01 May 2026 Custom Exercise Photos - Custom exercises now support photos: add an image when creating a new exercise or edit it later from the detail view. - Images shown as thumbnails in the exercise list and as a banner in the detail sheet. - Change or remove photos anytime via the detail sheet (custom exercises only). - Images stored in Documents directory and persist across iCloud backups / device transfers. Blank Plan — Custom Training from Scratch - New "Blank Plan" option when creating a training plan: start with an empty plan and fill it with your own workouts. - Mini setup wizard: pick format, duration (weeks), training days per week, and optional race date. - Empty days show a dashed "+" circle — tap any day to add a workout directly. - Guided onboarding card explains the 4-step flow (tap day → pick type → add exercises → copy to other days). - Copy Workout: long-press any workout in the plan to copy it to other days (available in both week strip and full plan view). - All empty/rest days are now tappable across all plan types (not just blank plans) to quickly add sessions. **Build 1** · 01 May 2026 Running Pace — Apple Sensor-Fused Speed - Replaced manual GPS delta pace calculation with Apple's `runningSpeed` (HKQuantityTypeIdentifier). This is the same smoothed, sensor-fused pace Apple's own Workout app uses — no more jumping pace display. - Distance tracking simplified: only reads cumulative distance from HealthKit, no longer computes pace from distance deltas. Pace Coaching — Reduced False Alerts - Pace coaching minimum distance increased from 200m to 400m (wait for stable signal). - Pace coaching throttle increased from 30s to 60s between alerts. - Pace deviation threshold increased from 15 to 25 sec/km (avoids false "too fast"/"too slow" announcements from minor fluctuations). Watch Run Block — Overview Button - Added missing Overview (list.bullet) button to run blocks on Watch. Previously only exercise blocks had this button, making it impossible to see the workout overview during a run. Readiness Charts — Improved Readability - Fixed: Y-axis now zooms to actual data range instead of starting at 0 (e.g., HRV ~60ms no longer shows 0-400ms range). - Fixed: Y-axis and X-axis labels enlarged (8→9pt) and color changed from tertiary to secondary for better readability. - Added subtle grid lines for easier value reading. - Fixed: Baseline reference line position now matches the zoomed Y-axis. - AreaMark fill corrected to start from chart bottom instead of 0. Elevation Tracking — New - Added live elevation gain tracking using HealthKit `flightsClimbed` (1 flight ≈ 3m). - Elevation gain displayed on Watch during run blocks (teal tile, only appears when > 0m). - Elevation gain shown in Workout History detail view and analysis stats grid. - Elevation data saved per-session in `WorkoutSessionResult` and per-split in `RunSplitResult`. - Properly reset on session start and block transitions. App Tour — German Translation - All tour step titles, descriptions, and buttons (Next, Back, Done, Skip Tour) are now fully localized in German. Training Load — Running Power Integration - Added `runningPower` (watts) to HealthKit read types for Training Load calculations. - TrainingLoadEngine now prefers Apple's running power over HR-based TRIMP for running/cross-training workouts. Power-based load (avgWatts × minutes / 100) is more accurate than HR-based TRIMP as it captures terrain, speed changes, and doesn't lag like heart rate. - Live `runningPowerWatts` property exposed on HealthKitManager for potential future Watch UI display. - Running power cleared on workout end/discard.
improvedApril 30, 2026

Version 1.0.3

**Build 12** · 30 April 2026 Live Workout Sync — Deep Fix (14 bugs across sync chain) Session Resolution: - Fixed: LiveWorkoutUpdate now includes trainingPlanSessionId so iPhone can reliably identify which training session the Watch is running, instead of relying on fragile block-ID matching. - Fixed: Watch startSession() now propagates trainingPlanSessionId from the plan, ensuring every live update carries the session ID from the very first tick. - Fixed: PhoneWorkoutCompanionView.resolveSession() uses trainingPlanSessionId from live update as primary method; block-ID matching is now fallback only. - Fixed: clearSessionCompletionState on companion appear now uses sessionId from live update. Completion Tracking: - Fixed: Pause blocks no longer included in completedBlockIds sent to iPhone. Previously, pause block IDs polluted completion tracking and could cause wrong exercises to appear checked off. - Fixed: completedBlockIds reconciled when blocks are replaced via remote update — stale IDs from removed blocks are cleaned up. - Fixed: allBlockSetResults and superSetProgress cleaned up for removed blocks during block replacement. Superset Handling: - Fixed: superSetProgress clamped to valid set count after remote block update (add/remove set on iPhone no longer causes out-of-bounds set index on Watch). - Fixed: superSetProgress clamped in beginBlock() to handle cases where set count decreased. - Fixed: currentBlockSetResults cleared when current block is removed/replaced during active workout. Exercise Swap: - Fixed: swapExercise() now calls initializeExerciseSets() after clearing, so Watch receives blocks with proper set arrays instead of empty ones. Logging & Diagnostics: - Added: Logging for HK mirroring decode failures on both Watch and iPhone sides. - Added: Logging for handleRemoteBlockUpdate failures (decode error, session mismatch, stale block cleanup). - Added: Logging for resolveSession() failures with diagnostic context. Previous (Build 11→12): - Block updates sent via 3 channels: HK mirroring + sendMessage + transferUserInfo. - RemoteWorkoutCommand.blockUpdate for HK mirroring channel. - Stale transfers cancelled before new ones. Sync toast accuracy improved. - Removed fragile block-count session matching fallback. **Build 11** · 29 April 2026 German Localization - Added German (de) as the first localized language with 2302 translated UI strings. - Created Localizable.xcstrings String Catalog in Shared/ for iOS + watchOS targets. - Converted 300+ enum/computed properties to `String(localized:)` for runtime localization. - Comprehensive pass across all views: Analyse tab, Dashboard, Race Detail/Comparison, Training Load, Plan Analyse, Race Planner, Today tab, Weekly Digest, Watch app, and all helper views. - Section headers, legend labels, placeholder messages, achievement descriptions, and interpolated strings all translated. - Technical terms (HR, HRV, CTL, ATL, etc.) and brand names kept in English. Session Detail — Fix False Change Detection - Fixed: "Apply changes to similar sessions?" dialog no longer appears when no edits were made. - Root cause: JSON encoding comparison was unreliable for block change detection; replaced with direct Equatable comparison. Readiness Score — Deep Insights & Fixes - New: Tap the readiness card to open a detailed Readiness view with history charts, factor breakdown, and "Why this score?" explanation. - New: 30-day/90-day readiness trend chart with zone bands. - New: Per-factor history charts (HRV, Sleep, Resting HR, Strain) with baseline reference lines. - New: Natural language explanation of each factor's contribution to today's score. - Fixed: Score showed 100 in simulator/no-data scenarios (only strain was calculated). Now returns neutral 70 when no biometric signals are available. - Fixed: Text inside the readiness ring was overflowing into the circular border. Ring enlarged to 110px, content constrained. - Improved: HRV baseline extended from 30 to 60 days per latest research (Plews et al., HRV4Training, Kubios methodology). - Fixed: "Apply to similar sessions?" dialog no longer appears when dismissing completed/skipped session details. - Fixed: Block snapshot timing in session detail to prevent false change detection from auto-initialized exercise sets. Training Plan Detail — Day Cards Show Workout Type - Completed day cards now show the workout type icon (run, strength, etc.) instead of a generic checkmark. - Green ring + checkmark badge replaces solid green fill, keeping the workout type visible. - Session type label (Run, Strength, Cond., etc.) shown below each day card instead of just duration. Paywall Restructuring — Generous Free Tier - Today Tab now fully free: readiness score, training load, daily workout, quick actions all accessible without Pro. - Training Plans now free: create, follow, and complete workout plans without Pro. Advanced features (AI Import, Deload, Pace Adaptation) remain Pro. - Analyse Tab partially free: Performance Level, Best Times, Progress Charts, and Race Splits are free. Deep analysis (Weakness, Pacing, HR Insights, Benchmarks, etc.) gated with elegant inline Pro teasers. - AI Analysis Prompt now free: share/copy race data prompt to any AI app without Pro. - New UI components: ProBadgeDot (tiny orange PRO indicator) and ProSectionGate (inline teaser cards for locked sections). - Removed full-tab paywall locks in favor of feature-level gating for better user engagement. **Build 11** · 29 April 2026 Discard Workout — No HealthKit Save - Cancelling a workout and tapping "Discard" now discards the HealthKit workout data instead of saving it. - Fixed `resetToReady()` also incorrectly saving workout data to Health. Watch — Back to Workout - Added "Back to Workout" button in the Watch workout overview screen. iPhone → Watch Live Sync - Changes made on iPhone companion view (removing sets, swapping exercises) now sync to Watch via `.onChange(of: planVersion)`. Watch Set Navigation - Left/right arrows in the exercise detail view now navigate between sets (back/forward) instead of between exercises. Watch Design System Migration - Transferred the iPhone glass design system (glassCard, glassInset, GRSpacing, GRRadius) to the entire Watch app. - watchOS 26: Native Liquid Glass support via `.glassEffect()`. External Workout → Training Plan - "Extra workout" button now adds the external workout as a completed session to today's training day (previously only dismissed). Week Overview — Improved Info Density - Completed sessions now show the session type icon (run, strength, etc.) instead of a generic checkmark. - Green ring + checkmark badge replaces solid green fill, keeping the workout type visible. - Short type label shown below each day circle (Run, Strength, Cond., etc.). **Build 10** · 29 April 2026 Performance & Visual Refinements - Massively improved scroll performance: reduced GlassBackground from 5 compositing layers to 1 (dark) or 2 (light). - Dark mode cards are now opaque dark surfaces — no blur, no shadow, subtle 0.5pt border. - Light mode cards use translucent material with soft shadow. - iOS 26+: Cards automatically use Apple's native Liquid Glass (`.glassEffect()`). - Stopped MeshGradient background animation — static gradient remains, no more continuous 60fps GPU redraws. Race Planner — Stations Only Autofill - "Calculate Race Plan" now asks whether to adjust stations only (keeping your pace) or recalculate everything. - Fixed critical bug: "Stations Only" was producing wrong totals (e.g. 1:16 instead of 1:10) because roxzone was counted once instead of twice per station. - If the target time is impossible with the current pace, a clear warning explains why and offers to adjust everything instead. Feedback Prompt - One-time feedback prompt appears after 7 days of app usage, linking to the feedback portal. Training Plan Reactivity - Added `planVersion` counter to `TrainingPlanManager` — views now react instantly to structural changes without expensive deep-equality checks. Watch Sync - Stale workout plan transfers are now cancelled before sending a new one, so the Watch always receives the latest version. **Build 6** · 28 April 2026 Glass Design System - Introduced Liquid Glass visual design across the entire app: material blur + tint overlay + specular highlight + hairline border + shadow on all cards. - Three glass tiers: `.glassCard()` (standard cards), `.glassInset()` (smaller elements), `.glassHero()` (hero cards). - Added MeshGradient animated background (`GRScreen`) on all main views (iOS 18+, radial fallback for older). - Replaced ~80+ `Color.surfaceCard` references with glass materials across 25+ files. - Transparent navigation bars on all views with `.toolbarBackground(.hidden)`. - Monospaced digit formatting (`.monospacedDigit()`) on all numeric displays (~40 instances). - Accent glow effect on primary action buttons. - Glass-styled "Start on iPhone" / "Start on Watch" buttons with gradient + border. - Glass-styled secondary action buttons (Move, Complete, Skip) with ultra-thin material. - Glass-styled share mode pills and Share Progress button. Minimizable Dashboard Cards - Cards on the Today tab can now be minimized via a subtle minus button in the top-right corner. - Minimized cards appear as compact 3-column mini tiles at the bottom of the page. - Tap a mini tile to restore the card to its original position. - "Restore All" button to bring back all minimized cards at once. - 11 Today cards are minimizable: Races, Readiness, Recommendation, Training Load, Weekly Digest, Activity, Workout, Stats, Share, Badges, Fitness Trend. - 29 Analyse sections are minimizable (19 Race Analysis + 10 Training). - Minimized state persists across app restarts via UserDefaults. Bug Fix - Fixed scrolling on Today tab: removed `PressableScale` gesture from `CardStyle` that was blocking ScrollView interaction on all cards. Localization - Replaced all remaining German UI strings with English translations across TrainingPlanViews, LogPastRaceView, and Watch TrainingViews. **Build 1** · 27 April 2026 Live Companion View (iPhone) - Instant set removal: removing a set in the live workout view on iPhone now updates the UI immediately. Previously it could take until the next Watch update to reflect the change. - Instant exercise swap display: swapping an exercise during a live workout now refreshes the card instantly on iPhone. - Exercise swap synced to Watch: swapping an exercise on iPhone during a live workout now sends the updated blocks to the Watch immediately. Previously the Watch kept the old exercise. - Block removal synced to Watch: removing a block on iPhone during a live workout now sends the change to the Watch. - Live sync uses fresh data: the sync-to-Watch function now reads the latest blocks from the plan instead of using stale cached/annotated blocks. Send to Watch (Workout Plan Transfer) - Fresh blocks on send: "Track on Watch" and "Send to Watch" in the session detail now always send the current version of the workout (with all edits). Previously it sent the version from when the detail sheet was first opened, so adding/removing blocks after opening the sheet was ignored. - Today section preserved: sending a workout to the Watch no longer removes it from the Watch's "TODAY" section. The scheduledDate is now always included when building the WorkoutPlan. - Stale transfer cancellation: when sending the same workout to Watch multiple times, old queued transfers are cancelled so the Watch always receives the latest version.
newApril 26, 2026

1.0.2

GPS Pace Smoothing (iPhone Run Tracker) - Smoothed pace display: current pace now uses a rolling median over the last 15 seconds instead of raw GPS speed values, eliminating erratic jumps (e.g. 4:20 → 12:00) during steady runs. - Speed accuracy filter: only GPS samples with speedAccuracy 3.0 m/s are used. Unreliable readings are discarded. - Pace clamping: values outside 2:00–15:00/km are filtered out to prevent nonsensical display values. Pace Coaching Improvements - Wider tolerance: pace alerts now use 5% of target pace (was fixed 15s). At 5:30/km target, alerts trigger outside ~5:13–5:47/km instead of 5:15–5:45/km. - Less frequent alerts: cooldown between alerts increased from 30s to 60s. - Later start: pace coaching only starts after 400m (was 200m) to allow average pace to stabilize. Apple Watch Native Workout Export - Tighter pace range: SpeedRangeAlert sent to the native Apple Watch Workout app now uses ±5% (was ±10%). At 5:30/km target, the alert zone is ~5:14–5:47/km instead of 5:00–6:06/km. Purchase & Trial - 3-day free trial: the Pro Monthly subscription now includes a 3-day free trial for new users (introductory offer). - Trial badge in paywall: eligible users see a 3-DAY FREE TRIAL label on the monthly subscription button. - Trial eligibility check: the app automatically detects whether the user qualifies for the introductory offer.
improvedApril 26, 2026

Version 1.0.2

**26 April 2026** GPS Pace Smoothing (iPhone Run Tracker) - Smoothed pace display: current pace now uses a rolling median over the last 15 seconds instead of raw GPS speed values, eliminating erratic jumps (e.g. 4:20 → 12:00) during steady runs. - Speed accuracy filter: only GPS samples with speedAccuracy < 3.0 m/s are used. Unreliable readings are discarded. - Pace clamping: values outside 2:00–15:00/km are filtered out to prevent nonsensical display values. Pace Coaching Improvements - Wider tolerance: pace alerts now use ±5% of target pace (was fixed ±15s). At 5:30/km target, alerts trigger outside ~5:13–5:47/km instead of 5:15–5:45/km. - Less frequent alerts: cooldown between alerts increased from 30s to 60s. - Later start: pace coaching only starts after 400m (was 200m) to allow average pace to stabilize. Apple Watch Native Workout Export - Tighter pace range: SpeedRangeAlert sent to the native Apple Watch Workout app now uses ±5% (was ±10%). At 5:30/km target, the alert zone is ~5:14–5:47/km instead of 5:00–6:06/km. Purchase & Trial - 3-day free trial: the Pro Monthly subscription now includes a 3-day free trial for new users (introductory offer). - Trial badge in paywall: eligible users see a "3-DAY FREE TRIAL" label on the monthly subscription button. - Trial eligibility check: the app automatically detects whether the user qualifies for the introductory offer.