PK
PACE
KEEPER
Not signed in
Sign in to sync

What's new

83 RELEASES
0.9.9

Every release, newest first. Each one names the build it put on each device — four surfaces ship separately, so a version alone cannot tell you what is on your bars.

BUILD 83· 0.9.9 · 2026-09-05ROWS
  • The GEL picker's rows end exactly where CANCEL and the page arrows begin. They were drawn to the SETUP screen's taller band while the taps were wired to their own, so the bottom of the last row belonged to the strip and the arrow cell painted over its caption, which read IOT PACKED on a three-row page.
WEB 0.9.9KAROO 2026.09.05.3
BUILD 82· 0.9.9 · 2026-09-05MOJITO
  • PowerBar PowerGel Hydro Mojito Caffeine is HYDRO MOJITO on every picker, the last shared row still wearing a ten-character slice. The flavour is what tells it from PowerGel Original; the caffeine already reads on the row's own sub-line.
WEB 0.9.9KAROO 2026.09.05.2PHONE 2026.09.05.2GARMIN 2026.09.05.2
BUILD 81· 0.9.8 · 2026-09-05SETTLED
  • A ride imported from the Hammerhead dashboard or from Garmin Connect now takes the gels it ate off the stash. Since the connection went live only a hand-uploaded FIT ever settled the drawer; the poller stored the ride and dropped the intakes, so the ledger stayed empty and the counts never moved. Every importer now goes through one saver, and the sync report says what each ride deducted, what was eaten that the stash never held, and what could not be applied.
  • A picker name up to sixteen characters reaches the Karoo and the Fenix whole. The web and the phone moved to sixteen on 2026-09-03, but the catalogue wire still cut at fourteen and both device parsers refused anything longer, so Enervit C2:1 Pro Citrus arrived as C2:1 PRO CITRU and a fifteen-character name would have made the Karoo throw the whole catalogue away. The budget is now one number in products.json, generated into every surface.
  • The Karoo and the Fenix must carry this build before the web deploys. The Karoo on the previous build refuses a catalogue with a fifteen-character name in it and falls back to its built-in six without saying so.
WEB 0.9.8KAROO 2026.09.05.1PHONE 2026.09.05.1GARMIN 2026.09.05.1
BUILD 80· 0.9.7 · 2026-09-03NAMES
  • A product is now named by what makes it DIFFERENT, never by its brand. Adding a product defaulted its picker name to the brand, and neither the phone nor the web ever rendered a field for it - so every gel from one brand arrived with the same name. Two UCAN Edge gels, Strawberry Banana and Orange Mango, both reached the bars as UCAN: byte-identical at the exact moment of choosing, with the FIT recording whichever row the thumb landed on.
  • Both ADD sheets now show the name in an editable field, labelled with where it appears and previewing what the picker will read. Left blank it is derived from the variant and the flavour - the two ends of the full name - because a left-to-right truncation turns both UCAN flavours into EDGE ENERG and reproduces the bug by another route. A collision with anything else you own becomes a suffix, never a silent duplicate.
  • The ten-character cap is gone; it was a database column slice, never a screen limit. The Karoo draws the name through a shrink-to-fit box that stays above the 12 px sunlight floor, so the budget is sixteen. Amacx Turbo Gel Cola Lime is TURBO COLA LIME on the bars instead of TURBO CL, and Amacx Turbo Gel Caffeine is TURBO CAFFEINE.
  • The generator refuses to build a library where two products share a picker name, where a product is named its own bare brand while that brand has siblings, or where a name exceeds the budget. Maurten GEL 100 was called MAURTEN among four Maurtens and Amacx Turbo Gel was called AMACX among five Amacx products; both are fixed.
WEB 0.9.7PHONE 2026.09.03.3
BUILD 79· 0.9.6 · 2026-09-03CARRY
  • The scan screen now ASKS instead of guessing: "still carrying what is packed above?", two answers side by side, each showing how many items its push would send. Replace stays the default because that is the rule - whatever you scan and press Go is what you are carrying - and add is one tap of the same size, not a smaller button underneath.
  • It replaces a clock that could not work. For half a day the add option was withheld once the pocket passed 18 hours, on the theory that a stale pocket belongs to a finished ride. A commute to work and a commute home four hours later is two rides inside that window, and packing on Friday for a Sunday start is one ride outside it. Elapsed time is not the variable; whether the gels are still on your body is, and only you know that.
  • The question is asked only when the two answers actually differ, so an empty pocket or a scan that changes nothing still gets a single button and no question. Two UCAN packed and one in front of the camera now counts as losing one, which the old wording called "nothing above is lost".
  • One push button, and it says what it will send: PUSH 5 TO DEVICES. The pocket list stays editable underneath, which is the lever for a cafe stop - nothing is deducted as you eat, so the packed list is what you packed, not what is left.
WEB 0.9.6PHONE 2026.09.03.2
BUILD 78· 0.9.6 · 2026-09-02POCKET
  • What you scan is what you are carrying. A push used to ADD the scan to whatever the pocket already held, so a scan of the four gels actually going in the jersey pushed those four plus the leftovers of the last one — and nothing on the bars tells the two apart. A push now REPLACES the pocket, and names any rows it is about to drop before you tap, not after the ride.
  • The kitchen-then-garage case is still there, as ADD TO THE POCKET INSTEAD, which appears only when there is something to add to. It was the default until today and it could never be noticed when it was wrong: a pocket that silently grows looks exactly like a pocket that is right.
  • A push with nothing scanned still sends the pocket unchanged, so editing the packed list by hand and pushing from TODAY does what it says. The web has always worked this way, so the two surfaces now agree about what one gesture means.
WEB 0.9.6PHONE 2026.09.02.1
BUILD 77· 0.9.5 · 2026-09-01SNAP
  • Gemini is in the scan-model picker, on the phone and on the web: Gemini 3.1 Pro and Gemini 3.7 Flash, priced from OpenRouter's list. Gemini reads a large photo in tiles rather than one downscaled frame, so the picker says TILED instead of inventing a resolution, and NOT YET PROVEN ON YOUR FOIL until the bench says otherwise. The two lists are pinned to each other by a test on each side, because a model known to one side only gets silently reverted to Sonnet on the next sync.
  • An unknown gel now fills itself in. The moment a scan comes back with a product the library does not know, the phone asks the free 488-panel reference for its label and pre-fills the ADD TO LIBRARY sheet — so the sheet stops opening blank and looking like the photo failed. When the reference has nothing either, the row says so and names the two ways left: LOOK IT UP (web search, from the daily cap) or type it from the packet.
  • The phone signs itself back in. A session that dies overnight is re-minted, silently, from the Google account that already authorised the app the next time the app comes to the front — so the camera opens to a signed-in phone. Never for a phone that has not signed in before, never with a sheet, and the SIGN IN button stays for the cases Credential Manager will not answer.
  • The Karoo's FUEL screen syncs from a tap on the band above DRINK and GEL, pre-ride and mid-ride, and says what the sync found: PLAN r3 · 11 PRODUCTS, CATALOGUE +1, NO CHANGE, OFFLINE, NOT PAIRED. A sync that changed nothing used to look identical to a tap that did nothing.
  • A scan test set. Twelve front/back pairs of the athlete's own packets that Snap & Go failed on live in calibration/scans/samples with what is really printed on each, and tools/scan_bench.mjs runs the phone's exact request against them on every model in the picker — the side-by-side the model note said nobody had done. tools/import_scan_samples.ps1 turns the phone's drop folder into new samples.
