Recording (audio and MIDI) mutated the document directly in the AudioEvent
handlers, outside the action system — so it was never undoable, and dirty-
tracking leaned on an ad-hoc `media_modified` flag that the MIDI stop handler
forgot to set (hence: recording a MIDI clip didn't trigger the save-on-close
prompt).
Recording is temporal (the clip streams into the document live over the take),
so it can't be applied by one synchronous execute(). Instead, commit the
finished take as an *already-applied* action:
- ActionExecutor::push_applied(action) — registers an action whose effect is
already present (clears redo, bumps the epoch so the doc reads as modified,
pushes to the undo stack) WITHOUT re-running execute()/execute_backend().
Undo then removes the content via rollback/rollback_backend; redo re-adds it.
- AddClipInstanceAction::already_applied(...) — constructs the action pre-seeded
into its post-execute state (executed + the existing backend clip id) so the
first undo can remove the live-recorded clip from both doc and backend, and
redo re-adds it through the normal path.
- Both recording stop handlers now finalize, then push_applied this action.
Keeping the clip in the document (not a transient) matters for streaming-to-
disk and keeps the doc the single source of truth.
Recordings now bump the epoch like every other edit, so the media_modified
flag is dropped for recordings (kept only as a defensive fallback if the action
can't be built). Whole workspace compiles; 299 core tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>