@hasna/recordings 0.2.10 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +350 -35
- package/bun.lock +3 -0
- package/dist/__tests__/helpers/native-fs-guard.d.ts +2 -0
- package/dist/__tests__/helpers/native-fs-guard.d.ts.map +1 -0
- package/dist/cli/index.js +1728 -320
- package/dist/cli/macos-permissions.d.ts +13 -0
- package/dist/cli/macos-permissions.d.ts.map +1 -0
- package/dist/cli/options.d.ts +12 -0
- package/dist/cli/options.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/db/recordings.d.ts +2 -1
- package/dist/db/recordings.d.ts.map +1 -1
- package/dist/db/remote-storage.d.ts +5 -1
- package/dist/db/remote-storage.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +628 -147
- package/dist/lib/bun-runtime.d.ts +11 -0
- package/dist/lib/bun-runtime.d.ts.map +1 -0
- package/dist/lib/config.d.ts +8 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/enhancer.d.ts +10 -2
- package/dist/lib/enhancer.d.ts.map +1 -1
- package/dist/lib/install-maintenance.d.ts +24 -0
- package/dist/lib/install-maintenance.d.ts.map +1 -0
- package/dist/lib/machine.d.ts +2 -0
- package/dist/lib/machine.d.ts.map +1 -0
- package/dist/lib/recorder.d.ts +2 -1
- package/dist/lib/recorder.d.ts.map +1 -1
- package/dist/lib/recording-create-identity.d.ts +13 -0
- package/dist/lib/recording-create-identity.d.ts.map +1 -0
- package/dist/lib/release-install-policy.d.ts +31 -0
- package/dist/lib/release-install-policy.d.ts.map +1 -0
- package/dist/lib/transcriber.d.ts.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +977 -194
- package/dist/sdk/index.js +5 -1
- package/dist/sdk/v1.generated.d.ts +4 -0
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/cloud-config.d.ts +9 -0
- package/dist/server/cloud-config.d.ts.map +1 -0
- package/dist/server/cloud-readiness.d.ts +10 -0
- package/dist/server/cloud-readiness.d.ts.map +1 -0
- package/dist/server/cloud.d.ts +9 -18
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +1654 -304
- package/dist/server/migrate-command.d.ts +11 -0
- package/dist/server/migrate-command.d.ts.map +1 -0
- package/dist/server/openapi.d.ts +22 -0
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/repo.d.ts +8 -1
- package/dist/server/repo.d.ts.map +1 -1
- package/dist/server/serve.d.ts +6 -1
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage.js +515 -80
- package/dist/store.d.ts +3 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +7 -4
- package/packaging/macos/Empty.entitlements +5 -0
- package/packaging/macos/Library/LaunchDaemons/com.hasna.recordings.updater.plist +34 -0
- package/packaging/macos/Verifier.entitlements +10 -0
- package/packaging/macos/artifact-verifier.sb +33 -0
- package/packaging/macos/build_release_pkg.sh +872 -0
- package/packaging/macos/managed_bootstrap.sh +623 -0
- package/packaging/macos/pkgutil_fingerprint.awk +37 -0
- package/packaging/macos/release_lifecycle.ts +463 -0
- package/packaging/macos/scripts/postinstall +565 -0
- package/packaging/macos/scripts/preinstall +297 -0
- package/scripts/build_companion_cli.sh +337 -0
- package/scripts/build_native_fs_guard.sh +59 -0
- package/scripts/generate-sdk.ts +19 -1
- package/scripts/install_macos_app.sh +1922 -77
- package/scripts/macos_artifact.ts +5316 -0
- package/scripts/migrate.ts +38 -10
- package/scripts/native/prebuilds/darwin-universal/recordings_fs_guard.node +0 -0
- package/scripts/native/recordings_fs_guard.c +1167 -0
- package/scripts/native_fs_guard.ts +158 -0
- package/scripts/release-guard.ts +20 -1
- package/scripts/resolve_tailscale_cli.sh +389 -0
- package/scripts/smoke_macos_app.sh +573 -0
- package/src/native/Recordings/App/ContentView.swift +83 -0
- package/src/native/Recordings/App/MenuBarStatusView.swift +102 -0
- package/src/native/Recordings/App/RecordWorkspaceView.swift +468 -0
- package/src/native/Recordings/App/RecordingDetailView.swift +138 -0
- package/src/native/Recordings/App/RecordingsApp.swift +367 -44
- package/src/native/Recordings/App/RecordingsListView.swift +130 -0
- package/src/native/Recordings/App/RecordingsStore.swift +206 -0
- package/src/native/Recordings/App/RuntimeSmoke.swift +158 -0
- package/src/native/Recordings/App/SidebarView.swift +212 -0
- package/src/native/Recordings/App/Theme.swift +87 -0
- package/src/native/Recordings/Package.resolved +5 -5
- package/src/native/Recordings/Package.swift +62 -2
- package/src/native/Recordings/RecordingsLib/AccessibilityPromptGate.swift +104 -0
- package/src/native/Recordings/RecordingsLib/BrandAssets.swift +0 -32
- package/src/native/Recordings/RecordingsLib/ChromeSurface.swift +17 -0
- package/src/native/Recordings/RecordingsLib/Info.plist +7 -3
- package/src/native/Recordings/RecordingsLib/MenuBarPresentation.swift +37 -0
- package/src/native/Recordings/RecordingsLib/NativeAppDiagnostics.swift +32 -2
- package/src/native/Recordings/RecordingsLib/NativeMachineIdentity.swift +24 -0
- package/src/native/Recordings/RecordingsLib/NativePCMRecorder.swift +262 -23
- package/src/native/Recordings/RecordingsLib/OpenAIAPIKeyStore.swift +56 -0
- package/src/native/Recordings/RecordingsLib/PermissionRequestLaunchPlan.swift +56 -0
- package/src/native/Recordings/RecordingsLib/ProjectStore.swift +321 -25
- package/src/native/Recordings/RecordingsLib/RealtimeTranscriptionClient.swift +605 -90
- package/src/native/Recordings/RecordingsLib/Recording.swift +141 -0
- package/src/native/Recordings/RecordingsLib/RecordingEngine.swift +3704 -376
- package/src/native/Recordings/RecordingsLib/RecordingStartControlPresentation.swift +29 -0
- package/src/native/Recordings/RecordingsLib/RecordingsCLI.entitlements +10 -0
- package/src/native/Recordings/RecordingsLib/RecordingsCLI.swift +222 -0
- package/src/native/Recordings/RecordingsLib/SettingsView.swift +45 -11
- package/src/native/Recordings/RecordingsLib/SpeechIntent.swift +331 -0
- package/src/native/Recordings/RecordingsLib/SpeechIntentClassifier.swift +232 -0
- package/src/native/Recordings/RecordingsLib/VoiceShortcuts.swift +17 -7
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +1343 -0
- package/src/native/Recordings/RecordingsTests/MenuBarPresentationTests.swift +98 -0
- package/src/native/Recordings/RecordingsTests/NativeAppDiagnosticsTests.swift +20 -0
- package/src/native/Recordings/RecordingsTests/NativePCMRecorderTests.swift +370 -1
- package/src/native/Recordings/RecordingsTests/PasteTargetTests.swift +987 -1
- package/src/native/Recordings/RecordingsTests/ProjectStoreTests.swift +385 -0
- package/src/native/Recordings/RecordingsTests/RealtimeTranscriptionTests.swift +835 -8
- package/src/native/Recordings/RecordingsTests/RecordingBridgeTests.swift +180 -0
- package/src/native/Recordings/RecordingsTests/RecordingEngineDeliveryTests.swift +760 -0
- package/src/native/Recordings/RecordingsTests/RecordingStartControlPresentationTests.swift +42 -0
- package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +264 -0
- package/src/native/Recordings/RecordingsTests/RecordingStartTimingTests.swift +129 -0
- package/src/native/Recordings/RecordingsTests/SpeechIntentTests.swift +600 -0
- package/src/native/Recordings/RecordingsTests/TranscriptResolutionTests.swift +62 -1
- package/src/native/Recordings/RecordingsTests/TranscriptionResultIdentityTests.swift +21 -0
- package/src/native/Recordings/Updater/BootstrapPreflight/BootstrapPreflightMain.swift +739 -0
- package/src/native/Recordings/Updater/Broker/ActivationRecoveryPolicy.swift +254 -0
- package/src/native/Recordings/Updater/Broker/ApplicationNamespace.swift +463 -0
- package/src/native/Recordings/Updater/Broker/ApplicationProcessQuiescence.swift +55 -0
- package/src/native/Recordings/Updater/Broker/ArtifactIngest.swift +341 -0
- package/src/native/Recordings/Updater/Broker/AtomicActivation.swift +477 -0
- package/src/native/Recordings/Updater/Broker/BrokerMain.swift +624 -0
- package/src/native/Recordings/Updater/Broker/CanonicalTreeCopy.swift +63 -0
- package/src/native/Recordings/Updater/Broker/CodeValidation.swift +561 -0
- package/src/native/Recordings/Updater/Broker/DarwinACLValidator.swift +66 -0
- package/src/native/Recordings/Updater/Broker/HostOSProductVersion.swift +50 -0
- package/src/native/Recordings/Updater/Broker/InstallJournal.swift +362 -0
- package/src/native/Recordings/Updater/Broker/InstallRecovery.swift +662 -0
- package/src/native/Recordings/Updater/Broker/MonotonicState.swift +456 -0
- package/src/native/Recordings/Updater/Broker/PeerIdentity.swift +274 -0
- package/src/native/Recordings/Updater/Broker/VerifierRunner.swift +81 -0
- package/src/native/Recordings/Updater/BrokerTests/ActivationRecoveryPolicyTests.swift +259 -0
- package/src/native/Recordings/Updater/BrokerTests/CanonicalReleaseOrderTests.swift +21 -0
- package/src/native/Recordings/Updater/Client/ClientMain.swift +119 -0
- package/src/native/Recordings/Updater/Protocol/BoundedProcess.swift +159 -0
- package/src/native/Recordings/Updater/Protocol/CandidateMetadataPolicy.swift +214 -0
- package/src/native/Recordings/Updater/Protocol/HostOSVersionPolicy.swift +55 -0
- package/src/native/Recordings/Updater/Protocol/MonotonicReleasePolicy.swift +152 -0
- package/src/native/Recordings/Updater/Protocol/ReleaseEnvelope.swift +229 -0
- package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +119 -0
- package/src/native/Recordings/Updater/ProtocolTests/BoundedProcessRunnerTests.swift +60 -0
- package/src/native/Recordings/Updater/ProtocolTests/CandidateMetadataPolicyTests.swift +168 -0
- package/src/native/Recordings/Updater/ProtocolTests/HostOSVersionPolicyTests.swift +62 -0
- package/src/native/Recordings/Updater/ProtocolTests/MonotonicReleasePolicyTests.swift +172 -0
- package/src/native/Recordings/Updater/ProtocolTests/ReleaseEnvelopeValidationTests.swift +65 -0
- package/src/native/Recordings/Updater/Signer/SignerMain.swift +210 -0
- package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +725 -0
- package/src/native/Recordings/Updater/VerifierLauncher/include/RecordingsVerifierLauncher.h +33 -0
- package/src/native/Recordings/build.sh +1990 -29
- package/src/native/Recordings/RecordingsLib/MenuBarPopover.swift +0 -380
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
struct ApplicationNamespaceSnapshot: Equatable, Sendable {
|
|
4
|
+
let live: String?
|
|
5
|
+
let candidateSlot: String?
|
|
6
|
+
let previousSlot: String?
|
|
7
|
+
let failedSlot: String?
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
enum CommitRecoveryAction: Equatable, Sendable {
|
|
11
|
+
case exchangeCandidateAndLive
|
|
12
|
+
case installCandidateExclusively
|
|
13
|
+
case retainPrevious
|
|
14
|
+
case ready
|
|
15
|
+
case invalid
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
enum RollbackRecoveryAction: Equatable, Sendable {
|
|
19
|
+
case exchangeCandidateAndLive
|
|
20
|
+
case exchangePreviousAndLive
|
|
21
|
+
case retainFailedFromPrevious
|
|
22
|
+
case retainFailedFromLive
|
|
23
|
+
case ready
|
|
24
|
+
case invalid
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
enum MonotonicBarrierPhase: Equatable, Sendable {
|
|
28
|
+
case seen
|
|
29
|
+
case aborted
|
|
30
|
+
case committed
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
enum PreparedBarrierRecoveryAction: Equatable, Sendable {
|
|
34
|
+
case recover
|
|
35
|
+
case discard
|
|
36
|
+
case invalid
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
enum RolledBackBarrierRecoveryAction: Equatable, Sendable {
|
|
40
|
+
case finalizeAbortThenPrune
|
|
41
|
+
case prune
|
|
42
|
+
case invalid
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
enum BootstrapRecoveryAction: Equatable, Sendable {
|
|
46
|
+
case discardBeforeSeen
|
|
47
|
+
case finalizeCommit
|
|
48
|
+
case validateCommitted
|
|
49
|
+
case prune
|
|
50
|
+
case invalid
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
enum BootstrapJournalPhase: Equatable, Sendable {
|
|
54
|
+
case prepared
|
|
55
|
+
case commitPending
|
|
56
|
+
case aborted
|
|
57
|
+
case committed
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// Pure bootstrap commit recovery. The broker performs no application namespace
|
|
61
|
+
/// mutation for bootstrap; recovery either closes a provably pre-seen journal or
|
|
62
|
+
/// commits the exact journal/state/candidate binding without envelope replay.
|
|
63
|
+
enum BootstrapRecoveryPolicy {
|
|
64
|
+
static func action(
|
|
65
|
+
journalPhase: BootstrapJournalPhase,
|
|
66
|
+
currentPhase: MonotonicBarrierPhase?,
|
|
67
|
+
exactBinding: Bool,
|
|
68
|
+
priorMonotonicStateWasAbsent: Bool,
|
|
69
|
+
candidateMatches: Bool
|
|
70
|
+
) -> BootstrapRecoveryAction {
|
|
71
|
+
guard priorMonotonicStateWasAbsent else { return .invalid }
|
|
72
|
+
|
|
73
|
+
guard let currentPhase else {
|
|
74
|
+
switch journalPhase {
|
|
75
|
+
case .prepared: return .discardBeforeSeen
|
|
76
|
+
case .aborted: return .prune
|
|
77
|
+
case .commitPending, .committed: return .invalid
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
guard exactBinding, candidateMatches else { return .invalid }
|
|
82
|
+
switch (currentPhase, journalPhase) {
|
|
83
|
+
case (.seen, .prepared), (.seen, .commitPending):
|
|
84
|
+
return .finalizeCommit
|
|
85
|
+
case (.committed, .prepared), (.committed, .commitPending):
|
|
86
|
+
return .validateCommitted
|
|
87
|
+
case (.committed, .committed):
|
|
88
|
+
return .prune
|
|
89
|
+
default:
|
|
90
|
+
return .invalid
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Pure recovery decisions shared by live activation and startup recovery. Each
|
|
96
|
+
/// namespace shape corresponds to a crash/failure boundary before or after one
|
|
97
|
+
/// descriptor-relative rename and its directory fsync/phase-journal update.
|
|
98
|
+
enum ActivationRecoveryPolicy {
|
|
99
|
+
static func preparedBarrierAction(
|
|
100
|
+
currentPhase: MonotonicBarrierPhase?,
|
|
101
|
+
currentSequence: UInt64?,
|
|
102
|
+
journalSequence: UInt64,
|
|
103
|
+
exactBinding: Bool,
|
|
104
|
+
sameCohort: Bool
|
|
105
|
+
) -> PreparedBarrierRecoveryAction {
|
|
106
|
+
guard let currentPhase, let currentSequence else { return .discard }
|
|
107
|
+
if currentPhase == .seen, exactBinding { return .recover }
|
|
108
|
+
if currentPhase == .aborted, exactBinding { return .discard }
|
|
109
|
+
if (currentPhase == .committed || currentPhase == .aborted),
|
|
110
|
+
sameCohort,
|
|
111
|
+
currentSequence < journalSequence {
|
|
112
|
+
return .discard
|
|
113
|
+
}
|
|
114
|
+
return .invalid
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static func rolledBackBarrierAction(
|
|
118
|
+
currentPhase: MonotonicBarrierPhase?,
|
|
119
|
+
currentSequence: UInt64?,
|
|
120
|
+
journalSequence: UInt64,
|
|
121
|
+
exactBinding: Bool,
|
|
122
|
+
sameCohort: Bool
|
|
123
|
+
) -> RolledBackBarrierRecoveryAction {
|
|
124
|
+
guard let currentPhase, let currentSequence else { return .prune }
|
|
125
|
+
if currentPhase == .seen, exactBinding { return .finalizeAbortThenPrune }
|
|
126
|
+
if currentPhase == .aborted, exactBinding { return .prune }
|
|
127
|
+
if (currentPhase == .committed || currentPhase == .aborted), sameCohort {
|
|
128
|
+
if currentSequence != journalSequence { return .prune }
|
|
129
|
+
}
|
|
130
|
+
return .invalid
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static func commitAction(
|
|
134
|
+
snapshot: ApplicationNamespaceSnapshot,
|
|
135
|
+
previousDigest: String?,
|
|
136
|
+
candidateDigest: String
|
|
137
|
+
) -> CommitRecoveryAction {
|
|
138
|
+
if let previousDigest {
|
|
139
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
140
|
+
live: previousDigest,
|
|
141
|
+
candidateSlot: candidateDigest,
|
|
142
|
+
previousSlot: nil,
|
|
143
|
+
failedSlot: nil
|
|
144
|
+
) {
|
|
145
|
+
return .exchangeCandidateAndLive
|
|
146
|
+
}
|
|
147
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
148
|
+
live: candidateDigest,
|
|
149
|
+
candidateSlot: previousDigest,
|
|
150
|
+
previousSlot: nil,
|
|
151
|
+
failedSlot: nil
|
|
152
|
+
) {
|
|
153
|
+
return .retainPrevious
|
|
154
|
+
}
|
|
155
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
156
|
+
live: candidateDigest,
|
|
157
|
+
candidateSlot: nil,
|
|
158
|
+
previousSlot: previousDigest,
|
|
159
|
+
failedSlot: nil
|
|
160
|
+
) {
|
|
161
|
+
return .ready
|
|
162
|
+
}
|
|
163
|
+
return .invalid
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
167
|
+
live: nil,
|
|
168
|
+
candidateSlot: candidateDigest,
|
|
169
|
+
previousSlot: nil,
|
|
170
|
+
failedSlot: nil
|
|
171
|
+
) {
|
|
172
|
+
return .installCandidateExclusively
|
|
173
|
+
}
|
|
174
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
175
|
+
live: candidateDigest,
|
|
176
|
+
candidateSlot: nil,
|
|
177
|
+
previousSlot: nil,
|
|
178
|
+
failedSlot: nil
|
|
179
|
+
) {
|
|
180
|
+
return .ready
|
|
181
|
+
}
|
|
182
|
+
return .invalid
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static func rollbackAction(
|
|
186
|
+
snapshot: ApplicationNamespaceSnapshot,
|
|
187
|
+
previousDigest: String?,
|
|
188
|
+
candidateDigest: String
|
|
189
|
+
) -> RollbackRecoveryAction {
|
|
190
|
+
if let previousDigest {
|
|
191
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
192
|
+
live: previousDigest,
|
|
193
|
+
candidateSlot: candidateDigest,
|
|
194
|
+
previousSlot: nil,
|
|
195
|
+
failedSlot: nil
|
|
196
|
+
) || snapshot == ApplicationNamespaceSnapshot(
|
|
197
|
+
live: previousDigest,
|
|
198
|
+
candidateSlot: nil,
|
|
199
|
+
previousSlot: nil,
|
|
200
|
+
failedSlot: candidateDigest
|
|
201
|
+
) {
|
|
202
|
+
return .ready
|
|
203
|
+
}
|
|
204
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
205
|
+
live: previousDigest,
|
|
206
|
+
candidateSlot: nil,
|
|
207
|
+
previousSlot: candidateDigest,
|
|
208
|
+
failedSlot: nil
|
|
209
|
+
) {
|
|
210
|
+
return .retainFailedFromPrevious
|
|
211
|
+
}
|
|
212
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
213
|
+
live: candidateDigest,
|
|
214
|
+
candidateSlot: previousDigest,
|
|
215
|
+
previousSlot: nil,
|
|
216
|
+
failedSlot: nil
|
|
217
|
+
) {
|
|
218
|
+
return .exchangeCandidateAndLive
|
|
219
|
+
}
|
|
220
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
221
|
+
live: candidateDigest,
|
|
222
|
+
candidateSlot: nil,
|
|
223
|
+
previousSlot: previousDigest,
|
|
224
|
+
failedSlot: nil
|
|
225
|
+
) {
|
|
226
|
+
return .exchangePreviousAndLive
|
|
227
|
+
}
|
|
228
|
+
return .invalid
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
232
|
+
live: nil,
|
|
233
|
+
candidateSlot: candidateDigest,
|
|
234
|
+
previousSlot: nil,
|
|
235
|
+
failedSlot: nil
|
|
236
|
+
) || snapshot == ApplicationNamespaceSnapshot(
|
|
237
|
+
live: nil,
|
|
238
|
+
candidateSlot: nil,
|
|
239
|
+
previousSlot: nil,
|
|
240
|
+
failedSlot: candidateDigest
|
|
241
|
+
) {
|
|
242
|
+
return .ready
|
|
243
|
+
}
|
|
244
|
+
if snapshot == ApplicationNamespaceSnapshot(
|
|
245
|
+
live: candidateDigest,
|
|
246
|
+
candidateSlot: nil,
|
|
247
|
+
previousSlot: nil,
|
|
248
|
+
failedSlot: nil
|
|
249
|
+
) {
|
|
250
|
+
return .retainFailedFromLive
|
|
251
|
+
}
|
|
252
|
+
return .invalid
|
|
253
|
+
}
|
|
254
|
+
}
|