WEB 0.9.5KAROO 2026.09.01.1PHONE 2026.09.01.4
BUILD 76· 0.9.4 · 2026-09-01SIGNIN
  • You can sign in again. signOut() blanks its keys instead of removing them, and the one read that decides whether you are signed in treated an empty string as a real user id — so the app believed it was signed in as nobody. Settings therefore drew the signed-in card, whose only control is SIGN OUT: there was no SIGN IN button to press, which is why signing in never reached the server.
  • Your own products now survive a dead token. Personal products live on the server and were held only in memory, so anything that stopped a sync emptied half your library — which is how your own UCAN Edge gels came back as NO LIBRARY MATCH. They are cached on the phone now and the app opens knowing them.
  • A push says what it is leaving behind. Rows with no library match have no carb value and cannot be packed — that stays — but they used to leave silently, so three gels on the table became a one-item plan with nothing on screen saying so.
WEB 0.9.2PHONE 2026.09.01.3
BUILD 75· 0.9.3 · 2026-09-01PUSHED
  • A finished push now says so. Snap & Go ends on TODAY, and TODAY's biggest button read PUSH TO DEVICES — so a plan that had already reached the server looked like one that had not, and the obvious move was to push it again. Once the plan on screen is the plan you just pushed, a PUSHED card takes that slot and the button steps down to PUSH AGAIN.
  • Signed out, a scan no longer claims a product is missing from your library. Your own products are pulled from the server, so with no session the app can only see the shared ones — that is how your own UCAN Strawberry came back as something to add. The row now says it could not check, and offers sign-in instead of ADD TO LIBRARY, which would have made a second permanent copy of a product you already own.
  • Scanned rows re-check themselves when your products arrive. Sign in mid-scan and anything that read as unknown is matched again — no re-shoot.
  • A sign-out now records why. The phone keeps the server's own error code for the last failed refresh and shows it on the ACCOUNT card, because the sign-out on 2026-08-31 erased its own cause and left nothing to diagnose.
WEB 0.9.2PHONE 2026.09.01.2
BUILD 74· 0.9.2 · 2026-09-01STAYSIGNEDIN
  • The app should stop signing you out. Its token refresh had no lock while fifteen places could trigger one at once, and Supabase rotates refresh tokens — so two refreshes racing meant the loser was refused, and any refusal signed you out for good. Six of your refresh tokens were still valid on the server the whole time.
  • A rate limit or a server hiccup no longer signs you out either. Only the server actually refusing your token does that; anything else just fails that one call and the session survives.
  • On the web scan, tapping a photo slot now offers your gallery and files as well as the camera. It was locked to camera-only, so a packet you had already photographed could not be used.
  • The button on an unmatched row says ADD TO LIBRARY, because that is what it opens. It said ADD TO STASH while opening a library form — naming the end of a two-step flow and hiding the step you were on.
  • LOOK IT UP on the web now checks your 488-panel reference before paying a model. Skratch Super High-Carb was in it all along, with the numbers off your own bag.
WEB 0.9.2PHONE 2026.09.01.1
BUILD 73· 0.9.1 · 2026-08-30GLOBALIDS
  • Tapping the fuel face on the Fenix APP now logs what you tapped. Every tap was being read as the START button, so it recorded the gel your plan had scheduled instead of the cell you touched — and there was no way to log water at all. The data field was never affected.
  • The BUTTONS help on the watch describes the fuel page properly: left cell is a sip, right cell is that gel, top undoes, bottom pages. It had been describing a screen that no longer existed.
  • Products you add now get an id that is unique across everyone, not just across your own library. Nothing you already own was renumbered.
  • Two people who add the same product can now be recognised as having the same thing, and a product promoted from the nutrition reference records which panel it came from.
  • On the watch fuel face, the time-since clock sits at the top of its column again, whether that column holds one gel or two. It had moved into the gap between two cells, which read differently from the bottle column beside it — the same three facts in two shapes.
  • You can sign in from the app again. There was no sign-in control anywhere in it — so when a session expired, nine screens told you to sign in and none of them could. It is in SET → ACCOUNT, and on the SCAN screen itself, because that is where it stops you.
  • Signed out, the scan now says so before you shoot. Your own added products are loaded from the server, so without a session they read NO LIBRARY MATCH even though you own them — which is what happened with a UCAN gel that was already in your library.
WEB 0.9.1KAROO 2026.08.30.1PHONE 2026.08.30.3GARMIN 2026.08.30.2
BUILD 72· 0.9.0 · 2026-08-29LOADOUTVETO
  • The Karoo takes your pushed plan again. Once you had ever edited a count on its SETUP screen, it refused every plan you pushed after that — silently, and forever, while reporting itself perfectly in sync. Your counts now beat only the plan they were made against; a plan pushed since wins.
  • SETUP has a RESET, right of SYNC. It drops the counts the device has been holding and lets the plan already on the bike fill the picker. It is amber only when it would actually change something.
  • The phone now tells you what the picker will SERVE, not how many products the device was offered. Those were free to disagree, and did.
  • A drink intake used to record the right grams against the wrong product. If your plan carried a drink other than the Sponser default, every sip went into the file as Sponser — the carbohydrate was right, the product name was not. Rides before today cannot be corrected; the contract records how to read them.
  • Mark a product as a REGULAR on the web stash page and it leads the picker on both head units, in the order you pin. Never derived from how many you have — a gel you have just run out of is still what you ride on.
  • SCAN is two jobs now, chosen before you shoot: SNAP & GO writes the ride and never touches the drawer; FILL THE DRAWER photographs a shelf in as many frames as it takes, reads them together, and never reaches a device.
  • Your two UCAN Edge rows lead the picker unchanged — they were already in your library, label-read by you. A third UCAN row was briefly added from a retailer's figures and has been withdrawn; yours are the better ones.
  • SYNC on the Karoo now works mid-ride from a tap. Nothing reaches for the network on its own during a ride; the ten-minute poller still stands down the moment one starts.
  • The Fenix APP now logs what you tapped. Every tap on its fuel face was being read as the START button, so it recorded the gel your plan had scheduled instead of the cell you touched - one test wrote 640 g of Amacx you never ate, with no way to log water at all. The data field was never affected.
WEB 0.9.0KAROO 2026.08.29.1PHONE 2026.08.29.1GARMIN 2026.08.29.2
BUILD 71· 0.8.43 · 2026-08-25DRINKSPLIT
  • A drink no longer appears in the Karoo gel picker. A scanned 55 g drink mix was showing up there as though it were a sachet, one tap from logging a whole bottle of carbohydrate.
  • The Karoo bottle is now whichever drink your plan carries. Every sip of mix used to be recorded against Sponser 80 whatever you had actually mixed up, and a scanned drink could not be logged on that device at all.
  • On the phone, long product names and their details no longer push a row until the next one is clipped. Unverified carbs show as a mark and a colour rather than fourteen more characters.
WEB 0.8.43KAROO 2026.08.25.3PHONE 2026.08.25.6
BUILD 70· 0.8.42 · 2026-08-25JOINCLOCK
  • The dashed line between two gels or two bottles is gone. The time since sits there instead, which separates the two cells just as clearly and puts a number where there was only a stroke.
  • With a single gel or a single bottle the clock stays on top of it, where it has always been.
  • Both names in a split column move away from the join, so there is room to read them.
WEB 0.8.42GARMIN 2026.08.25.23
BUILD 69· 0.8.41 · 2026-08-25TWOBOTTLES
  • A carb drink you scanned and pushed now appears as its own MIX cell, without having to remember a settings toggle.
  • Sips of that drink are recorded against the drink you actually pushed. They used to be recorded against whatever the watch had saved as its default drink, at that products carb value.
  • A drink no longer appears in the gel column. It was landing there as though it were a sachet - one tap for a whole bottles worth of carbohydrate.
WEB 0.8.41GARMIN 2026.08.25.22
BUILD 68· 0.8.40 · 2026-08-25SAMEAPP
  • On the watch app, START now records what you were actually logging. Tapping water and pressing START used to record the scheduled gel instead - water went into the ride as grams of carbohydrate.
  • The gel column now reads the same way the water column does: time since above, the name, and the ride total below. The per-gel carb value under each name is gone - it describes the product, not the ride.
  • With two gels the pair shares those three lines between them: the clock tops the first, the ride total sits under the second.
WEB 0.8.40GARMIN 2026.08.25.21
BUILD 67· 0.8.39 · 2026-08-25UNDOGLYPH
  • Tapping a gel now turns its cell gold for a moment, the same confirmation a water tap has always given. A gel logs in one press and had nothing to show for it.
  • The word UNDO is replaced by the counter-clockwise arrow Garmin uses, in red. It needs no reading, and it survives the shallow bottom band at a size the word never could.
  • The bottom band no longer counts how many gels you have taken, so the total grams get the whole space.
WEB 0.8.39GARMIN 2026.08.25.20
BUILD 66· 0.8.38 · 2026-08-25CENTRED
  • The small grey lines in the top and bottom sections are gone. They were decoration and they read as a divider that meant nothing.
  • Gel and water text no longer runs off the curve. The width was measured across the whole cell while the text is drawn from its centre, so one end could reach past the glass - which is what cut the corner off a single gel.
  • Every line now has a gap above and below it, so the gram figure no longer sits almost on the dashed line between two gels.
WEB 0.8.38GARMIN 2026.08.25.19
BUILD 65· 0.8.37 · 2026-08-25NORING
  • The countdown ring around the rim is gone, and the sections now reach the edge of the glass. It was a 22 mm band sitting on the only space the water and gel cells had left, and it was overlapping their text.
  • The countdown itself moved into the top section: within ten minutes of a gel being due it reads GEL IN and the time, warming toward red as it closes, exactly as the ring did.
WEB 0.8.37GARMIN 2026.08.25.18
BUILD 64· 0.8.36 · 2026-08-25NOCRASH
  • The fuel field no longer crashes when it draws. It was running out of stack deep inside the text layout - a data field gets much less of it than the watch app, which is why only the field died.
  • The text layout now resolves the geometry once per section and works in plain numbers, three call levels shallower than before.
WEB 0.8.36GARMIN 2026.08.25.17
BUILD 63· 0.8.35 · 2026-08-25NOOVERLAP
  • No more text written over the dividers or off the edge of the glass. Every line is now confined to the part of its section that is actually usable, instead of the whole wedge.
  • The top and bottom sections show two lines instead of three. The third was either an instruction or a restatement of the number above it, and it was the line landing on the dividers.
  • The ride total moved to the bottom section, which is idle most of the ride and has room for it.
  • The carb rate reads -- rather than 0 G/H for the first ten minutes. It is not zero, it is not measurable yet, and a zero on the glass claims otherwise.
  • Gel names get a bigger share of their cell, and a cell with no clock above it now gives that space to the name instead of leaving it empty.
WEB 0.8.35GARMIN 2026.08.25.16
BUILD 62· 0.8.34 · 2026-08-25GRID
  • The dividers on the watch face now bend the way you drew them: they fall from the centre and then run flat out to the edge, so the boundary meets the rim square instead of glancing off it.
  • The carb rate at the top has the full width of the glass to sit in, because above the bend the top section owns the whole face.
  • The line between two gels is dashed. The other dividers separate different things; that one separates two of the same kind.
  • The time and the totals in each cell are much bigger, and the ring is thicker.
  • The ring warms toward red over the last ten minutes before a gel is due, arriving fully by five.
  • You can choose how gels are named - the compact four-character tag, or up to twelve characters of the real product name.
WEB 0.8.34GARMIN 2026.08.25.15
BUILD 61· 0.8.33 · 2026-08-25WEDGE
  • The watch face is drawn the way you sketched it: the dividers radiate from two points instead of running straight across, so the water and gel cells are much bigger at the edges where your thumb lands - 365 px tall out wide, against a flat 223 px before.
  • The g/h readout and the undo band keep their room in the middle, where you actually look, because the wedges are deepest on the centre line.
  • No divider is drawn through a label any more. Text is measured against the wedge it sits in rather than against the full width of the glass.
  • A tapped cell is filled to its real shape, so what lights up is exactly what you pressed.
WEB 0.8.33GARMIN 2026.08.25.14
BUILD 60· 0.8.32 · 2026-08-25CADENCE
  • Ride files are a third smaller and far easier to read. The per-second block went from thirteen streams to seven; a five-hour ride carries 439 KiB of PaceKeeper data instead of 668 KiB.
  • Numbers that never changed second to second no longer pretend to. Sodium, caffeine and strap battery are written when they move and held forward by whatever reads the file.
  • Three values are gone from the file and recomputed instead: carb rate, carb debt and the countdown to the next intake. No field number was ever reused - they are reserved for good.
  • The Fenix data field writes the same intake block as the Karoo again. It had been dropping three fields to fit a 32-byte limit, and freeing that space was the point.
  • The Karoo now writes everything the Fenix does plus the physiology the Fenix cannot measure - one is a clean superset of the other.
WEB 0.8.32KAROO 2026.08.25.2GARMIN 2026.08.25.13
BUILD 59· 0.8.31 · 2026-08-25TWOCAPS
  • The watch face has a bottom band now. Undo appears there in gold after you log something, so it never covers the water or gel cells you are still using.
  • Each column carries its own clock: time since your last drink sits above H2O, time since your last gel above the gels. They used to sit side by side in the top band, which made you match a left-hand number up there to a left-hand column down here.
  • The top band shows your carb rate and what the ride has taken, and switches to the running millilitres while you are tapping sips - two taps reads +40 ML.
  • With more than two gels the bottom band pages through them and names the next one.
  • The two logging columns are now the tallest bands on the glass; the top and bottom bands were between them taking more room than the cells you tap every few minutes.
