Repository navigation
fix(cli): undo complete timeline batch receipts atomically - #5279
miguel-heygen merged 3 commits into
Conversation
jrusso1020
left a comment
There was a problem hiding this comment.
Thanks. apply and ids return receipt arrays that undo could not accept, so multi-file edits had no undo path. Validating the whole batch and restoring it through one atomic mutation call is the right shape, and a stale file now refuses the entire batch instead of throwing. The single-receipt output is unchanged. This conflicts with #5240 in the timeline e2e test file, so one of the two will need a rebase.
— Rames
|
Thanks for this fix, it is approved. main has moved since, and |
jrusso1020
left a comment
There was a problem hiding this comment.
Approve at 7062933e. The merge from main didn't change the fix. A batch undo still restores every file or none, and required CI is green.
What changed since my approval at 1e9512fd
a2Commands.ts: the PR's patch is line-for-line the same as before the merge.aecb135e(test only): it carries main's #5240 project-inspection tests and its--separator test into this file. That resolves the conflict I flagged.- The merge (
7062933e): the PR's diff against main is still justa2Commands.tsandtimeline.e2e.test.ts, and it removes none of main's lines. #5239 and #5240 are both kept.
All-or-nothing, checked against the CLI at this head
- One stale file: I applied a two-file batch, edited the second file, then ran undo on the whole receipt. It exits 2 with "file changed since the timeline was read", and both files are byte-identical before and after.
- Missing backup: with the second receipt's backup removed, undo fails while still reading inputs, before any write, and both files are unchanged.
- Why it holds:
applyFileMutationschecks every file's version before writing any file, and rolls back already-written files if a later write throws. - Mutants:
- Undoing receipts one at a time leaves the first file reverted on the stale case. The test that keeps the whole batch untouched when a later receipt is stale catches it.
- Validating only the first receipt is caught by the invalid-receipt case.
Nits (non-blocking)
- A missing backup or target file still surfaces as a raw
ENOENTwith exit 1, not a JSON refusal. That was already true for single receipts, and nothing is written. - Undoing an empty receipt (
[]) reportsok: truewith no files. That's tested and intended.
Tests: src/timeline/ 103/103. oxfmt --check and oxlint are clean on both files; CI's lint+format preflight was path-skipped on this run. Every required check passes.
— Rames
timeline apply --jsonandtimeline ids --jsonreturn receipt arrays, buttimeline undoonly accepts a single receipt object. Passing an entire saved response fails, and the array returned by undo cannot be used to redo the operation.Accept single receipts, receipt arrays, and complete command responses, either inline or from a JSON file. Validate the whole batch and prepare every restore before one call to the existing atomic mutation helper. A stale file refuses the entire batch; successful undo returns receipts that can redo it. Existing single-receipt output stays compatible, and empty batches are no-ops.
Validation: