Skip to content

Software Design Description (SDD)

Status: Final draft prepared for handoff (pending review)
Version: 0.9
Owner: BionicLoop engineering Prepared by: BionicLoop engineering Reviewer: ____
Approver: ____
Decision date: ____
Effective date: ____
Baseline freeze SHA: ____
Last updated: 2026-04-06 16:35 EDT

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 handoff-ready document-control metadata and software-handoff disposition language

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: LoopSessionStore owns app-layer runtime persistence reads/writes for loop armed state and runtime state snapshots.
  • SDD-APP-003: LoopWorkScheduler owns CGM-timestamp trigger dedupe and arm/reset semantics for runtime wake dispatch.
  • SDD-APP-004: LoopAlertMediator owns pump signal-loss tracking and report gating in app-layer state.
  • SDD-APP-005: LoopTelemetryWriter owns app-layer telemetry-store writes and reconciliation calls.
  • SDD-APP-006: LoopRuntimeWorkExecutor owns 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-AUTH-001: App auth-session boundary is split into AppAuthSessionManager (secure token persistence, restore, refresh, sign-out clear) and AuthenticatedAPIClient (bearer-auth request composition + one-time refresh retry on unauthorized response), implemented in BionicLoop/App/AuthSessionNetworking.swift. Recovered/refreshed token sets are validated for telemetry-ingest scope before persistence.
  • SDD-AUTH-002: Email/password recovery boundary is implemented in CognitoPasswordRecoveryService (ForgotPassword, ConfirmForgotPassword) plus unauthenticated route/state wiring (.forgotPassword) and NoAuthForgotPasswordView for reset-code request, confirmation, resend, and user-feedback messaging.
  • SDD-CORE-001: LoopRuntimeCoordinator (BionicLoopCore/.../Runtime/LoopRuntimeCoordinator.swift) handles due-step logic, input assembly, algorithm invocation, and command application.
  • SDD-ALG-001: RealBUDosingAlgorithm + Algo2015Bridge map runtime input into C bridge structs and receive output/state.
  • SDD-PUMP-001: PumpServiceAdapter + PumpStatusObserver handle status refresh, command execution, delivery reconciliation, home-status projection, and auto-polling while deliveryState == delivering.
  • SDD-CGM-001: G7ViewModel + CGM subsystem adapters provide CGM state ingestion and wake trigger source; telemetry cgm.state.changed is emitted from refreshed/current callback state to avoid stale has_sensor transitions, and cgm.connection.changed derives status_text from refreshed lifecycle state before emit.
  • SDD-BG-001: Manual BG entry path spans Home/UI entry, runtime bgCheck wake dispatch, single-pending-candidate BG state, next-eligible-step consumption logic, and telemetry source tagging (manualBG).
  • SDD-CLIN-001: Clinical settings boundary spans passcode-gated settings presentation, clinician-only control hosting (Subject ID, Weight, Start Algo, Reset 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.
  • SDD-LOG-001: LoopTelemetryStore stores per-step records for UI + export, and CloudTelemetryReporter emits authenticated telemetry envelopes with correlation metadata (event_id, session_id, subject_id) plus auth_user_sub derived from Cognito ID-token sub (fallback UNSET only when unavailable); loop-step payloads carry explicit execution timestamp step_executed_at (execution semantics) in addition to envelope created_at (ingest creation time). Loop command telemetry mapping is schema-stable: loop.command.blocked is emitted only when a recommendation existed but was blocked, while pump.command.result remains pump-result schema only and emits on delivery-result deltas only (no unchanged refresh re-emission). Outbox flushing is loss-avoidant: if flush is requested while a flush is active, a deferred follow-up flush is queued and executed immediately after the active pass completes (with full-flush escalation when any deferred request requires non-high-priority delivery). Client cloud-log threshold resolution uses precedence remote override (active, TTL-bound) -> local threshold -> default error; local threshold is exposed in debug builds via HomeSettingsView and persisted through CloudLogUploadPolicy.
  • 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 recency), dedupe keys, and debounced signal-loss handling. Current live UI presentation includes a Home vertical active-alert carousel (prioritized and multiplicity-aware), plus a Home bell entry to Alert Center (active + recently cleared), with secondary access from Settings. G1 source inventory/mapping baseline is documented in Alert Inventory and Mapping.
  • 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 reproducible TV-ALG-* evidence artifacts for IDE submission, as specified in Algo2015 Verification Plan.