WEB 0.8.31GARMIN 2026.08.25.12
BUILD 58· 0.8.30 · 2026-08-25ONESURFACE
  • The watch app now logs exactly the way the data field does - water on the left, gel on the right, sips that add up, the undo in the top third. It had no drink flow at all before, so a mouthful of water could not be recorded from it.
  • Both watch apps share one ride surface now rather than each carrying their own, so the two can no longer drift into different workflows on the same wrist.
  • The physical buttons still do everything they did on the watch app: START confirms, BACK undoes or snoozes, hold UP opens the ride menu. The touch surface is a second path, not a replacement.
WEB 0.8.30GARMIN 2026.08.25.11
BUILD 57· 0.8.29 · 2026-08-25POCKET
  • Today now shows what will go and what the devices are already holding, side by side, so you can see the difference before you push instead of after.
  • The pocket is editable everywhere it appears - Today, the scan review and the Plan tab - with a minus, a plus and a remove on every row. Taking one gel back out no longer means emptying the pocket and re-scanning the drawer.
  • PUSH TO DEVICES on Today actually pushes now. It used to open the how-to.
  • The pocket says how old it is, and warns past eighteen hours: it survives a push on purpose, so the one way to get it wrong is scanning on top of a pocket from a previous ride.
  • A row still on the devices but no longer in the pocket is marked DROPPING, so you know what the next push takes away.
  • The shortfall is measured against the ride - target times duration - rather than against the plan agreeing with itself. A pocket covering a third of the ride used to read PLAN READY.
WEB 0.8.29PHONE 2026.08.25.5
BUILD 56· 0.8.28 · 2026-08-25PICK
  • You pick what goes in the jersey. The Plan tab lists everything in the drawer with a plus and a minus, and will not let you pack more of something than you own.
  • Two starting points sit above the list rather than replacing it: FILL FROM DRAWER takes what the ride asks for, and ASK THE COACH proposes a pocket - both land in the same rows and every one of them stays editable.
  • The running total says what you are carrying against what the ride needs, and turns amber the moment it is short.
  • The coach is now reachable from the phone as well as the website; it was refusing the phone outright before.
  • On the watch, the undo panel is the same size as everything else and stays in the top third, so the water and gel columns underneath keep working while it is up.
WEB 0.8.28PHONE 2026.08.25.4GARMIN 2026.08.25.10
BUILD 55· 0.8.27 · 2026-08-25FLUID
  • The watch now logs the water you drink. Sips of plain water were counted on the glass but never recorded, so every Fenix ride finished with a fluid total of zero.
  • A run of sips is logged as the volume you actually drank rather than the whole bottle - two 20 ml sips of Sponser 80 are 40 ml and 5 g, not 640 ml and 80 g.
  • The top of the watch face names what just went in the moment you tap it, so a half-noticed press reads as "+40 ML LOGGED" instead of an unlabelled undo offer.
  • While you are still tapping sips, the top of the face counts the millilitres up as you go.
  • The top of the watch face now shows how long since your last drink and how long since your last gel, side by side - water on the left, gel on the right, the same sides as the buttons that log them.
WEB 0.8.27GARMIN 2026.08.25.9
BUILD 54· 0.8.26 · 2026-08-25NODEMO
  • The website no longer shows a sample stash or a sample plan. Signed out, it says so and points at sign-in; signed in, it shows only what you actually counted.
  • The example ride of five blocks over four hours twenty is gone from the plan page - the one that once rendered against a three-hour ride.
WEB 0.8.26
BUILD 53· 0.8.25 · 2026-08-25NODEMO
  • Demo mode is gone, along with the switch for it and every DEMO MODE message that used to stand between you and an action.
  • The seeded shelf went with it. A fresh phone now shows an empty stash rather than a dozen products you do not own - the seed was indistinguishable from real stock once it was on screen.
  • TODAY no longer opens on a made-up plan of five blocks over four hours twenty. With no plan pushed, it says so.
WEB 0.8.25PHONE 2026.08.25.3
BUILD 52· 0.8.25 · 2026-08-25POLISH
  • Water is cyan and food is amber, the same colours the Karoo uses, so which side is which no longer has to be read.
  • The countdown fits. A two-hour time was being laid out against the full width of the screen while sitting near the top, where a round face is much narrower, so its ends ran off the curve.
  • The tap coordinates left over from testing are gone from the screen.
  • The top third is the countdown and the undo panel; the bottom two thirds are the two logging columns, running the full height of the glass.
  • Carrying more than two gels? Tap the countdown to page to the next pair - the swap strip that used to eat a slice of the screen is gone.
WEB 0.8.25GARMIN 2026.08.25.7
BUILD 51· 0.8.25 · 2026-08-25UNCROSS
  • The Karoo totals sit on the right side of the screen at last. Carbs used to be shown above the DRINK button and fluid above the GEL button, so every glance had to cross over - and the same was true of the last-gel and last-drink clocks.
  • Fluid is now on the left, over the button that adds fluid, and carbs on the right, over the button that adds carbs. The DUE chip moved across with the gel clock it belongs to.
  • The watch reads the same way round, so the two devices no longer disagree about which side water lives on.
WEB 0.8.25KAROO 2026.08.25.1GARMIN 2026.08.25.6
BUILD 50· 0.8.25 · 2026-08-25COLUMNS
  • The fuel screen is now two columns: drink on the left, gel on the right - the same way round as the Karoo. Your hand already knows that pattern from the bars, and it should not have to learn a second one for the wrist.
  • Each column runs the full height of the screen, which on a round face gives both targets more reachable area than stacked bands did.
  • Carrying two bottles or two gels splits that column in half; carrying one of something gives it the whole column rather than parking a dead cell beside it.
  • The countdown, the totals and the undo panel keep the strip across the top.
WEB 0.8.25GARMIN 2026.08.25.5
BUILD 49· 0.8.25 · 2026-08-25TOUCH
  • You can see where to tap. The lines dividing the fuel screen were drawn so faintly they were invisible on the wrist, which on a screen made entirely of targets is the one thing the chrome has to tell you.
  • Text no longer sits on the dividing lines - each target keeps a margin, so the rows read as separate things rather than one run-together block.
  • After you log something the top HALF of the screen becomes UNDO, and it says what it would take back: plus sixty millilitres, plus forty grams. The bottom half stays live, so another sip is still one tap.
  • The resting screen now carries the running totals - carbs, how many items you have taken, and millilitres - because on a long ride the countdown cannot answer how much you have actually had.
WEB 0.8.25GARMIN 2026.08.25.4
BUILD 48· 0.8.25 · 2026-08-25POCKET
  • Snap and go adds to the ride instead of replacing it. Scan the gels in the kitchen and push, then find one more in the garage and push again, and the ride now has both - it used to keep only whatever you scanned last.
  • The same is true for a drink scanned on its own: it joins the gels rather than evicting them.
  • The scan screen shows what is already packed above the push button, so what is going out of the door with you is never invisible.
  • The pocket empties only when you tap START A NEW RIDE. Nothing you packed disappears on its own, because a missing gel is invisible until the moment you reach for it.
