fix: atomic writes for review-verdict-ledger and review-objections (#409) - #410
Conversation
…ssue #409) Both write_review_verdict_ledger and record_review_objection used non-atomic write_text() calls that could corrupt JSON files if the process was killed mid-write. Replace both with _write_json_file(), which writes to a .tmp file then uses os.replace() for a safe atomic swap. Widen _write_json_file's payload type from dict to dict|list so it can handle the objections store (which stores a list). Add three regression tests: atomic .tmp cleanup for the ledger write, atomic .tmp cleanup for the objections write, and direct exercise of the widened _write_json_file list-payload path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GZu8kwg8saVCk7i55Wf9Hd
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThe step runner now uses ChangesAtomic JSON writes
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Poem
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Summary
Fixes #409 — two non-atomic
write_text()calls inmap_step_runner.py.jinjathat could corrupt JSON files if the process was killed mid-write.write_review_verdict_ledger: replacedjson_path.write_text(json.dumps(ledger, ...) + "\n", ...)with_write_json_file(json_path, ledger)(atomic.tmp→os.replace()).record_review_objection: replacedobjections_path.write_text(json.dumps(existing, ...) + "\n", ...)with_write_json_file(objections_path, existing)._write_json_file: widenedpayload: dicttopayload: dict | listso it can handle the objections store (which stores a list). The implementation was already generic — only the annotation was narrow.Templates re-rendered (
make render-templates) to propagate changes to all generated trees.Tests
Three regression tests added to
tests/test_review_verdict_ledger.py:test_write_review_verdict_ledger_uses_atomic_write— verifies no residual.tmpfile remains and the ledger JSON is valid after a write.test_record_review_objection_uses_atomic_write— verifies no residual.tmpfile remains and the objections file is a valid JSON array.test_write_json_file_accepts_list_payload— directly exercises the widened list-payload path.make checkpasses: 4385 tests (3 new), ruff/mypy/pyright clean, check-render passes.Generated by Claude Code
Summary by CodeRabbit
Bug Fixes
Tests