diff --git a/Common/FeatureFlags.swift b/Common/FeatureFlags.swift
index b2f0953ee..3ed4b4a4e 100644
--- a/Common/FeatureFlags.swift
+++ b/Common/FeatureFlags.swift
@@ -38,6 +38,7 @@ struct FeatureFlagConfiguration: Decodable {
     let dynamicCarbAbsorptionEnabled: Bool
     let adultChildInsulinModelSelectionEnabled: Bool
     let profileExpirationSettingsViewEnabled: Bool
+    let missedMealNotifications: Bool
 
 
     fileprivate init() {
@@ -220,6 +221,14 @@ struct FeatureFlagConfiguration: Decodable {
         #else
         self.profileExpirationSettingsViewEnabled = true
         #endif
+
+        // Missed meal notifications compiler flag is inverse, since the default state is enabled.
+        #if MISSED_MEAL_NOTIFICATIONS_DISABLED
+        self.missedMealNotifications = false
+        #else
+        self.missedMealNotifications = true
+        #endif
+
     }
 }
 
@@ -253,7 +262,8 @@ extension FeatureFlagConfiguration : CustomDebugStringConvertible {
             "* usePositiveMomentumAndRCForManualBoluses: \(usePositiveMomentumAndRCForManualBoluses)",
             "* dynamicCarbAbsorptionEnabled: \(dynamicCarbAbsorptionEnabled)",
             "* adultChildInsulinModelSelectionEnabled: \(adultChildInsulinModelSelectionEnabled)",
-            "* profileExpirationSettingsViewEnabled: \(profileExpirationSettingsViewEnabled)"
+            "* profileExpirationSettingsViewEnabled: \(profileExpirationSettingsViewEnabled)",
+            "* missedMealNotifications: \(missedMealNotifications)"
         ].joined(separator: "\n")
     }
 }
diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj
index 0cb02fb94..52137df99 100644
--- a/Loop.xcodeproj/project.pbxproj
+++ b/Loop.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 52;
+	objectVersion = 54;
 	objects = {
 
 /* Begin PBXBuildFile section */
@@ -396,6 +396,7 @@
 		B40D07C7251A89D500C1C6D7 /* GlucoseDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40D07C6251A89D500C1C6D7 /* GlucoseDisplay.swift */; };
 		B42C951424A3C76000857C73 /* CGMStatusHUDViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B42C951324A3C76000857C73 /* CGMStatusHUDViewModel.swift */; };
 		B42D124328D371C400E43D22 /* AlertMuter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B42D124228D371C400E43D22 /* AlertMuter.swift */; };
+		B43CF07E29434EC4008A520B /* HowMuteAlertWorkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43CF07D29434EC4008A520B /* HowMuteAlertWorkView.swift */; };
 		B43DA44124D9C12100CAFF4E /* DismissibleHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43DA44024D9C12100CAFF4E /* DismissibleHostingController.swift */; };
 		B44251B3252350CE00605937 /* ChartAxisValuesStaticGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B44251B2252350CE00605937 /* ChartAxisValuesStaticGeneratorTests.swift */; };
 		B44251B62523578300605937 /* PredictedGlucoseChartTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B44251B52523578300605937 /* PredictedGlucoseChartTests.swift */; };
@@ -413,7 +414,7 @@
 		B4CAD8792549D2540057946B /* LoopCompletionFreshnessTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CAD8782549D2540057946B /* LoopCompletionFreshnessTests.swift */; };
 		B4D4534128E5CA7900F1A8D9 /* AlertMuterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4D4534028E5CA7900F1A8D9 /* AlertMuterTests.swift */; };
 		B4D620D424D9EDB900043B3C /* GuidanceColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4D620D324D9EDB900043B3C /* GuidanceColors.swift */; };
-		B4E202302661063E009421B5 /* ClosedLoopStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E2022F2661063E009421B5 /* ClosedLoopStatus.swift */; };
+		B4E202302661063E009421B5 /* AutomaticDosingStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E2022F2661063E009421B5 /* AutomaticDosingStatus.swift */; };
 		B4E96D4B248A6B6E002DABAD /* DeviceStatusHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E96D4A248A6B6E002DABAD /* DeviceStatusHUDView.swift */; };
 		B4E96D4F248A6E20002DABAD /* CGMStatusHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E96D4E248A6E20002DABAD /* CGMStatusHUDView.swift */; };
 		B4E96D53248A7386002DABAD /* GlucoseValueHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E96D52248A7386002DABAD /* GlucoseValueHUDView.swift */; };
@@ -1377,6 +1378,7 @@
 		B40D07C6251A89D500C1C6D7 /* GlucoseDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseDisplay.swift; sourceTree = "<group>"; };
 		B42C951324A3C76000857C73 /* CGMStatusHUDViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGMStatusHUDViewModel.swift; sourceTree = "<group>"; };
 		B42D124228D371C400E43D22 /* AlertMuter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertMuter.swift; sourceTree = "<group>"; };
+		B43CF07D29434EC4008A520B /* HowMuteAlertWorkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HowMuteAlertWorkView.swift; sourceTree = "<group>"; };
 		B43DA44024D9C12100CAFF4E /* DismissibleHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissibleHostingController.swift; sourceTree = "<group>"; };
 		B44251B2252350CE00605937 /* ChartAxisValuesStaticGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartAxisValuesStaticGeneratorTests.swift; sourceTree = "<group>"; };
 		B44251B52523578300605937 /* PredictedGlucoseChartTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredictedGlucoseChartTests.swift; sourceTree = "<group>"; };
@@ -1391,7 +1393,7 @@
 		B4CAD8782549D2540057946B /* LoopCompletionFreshnessTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopCompletionFreshnessTests.swift; sourceTree = "<group>"; };
 		B4D4534028E5CA7900F1A8D9 /* AlertMuterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertMuterTests.swift; sourceTree = "<group>"; };
 		B4D620D324D9EDB900043B3C /* GuidanceColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuidanceColors.swift; sourceTree = "<group>"; };
-		B4E2022F2661063E009421B5 /* ClosedLoopStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedLoopStatus.swift; sourceTree = "<group>"; };
+		B4E2022F2661063E009421B5 /* AutomaticDosingStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutomaticDosingStatus.swift; sourceTree = "<group>"; };
 		B4E96D4A248A6B6E002DABAD /* DeviceStatusHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStatusHUDView.swift; sourceTree = "<group>"; };
 		B4E96D4E248A6E20002DABAD /* CGMStatusHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMStatusHUDView.swift; sourceTree = "<group>"; };
 		B4E96D52248A7386002DABAD /* GlucoseValueHUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseValueHUDView.swift; sourceTree = "<group>"; };
@@ -1468,6 +1470,7 @@
 		C1004E342981F77B00B8CF94 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		C1004E352981F77B00B8CF94 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		C101947127DD473C004E7EB8 /* MockKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MockKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		C1092BFD29F8116700AE3D1C /* apply-info-customizations.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "apply-info-customizations.sh"; sourceTree = "<group>"; };
 		C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = far_future_high_bg_forecast.json; sourceTree = "<group>"; };
 		C11613482983096D00777E7C /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		C116134B2983096D00777E7C /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -1640,6 +1643,7 @@
 		C1E693CF29C786E200410918 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		C1E693D029C786E200410918 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		C1E71721292E90CC00DA646F /* SmallStatusWidgetEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallStatusWidgetEntryView.swift; sourceTree = "<group>"; };
+		C1E9CB5A295101570022387B /* install-scenarios.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-scenarios.sh"; sourceTree = "<group>"; };
 		C1EB0D1D299581D900628475 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		C1EB0D1E299581D900628475 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
 		C1EB0D1F299581D900628475 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -2037,7 +2041,7 @@
 				43511CDD21FD80AD00566C63 /* RetrospectiveCorrection */,
 				A9FB75F0252BE320004C7D3F /* BolusDosingDecision.swift */,
 				C17824A41E1AD4D100D9D25C /* ManualBolusRecommendation.swift */,
-				B4E2022F2661063E009421B5 /* ClosedLoopStatus.swift */,
+				B4E2022F2661063E009421B5 /* AutomaticDosingStatus.swift */,
 				B40D07C6251A89D500C1C6D7 /* GlucoseDisplay.swift */,
 				43C2FAE01EB656A500364AFF /* GlucoseEffectVelocity.swift */,
 				436A0DA41D236A2A00104B24 /* LoopError.swift */,
@@ -2380,6 +2384,7 @@
 				A9A056B224B93C62007CF06D /* CriticalEventLogExportView.swift */,
 				C191D2A025B3ACAA00C26C0B /* DosingStrategySelectionView.swift */,
 				43D381611EBD9759007F8C8F /* HeaderValuesTableViewCell.swift */,
+				B43CF07D29434EC4008A520B /* HowMuteAlertWorkView.swift */,
 				430D85881F44037000AF2D4F /* HUDViewTableViewCell.swift */,
 				A91D2A3E26CF0FF80023B075 /* IconTitleSubtitleTableViewCell.swift */,
 				C1742331259BEADC00399C9D /* ManualEntryDoseView.swift */,
@@ -2892,6 +2897,8 @@
 				C18A491222FCC22800FDA733 /* build-derived-assets.sh */,
 				C18A491522FCC22900FDA733 /* copy-plugins.sh */,
 				C18A491322FCC22900FDA733 /* make_scenario.py */,
+				C1E9CB5A295101570022387B /* install-scenarios.sh */,
+				C1092BFD29F8116700AE3D1C /* apply-info-customizations.sh */,
 			);
 			path = Scripts;
 			sourceTree = "<group>";
@@ -3115,8 +3122,10 @@
 				43776F8A1B8022E90074EA36 /* Resources */,
 				43A9439C1B926B7B0051FA24 /* Embed Watch Content */,
 				43A943AE1B928D400051FA24 /* Embed Frameworks */,
+				C113F4472951352C00758735 /* Install Scenarios */,
 				C16DA84322E8E5FF008624C2 /* Install Plugins */,
 				C1D19800232CFA2A0096D646 /* Capture Build Details */,
+				C1092BFE29F88F0600AE3D1C /* Apply Info Customizations */,
 				4F70C1EC1DE8DCA8006380B7 /* Embed App Extensions */,
 			);
 			buildRules = (
@@ -3653,6 +3662,44 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
+		C1092BFE29F88F0600AE3D1C /* Apply Info Customizations */ = {
+			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/../InfoCustomizations",
+			);
+			name = "Apply Info Customizations";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Scripts/apply-info-customizations.sh\"\n";
+		};
+		C113F4472951352C00758735 /* Install Scenarios */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+			);
+			name = "Install Scenarios";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${SRCROOT}/Scripts/install-scenarios.sh\"\n";
+		};
 		C16DA84322E8E5FF008624C2 /* Install Plugins */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -3691,6 +3738,7 @@
 		};
 		C1D19800232CFA2A0096D646 /* Capture Build Details */ = {
 			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			files = (
 			);
@@ -3819,7 +3867,7 @@
 				1D49795824E7289700948F05 /* ServicesViewModel.swift in Sources */,
 				1D4A3E2D2478628500FD601B /* StoredAlert+CoreDataClass.swift in Sources */,
 				892D7C5123B54A15008A9656 /* CarbEntryViewController.swift in Sources */,
-				B4E202302661063E009421B5 /* ClosedLoopStatus.swift in Sources */,
+				B4E202302661063E009421B5 /* AutomaticDosingStatus.swift in Sources */,
 				C191D2A125B3ACAA00C26C0B /* DosingStrategySelectionView.swift in Sources */,
 				A977A2F424ACFECF0059C207 /* CriticalEventLogExportManager.swift in Sources */,
 				89CA2B32226C18B8004D9350 /* TestingScenariosTableViewController.swift in Sources */,
@@ -3870,6 +3918,7 @@
 				4FC8C8011DEB93E400A1452E /* NSUserDefaults+StatusExtension.swift in Sources */,
 				43E93FB61E469A4000EAB8DB /* NumberFormatter.swift in Sources */,
 				C1FB428C217806A400FAB378 /* StateColorPalette.swift in Sources */,
+				B43CF07E29434EC4008A520B /* HowMuteAlertWorkView.swift in Sources */,
 				1D6B1B6726866D89009AC446 /* AlertPermissionsChecker.swift in Sources */,
 				4F08DE8F1E7BB871006741EA /* CollectionType+Loop.swift in Sources */,
 				A9F703772489D8AA00C98AD8 /* PersistentDeviceLog+SimulatedCoreData.swift in Sources */,
@@ -4995,6 +5044,7 @@
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).SmallStatusWidget";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "$(LOOP_PROVISIONING_PROFILE_SPECIFIER_WIDGET_EXTENSION_DEBUG)";
 				SKIP_INSTALL = YES;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
 				SWIFT_EMIT_LOC_STRINGS = YES;
@@ -5039,6 +5089,7 @@
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).SmallStatusWidget";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "$(LOOP_PROVISIONING_PROFILE_SPECIFIER_WIDGET_EXTENSION_RELEASE)";
 				SKIP_INSTALL = YES;
 				SWIFT_EMIT_LOC_STRINGS = YES;
 				SWIFT_VERSION = 5.0;
@@ -5139,6 +5190,7 @@
 				GCC_WARN_UNUSED_LABEL = YES;
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
 				LOCALIZED_STRING_MACRO_NAMES = (
 					NSLocalizedString,
 					CFLocalizedString,
@@ -5248,6 +5300,7 @@
 				GCC_WARN_UNUSED_LABEL = YES;
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
 				LOCALIZED_STRING_MACRO_NAMES = (
 					NSLocalizedString,
 					CFLocalizedString,
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/DoseMathTests.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/DoseMathTests.xcscheme
index c9925fc45..f225f4098 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/DoseMathTests.xcscheme
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/DoseMathTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1420"
+   LastUpgradeVersion = "1430"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/Loop Intent Extension.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/Loop Intent Extension.xcscheme
index d5655ac3a..b19776bb0 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/Loop Intent Extension.xcscheme	
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/Loop Intent Extension.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1420"
+   LastUpgradeVersion = "1430"
    wasCreatedForAppExtension = "YES"
    version = "2.0">
    <BuildAction
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/Loop Status Extension.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/Loop Status Extension.xcscheme
index 30c07a14f..c77ee7c19 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/Loop Status Extension.xcscheme	
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/Loop Status Extension.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1420"
+   LastUpgradeVersion = "1430"
    wasCreatedForAppExtension = "YES"
    version = "2.0">
    <BuildAction
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/Loop.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/Loop.xcscheme
index ddeda0df5..f38a16a9d 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/Loop.xcscheme
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/Loop.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1420"
+   LastUpgradeVersion = "1430"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "NO"
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/LoopTests.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/LoopTests.xcscheme
index d3aa149eb..c62fe2330 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/LoopTests.xcscheme
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/LoopTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1420"
+   LastUpgradeVersion = "1430"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/SmallStatusWidgetExtension.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/SmallStatusWidgetExtension.xcscheme
index 10f2b05b7..d0cc5847a 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/SmallStatusWidgetExtension.xcscheme
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/SmallStatusWidgetExtension.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1420"
+   LastUpgradeVersion = "1430"
    wasCreatedForAppExtension = "YES"
    version = "2.0">
    <BuildAction
diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme
index 4e8246236..2af717c23 100644
--- a/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme
+++ b/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1330"
+   LastUpgradeVersion = "1430"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/Loop/AppDelegate.swift b/Loop/AppDelegate.swift
index 17e126795..80d45a194 100644
--- a/Loop/AppDelegate.swift
+++ b/Loop/AppDelegate.swift
@@ -45,6 +45,8 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, WindowProvider {
 
     func applicationWillEnterForeground(_ application: UIApplication) {
         log.default(#function)
+        
+        loopAppManager.askUserToConfirmCrashIfNecessary()
     }
 
     func applicationWillTerminate(_ application: UIApplication) {
diff --git a/Loop/Base.lproj/Main.storyboard b/Loop/Base.lproj/Main.storyboard
index ed868df55..d9812eb13 100644
--- a/Loop/Base.lproj/Main.storyboard
+++ b/Loop/Base.lproj/Main.storyboard
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="OJt-dE-GaA">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="OJt-dE-GaA">
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
         <capability name="Named colors" minToolsVersion="9.0"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -19,7 +19,7 @@
                         <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <prototypes>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" layoutMarginsFollowReadableWidth="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="ChartTableViewCell" rowHeight="270" id="mQk-9D-0ub" customClass="ChartTableViewCell" customModule="LoopKitUI">
-                                <rect key="frame" x="0.0" y="44.5" width="375" height="270"/>
+                                <rect key="frame" x="0.0" y="50" width="375" height="270"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="mQk-9D-0ub" id="B1i-Pw-wSw">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="270"/>
@@ -64,20 +64,20 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" layoutMarginsFollowReadableWidth="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="PredictionInputEffectTableViewCell" rowHeight="64" id="Xc2-a9-ojZ" customClass="PredictionInputEffectTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="314.5" width="375" height="64"/>
+                                <rect key="frame" x="0.0" y="320" width="375" height="64"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Xc2-a9-ojZ" id="a4h-tq-Rnl">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
                                     <autoresizingMask key="autoresizingMask"/>
                                     <subviews>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bIL-Ub-qYp">
-                                            <rect key="frame" x="16" y="11" width="343" height="17"/>
+                                            <rect key="frame" x="16" y="11" width="343" height="20.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <nil key="textColor"/>
                                             <nil key="highlightedColor"/>
                                         </label>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d6m-qV-wWi">
-                                            <rect key="frame" x="16" y="30" width="343" height="23"/>
+                                            <rect key="frame" x="16" y="33.5" width="343" height="19.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
                                             <nil key="highlightedColor"/>
                                         </label>
@@ -98,20 +98,20 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" layoutMarginsFollowReadableWidth="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="PredictionSettingTableViewCell" rowHeight="64" id="I71-cY-0y7" customClass="PredictionSettingTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="378.5" width="375" height="64"/>
+                                <rect key="frame" x="0.0" y="384" width="375" height="64"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="I71-cY-0y7" id="0f9-ja-YFt">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
                                     <autoresizingMask key="autoresizingMask"/>
                                     <subviews>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="249" verticalHuggingPriority="252" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zbc-87-wxZ">
-                                            <rect key="frame" x="16" y="11" width="343" height="17"/>
+                                            <rect key="frame" x="16" y="11" width="343" height="20.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <nil key="textColor"/>
                                             <nil key="highlightedColor"/>
                                         </label>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OFA-qT-ZAg">
-                                            <rect key="frame" x="16" y="30" width="343" height="23"/>
+                                            <rect key="frame" x="16" y="33.5" width="343" height="19.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
                                             <nil key="highlightedColor"/>
                                         </label>
@@ -162,7 +162,7 @@
                         <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <prototypes>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="ChartTableViewCell" rowHeight="318" id="cuj-C4-IMF" customClass="ChartTableViewCell" customModule="LoopKitUI">
-                                <rect key="frame" x="0.0" y="44.5" width="375" height="318"/>
+                                <rect key="frame" x="0.0" y="50" width="375" height="318"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="cuj-C4-IMF" id="oeh-yE-DB8">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="318"/>
@@ -188,7 +188,7 @@
                                             <nil key="highlightedColor"/>
                                         </label>
                                         <stackView opaque="NO" contentMode="scaleToFill" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="Qdk-Cl-ljQ">
-                                            <rect key="frame" x="16" y="167" width="105" height="50"/>
+                                            <rect key="frame" x="16" y="167" width="109" height="50"/>
                                             <subviews>
                                                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yuD-Je-55e" customClass="CircleMaskView" customModule="Loop" customModuleProvider="target">
                                                     <rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
@@ -198,7 +198,7 @@
                                                     </constraints>
                                                 </view>
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Predicted" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="87H-N1-0vJ">
-                                                    <rect key="frame" x="54" y="0.0" width="51" height="50"/>
+                                                    <rect key="frame" x="54" y="0.0" width="55" height="50"/>
                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
                                                     <nil key="textColor"/>
                                                     <nil key="highlightedColor"/>
@@ -209,7 +209,7 @@
                                             </constraints>
                                         </stackView>
                                         <stackView opaque="NO" contentMode="scaleToFill" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="6T4-P6-RWt">
-                                            <rect key="frame" x="129" y="167" width="105" height="50"/>
+                                            <rect key="frame" x="133" y="167" width="109" height="50"/>
                                             <subviews>
                                                 <view alpha="0.5" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7dr-6C-JSN" customClass="CircleMaskView" customModule="Loop" customModuleProvider="target">
                                                     <rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
@@ -219,7 +219,7 @@
                                                     </constraints>
                                                 </view>
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Observed" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EAn-Ja-S1d">
-                                                    <rect key="frame" x="54" y="0.0" width="51" height="50"/>
+                                                    <rect key="frame" x="54" y="0.0" width="55" height="50"/>
                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
                                                     <nil key="textColor"/>
                                                     <nil key="highlightedColor"/>
@@ -255,7 +255,7 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="HeaderValuesTableViewCell" rowHeight="70" id="DoF-w2-AZv" customClass="HeaderValuesTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="362.5" width="375" height="70"/>
+                                <rect key="frame" x="0.0" y="368" width="375" height="70"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="DoF-w2-AZv" id="yoj-yn-ZNl">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="70"/>
@@ -282,16 +282,16 @@
                                                             </subviews>
                                                         </stackView>
                                                         <stackView opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="xsa-fa-q0Q">
-                                                            <rect key="frame" x="27.5" y="0.0" width="200" height="59.5"/>
+                                                            <rect key="frame" x="27.5" y="0.0" width="200" height="60"/>
                                                             <subviews>
                                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="g Active Carbs" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="SQx-au-ZcM">
-                                                                    <rect key="frame" x="0.0" y="0.0" width="200" height="9.5"/>
+                                                                    <rect key="frame" x="0.0" y="0.0" width="200" height="10"/>
                                                                     <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                                     <nil key="textColor"/>
                                                                     <nil key="highlightedColor"/>
                                                                 </label>
                                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="OEY-lo-WHp">
-                                                                    <rect key="frame" x="0.0" y="9.5" width="200" height="50"/>
+                                                                    <rect key="frame" x="0.0" y="10" width="200" height="50"/>
                                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
                                                                     <color key="textColor" systemColor="secondaryLabelColor"/>
                                                                     <nil key="highlightedColor"/>
@@ -318,16 +318,16 @@
                                                             </subviews>
                                                         </stackView>
                                                         <stackView opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="vVe-gm-YYF">
-                                                            <rect key="frame" x="27.5" y="0.0" width="82" height="59.5"/>
+                                                            <rect key="frame" x="27.5" y="0.0" width="82" height="60"/>
                                                             <subviews>
                                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="g Total" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="d3X-AN-tA5">
-                                                                    <rect key="frame" x="0.0" y="0.0" width="82" height="9.5"/>
+                                                                    <rect key="frame" x="0.0" y="0.0" width="82" height="10"/>
                                                                     <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                                     <nil key="textColor"/>
                                                                     <nil key="highlightedColor"/>
                                                                 </label>
                                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="2YJ-xx-nmh">
-                                                                    <rect key="frame" x="0.0" y="9.5" width="82" height="50"/>
+                                                                    <rect key="frame" x="0.0" y="10" width="82" height="50"/>
                                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
                                                                     <color key="textColor" systemColor="secondaryLabelColor"/>
                                                                     <nil key="highlightedColor"/>
@@ -356,7 +356,7 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="CarbEntryTableViewCell" rowHeight="66" id="R0n-uX-07P" customClass="CarbEntryTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="432.5" width="375" height="66"/>
+                                <rect key="frame" x="0.0" y="438" width="375" height="66"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="R0n-uX-07P" id="9An-oU-9y7">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
@@ -382,13 +382,13 @@
                                                             <rect key="frame" x="0.0" y="0.0" width="325" height="21.5"/>
                                                             <subviews>
                                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ufi-Kj-33k">
-                                                                    <rect key="frame" x="0.0" y="0.0" width="287.5" height="21.5"/>
+                                                                    <rect key="frame" x="0.0" y="0.0" width="281" height="21.5"/>
                                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                                                     <nil key="textColor"/>
                                                                     <nil key="highlightedColor"/>
                                                                 </label>
                                                                 <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" horizontalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aCb-Qs-bpu">
-                                                                    <rect key="frame" x="287.5" y="0.0" width="37.5" height="21.5"/>
+                                                                    <rect key="frame" x="281" y="0.0" width="44" height="21.5"/>
                                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                                                     <color key="textColor" systemColor="secondaryLabelColor"/>
                                                                     <nil key="highlightedColor"/>
@@ -399,13 +399,13 @@
                                                             <rect key="frame" x="0.0" y="25.5" width="325" height="21.5"/>
                                                             <subviews>
                                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Krd-Aa-ret">
-                                                                    <rect key="frame" x="0.0" y="0.0" width="287.5" height="21.5"/>
+                                                                    <rect key="frame" x="0.0" y="0.0" width="281" height="21.5"/>
                                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                                                     <color key="textColor" name="carbs"/>
                                                                     <nil key="highlightedColor"/>
                                                                 </label>
                                                                 <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" horizontalHuggingPriority="251" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J7x-W5-gwo">
-                                                                    <rect key="frame" x="287.5" y="0.0" width="37.5" height="21.5"/>
+                                                                    <rect key="frame" x="281" y="0.0" width="44" height="21.5"/>
                                                                     <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                                                     <color key="textColor" name="carbs"/>
                                                                     <nil key="highlightedColor"/>
@@ -478,7 +478,7 @@
                         <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <prototypes>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="HUDViewTableViewCell" rowHeight="70" id="vCp-19-ZkW" customClass="HUDViewTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="44.5" width="375" height="70"/>
+                                <rect key="frame" x="0.0" y="50" width="375" height="70"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vCp-19-ZkW" id="b8U-Fn-hSd">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="70"/>
@@ -500,7 +500,7 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="TitleSubtitleTableViewCell" id="zTq-QB-XNu" customClass="TitleSubtitleTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="114.5" width="375" height="44"/>
+                                <rect key="frame" x="0.0" y="120" width="375" height="44"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zTq-QB-XNu" id="vD6-31-qVz">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
@@ -545,7 +545,7 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="IconTitleSubtitleTableViewCell" id="5av-st-q28" customClass="IconTitleSubtitleTableViewCell" customModule="Loop" customModuleProvider="target">
-                                <rect key="frame" x="0.0" y="158.5" width="375" height="44"/>
+                                <rect key="frame" x="0.0" y="164" width="375" height="44"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5av-st-q28" id="lLV-fl-2Ke">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
@@ -597,7 +597,7 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="ChartTableViewCell" rowHeight="200" id="FEV-fX-i48" customClass="ChartTableViewCell" customModule="LoopKitUI">
-                                <rect key="frame" x="0.0" y="202.5" width="375" height="200"/>
+                                <rect key="frame" x="0.0" y="208" width="375" height="200"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="FEV-fX-i48" id="lS6-Qa-Lw7">
                                     <rect key="frame" x="0.0" y="0.0" width="375" height="200"/>
@@ -654,29 +654,7 @@
                             <outlet property="delegate" destination="1zR-tC-i50" id="OUg-z9-1ra"/>
                         </connections>
                     </tableView>
-                    <toolbarItems>
-                        <barButtonItem image="carbs" id="lpE-RX-jWF">
-                            <connections>
-                                <action selector="userTappedAddCarbs" destination="1zR-tC-i50" id="0dT-DJ-c5F"/>
-                            </connections>
-                        </barButtonItem>
-                        <barButtonItem style="plain" systemItem="flexibleSpace" id="g6k-L0-2qh"/>
-                        <barButtonItem enabled="NO" image="Pre-Meal" id="jdk-2o-ydO"/>
-                        <barButtonItem style="plain" systemItem="flexibleSpace" id="ava-EZ-v6i"/>
-                        <barButtonItem image="bolus" id="2kb-DB-Vag">
-                            <connections>
-                                <action selector="presentBolusScreen" destination="1zR-tC-i50" id="1G2-8L-uGt"/>
-                            </connections>
-                        </barButtonItem>
-                        <barButtonItem style="plain" systemItem="flexibleSpace" id="p68-fH-iuk"/>
-                        <barButtonItem enabled="NO" image="workout" id="8Qz-Cj-oVB"/>
-                        <barButtonItem style="plain" systemItem="flexibleSpace" id="d5h-bj-8ek"/>
-                        <barButtonItem image="settings" id="PHJ-4n-qiF">
-                            <connections>
-                                <action selector="onSettingsTapped:" destination="1zR-tC-i50" id="eJt-wB-R9Z"/>
-                            </connections>
-                        </barButtonItem>
-                    </toolbarItems>
+                    <toolbarItems/>
                     <navigationItem key="navigationItem" title="Status" id="3kU-n2-fha"/>
                     <simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
                     <connections>
@@ -713,7 +691,7 @@
                 <viewControllerPlaceholder storyboardName="OverrideSelectionViewController" bundleIdentifier="com.loopkit.LoopKitUI" id="n4Q-tf-UqN" sceneMemberID="viewController"/>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="bU3-Ra-HmR" userLabel="First Responder" sceneMemberID="firstResponder"/>
             </objects>
-            <point key="canvasLocation" x="1146" y="-49"/>
+            <point key="canvasLocation" x="838" y="79"/>
         </scene>
         <!--Add/Edit Carb Entry-->
         <scene sceneID="ie7-1g-0ay">
@@ -724,26 +702,26 @@
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <prototypes>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="DecimalTextFieldTableViewCell" id="zy0-gK-nts" customClass="DecimalTextFieldTableViewCell" customModule="LoopKitUI">
-                                <rect key="frame" x="16" y="49.5" width="343" height="44"/>
+                                <rect key="frame" x="16" y="55.5" width="343" height="44"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="zy0-gK-nts" id="xJK-Hq-Xwl">
                                     <rect key="frame" x="0.0" y="0.0" width="343" height="44"/>
                                     <autoresizingMask key="autoresizingMask"/>
                                     <subviews>
                                         <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="0" textAlignment="right" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Yf6-fw-Gex">
-                                            <rect key="frame" x="148" y="15" width="168.5" height="14"/>
+                                            <rect key="frame" x="171" y="15" width="144" height="14"/>
                                             <color key="textColor" systemColor="secondaryLabelColor"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <textInputTraits key="textInputTraits" keyboardType="decimalPad" returnKeyType="next"/>
                                         </textField>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="g" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0RV-d5-muE">
-                                            <rect key="frame" x="318.5" y="9" width="8.5" height="17"/>
+                                            <rect key="frame" x="317" y="4" width="10" height="20.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <color key="textColor" systemColor="secondaryLabelColor"/>
                                             <nil key="highlightedColor"/>
                                         </label>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Amount Consumed" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wx8-Tf-FnG">
-                                            <rect key="frame" x="16" y="13.5" width="124" height="17"/>
+                                            <rect key="frame" x="16" y="12" width="147" height="20.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <nil key="textColor"/>
                                             <nil key="highlightedColor"/>
@@ -767,20 +745,20 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TextFieldTableViewCell" id="vYF-Gy-b4w" customClass="TextFieldTableViewCell" customModule="LoopKitUI">
-                                <rect key="frame" x="16" y="93.5" width="343" height="44"/>
+                                <rect key="frame" x="16" y="99.5" width="343" height="44"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vYF-Gy-b4w" id="8uH-nf-jdg">
                                     <rect key="frame" x="0.0" y="0.0" width="343" height="44"/>
                                     <autoresizingMask key="autoresizingMask"/>
                                     <subviews>
                                         <textField opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="right" minimumFontSize="15" translatesAutoresizingMaskIntoConstraints="NO" id="bSR-8J-y14" customClass="CustomInputTextField" customModule="LoopKitUI">
-                                            <rect key="frame" x="92" y="10" width="235" height="22"/>
+                                            <rect key="frame" x="104.5" y="8" width="222.5" height="25.5"/>
                                             <color key="textColor" systemColor="secondaryLabelColor"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleTitle3"/>
                                             <textInputTraits key="textInputTraits" returnKeyType="next"/>
                                         </textField>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Food Type" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qPH-vU-xlu">
-                                            <rect key="frame" x="16" y="13.5" width="68" height="17"/>
+                                            <rect key="frame" x="16" y="12" width="80.5" height="20.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <nil key="textColor"/>
                                             <nil key="highlightedColor"/>
@@ -799,7 +777,7 @@
                                 </connections>
                             </tableViewCell>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="FoodTypeShortcutCell" id="82i-wy-6Rq" customClass="FoodTypeShortcutCell" customModule="LoopKitUI">
-                                <rect key="frame" x="16" y="137.5" width="343" height="44"/>
+                                <rect key="frame" x="16" y="143.5" width="343" height="44"/>
                                 <autoresizingMask key="autoresizingMask"/>
                                 <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="82i-wy-6Rq" id="qXY-LI-Wdv">
                                     <rect key="frame" x="0.0" y="0.0" width="343" height="44"/>
@@ -870,7 +848,7 @@
                                             </constraints>
                                         </stackView>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Food Type" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ap1-M6-naG">
-                                            <rect key="frame" x="16" y="13.5" width="68" height="17"/>
+                                            <rect key="frame" x="16" y="12" width="80.5" height="20.5"/>
                                             <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
                                             <nil key="textColor"/>
                                             <nil key="highlightedColor"/>
@@ -912,12 +890,7 @@
     </scenes>
     <resources>
         <image name="Oval Selection" width="21" height="21"/>
-        <image name="Pre-Meal" width="29" height="29"/>
-        <image name="bolus" width="22" height="24"/>
-        <image name="carbs" width="29" height="29"/>
-        <image name="chevron.right" catalog="system" width="96" height="128"/>
-        <image name="settings" width="25" height="40"/>
-        <image name="workout" width="30" height="29"/>
+        <image name="chevron.right" catalog="system" width="97" height="128"/>
         <namedColor name="carbs">
             <color red="0.3880000114440918" green="0.85500001907348633" blue="0.2199999988079071" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </namedColor>
diff --git a/Loop/Managers/AlertMuter.swift b/Loop/Managers/AlertMuter.swift
index 78c4ec877..4f47445ee 100644
--- a/Loop/Managers/AlertMuter.swift
+++ b/Loop/Managers/AlertMuter.swift
@@ -54,12 +54,12 @@ public class AlertMuter: ObservableObject {
         }
 
         func shouldMuteAlert(scheduledAt timeFromNow: TimeInterval = 0, now: Date = Date()) -> Bool {
-            guard timeFromNow >= 0 else { return false }
-
             guard let mutingEndTime = mutingEndTime else { return false }
 
             let alertTriggerTime = now.advanced(by: timeFromNow)
-            guard alertTriggerTime < mutingEndTime
+            guard let startTime = startTime,
+                  alertTriggerTime >= startTime,
+                  alertTriggerTime < mutingEndTime
             else { return false }
 
             return true
@@ -125,4 +125,16 @@ public class AlertMuter: ObservableObject {
             return shouldMuteAlert(scheduledAt: triggerInterval)
         }
     }
+
+    func unmuteAlerts() {
+        configuration.startTime = nil
+    }
+
+    var formattedEndTime: String {
+        guard let endTime = configuration.mutingEndTime else { return NSLocalizedString("Unknown", comment: "result when time cannot be formatted") }
+        let formatter = DateFormatter()
+        formatter.timeStyle = .short
+        formatter.dateStyle = .none
+        return formatter.string(from: endTime)
+    }
 }
diff --git a/Loop/Managers/Alerts/AlertManager.swift b/Loop/Managers/Alerts/AlertManager.swift
index 2c41a2180..54d52dc21 100644
--- a/Loop/Managers/Alerts/AlertManager.swift
+++ b/Loop/Managers/Alerts/AlertManager.swift
@@ -181,7 +181,7 @@ public final class AlertManager {
 
         for (minutes, isCritical) in [(20.0, false), (40.0, false), (60.0, true), (120.0, true)] {
             let warningInterval = TimeInterval(minutes: minutes)
-            let timeUntilNotification = lastLoopDate.addingTimeInterval(.minutes(minutes)).timeIntervalSinceNow
+            let timeUntilNotification = lastLoopDate.addingTimeInterval(warningInterval).timeIntervalSinceNow
             guard timeUntilNotification >= 0 else { break }
 
             let formatter = DateComponentsFormatter()
@@ -227,7 +227,6 @@ public final class AlertManager {
                     alertAt: nextTriggerDate,
                     title: notificationContent.title,
                     body: notificationContent.body,
-                    timeInterval: warningInterval,
                     isCritical: isCritical)
                 scheduledNotifications.append(scheduledNotification)
             }
@@ -784,6 +783,27 @@ extension AlertManager: AlertPermissionsCheckerDelegate {
     }
 }
 
+extension AlertManager {
+    func presentConfirmCrashAlert(confirmAction: @escaping (@escaping () -> Void) -> Void) {
+        let alert = UIAlertController(title: "New Study Product Detected", message: "We've detected a new study product is selected. In order to show use this study product, Loop will need to restart.", preferredStyle: .alert)
+        alert.addAction(UIAlertAction(title: "Confirm", style: .default, handler: { _ in
+            confirmAction() {
+                fatalError("DEBUG: Resetting Loop")
+            }
+        }))
+        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
+        
+        alertPresenter.present(alert, animated: true)
+    }
+    
+    func presentCouldNotResetLoopAlert(error: Error) {
+        let alert = UIAlertController(title: "Could Not Restart Loop", message: "While trying to restart Loop an error occured.\n\n\(error.localizedDescription)", preferredStyle: .alert)
+        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
+        
+        alertPresenter.present(alert, animated: true)
+    }
+}
+
 fileprivate extension UserDefaults {
     private enum Key: String {
         case hasIssuedNotificationPermissionsAlert = "com.loopkit.Loop.HasIssuedNotificationPermissionsAlert"
diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift
index 995bd52f4..4cfae7046 100644
--- a/Loop/Managers/DeviceDataManager.swift
+++ b/Loop/Managers/DeviceDataManager.swift
@@ -47,7 +47,7 @@ final class DeviceDataManager {
 
     @Published var pumpIsAllowingAutomation: Bool
 
-    private let closedLoopStatus: ClosedLoopStatus
+    private let automaticDosingStatus: AutomaticDosingStatus
 
     var closedLoopDisallowedLocalizedDescription: String? {
         if !cgmHasValidSensorSession {
@@ -249,7 +249,7 @@ final class DeviceDataManager {
          analyticsServicesManager: AnalyticsServicesManager,
          bluetoothProvider: BluetoothProvider,
          alertPresenter: AlertPresenter,
-         closedLoopStatus: ClosedLoopStatus,
+         automaticDosingStatus: AutomaticDosingStatus,
          cacheStore: PersistenceController,
          localCacheDuration: TimeInterval,
          overrideHistory: TemporaryScheduleOverrideHistory,
@@ -333,7 +333,7 @@ final class DeviceDataManager {
         
         self.cgmHasValidSensorSession = false
         self.pumpIsAllowingAutomation = true
-        self.closedLoopStatus = closedLoopStatus
+        self.automaticDosingStatus = automaticDosingStatus
 
         // HealthStorePreferredGlucoseUnitDidChange will be notified once the user completes the health access form. Set to .milligramsPerDeciliter until then
         displayGlucoseUnitObservable = DisplayGlucoseUnitObservable(displayGlucoseUnit: glucoseStore.preferredUnit ?? .milligramsPerDeciliter)
@@ -366,7 +366,7 @@ final class DeviceDataManager {
         }
 
         //TODO The instantiation of these non-device related managers should be moved to LoopAppManager, and then LoopAppManager can wire up the connections between them.
-        statusExtensionManager = ExtensionDataManager(deviceDataManager: self, closedLoopStatus: closedLoopStatus)
+        statusExtensionManager = ExtensionDataManager(deviceDataManager: self, automaticDosingStatus: automaticDosingStatus)
 
         loopManager = LoopDataManager(
             lastLoopCompleted: ExtensionDataManager.lastLoopCompleted,
@@ -381,7 +381,7 @@ final class DeviceDataManager {
             dosingDecisionStore: dosingDecisionStore,
             latestStoredSettingsProvider: settingsManager,
             pumpInsulinType: pumpManager?.status.insulinType,
-            automaticDosingStatus: closedLoopStatus,
+            automaticDosingStatus: automaticDosingStatus,
             trustedTimeOffset: { trustedTimeChecker.detectedSystemTimeOffset }
         )
         cacheStore.delegate = loopManager
@@ -441,7 +441,7 @@ final class DeviceDataManager {
             .map { $0 && $1 }
             .receive(on: RunLoop.main)
             .removeDuplicates()
-            .assign(to: \.closedLoopStatus.isClosedLoopAllowed, on: self)
+            .assign(to: \.automaticDosingStatus.isAutomaticDosingAllowed, on: self)
             .store(in: &cancellables)
 
         NotificationCenter.default.addObserver(forName: .HealthStorePreferredGlucoseUnitDidChange, object: glucoseStore.healthStore, queue: nil) { [weak self] _ in
@@ -455,14 +455,13 @@ final class DeviceDataManager {
             }
         }
     }
-    
 
     var availablePumpManagers: [PumpManagerDescriptor] {
         return pluginManager.availablePumpManagers + availableStaticPumpManagers
     }
 
-    func setupPumpManager(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings) -> Swift.Result<SetupUIResult<PumpManagerViewController, PumpManager>, Error> {
-        switch setupPumpManagerUI(withIdentifier: identifier, initialSettings: settings) {
+    func setupPumpManager(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings, prefersToSkipUserInteraction: Bool) -> Swift.Result<SetupUIResult<PumpManagerViewController, PumpManager>, Error> {
+        switch setupPumpManagerUI(withIdentifier: identifier, initialSettings: settings, prefersToSkipUserInteraction: prefersToSkipUserInteraction) {
         case .failure(let error):
             return .failure(error)
         case .success(let success):
@@ -477,12 +476,12 @@ final class DeviceDataManager {
 
     struct UnknownPumpManagerIdentifierError: Error {}
 
-    func setupPumpManagerUI(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings) -> Swift.Result<SetupUIResult<PumpManagerViewController, PumpManagerUI>, Error> {
+    func setupPumpManagerUI(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings, prefersToSkipUserInteraction: Bool = false) -> Swift.Result<SetupUIResult<PumpManagerViewController, PumpManagerUI>, Error> {
         guard let pumpManagerUIType = pumpManagerTypeByIdentifier(identifier) else {
             return .failure(UnknownPumpManagerIdentifierError())
         }
 
-        let result = pumpManagerUIType.setupViewController(initialSettings: settings, bluetoothProvider: bluetoothProvider, colorPalette: .default, allowDebugFeatures: FeatureFlags.allowDebugFeatures, allowedInsulinTypes: allowedInsulinTypes)
+        let result = pumpManagerUIType.setupViewController(initialSettings: settings, bluetoothProvider: bluetoothProvider, colorPalette: .default, allowDebugFeatures: FeatureFlags.allowDebugFeatures, prefersToSkipUserInteraction: prefersToSkipUserInteraction, allowedInsulinTypes: allowedInsulinTypes)
         if case .createdAndOnboarded(let pumpManagerUI) = result {
             pumpManagerOnboarding(didCreatePumpManager: pumpManagerUI)
             pumpManagerOnboarding(didOnboardPumpManager: pumpManagerUI)
@@ -565,12 +564,12 @@ final class DeviceDataManager {
         return availableCGMManagers
     }
 
-    func setupCGMManager(withIdentifier identifier: String) -> Swift.Result<SetupUIResult<CGMManagerViewController, CGMManager>, Error> {
+    func setupCGMManager(withIdentifier identifier: String, prefersToSkipUserInteraction: Bool = false) -> Swift.Result<SetupUIResult<CGMManagerViewController, CGMManager>, Error> {
         if let cgmManager = setupCGMManagerFromPumpManager(withIdentifier: identifier) {
             return .success(.createdAndOnboarded(cgmManager))
         }
 
-        switch setupCGMManagerUI(withIdentifier: identifier) {
+        switch setupCGMManagerUI(withIdentifier: identifier, prefersToSkipUserInteraction: prefersToSkipUserInteraction) {
         case .failure(let error):
             return .failure(error)
         case .success(let success):
@@ -585,12 +584,12 @@ final class DeviceDataManager {
 
     struct UnknownCGMManagerIdentifierError: Error {}
 
-    fileprivate func setupCGMManagerUI(withIdentifier identifier: String) -> Swift.Result<SetupUIResult<CGMManagerViewController, CGMManagerUI>, Error> {
+    fileprivate func setupCGMManagerUI(withIdentifier identifier: String, prefersToSkipUserInteraction: Bool) -> Swift.Result<SetupUIResult<CGMManagerViewController, CGMManagerUI>, Error> {
         guard let cgmManagerUIType = cgmManagerTypeByIdentifier(identifier) else {
             return .failure(UnknownCGMManagerIdentifierError())
         }
 
-        let result = cgmManagerUIType.setupViewController(bluetoothProvider: bluetoothProvider, displayGlucoseUnitObservable: displayGlucoseUnitObservable, colorPalette: .default, allowDebugFeatures: FeatureFlags.allowDebugFeatures)
+        let result = cgmManagerUIType.setupViewController(bluetoothProvider: bluetoothProvider, displayGlucoseUnitObservable: displayGlucoseUnitObservable, colorPalette: .default, allowDebugFeatures: FeatureFlags.allowDebugFeatures, prefersToSkipUserInteraction: prefersToSkipUserInteraction)
         if case .createdAndOnboarded(let cgmManagerUI) = result {
             cgmManagerOnboarding(didCreateCGMManager: cgmManagerUI)
             cgmManagerOnboarding(didOnboardCGMManager: cgmManagerUI)
@@ -1111,8 +1110,6 @@ extension DeviceDataManager: PumpManagerDelegate {
     }
 
     func pumpManagerPumpWasReplaced(_ pumpManager: PumpManager) {
-        // PumpManagers should report a continuous dosing history, across pump changes
-        //doseStore.resetPumpData(completion: nil)
     }
     
     func pumpManagerWillDeactivate(_ pumpManager: PumpManager) {
@@ -1177,6 +1174,10 @@ extension DeviceDataManager: PumpManagerDelegate {
         dispatchPrecondition(condition: .onQueue(queue))
         return doseStore.pumpEventQueryAfterDate
     }
+
+    var automaticDosingEnabled: Bool {
+        automaticDosingStatus.automaticDosingEnabled
+    }
 }
 
 // MARK: - PumpManagerOnboardingDelegate
@@ -1261,9 +1262,8 @@ extension DeviceDataManager: InsulinDeliveryStoreDelegate {
 // MARK: - TestingPumpManager
 extension DeviceDataManager {
     func deleteTestingPumpData(completion: ((Error?) -> Void)? = nil) {
-
         guard let testingPumpManager = pumpManager as? TestingPumpManager else {
-            assertionFailure("\(#function) should be invoked only when a testing pump manager is in use")
+            completion?(nil)
             return
         }
 
@@ -1277,8 +1277,16 @@ extension DeviceDataManager {
                 return
             }
 
-            healthStore.deleteObjects(of: self.doseStore.sampleType, predicate: devicePredicate) { success, deletedObjectCount, error in
-                if success {
+            guard !self.doseStore.sharingDenied else {
+                // only clear cache since access to health kit is denied
+                insulinDeliveryStore.purgeCachedInsulinDeliveryObjects() { error in
+                    completion?(error)
+                }
+                return
+            }
+            
+            insulinDeliveryStore.purgeAllDoseEntries(healthKitPredicate: devicePredicate) { error in
+                if error == nil {
                     insulinDeliveryStore.test_lastImmutableBasalEndDate = nil
                 }
                 completion?(error)
@@ -1287,11 +1295,18 @@ extension DeviceDataManager {
     }
 
     func deleteTestingCGMData(completion: ((Error?) -> Void)? = nil) {
-        
         guard let testingCGMManager = cgmManager as? TestingCGMManager else {
             assertionFailure("\(#function) should be invoked only when a testing CGM manager is in use")
             return
         }
+        
+        guard !glucoseStore.sharingDenied else {
+            // only clear cache since access to health kit is denied
+            glucoseStore.purgeCachedGlucoseObjects() { error in
+                completion?(error)
+            }
+            return
+        }
 
         let predicate = HKQuery.predicateForObjects(from: [testingCGMManager.testingDevice])
         glucoseStore.purgeAllGlucoseSamples(healthKitPredicate: predicate) { error in
@@ -1315,7 +1330,7 @@ extension DeviceDataManager: LoopDataManagerDelegate {
             return units
         }
 
-        let rounded = ([0.0] + pumpManager.supportedBolusVolumes).enumerated().min( by: { abs($0.1 - units) < abs($1.1 - units) } )!.1
+        let rounded = pumpManager.roundToSupportedBolusVolume(units: units)
         self.log.default("Rounded %{public}@ to %{public}@", String(describing: units), String(describing: rounded))
 
         return rounded
diff --git a/Loop/Managers/ExtensionDataManager.swift b/Loop/Managers/ExtensionDataManager.swift
index d66076652..f7b52c09c 100644
--- a/Loop/Managers/ExtensionDataManager.swift
+++ b/Loop/Managers/ExtensionDataManager.swift
@@ -13,13 +13,13 @@ import LoopKit
 
 final class ExtensionDataManager {
     unowned let deviceManager: DeviceDataManager
-    private let closedLoopStatus: ClosedLoopStatus
+    private let automaticDosingStatus: AutomaticDosingStatus
 
     init(deviceDataManager: DeviceDataManager,
-         closedLoopStatus: ClosedLoopStatus)
+         automaticDosingStatus: AutomaticDosingStatus)
     {
         self.deviceManager = deviceDataManager
-        self.closedLoopStatus = closedLoopStatus
+        self.automaticDosingStatus = automaticDosingStatus
 
         NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived(_:)), name: .LoopDataUpdated, object: deviceDataManager.loopManager)
         NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived(_:)), name: .PumpManagerChanged, object: nil)
@@ -119,7 +119,7 @@ final class ExtensionDataManager {
 
             context.lastLoopCompleted = lastLoopCompleted
             
-            context.isClosedLoop = self.closedLoopStatus.isClosedLoop
+            context.isClosedLoop = self.automaticDosingStatus.automaticDosingEnabled
 
             // Drop the first element in predictedGlucose because it is the currentGlucose
             // and will have a different interval to the next element
diff --git a/Loop/Managers/LocalTestingScenariosManager.swift b/Loop/Managers/LocalTestingScenariosManager.swift
index 1f029c299..da75d392c 100644
--- a/Loop/Managers/LocalTestingScenariosManager.swift
+++ b/Loop/Managers/LocalTestingScenariosManager.swift
@@ -30,6 +30,10 @@ final class LocalTestingScenariosManager: TestingScenariosManagerRequirements, D
             delegate?.testingScenariosManager(self, didUpdateScenarioURLs: scenarioURLs)
         }
     }
+    
+    var pluginManager: PluginManager {
+        deviceManager.pluginManager
+    }
 
     init(deviceManager: DeviceDataManager) {
         guard FeatureFlags.scenariosEnabled else {
@@ -37,10 +41,9 @@ final class LocalTestingScenariosManager: TestingScenariosManagerRequirements, D
         }
 
         self.deviceManager = deviceManager
-        let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
-        self.scenariosSource = documentsDirectory.appendingPathComponent("scenarios")
+        self.scenariosSource = Bundle.main.bundleURL.appendingPathComponent("Scenarios")
 
-        log.debug("Place testing scenarios in %{public}@", scenariosSource.path)
+        log.debug("Loading testing scenarios from %{public}@", scenariosSource.path)
         if !fileManager.fileExists(atPath: scenariosSource.path) {
             do {
                 try fileManager.createDirectory(at: scenariosSource, withIntermediateDirectories: false)
@@ -64,7 +67,6 @@ final class LocalTestingScenariosManager: TestingScenariosManagerRequirements, D
         do {
             let scenarioURLs = try fileManager.contentsOfDirectory(at: scenariosSource, includingPropertiesForKeys: nil)
                 .filter { $0.pathExtension == "json" }
-                .sorted(by: { $0.lastPathComponent < $1.lastPathComponent })
             self.scenarioURLs = scenarioURLs
             delegate?.testingScenariosManager(self, didUpdateScenarioURLs: scenarioURLs)
             log.debug("Reloaded scenario URLs")
diff --git a/Loop/Managers/LoopAppManager.swift b/Loop/Managers/LoopAppManager.swift
index 6a160790a..dca1d430d 100644
--- a/Loop/Managers/LoopAppManager.swift
+++ b/Loop/Managers/LoopAppManager.swift
@@ -89,7 +89,7 @@ class LoopAppManager: NSObject {
     private let log = DiagnosticLog(category: "LoopAppManager")
     private let widgetLog = DiagnosticLog(category: "LoopWidgets")
 
-    private let closedLoopStatus = ClosedLoopStatus(isClosedLoop: false, isClosedLoopAllowed: false)
+    private let automaticDosingStatus = AutomaticDosingStatus(automaticDosingEnabled: false, isAutomaticDosingAllowed: false)
 
     lazy private var cancellables = Set<AnyCancellable>()
 
@@ -198,7 +198,7 @@ class LoopAppManager: NSObject {
                                               analyticsServicesManager: analyticsServicesManager,
                                               bluetoothProvider: bluetoothStateManager,
                                               alertPresenter: self,
-                                              closedLoopStatus: closedLoopStatus,
+                                              automaticDosingStatus: automaticDosingStatus,
                                               cacheStore: cacheStore,
                                               localCacheDuration: localCacheDuration,
                                               overrideHistory: overrideHistory,
@@ -237,10 +237,10 @@ class LoopAppManager: NSObject {
                                         servicesManager: deviceDataManager.servicesManager,
                                         alertIssuer: alertManager)
 
-        closedLoopStatus.$isClosedLoopAllowed
+        automaticDosingStatus.$isAutomaticDosingAllowed
             .combineLatest(deviceDataManager.loopManager.$dosingEnabled)
             .map { $0 && $1 }
-            .assign(to: \.closedLoopStatus.isClosedLoop, on: self)
+            .assign(to: \.automaticDosingStatus.automaticDosingEnabled, on: self)
             .store(in: &cancellables)
 
         state = state.next
@@ -266,7 +266,7 @@ class LoopAppManager: NSObject {
         let statusTableViewController = storyboard.instantiateViewController(withIdentifier: "MainStatusViewController") as! StatusTableViewController
         statusTableViewController.alertPermissionsChecker = alertPermissionsChecker
         statusTableViewController.alertMuter = alertManager.alertMuter
-        statusTableViewController.closedLoopStatus = closedLoopStatus
+        statusTableViewController.automaticDosingStatus = automaticDosingStatus
         statusTableViewController.deviceManager = deviceDataManager
         statusTableViewController.onboardingManager = onboardingManager
         statusTableViewController.supportManager = supportManager
@@ -397,6 +397,30 @@ class LoopAppManager: NSObject {
         }
         return false
     }
+    
+    func askUserToConfirmCrashIfNecessary() {
+        deviceDataManager.pluginManager.availableSupports.forEach { supportUI in
+            if supportUI.loopNeedsReset {
+                supportUI.loopNeedsReset = false
+                alertManager.presentConfirmCrashAlert() { [weak self] completion in
+                    guard let pumpManager = self?.deviceDataManager.pumpManager else {
+                        supportUI.resetLoop()
+                        completion()
+                        return
+                    }
+                    
+                    pumpManager.prepareForDeactivation() { [weak self] error in
+                        guard let error = error else {
+                            supportUI.resetLoop()
+                            completion()
+                            return
+                        }
+                        self?.alertManager.presentCouldNotResetLoopAlert(error: error)
+                    }
+                }
+            }
+        }
+    }
 
     private var rootViewController: UIViewController? {
         get { windowProvider?.window?.rootViewController }
diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift
index 18a081662..ffc66ee31 100644
--- a/Loop/Managers/LoopDataManager.swift
+++ b/Loop/Managers/LoopDataManager.swift
@@ -208,7 +208,7 @@ final class LoopDataManager {
         // Turn off preMeal when going into closed loop off mode
         // Cancel any active temp basal when going into closed loop off mode
         // The dispatch is necessary in case this is coming from a didSet already on the settings struct.
-        self.automaticDosingStatus.$isClosedLoop
+        self.automaticDosingStatus.$automaticDosingEnabled
             .removeDuplicates()
             .dropFirst()
             .receive(on: DispatchQueue.main)
@@ -216,7 +216,7 @@ final class LoopDataManager {
                 self.mutateSettings { settings in
                     settings.clearOverride(matching: .preMeal)
                 }
-                self.cancelActiveTempBasal(for: .closedLoopDisabled)
+                self.cancelActiveTempBasal(for: .automaticDosingDisabled)
             } }
             .store(in: &cancellables)
     }
@@ -593,7 +593,7 @@ extension LoopDataManager {
     }
 
     private enum CancelActiveTempBasalReason: String {
-        case closedLoopDisabled
+        case automaticDosingDisabled
         case unreliableCGMData
         case maximumBasalRateChanged
     }
@@ -851,7 +851,7 @@ extension LoopDataManager {
 
             var (dosingDecision, error) = self.update(for: .loop)
 
-            if error == nil, self.automaticDosingStatus.isClosedLoop == true {
+            if error == nil, self.automaticDosingStatus.automaticDosingEnabled == true {
                 error = self.enactRecommendedAutomaticDose()
             } else {
                 self.logger.default("Not adjusting dosing during open loop.")
@@ -874,26 +874,28 @@ extension LoopDataManager {
         logger.default("Loop ended")
         notify(forChange: .loopFinished)
 
-        let carbEffectStart = now().addingTimeInterval(-MissedMealSettings.maxRecency)
-        carbStore.getGlucoseEffects(start: carbEffectStart, end: now(), effectVelocities: insulinCounteractionEffects) {[weak self] result in
-            guard
-                let self = self,
-                case .success((_, let carbEffects)) = result
-            else {
-                if case .failure(let error) = result {
-                    self?.logger.error("Failed to fetch glucose effects to check for missed meal: %{public}@", String(describing: error))
+        if FeatureFlags.missedMealNotifications {
+            let carbEffectStart = now().addingTimeInterval(-MissedMealSettings.maxRecency)
+            carbStore.getGlucoseEffects(start: carbEffectStart, end: now(), effectVelocities: insulinCounteractionEffects) {[weak self] result in
+                guard
+                    let self = self,
+                    case .success((_, let carbEffects)) = result
+                else {
+                    if case .failure(let error) = result {
+                        self?.logger.error("Failed to fetch glucose effects to check for missed meal: %{public}@", String(describing: error))
+                    }
+                    return
                 }
-                return
+                
+                self.mealDetectionManager.generateMissedMealNotificationIfNeeded(
+                    insulinCounteractionEffects: self.insulinCounteractionEffects,
+                    carbEffects: carbEffects,
+                    pendingAutobolusUnits: self.recommendedAutomaticDose?.recommendation.bolusUnits,
+                    bolusDurationEstimator: { [unowned self] bolusAmount in
+                        return self.delegate?.loopDataManager(self, estimateBolusDuration: bolusAmount)
+                    }
+                )
             }
-            
-            self.mealDetectionManager.generateMissedMealNotificationIfNeeded(
-                insulinCounteractionEffects: self.insulinCounteractionEffects,
-                carbEffects: carbEffects,
-                pendingAutobolusUnits: self.recommendedAutomaticDose?.recommendation.bolusUnits,
-                bolusDurationEstimator: { [unowned self] bolusAmount in
-                    return self.delegate?.loopDataManager(self, estimateBolusDuration: bolusAmount)
-                }
-            )
         }
 
         // 5 second delay to allow stores to cache data before it is read by widget
diff --git a/Loop/Managers/OnboardingManager.swift b/Loop/Managers/OnboardingManager.swift
index 2abc7bc88..d82c3e531 100644
--- a/Loop/Managers/OnboardingManager.swift
+++ b/Loop/Managers/OnboardingManager.swift
@@ -340,9 +340,9 @@ extension OnboardingManager: CGMManagerProvider {
         return cgmManagerType.onboardingImage
     }
 
-    func onboardCGMManager(withIdentifier identifier: String) -> Swift.Result<OnboardingResult<CGMManagerViewController, CGMManager>, Error> {
+    func onboardCGMManager(withIdentifier identifier: String, prefersToSkipUserInteraction: Bool) -> Swift.Result<OnboardingResult<CGMManagerViewController, CGMManager>, Error> {
         guard let cgmManager = deviceDataManager.cgmManager else {
-            return deviceDataManager.setupCGMManager(withIdentifier: identifier)
+            return deviceDataManager.setupCGMManager(withIdentifier: identifier, prefersToSkipUserInteraction: prefersToSkipUserInteraction)
         }
         guard cgmManager.managerIdentifier == identifier else {
             return .failure(OnboardingError.invalidState)
@@ -384,9 +384,9 @@ extension OnboardingManager: PumpManagerProvider {
                                        maximumBasalScheduleEntryCount: pumpManagerType.onboardingMaximumBasalScheduleEntryCount)
     }
 
-    func onboardPumpManager(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings) -> Swift.Result<OnboardingResult<PumpManagerViewController, PumpManager>, Error> {
+    func onboardPumpManager(withIdentifier identifier: String, initialSettings settings: PumpManagerSetupSettings, prefersToSkipUserInteraction: Bool) -> Swift.Result<OnboardingResult<PumpManagerViewController, PumpManager>, Error> {
         guard let pumpManager = deviceDataManager.pumpManager else {
-            return deviceDataManager.setupPumpManager(withIdentifier: identifier, initialSettings: settings)
+            return deviceDataManager.setupPumpManager(withIdentifier: identifier, initialSettings: settings, prefersToSkipUserInteraction: prefersToSkipUserInteraction)
         }
         guard pumpManager.managerIdentifier == identifier else {
             return .failure(OnboardingError.invalidState)
@@ -437,6 +437,12 @@ extension OnboardingManager: OnboardingProvider {
     var allowDebugFeatures: Bool { FeatureFlags.allowDebugFeatures }   // NOTE: DEBUG FEATURES - DEBUG AND TEST ONLY
 }
 
+// MARK: - SupportProvider
+
+extension OnboardingManager: SupportProvider {
+    var availableSupports: [SupportUI] { deviceDataManager.pluginManager.availableSupports }
+}
+
 // MARK: - OnboardingUI
 
 fileprivate extension OnboardingUI {
diff --git a/Loop/Managers/Store Protocols/DoseStoreProtocol.swift b/Loop/Managers/Store Protocols/DoseStoreProtocol.swift
index b330efb4c..478cc64d0 100644
--- a/Loop/Managers/Store Protocols/DoseStoreProtocol.swift	
+++ b/Loop/Managers/Store Protocols/DoseStoreProtocol.swift	
@@ -42,8 +42,6 @@ protocol DoseStoreProtocol: AnyObject {
     var pumpEventQueryAfterDate: Date { get }
     
     // MARK: dose management
-    func resetPumpData(completion: ((_ error: DoseStore.DoseStoreError?) -> Void)?)
-    
     func addPumpEvents(_ events: [NewPumpEvent], lastReconciliation: Date?, completion: @escaping (_ error: DoseStore.DoseStoreError?) -> Void)
     
     func addReservoirValue(_ unitVolume: Double, at date: Date, completion: @escaping (_ value: ReservoirValue?, _ previousValue: ReservoirValue?, _ areStoredValuesContinuous: Bool, _ error: DoseStore.DoseStoreError?) -> Void)
diff --git a/Loop/Managers/SupportManager.swift b/Loop/Managers/SupportManager.swift
index 356f00889..37250a24a 100644
--- a/Loop/Managers/SupportManager.swift
+++ b/Loop/Managers/SupportManager.swift
@@ -103,8 +103,9 @@ extension SupportManager {
 // MARK: Version checking
 extension SupportManager {
     func performCheck() {
-        checkVersion { [weak self] versionUpdate in
-            self?.notify(versionUpdate)
+        Task { @MainActor in
+            let versionUpdate = await checkVersion()
+            self.notify(versionUpdate)
         }
     }
     
@@ -114,37 +115,41 @@ extension SupportManager {
         }
     }
         
-    func checkVersion(completion: @escaping (VersionUpdate) -> Void) {
-        let group = DispatchGroup()
-        var results = [String: Result<VersionUpdate?, Error>]()
-        supports.value.values.forEach { support in
-            group.enter()
-            support.checkVersion(bundleIdentifier: Bundle.main.bundleIdentifier!, currentVersion: Bundle.main.shortVersionString) { result in
-                results[support.identifier] = result
-                group.leave()
+    func checkVersion() async -> VersionUpdate {
+
+        let results = await withTaskGroup(of: (VersionUpdate?,String).self) { group in
+            var updatesFromServices = [(VersionUpdate?,String)]()
+
+            supports.value.values.forEach { support in
+                group.addTask {
+                    return (await support.checkVersion(bundleIdentifier: Bundle.main.bundleIdentifier!, currentVersion: Bundle.main.shortVersionString), support.identifier)
+                }
             }
+
+            for await update in group {
+                updatesFromServices.append(update)
+            }
+
+            return updatesFromServices
         }
-        group.notify(queue: DispatchQueue.main) { [weak self] in
-            guard let self = self else { return }
-            self.saveState()
-            let (identifierWithHighestVersionUpdate, aggregatedVersionUpdate) = self.aggregate(results: results)
-            self.identifierWithHighestVersionUpdate = identifierWithHighestVersionUpdate
-            completion(aggregatedVersionUpdate)
-        }
+
+        self.saveState()
+        let (identifierWithHighestVersionUpdate, aggregatedVersionUpdate) = self.aggregate(results: results)
+        self.identifierWithHighestVersionUpdate = identifierWithHighestVersionUpdate
+        return aggregatedVersionUpdate
     }
 
-    private func aggregate(results: [String : Result<VersionUpdate?, Error>]) -> (String?, VersionUpdate) {
+    private func aggregate(results: [(VersionUpdate?,String)]) -> (String?, VersionUpdate) {
         var aggregatedVersionUpdate = VersionUpdate.default
         var identifierWithHighestVersionUpdate: String?
-        results.forEach { key, value in
-            switch value {
-            case .failure(let error):
-                self.log.error("Error from version check %{public}@: %{public}@", key, error.localizedDescription)
-            case .success(let versionUpdate):
-                if let versionUpdate = versionUpdate, versionUpdate > aggregatedVersionUpdate {
+        results.forEach { versionUpdate, identifier in
+            if let versionUpdate {
+                if versionUpdate > aggregatedVersionUpdate {
                     aggregatedVersionUpdate = versionUpdate
-                    identifierWithHighestVersionUpdate = key
+                    identifierWithHighestVersionUpdate = identifier
                 }
+            } else {
+                self.log.error("Version check failed for %{public}@", identifier)
             }
         }
         return (identifierWithHighestVersionUpdate, aggregatedVersionUpdate)
@@ -225,8 +230,8 @@ extension SupportManager {
 fileprivate extension Result where Success == VersionUpdate? {
     var value: VersionUpdate {
         switch self {
-        case .failure: return .none
-        case .success(let val): return val ?? .none
+        case .failure: return .noUpdateNeeded
+        case .success(let val): return val ?? .noUpdateNeeded
         }
     }
 }
diff --git a/Loop/Managers/TestingScenariosManager.swift b/Loop/Managers/TestingScenariosManager.swift
index 526662348..51a8c3bfb 100644
--- a/Loop/Managers/TestingScenariosManager.swift
+++ b/Loop/Managers/TestingScenariosManager.swift
@@ -8,7 +8,7 @@
 
 import LoopKit
 import LoopTestingKit
-
+import LoopKitUI
 
 protocol TestingScenariosManagerDelegate: AnyObject {
     func testingScenariosManager(_ manager: TestingScenariosManager, didUpdateScenarioURLs scenarioURLs: [URL])
@@ -18,6 +18,7 @@ protocol TestingScenariosManager: AnyObject {
     var delegate: TestingScenariosManagerDelegate? { get set }
     var activeScenarioURL: URL? { get }
     var scenarioURLs: [URL] { get }
+    var pluginManager: PluginManager { get }
     func loadScenario(from url: URL, completion: @escaping (Error?) -> Void)
     func loadScenario(from url: URL, advancedByLoopIterations iterations: Int, completion: @escaping (Error?) -> Void)
     func loadScenario(from url: URL, rewoundByLoopIterations iterations: Int, completion: @escaping (Error?) -> Void)
@@ -96,12 +97,15 @@ extension TestingScenariosManagerRequirements {
 // MARK: - Implementation details
 
 private enum ScenarioLoadingError: LocalizedError {
-    case noTestingManagersEnabled
+    case noTestingCGMManagerEnabled
+    case noTestingPumpManagerEnabled
 
     var errorDescription: String? {
         switch self {
-        case .noTestingManagersEnabled:
-            return "Testing pump and CGM managers must be enabled to load scenarios"
+        case .noTestingCGMManagerEnabled:
+            return "Testing CGM manager must be enabled to load CGM scenarios"
+        case .noTestingPumpManagerEnabled:
+            return "Testing pump manager must be enabled to load pump scenarios"
         }
     }
 }
@@ -186,13 +190,36 @@ extension TestingScenariosManagerRequirements {
             log.error("%{public}@", String(describing: error))
             completion(error)
         }
-
-        guard
-            let pumpManager = deviceManager.pumpManager as? TestingPumpManager,
-            let cgmManager = deviceManager.cgmManager as? TestingCGMManager
-        else {
-            bail(with: ScenarioLoadingError.noTestingManagersEnabled)
-            return
+        
+        let instance = scenario.instantiate()
+        
+        var testingCGMManager: TestingCGMManager?
+        var testingPumpManager: TestingPumpManager?
+        
+        if instance.hasCGMData {
+            if let cgmManager = deviceManager.cgmManager as? TestingCGMManager {
+                if instance.shouldReloadManager?.cgm == true {
+                    testingCGMManager = reloadCGMManager(withIdentifier: cgmManager.managerIdentifier)
+                } else {
+                    testingCGMManager = cgmManager
+                }
+            } else {
+                bail(with: ScenarioLoadingError.noTestingCGMManagerEnabled)
+                return
+            }
+        }
+        
+        if instance.hasPumpData {
+            if let pumpManager = deviceManager.pumpManager as? TestingPumpManager {
+                if instance.shouldReloadManager?.pump == true {
+                    testingPumpManager = reloadPumpManager(withIdentifier: pumpManager.managerIdentifier)
+                } else {
+                    testingPumpManager = pumpManager
+                }
+            } else {
+                bail(with: ScenarioLoadingError.noTestingPumpManagerEnabled)
+                return
+            }
         }
 
         wipeExistingData { error in
@@ -201,14 +228,12 @@ extension TestingScenariosManagerRequirements {
                 return
             }
 
-            let instance = scenario.instantiate()
-
             self.deviceManager.carbStore.addCarbEntries(instance.carbEntries) { result in
                 switch result {
                 case .success(_):
-                    pumpManager.reservoirFillFraction = 1.0
-                    pumpManager.injectPumpEvents(instance.pumpEvents)
-                    cgmManager.injectGlucoseSamples(instance.glucoseSamples)
+                    testingPumpManager?.reservoirFillFraction = 1.0
+                    testingPumpManager?.injectPumpEvents(instance.pumpEvents)
+                    testingCGMManager?.injectGlucoseSamples(instance.pastGlucoseSamples, futureSamples: instance.futureGlucoseSamples)
                     self.activeScenario = scenario
                     completion(nil)
                 case .failure(let error):
@@ -216,13 +241,64 @@ extension TestingScenariosManagerRequirements {
                 }
             }
         }
+        
+        instance.deviceActions.forEach { [testingCGMManager, testingPumpManager] action in
+            if testingCGMManager?.managerIdentifier == action.managerIdentifier {
+                testingCGMManager?.trigger(action: action)
+            } else if testingPumpManager?.managerIdentifier == action.managerIdentifier {
+                testingPumpManager?.trigger(action: action)
+            }
+        }
+    }
+    
+    private func reloadPumpManager(withIdentifier pumpManagerIdentifier: String) -> TestingPumpManager {
+        deviceManager.pumpManager = nil
+        guard let maximumBasalRate = deviceManager.loopManager.settings.maximumBasalRatePerHour,
+              let maxBolus = deviceManager.loopManager.settings.maximumBolus,
+              let basalSchedule = deviceManager.loopManager.settings.basalRateSchedule else
+        {
+            fatalError("Failed to reload pump manager. Missing initial settings")
+        }
+        let initialSettings = PumpManagerSetupSettings(maxBasalRateUnitsPerHour: maximumBasalRate,
+                                                       maxBolusUnits: maxBolus,
+                                                       basalSchedule: basalSchedule)
+        let result = deviceManager.setupPumpManager(withIdentifier: pumpManagerIdentifier,
+                                                    initialSettings: initialSettings,
+                                                    prefersToSkipUserInteraction: true)
+        switch result {
+        case .success(let setupUIResult):
+            switch setupUIResult {
+            case .createdAndOnboarded(let pumpManager):
+                return pumpManager as! TestingPumpManager
+            default:
+                fatalError("Failed to reload pump manager. UI interaction required for setup")
+            }
+        default:
+            fatalError("Failed to reload pump manager. Setup failed")
+        }
+    }
+    
+    private func reloadCGMManager(withIdentifier cgmManagerIdentifier: String) -> TestingCGMManager {
+        deviceManager.cgmManager = nil
+        let result = deviceManager.setupCGMManager(withIdentifier: cgmManagerIdentifier, prefersToSkipUserInteraction: true)
+        switch result {
+        case .success(let setupUIResult):
+            switch setupUIResult {
+            case .createdAndOnboarded(let cgmManager):
+                return cgmManager as! TestingCGMManager
+            default:
+                fatalError("Failed to reload CGM manager. UI interaction required for setup")
+            }
+        default:
+            fatalError("Failed to reload CGM manager. Setup failed")
+        }
     }
 
     private func wipeExistingData(completion: @escaping (Error?) -> Void) {
         guard FeatureFlags.scenariosEnabled else {
             fatalError("\(#function) should be invoked only when scenarios are enabled")
         }
-
+        
         deviceManager.deleteTestingPumpData { error in
             guard error == nil else {
                 completion(error!)
@@ -235,7 +311,14 @@ extension TestingScenariosManagerRequirements {
                     return
                 }
 
-                self.deviceManager.carbStore.deleteAllCarbEntries(completion: completion)
+                self.deviceManager.carbStore.deleteAllCarbEntries() { error in
+                    guard error == nil else {
+                        completion(error!)
+                        return
+                    }
+                    
+                    self.deviceManager.alertManager.alertStore.purge(before: Date(), completion: completion)
+                }
             }
         }
     }
diff --git a/Loop/Models/AutomaticDosingStatus.swift b/Loop/Models/AutomaticDosingStatus.swift
new file mode 100644
index 000000000..ae3930c12
--- /dev/null
+++ b/Loop/Models/AutomaticDosingStatus.swift
@@ -0,0 +1,21 @@
+//
+//  AutomaticDosingStatus.swift
+//  Loop
+//
+//  Created by Nathaniel Hamming on 2021-05-28.
+//  Copyright © 2021 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+
+class AutomaticDosingStatus {
+    @Published var automaticDosingEnabled: Bool
+    @Published var isAutomaticDosingAllowed: Bool
+
+    init(automaticDosingEnabled: Bool,
+         isAutomaticDosingAllowed: Bool)
+    {
+        self.automaticDosingEnabled = automaticDosingEnabled
+        self.isAutomaticDosingAllowed = isAutomaticDosingAllowed
+    }
+}
diff --git a/Loop/Models/ClosedLoopStatus.swift b/Loop/Models/ClosedLoopStatus.swift
deleted file mode 100644
index f895b4dcb..000000000
--- a/Loop/Models/ClosedLoopStatus.swift
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-//  ClosedLoopStatus.swift
-//  Loop
-//
-//  Created by Nathaniel Hamming on 2021-05-28.
-//  Copyright © 2021 LoopKit Authors. All rights reserved.
-//
-
-import Foundation
-
-class ClosedLoopStatus {
-    @Published var isClosedLoop: Bool
-    @Published var isClosedLoopAllowed: Bool
-
-    init(isClosedLoop: Bool,
-         isClosedLoopAllowed: Bool)
-    {
-        self.isClosedLoop = isClosedLoop
-        self.isClosedLoopAllowed = isClosedLoopAllowed
-    }
-}
-
-typealias AutomaticDosingStatus = ClosedLoopStatus
diff --git a/Loop/Models/StoredLoopNotRunningNotification.swift b/Loop/Models/StoredLoopNotRunningNotification.swift
index 82a6457ac..0b66f8eeb 100644
--- a/Loop/Models/StoredLoopNotRunningNotification.swift
+++ b/Loop/Models/StoredLoopNotRunningNotification.swift
@@ -12,7 +12,6 @@ struct StoredLoopNotRunningNotification: Codable {
     var alertAt: Date
     var title: String
     var body: String
-    var timeInterval: TimeInterval
     var isCritical: Bool
 }
 
diff --git a/Loop/View Controllers/CarbAbsorptionViewController.swift b/Loop/View Controllers/CarbAbsorptionViewController.swift
index 6090b2e92..c6d7502ba 100644
--- a/Loop/View Controllers/CarbAbsorptionViewController.swift	
+++ b/Loop/View Controllers/CarbAbsorptionViewController.swift	
@@ -28,7 +28,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif
 
     var isOnboardingComplete: Bool = true
 
-    var closedLoopStatus: ClosedLoopStatus!
+    var automaticDosingStatus: AutomaticDosingStatus!
 
     override func viewDidLoad() {
         super.viewDidLoad()
@@ -64,7 +64,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif
 
         navigationItem.rightBarButtonItem?.isEnabled = isOnboardingComplete
         
-        allowEditing = closedLoopStatus.isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled
+        allowEditing = automaticDosingStatus.automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled
 
         if allowEditing {
             navigationItem.rightBarButtonItems?.append(editButtonItem)
@@ -502,7 +502,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif
     
     @IBAction func presentCarbEntryScreen() {
         let navigationWrapper: UINavigationController
-        if FeatureFlags.simpleBolusCalculatorEnabled && !closedLoopStatus.isClosedLoop {
+        if FeatureFlags.simpleBolusCalculatorEnabled && !automaticDosingStatus.automaticDosingEnabled {
             let viewModel = SimpleBolusViewModel(delegate: deviceManager, displayMealEntry: true)
             let bolusEntryView = SimpleBolusView(viewModel: viewModel).environmentObject(DisplayGlucoseUnitObservable(displayGlucoseUnit: .milligramsPerDeciliter))
             let hostingController = DismissibleHostingController(rootView: bolusEntryView, isModalInPresentation: false)
diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift
index 904f64cab..0af4bcea5 100644
--- a/Loop/View Controllers/StatusTableViewController.swift	
+++ b/Loop/View Controllers/StatusTableViewController.swift	
@@ -33,7 +33,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
 
     var onboardingManager: OnboardingManager!
 
-    var closedLoopStatus: ClosedLoopStatus!
+    var automaticDosingStatus: AutomaticDosingStatus!
     
     var alertPermissionsChecker: AlertPermissionsChecker!
 
@@ -46,8 +46,12 @@ final class StatusTableViewController: LoopChartsTableViewController {
     override func viewDidLoad() {
 
         super.viewDidLoad()
+        
+        setupToolbarItems()
+        
         tableView.register(BolusProgressTableViewCell.nib(), forCellReuseIdentifier: BolusProgressTableViewCell.className)
         tableView.register(AlertPermissionsDisabledWarningCell.self, forCellReuseIdentifier: AlertPermissionsDisabledWarningCell.className)
+        tableView.register(MuteAlertsWarningCell.self, forCellReuseIdentifier: MuteAlertsWarningCell.className)
 
         if FeatureFlags.predictedGlucoseChartClampEnabled {
             statusCharts.glucose.glucoseDisplayRange = LoopConstants.glucoseChartDefaultDisplayBoundClamped
@@ -112,9 +116,9 @@ final class StatusTableViewController: LoopChartsTableViewController {
             },
         ]
 
-        closedLoopStatus.$isClosedLoop
+        automaticDosingStatus.$automaticDosingEnabled
             .receive(on: DispatchQueue.main)
-            .sink { self.closedLoopStatusChanged($0) }
+            .sink { self.automaticDosingStatusChanged($0) }
             .store(in: &cancellables)
 
         alertMuter.$configuration
@@ -136,14 +140,6 @@ final class StatusTableViewController: LoopChartsTableViewController {
         // Estimate an initial value
         landscapeMode = UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height
 
-        // Toolbar
-        toolbarItems![0].accessibilityLabel = NSLocalizedString("Add Meal", comment: "The label of the carb entry button")
-        toolbarItems![0].tintColor = UIColor.carbTintColor
-        toolbarItems![4].accessibilityLabel = NSLocalizedString("Bolus", comment: "The label of the bolus entry button")
-        toolbarItems![4].tintColor = UIColor.insulinTintColor
-        toolbarItems![8].accessibilityLabel = NSLocalizedString("Settings", comment: "The label of the settings button")
-        toolbarItems![8].tintColor = UIColor.secondaryLabel
-
         addScenarioStepGestureRecognizers()
 
         tableView.backgroundColor = .secondarySystemBackground
@@ -165,6 +161,9 @@ final class StatusTableViewController: LoopChartsTableViewController {
 
         navigationController?.setNavigationBarHidden(true, animated: animated)
         navigationController?.setToolbarHidden(false, animated: animated)
+        
+        setupToolbarItems()
+        updateToolbarItems()
 
         alertPermissionsChecker.checkNow()
 
@@ -261,15 +260,40 @@ final class StatusTableViewController: LoopChartsTableViewController {
         deviceManager.pumpManagerHUDProvider?.visible = active && onscreen
     }
 
+    private func setupToolbarItems() {
+        let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
+        let carbs = UIBarButtonItem(image: UIImage(named: "carbs"), style: .plain, target: self, action: #selector(userTappedAddCarbs))
+        let preMeal = createPreMealButtonItem(selected: false, isEnabled: true)
+        let bolus = UIBarButtonItem(image: UIImage(named: "bolus"), style: .plain, target: self, action: #selector(presentBolusScreen))
+        let workout = createWorkoutButtonItem(selected: false, isEnabled: true)
+        let settings = UIBarButtonItem(image: UIImage(named: "settings"), style: .plain, target: self, action: #selector(onSettingsTapped))
+        
+        toolbarItems = [
+            carbs,
+            space,
+            preMeal,
+            space,
+            bolus,
+            space,
+            workout,
+            space,
+            settings
+        ]
+    }
+    
     private func updateToolbarItems() {
         let isPumpOnboarded = onboardingManager.isComplete || deviceManager.pumpManager?.isOnboarded == true
-        let isClosedLoop = closedLoopStatus.isClosedLoop
 
+        toolbarItems![0].accessibilityLabel = NSLocalizedString("Add Meal", comment: "The label of the carb entry button")
         toolbarItems![0].isEnabled = isPumpOnboarded
-        toolbarItems![2].isEnabled = isPumpOnboarded && (isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled)
+        toolbarItems![0].tintColor = UIColor.carbTintColor
+        toolbarItems![2].isEnabled = isPumpOnboarded && (automaticDosingStatus.automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled)
+        toolbarItems![4].accessibilityLabel = NSLocalizedString("Bolus", comment: "The label of the bolus entry button")
         toolbarItems![4].isEnabled = isPumpOnboarded
+        toolbarItems![4].tintColor = UIColor.insulinTintColor
         toolbarItems![6].isEnabled = isPumpOnboarded
-        toolbarItems![8].isEnabled = true
+        toolbarItems![8].accessibilityLabel = NSLocalizedString("Settings", comment: "The label of the settings button")
+        toolbarItems![8].tintColor = UIColor.secondaryLabel
     }
 
     public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState? = nil {
@@ -384,7 +408,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
         var carbsOnBoard: HKQuantity?
         let startDate = charts.startDate
         let basalDeliveryState = self.basalDeliveryState
-        let isClosedLoop = closedLoopStatus.isClosedLoop
+        let automaticDosingEnabled = automaticDosingStatus.automaticDosingEnabled
 
         // TODO: Don't always assume currentContext.contains(.status)
         reloadGroup.enter()
@@ -491,7 +515,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
             }
         }
 
-        updatePreMealModeAvailability(isClosedLoop: isClosedLoop)
+        updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingEnabled)
 
         if deviceManager.loopManager.settings.preMealTargetRange == nil {
             preMealMode = nil
@@ -512,7 +536,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
             if let glucoseSamples = glucoseSamples {
                 self.statusCharts.setGlucoseValues(glucoseSamples)
             }
-            if (isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled), let predictedGlucoseValues = predictedGlucoseValues {
+            if (automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled), let predictedGlucoseValues = predictedGlucoseValues {
                 self.statusCharts.setPredictedGlucoseValues(predictedGlucoseValues)
             } else {
                 self.statusCharts.setPredictedGlucoseValues([])
@@ -615,7 +639,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
     }
 
     private enum Section: Int, CaseIterable {
-        case alertPermissionsDisabledWarning
+        case alertWarning
         case hud
         case status
         case charts
@@ -661,7 +685,6 @@ final class StatusTableViewController: LoopChartsTableViewController {
         case pumpSuspended(resuming: Bool)
         case onboardingSuspended
         case recommendManualGlucoseEntry
-        case tempMuteAlerts
 
         var hasRow: Bool {
             switch self {
@@ -700,22 +723,25 @@ final class StatusTableViewController: LoopChartsTableViewController {
             !premealOverride.hasFinished()
         {
             statusRowMode = .scheduleOverrideEnabled(premealOverride)
-        } else if alertMuter.shouldMuteAlert() {
-            statusRowMode = .tempMuteAlerts
         } else {
             statusRowMode = .hidden
         }
 
         return statusRowMode
     }
-    
+
+    private var shouldShowBannerWarning: Bool {
+        alertPermissionsChecker.showWarning || alertMuter.configuration.shouldMute
+    }
+
     private func updateBannerRow(animated: Bool) {
-        let warningWasVisible = tableView.numberOfRows(inSection: Section.alertPermissionsDisabledWarning.rawValue) != 0
-        let showWarning = alertPermissionsChecker.showWarning
-        if !showWarning && warningWasVisible {
-            tableView.deleteRows(at: [IndexPath(row: 0, section: Section.alertPermissionsDisabledWarning.rawValue)], with: animated ? .top : .none)
-        } else if showWarning && !warningWasVisible {
-            tableView.insertRows(at: [IndexPath(row: 0, section: Section.alertPermissionsDisabledWarning.rawValue)], with: animated ? .top : .none)
+        let warningWasVisible = tableView.numberOfRows(inSection: Section.alertWarning.rawValue) != 0
+        if !shouldShowBannerWarning && warningWasVisible {
+            tableView.deleteRows(at: [IndexPath(row: 0, section: Section.alertWarning.rawValue)], with: animated ? .top : .none)
+        } else if shouldShowBannerWarning && !warningWasVisible {
+            tableView.insertRows(at: [IndexPath(row: 0, section: Section.alertWarning.rawValue)], with: animated ? .top : .none)
+        } else {
+            tableView.reloadRows(at: [IndexPath(row: 0, section: Section.alertWarning.rawValue)], with: .none)
         }
     }
 
@@ -798,13 +824,13 @@ final class StatusTableViewController: LoopChartsTableViewController {
             guard oldValue != preMealMode else {
                 return
             }
-            updatePreMealModeAvailability(isClosedLoop: closedLoopStatus.isClosedLoop)
+            updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingStatus.automaticDosingEnabled)
         }
     }
 
-    private func updatePreMealModeAvailability(isClosedLoop: Bool) {
+    private func updatePreMealModeAvailability(automaticDosingEnabled: Bool) {
         let allowed = onboardingManager.isComplete &&
-                (isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled)
+                (automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled)
                 && deviceManager.loopManager.settings.preMealTargetRange != nil
         toolbarItems![2] = createPreMealButtonItem(selected: preMealMode ?? false && allowed, isEnabled: allowed)
     }
@@ -832,8 +858,8 @@ final class StatusTableViewController: LoopChartsTableViewController {
 
     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         switch Section(rawValue: section)! {
-        case .alertPermissionsDisabledWarning:
-            return alertPermissionsChecker.showWarning ? 1 : 0
+        case .alertWarning:
+            return shouldShowBannerWarning ? 1 : 0
         case .hud:
             return shouldShowHUD ? 1 : 0
         case .charts:
@@ -844,7 +870,6 @@ final class StatusTableViewController: LoopChartsTableViewController {
     }
 
     private class AlertPermissionsDisabledWarningCell: UITableViewCell {
-         
         override func updateConfiguration(using state: UICellConfigurationState) {
             super.updateConfiguration(using: state)
 
@@ -879,12 +904,55 @@ final class StatusTableViewController: LoopChartsTableViewController {
             contentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 6, leading: 0, bottom: 13, trailing: 0)
         }
     }
+
+    private class MuteAlertsWarningCell: UITableViewCell {
+        var formattedAlertMuteEndTime: String = NSLocalizedString("Unknown", comment: "label for when the alert mute end time is unknown")
+
+        override func updateConfiguration(using state: UICellConfigurationState) {
+            super.updateConfiguration(using: state)
+
+            let adjustViewForNarrowDisplay = bounds.width < 350
+
+            var contentConfig = defaultContentConfiguration().updated(for: state)
+            let title = NSMutableAttributedString(string: NSLocalizedString("All Alerts Muted", comment: "Warning text for when alerts are muted"))
+            contentConfig.image = UIImage(systemName: "speaker.slash.fill")
+            contentConfig.imageProperties.tintColor = .white
+            contentConfig.attributedText = title
+            contentConfig.textProperties.color = .white
+            contentConfig.textProperties.font = .systemFont(ofSize: adjustViewForNarrowDisplay ? 16 : 18, weight: .bold)
+            contentConfig.textProperties.adjustsFontSizeToFitWidth = true
+            contentConfig.secondaryText = String(format: NSLocalizedString("Until %1$@", comment: "indication of when alerts will be unmuted (1: time when alerts unmute)"), formattedAlertMuteEndTime)
+            contentConfig.secondaryTextProperties.color = .white
+            contentConfig.secondaryTextProperties.font = .systemFont(ofSize: adjustViewForNarrowDisplay ? 13 : 15)
+            contentConfiguration = contentConfig
+
+            var backgroundConfig = backgroundConfiguration?.updated(for: state)
+            backgroundConfig?.backgroundColor = .warning.withAlphaComponent(0.8)
+            backgroundConfiguration = backgroundConfig
+            backgroundConfiguration?.backgroundInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10)
+            backgroundConfiguration?.cornerRadius = 10
+
+            let unmuteIndicator = UIImage(systemName: "stop.circle")?.withTintColor(.white)
+            let imageView = UIImageView(image: unmuteIndicator)
+            imageView.tintColor = .white
+            imageView.frame.size = CGSize(width: 30, height: 30)
+            accessoryView = imageView
+
+            contentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 6, leading: 0, bottom: 13, trailing: 0)
+        }
+    }
     
     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         switch Section(rawValue: indexPath.section)! {
-        case .alertPermissionsDisabledWarning:
-            let cell = tableView.dequeueReusableCell(withIdentifier: AlertPermissionsDisabledWarningCell.className, for: indexPath) as! AlertPermissionsDisabledWarningCell
-            return cell
+        case .alertWarning:
+            if alertPermissionsChecker.showWarning {
+                let cell = tableView.dequeueReusableCell(withIdentifier: AlertPermissionsDisabledWarningCell.className, for: indexPath) as! AlertPermissionsDisabledWarningCell
+                return cell
+            } else {
+                let cell = tableView.dequeueReusableCell(withIdentifier: MuteAlertsWarningCell.className, for: indexPath) as! MuteAlertsWarningCell
+                cell.formattedAlertMuteEndTime = alertMuter.formattedEndTime
+                return cell
+            }
         case .hud:
             let cell = tableView.dequeueReusableCell(withIdentifier: HUDViewTableViewCell.className, for: indexPath) as! HUDViewTableViewCell
             hudView = cell.hudView
@@ -899,7 +967,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
                     return self?.statusCharts.glucoseChart(withFrame: frame)?.view
                 })
                 cell.setTitleLabelText(label: NSLocalizedString("Glucose", comment: "The title of the glucose and prediction graph"))
-                cell.doesNavigate = closedLoopStatus.isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled
+                cell.doesNavigate = automaticDosingStatus.automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled
             case .iob:
                 cell.setChartGenerator(generator: { [weak self] (frame) in
                     return self?.statusCharts.iobChart(withFrame: frame)?.view
@@ -940,11 +1008,6 @@ final class StatusTableViewController: LoopChartsTableViewController {
             switch StatusRow(rawValue: indexPath.row)! {
             case .status:
                 switch statusRowMode {
-                case .tempMuteAlerts:
-                    //TODO testing (need design to make the correct status row)
-                    let cell = getTitleSubtitleCell()
-                    cell.titleLabel.text = NSLocalizedString("Temp Mute Alerts", comment: "The title of the cell indicating alerts are temporarily muted")
-                    return cell
                 case .hidden:
                     let cell = getTitleSubtitleCell()
                     return cell
@@ -1059,7 +1122,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
                 } else {
                     cell.setSubtitleLabel(label: nil)
                 }
-                cell.doesNavigate = closedLoopStatus.isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled
+                cell.doesNavigate = automaticDosingStatus.automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled
             case .iob:
                 if let currentIOB = currentIOBDescription {
                     cell.setSubtitleLabel(label: currentIOB)
@@ -1083,7 +1146,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
                     cell.setSubtitleLabel(label: nil)
                 }
             }
-        case .hud, .status, .alertPermissionsDisabledWarning:
+        case .hud, .status, .alertWarning:
             break
         }
     }
@@ -1104,16 +1167,21 @@ final class StatusTableViewController: LoopChartsTableViewController {
             case .iob, .dose, .cob:
                 return max(106, 0.21 * availableSize)
             }
-        case .hud, .status, .alertPermissionsDisabledWarning:
+        case .hud, .status, .alertWarning:
             return UITableView.automaticDimension
         }
     }
 
     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         switch Section(rawValue: indexPath.section)! {
-        case .alertPermissionsDisabledWarning:
-            tableView.deselectRow(at: indexPath, animated: true)
-            AlertPermissionsChecker.gotoSettings()
+        case .alertWarning:
+            if alertPermissionsChecker.showWarning {
+                tableView.deselectRow(at: indexPath, animated: true)
+                AlertPermissionsChecker.gotoSettings()
+            } else {
+                tableView.deselectRow(at: indexPath, animated: true)
+                presentUnmuteAlertConfirmation()
+            }
         case .hud:
             break
         case .status:
@@ -1179,7 +1247,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
         case .charts:
             switch ChartRow(rawValue: indexPath.row)! {
             case .glucose:
-                if closedLoopStatus.isClosedLoop || !FeatureFlags.simpleBolusCalculatorEnabled {
+                if automaticDosingStatus.automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled {
                     performSegue(withIdentifier: PredictionTableViewController.className, sender: indexPath)
                 }
             case .iob, .dose:
@@ -1190,6 +1258,20 @@ final class StatusTableViewController: LoopChartsTableViewController {
         }
     }
 
+    private func presentUnmuteAlertConfirmation() {
+        let title = NSLocalizedString("Unmute Alerts?", comment: "The alert title for unmute alert confirmation")
+        let body = NSLocalizedString("Tap Unmute to resume sound for your alerts and alarms.", comment: "The alert body for unmute alert confirmation")
+        let action = UIAlertAction(
+            title: NSLocalizedString("Unmute", comment: "The title of the action used to unmute alerts"),
+            style: .default) { _ in
+                self.alertMuter.unmuteAlerts()
+            }
+        let alert = UIAlertController(title: title, message: body, preferredStyle: .alert)
+        alert.addAction(action)
+        alert.addCancelAction { _ in }
+        present(alert, animated: true, completion: nil)
+    }
+
     private func presentErrorCancelingBolus(_ error: (Error)) {
         log.error("Error Canceling Bolus: %@", error.localizedDescription)
         let title = NSLocalizedString("Error Canceling Bolus", comment: "The alert title for an error while canceling a bolus")
@@ -1224,7 +1306,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
         switch targetViewController {
         case let vc as CarbAbsorptionViewController:
             vc.isOnboardingComplete = onboardingManager.isComplete
-            vc.closedLoopStatus = closedLoopStatus
+            vc.automaticDosingStatus = automaticDosingStatus
             vc.deviceManager = deviceManager
             vc.hidesBottomBarWhenPushed = true
         case let vc as InsulinDeliveryTableViewController:
@@ -1257,7 +1339,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
 
     func presentCarbEntryScreen(_ activity: NSUserActivity?) {
         let navigationWrapper: UINavigationController
-        if FeatureFlags.simpleBolusCalculatorEnabled && !closedLoopStatus.isClosedLoop {
+        if FeatureFlags.simpleBolusCalculatorEnabled && !automaticDosingStatus.automaticDosingEnabled {
             let viewModel = SimpleBolusViewModel(delegate: deviceManager, displayMealEntry: true)
             if let activity = activity {
                 viewModel.restoreUserActivityState(activity)
@@ -1287,7 +1369,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
 
     func presentBolusEntryView(enableManualGlucoseEntry: Bool = false) {
         let hostingController: DismissibleHostingController
-        if FeatureFlags.simpleBolusCalculatorEnabled && !closedLoopStatus.isClosedLoop {
+        if FeatureFlags.simpleBolusCalculatorEnabled && !automaticDosingStatus.automaticDosingEnabled {
             let viewModel = SimpleBolusViewModel(delegate: deviceManager, displayMealEntry: false)
             let bolusEntryView = SimpleBolusView(viewModel: viewModel).environmentObject(deviceManager.displayGlucoseUnitObservable)
             hostingController = DismissibleHostingController(rootView: bolusEntryView, isModalInPresentation: false)
@@ -1461,7 +1543,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
                                           therapySettings: { [weak self] in self?.deviceManager.loopManager.therapySettings ?? TherapySettings() },
                                           sensitivityOverridesEnabled: FeatureFlags.sensitivityOverridesEnabled,
                                           initialDosingEnabled: deviceManager.loopManager.settings.dosingEnabled,
-                                          isClosedLoopAllowed: closedLoopStatus.$isClosedLoopAllowed,
+                                          isClosedLoopAllowed: automaticDosingStatus.$isAutomaticDosingAllowed,
                                           supportInfoProvider: deviceManager,
                                           automaticDosingStrategy: deviceManager.loopManager.settings.automaticDosingStrategy,
                                           availableSupports: supportManager.availableSupports,
@@ -1498,9 +1580,9 @@ final class StatusTableViewController: LoopChartsTableViewController {
         show(settings, sender: self)
     }
 
-    private func closedLoopStatusChanged(_ isClosedLoop: Bool) {
-        updatePreMealModeAvailability(isClosedLoop: isClosedLoop)
-        hudView?.loopCompletionHUD.loopIconClosed = isClosedLoop
+    private func automaticDosingStatusChanged(_ automaticDosingEnabled: Bool) {
+        updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingEnabled)
+        hudView?.loopCompletionHUD.loopIconClosed = automaticDosingEnabled
         hudView?.loopCompletionHUD.closedLoopDisallowedLocalizedDescription = deviceManager.closedLoopDisallowedLocalizedDescription
     }
 
@@ -1527,7 +1609,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
 
             // when HUD view is initialized, update loop completion HUD (e.g., icon and last loop completed)
             hudView.loopCompletionHUD.stateColors = .loopStatus
-            hudView.loopCompletionHUD.loopIconClosed = closedLoopStatus.isClosedLoop
+            hudView.loopCompletionHUD.loopIconClosed = automaticDosingStatus.automaticDosingEnabled
             hudView.loopCompletionHUD.lastLoopCompleted = deviceManager.loopManager.lastLoopCompleted
 
             hudView.cgmStatusHUD.stateColors = .cgmStatus
diff --git a/Loop/View Controllers/TestingScenariosTableViewController.swift b/Loop/View Controllers/TestingScenariosTableViewController.swift
index 2c11e8e27..d6ad2bb73 100644
--- a/Loop/View Controllers/TestingScenariosTableViewController.swift	
+++ b/Loop/View Controllers/TestingScenariosTableViewController.swift	
@@ -14,9 +14,10 @@ final class TestingScenariosTableViewController: RadioSelectionTableViewControll
 
     private let scenariosManager: TestingScenariosManager
 
-    private var scenarioURLs: [URL] = [] {
+    private var scenarios: [LoopScenario] = [] {
         didSet {
-            options = scenarioURLs.map { $0.deletingPathExtension().lastPathComponent }
+            options = scenarios.map(\.name)
+            
             if isViewLoaded {
                 DispatchQueue.main.async {
                     self.updateLoadButtonEnabled()
@@ -58,14 +59,14 @@ final class TestingScenariosTableViewController: RadioSelectionTableViewControll
         contextHelp = "The scenarios directory location is available in the debug output of the Xcode console."
 
         if let activeScenarioURL = scenariosManager.activeScenarioURL {
-            selectedIndex = scenarioURLs.firstIndex(of: activeScenarioURL)
+            selectedIndex = scenarios.firstIndex(where: { $0.url == activeScenarioURL })
         }
 
         updateLoadButtonEnabled()
     }
 
     override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
-        let url = scenarioURLs[indexPath.row]
+        let url = scenarios[indexPath.row].url
 
         let rewindScenario = contextualAction(
             rowTitle: "⏮ Rewind",
@@ -79,7 +80,7 @@ final class TestingScenariosTableViewController: RadioSelectionTableViewControll
     }
 
     override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
-        let url = scenarioURLs[indexPath.row]
+        let url = scenarios[indexPath.row].url
 
         let advanceScenario = contextualAction(
             rowTitle: "Advance ⏭",
@@ -130,7 +131,7 @@ final class TestingScenariosTableViewController: RadioSelectionTableViewControll
     }
 
     private func updateLoadButtonEnabled() {
-        loadButtonItem.isEnabled = !scenarioURLs.isEmpty && selectedIndex != nil
+        loadButtonItem.isEnabled = !scenarios.isEmpty && selectedIndex != nil
     }
 
     @objc private func loadSelectedScenario() {
@@ -139,9 +140,14 @@ final class TestingScenariosTableViewController: RadioSelectionTableViewControll
             return
         }
 
-        let url = scenarioURLs[selectedIndex]
+        let url = scenarios[selectedIndex].url
+
+        loadButtonItem.isEnabled = false
+        loadButtonItem.title = "Loading..."
         scenariosManager.loadScenario(from: url) { error in
             DispatchQueue.main.async {
+                self.loadButtonItem.isEnabled = true
+                self.loadButtonItem.title = "Load"
                 if let error = error {
                     self.present(UIAlertController(with: error), animated: true)
                 } else {
@@ -158,6 +164,13 @@ final class TestingScenariosTableViewController: RadioSelectionTableViewControll
 
 extension TestingScenariosTableViewController: TestingScenariosManagerDelegate {
     func testingScenariosManager(_ manager: TestingScenariosManager, didUpdateScenarioURLs scenarioURLs: [URL]) {
-        self.scenarioURLs = scenarioURLs
+        var filteredScenarios = Set<LoopScenario>()
+        manager.pluginManager.availableSupports.forEach { supportUI in
+            supportUI.getScenarios(from: scenarioURLs).forEach { scenario in
+                filteredScenarios.insert(scenario)
+            }
+        }
+        
+        self.scenarios = Array(filteredScenarios).sorted(by: { $0.name < $1.name })
     }
 }
diff --git a/Loop/View Models/BolusEntryViewModel.swift b/Loop/View Models/BolusEntryViewModel.swift
index bd2ecd47a..525eb6ad2 100644
--- a/Loop/View Models/BolusEntryViewModel.swift	
+++ b/Loop/View Models/BolusEntryViewModel.swift	
@@ -114,7 +114,15 @@ final class BolusEntryViewModel: ObservableObject {
     let selectedCarbAbsorptionTimeEmoji: String?
 
     @Published var recommendedBolus: HKQuantity?
+    var recommendedBolusAmount: Double? {
+        recommendedBolus?.doubleValue(for: .internationalUnit())
+    }
     @Published var enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0)
+    var enteredBolusAmount: Double {
+        enteredBolus.doubleValue(for: .internationalUnit())
+    }
+    private var userChangedBolusAmount = false
+    @Published var isInitiatingSaveOrBolus = false
     @Published var enacting = false
 
     private var dosingDecision = BolusDosingDecision(for: .normalBolus)
@@ -287,11 +295,11 @@ final class BolusEntryViewModel: ObservableObject {
     // MARK: - View API
 
     var isBolusRecommended: Bool {
-        guard let recommendedBolus = recommendedBolus else {
+        guard let recommendedBolusAmount = recommendedBolusAmount else {
             return false
         }
 
-        return recommendedBolus.doubleValue(for: .internationalUnit()) > 0
+        return recommendedBolusAmount > 0
     }
 
     func saveCarbEntry(_ entry: NewCarbEntry, replacingEntry: StoredCarbEntry?) async -> StoredCarbEntry? {
@@ -335,15 +343,13 @@ final class BolusEntryViewModel: ObservableObject {
             return false
         }
 
-        let amountEntered = enteredBolus.doubleValue(for: .internationalUnit())
-
-        let amountToDeliver = delegate.roundBolusVolume(units: amountEntered)
-        guard amountEntered == 0 || amountToDeliver > 0 else {
+        let amountToDeliver = delegate.roundBolusVolume(units: enteredBolusAmount)
+        guard enteredBolusAmount == 0 || amountToDeliver > 0 else {
             presentAlert(.bolusTooSmall)
             return false
         }
 
-        let amountToDeliverString = bolusVolumeFormatter.numberFormatter.string(from: amountToDeliver) ?? String(amountToDeliver)
+        let amountToDeliverString = formatBolusAmount(amountToDeliver)
 
         let manualGlucoseSample = manualGlucoseSample
         let potentialCarbEntry = potentialCarbEntry
@@ -435,7 +441,12 @@ final class BolusEntryViewModel: ObservableObject {
         activeAlert = alert
     }
 
-    private lazy var bolusVolumeFormatter = QuantityFormatter(for: .internationalUnit())
+    private lazy var bolusAmountFormatter: NumberFormatter = {
+        let formatter = QuantityFormatter()
+        formatter.setPreferredNumberFormatter(for: .internationalUnit())
+        formatter.numberFormatter.roundingMode = .down
+        return formatter.numberFormatter
+    }()
 
     private lazy var absorptionTimeFormatter: DateComponentsFormatter = {
         let formatter = DateComponentsFormatter()
@@ -447,15 +458,15 @@ final class BolusEntryViewModel: ObservableObject {
     }()
 
     var enteredBolusAmountString: String {
-        let bolusVolume = enteredBolus.doubleValue(for: .internationalUnit())
-        return bolusVolumeFormatter.numberFormatter.string(from: bolusVolume) ?? String(bolusVolume)
+        let bolusAmount = enteredBolusAmount
+        return formatBolusAmount(bolusAmount)
     }
 
     var maximumBolusAmountString: String? {
-        guard let maxBolusVolume = maximumBolus?.doubleValue(for: .internationalUnit()) else {
+        guard let maxBolusAmount = maximumBolus?.doubleValue(for: .internationalUnit()) else {
             return nil
         }
-        return bolusVolumeFormatter.numberFormatter.string(from: maxBolusVolume) ?? String(maxBolusVolume)
+        return formatBolusAmount(maxBolusAmount)
     }
 
     var carbEntryAmountAndEmojiString: String? {
@@ -641,18 +652,25 @@ final class BolusEntryViewModel: ObservableObject {
     private func updateRecommendedBolusAndNotice(from state: LoopState, isUpdatingFromUserInput: Bool) {
         dispatchPrecondition(condition: .notOnQueue(.main))
 
+        guard let delegate = delegate else {
+            assertionFailure("Missing BolusEntryViewModelDelegate")
+            return
+        }
+
         let now = Date()
         var recommendation: ManualBolusRecommendation?
         let recommendedBolus: HKQuantity?
         let notice: Notice?
         do {
             recommendation = try computeBolusRecommendation(from: state)
-            if let recommendation = recommendation {
-                recommendedBolus = HKQuantity(unit: .internationalUnit(), doubleValue: recommendation.amount)
 
+            if let recommendation = recommendation {
+                recommendedBolus = HKQuantity(unit: .internationalUnit(), doubleValue: delegate.roundBolusVolume(units: recommendation.amount))
+                //recommendedBolus = HKQuantity(unit: .internationalUnit(), doubleValue: recommendation.amount)
+                
                 switch recommendation.notice {
                 case .glucoseBelowSuspendThreshold:
-                    if let suspendThreshold = delegate?.settings.suspendThreshold {
+                    if let suspendThreshold = delegate.settings.suspendThreshold {
                         notice = .predictedGlucoseBelowSuspendThreshold(suspendThreshold: suspendThreshold.quantity)
                     } else {
                         notice = nil
@@ -773,6 +791,25 @@ final class BolusEntryViewModel: ObservableObject {
 
         chartDateInterval = DateInterval(start: chartStartDate, duration: .hours(totalHours))
     }
+
+    func formatBolusAmount(_ bolusAmount: Double) -> String {
+        bolusAmountFormatter.string(from: bolusAmount) ?? String(bolusAmount)
+    }
+
+    var recommendedBolusString: String {
+        guard let amount = recommendedBolusAmount else {
+            return "–"
+        }
+        return formatBolusAmount(amount)
+    }
+
+    func updateEnteredBolus(_ enteredBolusString: String) {
+        updateEnteredBolus(bolusAmountFormatter.number(from: enteredBolusString)?.doubleValue)
+    }
+
+    func updateEnteredBolus(_ enteredBolusAmount: Double?) {
+        enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: enteredBolusAmount ?? 0)
+    }
 }
 
 extension BolusEntryViewModel.Alert: Identifiable {
diff --git a/Loop/View Models/SettingsViewModel.swift b/Loop/View Models/SettingsViewModel.swift
index 16e58743b..c24876e26 100644
--- a/Loop/View Models/SettingsViewModel.swift	
+++ b/Loop/View Models/SettingsViewModel.swift	
@@ -143,6 +143,10 @@ public class SettingsViewModel: ObservableObject {
             self?.objectWillChange.send()
         }
         .store(in: &cancellables)
+        alertMuter.objectWillChange.sink { [weak self] in
+            self?.objectWillChange.send()
+        }
+        .store(in: &cancellables)
         pumpManagerSettingsViewModel.objectWillChange.sink { [weak self] in
             self?.objectWillChange.send()
         }
diff --git a/Loop/View Models/VersionUpdateViewModel.swift b/Loop/View Models/VersionUpdateViewModel.swift
index 2114786b9..fa2b87e6c 100644
--- a/Loop/View Models/VersionUpdateViewModel.swift	
+++ b/Loop/View Models/VersionUpdateViewModel.swift	
@@ -74,11 +74,8 @@ public class VersionUpdateViewModel: ObservableObject {
     }
     
     public func update() {
-        supportManager?.checkVersion { [weak self] versionUpdate in
-            DispatchQueue.main.async {
-                self?.versionUpdate = versionUpdate
-            }
+        Task { @MainActor in
+            versionUpdate = await supportManager?.checkVersion()
         }
     }
-    
 }
diff --git a/Loop/Views/AlertManagementView.swift b/Loop/Views/AlertManagementView.swift
index 9999786a3..856db6da1 100644
--- a/Loop/Views/AlertManagementView.swift
+++ b/Loop/Views/AlertManagementView.swift
@@ -12,10 +12,14 @@ import LoopKitUI
 
 struct AlertManagementView: View {
     @Environment(\.appName) private var appName
+    @Environment(\.guidanceColors) private var guidanceColors
 
     @ObservedObject private var checker: AlertPermissionsChecker
     @ObservedObject private var alertMuter: AlertMuter
 
+    @State private var showMuteAlertOptions: Bool = false
+    @State private var showHowMuteAlertWork: Bool = false
+
     private var formatter: DateComponentsFormatter = {
         let formatter = DateComponentsFormatter()
         formatter.unitsStyle = .full
@@ -23,15 +27,6 @@ struct AlertManagementView: View {
         return formatter
     }()
 
-    private var enabled: Binding<Bool> {
-        Binding(
-            get: { alertMuter.configuration.shouldMute },
-            set: { enabled in
-                alertMuter.configuration.startTime = enabled ? Date() : nil
-            }
-        )
-    }
-
     private var formattedSelectedDuration: Binding<String> {
         Binding(
             get: { formatter.string(from: alertMuter.configuration.duration)! },
@@ -40,6 +35,7 @@ struct AlertManagementView: View {
                 else { return }
                 DispatchQueue.main.async {
                     // avoid publishing during view update
+                    alertMuter.configuration.startTime = Date()
                     alertMuter.configuration.duration = AlertMuter.allowedDurations[selectedDurationIndex]
                 }
             }
@@ -69,12 +65,10 @@ struct AlertManagementView: View {
             alertPermissionsSection
             if FeatureFlags.criticalAlertsEnabled {
                 muteAlertsSection
-
-                if alertMuter.configuration.shouldMute {
-                    mutePeriodSection
-                }
             }
-            missedMealAlertSection
+            if FeatureFlags.missedMealNotifications {
+                missedMealAlertSection
+            }
         }
         .navigationTitle(NSLocalizedString("Alert Management", comment: "Title of alert management screen"))
     }
@@ -99,24 +93,79 @@ struct AlertManagementView: View {
 
     @ViewBuilder
     private var muteAlertsSection: some View {
-        Section(footer: muteAlertsSectionFooter) {
-            Toggle(NSLocalizedString("Mute All Alerts", comment: "Label for toggle to mute all alerts"), isOn: enabled)
+        Section(footer: DescriptiveText(label: String(format: NSLocalizedString("When muted, %1$@ alerts will temporarily display without sounds and will vibrate only. Once the mute period ends, your alerts will resume as normal.", comment: "Description of temporary mute alerts (1: app name)"), appName))) {
+            if !alertMuter.configuration.shouldMute {
+                howMuteAlertsWork
+                Button(action: { showMuteAlertOptions = true }) {
+                    HStack {
+                        muteAlertIcon
+                        Text(NSLocalizedString("Mute All Alerts", comment: "Label for button to mute all alerts"))
+                    }
+                }
+                .actionSheet(isPresented: $showMuteAlertOptions) {
+                   muteAlertOptionsActionSheet
+                }
+            } else {
+                Button(action: alertMuter.unmuteAlerts) {
+                    HStack {
+                        unmuteAlertIcon
+                        Text(NSLocalizedString("Tap to Unmute Alerts", comment: "Label for button to unmute all alerts"))
+                    }
+                }
+                HStack {
+                    Text(NSLocalizedString("All alerts muted until", comment: "Label for when mute alert will end"))
+                    Spacer()
+                    Text(alertMuter.formattedEndTime)
+                        .foregroundColor(.secondary)
+                }
+            }
         }
     }
 
-    private var mutePeriodSection: some View {
-        SingleSelectionCheckList(header: NSLocalizedString("Select Mute Period", comment: "List header for mute all alerts period"), footer: muteAlertsFooterString, items: formatterDurations, selectedItem: formattedSelectedDuration)
+    private var muteAlertIcon: some View {
+        Image(systemName: "speaker.slash.fill")
+            .foregroundColor(.white)
+            .padding(5)
+            .background(guidanceColors.warning)
+            .clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
     }
 
-    @ViewBuilder
-    private var muteAlertsSectionFooter: some View {
-        if !alertMuter.configuration.shouldMute {
-            DescriptiveText(label: muteAlertsFooterString)
+    private var unmuteAlertIcon: some View {
+        Image(systemName: "speaker.wave.2.fill")
+            .foregroundColor(.white)
+            .padding(.vertical, 5)
+            .padding(.horizontal, 2)
+            .background(guidanceColors.warning)
+            .clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
+    }
+
+    private var howMuteAlertsWork: some View {
+        Button(action: { showHowMuteAlertWork = true }) {
+            HStack {
+                Text(NSLocalizedString("Take a closer look at how mute alerts works", comment: "Label for link to learn how mute alerts work"))
+                    .font(.footnote)
+                    .foregroundColor(.secondary)
+                Spacer()
+                Image(systemName: "info.circle")
+                    .font(.body)
+            }
+        }
+        .sheet(isPresented: $showHowMuteAlertWork) {
+            HowMuteAlertWorkView()
         }
     }
 
-    private var muteAlertsFooterString: String {
-        NSLocalizedString("No alerts will sound while muted. Once this period ends, your alerts and alarms will resume as normal.", comment: "Description of temporary mute alerts")
+    private var muteAlertOptionsActionSheet: ActionSheet {
+        var muteAlertDurationOptions: [SwiftUI.Alert.Button] = formatterDurations.map { muteAlertDuration in
+            .default(Text(muteAlertDuration),
+                     action: { formattedSelectedDuration.wrappedValue =  muteAlertDuration })
+        }
+        muteAlertDurationOptions.append(.cancel())
+
+        return ActionSheet(
+            title: Text(NSLocalizedString("Mute All Alerts Temporarily", comment: "Title for mute alert duration selection action sheet")),
+            message: Text(NSLocalizedString("No alerts or alarms will sound while muted. Select how long you would you like to mute for.", comment: "Message for mute alert duration selection action sheet")),
+            buttons: muteAlertDurationOptions)
     }
     
     private var missedMealAlertSection: some View {
diff --git a/Loop/Views/BolusEntryView.swift b/Loop/Views/BolusEntryView.swift
index b59b3fbd7..60fee7769 100644
--- a/Loop/Views/BolusEntryView.swift
+++ b/Loop/Views/BolusEntryView.swift
@@ -68,7 +68,7 @@ struct BolusEntryView: View {
                     if amount == 0 {
                         newEnteredBolusString = ""
                     } else {
-                        newEnteredBolusString = Self.doseAmountFormatter.string(from: amount) ?? String(amount)
+                        newEnteredBolusString = viewModel.formatBolusAmount(amount)
                     }
                     enteredBolusStringBinding.wrappedValue = newEnteredBolusString
                 }
@@ -227,18 +227,12 @@ struct BolusEntryView: View {
         }
     }
 
-    private static let doseAmountFormatter: NumberFormatter = {
-        let quantityFormatter = QuantityFormatter()
-        quantityFormatter.setPreferredNumberFormatter(for: .internationalUnit())
-        return quantityFormatter.numberFormatter
-    }()
-
     private var recommendedBolusRow: some View {
         HStack {
             Text("Recommended Bolus", comment: "Label for recommended bolus row on bolus screen")
             Spacer()
             HStack(alignment: .firstTextBaseline) {
-                Text(recommendedBolusString)
+                Text(viewModel.recommendedBolusString)
                     .font(.title)
                     .foregroundColor(Color(.label))
                 bolusUnitsLabel
@@ -247,19 +241,9 @@ struct BolusEntryView: View {
         .accessibilityElement(children: .combine)
     }
 
-    private var recommendedBolusString: String {
-        guard let amount = viewModel.recommendedBolus?.doubleValue(for: .internationalUnit()) else {
-            return "–"
-        }
-        return Self.doseAmountFormatter.string(from: amount) ?? String(amount)
-    }
-
     private func didBeginEditing() {
         if !editedBolusAmount {
-            enteredBolusString = ""
-            DispatchQueue.main.async {
-                self.viewModel.enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: 0)
-            }
+            enteredBolusStringBinding.wrappedValue = ""
             editedBolusAmount = true
         }
     }
@@ -271,7 +255,7 @@ struct BolusEntryView: View {
             HStack(alignment: .firstTextBaseline) {
                 DismissibleKeyboardTextField(
                     text: enteredBolusStringBinding,
-                    placeholder: Self.doseAmountFormatter.string(from: 0.0)!,
+                    placeholder: viewModel.formatBolusAmount(0.0),
                     font: .preferredFont(forTextStyle: .title1),
                     textColor: .loopAccent,
                     textAlignment: .right,
@@ -294,10 +278,10 @@ struct BolusEntryView: View {
 
     private var enteredBolusStringBinding: Binding<String> {
         Binding(
-            get: { self.enteredBolusString },
+            get: { enteredBolusString },
             set: { newValue in
-                self.viewModel.enteredBolus = HKQuantity(unit: .internationalUnit(), doubleValue: Self.doseAmountFormatter.number(from: newValue)?.doubleValue ?? 0)
-                self.enteredBolusString = newValue
+                viewModel.updateEnteredBolus(newValue)
+                enteredBolusString = newValue
             }
         )
     }
diff --git a/Loop/Views/HowMuteAlertWorkView.swift b/Loop/Views/HowMuteAlertWorkView.swift
new file mode 100644
index 000000000..03dc0b860
--- /dev/null
+++ b/Loop/Views/HowMuteAlertWorkView.swift
@@ -0,0 +1,80 @@
+//
+//  HowMuteAlertWorkView.swift
+//  Loop
+//
+//  Created by Nathaniel Hamming on 2022-12-09.
+//  Copyright © 2022 LoopKit Authors. All rights reserved.
+//
+
+import SwiftUI
+import LoopKitUI
+
+struct HowMuteAlertWorkView: View {
+    @Environment(\.dismissAction) private var dismiss
+    @Environment(\.guidanceColors) private var guidanceColors
+
+    var body: some View {
+        NavigationView {
+            List {
+                VStack(alignment: .leading) {
+                    Text(NSLocalizedString("""
+Mute Alerts allows you to temporarily silence your alerts and alarms.
+
+When using Mute Alerts, also consider the impact of using iOS Focus Modes.
+""", comment: "Description of how mute alerts work"))
+                    .fixedSize(horizontal: false, vertical: true)
+                    
+                    VStack(alignment: .leading, spacing: 10) {
+                        HStack(spacing: 10) {
+                            Image(systemName: "speaker.slash.fill")
+                                .foregroundColor(.white)
+                                .padding(5)
+                                .background(guidanceColors.warning)
+                                .clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
+                            
+                            Text(NSLocalizedString("Loop Mute Alerts", comment: "Section title for description that mute alerts is temporary"))
+                                .bold()
+                                .fixedSize(horizontal: false, vertical: true)
+                        }
+                        
+                        Text(NSLocalizedString("""
+All Tidepool Loop alerts, including Critical Alerts, will be silenced for up to 4 hours.
+
+After the mute period ends, your alert sounds will resume.
+""", comment: "Description that mute alerts is temporary"))
+                        .fixedSize(horizontal: false, vertical: true)
+                        .padding(.bottom)
+                        
+                        HStack(spacing: 10) {
+                            Image(systemName: "moon.fill")
+                                .foregroundColor(.accentColor)
+                            
+                            Text(NSLocalizedString("iOS Focus Mode", comment: "Section title for description of how mute alerts work with focus mode"))
+                                .bold()
+                        }
+                        Text(NSLocalizedString("If iOS Focus Mode is ON and Mute Alerts is OFF, Critical Alerts will still be delivered, but non-Critical Alerts will be silenced until Loop is added to each Focus mode as an Allowed App.", comment: "Description of how mute alerts works with focus mode"))
+                            .fixedSize(horizontal: false, vertical: true)
+                    }
+                    .padding()
+                    .overlay(RoundedRectangle(cornerRadius: 10, style: .continuous).stroke(Color(.systemFill), lineWidth: 1))
+                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
+                }
+            }
+            .insetGroupedListStyle()
+            .navigationTitle(NSLocalizedString("Using Mute Alerts", comment: "View title for how mute alerts work"))
+            .navigationBarItems(trailing: closeButton)
+        }
+    }
+
+    private var closeButton: some View {
+        Button(action: dismiss) {
+            Text(NSLocalizedString("Close", comment: "Button title to close view"))
+        }
+    }
+}
+
+struct HowMuteAlertWorkView_Previews: PreviewProvider {
+    static var previews: some View {
+        HowMuteAlertWorkView()
+    }
+}
diff --git a/Loop/Views/SettingsView.swift b/Loop/Views/SettingsView.swift
index 90859273e..22c10d48d 100644
--- a/Loop/Views/SettingsView.swift
+++ b/Loop/Views/SettingsView.swift
@@ -145,6 +145,13 @@ extension SettingsView {
                         Spacer()
                         Image(systemName: "exclamationmark.triangle.fill")
                             .foregroundColor(.critical)
+                    } else if viewModel.alertMuter.configuration.shouldMute {
+                        Spacer()
+                        Image(systemName: "speaker.slash.fill")
+                            .foregroundColor(.white)
+                            .padding(5)
+                            .background(guidanceColors.warning)
+                            .clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
                     }
                 }
             }
diff --git a/LoopCore/NSUserDefaults.swift b/LoopCore/NSUserDefaults.swift
index da129160b..31e4cc80f 100644
--- a/LoopCore/NSUserDefaults.swift
+++ b/LoopCore/NSUserDefaults.swift
@@ -139,7 +139,12 @@ extension UserDefaults {
     }
     
     public var allowDebugFeatures: Bool {
-        return bool(forKey: Key.allowDebugFeatures.rawValue)
+        get {
+            bool(forKey: Key.allowDebugFeatures.rawValue)
+        }
+        set {
+            set(newValue, forKey: Key.allowDebugFeatures.rawValue)
+        }
     }
 
     public var allowSimulators: Bool {
diff --git a/LoopTests/Managers/LoopDataManagerDosingTests.swift b/LoopTests/Managers/LoopDataManagerDosingTests.swift
index 50142b2f2..7506ba83f 100644
--- a/LoopTests/Managers/LoopDataManagerDosingTests.swift
+++ b/LoopTests/Managers/LoopDataManagerDosingTests.swift
@@ -290,12 +290,12 @@ class LoopDataManagerDosingTests: LoopDataManagerTests {
         let observer = NotificationCenter.default.addObserver(forName: .LoopDataUpdated, object: nil, queue: nil) { _ in
             exp.fulfill()
         }
-        automaticDosingStatus.isClosedLoop = false
+        automaticDosingStatus.automaticDosingEnabled = false
         wait(for: [exp], timeout: 1.0)
         let expectedAutomaticDoseRecommendation = AutomaticDoseRecommendation(basalAdjustment: .cancel)
         XCTAssertEqual(delegate.recommendation, expectedAutomaticDoseRecommendation)
         XCTAssertEqual(dosingDecisionStore.dosingDecisions.count, 1)
-        XCTAssertEqual(dosingDecisionStore.dosingDecisions[0].reason, "closedLoopDisabled")
+        XCTAssertEqual(dosingDecisionStore.dosingDecisions[0].reason, "automaticDosingDisabled")
         XCTAssertEqual(dosingDecisionStore.dosingDecisions[0].automaticDoseRecommendation, expectedAutomaticDoseRecommendation)
         NotificationCenter.default.removeObserver(observer)
     }
@@ -345,7 +345,7 @@ class LoopDataManagerDosingTests: LoopDataManagerTests {
 
     func testLoopRecommendsTempBasalWithoutEnactingIfOpenLoop() {
         setUp(for: .highAndStable)
-        automaticDosingStatus.isClosedLoop = false
+        automaticDosingStatus.automaticDosingEnabled = false
         waitOnDataQueue()
         let delegate = MockDelegate()
         loopDataManager.delegate = delegate
@@ -417,7 +417,7 @@ class LoopDataManagerDosingTests: LoopDataManagerTests {
         let currentDate = Date()
 
         dosingDecisionStore = MockDosingDecisionStore()
-        automaticDosingStatus = AutomaticDosingStatus(isClosedLoop: false, isClosedLoopAllowed: true)
+        automaticDosingStatus = AutomaticDosingStatus(automaticDosingEnabled: false, isAutomaticDosingAllowed: true)
         let existingTempBasal = DoseEntry(
             type: .tempBasal,
             startDate: currentDate.addingTimeInterval(-.minutes(2)),
diff --git a/LoopTests/Managers/LoopDataManagerTests.swift b/LoopTests/Managers/LoopDataManagerTests.swift
index 524fe646c..5c24cfc97 100644
--- a/LoopTests/Managers/LoopDataManagerTests.swift
+++ b/LoopTests/Managers/LoopDataManagerTests.swift
@@ -110,7 +110,7 @@ class LoopDataManagerTests: XCTestCase {
         now = currentDate
         
         dosingDecisionStore = MockDosingDecisionStore()
-        automaticDosingStatus = AutomaticDosingStatus(isClosedLoop: true, isClosedLoopAllowed: true)
+        automaticDosingStatus = AutomaticDosingStatus(automaticDosingEnabled: true, isAutomaticDosingAllowed: true)
         loopDataManager = LoopDataManager(
             lastLoopCompleted: currentDate,
             basalDeliveryState: basalDeliveryState ?? .active(currentDate),
diff --git a/LoopTests/Managers/SupportManagerTests.swift b/LoopTests/Managers/SupportManagerTests.swift
index 3f72805f4..d1fd0d516 100644
--- a/LoopTests/Managers/SupportManagerTests.swift
+++ b/LoopTests/Managers/SupportManagerTests.swift
@@ -23,8 +23,13 @@ class SupportManagerTests: XCTestCase {
             nil
         }
         var mockResult: Result<VersionUpdate?, Error> = .success(.default)
-        func checkVersion(bundleIdentifier: String, currentVersion: String, completion: @escaping (Result<VersionUpdate?, Error>) -> Void) {
-            completion(mockResult)
+        func checkVersion(bundleIdentifier: String, currentVersion: String) async -> VersionUpdate? {
+            switch mockResult {
+            case .success(let update):
+                return update
+            case .failure:
+                return nil
+            }
         }
         weak var delegate: SupportUIDelegate?
     }
@@ -34,6 +39,11 @@ class SupportManagerTests: XCTestCase {
         override init() { super.init() }
         required init?(rawState: RawStateValue) { super.init() }
         var rawState: RawStateValue = [:]
+        
+        var loopNeedsReset: Bool = false
+        var studyProductSelection: String? = nil
+        func getScenarios(from scenarioURLs: [URL]) -> [LoopScenario] { [] }
+        func resetLoop() {}
     }
     class AnotherMockSupport: Mixin, SupportUI {
         func configurationMenuItems() -> [AnyView] { return [] }
@@ -41,6 +51,11 @@ class SupportManagerTests: XCTestCase {
         override init() { super.init() }
         required init?(rawState: RawStateValue) { super.init() }
         var rawState: RawStateValue = [:]
+        
+        var loopNeedsReset: Bool = false
+        var studyProductSelection: String? = nil
+        func getScenarios(from scenarioURLs: [URL]) -> [LoopScenario] { [] }
+        func resetLoop() {}
     }
     
     class MockAlertIssuer: AlertIssuer {
@@ -62,37 +77,35 @@ class SupportManagerTests: XCTestCase {
         supportManager.addSupport(mockSupport)
     }
     
-    func getVersion(fn: String = #function) -> VersionUpdate? {
-        let e = expectation(description: fn)
-        var result: VersionUpdate?
-        supportManager.checkVersion {
-            result = $0
-            e.fulfill()
-        }
-        wait(for: [e], timeout: 1.0)
-        return result
-    }
-    
-    func testVersionCheckOneService() throws {
-        XCTAssertEqual(VersionUpdate.none, getVersion())
+    func testVersionCheckOneService() async throws {
+        let result = await supportManager.checkVersion()
+        XCTAssertEqual(VersionUpdate.noUpdateNeeded, result)
         mockSupport.mockResult = .success(.required)
-        XCTAssertEqual(.required, getVersion())
+
+        let result2 = await supportManager.checkVersion()
+        XCTAssertEqual(.required, result2)
     }
     
-    func testVersionCheckOneServiceError() throws {
+    func testVersionCheckOneServiceError() async throws {
         // Error doesn't really do anything but log
         mockSupport.mockResult = .failure(MockError.nothing)
-        XCTAssertEqual(VersionUpdate.none, getVersion())
+        let result = await supportManager.checkVersion()
+        XCTAssertEqual(VersionUpdate.noUpdateNeeded, result)
     }
     
-    func testVersionCheckMultipleServices() throws {
+    func testVersionCheckMultipleServices() async throws {
         let anotherSupport = AnotherMockSupport()
         supportManager.addSupport(anotherSupport)
-        XCTAssertEqual(VersionUpdate.none, getVersion())
+        let result = await supportManager.checkVersion()
+        XCTAssertEqual(VersionUpdate.noUpdateNeeded, result)
+
         anotherSupport.mockResult = .success(.required)
-        XCTAssertEqual(.required, getVersion())
+        let result2 = await supportManager.checkVersion()
+        XCTAssertEqual(.required, result2)
+
+        let result3 = await supportManager.checkVersion()
         mockSupport.mockResult = .success(.recommended)
-        XCTAssertEqual(.required, getVersion())
+        XCTAssertEqual(.required, result3)
     }
     
 }
diff --git a/LoopTests/Mock Stores/MockDoseStore.swift b/LoopTests/Mock Stores/MockDoseStore.swift
index 050a3a895..d85f54d1e 100644
--- a/LoopTests/Mock Stores/MockDoseStore.swift	
+++ b/LoopTests/Mock Stores/MockDoseStore.swift	
@@ -71,10 +71,6 @@ class MockDoseStore: DoseStoreProtocol {
         completion(nil)
     }
     
-    func resetPumpData(completion: ((DoseStore.DoseStoreError?) -> Void)?) {
-        completion?(.configurationError)
-    }
-    
     func getInsulinOnBoardValues(start: Date, end: Date?, basalDosingEnd: Date?, completion: @escaping (DoseStoreResult<[InsulinValue]>) -> Void) {
         completion(.failure(.configurationError))
     }
diff --git a/LoopTests/ViewModels/BolusEntryViewModelTests.swift b/LoopTests/ViewModels/BolusEntryViewModelTests.swift
index 23946cc16..259a810f6 100644
--- a/LoopTests/ViewModels/BolusEntryViewModelTests.swift
+++ b/LoopTests/ViewModels/BolusEntryViewModelTests.swift
@@ -276,7 +276,7 @@ class BolusEntryViewModelTests: XCTestCase {
     func testUpdateRecommendedBolusNoNotice() async throws {
         await setUpViewModel(originalCarbEntry: mockOriginalCarbEntry, potentialCarbEntry: mockPotentialCarbEntry)
         XCTAssertFalse(bolusEntryViewModel.isBolusRecommended)
-        let recommendation = ManualBolusRecommendation(amount: 1.234, pendingInsulin: 4.321)
+        let recommendation = ManualBolusRecommendation(amount: 1.25, pendingInsulin: 4.321)
         delegate.loopState.bolusRecommendationResult = recommendation
         await bolusEntryViewModel.update()
         XCTAssertTrue(bolusEntryViewModel.isBolusRecommended)
@@ -293,7 +293,7 @@ class BolusEntryViewModelTests: XCTestCase {
     func testUpdateRecommendedBolusWithNotice() async throws {
         delegate.settings.suspendThreshold = GlucoseThreshold(unit: .milligramsPerDeciliter, value: Self.exampleCGMGlucoseQuantity.doubleValue(for: .milligramsPerDeciliter))
         XCTAssertFalse(bolusEntryViewModel.isBolusRecommended)
-        let recommendation = ManualBolusRecommendation(amount: 1.234, pendingInsulin: 4.321, notice: BolusRecommendationNotice.glucoseBelowSuspendThreshold(minGlucose: Self.exampleGlucoseValue))
+        let recommendation = ManualBolusRecommendation(amount: 1.25, pendingInsulin: 4.321, notice: BolusRecommendationNotice.glucoseBelowSuspendThreshold(minGlucose: Self.exampleGlucoseValue))
         delegate.loopState.bolusRecommendationResult = recommendation
         await bolusEntryViewModel.update()
         XCTAssertTrue(bolusEntryViewModel.isBolusRecommended)
@@ -306,7 +306,7 @@ class BolusEntryViewModelTests: XCTestCase {
     func testUpdateRecommendedBolusWithNoticeMissingSuspendThreshold() async throws {
         XCTAssertFalse(bolusEntryViewModel.isBolusRecommended)
         delegate.settings.suspendThreshold = nil
-        let recommendation = ManualBolusRecommendation(amount: 1.234, pendingInsulin: 4.321, notice: BolusRecommendationNotice.glucoseBelowSuspendThreshold(minGlucose: Self.exampleGlucoseValue))
+        let recommendation = ManualBolusRecommendation(amount: 1.25, pendingInsulin: 4.321, notice: BolusRecommendationNotice.glucoseBelowSuspendThreshold(minGlucose: Self.exampleGlucoseValue))
         delegate.loopState.bolusRecommendationResult = recommendation
         await bolusEntryViewModel.update()
         XCTAssertTrue(bolusEntryViewModel.isBolusRecommended)
@@ -318,7 +318,7 @@ class BolusEntryViewModelTests: XCTestCase {
 
     func testUpdateRecommendedBolusWithOtherNotice() async throws {
         XCTAssertFalse(bolusEntryViewModel.isBolusRecommended)
-        let recommendation = ManualBolusRecommendation(amount: 1.234, pendingInsulin: 4.321, notice: BolusRecommendationNotice.currentGlucoseBelowTarget(glucose: Self.exampleGlucoseValue))
+        let recommendation = ManualBolusRecommendation(amount: 1.25, pendingInsulin: 4.321, notice: BolusRecommendationNotice.currentGlucoseBelowTarget(glucose: Self.exampleGlucoseValue))
         delegate.loopState.bolusRecommendationResult = recommendation
         await bolusEntryViewModel.update()
         XCTAssertTrue(bolusEntryViewModel.isBolusRecommended)
@@ -382,7 +382,7 @@ class BolusEntryViewModelTests: XCTestCase {
         await setUpViewModel(originalCarbEntry: mockOriginalCarbEntry, potentialCarbEntry: mockPotentialCarbEntry)
         bolusEntryViewModel.manualGlucoseQuantity = Self.exampleManualGlucoseQuantity
         XCTAssertFalse(bolusEntryViewModel.isBolusRecommended)
-        let recommendation = ManualBolusRecommendation(amount: 1.234, pendingInsulin: 4.321)
+        let recommendation = ManualBolusRecommendation(amount: 1.25, pendingInsulin: 4.321)
         delegate.loopState.bolusRecommendationResult = recommendation
         await bolusEntryViewModel.update()
         XCTAssertTrue(bolusEntryViewModel.isBolusRecommended)
diff --git a/LoopUI/StatusBarHUDView.xib b/LoopUI/StatusBarHUDView.xib
index b56cfae23..f603d7cf9 100644
--- a/LoopUI/StatusBarHUDView.xib
+++ b/LoopUI/StatusBarHUDView.xib
@@ -131,7 +131,7 @@
                         <constraint firstItem="KzR-4q-Npx" firstAttribute="top" secondItem="MLJ-z5-oVV" secondAttribute="top" constant="10" id="Aoa-Yp-Y0v"/>
                         <constraint firstItem="KzR-4q-Npx" firstAttribute="leading" secondItem="BMR-SB-Ayc" secondAttribute="leading" constant="10" id="Cin-hu-S8N"/>
                         <constraint firstItem="oSZ-F8-Rb1" firstAttribute="trailing" secondItem="BMR-SB-Ayc" secondAttribute="trailing" id="FQq-0p-pJZ"/>
-                        <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="150" id="Nl5-qI-g5J"/>
+                        <constraint firstAttribute="width" relation="greaterThanOrEqual" priority="999" constant="150" id="Nl5-qI-g5J"/>
                         <constraint firstAttribute="trailing" secondItem="BMR-SB-Ayc" secondAttribute="trailing" id="VJX-X2-64n"/>
                         <constraint firstAttribute="trailing" secondItem="KzR-4q-Npx" secondAttribute="trailing" constant="6" id="YfI-gU-2nA"/>
                         <constraint firstItem="oSZ-F8-Rb1" firstAttribute="top" secondItem="BMR-SB-Ayc" secondAttribute="top" constant="-9" id="f9r-1G-yvo"/>
diff --git a/LoopUI/ViewModel/CGMStatusHUDViewModel.swift b/LoopUI/ViewModel/CGMStatusHUDViewModel.swift
index 584c91840..a26834e4b 100644
--- a/LoopUI/ViewModel/CGMStatusHUDViewModel.swift
+++ b/LoopUI/ViewModel/CGMStatusHUDViewModel.swift
@@ -61,6 +61,12 @@ public class CGMStatusHUDViewModel {
                 // If there is a current manual glucose, it displays the current status highlight icon
                 setManualGlucoseTrendIconOverride()
             }
+
+            if let localizedMessage = storedStatusHighlight?.localizedMessage.replacingOccurrences(of: "\n", with: " "),
+               let statusStateMessage = storedStatusHighlight?.state.localizedDescription
+            {
+                accessibilityString = localizedMessage + ", " + statusStateMessage
+            }
         }
     }
     
@@ -159,6 +165,12 @@ public class CGMStatusHUDViewModel {
         } else {
             glucoseTrendTintColor = .glucoseTintColor
         }
+
+        if let statusStateMessage = storedStatusHighlight?.state.localizedDescription,
+           let localizedMessage = storedStatusHighlight?.localizedMessage.replacingOccurrences(of: "\n", with: " ")
+        {
+            accessibilityStrings.append(localizedMessage + ", " + statusStateMessage)
+        }
                 
         unitsString = unit.localizedShortUnitString
         accessibilityString = accessibilityStrings.joined(separator: ", ")
diff --git a/LoopUI/Views/CGMStatusHUDView.swift b/LoopUI/Views/CGMStatusHUDView.swift
index 651087cd5..ad659445f 100644
--- a/LoopUI/Views/CGMStatusHUDView.swift
+++ b/LoopUI/Views/CGMStatusHUDView.swift
@@ -68,6 +68,8 @@ public final class CGMStatusHUDView: DeviceStatusHUDView, NibLoadable {
         defer {
             // when the status highlight is updated, the trend icon may also need to be updated
             updateTrendIcon()
+            // when the status highlight is updated, the accessibility string is updated
+            accessibilityValue = viewModel.accessibilityString
         }
         
         guard statusStackView.arrangedSubviews.contains(glucoseValueHUD),
@@ -89,6 +91,8 @@ public final class CGMStatusHUDView: DeviceStatusHUDView, NibLoadable {
         defer {
             // when the status highlight is updated, the trend icon may also need to be updated
             updateTrendIcon()
+            // when the status highlight is updated, the accessibility string is updated
+            accessibilityValue = viewModel.accessibilityString
         }
         
         guard statusStackView.arrangedSubviews.contains(statusHighlightView) else {
diff --git a/Scripts/apply-info-customizations.sh b/Scripts/apply-info-customizations.sh
new file mode 100755
index 000000000..705390103
--- /dev/null
+++ b/Scripts/apply-info-customizations.sh
@@ -0,0 +1,61 @@
+#!/bin/sh -e
+
+#  apply-info-customizations.sh
+#  Loop
+#
+#  Created by Pete Schwamb on 4/25/23.
+#  Copyright © 2023 LoopKit Authors. All rights reserved.
+
+
+SCRIPT="$(basename "${0}")"
+SCRIPT_DIRECTORY="$(dirname "${0}")"
+
+error() {
+  echo "ERROR: ${*}" >&2
+  echo "Usage: ${SCRIPT} [-i|--info-plist-path info-plist-path]" >&2
+  echo "Parameters:" >&2
+  echo "  -i|--info-plist-path <info-plist-path>                     path to the Info.plist file to modify; optional, defaults to \${BUILT_PRODUCTS_DIR}/\${INFOPLIST_PATH}" >&2
+  exit 1
+}
+
+warn() {
+  echo "WARN: ${*}" >&2
+}
+
+info() {
+  echo "INFO: ${*}" >&2
+}
+
+info_plist_path="${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}"
+while [[ $# -gt 0 ]]
+do
+  case $1 in
+    -i|--info-plist-path)
+      info_plist_path="${2}"
+      shift 2
+      ;;
+  esac
+done
+
+if [ ${#} -ne 0 ]; then
+  error "Unexpected arguments: ${*}"
+fi
+
+if [ "${info_plist_path}" == "/" -o ! -e "${info_plist_path}" ]; then
+  error "Must provide valid --info-plist-path, or have valid \${BUILT_PRODUCTS_DIR} and \${INFOPLIST_PATH} set."
+fi
+
+info "Applying info.plist customizations from ../InfoCustomizations.txt"
+
+while read -r -a words; do                # iterate over lines of input
+  set -- "${words[@]}"                 # update positional parameters
+  for word; do
+    if [[ $word = *"="* ]]; then       # if a word contains an "="...
+        key=${word%%=*}
+        value=${word#*=}
+        echo "Key = $key"
+        echo "Value = $value"
+        plutil -replace $key -string "${value}" "${info_plist_path}"
+    fi
+  done
+done <"../InfoCustomizations.txt"
diff --git a/Scripts/install-scenarios.sh b/Scripts/install-scenarios.sh
new file mode 100755
index 000000000..36440d644
--- /dev/null
+++ b/Scripts/install-scenarios.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+#  install-scenarios.sh
+#  Loop
+#
+#  Created by Pete Schwamb on 12/19/22.
+#  Copyright © 2022 LoopKit Authors. All rights reserved.
+
+SCENARIOS_DIR="$WORKSPACE_ROOT"/Scenarios
+
+if [ -d "$SCENARIOS_DIR" ]
+then
+    echo "$SCENARIOS_DIR exists. Installing scenarios."
+    echo cp -a "$SCENARIOS_DIR" "${BUILT_PRODUCTS_DIR}/Scenarios"
+    cp -a "$SCENARIOS_DIR" "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Scenarios"
+else
+    echo "Scenarios missing or not configured... Not installing."
+fi
diff --git a/StatusWidget/StatusWidget.swift b/StatusWidget/StatusWidget.swift
index 71202c15b..8aa044725 100644
--- a/StatusWidget/StatusWidget.swift
+++ b/StatusWidget/StatusWidget.swift
@@ -223,7 +223,6 @@ extension Date {
     }
 }
 
-@main
 struct SmallStatusWidget: Widget {
     let kind: String = "SmallStatusWidget"
 
@@ -236,3 +235,10 @@ struct SmallStatusWidget: Widget {
         .supportedFamilies([.systemSmall])
     }
 }
+
+@main
+struct SmallStatusWidgets: WidgetBundle {
+    var body: some Widget {
+        SmallStatusWidget()
+   }
+}
diff --git a/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift b/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift
index b06e16032..0592bf777 100644
--- a/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift	
+++ b/WatchApp Extension/Views/Carb Entry & Bolus/BolusInput.swift	
@@ -102,10 +102,10 @@ fileprivate extension Collection where Element == Decimal {
     /// - Precondition: The collection is sorted in ascending order.
     func deltaScale(boundedBy maxScale: Int) -> Int {
         let roundedToMaxScale = lazy.map { $0.rounded(toPlaces: maxScale) }
-        guard let maxDelta = roundedToMaxScale.adjacentPairs().map(-).map(abs).max() else {
+        guard let minDelta = roundedToMaxScale.adjacentPairs().map(-).map(abs).min() else {
             return 0
         }
 
-        return abs(Swift.min(maxDelta.exponent, 0))
+        return abs(Swift.min(minDelta.exponent, 0))
     }
 }
