Found while migrating the publication fields onto the #1478 P4a aggregate (PR #1532); preserved there byte-for-byte because a refactor must not change behavior. Filing it so the behavior gets a deliberate decision.
The quirk
A second successful open on an authoring session aborts the recording: the session gets authoring{aborted}, recordSession is cleared, and the user is warned "Script publication was aborted…". close --save-script on that session is correctly rejected by the terminal-recording gate ("cannot publish this terminal recording").
But the abort is not sticky against the recorder's flag ingress. If the second open itself carried --save-script (or any later recorded action does — e.g. a replayed open step whose recorded flags include it), recordActionEntry's ingress re-enables recordSession while the status stays aborted. A bare close then publishes the full session log — the writer gates on recordSession and the repair variant only, not on the aborted authoring status. So a recording the user was explicitly told was aborted still lands on disk, just not via the guarded path.
Repro sketch (unit-level): open app --save-script → open app2 --save-script (abort + re-arm ingress) → bare close → the log is written.
Why it also blocks a simplification
recordSession is now the aggregate's ninth co-resident flag with three declared writers (R7). If aborted meant stopped, recordSession would be derivable from the aggregate (authoring{armed} || repair-active || close-time arming) and could be deleted as a stored field. This quirk is the one reachable state where the two disagree (aborted + recordSession: true), so it is the exact blocker for that follow-up.
Decision needed
Either (a) make abort sticky — the flag ingress on an authoring{aborted} session must not re-enable recording, and the bare-close write is gated on !aborted — or (b) declare the current behavior intended ("any later --save-script re-opts in") and document it in ADR 0016. Option (a) then unlocks deriving recordSession from the aggregate and deleting the field (R7 shrinks by one more row).
Depends on the #1478 P4a stack (PR #1532) landing first — the fix belongs on the aggregate, not the old fields.
Found while migrating the publication fields onto the #1478 P4a aggregate (PR #1532); preserved there byte-for-byte because a refactor must not change behavior. Filing it so the behavior gets a deliberate decision.
The quirk
A second successful
openon an authoring session aborts the recording: the session getsauthoring{aborted},recordSessionis cleared, and the user is warned "Script publication was aborted…".close --save-scripton that session is correctly rejected by the terminal-recording gate ("cannot publish this terminal recording").But the abort is not sticky against the recorder's flag ingress. If the second
openitself carried--save-script(or any later recorded action does — e.g. a replayedopenstep whose recorded flags include it),recordActionEntry's ingress re-enablesrecordSessionwhile the status staysaborted. A bareclosethen publishes the full session log — the writer gates onrecordSessionand the repair variant only, not on the aborted authoring status. So a recording the user was explicitly told was aborted still lands on disk, just not via the guarded path.Repro sketch (unit-level):
open app --save-script→open app2 --save-script(abort + re-arm ingress) → bareclose→ the log is written.Why it also blocks a simplification
recordSessionis now the aggregate's ninth co-resident flag with three declared writers (R7). If aborted meant stopped,recordSessionwould be derivable from the aggregate (authoring{armed} || repair-active || close-time arming) and could be deleted as a stored field. This quirk is the one reachable state where the two disagree (aborted+recordSession: true), so it is the exact blocker for that follow-up.Decision needed
Either (a) make abort sticky — the flag ingress on an
authoring{aborted}session must not re-enable recording, and the bare-close write is gated on!aborted— or (b) declare the current behavior intended ("any later --save-script re-opts in") and document it in ADR 0016. Option (a) then unlocks derivingrecordSessionfrom the aggregate and deleting the field (R7 shrinks by one more row).Depends on the #1478 P4a stack (PR #1532) landing first — the fix belongs on the aggregate, not the old fields.