UX-NB-002 — Make Save, Discard, and Cancel truthful
| Field | Value |
|---|---|
| Status | Open; source-verified |
| Architecture state | Source-backed current behavior |
| Severity | High |
| Affected surface | Closing active and background notebook tabs with unsaved changes |
| Components | sparqd/oqullus |
| Associated issue | oqullus #518 |
Where the problem appears
Close active and background dirty tabs and exercise Save Changes, Discard, and Cancel while recording which notebook is written and how many requests occur.
Concrete observed case
The close path invokes a parameterless save before resolving the tab being closed. Discard continues through that saving path, while Save Changes can save once explicitly and again during close. A background close can target the active tab.
Expected condition
Save and Close writes the selected tab exactly once and closes only after success. Discard and Close performs no save. Cancel performs no mutation. Compute shutdown remains a separate choice.
Cause and evidence
Save is scoped to the active tab while close accepts a target tab ID. The dialog branches converge on a close function that saves again, and failed saves can be reported as success.
Why it matters
The current labels cannot be trusted: users may lose the intended notebook, save a different one, or preserve content they explicitly chose to discard.
Existing controls and workarounds
Manually save the intended tab before closing and verify its saved state. Avoid closing background dirty tabs until targeting is corrected.
Alternatives considered
- Recommended: one atomic tab-scoped decision with a supplied content snapshot and expected version.
- Always autosave on close — rejected because it removes a real Discard choice.
- Remove confirmation — rejected while persistence can fail or target the wrong document.
Component involvement
sparqd/oqullusowns target resolution, the three choices, request count, failure handling, and separation from compute shutdown.
Reproduction and verification
Follow NB-S017.
Resolution conditions
Close when active/background tabs receive the intended atomic outcome, request counts are exact, and failure never closes or clears dirty state unexpectedly.
Validation and blockers
Source behavior is confirmed; deployed request capture remains pending.