WEB 0.8.25PHONE 2026.08.25.2
BUILD 47· 0.8.25 · 2026-08-25FIX
  • The new fuel screen works. It was asking the layout for the screen size through a name that did not exist, so it failed on its very first frame - which is why the Connect IQ error icon appeared the moment a ride started.
  • The screen now also survives its own mistakes: if drawing ever fails again it falls back to the previous layout for the rest of the ride instead of taking the field down.
WEB 0.8.25GARMIN 2026.08.25.3
BUILD 46· 0.8.25 · 2026-08-25GUARD
  • The new fuel screen can no longer take the field down mid-ride. If its drawing hits a fault it falls back to the layout that has ridden for weeks and stays there, instead of leaving the Connect IQ error icon where PaceKeeper should be.
  • Fixed the ring's arc: past a quarter of a gel interval it was being drawn with an angle below zero, which is not a valid one.
  • The build stamp moves with every fix, so the screen always tells you which version you are actually riding.
WEB 0.8.25GARMIN 2026.08.25.2
BUILD 45· 0.8.25 · 2026-08-25FACE
  • The watch fuel screen is now all targets. Two lines and a spine cut the round face into regions - the countdown at the top, your two gels, the bottles, and a swap strip - and every region is live edge to edge, so there is nothing to miss between two controls.
  • A gel is one tap, because it is named on the screen. A bottle counts: one tap is one sip, and the run files itself a few seconds after you stop tapping. That is why there is no plus or minus while riding.
  • The way back is the top of the screen, deliberately far from the cells you just tapped: after anything is logged it turns into UNDO for a few seconds, then REDO, then back to the countdown.
  • The ring around the edge is the gel clock - one full lap is one gel interval, draining as it runs out, and it turns amber when a gel is due and red when you are behind.
  • With more than two gels packed, the bottom strip pages to the next pair; with one gel or water only, the leftover space is given to what is actually there rather than shown as a cell that would refuse a tap.
WEB 0.8.25GARMIN 2026.08.25.1
BUILD 44· 0.8.25 · 2026-08-25SETTINGS
  • The gel reminder is a setting, and it starts at 25 minutes. So are sip size, carb-mix strength, the undo window, the sip settle, and whether a carb bottle is on the cage at all - six numbers, editable on the phone, on the web, and now on the watch itself.
  • The watch has settings for the first time. A sideloaded app gets no settings page in Garmin Connect, so these numbers sat stranded at their built-in values with no way to change them on the device; they now open from the activity's Connect IQ Settings.
  • Whichever surface you edited last wins. There is no per-device override and nothing is merged, because two versions of a number with no way to order them leaves you unable to say which one the ride actually used.
  • The carb bottle is off by default. Most rides are water, and an absent bottle now gives its space to the water target rather than leaving a dead half-cell you would reach for once.
  • Carbs per sip is worked out from sip size and mix strength wherever it is shown, and never stored on its own - a third number that can disagree with the two it comes from is a wrong carb value waiting to happen.
WEB 0.8.25PHONE 2026.08.25.1GARMIN 2026.08.24.3
BUILD 43· 0.8.24 · 2026-08-24FIELD
  • The data field can finally be paired. It has no keyboard and, sideloaded, no settings page in Garmin Connect - so the phone now sends the pairing code over bluetooth: SET has a SEND TO FENIX button that mints a code if needed and delivers it through Garmin Connect to the field, which pairs itself the next time it is on screen with the timer off.
  • The phone waits for proof - not Garmin's 'sent', but the field reporting its plan to the server - and says PAIRED with the revision and product count, the same line the Devices page shows.
  • Every failure on that path names its recovery in plain words: Garmin Connect missing, watch out of range, code expired, field not yet on the watch.
  • Buttons across the phone now answer a press-and-hold with a line saying what they will do - the same rule the web's tooltips follow.
WEB 0.8.24PHONE 2026.08.24.1GARMIN 2026.08.24.1
BUILD 42· 0.8.23 · 2026-08-24PAIR
  • The phone mints pairing codes. SET has a DEVICES card with NEW CODE - the same ten-minute, single-use code the web mints - so a watch in your hand no longer waits on a browser that is not signed in.
  • The Devices page notices a new device by itself while a code is live; it used to keep the old list until you refreshed.
  • Every control on the older web screens carries a tooltip saying what it does - thirty-two of them had none.
  • The watch's READY and DONE screens no longer draw the hexagon behind their text, and the in-ride mark is back to its reference size; the larger one ran through the lines.
  • tools/check_double_logs.mjs reads a day's intakes across every surface and raises any product logged on two devices within ten minutes - the check to run after the first ride with a phone-logged meal.
WEB 0.8.23PHONE 2026.08.23.8GARMIN 2026.08.23.5
BUILD 41· 0.8.22 · 2026-08-23LABELS
  • Amacx Turbo Gel Caffeine carries 200 mg of caffeine, from the product description you supplied - not 75. Its carbohydrate and sodium are untouched and the row stays unread: those are the numbers its sibling's label disproved, and the description gives no gram figure.
  • TL Protein+ carries about 420 mg of sodium, from the product description (400-440 mg across flavours). You no longer carry it, so its stash is zero and it drops out of the device catalogue.
  • PF Flow's zero sodium is confirmed: the product has no added sodium by design.
WEB 0.8.22
BUILD 40· 0.8.21 · 2026-08-23HELP
  • The Fenix types its own pairing code. Hold UP before a ride, choose PAIR, and enter the six characters from the web on the watch's keyboard - the Karoo's model. Garmin Connect is no longer part of it: a sideloaded app is not in the Connect IQ store, and whether Connect shows its settings at all depends on the phone.
  • A paired device can be unpaired from the web. The Devices page had no way to remove one; each row now carries UNPAIR, which revokes that device's token. The device rides its cached plan until it is paired again.
  • The Devices page speaks about devices, not only the Karoo. The code panel says how to enter it on each head unit, and the ride-start explanation no longer names one of them.
  • A HELP page on the web walks through the whole thing with the real screens: setting up and pairing each device, how syncing and refreshing work, how a fuel plan turns into prompts, and every button and tap on the Karoo and the Fenix.
  • The phone's first-run tour is a quick start now - six pages from scan to ride - and it opens from SET at any time.
  • The BUTTONS help on the watch is a native scrolling list - one key per line with its meaning beneath - instead of six two-column rows squeezed onto the round face, where the text overlapped at the top and bottom. Scroll it with UP and DOWN or a finger; BACK closes it.
WEB 0.8.21PHONE 2026.08.23.7GARMIN 2026.08.23.4
BUILD 39· 0.8.20 · 2026-08-23BUTTONS
  • The SYNC control on the Karoo is a button, not a caption. It was a 26 px word at the edge of a status line, and on the first ride with a synced plan (2026-08-23, one Enervit gel logged off the pulled catalogue) it had to be found rather than hit. The whole band is now 100 px, filled, with SYNC in 40 px type; the SETUP rows gave up five pixels each.
  • The header band on the fuel screen reads larger for the same reason.