3. Runtime Sequence (Nominal)

  1. New CGM timestamp arrives.
  2. LoopRuntimeEngine triggers coordinator doWork.
  3. Coordinator computes expected step from anchor + interval.
  4. Coordinator builds algorithm input:
  5. CGM (or unavailable -1 by policy).
  6. Pump fields (or unavailable values if pump not available).
  7. Algorithm returns recommendation and updated internal state blob.
  8. If pump status is available and recommendation passes gates, command is attempted.
  9. Telemetry record is persisted with input/output/command fields.
  10. Pump status refresh reconciles delivered/requested units.

4. Key Design Policies

  • SDD-POL-001 (Cadence): anchored 5-minute slot model.
  • SDD-POL-002 (CGM): step 0 strict gate, step >0 degraded 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, and not 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. Unavailable-reason precedence reports noPump before signalLoss when there is no active pod. Home/meal presentation logic revalidates meal availability when the app refreshes to active while the composer is visible and again immediately before submit, closing stale-composer paths by replacing them with the current unavailable presentation instead of dispatching a now-invalid meal request. This is the accepted current software handoff baseline for late-submit meal behavior.
  • 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 (nextDueAt from anchor + step index) so borrowed meal steps do not falsely age status before the next due boundary. Current thresholds: Active through nextDueAt + 2m, Aging through nextDueAt + 15m, then Stale.
  • SDD-POL-007 (Modal setup cancellation): startup/setup modals for CGM and Pod provide direct dismiss behavior via explicit Cancel, 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 triggers bgCheck with 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 in LoopRuntimeEngine and shall not dispatch bgCheck while disarmed.
  • SDD-POL-012 (BG step-0 guard): until step-0 BG rescue is approved, manual BG submit is rejected if firstSuccessfulStepAt is not established.
  • SDD-POL-013 (Clinical settings policy): clinician configuration access is passcode-gated using the current investigational baseline value 020508, 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. HomeSettingsView persists 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, HomeSettingsView explicitly retracts the app-level ALERT-SUBJECT-ID-CONFLICT alert 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 control remains subject to replacement by authenticated role-based access before production release.
  • SDD-POL-014 (CGM display masking for stale/unreliable data): G7ViewModel applies a display-staleness cutoff of 11 minutes and checks hasReliableGlucose on 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, Home shows a persistent auth-recovery alert (ALERT-AUTH-LOGIN-REQUIRED) with direct Log In action until re-authentication completes.
  • SDD-POL-017 (Clinical/settings telemetry): Clinical Settings save-review flow emits ui.critical telemetry with stable event/action mapping: state_viewed on review presentation, submit on Save, cancel on review dismissal, and blocked on 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 stable ui.critical lifecycle (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 actionable ALERT-APP-CLOCK-SKEW warning no more than once per 24 hours; unavailable checks do not show user warnings.
  • SDD-POL-019 (CGM boundary display + chart scaling): CGM value rendering maps <=39 mg/dL to LOW and >=401 mg/dL to HIGH across 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.
  • SDD-POL-020 (algorithm stepping interruption monitoring): LoopRuntimeEngine monitors for stalled loop execution while armed using persisted runtime/session state rather than CGM-receipt time alone. The interruption deadline is computed from lastSuccessfulRunAt + 15 minutes; if no successful step exists yet, the baseline is session start / first-step wait state. AppAlertCenter clears 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 to firstSuccessfulStepAt with 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 is ALERT-ALGORITHM-STEPPING-INTERRUPTED, keyed to lack of successful algorithm execution rather than lack of CGM receipt alone. Trigger basis is loop armed plus no 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 (for example no active pod, pump signal loss, or another execution gate), clears on the next successful step or loop disarm/reset, and exposes blocker/root-cause detail without masking stronger source-native CGM/pump alerts.
  • SDD-POL-023 (meal-request durability baseline): LoopRuntimeState persists pending meal-request state across relaunch using submit time, the concrete execution step accepted by LoopRuntimeCoordinator, 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() returns requestInProgress or uncertainPreviousMeal and 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-driven submitted, accepted, success, blocked, uncertain, and resolved paths. HomeView keeps the composer in a submitting state while LoopRuntimeEngine.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 the lastExecutedStep observed when the meal composer opens and passes that snapshot with submit; LoopRuntimeCoordinator compares it against current cadence state and returns mealSlotConflict if 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 correlated accepted telemetry after coordinator acceptance and resolved telemetry 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 explicit command_outcome semantics 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. HomeRegularTargetChangeApprovalPolicy first 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:) derives ALERT-CGM-URGENT-LOW from current live G7 data when latestReading.hasReliableGlucose == true, the reading timestamp is within the trusted freshness window, and glucose < 55 mg/dL. The alert is app-derived for clinician review and cloud telemetry, not Dexcom-app alarm acknowledgement. AppAlertCenter keeps the alert active after acknowledge by stamping acknowledgedAt rather 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 existing acknowledgedAt for the active episode, and a later new <55 mg/dL episode reissues as unacknowledged after recovery clears the prior episode. CGMAlertPersistenceStore persists 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, HomeActionCoordinator routes the flow into a dedicated cancel-delivery presentation on Home instead of exposing a second meal submit path. HomeView reveals a destructive slider-backed Cancel Delivery action beneath the Manual BG / Let's Eat controls, and that action can now remain visible automatically while an active meal-announcement bolus is still in progress, even without a second tap on Let's Eat, by deriving the active cancelable state from current pump delivery state plus the matching meal step telemetry. When PumpStatus.lastDelivery is 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 calls PumpStatusObserver.cancelBolusDelivery(), which delegates to PumpService.cancelBolus() and converts the canceled dose into actual requested/delivered units. On success, Home shows an orange 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 (requestedUnits vs deliveredUnits), but active in-progress meal delivery remains rendered in the normal meal-dose color while the pump still reports .delivering; LoopTelemetryStore now 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. Caution color is reserved for actual interrupted/partial delivery once delivery has been stopped or otherwise ended short. When cancel succeeds, PumpStatusObserver explicitly reconciles the shared LoopTelemetryStore step 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 shared LoopTelemetryStore record 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 .delivering when adjacent bars collapse onto one display pixel so compaction cannot strip active-delivery styling. The pump adapter preserves the delivered amount in PumpStatus.lastDelivery so 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-reported requested - bolusNotDelivered amount instead of regressing a completed bolus back into partial-delivery state.
  • SDD-POL-008 (Alert policy, partial): multi-source alert normalization model drives pump and CGM alert mapping plus pump signal-loss debounce (5 minutes), no-active-pod debounce (5 minutes), dedupe, deterministic alert precedence, and auto-clear behavior. Home active-alert presentation uses a vertical carousel ordered by severity then recency, with multiplicity indicator and step-through controls when multiple alerts are active. High-priority non-CGM alerts additionally route to background local notifications through AppAlertCenter with 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); the cgm route 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 Home banner/carousel and in Alert Center (ackState == requiresAcknowledge); current production required-ack alerts are pump fault, pump incompatible, and app-derived ALERT-CGM-URGENT-LOW. OS-notification clear calls are idempotent on every retract attempt (including already-cleared keys) to cover async schedule/retract races; alert lifecycle telemetry still emits alert.notification.cleared only when an active alert transitions to removed. App-level active/recently-cleared alert state is persisted and restored across relaunch; pump/cgm delegate PersistedAlertStore hooks 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-FAULT and ALERT-PUMP-INCOMPATIBLE are retained until explicit lifecycle retraction or acknowledge closure. Time-sensitive alert countdown text (ALERT-PUMP-EXPIRING and ALERT-PUMP-EXPIRED) is carried as countdown metadata and refreshed by AppAlertCenter on a minute interval while active so displayed remaining time stays current. Pod expiration/expired alerting is sourced from both delegate issue/retract callbacks and state-driven synthesis from pump expiresAt on 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 in SDD-POL-026. Runtime-derived ALERT-ALGORITHM-STEPPING-INTERRUPTED is 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. Remaining work is expanded severity channels/escalation surfaces and real-device/background validation. Mapping baseline and source inventory are maintained in Alert Inventory and Mapping.

5. Data Persistence

  • SDD-DATA-001: runtime cadence state is persisted in UserDefaultsLoopRuntimeStateStore.
  • SDD-DATA-002: algorithm state blob is persisted in UserDefaultsAlgoStateStore.
  • SDD-DATA-003: step telemetry is persisted in LoopTelemetryStore.
  • SDD-DATA-004: device managers are persisted via app delegates for reconnect behavior.
  • SDD-DATA-005: alert lifecycle state is persisted in both AppAlertCenter (active + recently-cleared timeline, capped at 100 entries) and delegate-level LoopKit PersistedAlertStore implementations (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 either Pregnancy or Standard deterministically.

6. Requirement Allocation

SRS ID Design Element(s)
SRS-RUN-001..005 SDD-APP-001, SDD-CORE-001, SDD-POL-001, SDD-POL-021
SRS-ALG-001..007 SDD-ALG-001, SDD-QA-001
SRS-CGM-001..005 SDD-CORE-001, SDD-POL-002, SDD-POL-020, SDD-CGM-001, SDD-APP-003, SDD-SIM-001
SRS-BG-001..012 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..005 SDD-PUMP-001, SDD-POL-003, SDD-SIM-001
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-STATE-001..003 SDD-DATA-001..005, SDD-POL-005
SRS-LOG-001..008 SDD-LOG-001, SDD-SIM-001, SDD-POL-017, SDD-POL-018, SDD-POL-024, SDD-POL-025, SDD-APP-007
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-VAL-001 SDD-CLIN-001, SDD-DATA-006
SRS-ALERT-001..015 SDD-ALERT-001, SDD-POL-008, SDD-POL-020, SDD-POL-022, SDD-DATA-005
SRS-SEC-001..002 SDD-LOG-001 + Docs/Quality/CybersecurityPlan.md (current software handoff scope)
SRS-SEC-003..004, SRS-SEC-006..009 SDD-AUTH-001, SDD-AUTH-002, SDD-POL-015, SDD-POL-016 + Docs/Quality/CybersecurityPlan.md (documented implementation; deferred from current software handoff package)

7. Design Constraints

  • iOS background execution is opportunistic; runtime requires robust skip/degraded behavior.
  • External device SDK behavior (OmniBLE, G7SensorKit) constrains event cadence and status timing.
  • Closed-loop safety policy requires avoiding manual bolus path exposure.

Security/auth scope note:

  • SDD-AUTH-001, SDD-AUTH-002, SDD-POL-015, and SDD-POL-016 document current implementation boundaries because the code exists in the repository.
  • For the current engineering software handoff package, those auth/provider/session-continuity design elements are documented implementation context only.
  • Closure claims for SRS-SEC-003..009 remain deferred and are not being asserted through the current handoff package.

8. BG Design and Pending Decisions

8.1 Functional flow

  1. User opens BG entry flow and submits BG with explicit confirmation.
  2. Runtime validates session state and computes expectedStep.
  3. Submitted BG must be within 20...600 mg/dL.
  4. Runtime creates/updates one pending BG candidate:
  5. if due step has not executed yet, target that due step;
  6. if due step already executed, target immediate next step.
  7. if a candidate already exists, replace with newer BG submission.
  8. Runtime dispatches doWork(cause: bgCheck) without borrowing future slots.
  9. On execution, coordinator consumes pending BG candidate only when step index matches candidate target and candidate freshness is valid.
  10. Coordinator builds algorithm input with:
  11. BGval from submitted manual BG.
  12. CGM input from normal CGM mapping policy (may remain -1).
  13. Algorithm executes once for due step.
  14. Command application follows normal pump safety policy.
  15. Telemetry records manualBG source, value, timestamps, and execution outcome.
  16. 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 Pending decisions before implementation lock

  • Final manual BG freshness window.
  • 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 (300s cadence, 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.