Skip to content

Sync upstream dev (0.8.4.106) into Build-Experiment - #91

Open
Sjoerd-Bo3 wants to merge 291 commits into
Build-Experimentfrom
sync/dev-updates-9
Open

Sjoerd-Bo3 wants to merge 291 commits into
Build-Experimentfrom
sync/dev-updates-9

Conversation

@Sjoerd-Bo3

Copy link
Copy Markdown
Owner

What

Brings Build-Experiment up to the latest upstream dev (0.8.4.106, 286 commits) so the build is current. This is a large sync with several upstream refactors; fork customizations are preserved.

Conflict resolution (18 files)

Adopted upstream (its callers are wired throughout, or it supersedes a fork bit):

  • Pump/CGM catalog refactorsetupPumpEntry / PumpCatalogEntry (Home + setup sheets now use it).
  • Chart-selection readout — moved into the meal slot (ChartSelectionRow + ChartSelectionLookup); removed the old in-chart detail card and the now-unused SelectionPopoverView.
  • Device-alarm tier system — day/night windows, tone config, and the alarm volume/gating safety fixes.
  • Accessibility labels across header, meal panel, treatments, history.
  • Contact-image views/rendering — upstream's version now includes the background-mode picker from the earlier cherry-pick, so it supersedes it.

Kept ours (clean fork features):

  • Loop/reservoir spinning-border animations (plus upstream's new accessibility labels layered on).
  • Quick-Pick Boluses (Quick-Pick Treatments stays excised).
  • ProfilePresets activation/save-new-preset flow.
  • Settings import/export work.

⚠️ Follow-up flagged

The fork's per-alert severity screen (Settings → Notifications → Alert Severity) is now superseded by upstream's Device Alarms tier system and no longer affects alert delivery. It still compiles but would mislead — recommend removing that screen in a follow-up. (Left in place here to keep this sync focused on getting the build green.)

Verification

No conflict markers; pbxproj integrity clean (no duplicate GUIDs, no dangling build-file/file-reference entries); all new upstream files registered. Symbol checks pass for the adopted refactors (PumpCatalogEntry, ChartSelectionLookup, applyDeviceSeverityConfig, minutesAgoAccessible) and the kept fork code (enactBolus API, QuickBolus wiring, catalog .concept). The Xcode-27 shift only added chart-label tweaks + a 26.2 type-check fix, so compile_check (Xcode 26.2) stays valid.

Compiles only via the compile_check workflow (branch added to its trigger list) — no local iOS build in this environment.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EpcDkYHNDwWH5Ub6kdVh5g


Generated by Claude Code

trioneer-dev and others added 30 commits August 19, 2026 23:31
roundBasal floored every pump to a Medtronic x23/x54 band table, so Dana
lost 240 of its 300 rates and a gen >= 23 Minimed lost the 0.025 U it
delivers. It now floors against the paired driver's supportedBasalRates,
injected per determination, exactly as roundToSupportedBasalRate does at
enactment. Two parity determinations shift down by one increment.
performBasal and performBolus handed the determination straight to the
driver unrounded, unlike their enactTempBasal and enactBolus twins.
BaseAPSManager registered itself as a PumpManagerStatusObserver only once,
at init. When the live pump instance was replaced without an app relaunch
(onboarding a pump, or the pumpManagerDidUpdateState fallback assignment) the
observer stayed bound to the previous instance. The delegate is re-attached in
DeviceDataManager's didSet, so reservoir/dose/status data kept flowing, but the
observer-driven storeBatteryStatus never ran for the new pump -- no
OpenAPS_Battery rows were written and the home battery icon stayed hidden until
relaunch.

Fix at the single funnel: DeviceDataManager emits pumpManagerDidChange from the
pumpManager didSet (where the delegate is already re-attached), covering every
assignment path. APSManager re-registers its status observer on that signal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A three-way [Decimal] concatenation type-checks on 26.6 but exceeds the
budget on the 26.2 that CI pins. The five tables now live once in
PumpRateTables, built with append(contentsOf:).
Decimal -> Double via Double(truncating:) can land a hair low, 0.07 becomes
0.06999999999999999, and every pump table floors, so 41 of Dana's 301 rates
lost a full increment. Convert via the decimal string and drop the floor the
algorithm already applied. Reported by mountrcg.
Glass panels and the small material affordances (rate capsule, chart-info
button) fall back to an opaque, higher-contrast fill when Reduce Transparency
or Increase Contrast is on. Also labels the icon-only chart-legend button.
Each value row reads as one element (label + value + button) with an
accessibilityValue and an action to open the picker; the icon-only hint
button gets a label. Covers ~20 settings modules that use this component.
Schedule editor entries read as one element with an accessible delete;
numeric-field toolbar buttons (clear/prev/next/dismiss) get labels in both
the SwiftUI and UIKit variants; custom Radio/Checkbox toggle styles expose
on/off value and a toggle action to VoiceOver.
Slide-to-confirm gains a VoiceOver button action (was drag-only, blocking
delivery); the + button exposes treatment + quick-bolus actions; quick-pick
pills announce selection; the bobble reads value, range, trend, delta and age
as one element instead of fragments.
Recommendation-math cards read as grouped phrases and the final dose reads
with its unit; the recommendation apply/info buttons get labels and a hint;
over-limit macro fields announce 'over the maximum' instead of a bare warning
emoji.
Add VoiceOver labels to glucose and forecast charts, the
version-copy button, and Max Carbs/Fat/Protein picker rows.
Give the progress bar a spoken chapter summary, mark the step
header as a combined header with its icon hidden, announce
selection state on the radio-card options, and make the delivery-
limit and algorithm-setting picker rows operable with VoiceOver.
Announce selection/active state on override and temp-target cards
and radio buttons, make target/value pickers operable with
VoiceOver, label help buttons, group stat summaries into spoken
values, hide decorative row dots, give history glucose rows a
faithful spoken label, and name the twelve statistics charts.
Cap Dynamic Type at accessibility1 globally so large text still
scales for low vision without shattering layouts, and cap the
dense Statistics screen tighter at xxLarge like Home already does.
Speak the app version card's update status and hide its
decorative icon, make the alarm-threshold and glucose-threshold
tap-to-reveal picker rows operable with VoiceOver, and label the
UI settings hint buttons.
Speak the loop pill, pump reservoir/battery/pod, IOB/COB, alarms,
and eventual-glucose status in words instead of color and icon
names; make the tappable header panels operable via VoiceOver
actions; and label the icon-only help buttons across settings.
Announce selected state on the diagnostics, telemetry, and export
choice rows, and give the icon-only and bracketed action buttons
spoken labels (time nudge, serving add/remove, add/remove alarm
and widget, dismiss).
Name the basal, carb-ratio, ISF, and target profile charts and
the calibration chart for VoiceOver, and announce tone selection
and play/stop state in the alarm sound picker.
Make the stop-adjustment, stop-temp-target, and stop-override
cancels operable via VoiceOver, group the bolus-progress readout
into a spoken value, label its cancel button, and expose the
adjustment panel tap as an action.
Speak Nightscout and Tidepool connection state in words instead
of icon glyphs, and fold the sensor warmup/expiry tag into the
glucose bobble's spoken label.
Label the rendered contact-image previews and hide the row
thumbnail, and give the app-icon grid readable names with a
selected state instead of raw asset identifiers.
Speak elapsed/pod time as words so VoiceOver stops reading 'm'
as meters, group the pump panel into one button that announces
reservoir/battery/pod, and label the iOS 26 tab-bar items.
Hide the decorative welcome logo, mark the welcome heading as a
header, collapse each bullet into one spoken element, and move
VoiceOver focus to the top of each step on navigation.
Announce onboarding chapter rows as complete or not complete, and
re-apply accessibility to the renamed quick-pick treatments: pills
announce amount, unit and selected state, and the slide-to-confirm
exposes a double-tap action for VoiceOver.
iOS resolves a UNNotificationSoundName against the main bundle root and
Library/Sounds only. The tones shipped as an Xcode folder reference, so
they landed in Trio.app/Sounds/ and every notification silently fell back
to the default iOS sound — while the picker preview and the critical-audio
player worked, being the only paths passing subdirectory: "Sounds".

Register the 18 .caf files individually so they flatten to the bundle
root, and drop the now-wrong subdirectory from both lookups.

Vendor sounds move from Library/Sounds/<manager>/<file> to a flat
<manager>-<file>, since iOS only reads the top level of that directory.

Fixes nightscout#1371
The critical-audio fallback is what pierces the silent switch and Focus on
builds without the Critical Alerts entitlement, but it rejected anything
that wasn't .immediate. The not-looping watchdog is the only .delayed alert
Trio creates, so the one alarm that fires unattended was the one alarm that
never got audio.

Start playback from the modal scheduler's timer instead, whose .insert
decision already means live, not stale and not snoozed. Arming time is
20 minutes early, so .immediate keeps playing at issue time.
evaluateForecast bailed on the same CGM-ownership guard as the reading
path, so on Dexcom, xDrip4iOS and Libre — where "Use CGM App Alerts"
defaults on — Low Glucose Soon was never evaluated, silently and forever.

A CGM app can alarm on the current reading but cannot compute Trio's oref
forecast, so it can never cover this alarm. evaluateCarbsRequired already
omits the guard for the same reason, and the settings screen only moves
reading-driven types into the "Handled by CGM App" section, so the alarm
was shown to the user as armed.

Fixes nightscout#1428
Add a unit speller that expands compact abbreviations (mg/dL,
mmol/L, U, g) and compound units (g/U, mg/dL/U, U/hr) into spoken
words, and use it in the accessibility values across glucose,
delivery-limit, therapy, and threshold controls.
Without the Critical Alerts entitlement the in-process audio player is the
only thing that pierces the silent switch and Focus, and it can only sound
while Trio is running. AlarmKit is system-rendered, needs no entitlement,
and still fires when iOS has suspended the app.

Ported from Loop's CriticalAlertAlarmScheduler. Alert-only presentation, so
no Widget Extension is needed, scheduled two seconds out because a now/past
fixed date schedules silently. The alarm plays the tone the user picked —
AlertSound.named resolves like UNNotificationSoundName, from the bundle
root, which is where the tones now live.

Stop routes through a shared bridge so it acknowledges the Trio alert
rather than only silencing it, queueing taps that land before the manager
registers. The audible channel is now AlarmKit, then the audio player.
dnzxy and others added 30 commits September 13, 2026 17:38
Anchor bolus and carb amount labels to a zero-size companion mark
Their trio branches carry Trio-only commits; the script manifest is fixed to match.
isDisplayOnly means the reading was shifted for visual consistency after
calibration (LoopKit), not that it is unsafe to dose on: Loop keeps these
samples and excludes them only from momentum and counteraction. The gate was
LibreLoop-scoped, so Trio already dosed on Dexcom's display-only samples.

It never held either way: LibreLoop's backfill paths forward the same sensor
minute with isDisplayOnly false, so a dropped reading re-entered unflagged.
On Libre 3 Plus the actionability bit is stuck clear, so every reading was
discarded and those users could not loop at all.

Readings the sensor reports as faulty are still withheld by the driver.
Backport of loopandlearn#159; addresses the -034 fault increase on Omnipod 5.
…y-gate

Fix for Libre 3/3 Plus: Stop dropping display-only glucose readings
Resolves conflicts with the DI hygiene refactor (nightscout#1367), which moved
TelemetryClient and TelemetryAttestor to container-scoped singletons with
init(resolver:) and removed the lazy injectIfNeeded() pattern. Kept that
structure and layered this branch's TelemetryRequestContext parameters on
top of the new signatures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Prefer appDevVersion over CFBundleShortVersionString for the
  X-Trio-Version header, falling back to "unknown".
- Document the daily anonymous install heartbeat in PRIVACY_POLICY.md,
  including that it still runs when usage telemetry is opted out, and
  mirror a short version of it in the in-app privacy screen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-and-volume

Various Alarm Adjustments / Fixes
Significantly improve telemetry reliability
…modules

Update submodules to current upstream
Merge the latest upstream dev (0.8.4.106) into the fork, preserving
Build-Experiment customizations.

Conflict resolution:
- Adopted upstream's pump/CGM catalog refactor (setupPumpEntry /
  PumpCatalogEntry) since its callers are now wired throughout Home.
- Adopted upstream's chart-selection readout (meal-slot ChartSelectionRow +
  ChartSelectionLookup) and removed the old in-chart detail card and the
  now-unused SelectionPopoverView, matching upstream.
- Adopted upstream's device-alarm tier system (day/night windows, tone
  config, volume-handling fixes) and its accessibility labels across the
  header, meal panel, treatments and history.
- Kept the fork's loop/reservoir spinning border animations, Quick-Pick
  Boluses, ProfilePresets activation flow, and settings-import work.
- Kept Quick-Pick Treatments excised.
- Superseded by upstream's contact-image work: took upstream's contact
  image views/rendering (they now include the background-mode picker).

Note: the fork's per-alert severity screen is now superseded by upstream's
Device Alarms and no longer affects delivery; slated for follow-up removal.

Also absorbed: DI-hygiene refactor, telemetry updates, Libre3/OmnipodKit/
DanaKit/EversenseKit bumps, glucose display-only gating fixes, and many
upstream fixes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpcDkYHNDwWH5Ub6kdVh5g
The 286-commit dev sync mis-balanced braces where fork and upstream
diverged. Take upstream's full MealPanel/BottomControls/TreatmentsRootView
(their Home rework, which keeps snooze, glass panels and remaining bars),
and close the preset-activation glassActionSheet correctly in Adjustments
while preserving the ProfilePresets activation/save-preset alerts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpcDkYHNDwWH5Ub6kdVh5g
The dev-sync resolution left upstream's Quick-Pick Treatments symbols in
HomeRootView's accessibility action; point it at the fork's Quick-Pick
Boluses flow (enableQuickBolus / quickBolusHistory / showQuickBolus*).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpcDkYHNDwWH5Ub6kdVh5g
The switch includes the fork's .profiles (EmptyView) case, so the
property needs @ViewBuilder for its heterogeneous branches; the merge
resolution had dropped it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpcDkYHNDwWH5Ub6kdVh5g
Upstream removed the Medtronic Enlite CGM type; drop the obsolete
import warning that referenced merged.cgm == .enlite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpcDkYHNDwWH5Ub6kdVh5g
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.