WEB 0.8.20KAROO 2026.08.23.3
BUILD 38· 0.8.19 · 2026-08-23FENIX
  • The Fenix pulls the plan you push. Until now nothing ever delivered a plan to the watch - its cache had no writer - so every ride ran the built-in defaults and showed ROAD DEFAULTS. It now claims a pairing code pasted into Garmin Connect, pulls the newest plan and your product list at launch, and reports back what it is holding, exactly as the Karoo does.
  • The watch says where it stands. The profile screen leads with the last sync and its age, NOT PAIRED when there is no token, and PLAN UPDATED with one buzz when a new revision lands; hold UP before a ride for SYNC NOW.
  • Products you created yourself now work on the watch. A plan naming one of them was refused outright, because the watch only knew the shared library; it now keeps the catalogue the web serves and resolves your own ids through it.
  • The plan id the web mints is now representable on every device. The watch cannot hold a value above 2^31 in a uid half, and half of all plans carried one - the ack could never have matched. The low half is 31 bits now, the width the phone already used.
  • The phone shows what changed. SET carries the build you are running and a WHAT'S NEW list read from the same file the web renders, with a count of releases you have not looked at.
  • After a push the phone names every device that has reported the plan, not only the first.
WEB 0.8.19PHONE 2026.08.23.6GARMIN 2026.08.23.2
BUILD 37· 0.8.18 · 2026-08-23GLASS
  • The Fenix lays out to the glass instead of to a rectangle. Every line was sized against a flat inset, which is too tight across the middle of a round watch and still too generous at the top and bottom - so values were smaller than they could be, and the chip at the bottom ran its border off both edges of the screen. Each line is now measured against the actual width available at the height it sits.
  • The hexagon is bigger. It was drawn at the design reference's size for a mark sitting among other elements, but on the watch it is often the only thing on the face and left about a third of the glass empty.
  • The watch no longer tells you to log an intake on a device you did not bring. Riding the Fenix alone, the fuel alert said LOG IT ON THE KAROO - which was on the kitchen table. It now points at the phone, which is always with you and can always log.
  • PUSH TO KAROO is now PUSH TO DEVICES. The Fenix pulls the same plan from the same endpoint, so the button was naming one of its two destinations.
  • Settings have their own tab on the phone. Theme, scan model, daily cap, the API key and your account all lived at the bottom of the PLAN screen, which made the planner read as a settings page with a plan attached.
  • The phone tells you when the bike actually has the plan, not just when the server took it. It waits for the head unit to report back the plan it just pushed, and says so in amber if the device took the plan but threw your product list away.
  • You can plan a ride on the phone now: how long and how hard, picked from your drawer. It was read-only before, so planning a ride you had not just photographed meant opening the web app. A shortfall is shown before you push, while there is still time to add a gel.
WEB 0.8.18PHONE 2026.08.23.5GARMIN 2026.08.23.1
BUILD 36· 0.8.17 · 2026-08-23DRAWER
  • Amacx Turbo Gel is 40 g of carbohydrate and 200 mg of sodium, read off the sachet. It was recorded as 27 g and 100 mg and marked as checked, and it was one of the six products the Karoo falls back to - so the wrong figure was the one on the bars whenever the catalogue was rejected. It had never been logged on a ride, so nothing is rewritten.
  • The caffeinated Amacx gel is now marked unread. It carried the same numbers that just turned out to be wrong, and its own label has not been read - so the claim is withdrawn rather than a likely number invented.
  • After you push, the scan screen waits for the bike to confirm it. Until now PUSHED only meant the server accepted the plan, which was never the half that failed.
  • On the phone, a stash shortage no longer looks like an unidentified product. Both showed a question mark; empty drawer now shows a zero.
  • Deleting the Karoo's catalogue file returns it to the built-in products, which is what the code always claimed and never did until now.
WEB 0.8.17KAROO 2026.08.23.2PHONE 2026.08.23.2
BUILD 35· 0.8.16 · 2026-08-23LABEL
  • Scanning something that is not in your library now says so, and says that adding it also packs it for this ride. It used to read like filing paperwork, so a scanned Enervit gel was left stranded on the scan screen and never reached the pack list.
  • Adding a product shows the energy cross-check: 40 g of carbohydrate is about 160 kcal, so the calorie line on the packet is an independent statement of the same fact. Both product errors found this week fail that check on sight - PF Flow at 50 g in a 50 g serving implies 200 kcal, and Amacx Turbo Gel at 27 g implies 108 kcal against a panel that reads 160.
  • Enervit Carbo Gel C2:1 Pro is in the shared library at 40 g, read off the sachet.
  • The Karoo says when a new plan has landed. A plan pushed from the phone used to arrive in silence - the picker simply changed - which from the saddle is indistinguishable from the push having failed.
  • You can get back to SETUP from the fuel screen. Tapping DONE left you on HOME with no route back, so the SYNC band and the whole pack list were unreachable for the rest of the session. The header band now returns you there, and says BUILT-IN LIST in amber if the catalogue did not land.
WEB 0.8.16KAROO 2026.08.23.1PHONE 2026.08.23.1
BUILD 34· 0.8.15 · 2026-08-22STALE
  • A plan you have just made now actually reaches the bike. The server picked the plan with the highest revision number instead of the most recent one, and because a brand-new plan starts at revision 1 it could never beat an older plan you had edited a few times. Your Pocket plan from 2026-08-21 lost to a plan last touched on 2026-08-16, so every push was saved, answered with a 200, and then quietly never served.
  • The Karoo now reports back what it is actually holding, and the devices page shows it. Until now the web only knew the device had been in touch, never what it kept - which is how a rejected catalogue sat there for six days looking healthy.
  • SETUP has a SYNC band. It names the plan revision and product count the picker is actually serving, says in amber when those products are the built-in fallback rather than your drawer, and a tap pulls from the web instead of waiting out the ten-minute poller.
  • PF Flow is 30 g of carbohydrate per 51 g serving, read off the pouch. It was recorded as 50 g in a 50 g serving - a gel that is 100 percent carbohydrate, which cannot exist - and that overstated it by 67 percent. The pouch is 510 g holding 300 g of carbohydrate, so it is ten servings and not six. No intake of it was ever logged, so no ride history moves.
WEB 0.8.15KAROO 2026.08.22.2
BUILD 33· 0.8.14 · 2026-08-17CATALOGUE
  • Products you created yourself now reach the Karoo. Their ids start at 1000 and the device refused anything above 999, which threw away the whole catalogue and left six built-in products standing - five of which you no longer own.
  • That is why the picker showed the wrong gels on 2026-08-17. Your PF Flow pouch, the largest single item in the drawer, was never in it.
WEB 0.8.14KAROO 2026.08.17.1
BUILD 32· 0.8.13 · 2026-08-17BARS
  • The Karoo gel picker shows at most three products a page, and its page arrows are as tall as the CONFIRM buttons. Six rows cleared the touch floor on paper and were still the wrong target on a moving bike.
  • Food stops no longer appear in that picker. A cafe meal is bought on the road and logged on the phone, so a tappable row for it on the bars was two thirds of a page spent on something you cannot take out of a pocket.
