Fix setup wizard runtime spinner and prepare 1.0.2 hotfix - #1254
Conversation
|
Bug: timeout path in In But the post-loop "did not finish" fallback only fires for the guard shouldRetry else {
if completedAttempts >= ServiceStatusEvaluator.transientRefreshAttemptLimit,
runtimeStatus == .starting
{
await MainActor.run {
serviceStatus = .failed(error: "Runtime startup did not finish. Click Restart to retry.")
}
}
return
}If the runtime stays Suggested fix: broaden the condition to cover both timeout branches, e.g. reuse the same predicate used for retrying: if completedAttempts >= ServiceStatusEvaluator.transientRefreshAttemptLimit,
runtimeStatus == .starting || (runtimeStatus == .stopped && isInTransientStartupWindow)
{
...
}Also note the new tests ( |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04731b0961
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if completedAttempts >= ServiceStatusEvaluator.transientRefreshAttemptLimit, | ||
| runtimeStatus == .starting |
There was a problem hiding this comment.
Finish capped retries for transient stopped states
When currentRuntimeStatus() returns .stopped while isInTransientRuntimeStartupWindow() remains true, the 30th observation has already mapped the UI to .starting, but this condition handles only a literal .starting runtime status and then returns with no polling task left. This occurs during the 140-second initial/start grace window and indefinitely for pending SMAppService approval, so a runtime that becomes healthy after the cutoff is never observed and the setup page remains on the spinner without exposing Start or the required approval action. Continue through the authoritative startup window or transition both transient .starting and .stopped states to an explicit terminal state at the cap.
AGENTS.md reference: AGENTS.md:L311-L316
Useful? React with 👍 / 👎.
|
Addressed in |
|
Review notes on the
Nothing else stood out; the pure-function logic in |
|
Follow-up on the latest review notes:
No additional permission-polling surface is being restored. |
What changed
Root cause
The runtime service page performed a single status observation. Its broad auto-refresh timer had previously been disabled to avoid invasive permission checks. If the one observation landed during the brief runtime startup window, the page rendered “Starting KeyPath runtime…” forever even after the runtime became healthy.
User impact
Users who launch KeyPath during that transition can now progress automatically once the already-healthy runtime is observed. The retry is bounded and runtime-only; it does not restore broad permission polling.
Validation
swift test --filter ServiceStatusEvaluatorActionTests— 7 passed.plutil -lint Sources/KeyPathApp/Info.plist— passed.git diff --check— passed.