Skip to content

Tidepool sync 2026-05-11#591

Closed
loopkitdev wants to merge 839 commits into
LoopKit:devfrom
loopkitdev:tidepool-sync/2026-05-11
Closed

Tidepool sync 2026-05-11#591
loopkitdev wants to merge 839 commits into
LoopKit:devfrom
loopkitdev:tidepool-sync/2026-05-11

Conversation

@loopkitdev

Copy link
Copy Markdown

Refreshed Tidepool → DIY sync from the tidepool-sync/2026-05-11 branch.

This supersedes and replaces the previous Tidepool Merge PR (#550), which is being closed in favor of this one.

Camji55 and others added 30 commits June 18, 2025 11:42
* Enable scheduled presets

* Fix bug with not looking ahead full week

* Updates for async alert issuing

* Fix warning

* starting presets from notifications

* Update getSyncCarbObjects to async

* Fix tests
* Enable scheduled presets

* Fix bug with not looking ahead full week

* Updates for async alert issuing

* Fix warning

* starting presets from notifications

* Update getSyncCarbObjects to async

* Fix tests
loopkitdev and others added 11 commits April 9, 2026 15:26
Xcode extracted new localizable strings and marked stale entries
after the tidepool-sync/2026-03-10 merge and build.
Resolved conflict in InsulinType.swift: took upstream's separate
fiasp/lyumjev descriptions (more informative than grouped generic).
Add SupportProviding protocol so services can declare a companion
SupportUI. MockService conforms via extension in MockKitUI, enabling
MockSupport to load when MockService is added.

Update MockSupport with proper software update view, shared update
descriptions between alerts and the view, and wire configurationMenuItems
for the settings support section.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
MockSupport no longer issues its own alert for .required version updates.
Instead, it returns the enum value so Loop can handle it with a blocking
modal and critical notification. Adds requiredUpdate notification category.
Filter pump-supported basal rates by therapySettings.maximumBasalRatePerHour
in the TherapySettingsViewModel convenience initializer so the schedule
editor's picker cannot offer rates above the user's configured max basal.

DIY divergence from tidepool-org/LoopKit PR #734 (LOOP-5767, "Basal
schedule editor should ignore max basal rate"). Reported by a DIY user
on OmniBLE / Dash who could select schedule entries above their max
basal setting.
409 commits from tidepool-org/LoopKit dev. 18 source conflicts + 19 pbxproj
regions resolved per LOOPKIT_SYNC_PROCESS.md.

Take Tidepool:
- DoseStore.swift (LOOP-5843 isMutable for unfinished doses)
- InsulinType.swift (combined Fiasp/Lyumjev case)
- LoopNotificationCategory.swift (LOOP-1114 requiredUpdate case)
- QuantityFormatter.swift (drop unused rounding-rule parameter)
- TemporaryScheduleOverride.swift (LOOP-5807 preset insulin scale tuning)
- LoopKitUI/SupportUI.swift (LOOP-1114 SupportProviding protocol)
- GlucoseTherapySettingInformationView.swift (minor cleanup)
- CorrectionRangeOverridesEditor.swift (LOOP-5878 guardrail wiring)
- New preset views (EditPresetView, ReviewNewPresetView,
  InsulinNeedsAdjustmentPreview) added on both sides — took Tidepool's

Accept Tidepool deletions (LOOP-4781 LoopAlgorithm package extraction):
- ExponentialInsulinModel.swift
- LoopAlgorithm/LoopAlgorithm.swift
- LoopAlgorithm/LoopPredictionOutput.swift
Logic now lives in tidepool-org/LoopAlgorithm Swift Package, already
pinned in workspace Package.resolved.

Accept Tidepool deletion (preset UI replaced):
- OverrideSelectionViewController.swift — superseded by EditPresetView et al.
  DIY's crash-fix commit 3ce43de does not apply to the new SwiftUI flow.

Keep DIY:
- MockCGMManagerSettingsView.swift, MockPumpManagerSettingsView.swift —
  simulator settings sections gated by allowDebugFeatures
- BasalRateScheduleEditor.swift line 73 — DIY divergence from
  tidepool/LoopKit PR #734 (LOOP-5767). Auto-merge silently reverted to
  Tidepool's `nil`; manually restored DIY's max-basal filtering.

pbxproj (19 conflict regions, resolved bottom-up):
- Dropped all Tidepool *.strings refs; kept DIY's *.xcstrings (rule 1+2)
- Kept LOCALIZATION_PREFERS_STRING_CATALOGS = YES (rule 7)
- Kept Tidepool's new Media/Transcript files + TimeInterval+Timecode (rule 5)
- Dropped refs to the 4 deleted source files
- Pre-existing XCRemoteSwiftPackageReference "LoopAlgorithm" in HEAD left
  alone — was not introduced by this merge; same as previous sync
- Final state: { = 1898, } = 1898, xcodebuild -list parses cleanly
…ds, and Coordinator

The 2026-05-11 tidepool sync auto-merge silently dropped the 'public'
modifier from 9 declarations in this file (the struct, init,
makeCoordinator, makeUIView, updateUIView, the Coordinator class, and
its 4 UIPickerView delegate/datasource methods).

Tidepool's branch never had these public modifiers — they're DIY-only
additions from commits 631bdc8 'Make ResizeablePicker public so Loop
app can use it', 9f755d7 'Expose ResizeablePicker...', 1d1b3a2, and
12ed30a. With the merge collapsing to Tidepool's internal-only
version, Loop/Views/LiveActivityManagementView.swift could no longer
resolve 'ResizeablePicker in scope'.

Restored DIY's pre-merge version (tidepool-sync/2026-03-10 tip).
Tidepool made no substantive changes to this file in the sync window
other than the public removals, so nothing of theirs is lost.
Loop no longer references ResizeablePicker cross-module (the only call
site, LiveActivityManagementView, now uses standard SwiftUI Picker). The
public modifiers DIY had been carrying (commits 631bdc8, 9f755d7,
1d1b3a2, 12ed30a) are no longer needed. Reverting to Tidepool's
internal-only version removes a DIY divergence in LoopKitUI.
Pete Schwamb and others added 8 commits May 20, 2026 19:02
…letion

processResults now only honors HealthKit deletions for samples that originated
from another app. A record Loop itself wrote is kept in the dose history even if
it is deleted in Apple Health, so a user deleting a Loop record in Health does
not silently reduce active insulin and change dosing. deleteDoseEntries gains an
excludingProvenanceIdentifier parameter; Loop's own direct deletions are
unaffected. When insulin ingest from other apps is disabled, every cached record
is Loop's own, so no HealthKit deletion is propagated.
CachedInsulinDeliveryObject.dose asserted that a .bolus always has
programmedUnits and/or deliveredUnits. Upgrading from an older DIY install can
carry legacy bolus records with neither, which trapped debug builds on the
first dose read. Drop the assertion and fall back to the existing 0 value so
the upgrade succeeds; release behavior is unchanged (the assertion was already
a no-op there).
The v4→v6 mapping for CachedInsulinDeliveryObject used auto-generated (name-based)
attribute mappings, so the v4 `value` column (delivered units) had no destination
and the v6 `deliveredUnits`/`programmedUnits` came up nil. Upgrading a v4 store
(e.g. from older DIY) therefore zeroed every cached bolus and basal — understating
IOB and tripping a read-time assertion. Fresh installs start at v5/v6 so this path
was never exercised upstream.

Add CachedInsulinDeliveryObjectMigrationPolicy to copy `value` → `deliveredUnits`
(and `programmedUnits` for boluses) during the v4→v6 migration; wire it into the
mapping model. Basal rates already migrate (scheduledBasalRate/programmedTempBasalRate
carry by name). Validated against a real v4 store: boluses retain their amounts,
IOB is correct, no crash.
Repoint the LoopAlgorithm Swift package from tidepool-org/LoopAlgorithm
to LoopKit/LoopAlgorithm (main), the community fork.
Use a local Swift package reference (../LoopAlgorithm) instead of the remote
GitHub package, so LoopAlgorithm can be vendored as a workspace submodule and
edited in place. Package.swift keeps the remote dependency for standalone
package builds.
Remove LoopKit's own LoopAlgorithm package reference; the LoopAlgorithm
product is now resolved from the workspace-declared local package, so the
LoopWorkspace owns the dependency.
reconciled() emits doses out of startDate order (boluses ahead of deferred
basals), and getNormalizedDoseEntries concatenates multiple dose sources, so
neither is sorted. LoopAlgorithm's binary-search filterDateRange requires
ascending order — unsorted input returned wrong dose subsets (silently in
release; the debug assert caught it as a crash). Sort at both chokepoints.

@marionbarker marionbarker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is approved by testing it as part of the LoopKit/LoopWorkspace#450.

When building with Xcode 26.5 on a Mac, the following files are updated. I can provide a PR or you can just commit the xcstrings changes after building.

modified: LoopKit/Resources/Localizable.xcstrings
modified: MockKitUI/Resources/Localizable.xcstrings

ps2 added 6 commits June 2, 2026 20:35
- UnfinalizedDose: temp-basal init takes an `automatic:` flag (default
  true) and the UnfinalizedDose->DoseEntry bridge now propagates it
  (matching the bolus/suspend/resume cases that already did).
- MockPumpManager: split enactTempBasal into a public
  runTemporaryBasalProgram(...automatic:) helper; enactTempBasal calls
  it with automatic:true; expose supportedTempBasalDurations.
- MockPumpManagerSettingsViewModel: manualBasalTimeRemaining,
  allowedTempBasalRates, runTemporaryBasalProgram (automatic:false),
  cancelManualTempBasal, timeRemainingFormatter.
- MockPumpManagerSettingsView: new Activity-row that toggles between
  "Set Temporary Basal Rate" (presents a fileprivate
  ManualTempBasalEntryView modeled on OmniBLE's) and Cancel/Remaining
  display, plus an alert for cancel failures.

Lets the Mock pump exercise the new isManualTempBasalRunning gate in
LoopDataManager without needing a real Omnipod.
The Suspend Insulin Delivery row was centered, bold, and padded while
the Set Temporary Basal Rate row used the plain List-row style --
visually jarring side by side. Reformats the suspend row to match:
icon on the left, regular-weight text, optional spinner on the right.

Also removes the Replace Pump row, which only navigated to
DemoPlaceHolderView and had no real behavior.
Source order drives allCases, which the Dosing Strategy picker
iterates -- swapping the source order moves Automatic Bolus to the
first row. Raw values are pinned (tempBasalOnly = 0, automaticBolus = 1)
so persisted settings keep their meaning.
- LoopKitUI CorrectionRangeInformationView: the format string had an
  appName argument but no %@ placeholder, so the substituted name was
  being silently dropped and the literal "Tidepool Loop" rendered.
  Adds %1$@ to the format so the env-injected appName is used.
- LoopKitUI ReviewNewPresetView: adds @Environment(\.appName) and
  formats the scheduled-preset note with %1$@.
- MockKitUI MockPumpManagerSettingsView: pumpTimeSubSectionFooter now
  uses the struct's existing appName property.
@loopkitdev loopkitdev closed this Jun 4, 2026
@loopkitdev loopkitdev deleted the tidepool-sync/2026-05-11 branch June 4, 2026 12:13
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.

5 participants