WEB 0.8.13KAROO 2026.08.16.1
BUILD 31· 0.8.12 · 2026-08-16GUTTER
  • The ride-block row stays inside the page margin on a phone. It had been running off the bare edge of the screen rather than scrolling within its own box, which is also why the new edge fade had nothing to fade against.
WEB 0.8.12
BUILD 30· 0.8.11 · 2026-08-16EDGE
  • The ride-block row fades at its right edge on a phone when there are more blocks than fit, so a fourth and fifth block no longer hide off-screen.
  • The first attempt at that painted a pale block over the honeycomb texture; it fades the blocks themselves now instead of painting over the page.
WEB 0.8.11
BUILD 29· 0.8.10 · 2026-08-16SODIUM
  • Three products that carried a sodium of zero now carry a real figure: Maurten GEL 160 at 30 mg, SIS GO Isotonic at 10 mg, SIS GO Bake at 100 mg. Your sodium total no longer understates on rides that use them.
  • Those three are manufacturer figures, not label reads, and shared/products.json says so - their carbohydrate is still the measured part.
  • The Transparent Labs bar keeps a sodium of zero, meaning unknown: no source states it for the Oatmeal Chocolate Chip flavour, and the nearest one was a different flavour.
  • The ride-block hexagons on the plan page show a shadow at the edge when there are more blocks than fit. On a phone the third one sat clipped with nothing to say a fourth and fifth existed.
  • Three leftover food products from building the meal parser are gone; the chicken rice plate you planned around stays.
WEB 0.8.10PHONE 2026.08.16.2
BUILD 28· 0.8.9 · 2026-08-16ROADSIDE
  • You can log food from the phone during a ride: LOG SOMETHING NOW on the LOG tab, either a product from the library or a plate with the grams typed in.
  • It works with no signal. The log is written to the phone first and sent when there is a network, and it stays on screen as WAITING TO SYNC until the server has it.
  • The grams box for food opens on the figure your plan plotted for a stop, so the usual move at a cafe is to confirm rather than to guess.
  • Anything logged on the phone comes off the drawer the next time the web looks, and never twice.
  • The same product logged on both the phone and the head unit within ten minutes is raised as a question rather than counted twice - the two surfaces mint different ids, so nothing can merge them for you.
WEB 0.8.9PHONE 2026.08.16.1
BUILD 27· 0.8.8 · 2026-08-16LABELS
  • PowerGel Hydro Mojito is 26 g, not 25, and both it and GU Vanilla Bean are label-read now. Every product in your drawer carries a measured carb value.
  • The phone build that shares one daily AI ceiling with the web is on your Pixel - it had been left a build behind, still publishing a cap nothing read.
WEB 0.8.8KAROO 2026.08.15.5PHONE 2026.08.15.8
BUILD 26· 0.8.7 · 2026-08-15LIBRARY
  • BARS are a product kind. There were only gels, drinks and tabs, so every bar was filed as a gel.
  • Your drawer is in the stash with its own photographs: Cadence, GU Vanilla Bean, GU Tri-Berry, SIS GO Bake, PowerGel Hydro, Precision PF 30 and the Transparent Labs bar.
  • SIS GO Isotonic and PowerGel Original were promoted to label-read after you checked the packets. Two products carry figures from a retailer page and say so - an unverified carb value shows as a claim, never as a measurement.
WEB 0.8.7KAROO 2026.08.15.5PHONE 2026.08.15.7GARMIN 2026.08.15.1
BUILD 25· 0.8.6 · 2026-08-15STASH
  • Your stash goes down when a ride is imported, by what the ride actually recorded eating. Nothing is deducted at packing time, because gels come home.
  • Re-importing a ride, or importing the same ride from two devices, deducts once.
  • Eat more of something than the drawer held and it says so rather than hiding it - that is a gel from a friend, a shop, or a jersey pocket, and it is worth knowing before the next plan.
WEB 0.8.6
BUILD 24· 0.8.5 · 2026-08-15KAROO
  • The gel picker pages, with arrows. Seven products in a drawer and the picker could show six, so the seventh could not reach the bike at all.
  • A page is drawn at the size its own row count deserves, so a two-gel pocket keeps its half-page buttons and still reaches the rest with the arrows.
  • Every product is reachable now, not just what you packed - a gel handed over at the top of a climb could previously only be logged by tapping something else. Rows outside your loadout read NOT PACKED.
WEB 0.8.5KAROO 2026.08.15.4
BUILD 23· 0.8.4 · 2026-08-15STASH
  • The stash has a TABLE view beside the honeycomb - the comb reads a shelf at a glance, the table reads the numbers.
  • Products show YOUR OWN PHOTO, cropped from the scan that found them. Every cell used to fall through to a code on a tile because nothing ever wrote a picture. Still never a brand logo: a wordmark looks like verification of numbers nobody checked.
  • CLEAR ALL waits for the server before it clears the screen. It used to clear optimistically and could leave a cleared page over rows that were still there.
WEB 0.8.4
BUILD 22· 0.8.3 · 2026-08-15SCAN
  • The phone and the web now agree on which vision model reads your labels. The phone kept its own copy of that setting and never compared it, so it had been scanning on the cheap low-resolution model while everything else believed otherwise.
  • The model picker states the RESOLUTION each one reads at, and warns when a model is not fit for a nutrition panel. It used to advertise only price, which made the wrong choice look like the good deal.
  • Scan cost is measured rather than assumed: a real two-photo read costs about six times the old estimate, so the daily cap now stops you where it says it will.
WEB 0.8.3PHONE 2026.08.15.4
BUILD 21· 0.8.2 · 2026-08-15SCAN
  • The scan understands a DRAWER: many different products laid out and shot twice, front and back. It was told the two photos were one product seen from two sides, and merged eighteen gels into one item.
  • It also expects packets to lie at any angle. Upside-down text used to be a reason to skip a packet; on a real drawer photo the read went from six wrong names to seventeen packets across seven correct products.
  • LOOK IT UP works. It had never once succeeded - the reply was cut off before it finished its first field, every time.
  • A scan that runs out of room says so, instead of failing with a JSON error.
WEB 0.8.2PHONE 2026.08.15.6
BUILD 20· 0.8.1 · 2026-08-15FIX
  • The plan and the gel list now always come from the SAME plan. They were fetched by two different orderings, so the device could pull today's plan with a three-day-old gel list and offer one gel out of five - while reporting a successful sync.
WEB 0.8.1KAROO 2026.08.15.1
BUILD 19· 0.8.0 · 2026-08-15FIX
  • The Karoo asks for a new plan while it is parked, so a pocket pushed from the phone arrives without waiting for a ride to start and finish. It only ever asked at start-up before, which is why a plan pushed on the 14th was still not on the device on the 15th.
  • It also asks the moment the FUEL field comes on screen, and adopts a cached plan's gels when there is no signal at all - a bike computer on the bars is normally off Wi-Fi.
