fix(feedback): don't count errored sessions; mark review asked before requesting

Review findings on the store-review prompt:

1. SessionStatus has no error variant and session.error never touches
   sessionStatus, so an errored session still ends busy -> idle and was
   counted as a success — potentially burning the once-ever review prompt
   on a failed run. Track an erroredSessions set: mark in the
   session.error handler, clear when the session goes busy again (new
   run) and on disconnect, and skip recordSuccessfulSession() on the
   busy -> idle transition if the session errored.

2. ASKED_KEY was persisted only after requestReview() resolved. On iOS
   requestReview() can throw (MissingCurrentWindowSceneException while
   backgrounded — likely, since sessions often complete in background),
   which would retry the prompt on later successes, violating the
   "at most once, ever" contract. Persist ASKED_KEY before calling
   requestReview(); a failed attempt consumes the one shot.
This commit is contained in:
engineer
2026-07-16 15:53:24 -07:00
parent d3ee3d9e82
commit d4555d45b4
2 changed files with 24 additions and 4 deletions

View File

@@ -59,8 +59,13 @@ async function recordSuccessfulSessionInternal(): Promise<void> {
const available = await StoreReview.isAvailableAsync()
if (!available) return
await StoreReview.requestReview()
// Mark as asked BEFORE requesting: on iOS requestReview() can throw
// (e.g. MissingCurrentWindowSceneException while backgrounded — likely,
// since sessions often complete in the background). A failed attempt
// consumes the one shot; that beats retrying and violating the
// "at most once, ever" contract.
await SecureStore.setItemAsync(ASKED_KEY, "true")
await StoreReview.requestReview()
} catch {
// A review-prompt failure must never affect session handling.
}