Software Design Description (SDD)¶
Status: Frozen-baseline design description approved for IDE submission
Version: 1.84
Owner: BionicLoop engineering
Prepared by: BionicLoop engineering
Approval reference: Edward R. Damiano, PhD, final software-package approval,
controlled email dated 2026-09-07 EDT
Baseline freeze SHA: 91c0e98a9bc9429a0486bebdebffc7d8dbbe300e
Last updated: 2026-09-08
Revision History¶
| Version | Date | Author | Summary of Changes |
|---|---|---|---|
| 0.1 | 2026-04-05 | Engineering | Initial controlled design draft |
| 0.9 | 2026-04-06 | BionicLoop engineering | Added document-control metadata and disposition fields |
| 0.91 | 2026-04-08 | BionicLoop engineering | Added fallback-event review-state persistence for masked offline fallback |
| 0.92 | 2026-04-08 | BionicLoop engineering | Added the pump basal-schedule interface for masked offline fallback |
| 0.93 | 2026-04-08 | BionicLoop engineering | Clarified that programmed basal-schedule replacement is a disruptive masked-fallback arm/disarm operation that is blocked during active bolus, active temp basal, or non-steady basal-delivery states |
| 0.94 | 2026-04-08 | BionicLoop engineering | Clarified that masked-fallback schedule refresh uses a controlled reprogram-and-immediate-remask maintenance sequence and that unknown basal-delivery state blocks disruptive schedule replacement |
| 0.95 | 2026-04-08 | BionicLoop engineering | Added active masked-fallback maintenance lifecycle details, active-session gating, and reset/disarm restore behavior |
| 0.96 | 2026-04-08 | BionicLoop engineering | Clarified 20-minute masked-fallback renewal-window behavior, deferred maintenance semantics, and pre-step renewal before a new bolus-bearing step |
| 0.97 | 2026-04-14 | BionicLoop engineering | Added reconciliation-required blocked-state design notes after offline mask expiry |
| 0.98 | 2026-04-14 | BionicLoop engineering | Added reconnect restore/disarm retry notes and explicit fresh re-arm behavior after successful masked-fallback recovery |
| 0.99 | 2026-04-14 | BionicLoop engineering | Updated reconnect recovery design to preserve the existing session/cadence anchor and mark successful feasibility-path recovery as same-session unreconciled resume |
| 1.00 | 2026-04-15 | BionicLoop engineering | Added basal-only reconnect evidence, pod total-delivery baseline capture, modeled-vs-pump-reported fallback review, and pre-step missing-fallback arm details |
| 1.01 | 2026-04-15 | BionicLoop engineering | Added confirmed/corrected basal-only reconnect replay design details, persisted replay-plan state, and replay-specific review detail in Home timeline surfaces |
| 1.02 | 2026-04-15 | BionicLoop engineering | Added dedicated cloud fallback telemetry emission from structured fallback review state for BionicScout timeline and dosing overlays |
| 1.03 | 2026-04-15 | BionicLoop engineering | Clarified that replayed internal steps now persist into local per-step telemetry / CSV export as distinct replay-marked rows |
| 1.04 | 2026-04-27 | BionicLoop engineering | Clarified that fallback replay uses pump-reported delivered-insulin delta only; modeled fallback exposure is logging/review evidence when pump reconciliation is unavailable |
| 1.05 | 2026-05-06 | BionicLoop engineering | Added Swift-maintained q5 nominal-basal profile persistence, safety-track four-bucket fallback schedule generation, schedule-aware exposure modeling, and profile/schedule cloud telemetry details |
| 1.06 | 2026-06-02 | BionicLoop engineering | Reframed masked-fallback recovery as pump-delta missed-step algorithm replay with unavailable CGM input, tightened pump-evidence credibility, restored IDE schedule-refresh cadence, and added repeated no-active-pod alerting |
| 1.07 | 2026-06-08 | BionicLoop engineering | Added persisted-schedule-weighted replay allocation for credible same-pod pump delta, including partial-slot / midnight weighting and zero-weight suppression rules |
| 1.08 | 2026-06-12 | BionicLoop engineering | Added generalized issued-dose attribution design for interrupted meal, correction, mixed, and basal bolus commands |
| 1.09 | 2026-06-13 | BionicLoop engineering | Hardened issued-dose attribution design for delivered-unit credibility, replacement-pod live-step input scrubbing, and automatic resume blocking under active holds |
| 1.10 | 2026-06-15 | BionicLoop engineering | Updated different/new-pod issued-dose design to assumed-delivered replay/live attribution, nonblocking replacement-pod dosing, legacy hold clearance, and deferred adaptation-forget consideration |
| 1.11 | 2026-06-17 | BionicLoop engineering | Added explicit meal-progress pod-replacement escape design with user-abandoned unavailable-pod evidence |
| 1.12 | 2026-06-18 | BionicLoop engineering | Added retired/expired/no-active-pod masked-fallback recovery design that records modeled fallback exposure as assumed delivered when the old pod cannot provide connected reconciliation evidence. |
| 1.13 | 2026-07-08 | BionicLoop engineering | Added Algo2015 delivered-insulin echo persistence and cloud divergence telemetry for read-only insulin-conservation review. |
| 1.14 | 2026-07-08 | BionicLoop engineering | Added Algo2015 checkBG fingerstick prompt surfacing with haptic feedback, BG-button emphasis, dedupe, clear, and stale-relaunch rules. |
| 1.15 | 2026-07-08 | BionicLoop engineering | Added Algo2015 forced-open-loop command block and safety-critical alert surfacing while preserving fallback-basal maintenance. |
| 1.16 | 2026-07-08 | BionicLoop engineering | Added accepted no-boundary-cancel issued-dose liveness-bound design note for DASH delivery-state convergence and unavailable/unknown disconnect paths. |
| 1.17 | 2026-07-08 | BionicLoop engineering | Replaced the merged-first-fallback-row issued-dose design with pre-fallback confirm row + zero-delivery echo sentinels + seam ask echo (SDD-POL-029); no-room overlap keeps the merge with the requested side echoing the issued ask exactly. |
| 1.18 | 2026-07-09 | BionicLoop engineering | Exempted fallback replay backfill rows from interrupted-delivery chart styling (SDD-POL-027): offline asks are not pump commands, so their shortfall vs the pod-true share is not an interruption; issued-dose resolution rows keep the caution signal for genuine partial deliveries. |
| 1.19 | 2026-07-09 | BionicLoop engineering | Replay backfill bars render as a muted insulin-bar variant (whole-bucket/whole-pixel rule); documented the minimum-height zero-dose chart mark that distinguishes executed zero-dose steps (and sentinels) from missed steps. |
| 1.20 | 2026-07-09 | BionicLoop engineering | Scrub readout pills show only during active scrubbing with animated transitions; chart scrub state force-clears on view teardown and scene backgrounding; loop-status ring rendered without card chrome. |
| 1.21 | 2026-07-09 | BionicLoop engineering | Home visual polish pass: rounded monospaced hero BG value with baseline-aligned trend arrow, investigational-use chip, sliding-thumb chart range control, quieted solid-hairline chart grid with monospaced axis labels and CGM area fill, the primary actions share an outlined family (surface fill, accent-blue border) with chart-linked glyph colors - the compact Manual BG square carries a scheme-adaptive fingerstick-red droplet and Let's Eat carries the meal-dose purple fork - and the fingerstick-request state adds a faint caution wash under the amber ring so the glow reads anchored, 12 pt card-padding rhythm, and animated banner/section transitions. Display-only; IFU screenshots to be refreshed at next capture pass. |
| 1.22 | 2026-07-09 | BionicLoop engineering | Recent Dose Steps redesign: honest dose-settlement status policy (Delivered only with pump-anchored settlement; Requested for bare commands; Delivering/Assumed/Replayed), compact summary rows with disclosure detail, and a clinical-unlock-gated CSV share action (SDD-LOG-001). |
| 1.23 | 2026-07-09 | BionicLoop engineering | Home alert stack with root-cause suppression matrix replaces the carousel (SDD-ALERT-001, SDD-POL-008); interrupted-dose chart bars keep identity color with a caution ghost outline to requested height and the partial-delivery summary wording is caution-colored (SDD-POL-027); step-drift preview catalog entry realigned to SRS-RUN-007 copy. |
| 1.24 | 2026-07-09 | BionicLoop engineering | Meal/BG modal cleanup: digit-keypad manual BG entry with inline range validation and single submit telemetry event (SDD-BG-001); meal carb choice as a fixed three-option row with unified subtle-fill selection styling, locale short-time availability copy, reserved composer heights with animated state swaps, neutral Cancel buttons, shared modal header, standardized sheet detents. |
| 1.25 | 2026-07-09 | BionicLoop engineering | Meal composer revalidation redesign (SDD-POL-004): in-place re-arm on stale observed step, inline self-healing blocked messaging with selections preserved, cancel-delivery routing retained; mid-composition dismissal into a second sheet removed. |
| 1.26 | 2026-07-09 | BionicLoop engineering | Home alert stack related-alert line (SDD-ALERT-001): hidden-count affordance into Alert Center when suppression is active; alert preview catalog extended with check-BG, dosing-paused (base + escalated), and backup-insulin-not-confirmed entries so the generated IFU reference covers every live alert; clinical-readability vocabulary pass on backup-basal event detail and algorithm-arm block messages. |
| 1.27 | 2026-07-10 | BionicLoop engineering | Added dual-instance algorithm hosting under SDD-ALG-001: the safety track binds a symbol-isolated second compilation so the two live instances share no C++ global state. |
| 1.28 | 2026-07-10 | BionicLoop engineering | Aligned forced-open descriptions with the implemented informational-first, escalation, and fingerstick behavior; added the fallback-replay-disposal acknowledgment; aligned alert, state-store, runtime-sequence, and requirement-allocation descriptions; and removed obsolete feasibility wording. |
| 1.29 | 2026-07-14 | BionicLoop engineering | Added SDD-OUTAGE-001 for fingerstick-supported CGM-outage dosing, including the persisted BG-due schedule, tiered alerts, Home countdown, backup-basal bridge, replay-based reconciliation, and no maximum-outage stop; added allocation rows for SRS-OUTAGE-001..006 and SRS-PUMP-011. |
| 1.30 | 2026-07-14 | BionicLoop engineering | SDD-CLIN-001 extended for clinical-feedback changes: first-launch Standard/120/75%/40 defaults and the New Participant Reset design (full participant-scoped wipe + sign-out, armed/active-pod refusal, relabeled same-participant reset). |
| 1.31 | 2026-07-14 | BionicLoop engineering | Sponsor device-pass feedback: SDD-CLIN-001 updated for the grouped first-launch layout with per-mode target defaults, the defaults-without-persist empty-store load, the symmetric reset-button row, and the guided stop-then-reset flow. |
| 1.32 | 2026-07-14 | BionicLoop engineering | Aligned SDD-POL-029 with the implemented assumed-delivered policy; aligned the armed reset and sign-out paths; added the SRS-PUMP-011 watchdog design and RA-018 notification-permission limitation; and corrected the header date. |
| 1.33 | 2026-07-16 | BionicLoop engineering | SDD-ALERT-001 permission wording corrected to the actual mechanism (iOS drops delivery; the scheduler never skipped) and extended with the 2026-07-16 observability additions (authorization_status telemetry stamping + unauthorized-schedule cloud warning); no in-app logging controls remain (Settings cloud-log section removed; remote config per SRS-LOG-011). |
| 1.34 | 2026-07-16 | BionicLoop engineering | SDD-LOG-001 threshold-resolution tail corrected and extended: precedence stated as session > remote override > default error, the stale "local threshold exposed in debug builds via HomeSettingsView" sentence (invalidated by the 1.33 control removal) replaced with the read-only Settings status text design (CloudLogStatusSupport + HomeSettingsStudyLoggingSectionView), and the remote-config refresh triggers documented as launch/foreground/30-minute periodic (startPeriodicRefresh). |
| 1.35 | 2026-07-16 | BionicLoop engineering | SDD-LOG-001 tail re-stated for the SRS-LOG-010 supersession: session layer removed from precedence (server config > default only; retired session-key storage never read) and the configChangeObserver -> threshold-exempt remote_logging_config markers design added (bypass source list). |
| 1.36 | 2026-07-16 | BionicLoop engineering | SDD-APP-008 added: server-configurable investigational badge (CloudAppBannerConfigSupport three-state effectiveText, HomeTopOverlayBar TimelineView rendering) and the shared CloudRemoteConfigSupport.refreshAll/startPeriodicRefresh cadence for all server-issued configs (periodic loop relocated from CloudLogRemoteConfigSupport). |
| 1.37 | 2026-07-16 | BionicLoop engineering | SDD-LOG-001: G7 BLE trace emission follows the server-issued debug level when no local override is set; an explicit local off setting still takes precedence. |
| 1.38 | 2026-07-16 | BionicLoop engineering | SDD-POL-029: meal-adaptation exclusion stated explicitly on every step cloud payload (meal_adaptation_exclusion_active true/false + request step/reason when active; sponsor request - excluded-or-not must never be inferred from silence; success path visible as the flag reverting without disposal evidence). |
| 1.39 | 2026-07-16 | BionicLoop engineering | SDD-OUTAGE-001: outage-surface gating aligned to the SRS-OUTAGE-002 v1.37 definition (field catch - relaunch blind steps no longer show a false fingerstick countdown). |
| 1.40 | 2026-07-16 | BionicLoop engineering | SDD-OUTAGE-001 added release-window quantification at re-arm, updating the engaged event with duration and modeled schedule exposure under RA-020. |
| 1.41 | 2026-07-17 | BionicLoop engineering | Extended SDD-CLIN-001 for the SRS-CLIN-014 telemetry drain guard: pre-confirmation flush, pending-count consent line, guarded asynchronous outbox discard with sequence continuity, and episode-latched operator alerting for permanent upload rejections. |
| 1.42 | 2026-07-18 | BionicLoop engineering | SDD-OUTAGE-001 aligned to SRS-OUTAGE-006 v1.42 (2026-07-18 field incident): released-window accounting restated as implemented live per-step crediting (OutageDeliveryCreditSupport echo + pod-delta tuples), pod-away gap reconciliation described as the coordinator-synthesized standard bounded replay (confirmed-stamped plan, echo chain, re-anchor + exactly-once accumulation), and re-arm quantification's pump-measured upgrade documented; the v1.40 interim-posture clause is closed. |
| 1.43 | 2026-07-18 | BionicLoop engineering | Aligned SDD-OUTAGE-001 with SRS-OUTAGE-006 v1.43 after independent safety review: 0.01 U quantized largest-remainder replay in the engaged profile timezone; persisted credit context across termination; and discard/re-synthesis after a cadence-drift skip. |
| 1.44 | 2026-07-18 | BionicLoop engineering | Documentation truth-sync: SDD-POL-029 and SDD-DATA-003 no longer treat active issued-dose reconciliation holds as an available or persisted mechanism. The writer-less hold was removed in c42f2a6; pending attribution, confirmed or assumed-delivered exactly-once consumption, discrepancy evidence, and lifecycle expiry remain the implemented controls. SDD-LOG-001 now records the sponsor-approved RA-009 local-file controls, including protection/backup exclusion for enumerated Algo2015 diagnostics. |
| 1.45 | 2026-07-18 | BionicLoop engineering | SDD-ALERT-001 check-BG presentation aligned to the study workflow: copy states that either a fingerstick BG check or sensor read can resume automated dosing; the alert has no inline Enter BG action, while the separate Home BG-entry control remains emphasized and available. |
| 1.46 | 2026-07-19 | BionicLoop engineering | Exact-step pending-BG meal availability and pump-signal alert precedence: the forced-open meal block is bypassed only for a valid pending BG targeting the prospective meal step, with shared primary/safety consumption; pump signal loss ranks above same-severity check-BG while severity remains dominant. |
| 1.47 | 2026-07-20 | BionicLoop engineering | Manual-BG entry now reviews the frozen exact value in a native confirmation alert instead of mutating the submit button in place; direct check-BG, due-soon, and overdue requests share the Home gold breathing emphasis with a static Reduce Motion alternative. |
| 1.48 | 2026-07-20 | BionicLoop engineering | Manual-BG request emphasis now keeps the card shadow static and confines its repeating animation to a bounded gold stroke halo around the BG control, preventing chart-layer compositing artifacts while preserving the existing request policy and Reduce Motion behavior. |
| 1.49 | 2026-07-20 | BionicLoop engineering | SDD-POL-029 added the fresh-completion upgrade rule after a 2026-07-20 field incident: same-pod settled post-completion status can supersede deferred evidence with pump-observed completion, while canceled partials retain authoritative partial evidence. |
| 1.50 | 2026-07-20 | BionicLoop engineering | SDD-POL-004 (SRS-MEAL-006 v1.49): open-composer revalidation gains consumed-carve-out detection — carve-out context captured at composer open and on every in-place re-arm, and a carveOutBGConsumed flag that, only for the backupBasalRunning reason, swaps the generic backup-basal copy for the consumed-carve-out inline message; all other reasons and recovery routes unchanged. |
| 1.51 | 2026-07-20 | BionicLoop engineering | SDD-POL-004 corrected (SRS-MEAL-006 v1.50, sponsor correction of the v1.49 model): the consumed-carve-out flag becomes carveOutBGConsumptionInFlight (pending BG cleared while the captured target step has not yet published) and routes the backupBasalRunning reason to a showTransientWaiting hold — composer armed, passive applying notice, re-armed by the consuming step's publication — instead of any inline block or new-fingerstick demand; the same predicate guards backup-basal-blocked submits (pre-check and engine-blocked outcomes). Persisting forced-open after the consuming step published falls through to the generic backup-basal copy. |
| 1.52 | 2026-07-21 | BionicLoop engineering | SDD-LOG-001 amended (SRS-LOG-009 v1.51 steady-cadence fallback schedule visibility): schedule_checked_unchanged events attach the schedule + coverage payload minus profile_rates_288; new profile_observed_slot_counts_by_bucket field on arm/refresh/unchanged events (from Q5NominalBasalProfileSchedule.observedSlotCountsByBucket); Recent Dose Steps schedule rows add outcome label + per-segment observed/imputed provenance via HomeRecentDoseStepsDisplaySupport. |
| 1.53 | 2026-07-21 | BionicLoop engineering | SDD-POL-029 now persists explicit canceled-vs-in-progress-capped observation context and permits fresh completion upgrade only for positively identified in-progress caps; zero post-relaunch bolusNotDelivered no longer overrides canceled or legacy-unclassified partial evidence. SDD-ALERT-001 truth-synced to the accepted 569f17c centered shadow bloom (meal-selector envelope) and no-glow Reduce Motion treatment. |
| 1.54 | 2026-07-21 | BionicLoop engineering | SDD-POL-004 gains a shared prospective forced-open meal policy. OutageBGRunContext persists the algorithm step that consumed the last qualifying glucose; UI availability evaluates the exact prospective step, and the coordinator repeats the check after step resolution but before accepted-meal persistence. The characterized 12th blind step remains eligible; the 13th is rejected unless that step carries fresh CGM or a valid exact-step fingerstick. |
| 1.55 | 2026-07-22 | BionicLoop engineering | SDD-POL-004 meal-unavailable precedence corrected so a live connected .delivering status is presented as pump busy before pending attribution messaging; idle unresolved attribution behavior is unchanged. |
| 1.56 | 2026-07-22 | BionicLoop engineering | SDD-POL-004 consumed-BG revalidation now uses the exact step's persisted lastQualifyingGlucoseStep as its completion marker instead of lastExecutedStep alone, covering the pre-command maintenance checkpoint race. Home observes qualifying-glucose and pump-status changes to revalidate an open composer, re-arm on final BG publication, and replace stale backup-basal copy with connected pump-busy guidance when delivery starts. |
| 1.57 | 2026-07-24 | BionicLoop engineering | Added SDD-CLIN-002 and extended SDD-CLIN-001/LOG-001 for the Pregnancy Temporary Target lifecycle, execution-time primary-target resolution, permanent safety/fallback basis, explicit UI workflow, relaunch/expiry handling, Standard-to-Pregnancy meal default, and app-to-Scout observability. |
| 1.58 | 2026-07-24 | BionicLoop engineering | Hardened the SDD-CLIN-001/002 and SDD-LOG-001 New Participant Reset and Temporary Target telemetry boundary: reset gates new transport, waits a bounded interval for ordinary transport quiescence, durably erases before initiating the detached discard marker, rechecks live Pod/session guards, blocks concurrent algorithm arming, fully removes outgoing Temporary Target audit state, preserves legacy wire event IDs while deduplicating them against the current deterministic UUID form, and pins execution telemetry to the configuration captured for that serialized work pass. |
| 1.59 | 2026-07-30 | BionicLoop engineering | Extended SDD-CLIN-002 with the reusable OmniBLE suspension control hosted directly on Exercise and Insulin Delivery, BionicLoop-only suppression of the duplicate Pod Settings Activity section, and one-shot suspend-alert navigation to the relocated control. |
| 1.60 | 2026-07-30 | BionicLoop engineering | Extended SDD-POL-016 with persistent signed-out Home login access, direct recovery actions from Alert Center and Account & Session, login-specific notification routing, and local-therapy/session continuity during authentication re-entry. |
| 1.61 | 2026-07-30 | BionicLoop engineering | Extended SDD-CLIN-002 with the reordered Settings entry, app-standard Temporary Target selectors/actions, removal of unrelated participant-reset guidance, and local draft-loss interception for target-only, duration-only, and complete unactivated selections. |
| 1.62 | 2026-07-30 | BionicLoop engineering | Extended SDD-POL-019 with the Home bottom safe-area action surface: Manual BG and Meal Announcement remain fixed while the reserved-inset content area scrolls, reusing the existing action handlers and emphasis policy. |
| 1.63 | 2026-07-30 | BionicLoop engineering | Replaced the episode-latched participant telemetry-rejection alert with durable failed-permanent outbox evidence (failure timestamp + HTTP status), preserved Scout gap detection and the specific Subject ID Conflict alert, retained 429 retry behavior, and added a one-time launch migration that clears earlier-build generic alerts/notifications. |
| 1.64 | 2026-07-30 | BionicLoop engineering | Extended SDD-CLIN-002/SDD-POL-008 with a direct, serialized OmniBLE resume command on the suspend-ended alert and persisted 15-minute actionable-to-safety-critical escalation with one-time re-notification. |
| 1.65 | 2026-07-30 | BionicLoop engineering | Extended SDD-POL-004/029 and Home status design so suspended delivery blocks meal execution before algorithm state advances, confirmed resume revalidates immediately, and definitively rejected bolus cache state cannot be reconstructed as later delivery feedback. |
| 1.66 | 2026-07-30 | BionicLoop engineering | Added SDD-CGM-002 for persistent explicit G7 replacement acquisition, raw-scan/replacement-scan state separation, timed in-app guidance, and durably deduplicated acquisition telemetry. |
| 1.67 | 2026-07-31 | BionicLoop engineering | Extended SDD-POL-022 with execution-outcome-based interruption diagnosis, explicit suspension/fallback-recovery blocker states, stale-blocker clearing after successful stepping, and Home suppression of redundant interruption banners while the suspend-ended alert is active; aligned SDD-CLIN-001 reset teardown with asynchronous G7 persistence/telemetry isolation. |
| 1.68 | 2026-08-06 | BionicLoop engineering | Extended SDD-LOG-001 with persisted-input-derived fingerstick provenance in Recent Dose Steps, including exact manual BG value and concurrent CGM retention. |
| 1.69 | 2026-08-11 | BionicLoop engineering | Corrected SDD-ALG-001 host output mapping so each pump recommendation sums Algo2015 bolus, basal, and meal components exactly as the reference-host interface requires. |
| 1.70 | 2026-08-11 | BionicLoop engineering | Aligned SDD-CLIN-001 with the implemented initial-configuration boundary: no unlock while the persisted subject configuration is unusable/unset; the first successful save closes that exception and later access remains unlock gated. |
| 1.71 | 2026-08-13 | BionicLoop engineering | Extended SDD-LOG-001 with the v2 incremental telemetry spool, transactional v1 migration, retained-first recovery ordering, coalesced chatter-drop evidence, notification lifecycle deduplication, and passive upload-health presentation. |
| 1.72 | 2026-08-17 | BionicLoop engineering | Extended SDD-LOG-001 with the SQLite v3 retained-evidence ledger, async network drain/retry liveness, bounded backward-compatible batch upload, and a complete protected active-session step archive separate from the 576-row UI cache. |
| 1.73 | 2026-08-20 | BionicLoop engineering | Extended SDD-BG-001 with persisted pending-BG chart projection and explicit completed-step consumption evidence so the Home marker changes from outline to fill without timestamp movement or duplication. |
| 1.74 | 2026-08-20 | BionicLoop engineering | Extended SDD-LOG-001 with read-only discovery, epoch-session selection, bounded protected snapshots, stored-entry ZIP generation, and clinical-gated sharing for legacy Algo2015 artifacts. |
| 1.75 | 2026-08-20 | BionicLoop engineering | Corrected SDD-LOG-001 export presentation sequencing so session choice, confirmation, preparation, sharing, and failure remain within one stable sheet lifecycle instead of competing UIKit presentations. |
| 1.76 | 2026-08-20 | BionicLoop engineering | Replaced the unstable Settings export flow with a prebuilt combined CSV/Algo2015 recovery ZIP shared by the existing Recent Dose Steps ShareLink; exact epoch mismatch now falls back to CSV-only. |
| 1.77 | 2026-08-20 | BionicLoop engineering | Extended SDD-POL-022 with a status-refresh-only pump recovery transition: newer active-Pod idle evidence replaces stale unavailable copy under the existing alert key without waking the algorithm, and later unknown status restores the unavailable diagnosis. |
| 1.78 | 2026-08-20 | BionicLoop engineering | Updated SDD-POL-019 to use point-only CGM chart rendering, removing the connector stroke and connected area fill while retaining dot styling, axes, and scrub behavior. |
| 1.79 | 2026-08-21 | BionicLoop engineering | Bound the controlled design description to the immutable 2026-08-21 software freeze and clarified the pending approval boundary. No design or product behavior changed. |
| 1.80 | 2026-08-21 | BionicLoop engineering | Added the candidate build-input control that requires CryptoSwift 1.10.0 exactly, tracks the app-workspace SwiftPM resolution, and fail-closed checks source/version/revision/Git control. No runtime, dosing, pump-command, or cryptographic behavior changed. The frozen baseline and archive 826 remain historical identities. |
| 1.81 | 2026-08-27 | BionicLoop engineering | Replaced internal development labels and test-device shorthand with reviewer-neutral descriptions, removed an obsolete unselected future-mitigation note, and updated the approval role. No design or product behavior changed. |
| 1.82 | 2026-08-28 | BionicLoop engineering | Completed allocation of the five active SRS identifiers omitted from the design-allocation table and reclassified the manual-BG wall-clock question as a deferred enhancement rather than an unresolved baseline decision. No design or product behavior changed. |
| 1.83 | 2026-09-03 | Software Developer | Recorded the frozen Build 843 G7 replacement-acquisition implementation limits found by the RA-023 adversarial review: direct manager reconstruction preserves an episode, but CGM-screen setup reentry can install a fresh manager; already-queued concurrent candidates lack an atomic single-winner gate; and the first accepted replacement reading can reach runtime before post-connection comparison. No product source or frozen design implementation changed. |
| 1.84 | 2026-09-03 | Software Developer | Aligned Build 843 configuration status, register references, alert-validation status, dependency wording, and submission-facing citations with the final software approvals and controlled appendix boundary. No product design or frozen implementation changed. |
1. Design Intent¶
This design implements a CGM-triggered closed-loop runtime with:
- deterministic cadence state
- degraded execution behavior when inputs are unavailable
- explicit gating for pump command application
- traceable per-step telemetry
2. Major Components¶
-
SDD-APP-001:LoopRuntimeEngine(BionicLoop/Runtime/LoopRuntimeEngine.swift) handles wake handling, availability logic, session control, and telemetry orchestration. -
SDD-APP-002:LoopSessionStoreowns app-layer runtime persistence reads/writes for loop armed state and runtime state snapshots. -
SDD-APP-003:LoopWorkSchedulerowns CGM-timestamp trigger dedupe and arm/reset semantics for runtime wake dispatch. -
SDD-APP-004:LoopAlertMediatorowns pump signal-loss tracking and report gating in app-layer state. -
SDD-APP-005:LoopTelemetryWriterowns app-layer telemetry-store writes and reconciliation calls. -
SDD-APP-006:LoopRuntimeWorkExecutorowns coordinator doWork execution snapshot sequencing (latest reading capture, operation execution, completion timestamp, state snapshot). -
SDD-APP-007:DeviceClockSyncMonitor(BionicLoop/App/AuthSessionNetworking.swift) owns UTC midpoint drift checks (GET /v1/time/utc), retry policy, 24-hour foreground check gating, timezone/significant-time-change trigger handling, and lifecycle telemetry context projection. -
SDD-APP-008:CloudAppBannerConfigSupport(BionicLoop/App/CloudAppBannerConfigSupport.swift) owns the server-configurable investigational badge (SRS-UI-009): parse ({"config": {"text", "issued_by"}}envelope; missing/non-string text ignored;nullclears), UserDefaults persistence, and the three-stateeffectiveText(absent config -> built-inNOT FOR HUMAN USE, configured text verbatim, explicit blank ->nil= no capsule).HomeTopOverlayBarrenders the capsule fromeffectiveTexton a one-minuteTimelineViewrefresh. All server-issued configs share one fetch cadence viaCloudRemoteConfigSupport.refreshAll/startPeriodicRefresh(launch, foreground, 30-minute loop) - the logging-config loop moved here fromCloudLogRemoteConfigSupportwhen the second config was added. -
SDD-AUTH-001: App auth-session boundary is split intoAppAuthSessionManager(secure token persistence, restore, refresh, sign-out clear) andAuthenticatedAPIClient(bearer-auth request composition + one-time refresh retry on unauthorized response), implemented inBionicLoop/App/AuthSessionNetworking.swift. Recovered/refreshed token sets are validated for telemetry-ingest scope before persistence. -
SDD-AUTH-002: Email/password recovery boundary is implemented inCognitoPasswordRecoveryService(ForgotPassword,ConfirmForgotPassword) plus unauthenticated route/state wiring (.forgotPassword) andNoAuthForgotPasswordViewfor reset-code request, confirmation, resend, and user-feedback messaging. -
SDD-CFG-001: Build 843 is the IDE submission build approved on 2026-09-03. Its controlled source requires CryptoSwift1.10.0exactly in the OmniBLE Xcode project, tracks the app-workspace SwiftPM resolution, and applies a fail-closed source/version/revision/Git-control check. This prevents an archive and its verification run from silently resolving different dependency versions. Archive identity, signing, installation, and evidence acceptance remain separate configuration controls. -
SDD-CORE-001:LoopRuntimeCoordinator(BionicLoopCore/.../Runtime/LoopRuntimeCoordinator.swift) handles due-step logic, input assembly, algorithm invocation, and command application. -
SDD-ALG-001:RealBUDosingAlgorithm+Algo2015Bridgemap runtime input into C bridge structs and receive output/state. The primary host constructs the pump recommendation asbolusInsulinRequested + basalInsulinRequested + mealInsulinRequested, matching the referenceAlgorithmInterface.handAlgorithmController.deliverFluidcontract; the same total is persisted as the issued request and returned as pump feedback soReconcile_I_Dosecompares like-for-like values. Two live algorithm instances run per host step (primary dosing track; safety track computing raised-target fallback basal profiles): each binds its OWN symbol-isolated compilation of the unmodified algorithm + bridge sources (Algo2015.xcframework/Algo2015Safety.xcframework; the controlled safety build renames three extern "C" entries and localizes all other symbols, and its identity report proves byte-identical object code). This preserves the C++'s one-instance-per-process state model (file-scope globals, load-once) per instance;RealBUDosingAlgorithmselects the copy viaAlgo2015EngineInstance(2026-07-10). -
SDD-PUMP-001:PumpServiceAdapter+PumpStatusObserverhandle status refresh, command execution, delivery reconciliation, home-status projection, and auto-polling whiledeliveryState == delivering. For the masked offline-fallback subsystem, the pump abstraction also carries a domain-level programmed basal-schedule seam (PumpBasalSchedule) so runtime can read and rewrite the pod's current basal schedule without taking a direct dependency on OmniBLE schedule types. On DASH, replacing the programmed basal schedule is a disruptive arm/disarm operation rather than a neutral setter: the OmniBLE implementation cancels current delivery before applying the new schedule, so the app seam now treats schedule replacement as an interrupting operation and blocks it unless pump delivery is in a known safe connected state (no active bolus, no nonzero temp basal, not suspended/resuming/suspending, and no unknown basal-delivery state). The accepted masked-fallback path uses that seam in two explicit maintenance operations only:performMaskedFallbackMaintenance(...)replaces the programmed fallback schedule and immediately reapplies the0.0 U/hr / 30 minutemask, whileperformMaskedFallbackDisarm(...)restores the original programmed schedule without reapplying the mask. Runtime arms masked fallback immediately for a new active algorithm session once a valid fallback candidate is available from the current or latest successful step. If the candidate is first produced by the current step,LoopRuntimeCoordinatorinvokes a pre-pump-command maintenance hook after primary/secondary algorithm calculation but before applying that same step's pump recommendation; this lets step0program the fallback schedule and0.0 U/hrmask before a bolus command can place the pod into bolus-in-progress. The hook receives the same refreshed pump status used by pump-command classification and skips fallback maintenance when that status is unavailable or unknown, so it cannot bypass the normal pump availability/unknown-state gate. If a valid candidate is already persisted but no fallback is currently armed, the existing pre-step maintenance pass first refreshes pump status and only arms fallback before the next loop execution when that status is idle; unavailable, unknown, delivering, or failed refresh leaves maintenance deferred without pod mutation. If the initial arm is cleanly blocked before any schedule mutation, runtime leaves fallback explicitly unarmed, records a failure instead of pretending ordinary deferred masked maintenance is active, and lets the current step's normal pump command proceed through its own safety gates; the same execution cycle does not then run post-execution masked-fallback maintenance for a second first-arm attempt. If the programmed fallback schedule may have been written but the immediate mask fails, is blocked, or is uncertain,PumpServiceAdapternormalizes that post-schedule mask error asremaskFailed, runtime persists reconciliation-required recovery context, and the current step's normal pump command is blocked before additional pod mutation. Runtime now maintains Swift-side q5 nominal-basal profiles from primary and secondary/safety algorithm scalar outputs; fallback programming prefers the secondary/safety profile, imputes missing 5-minute slots from observed values, averages four local-time six-hour buckets, rounds each bucket through the pump service, and programs the resulting four-entryPumpBasalSchedule(0,21600,43200,64800seconds) under the mask. If no q5 profile is available, runtime falls back to the latest rounded scalar safety-track nominal-basal candidate. Runtime refreshes the programmed fallback schedule no more often than the configured refresh interval when the desired schedule changes, preserves recoverable restore context on session reset/disarm until the original programmed schedule is successfully restored or explicit restore failure is recorded, and blocks the next algorithm start while unresolved restore-failed masked-fallback recovery remains in persisted state. For an already-masked fallback, steady-state connected behavior does not rewrite the mask every step: runtime tracksmaskExpiresAt, enters a renewal window when20 minutesor less remain on the active30 minutemask, and performs pre-step renewal before the next loop execution only after a fresh idle pump-status refresh. If bolus, unknown/unavailable status, refresh failure, or other blocked pump state prevents renewal while the current mask is still active, runtime records deferred maintenance rather than immediate failure;PumpServiceAdapternow normalizes both device-state and late communicationunfinalizedBolusoutcomes on the temp-basal renewal path into that deferred-maintenance result while the current mask still has time remaining. If a remask failure occurs after an existing masked fallback renewal or schedule-refresh path and may leave fallback exposure uncertain, runtime records the exposure start (maskExpiresAtfor renewal uncertainty, or current time for post-refresh remask failure) and enters reconciliation-required recovery rather than continuing ordinary stepping. If successful step execution stalls or deferral continues long enough for the active mask to expire, the pod is allowed to resume the programmed fallback schedule and runtime records that activation for later reconciliation rather than immediately remasking. OncemaskExpiredOfflineis recorded, runtime also persists a reconciliation-required recovery state and suppresses ordinary loop execution, manual BG dispatch, meal announce availability, and new arm until reconnect recovery resolves. While that state remains pending, runtime attempts connected restore/disarm of the original programmed basal schedule on runtime start, app foreground, or pump reconnect. If restore succeeds while the loop remained armed, runtime clears the persisted masked-fallback state without resetting the current session, preserves the existing cadence anchor, and resolves basal-only reconnect evidence against the persisted fallback context. Exact cached-schedule equality is no longer a hard prerequisite for corrected recovery: if reconnect finds a different cached programmed schedule in local OmniBLE manager state, recovery may still record acorrectedresult and proceed with pump-delta reconciliation, but only when the persisted blackout context, proven same-pod continuity, a fresh connected pod-total-delivery baseline, and close agreement between modeled and pump-reported delivered insulin together provide credible basal-only evidence. App-log diagnostics capture both the persisted fallback schedule and the cached reconnect schedule from manager state for later review; that cached schedule is explicitly not treated as authoritative pod truth. Confirmed or corrected recovery persists pending pump-delta reconciliation metadata, records the resolveddisarmedfallback event with reconciliation metadata, and letsLoopRuntimeCoordinatorallocate the same-pod pump-reported delivered-insulin delta across missed 5-minute primary/secondary algorithm replay steps using the persisted programmed fallback schedule as the weighting model. Each missed replay step usesCGM=-1, that step's delivered-insulin allocation including explicit0 Uinput when no pump allocation belongs to that step, and no pump command application; the resumed live step then runs with actual refreshed pump status rather than a duplicate aggregate recovered-delivery input. If a positive pump delta cannot be weighted because persisted fallback schedule weights are unavailable or zero, runtime suppresses replay rather than fabricating an allocation; if the authoritative pump delta is0 U, the replay plan may still preserve the missed-step range so coordinator replay can emit0 Ualgorithm inputs. Pending replay metadata is single-use: if the live due step no longer matches, the plan is malformed, no session anchor exists, or the plan no longer contains missed steps before the current due step, coordinator emits a skipped replay trace and clears the pending plan instead of retrying it against later wakes. Ambiguous, different/new pod, unknown pod identity, or history-discontinuous recovery records a resolveddisarmedevent stamped asresumed_without_reconciliationand permits only the current due 5-minute step without replay. If the operator explicitly reset or turned the loop off first, successful recovery restores the original programmed schedule but keeps the loop off. The reconnect path now also exposes a basal-onlymakeFallbackBasalReconciliationSnapshot(...)seam carrying a stable pod identity, the cached programmed basal schedule from manager state, recent automatic temp-basal evidence, and pod cumulative delivered-insulin measurements so recovery can compare modeled fallback exposure against pump-reported delivered insulin since the last connected same-pod fallback baseline. Core now contains pureFallbackBasalExposureReconciliation,FallbackBasalPodContinuity, andFallbackBasalReplayPlansupport types, and runtime/coordinator use them both for recovery classification/review and for no-command pump-delta missed-step algorithm replay when reconnect evidence is confirmed/corrected and same-pod; modeled exposure and replay weighting now integrate the persisted fallback schedule across six-hour bucket boundaries, partial replay slots, and local-day midnight wrap rather than multiplying the entire blackout by one scalar rate. Current audible-command behavior remains split by the existing OmniBLE command categories: the automatic0.0 U/hrmask temp basal follows automatic-command beep preference rules, while fallback schedule arm/refresh/disarm still reuse the manual/profile basal-schedule programming path and therefore may emit the normal DASH confidence beep unless pod confidence beeps are disabled or the pod is silenced. A silent maintenance-specific basal-schedule write path remains deferred backlog work. Every pump command and status await inPumpServiceAdapteris bounded byPumpCommandWatchdog(120seconds): a timeout fails the command as uncertain (or the status read as blocked) instead of stalling the serialized loop work pass, and late or duplicate transport completions after the watchdog fires are ignored safely (SRS-PUMP-011); the pump-event storage delegate's synchronous-completion contract is regression-pinned. - Retired/expired/no-active pod exception: when masked-fallback recovery is pending and
PumpStatusObserverproves the previous pump session no longer has an active pod, or the observed time is beyond hard pod service stop, runtime may synthesize an assumeddisarmedrecovery event without connected schedule restore. The event usesassumed_delivered_per_clinical_policy, sets actual delivered fallback units equal to modeled schedule exposure for the bounded fallback-active interval, queues the normal no-command replay plan, clears the recovery state, and keeps the existing algorithm session. UI and telemetry label this as assumed delivered, not confirmed/corrected pump reconciliation. - Replay eligibility is bounded to missed slots whose delivery interval overlaps confirmed fallback-active time. Missing slots that occurred after pump communication loss but before offline fallback activation remain absent from replay, not synthetic
0 Urows; explicit0 Ureplay rows are preserved only inside the fallback-active interval. -
SDD-CGM-001:G7ViewModel+ CGM subsystem adapters provide CGM state ingestion and wake trigger source; telemetrycgm.state.changedis emitted from refreshed/current callback state to avoid stalehas_sensortransitions, andcgm.connection.changedderivesstatus_textfrom refreshed lifecycle state before emit. -
SDD-CGM-002:G7CGMManagerStatepersists a replacement-acquisition episode separately fromG7Sensor.isScanning: start time, prior sensor ID, trigger, the latest adoption event, and post-enqueue telemetry markers survive direct manager reconstruction.G7SettingsViewModel.scanningForReplacementtherefore controls a separate progress label without conflating ordinary BLE search for the bound sensor with user-directed replacement; theScan for new sensorbutton remains visible and actionable during both states so an instructed retry can restart BLE discovery.G7CGMManager.scanForNewSensorrecords the episode, invokes a thread-safe synchronous app persistence handler with that snapshot, and only then directs the lower BLE layer to release its binding. Repeated triggers on the retained manager preserve the original clock/evidence, and authenticated glucose discovery records adoption and clears replacement state. Device-reported sensor failure/session end and the existing remote-disconnect-during-authentication heuristic can enter replacement mode; routine disconnect does not.AppCGMManagerDelegatederives the ten-minute alert, owns and cancels its delayed evaluation task, retracts it on recovery, and emits stable-IDcgm.state.changedstall/adoption payloads from the common state-sync path independently of CGM screen lifetime, including the first sync after relaunch. An in-memory in-flight guard prevents duplicate telemetry enqueue; after durable outbox acceptance, the manager synchronously persists the matching marker, while failed enqueue remains eligible for a later retry. Stale reading age does not participate in replacement selection. Known frozen Build 843 limits are recorded underANOM-007andRES-010in the IDE Known Anomalies and Residuals register, andD06in the IDE Submission Decision Register: reopening CGM setup while the binding is cleared can install a fresh manager and reset the retained episode; already-queued candidate callbacks have no atomic single-winner adoption gate; and the first accepted replacement reading can reach runtime before staff complete the IFU post-connection comparison. -
SDD-BG-001: Manual BG entry path spans Home/UI entry, runtimebgCheckwake dispatch, single-pending-candidate BG state, next-eligible-step consumption logic, and telemetry source tagging (manualBG). The same runtime entrypoint now also checks persisted masked-fallback recovery state and refusesbgCheckdispatch while reconnect reconciliation is required. A valid pending BG may ride with meal input only whenpendingManualBGTargetStepequals the exact prospective meal execution step; coordinator consumption supplies the same value once to both primary and safety algorithms and clears the persisted candidate. Once submission persistence succeeds,LoopRuntimeEnginepublishes the stored pending value, submission time, and target step before runningdoWork, allowing Home to project an unfilled blood-drop marker immediately and after relaunch. Coordinator execution carries aManualBGConsumptionreceipt throughDoWorkResult;LoopTelemetryStorepersists its original submission time beside the completed step'sAlgorithmInputSnapshot. Home derives filled markers only from completed step records with valid positivebgValueMgdl, prefers that used evidence over a concurrent pending projection for the same target step, and retains the original submission time so the marker changes state without moving. Older step records decode without the optional timestamp and fall back to execution time. Pending-state disappearance alone is never interpreted as consumption. The entry sheet uses explicit digit-keypad entry (starts empty; a fingerstick value must be typed, never submitted from a stale prefill), a large rounded monospaced value display with inline range validation against20...600 mg/dL(out-of-range shows safety-critical styling and disables submit), tightened no-CGM-calibration guidance, and a neutral (non-destructive) Cancel.Review BGfreezes the valid entered value and presents a native, spatially separateUse <value> mg/dL?alert;Changedismisses the alert without clearing the digits, and only the alert's exact-valueUseaction submits. Rapid repeated taps on the entry action can therefore only present the review alert, not submit. A single UI-critical telemetry event carries the frozen final value at confirmation rather than one event per keypad tap. -
SDD-CLIN-001: Clinical settings boundary spans initial staff configuration, offline clinical-unlock-gated subsequent settings presentation, clinician-only control hosting (Subject ID,Weight,Start Algo,Same-Participant Reset- formerlyReset Algo), runtime-facing pregnancy configuration projection (target,meal upfront,TMAX), a clinician-controlled participant target-access profile (Pregnancy/Standard), and the participant-facing target-change approval-capture sheet hosted in general settings.HomeClinicalSettingsSavePolicy.hasUsableClinicalSettingsdefines the boundary: while subject ID or clinically plausible weight is absent, the initial review/save path is available without an unlock; the first successful save makes the configuration usable and all later Clinical Settings access/edits require the subject-scoped offline unlock. First-launch defaults are Standard/120 mg/dL/75%/40-minute TMAX (HomeClinicalSettingsPolicy, clinical direction 2026-07-14); defaults never rewrite persisted values. Clinical Settings additionally hosts theNew Participant Reset(UI entry pointLoopRuntimeEngine.performNewParticipantResetDiscardingTelemetryOutbox, wrapping the synchronousperformNewParticipantReset): a dual-confirmed, unlock-gated wipe of every participant-scoped store (config, algorithm/runtime state, Temporary Target state, local telemetry + CSV, cloud outbox, alert history, stored pump/CGM manager state, subject-scoped keychain unlock material, onboarding completion/claim), with sign-out performed by the app-root caller (onParticipantSignOut-> session store) after the engine wipe completes -performNewParticipantResetitself does not sign out. The reset is refused while a Pod is active; the pre-existing control is relabeledSame-Participant Resetand sits besideNew Participant Resetin a symmetric two-button row; when a session is armed, New Participant Reset presents a guidedStop Session and Continueconfirmation before the erase confirmation. Telemetry drain guard: tapping the reset (and again after a guided session stop) triggers a finalCloudTelemetryReporter.flushNow()and re-readspendingUploadSummary(); a nonzero pending count appends the discard-consent line to the erase confirmation viaHomeNewParticipantResetConfirmationPolicy(nil count = no line until the drain settles). On confirm, the drain-guard checks the live armed/Pod guards, blocks concurrent algorithm arming, invalidates and drains queued runtime work, cancels Temporary Target drain/retry work, gates new outbox transport, and lets any ordinary transport already in flight quiesce for a bounded interval. Timeout or persistence failure returnsfailedTelemetryErasureand leaves participant stores intact. The engine rechecks live guards after asynchronous preparation and immediately before invoking the irreversible erase.CloudTelemetryReporter.discardOutboxWithinNewParticipantResetTransaction()then erases spool entries in every state while preserving the install-scoped sequence counter, reserves a sequence, and initiates the nonblocking best-efforttelemetry.outbox.discardedmarker; the telemetry gate remains held until the synchronous participant wipe completes, preventing outgoing-subject events from repopulating the spool.AppCGMManagerDelegate.clearStoredParticipantStatecancels replacement-acquisition alert work, clears acquisition/adoption event IDs in flight, detaches both the ordinary manager-state delegate and the G7 replacement-state persistence callback, and releases its attached-manager reference before removing raw manager state; a late manager callback or cloud-enqueue completion therefore cannot repersist an outgoing participant's CGM state after reset. First-launch setup renders labeled groups (Participant,Mode & Glucose Target,Insulin Settings) with per-mode target defaults and a review summary that includes the mode;ClinicalAlgorithmConfigStore.loadreturns first-launch defaults for an empty store WITHOUT persisting them. -
SDD-CLIN-002:TemporaryTargetStoreowns a subject-bound, lock-serialized UserDefaults state containing the active override, pending lifecycle telemetry, first-applied evidence, and bounded effective-time intervals used to classify historical replay rows.LoopRuntimeEngine.activateTemporaryTargetvalidates Pregnancy profile, armed-session, active-Pod, recovery-idle, explicit target, and explicit duration gates; activation persists before UI success, schedules an informational local expiry notification, and does not issue a Pod command.LoopRuntimeEngineOperationalSupport.primaryTargetResolverresolves the primary target from each row's execution timestamp, while coordinator construction derives the safety target exclusively fromLoopConfig.permanentTargetMgdl; Temporary Target therefore cannot change the safety instance, q5 profile basis, programmed fallback schedule, or session identity. Exact timestamp resolution makes the first row at/after expiry use the permanent target even after relaunch or missed notification. Replacement closes the prior interval and records a replacement lifecycle event before the new activation; early end, expiry, session stop/reset, profile change, and participant reset have distinct deterministic dispositions. Session stop closes the active interval while preserving the historical interval needed for already-executed replay evidence; New Participant Reset cancels lifecycle drain/retry work and removes the complete outgoing-subject Temporary Target store without emitting or retaining a reset lifecycle record.HomeTemporaryTargetViewprovides the explicit no-preselection review/confirm flow on the combinedExercise and Insulin Deliveryscreen, while Home and Settings publish active target/end time. The Settings root places that destination before User; the screen uses the same outlined selected-state palette and primary/secondary action styles as the rest of the participant UI and omits the unrelated reset-location note.TemporaryTargetSelectionPolicy.hasUncommittedSelectiontreats either selected field as a transient draft; while a draft exists, the view replaces native back navigation with an explicit discard alert and disables interactive sheet dismissal. Successful activation clears both draft values before ordinary navigation is restored. The same screen embedsOmniBLEInsulinSuspensionView, a reusable presentation of the existing OmniBLE suspend/resume commands and four reminder choices; presentation policy disables commands for unusable Pods and transitional basal states while preserving the existing manual-resume requirement. The standard BionicLoop Pod Settings route passesshowsInsulinSuspensionControls = falseintoDashUICoordinator, removing the duplicate Activity section without changing OmniBLE's default integration behavior. Suspend-alert notification routing creates a one-shotHomeSettingsNavigationRequestthat presents Settings atExercise and Insulin Delivery; other pump-alert routes remain unchanged.HomeInsulinResumeActionModelalso exposes the sameOmniBLEPumpManager.resumeDeliverycommand directly from the active suspend-ended Home/Alert Center row, serializes taps while the command is in flight, surfaces a retryable communication error, refreshes pump status after command success, and deliberately leaves alert retraction to pump-confirmed lifecycle evidence. The explicit Standard-to-Pregnancy draft transition is centralized inHomeClinicalSettingsPolicy.mealUpfrontPercent(afterTransitionFrom:to:currentValue:), leaving stored configurations unchanged until save.TemporaryTargetTelemetrySupportemits subject-overridden durable lifecycle envelopes, and loop-step telemetry carries permanent/applied/safety target context; each serialized work pass retains theLoopConfigcaptured for that operation through lifecycle attribution and cloud emission, preventing a later configuration change from relabeling the completed pass. BionicScout merges lifecycle and step-use evidence by override ID and event time so delayed events cannot resurrect a terminal interval. -
SDD-LOG-001:LoopTelemetryStorekeeps the newest 576 per-step records as the Recent Dose Steps presentation cache and independently upserts every current-session step intoSQLiteLoopStepArchive; the protected clinical-gated CSV reads the complete archive, and explicit session reset clears it.CloudTelemetryReporteremits authenticated telemetry envelopes with correlation metadata (event_id,session_id,subject_id) plusauth_user_subderived from Cognito ID-tokensub(fallbackUNSETonly when unavailable); loop-step payloads carry explicit execution timestampstep_executed_at(execution semantics) in addition to envelopecreated_at(ingest creation time). Loop command telemetry mapping is schema-stable:loop.command.blockedis emitted only when a recommendation existed but was blocked, whilepump.command.resultremains pump-result schema only and emits on delivery-result deltas only (no unchanged refresh re-emission). For the masked offline-fallback subsystem, the same local telemetry store also persists structured fallback-basal review events published from runtime state so HomeRecent Dose Stepscan show fallback rate, source (instantvsnominal), safety target, duration, reconciliation status, pod-continuity result, restore/remask failure detail, modeled fallback delivery, and pump-reported delivered insulin since the last proven same-pod connected fallback baseline separately from ordinary step rows without adding blocking export work to the main actor. That local fallback event store now also acts as the app-side cloud emitter seam for a dedicated authenticatedloop.fallback.eventfamily: when a fallback event is newly created or materially updated,LoopTelemetryStoreemits a structured payload carrying stablefallback_event_id, lifecycle kind, occurrence timestamps (issued_at, optionalreconciled_at), selected/reconciled fallback rates, modeled delivery, pump-reported delivered insulin,pod_continuity, and reconciliation summary detail. Arm and schedule-refresh fallback events additionally attach the exact programmed schedule entries plus the safety q5 profile metadata used for that programming operation (profile_source_track,profile_kind, observed/imputed slot counts, the per-six-hour-bucket observed-slot countsprofile_observed_slot_counts_by_bucketsourced fromQ5NominalBasalProfileSchedule.observedSlotCountsByBucket, timezone fields, andprofile_rates_288); the steady-cadenceschedule_checked_unchangedcheck attaches that same schedule + coverage payload minus only the bulkprofile_rates_288array (sponsor request 2026-07-20: a stable profile must not let the programmed fallback rates vanish from recent telemetry), and routine mask renewals attach no schedule/profile payload to avoid high-volume telemetry churn.Recent Dose Stepsfallback schedule rows (armed / schedule updated / schedule checked - unchanged) render a plain outcome label, the four programmed segment rates, profile coverage, and per-segment provenance; a segment with fewer than half of its 72 slots observed readsimputed; viaHomeRecentDoseStepsDisplaySupportpure functions (fallbackScheduleOutcomeText,fallbackScheduleProvenanceText). Because a single logical fallback event can be updated later with reconciliation detail, the cloud contract treatsfallback_event_idas the stable backend projection key while each emitted envelope keeps its own unique transportevent_id. Executed step rows now retain both the primary algorithm telemetry snapshot and the secondary/safety algorithm telemetry snapshot plus each track's recommendation, soRecent Dose Stepscan review both tracks' step count, suggested dose, nominal basal, and instant basal alongside the dose row. Recent Dose Steps rows use honest dose-settlement labeling via a testable status policy:Deliveredis claimed only with positive pump-anchored settlement (idle refreshed status after an applied command, or replay resolution evidence), a bare command with no pod feedback readsRequested, active delivery readsDelivering, assumed clinical-policy evidence readsAssumed, fallback backfills readReplayed, and the requested-vs-delivered pair is shown only when a settled delivery genuinely differs from the ask (partials). Rows render as a compact summary (step, status chip, Meal/Replay/Discrepancy tags, dose, time) with the engineering detail - CGM tuple, algorithm input/output snapshots, pump evidence chain, primary/secondary track summaries, fallback schedule/profile/trace - behind per-row disclosure. The existing toolbarShareLinkexposes one protected snapshot ZIP containing the continuously maintained full-session step-telemetry CSV plus only the matching/current legacy Algo2015 session artifacts; it requires an active clinical unlock in release/study builds and is always available in DEBUG builds for engineering review. Algorithm output snapshots, CSV export, and loop-step cloud payloads also retain Algo2015's read-only delivered-insulin echo (bolusInsulinDelivered,basalInsulinDelivered,mealInsulinDelivered, anddeliveryTime) and mark a cloud divergence flag when a matching pump-input delivery differs from the algorithm echo by more than pump mechanical resolution. When confirmed/corrected reconnect recovery occurs,LoopRuntimeCoordinatorallocates the credible same-pod pump-reported fallback delivery delta into no-command missed-step primary/secondary algorithm replay rows withCGM=-1and schedule-weighted per-step pump-delivery input, then records the resumed live step with actual refreshed pump status and no duplicate recovered-delivery input. Reconnect diagnostics now also emit app-log evidence for every masked-fallback recovery attempt, including the persisted fallback schedule, the cached programmed schedule from local OmniBLE manager state, the original pre-fallback schedule, cached-schedule match state, cached-schedule source labeling, baseline/observed pod identity, pod-continuity result, modeled-vs-pump-reported delivered insulin totals, and no-replay reason when replay cannot be safely allocated, so backend review can determine whether schedule divergence reflects stale cached reconnect state, an incorrect schedule-programming command, zero/unavailable replay weights, or replacement/unknown pod continuity. The masked-fallback event lifecycle now includes explicitarmed,maintenance_deferred,mask_renewed,schedule_checked_unchanged,schedule_refreshed,mask_expired_offline,disarmed,remask_failed, andrestore_failedtransitions. Outbox flushing is loss-avoidant: durable enqueue completes before independent network work; concurrent flush requests coalesce with full-flush escalation, while scheduled retry work remains separate so a newer immediate drain cannot cancel an older row's retry. Client cloud-log threshold resolution uses precedenceserver-issued remote override (active, TTL-bound) -> default error threshold, persisted throughCloudLogUploadPolicy; the server config is the sole study logging lever (the build-baked profile and the on-phone integration-session layer were removed 2026-07-16 pre-ship, and storage left under the retired session keys is never read). No in-app logging control is exposed in any build; Settings shows read-only effective-state status text (CloudLogStatusSupportmirrors the upload precedence exactly, rendered byHomeSettingsStudyLoggingSectionViewon a one-minute display refresh). The remote override refreshes at launch, on each foreground, and on a nominal 30-minute periodic interval while running (the sharedCloudRemoteConfigSupport.startPeriodicRefreshloop, SDD-APP-008); fetch failures leave the stored override untouched. A refresh that changes the stored override firesconfigChangeObserver, which the app wires to threshold-exemptremote_logging_config_applied/_clearedcloud markers (sourcebionicloop.remote_logging_configon the always-upload bypass list, so a cleared marker survives the very threshold drop it records). The G7 BLE trace (AppCGMManagerDelegate.emitBLETrace, subsystemBionicLoop.CGM/BLE.Core) follows the same lever: with no local env/defaults override set, trace emission is enabled exactly when the effective threshold isdebug, so the server-issued debug level unlocks the full BLE narrative on study phones (an explicit local off still wins). - Recent Dose Steps under
SDD-LOG-001:HomeRecentDoseStepsDisplaySupportderives aFingersticktag and exact displayed value only from a positive persistedAlgorithmInputSnapshot.bgValueMgdl. When the same input also contains valid CGM, the display retains both values; it does not infer fingerstick use from wake cause or later UI state. - Local-file controls under
SDD-LOG-001: the CSV is written under Application Support with complete file protection and backup exclusion; the telemetry outbox uses a complete-until-first-unlock protected and backup-excluded file spool; participant builds omit Files sharing/open-in-place; and enumerated C++-created Algo2015 diagnostics receive complete-until-first-unlock protection plus backup exclusion.CloudTelemetryReporterclassifies HTTP 4xx responses other than 429 as permanent, andCloudTelemetryOutboxpersists the failed entry with its sequence number, event type, failure timestamp, HTTP status, and error detail. No generic participant alert is created; BionicScout detects the missing sequence, server logs retain the rejection, and a 409 subject-identity conflict independently raises only the specific actionable Subject ID Conflict alert. HTTP 429 remains pending for retry.AppAlertCenterperforms a one-time launch cleanup for an orphaned retired telemetry-rejection notification; persisted-alert loading always filters the retired key and clears its scheduled notification so earlier-build state cannot survive upgrade. - Incident-scale recovery under
SDD-LOG-001:SQLiteCloudTelemetryOutboxLedgeris the normal authoritative v3 store, configured with WAL, full synchronous commits, secure deletion, complete-until-first-unlock protection, and backup exclusion. It transactionally imports the prior file spool and monotonic counters, purges the source only after commit, and repeats idempotent import when a later transient SQLite failure caused the app to write a fallback spool. Retained clinical/runtime rows have no count cap; chatter rotates at 2,000.CloudTelemetryOutbox.nextDeliverablechooses retained evidence before chatter for an ordinary drain and preserves sequence order within each class.CloudTelemetryReporter.emitreturns after the ledger commit, schedules independent coalesced drain work, and retains a separate earliest-retry timer. The optional batch path concatenates unchanged persisted envelope bytes into at most 50 events/512 KiB, applies per-event results, and returns inflight rows to pending before disabling batch on HTTP 404/405/501; the existing single route remains the compatibility path. Chatter cap evictions accumulate in durable metadata and produce one aggregatetelemetry.event.droppedrecord only after an outbox delivery proves transport progress. New Participant Reset closes and physically recreates the outbox database, removes the database/WAL/shared-memory artifacts, and restores only install-scoped monotonic counters before reset completion; an erasure failure aborts the wider participant reset. The separate current-session step archive uses secure deletion and checkpoint/VACUUM cleanup when an explicit algorithm-session reset clears it.UserNotificationAppAlertSchedulerpersists active dedupe keys and emits clear telemetry once per scheduled-to-cleared transition across relaunch. Settings reads an atomic retained/chatter/permanent-failure summary and renders passive upload health; no participant alert or dosing dependency is introduced. - Full-session export under
SDD-LOG-001: archive reads, record decoding, and CSV construction run on a utility queue so archive growth cannot progressively block the main actor. - Recovery export under
SDD-LOG-001:RecentDoseStepsViewprepares one archive off the main actor and supplies its URL to the pre-existing systemShareLink; no Settings export row, picker, confirmation alert, custom activity controller, or nested presentation remains.LegacyAlgorithmArtifactCollectorrequires the complete retainedBionicLoop_StepTelemetry.csv, enumerates only the documentedBP_<epoch>.txt,BP_LOG_<epoch>.txt, andBP_ReadMatrix.mpatterns, and groups timestamped files by epoch while associating the fixed matrix only after parsing its referencedBP_<epoch>.txt. The latest algorithm inspection exposes the active C++ real-T0 epoch. An available epoch selects only an exact group; a missing exact group yields a CSV-only archive. If inspection state is unavailable after relaunch, the newest valid grouped epoch is used. Every included file is copied only to its size observed at copy start into a uniquely named complete-protected, backup-excluded temporary snapshot, thenLegacyAlgorithmStoredZIPWriterwrites stored entries so bytes are not decoded or transformed. The share action remains DEBUG-visible and otherwise clinical-unlock-gated. The operation directory is removed when Recent Dose Steps closes. The algorithm writer, stream ownership, rotation, runtime execution, dosing, and telemetry persistence paths are unchanged. - Confirmed/corrected reconnect replay telemetry is limited to fallback-active missed slots. Pre-activation disconnected gaps remain visible by absence rather than replay rows;
0 Ureplay rows are emitted only for fallback-active slots with no pump allocation. -
SDD-SIM-001: Deterministic simulation harness (medium-fidelity) uses protocol-conformant mock CGM/pump services plus a virtual clock/scenario runner to exercise runtime logic without BLE transport dependency. -
SDD-ALERT-001: Alert normalization/presentation layer is implemented as an app-level normalized model (AppAlert*types +AppAlertCenter) with deterministic precedence (severity, then condition-specific rank, then recency), dedupe keys, and debounced signal-loss handling. Active pump signal loss ranks above a same-severity algorithm check-BG prompt while every safety-critical alert remains dominant. Current live UI presentation includes a Home severity-prioritized alert stack (top alert always visible, compressed peek plus an expansion affordance for the rest, root-cause suppression perSDD-POL-008, and a tappable related-alert count line that opens Alert Center whenever suppression hides any active alert -AppAlertPresentationPolicy.homeHiddenAlertCount), plus a Home bell entry to Alert Center (active + recently cleared), with secondary access from Settings. Algo2015checkBGoutput is synchronized after each successful algorithm output publication into a deduped actionableALERT-ALGORITHM-CHECK-BG-REQUESTEDprompt with foreground haptic feedback and Home BG-button emphasis. Its body states, "A fingerstick BG check or sensor read is needed for automated dosing to resume." The alert has no inline primary action; the separate Home BG-entry control remains emphasized and available.HomeManualBGRequestEmphasisPolicyapplies the same gold breathing emphasis to direct check-BG, outage due-soon, and outage overdue requests while excluding generic sensor, backup-basal, and pump alerts; Reduce Motion replaces breathing with a static emphasized ring.HomeManualBGHighlightVisualPolicykeeps the card shadow static and confines the repeating animation transaction to a bounded stroke halo around the BG control rather than the parent chart/actions hierarchy. This presentation-only policy reads existing active alerts and does not affect alert issuance, ordering, or runtime gates. The check-BG prompt clears on manual BG entry or a latercheckBG == 0, suppresses repeated alerts while already active, and is filtered from restored active alerts at relaunch so stale requests do not survive without fresh algorithm output. Algo2015 primary or safetyopenLoopMode == LOOP_MODE_FORCED_OPENoutput is synchronized into a dedupedALERT-ALGORITHM-FORCED-OPEN-LOOPprompt that presents informational-first (auto-clearing "Dosing Paused" note) and escalates to safety-critical advisory wording after3consecutive blocked steps, instructing a fingerstick BG to resume automated dosing plus sensor-check/study-team guidance (never a reset demand); it remains active across skipped/no-telemetry publications and clears after a later algorithm output reports forced-open inactive. The alert source inventory and mapping baseline is documented in Alert Inventory and Mapping. Pre-scheduled OS notifications (stepping-interrupted, outage due-soon/overdue) depend on user-granted notification permission: authorization is primed once at app startup; scheduling always hands the request to iOS, which silently drops delivery when permission is denied or later revoked. Since 2026-07-16 the scheduler stampsauthorization_statusonto everyalert.notification.scheduledtelemetry event and logs a cloud warning when scheduling occurs unauthorized - observability, not user surfacing; the in-app permission-state indicator remains the identified in-app permission-status gap (RA-018 control gap), while the in-app alert stack and Home countdown remain permission-independent. Presentation clarification (v1.53; supersedes the stroke-halo details above):HomeManualBGHighlightVisualPolicykeeps the ordinary card shadow static and applies a centered caution-amber breathing shadow bloom directly to the BG control using the meal-selector opacity/radius envelope. Reduce Motion disables that glow; the static amber border and wash remain the cue. This remains presentation-only and does not alter alert issuance, ordering, runtime, or dosing behavior. -
SDD-QA-001: Algo2015 verification infrastructure uses deterministic replay vectors plus instrumented coverage collection, mandatory static-analysis lane execution on formal runs, and conditional MISRA policy linkage (report+deviations or explicit N/A rationale) to generate reproducibleTV-ALG-*evidence artifacts for IDE submission, as specified in Algo2015 Verification Plan.
3. Runtime Sequence (Nominal)¶
- New CGM timestamp arrives.
LoopRuntimeEnginetriggers coordinatordoWork.- Coordinator computes expected step from anchor + interval.
- Coordinator builds algorithm input:
- CGM (or unavailable
-1by policy). - Pump fields (or unavailable values if pump not available).
- Algorithm returns recommendation and updated internal state blob (primary track; the isolated safety-track instance computes fallback-basal recommendations through the same interface against its own engine and state store).
- If pump status is available and recommendation passes gates, command is attempted.
- Telemetry record is persisted with input/output/command fields.
- Pump status refresh reconciles delivered/requested units.
4. Key Design Policies¶
-
SDD-POL-001(Cadence): anchored 5-minute slot model. -
SDD-POL-002(CGM): step0strict gate, step>0degraded allowed. -
SDD-POL-003(Pump): unavailable pump permits algorithm step but blocks command application. -
SDD-POL-004(Meal announce): explicit pump-ready gating (active pod present,known, andnot delivering), established first-step cadence anchor requirement, borrow-window gating for pre-due execution, and current-due-step execution when request arrives after slot is due/missed.OutageBGRunContextstores the optional, decode-compatiblelastQualifyingGlucoseStepwhenever an executed step consumes positive CGM or fingerstick input.MealAnnouncementOfflinePolicypins the real-CPP dropout boundary: at most 12 consecutive blind steps after that anchor remain eligible; a prospective 13th blind step is treated as the forced-open transition. Home availability computes the same prospective step as meal execution using the shared execution lead and blocks that transition before opening/submitting; a current fresh in-range CGM or valid persisted manual BG targeted to the exact prospective step permits the step. After exact meal-step resolution,LoopRuntimeCoordinatorrepeats the policy beforepersistAcceptedMealExecutionState; rejection returnsmeal_announcement_would_enter_forced_open_loop, performs no algorithm call or pump command, and maps to participant-facingbackupBasalRunningcopy stating that the meal was not announced and no meal insulin was delivered. Established forced-open meal availability remains blocked unless a valid persisted manual BG is targeted to the exact prospective meal step; invalid, stale, or future-target BG state cannot bypass the block, and all pump/reconciliation gates remain authoritative. Unavailable-reason precedence reportsnoPumpbeforesignalLosswhen there is no active pod. After loop-off and masked-fallback reconciliation gates, an active pod with live.deliveringstatus maps topumpDeliveringbefore pending meal/issued-dose attribution checks, preventing stale reconnect guidance while the connected pump is merely busy; pending attribution still blocks with reconciliation guidance once status is idle. A persisted masked-fallback reconciliation-required state blocks meal availability with reconnect/recovery-required guidance until that recovery resolves. Home/meal presentation logic revalidates meal availability on loop-step publication, qualifying-glucose publication, live pump-status change, foreground refresh, and immediately before submit. Revalidation of an open composer usesHomeRuntimeActionCoordinator.mealComposerRevalidationDecision: a slot conflict (observed step stale under the open sheet) with an available fresh check re-arms in place - observed step updated, selections preserved, a transient 'Timing updated' notice shown, telemetry resultrecovered_in_place; genuinely unavailable conditions render the current blocked messaging inline inside the composer (caution-tinted card, optional Open Settings action, selections preserved) and self-heal when a later revalidation reports availability; pump-delivering with an active cancellation context still routes to the cancel-delivery presentation. The composer captures the pending-BG carve-out context at open and on every in-place re-arm (HomeRuntimeActionCoordinator.mealComposerCarveOutBGTargetStepintoHomePresentationState.mealAnnouncementCarveOutBGTargetStep); the revalidation decision takes acarveOutBGConsumptionInFlightflag. The helper requires a captured target, a cleared pending BG value, no matching-or-laterOutageBGRunContext.lastQualifyingGlucoseStep, and no executed step beyond the captured target. This uses the final qualifying-glucose publication as the completion marker because pre-command fallback maintenance may persistlastExecutedStep == targetbefore app-level execution publication updates the outage context. OnlybackupBasalRunningroutes toshowTransientWaitingwith the passive applying notice (MealAnnouncementAvailabilityPresentation.carveOutBGApplyingNotice): the composer stays armed and the qualifying-glucose publication re-arms it through the standard slot-conflict / inline-recovered routes, because an accepted fingerstick clears forced-open on its own step and restarts the full 60-minute dropout window (Algo2015ManualBGDropoutClockCharacterizationTests). A pump-status change revalidates the same composer so connected.deliveringguidance supersedes any intermediate waiting or backup-basal copy immediately. The same predicate (mealComposerSubmitShouldHoldForCarveOutBGConsumption) holds a backup-basal-blocked submit on the waiting notice at both the pre-check and the engine-blocked outcome instead of tearing down to the unavailable sheet. Once the qualifying marker publishes, or a later executed step proves the target passed, persisting forced-open availability keeps the generic backup-basal copy; all other unavailable reasons and every recovery route are unaffected by the flag. This is the accepted current software baseline for late-submit meal behavior. Suspension hardening (v1.65): both Home availability andMealExecutionPolicyrequire the active Pod's delivery state to be.idle;.suspendedmaps topumpSuspendedwith resume-before-meal guidance. The coordinator rejects before accepted-meal persistence and before either algorithm runs, so a suspended meal cannot advance cadence, produce a 2.9 U-style recommendation, issue a command, or seed chart/feedback state.LoopRuntimeEngineevaluates the freshest service status ahead of observer fallback, so a pump-confirmed.idlestatus after Resume makes meal entry available immediately without waiting for another loop step. Home separately rendersInsulin delivery is paused.from live pump status, and the pinned action surface has no decorative top hairline. -
SDD-POL-005(Reset): full session reset clears persisted runtime + algorithm + timeline session data. -
SDD-POL-006(Home status): state precedence is deterministic and runtime-derived; age-based states use cadence phase (nextDueAtfrom anchor + step index) so borrowed meal steps do not falsely age status before the next due boundary. Current thresholds:ActivethroughnextDueAt + 2m,AgingthroughnextDueAt + 15m, thenStale. -
SDD-POL-007(Modal setup cancellation): startup/setup modals for CGM and Pod provide direct dismiss behavior via explicitCancel, including persisted-manager/no-active-pod Pod setup. -
SDD-POL-009(Meal composer lifecycle safety): if app scene transitions to background while meal composer is presented, the composer is auto-cancelled/dismissed. -
SDD-POL-010(BG check): manual BG submit triggersbgCheckwith no borrowing, uses a single pending BG candidate (replace-on-new submit), applies candidate to the next eligible step, and expires candidate if not consumed on that immediate next step. -
SDD-POL-011(BG safety gate): manual BG submit path checks loop-armed state plus persisted masked-fallback recovery state inLoopRuntimeEngineand shall not dispatchbgCheckwhile disarmed or while reconnect reconciliation is required. -
SDD-POL-012(BG step-0 guard): until step-0 BG rescue is approved, manual BG submit is rejected iffirstSuccessfulStepAtis not established. -
SDD-POL-013(Clinical settings policy): clinician configuration access is gated byClinicalUnlockVerifierandKeychainClinicalUnlockStateStore. The app verifies subject-scoped single-use unlock codes offline after verifier material is provisioned, stores verifier material/local state per subject in the Keychain, burns the matched counter before exposing clinician controls, and keeps the clinician controls unlocked only until the provisioned expiration timestamp or explicit manual lock. The app-side material provisioning path validates the verifier material before storage, rejects subject/material mismatches, preserves the last accepted counter when material is refreshed, clears active unlock expiration on refresh, and resets local failed-attempt/lockout state so refreshed material does not silently preserve an open clinician session. The verifier normalizes pasted/grouped ASCII numeric input, computes the HMAC code using the current provisioned secret version, searches only the configured future counter lookahead, and rejects malformed, non-ASCII digit, reused/lower-counter, wrong-subject, beyond-lookahead, and unsupported-version codes. Manual lock writes the cleared unlock expiration back to secure storage; if storage persistence fails,HomeSettingsViewkeeps clinician controls visibly unlocked and shows the storage-failure message instead of presenting a false locked state. Production master secrets are not embedded in app source; DEBUG UI-test provisioning uses the public contract test secret only underUI_TEST_MODEand exercises the same app-side provisioning path. Operational provisioning is human-typed:ClinicalUnlockProvisioningCode(BionicLoopCore) decodes the BionicScout-issued one-time provisioning code (Crockford base32 of a 30-byte payload carrying format version, secret version, code digits, offline lookahead, unlock duration, a 4-byte subject binding check, the 16-byte per-subject derived device secret, and a 2-byte checksum; input normalization mapsI/Lto1andOto0and strips separators), andClinicalUnlockProvisioningInstallerinstalls the decoded material throughClinicalUnlockSessionController.provision.HomeClinicalSettingsFormViewpresents provisioning as an operator-facing "Clinical Unlock Setup" section only while clinician controls are locked: when material is installed for the current subject it collapses to a ready confirmation (subject + code-set version, with an explicit "Redo Device Setup" action); otherwise it shows a guided form with "Set Up Automatically" (authenticated fetch) as the primary action and the typed setup code behind a manual-entry disclosure, and the locked unlock-code field shows a set-up-required hint. On successful installationHomeSettingsViewadopts the provisioned subject ID only when the app has no subject configured yet (bootstrap) and never silently changes a non-empty configured subject.ClinicalUnlockAutoProvisionerperforms the fetch throughAuthenticatedAPIClient(GET /v1/subjects/{subject_id}/clinical-unlock-material, subject-device token with automatic refresh), maps auth/claim failures to operator-readable messages (notSignedIn,subjectNotClaimed), rejects responses whosesubject_iddiffers from the requested subject, and installs the fetched provisioning code through the identicalClinicalUnlockProvisioningInstallerpath so typed and fetched material share one validation surface. The device stores only the per-subject derived secret, so compromise of one device's Keychain material exposes only that subject's unlock codes. Clinical control values are validated to allowed ranges (target 90...130 step 10,meal upfront 75/90,TMAX 40...70 step 5) and mapped into algorithm/runtime configuration without changing existing start/reset semantics.HomeSettingsViewpersists a target-access profile (Pregnancy,Standard) alongside the clinical config; participant-facing settings derive their available target buttons from that profile (Pregnancy -> 90/100/110,Standard -> 110/120/130). The clinician target selector now uses that same profile subset and normalizes any inherited out-of-profile draft target to the nearest allowed value when the profile changes. When a previously conflicting subject identifier is corrected and the save/claim flow succeeds,HomeSettingsViewexplicitly retracts the app-levelALERT-SUBJECT-ID-CONFLICTalert so operator-facing alert state matches the resolved persisted configuration. Separately, Home now performs a throttled silent re-claim check for the currently persisted subject identifier when the conflict alert is still active and the operator launches, foregrounds, or reopens settings; if the backend claim now succeeds, Home retracts the stale conflict alert without requiring a settings edit/resave round-trip. This investigational single-device unlock control remains distinct from broader production role-based authorization. -
SDD-POL-014(CGM display masking for stale/unreliable data):G7ViewModelapplies a display-staleness cutoff of11minutes and checkshasReliableGlucoseon the latest G7 reading. If stale or unreliable, display accessors emit masked glucose text (-- mg/dL/--), suppress trend-arrow rendering, and do not append unreliable points into chart-history persistence. -
SDD-POL-015(Auth/runtime decoupling): authentication/session state shall not stop or reset local loop runtime state. Auth gates cloud/protected operations and onboarding surfaces, while therapy runtime continuity is preserved unless user explicitly performs runtime reset/start-stop actions. -
SDD-POL-016(Auth re-entry with continuity fallback): app launch attempts silent token-session restore/refresh when persisted auth state is authenticated; on restore success, authenticated UX remains uninterrupted. If auth state changes to unauthenticated while restore is in flight (for example explicit user sign-out), launch reconciliation preserves the current unauthenticated state and does not auto-reauthenticate. When restore fails (or user is unauthenticated) and local runtime indicates active algorithm state, login UX exposes explicit Home bypass. In bypass mode,HomeTopOverlayBarkeeps a persistentLog Incontrol visible independent of active-alert precedence; the Home alert, Alert Center active row, and signed-out Account & Session screen expose the same recovery action.ALERT-AUTH-LOGIN-REQUIREDnotification taps route to the login destination instead of generic Home. Every route calls the app-level login presentation handler, which closes Home modals and displays authentication without stopping or resetting the local algorithm session. -
SDD-POL-017(Clinical/settings telemetry): Clinical Settings save-review flow emitsui.criticaltelemetry with stable event/action mapping:state_viewedon review presentation,submitonSave,cancelon review dismissal, andblockedon invalid/locked/no-change save attempts. Save telemetry includes changed-field list and old/new clinical values (subject,weight_lbs,target_mgdl,target_range_profile,meal_upfront_percent,tmax_minutes). Participant target-change approval capture emits its own stableui.criticallifecycle (state_viewed,submit,cancel,blocked) with requested target, current target, target-access profile, approving staff name, and approval timestamp. -
SDD-POL-018(Clock-sync safety telemetry): App lifecycle telemetry (app.lifecycle.launched,app.lifecycle.foregrounded) includes timezone + UTC-check context fields (device_timezone_id,device_utc_offset_seconds,clock_check_result, optional skew/rtt/timestamp). UTC checks run on launch, timezone/significant-time-change notifications, and foreground only when last successful check is older than 24 hours. If absolute skew exceeds 600 seconds, app raises actionableALERT-APP-CLOCK-SKEWwarning no more than once per 24 hours; unavailable checks do not show user warnings. -
SDD-POL-019(Home chart and primary-action layout): CGM value rendering maps<=39 mg/dLtoLOWand>=401 mg/dLtoHIGHacross Home/G7 primary value surfaces and scrub value presentation; Home inline CGM chart uses bounded stepped maxima (300,350,400 mg/dL) based on observed peak values so out-of-range excursions remain visible without unbounded axis drift.InlineCGMChartViewrenders each glucose sample as one value-colored dot at its recorded timestamp and does not render the former connector stroke or connected area fill, avoiding visual interpolation between discrete sensor samples. Scrub readouts (CGM/Dose value pills above the combined Home chart) appear only while a scrub gesture is active, with animated show/hide transitions, and every chart scrub state is force-cleared on view teardown and on scene backgrounding - a cancelled drag never fires the gesture's end handler, so lifecycle clearing guarantees scrub overlays cannot stay stuck. The Home loop-status ring is a passive indicator rendered without card chrome (it is not a button).HomeViewplaces the existingHomePrimaryActionsRowin a bottomsafeAreaInset, with an opaque background and top divider; SwiftUI reserves that inset from the scrollable status/alert/chart region, so Manual BG and Meal Announcement stay visible without covering clinical content. The fixed row reuses the same BG-request emphasis and action handlers, so placement does not change availability, meal preflight, BG validation, or dosing behavior. -
SDD-POL-020(algorithm stepping interruption monitoring):LoopRuntimeEnginemonitors for stalled loop execution while armed using persisted runtime/session state rather than CGM-receipt time alone. The interruption deadline is computed fromlastSuccessfulRunAt + 15 minutes; if no successful step exists yet, the baseline is session start / first-step wait state.AppAlertCenterclears any prior pending interruption notification and schedules a replacement local-notification deadline at the current interruption deadline; if the deadline passes while still current, it raises actionable in-app alert state. Monitoring is recomputed on app foreground and refreshed after each successful step. The alert clears when successful stepping resumes or when the loop is disarmed/reset. -
SDD-POL-021(reconnect fallback execution): current cadence remains anchored tofirstSuccessfulStepAtwith the existing early execution lead (27 seconds). Pump reconnect is treated as a secondary wake source rather than a cadence source: app runtime listens for pump-status recovery (not raw BLE connect), only after an anchored session exists, only for step>0, only when the accepted CGM receipt is older than the approved freshness limit (>5 minutes), and only when the current due slot has not already executed. The reconnect path may execute only the current due step, shall not replay missed slots, shall not re-anchor the schedule, and shall remain suppressed once fresh CGM receipts resume so CGM retains priority as the primary loop trigger. -
SDD-POL-022(algorithm stepping interrupted alert policy): the normalized runtime interruption alert isALERT-ALGORITHM-STEPPING-INTERRUPTED, keyed to lack of successful algorithm execution rather than lack of CGM receipt alone. Trigger basis isloop armedplusno successful step for >15 minutes, measured from the most recent successful executed step or, if none exists yet, from session arm time / first-step wait state. The alert issues even when the immediate blocker is not CGM-specific.LoopRuntimeEngineStepInterruptionMonitoringSupportclassifies the latest unresolveddoWorkskip plus authoritative pump-native conditions into blocker-specific detail; suspension and fallback reconciliation have explicit states, broad CGM lifecycle alerts do not independently establish step causality, and current suspension outranks fallback recovery while fallback recovery outranks an older persisted CGM/pump-status diagnosis. Following apumpStatusUnavailableskip, the existing pump-status observer refresh path reevaluates interruption copy without callingdoWork: only an active Pod status withdeliveryState == idleandlastUpdatedlater than the failed attempt enters the persistedpumpRecoveredAwaitingNextStepstate and changes the same deduped alert to communication-restored/waiting-for-glucose guidance. Status-driven refresh applies the alert update only when the persisted blocker changes, so repeated newer idle polls do not churn alert timestamps, lifecycle telemetry, or notification attempts. Stale or non-idle status remains unavailable; a later unknown status returns the persisted diagnosis to unavailable. The recovered-waiting state survives relaunch until a newer result or contradictory status supersedes it. Any successful live step clears interruption state.AppAlertCenterupdates changing blocker copy under one dedupe key; Home hides the redundant interruption banner while the stronger suspend-ended alert is active, while Alert Center and telemetry retain the interruption record. -
SDD-POL-023(meal-request durability baseline):LoopRuntimeStatepersists pending meal-request state across relaunch using submit time, the concrete execution step accepted byLoopRuntimeCoordinator, a pending-state discriminator (awaitingExecution,uncertainCommandOutcome), and the correlated meal flow identifier. On startup/foreground availability checks, runtime reconciles that state against persisted step history (lastExecutedStep) and, for uncertain outcomes, against pump-delivery evidence (lastDelivery.requestTimeStep) after pump attachment. While the pending request remains unresolved,mealAnnouncementAvailability()returnsrequestInProgressoruncertainPreviousMealand duplicate meal entry is blocked until reconciliation or session reset/disarm. -
SDD-POL-024(meal outcome handling): Home/UI and runtime telemetry split meal flow into pre-submit interaction plus outcome-drivensubmitted,accepted,success,blocked,uncertain, andresolvedpaths.HomeViewkeeps the composer in a submitting state whileLoopRuntimeEngine.announceMeal()awaits coordinator completion, dismisses only on executed success, presents explicit blocked messaging when runtime returns a blocked/rejected outcome, and presents explicit uncertain-delivery guidance when pump command outcome is unresolved. Home captures thelastExecutedStepobserved when the meal composer opens and passes that snapshot with submit;LoopRuntimeCoordinatorcompares it against current cadence state and returnsmealSlotConflictif another step has already advanced, so runtime maps the result to explicit slot-conflict retry guidance instead of silently reassigning the meal into a new borrowed step. Runtime now emits correlatedacceptedtelemetry after coordinator acceptance andresolvedtelemetry when the request clears immediately, reconciles after uncertainty, or is cleared by session reset, using persisted replay state for the meal flow identifier + target step until those lifecycle events are emitted so cloud review can close the lifecycle across relaunch/terminate windows. Loop-command telemetry carries explicitcommand_outcomesemantics so uncertain delivery is not flattened into generic blocked state. -
SDD-POL-025(participant target-change approval flow): The general settings target control is a constrained participant-facing action, not a direct free-form clinical config editor.HomeRegularTargetChangeApprovalPolicyfirst validates that the requested target belongs to the clinician-selected profile subset and that the request would change the applied target. Valid requests open an approval-capture sheet that blocks dismissal until the operator either cancels or records both approving staff name and approximate approval time. Only after successful validation does the app persist the updated target into the shared clinical config store and update the live runtime-facing target binding. Invalid approval-capture attempts emit blocked telemetry and keep the prior target unchanged. -
SDD-POL-026(CGM urgent-low review alert):AppCGMManagerDelegate.syncG7Alerts(for:)derivesALERT-CGM-URGENT-LOWfrom current live G7 data whenlatestReading.hasReliableGlucose == true, the reading timestamp is within the trusted freshness window, andglucose < 55 mg/dL. The alert is app-derived for clinician review and cloud telemetry, not Dexcom-app alarm acknowledgement.AppAlertCenterkeeps the alert active after acknowledge by stampingacknowledgedAtrather than clearing it immediately, so Home / Alert Center can display reviewed state while the urgent-low condition remains active. The active urgent-low alert auto-clears only when a later trustworthy reading is>=55 mg/dL; stale, unreliable, or missing readings leave the active episode in place. Repeated live-state upserts preserve existingacknowledgedAtfor the active episode, and a later new<55 mg/dLepisode reissues as unacknowledged after recovery clears the prior episode.CGMAlertPersistenceStorepersists acknowledged dedupe state so reviewed active urgent-low episodes survive app reset / delegate reattach until glucose recovery clears the episode. As with all CGM-derived alerts, this path never schedules OS local notifications. -
SDD-POL-027(meal cancel-delivery path): When the operator opens meal announce while pump bolus delivery is already in progress,HomeActionCoordinatorroutes the flow into a dedicated cancel-delivery presentation on Home instead of exposing a second meal submit path.HomeViewreveals a destructive slider-backedCancel Deliveryaction beneath theManual BG/Let's Eatcontrols, and that action can now remain visible automatically while an active meal-announcement bolus is still in progress, even without a second tap onLet's Eat, by deriving the active cancelable state from current pump delivery state plus the matching meal step telemetry. WhenPumpStatus.lastDeliveryis unavailable during reconnect/status-thin windows, Home falls back to the latest still-delivering meal step record so the cancel affordance is not hidden solely because detailed delivery accounting has not yet arrived. The cancel action callsPumpStatusObserver.cancelBolusDelivery(), which delegates toPumpService.cancelBolus()and converts the canceled dose into actual requested/delivered units. On success, Home shows a caution-colored partial-delivery summary in the normal alert-summary region above the chart so the operator can see how much insulin was already delivered before cancellation before later reopening meal announce. That summary now carries cancel time plus meal type/size context derived from the matching meal step telemetry, so the operator can distinguish which meal was interrupted without reopening the composer. The summary is retained until both at least one later algorithm step has executed and at least 5 minutes have elapsed, preventing the warning from disappearing immediately after the next step. The Home insulin chart derives interrupted-delivery styling directly from existing step telemetry (requestedUnitsvsdeliveredUnits), but active in-progress meal delivery remains rendered in the normal meal-dose color while the pump still reports.delivering;LoopTelemetryStorenow marks a successfully issued bolus as delivering immediately until the first pump refresh arrives, so a just-started meal bolus does not flash yellow while waiting for hardware status. Interrupted/partial deliveries keep their data-identity bar color (meal purple / insulin blue) at the delivered height, with the caution treatment rendered as a ghost outline up to the requested height - the bar reads "what was delivered vs what was intended" without erasing what kind of dose it was; the caution ghost appears only once delivery has been stopped or otherwise ended short. Fallback replay backfill rows (fallback-only replay rows with no issued-dose evidence source) are exempt from interrupted-delivery styling: they pair the algorithm's offline ask with the pod-true quantized fallback share and issued no pump command, so a requested-vs-delivered shortfall there is historical reconciliation, not an interruption. Replay rows carrying an issued-dose resolution report a real command outcome and keep the caution treatment for genuinely partial deliveries. Fallback replay backfill rows additionally render as a muted variant of the insulin bar color (reduced-opacity tiers at every scrub state) so historical reconstruction reads differently from live-commanded doses; the muting applies only when an entire display bucket/pixel is backfill - any live dose in the same bucket keeps normal styling. Every executed step renders a minimum-height chart mark even at 0 U delivered (including dead-gap sentinel rows), distinguishing 'the loop ran here with a zero dose' from a genuinely missed step, which has no record and renders nothing. When cancel succeeds,PumpStatusObserverexplicitly reconciles the sharedLoopTelemetryStorestep record with the cancel-returned delivered amount and forces the corresponding local delivery state back to idle, so the chart bar height reflects actual delivered insulin even if the immediate post-cancel status refresh or lagging LoopKit event history still overstates the completed amount. Later pump-status observer refreshes continue reconciling the sharedLoopTelemetryStorerecord for the same step until delivery completes, so an in-progress partial snapshot does not remain yellow on the chart after a later refresh proves full delivery completed. The chart render compactor preserves.deliveringwhen adjacent bars collapse onto one display pixel so compaction cannot strip active-delivery styling. The pump adapter preserves the delivered amount inPumpStatus.lastDeliveryso the next algorithm step consumes actual partial-delivery evidence rather than assuming the full original bolus completed, and when LoopKit event history lags a later pod status refresh it now floors delivered insulin to the pod-reportedrequested - bolusNotDeliveredamount instead of regressing a completed bolus back into partial-delivery state. -
SDD-POL-028(operator-controlled algorithm session lifecycle):LoopRuntimeEnginetreats algorithm start, stop, reset, and replacement session creation as explicit operator actions only. Recovery code paths may preserve or clear blocked fallback state, retry pump schedule restoration, suppress replay, continue the existing cadence slot, and emit unreconciled telemetry, but they shall not silently stop/start/reset the algorithm or create a replacement algorithm session. For masked-fallback recovery, same physical pod continuity is established by persisting the fallback pod identity with the connected delivery baseline and comparing it with the recovery snapshot; different/new pod, unknown identity, or delivery-counter/history discontinuity suppresses replay while preserving the existing session/cadence state if the loop remained armed. If the previous pod is known inactive/retired or past hard service-stop before restore evidence can be collected, the recovery path preserves the existing algorithm session and records assumed modeled fallback delivery instead of creating a new session or holding the user in an unrecoverable blocked state. -
SDD-POL-029(issued-dose attribution replay):LoopRuntimeCoordinatorpersistsPendingIssuedDoseAttributionfor any applied or uncertain automatic bolus command, not only meal announcements. The attribution records request step, first eligible attribution step, requested units, request/completion timing, component split (basal,correction,meal, ormixed), flow ID, and pod identity when available.PumpServiceAdapterrestores that metadata before post-relaunch status reconciliation; persisted matching reconciliation evidence defers or suppresses the adapter's pod-counter reconstruction, except under the SRS-PUMP-010 fresh-completion upgrade rule: a fresh same-pod settled status taken at/after the dose's expected physical completion with thebolusNotDeliveredregister at zero supersedes the deferral and the adapter surfaces the pump-observed completed delivery (a canceled/interrupted partial's nonzero register keeps the deferral), while the engine replaces matching non-assumed evidence recorded below the requested amount with a strictly-higher fresh same-pod post-completion pump observation before that evidence is consumed. A same-pod.deliveringor unknown state keeps the attribution pending and skips the due step under the accepted DASH completion liveness bound. Fresh matching evidence must prove request step, requested-unit tolerance, pod identity, and delivered units in0...requestedbefore confirmed consumption. When historical rows are due, coordinator replays them before the live step withCGM=-1, injects delivered insulin only at the first eligible attribution row, and emits no catch-up pump command; when the live due step is the first eligible attribution step, it consumes the evidence directly without synthetic replay. Definitive command rejection (v1.65): the adapter records request metadata immediately before entering OmniBLE so crash/uncertain outcomes remain recoverable. If OmniBLE returns a definitive blocked result, the coordinator callsDefinitivelyBlockedBolusCommandHandlingwith the unique request step and units.PumpServiceAdapterclears only a matching cached request and any matching cachedlastDelivery; a mismatched/newer request is retained. This prevents a rejected request from being paired with DASHbolusNotDelivered == 0and fabricated as completed delivery. Uncertain outcomes deliberately do not invoke this cleanup. Fresh-completion implementation clarification (v1.53; supersedes the register-only exception above):IssuedDoseReconciliationEvidence.observationContextis decode-compatible optional durable provenance. Cancel returns persist.canceledDelivery; pump progress whose resolved source is capped while active persists.deliveryInProgressCapped; legacy records decode with no context. Adapter and engine completion upgrades require the explicit in-progress-capped context for partial evidence. Canceled and nil-context partials continue to defer reconstruction even when a later DASH refresh reports zero not-delivered. Assumed-full evidence may allow a matching direct observation to surface, but cannot increase insulin attributed to the algorithm. When fallback recovery and a pending issued dose share a same-pod cumulative pump delta,FallbackBasalExposureReconcilerpartitions the known dose only if the total covers it, completion time has passed, identity matches, and the residual credibly matches fallback exposure. The issued-dose share is persisted aspartitioned_pump_delta; the fallback event stores residual actual delivery separately from the raw pump total. If the split is not credible, no partition is guessed and the raw total is not represented as actual fallback delivery. Issued-dose replay precedes fallback replay. Its confirmation tuple echoes the issued ask exactly, dead-gap rows use zero-delivery echo retractions, and the first fallback row echoes the preceding replay ask. If fallback begins on the attribution step itself, the resolved dose and one bounded fallback share merge into that row with the fallback share carried only in delivered units. Once a fresh settled status exists, unresolved, mismatched, non-credible, missing-identity, retired-pod, or replacement-pod cases resolve under the accepted assumed-delivered clinical policy: requested units are consumed exactly once by replay or live input, the assumed source remains explicit in UI and telemetry, and meal-linked assumed doses schedule meal-adaptation exclusion. A replacement pod's unrelatedlastDeliveryis scrubbed before live input, and later automatic commands are not blocked solely because the original pod cannot be queried. Consumed request-step deduplication is keyed by request step rather than units; a later same-step units mismatch becomes discrepancy evidence instead of fresh insulin. Legacy persistedactiveIssuedDoseReconciliationHoldkeys are ignored during decode. The writer-less hold mechanism was removed inc42f2a6; no current clinical disposition depends on it. When Home presents an unresolved meal-delivery progress modal for a matching meal-linked pending attribution and the original pod is known unavailable/service-stopped/different or has not produced matching evidence by expected physical completion plus two minutes,MealDeliveryPodReplacementEscapePolicyexposes aReplace Podaction. The action usesLoopRuntimeEngine.reconciledUserAbandonedMealIssuedDoseEvidenceState(...)to persist assumed-delivered evidence withIssuedDoseReconciliationFailure.reason == user_abandoned_unavailable_pod, clears only the meal-progress UI fields, leavesPendingIssuedDoseAttributionfor coordinator replay/live-step consumption, emits the meal resolved telemetry path as uncertain/reconciled, and then routes to pod setup. If legacy/partial state lacks pod identity, coordinator accepts this assumed-delivered evidence only for the user-confirmed unavailable-pod path and only when request step, requested units, delivered-unit bounds, and non-active pump status match. The policy rejects correction-only or basal-only pending attributions and hides the action once matching reconciliation evidence exists. -
SDD-POL-008(Alert policy): multi-source alert normalization model drives pump and CGM alert mapping plus pump signal-loss debounce (5 minutes), no-active-pod debounce (5 minutes), repeating safety-critical notification attempts every30 minuteswhile the condition remains true, dedupe, deterministic alert precedence, and auto-clear behavior. Home active-alert presentation uses a severity-then-recency stack: the highest-priority alert renders in full with a compressed peek edge and an explicit "N More" expansion revealing the remaining Home-visible alerts in place. A sponsor-approved root-cause suppression matrix (2026-07-09) hides generic alerts from the Home surface while a specific active alert already explains them:ALERT-ALGORITHM-STEPPING-INTERRUPTEDis hidden while forced-open-loop, step-realign, awaiting-first-step, pump signal-loss/no-pod/expired/fault/suspend, or CGM unavailable/failed alerts are active, andALERT-LOOP-COMMAND-BLOCKEDis hidden while forced-open-loop or those pump-outage alerts are active. Suppression is presentation-only (issuance, telemetry, and clearing unchanged), never applies to safety-critical alerts, and Alert Center always shows the complete active list. High-priority non-CGM alerts additionally route to background local notifications throughAppAlertCenterwith per-alert dedupe and severity cooldown (actionable: 5 minutes,safetyCritical: 60 seconds), and resolved alerts clear matching pending/delivered OS notifications. CGM availability/failure alerts are informational in-app status only and never schedule background local notifications; the FDA-cleared Dexcom application remains the source of truth for CGM alarming. Notification-tap routing maps alert category to app context (pump-> Pod modal,cgm-> CGM modal, non-device -> Home), except suspend-in-progress and suspend-ended alerts route directly toSettings > Exercise and Insulin Delivery, where the resume control is located; the suspend-ended in-app alert additionally carries a direct resume action. Its persisted deadline is the initial reminder timestamp plus 15 minutes; while the same condition remains active, expiry changes the alert from actionableResume Insulinto safety-criticalInsulin Still Suspended, emits an alert-update telemetry event, and schedules one fresh safety-critical notification. Countdown removal makes the transition exactly once, and a repeated source issue cannot restart or downgrade an already-escalated condition. Thecgmroute remains defined for in-app navigation/preview support even though production CGM alerts do not schedule OS notifications. Safety-critical alerts expose explicit acknowledge action on the Home alert stack and in Alert Center (ackState == requiresAcknowledge); current production required-ack alerts are pump fault, pump incompatible, app-derivedALERT-CGM-URGENT-LOW, andALERT-FALLBACK-REPLAY-DISPOSED(unconfirmed backup-insulin disposition). OS-notification clear calls are idempotent on every retract attempt (including already-cleared keys) to cover async schedule/retract races; alert lifecycle telemetry still emitsalert.notification.clearedonly when an active alert transitions to removed. App-level active/recently-cleared alert state is persisted and restored across relaunch; pump/cgm delegatePersistedAlertStorehooks are implemented for issued/unretracted/retracted lifecycle lookup. On no-active-pod restore/sync cleanup, only non-critical pod-tied alerts are auto-retracted;ALERT-PUMP-FAULTandALERT-PUMP-INCOMPATIBLEare retained until explicit lifecycle retraction or acknowledge closure. Time-sensitive alert metadata (ALERT-PUMP-EXPIRING,ALERT-PUMP-EXPIRED, and suspend-ended escalation) is refreshed byAppAlertCenteron a minute interval while active. Pod expiration/expired alerting is sourced from both delegate issue/retract callbacks and state-driven synthesis from pumpexpiresAton status refresh/startup to avoid relaunch misses and misclassification. For CGM, failed/expired classification is state-driven (lifecycleState/algorithmState) while delegate fallback keyword mapping prioritizes unavailable-temporary states and does not escalate failed/expired from message-only payload text; the only app-derived CGM required-ack path is the urgent-low review alert defined inSDD-POL-026. Runtime-derivedALERT-ALGORITHM-STEPPING-INTERRUPTEDis step-based rather than CGM-receipt-based, carries blocker detail, routes notification-tap navigation to Home, and remains distinct from pump-native alerts while CGM state remains visible as informational context. Runtime-derivedALERT-ALGORITHM-FORCED-OPEN-LOOPpresents informational-first and escalates to safety-critical advisory wording after3consecutive blocked steps (fingerstick-BG remedy instruction with sensor-check/study-team guidance; no reset demand), routes notification-tap navigation to Home, persists across skipped/no-telemetry publications, and clears when a later algorithm output reports forced-open inactive. The frozen alert behavior is covered by executed automated evidence; no separate formal physical alert-validation claim is retained for this submission. Mapping baseline and source inventory are maintained in Alert Inventory and Mapping.
5. Data Persistence¶
-
SDD-DATA-001: runtime cadence state is persisted inUserDefaultsLoopRuntimeStateStore. -
SDD-OUTAGE-001: fingerstick-supported sustained dosing during CGM outage (clinically approved 2026-07-14). A persistedOutageBGRunContext(inLoopRuntimeState) anchors the fingerstick-due schedule to the last qualifying glucose (OutageBGRunPolicy:120-minute interval,60when the measured value is>200/<80 mg/dL); the engine re-anchors it from each executed step's accepted input, quantifies each release window at mask re-arm by updating the engaged fallback event in place (same fallback_event_id; duration + PumpBasalSchedule.deliveredUnits modeled exposure over the programmed fallback schedule, upgraded to a pump-measured confirmed total when the coordinator accumulated per-step credits, else status resumed_without_reconciliation; RA-020 accounting implemented per SRS-OUTAGE-006 v1.42), gates the outage surfaces on the SRS-OUTAGE-002 v1.37 definition (blind executed step AND algorithm offline modeopenLoopMode == 2/ fingerstick-fed step / mid-outage persistence via the context's last qualifying source - an isolated relaunch/wake blind step with the dropout clock intact shows nothing), and drives three alert tiers throughAppAlertCenter.updateOutageBGDueMonitoring(pre-scheduled OS notifications for due-soon/overdue, mirror of the stepping-interruption pattern) plus a Home countdown line. The backup-basal bridge lives in the pre-command maintenance path (performOutageBridgeTransitionIfNeeded): on a connected forced-open step with the mask armed it actively cancels the0 U/hrtemp basal (PumpService.cancelTempBasal) and marksMaskedFallbackMode.releasedForOutage(maintenance policy suppresses renewals in that mode); on the next non-forced-open step it re-arms the mask BEFORE the step's pump command; cancel failure keeps the mask and retries, re-arm failure blocks that step's insulin command. Bridged exposure enters the algorithm's accounting live while released:OutageDeliveryCreditSupportfeeds one synthetic per-step tuple (echo of the persisted previous ask + identity-guarded pod-counter delta) on every executed released step, and a pod-away gap (skipped steps, then a matching-identity reconnect status with pod totals) is reconciled by the standard bounded schedule-weighted fallback replay synthesized in the coordinator (prepareReleasedOutageGapReplayIfNeeded->performPendingFallbackReplayIfNeeded; confirmed-stamped plan, SRS-RUN-006 echo chain - sponsor direction 2026-07-18, never a single reconnect-step chunk). Per-row shares are whole multiples of the algorithm's 0.01 U insulin-ledger resolution allocated by schedule-weighted largest remainder (FallbackBasalReplayPlanner.quantizedRowUnits; zero-share rows keep their echo/retraction role) so the C++'s booked row total equals the measured delta exactly, with schedule weights evaluated in the engaged event's recorded profile timezone (device zone fallback, mirroring the classic replay call site). The plan itself carries the credit bundle (FallbackBasalReplayPlan.ReleasedOutageGapCredit: measured delta, re-anchor counter and pod identity, first-row echo ask); whichever pass consumes the plan applies the baseline re-anchor, the exactly-once accumulation, and the final-row ask handoff in the same save that clears it, so a force-quit at any mid-pass persistence point replays on relaunch with the full bundle instead of double-counting; a cadence-drift skip on the synthesis pass discards the just-synthesized plan untouched and the next pass re-synthesizes against the realigned counter. No maximum-outage stop exists by design. -
SDD-DATA-002: primary and safety/fallback algorithm state blobs are persisted in separateUserDefaultsAlgoStateStoreinstances with distinct storage keys, so neither track's persisted state can be loaded into the other. -
SDD-DATA-003: step telemetry is persisted inLoopTelemetryStore; shared runtime state persists the latest structured fallback-basal event and the maintenance state required across relaunch (originalProgrammedBasalSchedule, fallback schedule/rate, safety target, pod identity, pump-total baseline/timestamp, mask-renewal and schedule-refresh timestamps/outcomes, and recovery detail). Per-step records persist Algo2015 delivered-insulin echo fields beside algorithm snapshots so reconciled accounting is auditable.maskedFallbackRecoveryStateandpendingFallbackBasalReplayPlansurvive relaunch and support connected retry, bounded no-command replay, or explicit unreconciled disposition. Runtime state also persists pending issued-dose attribution, credible partition evidence, the most recent consumed issued-dose delivery, delivery discrepancy, and reconciliation failure; lifecycle expiry prevents stale records from coloring a fresh episode. Different/new-pod cases consume assumed-delivered evidence without creating a blocking hold. Primary and secondary/safety q5 nominal-basal profiles persist independently for traceable schedule generation. Resolved fallback events retain modeled exposure, actual fallback delivery only when evidence supports it, raw pump-total delta separately, pod continuity, and replay metadata. Confirmed/corrected replay rows useCGM=-1, schedule-weighted delivered input, and no catch-up commands; modeled exposure remains review-only when evidence cannot support allocation. Retired/expired/no-active pod fallback recovery is persisted as a separate assumed-delivered disposition: modeled expected delivery is copied into actual delivered units only withassumed_delivered_per_clinical_policy, and replay/review telemetry must preserve that source so assumed fallback accounting cannot be mistaken for pump-counter-confirmed delivery. pendingFallbackBasalReplayPlan.firstReplayStep/lastReplayStepdenote the fallback-active replay interval, not the full disconnected gap. The stored plan includes explicit0 Udeliveries only for replay-eligible fallback-active slots.-
SDD-DATA-004: device managers are persisted via app delegates for reconnect behavior. -
SDD-DATA-005: alert lifecycle state is persisted in bothAppAlertCenter(active + recently-cleared timeline, capped at 100 entries) and delegate-level LoopKitPersistedAlertStoreimplementations (issued/retracted records for pump/cgm sources). -
SDD-DATA-006: clinical settings are persisted in a versioned model with deterministic defaults and migration behavior; weight is normalized lbs (UI) -> kg (runtime input). The persisted clinical config now also carries the participant target-access profile, with migration default/inference rules so legacy saved target values load into eitherPregnancyorStandarddeterministically.
6. Requirement Allocation¶
| SRS ID | Design Element(s) |
|---|---|
| SRS-RUN-001..007 | SDD-APP-001, SDD-CORE-001, SDD-POL-001, SDD-POL-021, SDD-PUMP-001 |
| SRS-ALG-001..009 | SDD-ALG-001, SDD-QA-001 |
| SRS-OUTAGE-001..006 | SDD-OUTAGE-001, SDD-PUMP-001, SDD-ALERT-001 |
| SRS-PUMP-011 | SDD-PUMP-001 |
| SRS-CLIN-013..015 | SDD-CLIN-001 |
| SRS-CLIN-016..017 | SDD-CLIN-001, SDD-CLIN-002, SDD-LOG-001 |
| SRS-CGM-001..005 | SDD-CORE-001, SDD-POL-002, SDD-POL-020, SDD-CGM-001, SDD-APP-003, SDD-SIM-001 |
| SRS-CGM-006 | SDD-CGM-002, SDD-ALERT-001, SDD-LOG-001 |
| SRS-BG-001..013 | SDD-APP-001, SDD-CORE-001, SDD-BG-001, SDD-POL-010, SDD-POL-011, SDD-POL-012, SDD-LOG-001 |
| SRS-CLIN-001..012 | SDD-CLIN-001, SDD-POL-013, SDD-POL-017, SDD-POL-025, SDD-DATA-006 |
| SRS-PUMP-001..010 | SDD-PUMP-001, SDD-POL-003, SDD-POL-029, SDD-SIM-001, SDD-DATA-003 |
| SRS-MEAL-001..006 | SDD-APP-001, SDD-CORE-001, SDD-POL-004 |
| SRS-MEAL-007..011 | SDD-APP-001, SDD-PUMP-001, SDD-LOG-001, SDD-POL-023, SDD-POL-024, SDD-POL-027 |
| SRS-MEAL-012 | SDD-APP-001, SDD-POL-029 |
| SRS-STATE-001..005 | SDD-DATA-001..005, SDD-POL-005, SDD-POL-028, SDD-POL-029, SDD-PUMP-001 |
| SRS-LOG-001..015 | SDD-LOG-001, SDD-SIM-001, SDD-POL-017, SDD-POL-018, SDD-POL-024, SDD-POL-025, SDD-APP-007, SDD-POL-028, SDD-CLIN-002 |
| SRS-UI-001..008 | SDD-APP-001, SDD-POL-006, SDD-POL-007, SDD-POL-009, SDD-POL-014, SDD-POL-018, SDD-POL-019, SDD-CGM-001 |
| SRS-UI-009 | SDD-APP-008 |
| SRS-VAL-001 | SDD-CLIN-001, SDD-DATA-006 |
| SRS-ALERT-001..019 | SDD-ALERT-001, SDD-POL-008, SDD-POL-020, SDD-POL-022, SDD-POL-026, SDD-DATA-005 |
| SRS-ALERT-020 | SDD-ALERT-001, SDD-CGM-002 |
| SRS-SEC-001..002 | SDD-LOG-001, SDD-CFG-001, and the Cybersecurity Plan (current software scope) |
| SRS-SEC-003..009 | SDD-AUTH-001, SDD-AUTH-002, SDD-POL-015, SDD-POL-016, and the Cybersecurity Plan (documented implementation; deferred from current software package) |
7. Design Constraints¶
- iOS background execution is opportunistic; runtime requires deterministic, bounded skip and degraded behavior.
- External device SDK behavior (
OmniBLE,G7SensorKit) constrains event cadence and status timing. - Closed-loop safety policy requires avoiding manual bolus path exposure.
- The designated study build and any later controlled build must use a tracked app-workspace SwiftPM resolution and exact CryptoSwift requirement; dependency-control checks fail when the source URL, exact version, revision, or Git control drifts.
Security/auth scope note:
SDD-AUTH-001,SDD-AUTH-002,SDD-POL-015, andSDD-POL-016document current implementation boundaries because the code exists in the repository.- For the current software package, those auth/provider/session-continuity design elements are documented implementation context only.
- Closure claims for
SRS-SEC-003..009remain deferred and are not being asserted through the current software package.
8. BG Design and Deferred Considerations¶
8.1 Functional flow¶
- User opens BG entry flow and submits BG with explicit confirmation.
- Runtime validates session state and computes
expectedStep. - Submitted BG must be within
20...600 mg/dL. - Runtime creates/updates one pending BG candidate:
- if due step has not executed yet, target that due step;
- if due step already executed, target immediate next step.
- if a candidate already exists, replace with newer BG submission.
- Runtime dispatches
doWork(cause: bgCheck)without borrowing future slots. - On execution, coordinator consumes pending BG candidate only when step index matches candidate target and candidate freshness is valid.
- Coordinator builds algorithm input with:
BGvalfrom submitted manual BG.- CGM input from normal CGM mapping policy (may remain
-1). - Algorithm executes once for due step.
- Command application follows normal pump safety policy.
- Telemetry records
manualBGsource, value, timestamps, and execution outcome. - If candidate target step is missed without consumption, runtime discards candidate as too old.
8.2 Guards and invariants¶
- No future-slot borrowing is allowed for
bgCheck. - Exactly one pending BG candidate is kept at a time.
- New BG submit replaces existing pending candidate before consumption.
- Pending BG candidate is single-step scoped and expires if not consumed on immediate next target step.
- Manual BG freshness is required at execution time.
- Pump-unavailable behavior remains unchanged from degraded-mode policy.
- Before first successful anchored step exists, manual BG submit is rejected (step-0 BG rescue disabled by current policy).
8.3 Deferred considerations¶
- The current baseline uses immediate-next-step validity rather than a separate wall-clock manual-BG freshness window. A future wall-clock limit would require an approved SRS, risk, design, and verification change.
- Step-0 BG-rescue policy (
SRS-BG-008) is deferred; current implementation remains CGM-only at step 0.
9. Simulation Strategy (Medium now, High later)¶
9.1 Medium-fidelity harness (in-scope)¶
- Architecture:
- Scenario runner emits deterministic event timelines into runtime ports.
- Mock services conform to production protocols (
CGMService,PumpService) so runtime/coordinator logic remains unmodified. - Virtual clock controls step-slot progression (
300scadence, early window, skip/catch-up timing). - Scenario event classes:
- CGM readings (value, timestamp, reliability, availability transitions)
- pump status transitions (
idle,delivering,unknown, disconnect/reconnect) - command-result events (success/failure/reconciliation data)
- normalized alert issue/retract events
- Required outputs:
- executed step index and skip reason
- algorithm input/output snapshot
- command-application decision
- alert center active/recent lifecycle state
9.2 High-fidelity emulator (future)¶
- Target:
- BLE/session-level emulation for Omni/G7 transport behavior (timing jitter, ACK patterns, session-restore edge cases).
- Positioning:
- not a near-term gating dependency; added after medium-fidelity harness is stable.
9.3 Safety/testing contribution¶
- Improves hazard-path reproducibility for race conditions that are hard to force on demand with real devices.
- Expands deterministic pre-merge coverage for gating failures (step timing, degraded inputs, command-block behavior, alert escalation).
- Produces traceable verification artifacts that can be mapped to RA/SRS/TV with lower variance than ad hoc manual runs.
- Complements, but does not replace, hardware-in-the-loop verification for true transport and physical-delivery behavior.