Problem
The anchored byte-artifact transaction deliberately catches BaseException so reverse rollback can continue across every recorded mutation. Its final aggregation currently converts every rollback failure into an OSError, including KeyboardInterrupt, SystemExit, and other control-flow exceptions.
A transaction interrupted during rollback therefore reports the earlier ordinary I/O failure instead of the cancellation signal. Completed unlink cleanup can also surface a post-operation signal before the cleanup durability barrier runs.
This is reproducible on current main: trigger an ordinary failure after commit, raise KeyboardInterrupt from before_rollback, and publish_specs() escapes OSError with the interruption only mentioned in a note.
Related: #719, #774, #823
Scope
- Continue attempting all reverse rollbacks after an individual failure.
- Preserve and re-raise the exact first
BaseException that is not an Exception, including its identity and SystemExit.code.
- Keep an original forward control signal authoritative when rollback has only ordinary failures.
- Attach the primary transaction error, additional rollback failures, and retained recovery paths as notes without replacing the selected control signal.
- Complete ownership bookkeeping and the applicable durability barrier before propagating a post-unlink cleanup signal.
- Preserve ordinary rollback aggregation and completed-with-error behavior.
Acceptance criteria
- Ordinary forward failure plus rollback
KeyboardInterrupt or SystemExit re-raises the exact rollback signal after all rollback entries are attempted.
- Forward
KeyboardInterrupt or SystemExit remains the escaping object when rollback has only ordinary failures.
- Multiple rollback signals have deterministic first-signal precedence and retain all secondary details as notes.
- Signals after completed replace/unlink operations record ownership correctly before propagation.
- Cleanup performs its directory durability attempt after a completed unlink before re-raising the exact signal.
- Tests cover publish, absent publish, restore, both rollback directions, cleanup, retained recovery, and exception identity.
- Native Windows transaction CI, Pyright, Ruff, the full unit suite, and exact Godot 4.7.1 validation pass.
Problem
The anchored byte-artifact transaction deliberately catches
BaseExceptionso reverse rollback can continue across every recorded mutation. Its final aggregation currently converts every rollback failure into anOSError, includingKeyboardInterrupt,SystemExit, and other control-flow exceptions.A transaction interrupted during rollback therefore reports the earlier ordinary I/O failure instead of the cancellation signal. Completed unlink cleanup can also surface a post-operation signal before the cleanup durability barrier runs.
This is reproducible on current
main: trigger an ordinary failure after commit, raiseKeyboardInterruptfrombefore_rollback, andpublish_specs()escapesOSErrorwith the interruption only mentioned in a note.Related: #719, #774, #823
Scope
BaseExceptionthat is not anException, including its identity andSystemExit.code.Acceptance criteria
KeyboardInterruptorSystemExitre-raises the exact rollback signal after all rollback entries are attempted.KeyboardInterruptorSystemExitremains the escaping object when rollback has only ordinary failures.