WEB 0.8.0KAROO 2026.08.15.1
BUILD 18· 0.7.0 · 2026-08-10
  • New RIDES page: the whole ingested history with a chart per fuelled ride, plus WHAT YOU ACTUALLY RIDE ON — the all-time product tally.
  • All-time rates cover only the rides that logged intakes; the page says so. Averaging in rides from before the FUEL field existed would describe the software's age, not your riding.
BUILD 17· 0.6.1 · 2026-08-10
  • WHAT WENT IN — each ride now lists its products as text: gels counted with their carbs, drinks summed in ml. A code this build cannot name is listed as UNIDENTIFIED rather than quietly folded into a neighbour.
BUILD 16· 0.6.0 · 2026-08-10
  • The ride chart now tells gels from drinks: a tall gold tick ABOVE the axis for a gel, a short tick BELOW for a sip. Hover either one and it names the product.
  • Brands resolve through the legacy map — pk_fuel_gel carried an ad-hoc 1-7 code before 2026-07-30 and a library id after, so old rides name their gels correctly too.
  • History backfilled to 29 May: 47 rides, no errors.
BUILD 15· 0.5.2 · 2026-08-10
  • Hammerhead sync takes a maxRides for a deliberate backfill (bounded at 30) and now REPORTS every ride it wrote — carbs, intakes, fluid — instead of only counting them.
BUILD 14· 0.5.1 · 2026-08-10
  • Garmin sync fixed: Garmin streams its download archive, so the sizes in the ZIP's local headers are zeros — the reader now uses the central directory, which carries the true ones.
BUILD 13· 0.5.0 · 2026-08-10
  • GARMIN CONNECT is live — switch between it and Hammerhead with the radio buttons; still exactly one importer, so a ride can never land twice.
  • Ported from the proven visus bridge (SSO login, service ticket, OAuth1 pair, MFA supported). One deliberate change: PaceKeeper downloads the ORIGINAL FIT rather than the TCX, because TCX carries no fuel fields.
  • No password is stored for either connection — Garmin keeps an OAuth1 token pair, verified against Garmin before it is written.
  • The daily cron now serves both sources, selected per athlete by the query itself.
BUILD 12· 0.4.1 · 2026-08-10
  • Hammerhead: if the password is refused, connect by pasting the token your own signed-in dashboard already holds (F12 → Console → copy(localStorage['jwt:refresh'])). Nothing but the token leaves your machine, and it is verified before it is stored.
BUILD 11· 0.4.0 · 2026-08-10
  • Hammerhead now connects through SRAM ID — and NO PASSWORD IS STORED. You sign in once in Settings; the server exchanges the credentials for tokens on the spot and keeps only a refresh token, which renews itself and is revocable from your SRAM account.
  • Two-factor supported: if SRAM asks, the card asks you for the 6-digit code.
  • Any password saved under the previous scheme has been wiped from the database.
BUILD 10· 0.3.1 · 2026-08-10
  • Hammerhead sign-in now matches the dashboard exactly (form-encoded, lower-cased email) and reports the real reason it was refused — including the SRAM ID case, where no Hammerhead password exists to use.
  • The demo plan is called "Example ride (demo)" — it read as real history on TODAY.
BUILD 9· 0.3.0 · 2026-08-10
  • HAMMERHEAD AUTO-SYNC: connect your Karoo dashboard in Settings and rides import themselves — the ORIGINAL FIT with the fuel fields intact. A daily cron does it hands-free; SYNC NOW does it immediately.
  • ONE ride-import connection, never two (Hammerhead / Garmin / manual) — duplicates were the failure mode, so it is a choice, not switches. intervals.icu stays plan-only: its FIT copy drops the fuel fields.
  • TODAY draws the ride now: planned vs eaten as staircases, a tick per intake, and the longest no-intake gap shaded — the visus fuel-tab idea, reduced to a morning glance.
  • Signed in, an empty stash STAYS empty — no more seeded demo products wearing your name. RESET STASH removes every row for a clean refill; CLEAR ALL still just zeroes counts.
BUILD 8· 0.2.6 · 2026-08-10
  • RIDE RECONCILIATION on TODAY: upload the FIT off the Karoo — planned vs eaten from the file's own fuel fields, intake count, fluid, adherence. The intervals.icu re-encode is refused loudly (it drops the fields).
  • Picking a past ride or calendar workout now moves the duration slider and intensity with it (and the slider steps by 5 min).
  • The Karoo now PULLS the plan: paired device fetches the newest revision pre-ride and caches it — pk_fallback finally says PLANNED on a planned ride.
BUILD 7· 0.2.5 · 2026-08-10
  • Moving the duration slider rebuilds the blocks live — a third hour appears as you drag past 2:15.
  • The TARGET readout carries the selected block's truth: warn when it misses its ask, with a '60 OF 100 G · UNDER' status line.
BUILD 6· 0.2.4 · 2026-08-10
  • + ADD FROM STASH works: a picker lists your counted stash — carbs, count, tap to add to the editing block.
BUILD 5· 0.2.3 · 2026-08-10
  • Plan page fixed — the workspace had vanished from the page body entirely.
  • Duration is one slider (20 min – 8 h, 15-min steps) with a live H:MM readout.
  • intervals.icu: the athlete id is optional now (the key alone identifies you), and a stale error no longer lingers after a successful pick.
BUILD 4· 0.2.2 · 2026-08-10
  • Stash honeycomb scaled ×1.44 — the cells use the page now instead of swimming in it.
  • Plan: PAST RIDES from intervals.icu — your last 30 days with time and distance, click one to plan a ride like it. The calendar pull now says plainly when the key works but today is empty.
  • Scan: your personal library products (ids ≥ 1000) join the AI digest, so scanning your own product matches it.
BUILD 3· 0.2.1 · 2026-08-10
  • Settings: OpenRouter cost tracking (design 1d) — TODAY spend against the hard cap, a 14-day bar chart with the cap line, and the recent calls ledger.
  • Stash: the count/par chip is one line again (the stacked version overlapped the row below), and the fill-to-par gauge is the default view — a cell fills from the bottom in proportion to par, warn outline below half.
  • TODAY page, editable library (your ids ≥ 1000), and manual-first ride sources shipped earlier today.
BUILD 2· 0.2.0 · 2026-08-10
  • Production launch at pacekeeper.letzi-labs.com — dark by default, P/K mark.
  • SCAN: photograph your gels (front, back, or both) — AI reads the labels against the library; confirms land in the stash; unknowns get web research with sources.
  • Model choice in Settings, with per-call spend tracked against a $0.50/day cap.
  • LIBRARY page — your in-stash products sort first; unverified rows stay loud.
  • Stash: counts persist, CLEAR ALL for a fresh count, shopping list from pars.
  • Devices: pairing codes verified end-to-end against a real Karoo.
  • New library row: 133 Amacx Drink Gel Orange (label read by the athlete).
BUILD 1· 0.1.0 · 2026-07-30
  • The four-surface expansion: web planner + stash, Karoo extension, phone app, Fenix app/field.
  • FIT contract amended (A1–A8); fields 0–8 frozen, fuel block 16–38.
  • Google sign-in via the shared letzi-labs Supabase (Flow A, appended audience).
BUILD DEV