Skip to content

fix(tts): reject cancel_synthesis for terminal entry statuses - #178

Merged
xilec merged 1 commit into
mainfrom
fix/176-cancel-entry-guard
Aug 1, 2026
Merged

fix(tts): reject cancel_synthesis for terminal entry statuses#178
xilec merged 1 commit into
mainfrom
fix/176-cancel-entry-guard

Conversation

@xilec

@xilec xilec commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • cancel_entry previously flipped any entry to pending unconditionally. A cancel arriving after the entry left processing (the race fixed frontend-side in feat(ui): expose cancel_synthesis in the queue entry menu #174: synthesis finishes while the context menu is open) silently regressed a ready/error entry and orphaned its audio from the state machine (playback requires ready; the entry would be re-synthesized on the next trigger).
  • Now ready/playing/error are rejected with synthesis_error before touching the registries or storage — same error style as play_entry's "entry is not ready".
  • pending stays allowed deliberately: cancel is idempotent for idle entries (existing feat(tts): make cancel_synthesis actually stop synthesis #129 orchestration test pins this), and a just-added entry briefly sits in pending with its synthesis task already registered — rejecting it would break that window.
  • OpenSpec change harden-cancel-entry-status-guard archived; ipc-commands spec updated (idle-cancel allowed, terminal-entry rejection, new scenarios).

Test plan

  • cargo test — 974 passed (new: reject ready/error with registries untouched; pending with a registered task still aborts it)
  • just lint green
  • openspec validate --specs --strict green

Follow-up (not in this PR)

A µs-scale read-decide-write race remains between require_entry and update_entry (guard reads a clone, synthesis can complete before the write). Closing it needs a storage-level compare-and-set, which would also harden apply_ready_if_current/apply_error_if_current — will be filed as a separate tech-debt issue.

Closes #176

cancel_entry flipped any entry to pending unconditionally, so a cancel
arriving after the entry left processing (race: synthesis finished while
the UI menu was open) silently regressed a ready/error entry and orphaned
its audio from the state machine. Now ready/playing/error are rejected
with synthesis_error before touching registries or storage. pending stays
allowed: cancel is idempotent for idle entries (#129 semantics) and a
just-added entry briefly sits in pending with its task already
registered.
@xilec
xilec merged commit 3790848 into main Aug 1, 2026
6 checks passed
@xilec
xilec deleted the fix/176-cancel-entry-guard branch August 1, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

harden cancel_entry against non-processing entries

1 participant