Skip to content

fix: write the plan file atomically so a crash mid-save cannot destroy it - #172

Open
vitali87 wants to merge 1 commit into
fix/ignore-plan-dir-in-clean-checkfrom
fix/atomic-plan-save
Open

fix: write the plan file atomically so a crash mid-save cannot destroy it#172
vitali87 wants to merge 1 commit into
fix/ignore-plan-dir-in-clean-checkfrom
fix/atomic-plan-save

Conversation

@vitali87

Copy link
Copy Markdown
Owner

Summary

save_plan truncated and rewrote .pr-split/plan.json in place. The file embeds the full raw diff, and the most important save happens right after PRs are created — so a crash, SIGKILL, or full disk mid-write left truncated JSON and destroyed the previous good plan, orphaning the just-created PRs and branches with no record for clean/status/merge to act on (#64 only cleans up the resulting error message; the data was still gone).

The plan is now written to plan.json.tmp in the same directory and os.replace()d onto the target — atomic on the same filesystem — with the temp file unlinked in a finally on failure. Review confirmed the temp file is invisible to #169's clean check and that a stray .tmp after SIGKILL is harmless and overwritten by the next save.

Stacked on #169 (stack #159 = #64#158#169→this).

Test plan

  • test_failed_write_preserves_the_previous_plan: an ENOSPC mid-write leaves the previous plan byte-for-byte intact and loadable — fails on the base
  • test_no_temp_file_left_behind guards the new mechanism
  • Review reproduced the base failure mode (truncated JSON) and verified replace/unlink semantics in a scratch repo
  • 464 tests pass, ruff clean
  • Local review: 5/5

…y it

save_plan truncated and rewrote .pr-split/plan.json in place. The file is
large (it embeds the full raw diff) and the most important save happens
right after PRs are created; a crash or full disk mid-write left truncated
JSON and wiped the previous good plan, orphaning the just-created PRs and
branches with no record for clean/status/merge to act on. The plan is now
written to a temp file in the same directory and os.replace()d over the
target, with the temp file cleaned up on failure.
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e6d33b4-6ef5-4087-a33e-813e820d40a8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant