Skip to content

Add a redesigned interface with Now, Trends and Logbook tabs (next-dev) - #2621

Open
Nutcasey wants to merge 17 commits into
LoopKit:next-devfrom
Nutcasey:loop-ui-redesign-next-dev
Open

Nutcasey wants to merge 17 commits into
LoopKit:next-devfrom
Nutcasey:loop-ui-redesign-next-dev

Conversation

@Nutcasey

@Nutcasey Nutcasey commented Oct 28, 2026 •

Copy link
Copy Markdown

This is the redesigned interface from #2615 (Now, Trends, Logbook and Settings tabs), rebuilt on next-dev. #2615 is now closed; its description covers the design, the error states, the appearance and icon options, the localisation and the widget, and all of that applies here. This description covers what changed to fit next-dev.

The first six commits follow #2615's commits one for one. The later commits are the review, parity and fix updates listed below. The branch is rebased on next-dev e0eb9856 (30 October 2026).

What changed for next-dev

  • Home screen. next-dev hosts StatusTableViewController inside the SwiftUI StatusTableView with its own action bar. In the new interface the tabs wrap that hosting controller and the action bar is hidden (StatusTableView.showsActionTabs(_:)), because Now has its own Add carbs, Bolus and Presets buttons. The classic interface is next-dev's screen, unchanged.
  • Data. The Now screen reads LoopDataManager.algorithmDisplayState, activeInsulin and activeCarbs, plus SettingsManager and TemporaryPresetsManager, instead of getLoopState and LoopSettings. The day pages' insulin and carbs on board come from two small LoopDataManager helpers. They use next-dev's own maths: doses annotated with basal history, and the carb absorption review.
  • Presets. On next-dev, pre-meal is one of the presets on the Presets screen, so the Now screen has one Presets button that opens it, rather than Add a redesigned interface with Now, Trends and Logbook tabs #2615's pre-meal menu. The button shows the active preset's name. next-dev's active-preset banner stays above the screen.
  • Closed loop paused uses DeviceDataManager.closedLoopDisallowedLocalizedDescription (no sensor session, or a manual temp basal).
  • Status rows. next-dev already draws No Recent Glucose, Tap to Resume and bolus progress as rounded cards, so Add a redesigned interface with Now, Trends and Logbook tabs #2615's card styling for them is left out.
  • Deeplinks. DeeplinkManager is gone on next-dev. LoopAppManager.handle(_:) switches to the Now tab before opening the carb, bolus or presets screen. The widget's buttons use the shared Deeplink type.
  • Settings tab. It selects Now before presenting Settings. Device and service setup screens open from Settings through StatusTableViewController, which is only in the window while Now is selected. Without this, choosing a service in Add Service from Trends or Logbook showed nothing.
  • Closed-loop history for Trends. This is recorded from SettingsManager.dosingEnabled. LoopDataManager.automationHistory keeps only 36 hours, too short for the 90-day view.
  • Strings. The catalogue keeps next-dev's entries and comments and adds the redesign's keys and translations. next-dev's Statistics screen gains translations for the labels it shares with Trends: Average, GMI, High and Low.
  • Names. next-dev has its own AGPChartView (Statistics), so the Trends chart is TrendsAGPChart.

Screenshots (iOS 26.3 simulator, Pump and CGM Simulators)

Now while a bolus is delivered Trends, 14 days Day page with insulin and carbs on board A service set up from Settings New Interface off: next-dev's classic screen

Testing

On the iOS 26.3 simulator, with the Pump and CGM Simulators and data carried over from a dev install:

  • Now: carbs and a bolus entered and delivered; IOB, COB, prediction, Today and the loop, pump and CGM pills each open their screen; a preset started; delivery suspended and resumed.
  • Trends and Logbook: Day, 7 d and 14 d checked against the day totals. A carb entry edited and deleted from Logbook.
  • Settings: a service added from Add Service with Logbook selected; New Interface switched off and on; Night appearance and the alternate icons.
  • Other: German; the redesigned Lock Screen Live Activity.

LoopTests: 389 of 391 pass. The two failures, BolusEntryViewModelTests.testCarbEntryDateAndAbsorptionTimeString and …String2, fail the same way on plain next-dev on the same simulator ("12:00 PM" against "12:00").

Known limitations

  • Upgrading from dev: loop runs that dev stored before the upgrade didn't come back from DosingDecisionStore.executeDosingDecisionQuery, which drops records it can't decode. So "Loop active" on Trends starts at the upgrade. I haven't confirmed which field fails to decode.
  • Negative predictions: with a large IOB the prediction can go below zero, and "Eventually" shows that value. The classic screen does the same, as neither LoopAlgorithm nor dev's LoopMath sets a floor.
  • Runtime coverage: the medium Home Screen widget was verified on the iOS 27.0 simulator in the 31 October comprehensive review below. Other widget sizes and Lock Screen/expanded Live Activity layouts were not re-exercised in that review. A real iPhone install was checked in the 28 October rebase update.

Trends gains what Statistics shows — 1 November 2026

Trends and Statistics answer the same question, so 5e4d93cb brings into Trends everything Statistics shows that Trends lacked. Trends already had the 7/14/30/90-day ranges, GMI, average, CV, CGM active, time in range, the daily pattern and daily insulin with its basal, bolus and automatic split.

On Statistics Now on Trends
"Goal:" under GMI (<7%), Average (<154 mg/dL), Variability (≤36%) and CGM Active (>70%) One "Aim:" line under the summary tiles: average under 8.6 mmol/L (154 mg/dL), GMI under 7%, CV 36% or less. CGM active over 70% is on the Time in range card, beside its figure.
Time in range goals: in range >70%, above <25%, below <4%, very high <5%, very low <1% The Time in range card's "Aim:" line carries all five.
"Usually X U by HH:MM" under Today Under "Total so far" on today's Day view, and under the Insulin per day chart on longer periods ending today. Same InsulinDeliveryHistory.typicalDelivery, so the same figure.
"· scheduled X U" beside average basal "Scheduled X U" under Basal in Basal and bolus: the schedule that applied (stored profile with presets), or today's schedule where the profile history doesn't reach.
"Showing N days of data…" when the period isn't full "CGM data covers N of M days." under Summary.
Fingerstick (user-entered) readings left out of the figures Left out of every Trends figure too. The day timeline still draws them.

Not carried over: "This device keeps N days of glucose. Increase the cache duration…" (Trends reads older days from Apple Health, so the local cache doesn't limit it), and the two helper lines "Each 5% increase in range is clinically beneficial" and "Each 1% time in range ≈ 15 minutes" (Trends shows each band's hours a day).

On the same 14 days of simulator data, GMI, average, CV, CGM active, "usually by now" and scheduled basal match Statistics exactly. Here Statistics stays in Settings in the classic interface and is hidden in the new one, as before. The same commit is in the split as part 1's second commit (#2637).

The additions on Trends, outlined

🤖 Generated with Claude Code

https://claude.ai/code/session_01QHnVPACb9uRhdQPgF5h2mj

Review update — 28 October 2026

A comprehensive code-reviewer-cx review of the full PR found four issues, fixed in 42b476ad:

  • Historical IOB now applies the preset multipliers to the stored basal history before calculating net active insulin.
  • Day and Logbook history use stored basal profiles and dated presets, avoiding repetition of recent presets across older days.
  • Weekly insulin bars use the same eligible-day rule as the summary, excluding missing days and a partial current day when complete days exist in that week.
  • The status error alert reads the manager's last completion time, so the hidden classic HUD cannot cause an older device error to mask the current error.

Both added regression tests failed on the original code and pass after the fixes. The two affected suites pass all 33 tests. Simulator app and test builds succeed.

With an isolated XCTest runner using the compiled production and test objects, 409 of 411 executed tests pass. The other two are the existing BolusEntryViewModelTests.testCarbEntryDateAndAbsorptionTimeString / …String2 locale-format failures, reproduced on the original PR head. Four DeviceDataManagerTests remain unverified because the isolated runner lacks HealthKit's registered app-host context. The normal Xcode-hosted run remains blocked during test-host launch; this is not a passing full hosted-suite result.

The loop simulator was driven through preset activation, carb entry and saving, Logbook editing, CSV sharing, day navigation and Settings presentation. After the fixes, Now, the day pages, Logbook, Settings and the 90-day Trends view were checked again. Widget and Live Activity changes were reviewed and built; their runtime rendering remains unverified in this review.

Parity update — 28 October 2026

Checked the new interface screen by screen against next-dev's own screens and totals, on the loop simulator (Xcode 27.1, iOS 27.0, Pump and CGM Simulators, 90 days of generated history). Fixed in 41e9535a:

Parity

  • IOB tile opens next-dev's Insulin Delivery Log, which has dose details and manual dose entry. The classic IOB chart uses the same showInsulinDelivery, so the two can't drift apart.
  • Loop pill opens next-dev's LoopStatusModalView. A newer device or loop error still opens the error first. With no classic HUD to keep the modal's "ago" current, it showed "Automation was unsuccessful" while Loop was running; the value is now set before the modal is presented.
  • Settings hides next-dev's Statistics row in the new interface, because Trends covers glucose metrics, time in range, AGP and daily insulin. Current Setup stays, as it has no counterpart.
  • Day page hides the tab bar when pushed from Now, as next-dev's Insulin, Carbohydrates and Predicted Glucose screens do.

Accuracy

  • Basal now follows next-dev's InsulinDeliveryHistory rule. From the first dose record, time without a basal record counts at the pump's programmed rate, rather than as no insulin. On the same data, Trends and next-dev's Statistics now agree on basal (25.6 and 25.3 U/day). The remaining gap in total insulin comes from the period, not the maths:
    • Trends' 7 d runs to today and averages the complete days ("6 of 7 days").
    • Statistics uses the seven complete days before today.
  • Totals match across screens: today's insulin is the same on Now, the Day page, Logbook and the Insulin screen (28.8 U, rising as the day went on).
  • Pump alarms in Logbook show the pump's own alarm text, or "Pump alarm", instead of the event's debug title. The simulator's events were showing a UUID.

Performance (debug build, simulator)

  • Trends loaded in 6.6–16.4 s, almost all of it in loopRuns(), which paged and fully decoded every stored dosing decision. It now decodes only date, reason and errors for the local window through DosingDecisionStore.getDosingDecisions, and loads in 0.5–1.8 s.
  • Logbook took 12.3 s, because basalSegments scanned every record for every cut. A binary search bounded by the running furthest end brings it to 1.7 s. The 90-day view spends about 9 s reading Apple Health for the 83 older days.

Noticed, outside the redesign (not changed here)

  • next-dev's simulated history writes pump events without reconciling them, so getNormalizedDoseEntries ignores them, and Trends, Statistics and the Insulin screen show no generated insulin. The generator also adds a bolus about every 20 minutes, although its comment says eight a day. For these screenshots I adjusted it locally (not committed).
  • Its alert-history step never returns, so the "Generating" spinner stays up after the rest of the data is saved.
  • next-dev's Carbohydrates screen showed "40 g absorbed" for a 10 g entry.

The "Alarms are turned OFF" banner in the screenshots is next-dev's warning: the simulator can't grant AlarmKit or Critical Alerts.

Screenshots (iOS 27.0 simulator)

Now Now, Today so far Loop pill: LoopStatusModalView IOB: Insulin Delivery Log

COB: Carbohydrates Next 3 hours: Predicted Glucose Day page Presets

Trends, 14 days Trends, daily pattern and insulin Trends, insulin and Loop status Trends, 90 days

Logbook Logbook, edit or delete carbs Settings: New Interface, no Statistics row Appearance and App Icon

Now, dark Trends, dark Logbook, dark Insulin, dark

Tests: LoopHistoryMathTests gains a regression for the programmed-rate rule. As noted above, the Xcode-hosted LoopTests run still hangs at test-host launch on this machine, so the new test has been compiled but not run there.

Basal and bolus split — 29 October 2026

Trends, the Day page and the Logbook now show basal and bolus explicitly, with the total, instead of one insulin number.

  • Trends has a "Basal and bolus" card above Insulin per day. It shows a ratio bar, basal and bolus in units and percent, manual and automatic bolus, and the total.
    • For a period it's the average per day, over the same days as the Insulin per day figure. For a single day it's that day, and today is "so far".
    • The Insulin per day legend now only names its marks, because the figures are in the card above it.
  • Day page: the same card replaces the Bolus and Basal tiles.
  • Logbook: each day header has a hairline ratio bar and "Basal x · Bolus y · z U" under the date.
  • Colour: bolus gets its own token, a deeper orange than basal's pale fill. Automatic bolus is the same colour hatched, on the timeline, daily bars and legends; in the hairline it is a tint. We looked at Glooko (purple: basal #6C4E87, bolus #BD9CBB) and Tidepool (blue: basal #19A0D7, bolus #7CD0F0, automated #00B2C3). Both keep insulin in one colour family, tell basal from bolus by lightness, and reserve red for warnings. Loop does the same in its own orange: blue is Loop's glucose colour, and the IOB, classic screens, watch and widgets all stay orange.
  • Unclassified doses: a dose in Apple Health without MetadataKeyAutomaticallyIssued is no longer counted as manual. While any bolus in range is unclassified, the manual and automatic detail is hidden rather than guessed.
  • CSV export adds manual_bolus_u and auto_bolus_u columns, which are blank for a day with an unclassified bolus.
  • Translations: the 15 new strings are translated into the redesign's 23 languages. Native-speaker review is welcome.

Tests

  • New: testInsulinSplitSeparatesManualAutomaticAndUnclassifiedBolus. Changed: the CSV test now checks the ten columns, including a day with an unclassified bolus.
  • The hosted run still hangs at launch on this machine, so the tests were run with the simulator's xctest agent on the built test bundle.
    • LoopHistoryMathTests: 22 tests, 0 failures.
    • All classes except DeviceDataManagerTests, which needs a HealthKit host: 413 tests, with only the 2 known BolusEntryViewModelTests 12-hour-clock failures. These also fail without this change.

Checked on the simulator: Trends for one day (today), 14 days and 90 days, the weekly bars, the Logbook, and the Day page, in light and dark and at Accessibility Extra Large text. The card, the Summary tile and the Logbook totals agree.

Trends, today Trends, 14 days Logbook Day page

Trends, today, dark Trends, 14 days, dark Logbook, dark Day page, dark

Basal and bolus contrast — 30 October 2026

In use, basal and bolus were still too alike. The part of basal you notice is its edge line, and it was nearly the same orange as bolus: 1.04:1 in dark mode and 1.43:1 in light. The pale basal fill barely shows against the card (1.34:1).

  • Colours. Everything stays orange.
    • Basal is paler: #FCE3C2 light, #43301B dark.
    • Basal's edge is a quiet tan: #E3B983 light, #6E5232 dark.
    • Bolus is deeper in light mode (#A9480A, ink #8A3A06). Dark mode bolus is unchanged.
    • The edge and bolus are now at least 3:1 apart (3.2:1 light, 3.6:1 dark), and the fill and bolus are 4.7:1 and 6.3:1.
  • Gaps. Bolus parts now get a thin card-coloured gap wherever they touch basal or each other: in the Insulin per day bars, the ratio bar and the day timeline. This follows WCAG 1.4.11 and technique G209 for touching chart parts.
  • Options considered. Violet basal with orange bolus, and the reverse. Both were clearer still, but we kept Loop's insulin orange.
  • Tests. No logic changed. Checked on the simulator on Trends (14 days and Day), the Logbook and Now, in light and dark.

Basal and bolus card Insulin per day Logbook Today so far

Basal and bolus card, dark Insulin per day, dark Logbook, dark Today so far, dark

Add carbs, Trends Day and Logbook insulin kinds — 31 October 2026

Add carbs is redesigned. CarbEntryScreen drives the existing CarbEntryViewModel unchanged, so validation, warnings, favourite foods and the hand-off to the bolus screen all behave as before.

  • The amount is the main element on the screen.
  • "How fast it absorbs" offers Fast, Medium, Slow and Other. Each card draws Loop's own absorption curve (the piecewise-linear model in CarbMath) on a shared time axis, so a slow meal draws as a long, low ramp. Other shows "Custom" until it is chosen, then offers a food type and an absorption time.
  • "Eaten" has quick choices (Now, 15m, 30m, 1h ago) and a time picker.
  • Continue stays pinned at the bottom of the screen.
  • Scrolling or tapping Done puts the keyboard away. At accessibility text sizes the cards switch to a 2 × 2 grid.
  • The classic interface still uses CarbEntryView.

Trends → Day now shows the same timeline card as Now's "Today so far", instead of an AGP with one day of data. The tiles use whole counts and say "Insulin", "Carbs" and "Boluses". Carb entries close together share one label showing their total, so labels no longer print over each other.

Logbook:

  • Manual bolus, automatic bolus and basal are drawn the way the charts draw them: solid, hatched and pale basal.
  • Runs of automatic boluses fold into one row, which opens a list of them.
  • At accessibility sizes, the amount moves under the title and the day totals move under the date.

Strings: new strings are added in all 23 languages. These translations are mine and haven't been reviewed by native speakers.

Testing:

  • On the iOS 27.0 simulator with the Pump and CGM Simulators: entered 60 g with Other (🍝, 6 h, eaten 30 minutes ago), checked the hand-off to Meal Bolus and delivered 5.5 U. Then edited that entry in the Logbook to Medium and saved it without a bolus. Checked Trends → Day, the Logbook and the folded run list in light, dark and AX XXXL.
  • LoopTests: 429 tests, 2 failures. Both are the existing BolusEntryViewModelTests.testCarbEntryDateAndAbsorptionTimeString{,2} assertions that expect a 12-hour clock (they fail the same way without this PR).
  • New tests cover DayHistory.clipped(to:) and the folding of automatic boluses.
  • Installed 3fa82de3 on a physical iPhone 18 Pro (iOS 27.2) running Omnipod 5 and Dexcom G7 in closed loop. Loop relaunched in closed loop, and Now, Trends and the Logbook load with real pump history. Nothing was delivered or changed during this check.

A simulator issue found along the way, not caused by this PR: the Pump Simulator can lose a bolus if Loop is killed before the bolus is finalised. MockKit/UnfinalizedDose.rawValue stores decisionId as a UUID, which isn't a property-list type, so saving PumpManagerState fails ("Error saving PumpManagerState") whenever a dose with a decision ID is in progress. After a restart, the pump state has no bolus, and the next sync's replacePendingEvents purges the mutable event. Storing decisionId.uuidString would fix it. This only affects the simulator pump.

Add carbs Other food type and absorption time Hand-off to Meal Bolus Editing a carb entry

Trends, one day Trends day timeline Logbook with manual, automatic and basal Folded automatic boluses

Add carbs, dark Trends day, dark Logbook, dark Add carbs at AX XXXL Logbook at AX XXXL

Comprehensive review — 31 October 2026

Reviewed the complete PR against next-dev e0eb9856 using code-reviewer-cx. Fixes are in 088e6bbd.

  • Favourite meals: choosing an absorption speed after a favourite no longer clears the amount or resets the absorption time. Favourite selection now applies synchronously on the main actor.
  • Historical targets: day charts read stored target profiles and dated presets, including their actual end times. They no longer repeat today's profile or omit ended presets.
  • Midnight boluses: the initial history query retains instantaneous boluses at the start of the day.
  • Carb entry: the exact picker includes the date; a prefilled older time does not select Now. The amount field has an explicit accessibility label. The favourite editor receives the selected preset emoji.
  • Accessibility: the date/time picker stacks beneath its label at accessibility text sizes.

Simulator verification: Xcode 27.1, iOS 27.0, Device Hub loop, Pump and CGM Simulators. Built from an isolated PR checkout and clean LoopKit checkout, excluding the unrelated local Glooko integration changes.

Exercised favourite selection and speed changes, Meal Bolus hand-off, saving and editing carbs through Logbook, every Logbook filter, folded automatic-dose details, day navigation, all Trends periods through 90 days, previous/next periods, CSV/PDF sharing, classic/redesigned interface switching, dark mode, AX XXXL and the maximum-meal warning. Checked the final accessibility layout after rebuilding. The medium Home Screen widget now has runtime verification, including glucose, COB, forecast and its four actions. Lock Screen and expanded Live Activity layouts were not re-exercised in this review.

Tests: the two bug regressions fail with the pre-fix scheduling and target-selection behaviour restored; all three new tests pass with the fixes. The isolated XCTest run executes 432 tests: 430 pass, two fail. Both failures are the existing BolusEntryViewModelTests.testCarbEntryDateAndAbsorptionTimeString{,2} 12/24-hour formatting assertions, also reproduced with the pre-fix behaviour.

Coverage limit: the normal Xcode-hosted run stalled at launch and was stopped after 150 seconds without a completed test result. Four DeviceDataManagerTests remain unverified: HealthKit reports a nil client bundle identifier, including in a separately registered disposable test app. This is not a clean full hosted-suite pass.

Changing a favourite to Fast retains 35 g Trends Day The four doses inside a folded automatic-bolus row Medium Home Screen widget running in the simulator Date and time at AX XXXL in dark mode

Add carbs rebuilt — 1 November 2026

e95e1198 replaces the 31 October Add carbs layout above. CarbEntryViewModel is still unchanged, so validation, warnings, favourites and the hand-off to Meal Bolus behave as before.

  • Meal preview. The amount sits over the meal's absorption curve (Loop's piecewise-linear absorption), drawn in the style of the day page's carbs-on-board chart: soft fill under a line, solid up to now and dashed after, hour gridlines and a Now rule. Grams set the curve's height, the speed its length and the eaten time where it sits against now. Under it are the eaten time and "Absorbed by". Touch and hold shows the carbs left at that time.
  • Controls. Speed and eaten time are each one track with a sliding selection. The exact date and time moved into the Eaten heading. Section titles are smaller so the preview leads.
  • Keyboard. A new entry now opens with the amount focused, as the classic screen does. Focus set while the sheet was still presenting had been dropped.
  • Fixes found while testing. Choosing a favourite after Other left Other selected instead of the favourite's speed. At accessibility text sizes the preview's labels now stack instead of overlapping.
  • Strings. Two new keys, Absorbed by %1$@ and Eaten at %1$@, absorbed by %2$@ (the chart's VoiceOver summary), English only.

Testing (iOS 27.0 loop simulator, Pump and CGM Simulators): Fast, Medium, Slow and Other with absorption-time steps; Now, 15m, 30m and 1h ago; a favourite after Other; Continue to Meal Bolus (23 g 🍕, 08:08 + 5h on the final build; backed out without saving); editing a Logbook entry; dark mode. Light mode, AX XXXL and Logbook editing were checked on the previous draft of the preview, which used the same layout with a hand-drawn curve. Not verified on the final build: the touch-and-hold callout, light mode and AX XXXL.

Add carbs, empty 45 g, Medium, eaten an hour ago 23 g, Fast, eaten 15 minutes ago

One colour per meaning — 1 November 2026

5ebec987 is a pass over every screen for colour consistency. Changes are to colour only, plus one shared view.

  • One insulin ink. Bolus amounts had their own ink (bolus-ink, #8A3A06), darker than the one used for IOB and day totals (insulin-ink, #A35200). In light mode, "Today so far" showed the total and the bolus in two different oranges side by side. insulin-ink now matches the bolus marks (#8A3A06 light, #FFA347 dark), and bolus-ink is removed. The bright insulin orange stays for the Bolus button and the active insulin curve, because black text on the deep bolus colour fails contrast. Contrast is about 8:1 on white, 6.4:1 on the light tiles and 7:1 on the dark tiles.
  • Tinted amounts, everywhere they stand alone. Insulin and carb amounts take their ink. Glucose, basal, counts and figures beside a legend swatch stay in the text colour. The Trends Summary tiles, the Logbook day totals and the Basal and bolus total were plain and now follow the rule. The rule is in the LoopDesign doc comment.
  • Open loop is grey, not red. The Trends Loop status bar, its legend and the Gaps list drew open loop in the critical red. The Now screen shows open loop in muted grey, and red is kept for problems that need action. "Limited" stays yellow, matching the stale-loop yellow on Now.
  • Basal "vs plan" on Now is now muted text, as in the Logbook, instead of insulin orange.
  • Day page stepper. It now uses the same round step buttons as Trends instead of blue chevrons. This is a new shared StepButton. The Trends step buttons now have a 44 pt touch target.
  • Add carbs. The cursor is now green to match the amount. The missed-meal and rising-glucose warnings now use the same card as the Now screen's alerts.
  • Checked and unchanged:
    • Carbs, in range and loop-fresh are three nearby greens. carbs and fresh are Loop's existing assets, which DerivedAssetsOverride can recolour.
    • In light mode the fresh green on the Loop status bar is under 3:1 against white.
    • Selection is shown three ways: Logbook filter chips, the Trends range control and the Add carbs choices. These are different kinds of control.

Testing (iOS 27.0 loop simulator, Pump and CGM Simulators): compared every screen in light and dark before and after the change: Now, Trends 14 d and Day, the day page, Logbook and Add carbs. The built asset catalog has no bolus-ink. Unit tests were not run, because no logic changed and no test references the removed token.

Before, light mode: total and bolus in two inks, and plain Summary tiles.

Before: Today so far, two insulin inks Before: Trends Summary, plain tiles

After, light mode:

Now Today so far Trends Summary Basal and bolus Loop status, open loop grey Day page Logbook

After, dark mode:

Now, dark Today so far, dark Trends Summary, dark Basal and bolus, dark Loop status, dark Day page, dark Logbook, dark Add carbs, dark

Codex review — 1 November 2026

Codex reviewed the complete 84-file PR diff from 5ebec987 against next-dev e0eb9856, using code-reviewer-cx, and fixed the outstanding issue identified in this review in 27b339dd.

Basal delivery on Now: a preset changes Loop's planned basal, while the pump continues its programmed profile until a temp basal is enacted. Now previously used the preset-adjusted plan as the delivered rate when no temp basal was running. It now keeps the programmed rate separate, including the fallback after a temp basal expires.

Reproduced and verified on the loop simulator: with automation off, the Biking preset at 22%, and the Pump Simulator delivering scheduled basal, Now showed 0.28 U/h while Loop's insulin log showed 1.25 U/h. The repaired build shows 1.25 U/h, +0.98 vs plan in the same state. The preset was ended and closed loop restored after checking.

Verification:

  • A fresh simulator app build and test build succeed; bundle signature verification and git diff --check pass.
  • Exercised preset activation, pump suspension/resumption, the existing insulin log, a 45 g Slow meal eaten one hour ago through the Meal Bolus hand-off, 90-day Trends, Day and previous/next navigation, and Logbook filters.
  • The freshly compiled isolated XCTest run executes 432 tests: 430 pass, two existing clock-format assertions fail (BolusEntryViewModelTests.testCarbEntryDateAndAbsorptionTimeString{,2}). The earlier baseline logs show the same failures; their production formatting code is unchanged.
  • The standard Xcode-hosted run stalled before XCTest connected and was stopped after 150 seconds. Four HealthKit-dependent DeviceDataManagerTests remain unverified. This is not a clean full hosted-suite result.
  • Both string catalogues retain all existing keys; changed format placeholders match their English source. Widget and Live Activity implementations were reviewed and built; their runtime layouts were not re-exercised in this pass.

Codex has reviewed this PR and fixed all outstanding issues identified in this review. No further findings meet the skill's confidence threshold of 80/100. The PR is ready for human review.

@Nutcasey
Nutcasey force-pushed the loop-ui-redesign-next-dev branch from 056eab5 to 54c9d85 Compare October 28, 2026 19:37
@Nutcasey

Copy link
Copy Markdown
Author

Rebased onto the current next-dev (3c4f8b0e, 11 commits newer than the previous base 1640e148). The rebase was clean, with no code changes to the redesign.

Checked after the rebase:

  • Simulator (Xcode 27.1, iOS 27.0, Pump and CGM Simulators): Now, Trends and Logbook load, with a single tab bar.
  • Installed on a real iPhone 18 Pro (iOS 27.2) with the Pump Simulator and a Dexcom G7 read through the Dexcom app.

LoopTests weren't run for this update. On this build machine the test host hangs before XCTest connects, with both ad-hoc and automatic simulator signing, so that's still to do.

This replaces #2615, which targeted dev and is now closed.

🤖 Generated with Claude Code

@Nutcasey

Copy link
Copy Markdown
Author

Reviewed the full 79-file diff at 54c9d857 against next-dev 3c4f8b0e using code-reviewer-cx, including the surrounding stores and controllers. Four high-confidence findings are fixed in 42b476ad.

Critical (confidence 90–100)

  • Historical IOB ignored preset-adjusted basal — confidence 95/100. Delivery matching a preset's basal could appear as positive or negative net IOB. The history calculation now applies the dated preset multipliers before annotating doses, as Loop's main calculation does.

Important (confidence 80–89)

  • Historical schedules could repeat recent presets on older days — confidence 89/100. Day and Logbook history expanded a repeating daily schedule based on the current profile. It now reads stored profiles and applies each preset over its actual dates.
  • Weekly insulin averages disagreed with the summary — confidence 89/100. Weekly aggregation included missing days and today's partial total. For two complete 30 U days, one missing day and a partial 3 U day, the bar showed 15.75 U/day. It now shows 30 U/day and retains the existing fallback when only a partial day is available.
  • An older device error could mask the current error — confidence 86/100. Error selection read the completion time from the classic HUD, which the redesign does not instantiate. It now reads loopManager.lastLoopCompleted directly.

Verification

  • Both added regression cases fail before the fixes and pass afterwards; all 33 tests in the two affected suites pass.
  • Simulator app and test builds succeed. The simulator was driven through presets, carb entry/saving, Logbook editing, CSV sharing and navigation. After rebuilding, Now, day navigation, Logbook, Settings and 90-day Trends were checked again.
  • The isolated XCTest run completed 411 tests: 409 passed, two existing locale-format failures. Both failures were reproduced using the original PR code. Four HealthKit-dependent DeviceDataManagerTests remain unverified: the normal hosted run fails during launch, and the isolated runner lacks HealthKit's registered app-host context. This is not a clean full hosted-suite pass.
  • Both string catalogues retain all pre-existing keys and translations. Added format placeholders and asset JSON validate. Widget/Live Activity code was reviewed and built; runtime rendering was not exercised during this review.

The PR description now records the fixes, current validation and limitations, and corrects the stale statement that #2615 is still open. No further findings met the skill's confidence threshold in this pass.

Nutcasey added a commit to Nutcasey/Loop-1 that referenced this pull request Oct 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP5sTMyrVG4zz5Wp4KM
Nutcasey and others added 10 commits October 30, 2026 18:26
…dling

Build Now, Trends and Logbook around Loop's existing controllers and stores.
Keep delivered quantities and history partitions accurate, preserve editing
drafts across updates, propagate load failures and share chart averages.
Per-day Trends figures leave out the day in progress and share insulin's
days, the day chart names a day without readings, and the Logbook carb
editor receives Loop updates on the main thread.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Driving the error states in the simulator (pump fault, comms issue,
suspension, sensor warmup, signal loss, sensor failed) showed that a
device problem could be off-screen: the status pills scrolled sideways,
so during warmup the CGM pill was past the edge and nothing visible said
so.

- Status pills wrap instead of scrolling.
- A device highlight, or a loop that hasn't completed for 15 minutes,
  gets a notice under the pills with the device's message and icon, what
  it means for Loop, and a tap through to the device; most serious first.
- Two-line plugin highlights ("Signal\nLoss") are joined.
- When Loop pauses closed loop (no CGM session or data), the pill says
  "Closed loop paused" instead of "Open loop".
- Loop's status rows (No Recent Glucose, Tap to Resume, bolus progress,
  presets) take the card shape in the new interface; the non-critical
  pump notice is left out while the Resume row shows.

LoopTests: 323 pass on the iPhone 17 Pro simulator (iOS 26.3).
On next-dev, Loop's status rows are already drawn as rounded cards (LOOP-5437), so the
new interface keeps them as they are rather than adding a second card behind them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVPACb9uRhdQPgF5h2mj
Settings gets an "Appearance and App Icon" screen:

- Appearance: System, Day or Night. It sets the window's interface
  style, so it applies to the whole app (new and classic interface,
  sheets included) and takes effect without a relaunch.
- App Icon: Classic (the primary icon, unchanged), Day, Night, and Day
  and Night, whose dark appearance variant follows the home screen's
  light or dark icons. Day, Night and Day and Night are alternate icon
  sets in DerivedAssetsBase, listed in the Loop target's
  ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES; small preview image
  sets show them in the picker because iOS doesn't expose alternate
  icons as images.

The new icons keep Loop's ring and add the blue reading dot from the
Now screen, on a light ground for Day and a midnight-blue one for
Night. The artwork was generated with GPT image generation and chosen
from two takes each.

iOS can report an error from its "icon changed" alert even though the
icon changed (the iOS 26.3 simulator does this every time), so the
picker trusts the icon iOS reports afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVPAQn8LyVAJrZEA3f2T
Every string the new interface shows or speaks now goes through
NSLocalizedString with a translator comment, and Localizable.xcstrings
gains 213 keys with translations in all 23 of Loop's other languages
(ar cs da de es fi fr he hu it ja nb nl pl pt-BR ro ru sk sv tr uk vi
zh-Hans). Fourteen existing keys the redesign reuses ("Bolus", "%1$@ U",
"Settings", ...) keep their translations and gain the languages they
were missing.

- Sentences with values are whole keys with positional placeholders,
  and counts ("%lld days", "%lld shorter gaps", "Loop · %lld changes")
  use plural variations, so no text is glued together in code.
- Numbers, dates, ranges and durations follow the user's locale:
  LoopFormat.number replaces String(format:), date ranges use
  DateIntervalFormatter and durations DateComponentsFormatter.
- The Trends one-day period has its own key, "Day (Trends period)",
  because "Day" is also the light appearance and icon name and some
  languages need different words for the two.
- The Now action buttons wrap to two lines and tile labels scale down,
  so longer languages don't truncate.
- The CSV export stays English with '.' decimals on purpose; it is
  data for spreadsheets, not display text.

Translations follow Loop's existing terms per language and were checked
for placeholder and plural-category integrity. Each language was run
through the simulator with NSShowNonLocalizedStrings. They have not
been reviewed by native speakers.
On next-dev the catalogue merge keeps next-dev's own entries and comments and adds the
redesign's keys and translations. The pre-meal menu strings are left out because next-dev
opens pre-meal from the Presets screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVPACb9uRhdQPgF5h2mj
…esign

The home screen widget and the Live Activity now follow the redesign's
rules from the Now screen: a white SF Pro Rounded glucose number with a
blue trend arrow, low and high said in words rather than by tinting the
number, Loop's state as a dot with words, sunken tiles, and device
problems written out.

- Widget: the Now hero with COB and Forecast tiles; the medium size adds
  Add carbs, Bolus, Pre-meal and Presets in the Now screen's styles.
- Lock Screen: hero, the Now chart's style (blue readings, dashed
  prediction, target band) and the configured bottom row as one-line
  tiles, within the 160 pt limit.
- Dynamic Island: white number and blue arrow, the change or "Low"/"High"
  in words with a loop dot, a keyline tinted for low and high, and an
  expanded view with a full-width status line and the chart.

They follow the New Interface setting: the app mirrors it into the app
group, reloads widget timelines and redraws the Live Activity when it
changes, so classic users keep the classic widget and Live Activity.
LoopDesign.swift and the redesign's colour sets are shared with the
widget target. The widget entry gains the CGM highlight and COB from the
existing extension context.

The widget catalogue gains the redesign's strings in all 24 languages,
reusing Loop's translations, plus a short "Forecast" tile label. The
Arabic "in 5 min" now uses an Arabic-Indic digit in both catalogues.
On next-dev the widget buttons use next-dev's shared Deeplink type, which replaced
SystemActionLink, and glucose units are LoopUnit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVPACb9uRhdQPgF5h2mj
Parity with next-dev:
- The IOB tile opens next-dev's Insulin Delivery Log (dose details, manual
  dose entry), shared with the classic IOB chart through showInsulinDelivery.
- The Loop pill opens next-dev's LoopStatusModalView. Device and loop errors
  still open the last error first. The new interface has no HUD to keep the
  modal's "ago" current, so it is set before presenting; without it the modal
  reported "Automation was unsuccessful" while Loop was running.
- Settings hides next-dev's Statistics row in the new interface, which the
  Trends tab covers. Current Setup stays.
- The Day page hides the tab bar when pushed from Now, like the Insulin,
  Carbohydrates and Predicted Glucose screens.

Accuracy:
- Basal totals follow next-dev's InsulinDeliveryHistory: from the first dose
  record, time without a basal record counts at the pump's programmed rate
  instead of as no insulin. Trends now agrees with next-dev's Statistics on
  basal (25.6 vs 25.3 U/day on the same data). Remaining differences are the
  period: Trends' 7 d includes today and averages complete days.
- Pump alarms in the Logbook show the pump's own alarm text, or "Pump alarm",
  rather than the event's debug title.

Performance:
- Loop runs decode only date, reason and errors for the local window via
  DosingDecisionStore.getDosingDecisions, instead of paging every stored
  decision: Trends loads in 0.5-1.8 s instead of 6.6-16.4 s.
- basalSegments finds the covering record by binary search bounded by the
  running furthest end, instead of a linear scan per cut: a week of
  five-minute records builds in 0.4 s instead of 10.8 s.
- The start of the local insulin records is cached for five minutes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP5sTMyrVG4zz5Wp4KM
- Trends has a "Basal and bolus" card above Insulin per day. It shows a
  ratio bar, basal and bolus in units and percent, the manual and automatic
  bolus, and the total. For a period it's the average per day, over the
  same days as the Insulin per day figure; for today it's "so far".
- The day page shows the same card in place of the bolus and basal tiles.
- Each Logbook day header has a hairline ratio bar and
  "Basal x · Bolus y · z U" under the date.
- Bolus gets its own colour, a deeper orange than basal's pale fill, so the
  two read apart by lightness as in Glooko and Tidepool, with no new hue.
  Automatic bolus is the same colour hatched (tinted in hairline bars), on
  the timeline, the daily bars and the legends.
- A dose in Apple Health that doesn't say whether it was automatic is no
  longer counted as manual. While any bolus in range is unclassified, the
  manual and automatic detail is hidden rather than guessed.
- The CSV export adds manual_bolus_u and auto_bolus_u columns, which are
  blank for days with an unclassified bolus.
- The new strings are translated into the redesign's 23 languages.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP5sTMyrVG4zz5Wp4KM
Pushed inside the Logbook tab, the carb editor and its bolus screen kept
the floating tab bar over their bottom button (Save Carbs & Deliver /
Save without Bolusing). The editor now opens as a sheet with Cancel,
the way Add carbs does on Now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP5sTMyrVG4zz5Wp4KM
@Nutcasey
Nutcasey force-pushed the loop-ui-redesign-next-dev branch from 415926d to 1b6efc9 Compare October 30, 2026 19:25
@Nutcasey

Copy link
Copy Markdown
Author

Rebased onto the current next-dev (e0eb9856), adding #2625, #2626, #2628 and #2629. The PR now merges cleanly.

Conflicts

Fix found in testing (1b6efc9a)

  • When a carb entry was edited from Logbook, the floating tab bar covered the bottom button of the carb and meal-bolus screens. Logbook now opens the editor as a sheet with Cancel, the way Add carbs works on Now. Hiding the tab bar with SwiftUI's .toolbar(.hidden, for: .tabBar) was tried first and had no effect on this UIKit tab bar.

Checked on the loop simulator (Xcode 27.1, iOS 27.0, Pump and CGM Simulators):

  • Now: 30 g of carbs → 3.7 U recommended → delivered. IOB went from −0.72 to 3.58 U and COB from 0 to 30 g.
  • Now: the IOB tile and the loop, pump, CGM and Presets pills each open their screen. Walking was started (the Presets button shows "Walking", target 8.3–9.4) and ended.
  • Logbook: the carb entry was edited from 30 to 35 g with a 0.6 U top-up, then the editor was opened and cancelled, then the entry was deleted. Day totals updated each time (55 → 60 → 25 g).
  • Trends: Day, 7, 14, 30 and 90 days, the previous day, and a PDF export ("Loop trends 29 Oct 2026", 48 KB).
  • The Day page from "Today so far" hides the tab bar. Its 34.0 U (20.3 basal, 13.8 bolus) matches the Logbook and Trends.
  • Deep links from Trends and Logbook (carb entry, manual bolus, custom presets) switch to Now and open the right screen.
  • New Interface off and on. The classic screen and the new interface agree: IOB 3.94 U, "Eventually" −4.4 mmol/L.

LoopTests were not run on this simulator. The hosted test runner hangs before connecting ("The test runner hung before establishing connection"). It hangs the same way on plain next-dev e0eb9856, so the cause is the iOS 27.0 simulator environment, not this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QHnVP5sTMyrVG4zz5Wp4KM

Nutcasey and others added 2 commits October 30, 2026 20:38
Basal's edge was the same orange as bolus (1.04:1 in dark mode), and the
pale basal fill barely showed against the card, so the two read as one.
Basal is now paler with a quiet tan edge, bolus is deeper in light mode,
and the edge and bolus are at least 3:1 apart in both modes. Bolus marks
also get a thin card-coloured gap wherever they touch basal or each other:
in the daily bars, the split bar and the day timeline.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP8UwbiZYLRjsYUYXhE
…kinds apart in the Logbook

Add carbs
- New CarbEntryScreen on top of the unchanged CarbEntryViewModel: a large
  amount, "How fast it absorbs" cards that draw Loop's own absorption curve
  (Fast, Medium, Slow, Other), "Eaten" quick times plus a time picker, and a
  pinned Continue that hands over to the existing bolus screen.
- Other shows "Custom" and no curve until it is chosen.
- Any scroll or the Done button puts the keyboard away, so the form stays
  reachable at accessibility text sizes; the cards and times go 2 x 2 there.
- Used from the Now screen and for editing carbs in the Logbook when the
  redesign is on; the classic interface keeps CarbEntryView.

Trends, one day
- Shows the same timeline card as Now's "Today so far" (shared as
  DayTimelineCard) instead of the AGP and the single Insulin per day bar.
- Tiles read Insulin, Carbs and Boluses with whole counts, and "3 entries"
  is a proper plural.
- Carb markers closer than the label spacing share one label with their
  total, placed after the last marker, so labels no longer overprint.

Logbook
- Manual bolus, automatic bolus and basal use the charts' encoding: solid,
  hatched and pale basal tiles; the day key and hairline bar match.
- Two or more automatic boluses in a row fold into one "Automatic boluses"
  row that opens the list.
- At accessibility sizes the amount sits under the title and the day
  totals move under the date.

Strings added in all 23 languages (unreviewed translations).
Tests: DayHistory.clipped(to:) and the automatic-bolus folding.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP8UWK6Li65s9wma3FF
Nutcasey added a commit to Nutcasey/Loop-1 that referenced this pull request Oct 31, 2026
…s for PR LoopKit#2621

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP8UWK6Li65s9wma3FF
@Nutcasey

Copy link
Copy Markdown
Author

Reviewed the complete PR #2621 diff (85 changed files) against next-dev e0eb9856, starting at 3fa82de3, using code-reviewer-cx. All findings below are fixed in 088e6bbd.

Critical

  • 96/100 confidence — Loop/View Models/CarbEntryViewModel.swift:265: Selecting a speed after a favourite queues a reset that clears the carbohydrate amount and overwrites the absorption time. Fixed: Apply favourite selection synchronously on the main actor, before the replacement meal is entered.
  • 94/100 confidence — Loop/Redesign/LoopHistoryProvider.swift:479: Historical day charts repeat the current target profile and omit presets that have ended. Fixed: Read stored target history and apply dated presets, respecting their actual end times.

Important

  • 89/100 confidence — Loop/Redesign/LoopHistoryProvider.swift:305: The cold-cache dose filter drops an instantaneous bolus at the interval start because its end equals its start. Fixed: Use the bolus start date for the half-open window, retaining overlap checks for basal delivery.
  • 88/100 confidence — Loop/Redesign/CarbEntryScreen.swift:254: The time-only picker cannot select the previous date across midnight; prefilled historical entries can also have Now selected. Fixed: Restore the date component, honour the prefilled time, and stack the picker at accessibility text sizes.
  • 85/100 confidence — Loop/Redesign/CarbEntryScreen.swift:157: The new amount field has no accessible label in the simulator hierarchy. Fixed: Restore the Amount Consumed label and the existing carbohydrate amount accessibility identifier.

The favourite editor also receives the effective food emoji. The exact date/time controls stack at accessibility sizes; the final AX XXXL capture confirms the label stays readable. Final diff review found no further issues at the skill's ≥80 confidence threshold.

Verification

  • Simulator app and test builds succeed; bundle signature verification and git diff --check pass.
  • The favourite reset was reproduced through the original UI: 35 g became blank and Continue was disabled. The fixed UI retains 35 g and hands the chosen absorption time to Meal Bolus.
  • Both bug regressions fail with the old scheduling/target-selection behaviour restored. All three added tests pass after the fixes.
  • 432 tests executed in the isolated XCTest agent: 430 passed, two existing locale-format assertions failed. The same two failures reproduce with the pre-fix behaviour.
  • Four DeviceDataManagerTests remain unverified. HealthKit rejects the isolated agent's client identity; installing and launching a separately registered disposable app did not resolve it.
  • The normal Xcode-hosted attempt stalled at launch and was stopped after 150 seconds. No completed hosted-suite result was obtained.
  • Hands-on checks covered favourite/speed changes, carb entry and Logbook editing, all filters, folded-dose totals, day navigation, Day/7/14/30/90-day Trends periods, previous/next periods, CSV/PDF sharing, interface switching, dark mode, AX XXXL and the maximum-meal warning.
  • The medium Home Screen widget rendered with glucose, COB, forecast and all four actions. Lock Screen and expanded Live Activity layouts were not re-exercised.

The PR description contains five simulator screenshots and the same coverage limits. The review build uses the PR sources and clean LoopKit dependencies, without the unrelated local Glooko host edits.

The amount now sits over the meal's absorption curve, drawn like the day
page's carbs-on-board chart: grams set its height, the speed its length,
and the eaten time where it sits against now (solid before, dashed after).
Touch and hold reads the carbs left at any time. Speed and eaten time are
single tracks with a sliding thumb, and the keyboard opens on its own for
a new entry.

Choosing a favourite after Other now shows the favourite's speed rather
than leaving Other selected, and the preview's labels stack at
accessibility text sizes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP89Q78jL8mjGo7fQsZ
Nutcasey added a commit to Nutcasey/Loop-1 that referenced this pull request Nov 1, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP89Q78jL8mjGo7fQsZ
Nutcasey and others added 2 commits November 1, 2026 09:38
- Set every insulin amount in one ink. Bolus amounts had their own darker
  ink, so a day's total and its bolus sat side by side in two oranges.
  insulin-ink now matches the bolus marks, and bolus-ink is gone.
- Tint insulin and carb amounts wherever they stand alone: the Trends
  summary tiles, the Logbook day totals and the Basal and bolus total.
- Show open loop in grey on Trends, as the Now screen does. Red is kept
  for problems that need action.
- Show the Now basal "vs plan" difference in muted text, as the Logbook
  does.
- Use the Trends round step buttons on the day page in place of blue
  chevrons.
- Tint the Add carbs cursor green and give its warnings the same card as
  the Now screen's alerts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP89Q78jL8mjGo7fQsZ
Keep the pump profile separate from the preset-adjusted plan on Now, including the fallback after a temp basal expires. Verified the reported rate against the simulator pump and insulin delivery log.

Reviewed and repaired by Codex using code-reviewer-cx.
@Nutcasey

Nutcasey commented Nov 1, 2026

Copy link
Copy Markdown
Author

Codex reviewed the complete PR #2621 diff (84 changed files), starting at 5ebec987 against next-dev e0eb9856, using code-reviewer-cx.

Critical (confidence 90–100)

  • 96/100 confidence — Loop/Redesign/NowScreen.swift:95: the displayed basal rate assumed a preset had changed the pump's programmed delivery. With automation off and a 22% Biking preset active, Now reported 0.28 U/h while the pump's scheduled basal and Loop's insulin log were 1.25 U/h. Fixed in 27b339dd: read the programmed pump profile separately from the preset-adjusted plan. Use it while scheduled basal is active and after a temp basal expires. The repaired simulator build shows 1.25 U/h, +0.98 vs plan in the same state.

Verification

  • Fresh simulator app and test builds succeed; bundle signature verification and git diff --check pass.
  • Reproduced the incorrect rate using the original PR sources, then verified the fix through the actual app with the same simulator configuration.
  • Exercised presets, pump suspension/resumption, insulin history, the 45 g Slow meal hand-off with a time one hour ago, 90-day Trends, Day navigation and Logbook filters. Ended the test preset and restored closed loop on the simulator afterwards.
  • 432 freshly compiled tests executed in the isolated XCTest agent: 430 passed, two existing clock-format assertions failed. Both are BolusEntryViewModelTests.testCarbEntryDateAndAbsorptionTimeString{,2}, matching the earlier baseline failures.
  • The standard Xcode-hosted attempt stalled before XCTest connected and was stopped after 150 seconds. Four HealthKit-dependent DeviceDataManagerTests remain unverified. This is not a clean full hosted-suite pass.
  • The review also covered the remaining Swift integration, history calculations, accessibility, project wiring, widget/Live Activity code, and both string catalogues. Widget/Live Activity runtime layouts were not re-exercised in this pass.

Codex has reviewed this PR and fixed all outstanding issues identified in this review. No further high-confidence findings remain. The PR is ready for human review. The description now records the repair and the verification limits.

@Nutcasey

Nutcasey commented Nov 1, 2026

Copy link
Copy Markdown
Author

Following Pete's suggestion, this PR is now split into six smaller PRs, to be reviewed in order. Each builds on the one before, so please review only the last commit of each:

  1. [1/6] Add a Trends screen for glucose, insulin and Loop status #2637 Trends, opened from Settings
  2. [2/6] Add a Logbook of the last 7 days #2638 Logbook, opened from Settings
  3. [3/6] Add the Now home screen with Now, Trends, Logbook and Settings tabs #2639 Now home screen with Now, Trends, Logbook and Settings tabs
  4. [4/6] Rebuild Add carbs around a live preview of the meal #2640 Redesigned Add carbs
  5. [5/6] Restyle the widget, Dynamic Island and Live Activity for the new interface #2641 Widget, Dynamic Island and Live Activity
  6. [6/6] Add Day and Night app icons and an appearance setting #2642 Day and Night app icons and the appearance setting

Together they match this PR, plus a few fixes found while splitting and testing. Each fix is listed in the PR that carries it:

  • Settings navigation for parts 1 and 2.
  • A basal-fill caching bug.
  • Three Add carbs form bugs: a favourite showing 0 g, the wrong time for entries older than 12 hours, and a stale speed after letting a favourite go.
  • The Testflight alternate icons.

I'll leave this PR open as the combined reference until the series lands.

🤖 Generated with Claude Code

Nutcasey added a commit to Nutcasey/Loop-1 that referenced this pull request Nov 1, 2026
Settings gains Appearance and App Icon, under the New Interface
toggle. Appearance follows the system or keeps Loop in Day or Night,
applied to the whole window at launch and as soon as it changes. The
app icon can stay Classic, follow the home screen's light or dark
appearance (Day and Night), or stay Day or Night. The alternate icons
are declared in the Debug, Release and Testflight configurations.

This is part 6 of 6 splitting LoopKit#2621, and builds on parts 1 to 5.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP7ynB62LNuuYMy3yvH
Nutcasey added a commit to Nutcasey/Loop-1 that referenced this pull request Nov 1, 2026
Settings gains Appearance and App Icon, under the New Interface
toggle. Appearance follows the system or keeps Loop in Day or Night,
applied to the whole window at launch and as soon as it changes. The
app icon can stay Classic, follow the home screen's light or dark
appearance (Day and Night), or stay Day or Night. The alternate icons
are declared in the Debug, Release and Testflight configurations.

This is part 6 of 6 splitting LoopKit#2621, and builds on parts 1 to 5.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP7ynB62LNuuYMy3yvH
Trends now carries everything Statistics shows that it lacked, so it
can take Statistics' place:

- Consensus goals: average under 8.6 mmol/L (154 mg/dL), GMI under 7%
  and CV 36% or less under the summary tiles; time in range over 70%,
  under 25% above and 4% below, under 5% very high and 1% very low,
  and CGM active over 70% on the Time in range card.
- Scheduled basal under Basal in Basal and bolus: the schedule that
  applied over the same days (the stored profile with presets), or
  today's schedule where the profile history doesn't reach.
- "Usually X U by HH:MM": today's insulin against the median by this
  time over the last 14 days, from InsulinDeliveryHistory as on
  Statistics. Under Total so far on today's Day view, and under the
  Insulin per day chart on longer periods ending today.
- "CGM data covers 5 of 14 days." under Summary when readings start
  partway through the period.
- Typed-in (fingerstick) readings are left out of every figure, as on
  Statistics. The day timeline still draws them.

Each new line reuses a pattern already on the screen: the Aim
footnote, the indented line under Bolus, and the muted footnote.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHnVP7ynB62LNuuYMy3yvH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant