uttrflow / uttrflow/uttrflow-swift
SuggestionSession restores alternatives removed by the latest verification result
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 277
Description
## Problem
On main `8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d`, the session can keep offering an alternative that is absent from the current verified candidates.
[SuggestionSession.settle, lines 394–408](https://github.com/uttrflow/uttrflow-swift/blob/8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d/Sources/UttrflowPredict/SuggestionSession.swift#L394-L408) preserves the old alternatives whenever a new `.certain` result has the same leader as the previous `.choice`. It filters those alternatives only for matching the typed prefix. It never checks whether they survived the latest verification.
Consequently, `resolve(_:for:now:elapsedMilliseconds:)` can receive a verified list containing only A and return an armed choice containing A and the old B. A previously plausible candidate that no longer survives the gates is still selectable.
## Verified reproduction
An isolated regression uses the unchanged production `SuggestionSession` and `KeyRouting`, with two valid successive query/verification requests for the same surface and typed prefix `git c`:
1. Resolve the first request with `git commit` (five uses) and `git checkout` (four uses). Confirm the result is a choice with `git commit` leading.
2. Begin another turn for the same surface/prefix and resolve its verification request with **only `git commit`**.
3. Expected: `.certain("git commit")` and no Down-arrow interception.
4. Actual: `.choice(leader: "git commit", others: ["git checkout"])`, still arming Down.
5. Route Down once, then Tab. Actual action: `.accept("git checkout")`, although that text was omitted from the new verified result.
All three regression assertions fail on main: old alternative removed, Down disarmed, and old alternative not accepted. This is a deterministic session-boundary test, not a live model or UI test; verified candidate arrays are supplied directly to the session.
The existing `aRedrawOfTheSameLineKeepsItsList` test intentionally preserves generated alternatives across corpus redraws, but does not distinguish that situation from an authoritative verification result removing an alternative.
## Acceptance criteria
- A completed verification result cannot restore alternatives absent from that result.
- If generated alternatives must survive a corpus-only redraw, track their origin and validity explicitly so this does not also preserve candidates removed by verification.
- Add the two-turn regression, including keyboard routing, and retain coverage for valid generated alternatives surviving appropriate redraws.
- Apply quiet-mode filtering and selection bounds consistently when retaining any list.
Priority: P2 (stale suggestions remain actionable).
Separate from #764 / PR #768: those improve candidate validation; this failure happens after the current verified set has already been supplied to the session.
Contributor guide
Research direction
Start in Sources/UttrflowPredict/SuggestionSession.swift at settle and resolve, then inspect KeyRouting and the existing aRedrawOfTheSameLineKeepsItsList test. Reproduce the two successive verification requests with git commit and git checkout, add regression coverage for session state and Down/Tab routing, and retain valid generated alternatives across appropriate corpus redraws.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100