Skip to content

fix: atomic writes for review-verdict-ledger and review-objections (#409) - #410

Merged
azalio merged 1 commit into
mainfrom
claude/compassionate-cerf-vwf71g
Aug 11, 2026
Merged

fix: atomic writes for review-verdict-ledger and review-objections (#409)#410
azalio merged 1 commit into
mainfrom
claude/compassionate-cerf-vwf71g

Conversation

@azalio

@azalio azalio commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #409 — two non-atomic write_text() calls in map_step_runner.py.jinja that could corrupt JSON files if the process was killed mid-write.

  • write_review_verdict_ledger: replaced json_path.write_text(json.dumps(ledger, ...) + "\n", ...) with _write_json_file(json_path, ledger) (atomic .tmpos.replace()).
  • record_review_objection: replaced objections_path.write_text(json.dumps(existing, ...) + "\n", ...) with _write_json_file(objections_path, existing).
  • _write_json_file: widened payload: dict to payload: dict | list so 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 .tmp file remains and the ledger JSON is valid after a write.
  • test_record_review_objection_uses_atomic_write — verifies no residual .tmp file 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 check passes: 4385 tests (3 new), ruff/mypy/pyright clean, check-render passes.


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability when saving review verdict and objection records.
    • Prevented incomplete or temporary files from being left behind during JSON updates.
    • Added support for preserving list-based JSON data.
  • Tests

    • Added coverage verifying saved records remain valid and parseable after updates.

…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
@azalio
azalio merged commit bce85be into main Aug 11, 2026
1 check passed
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d8fa3365-dcb6-4ba8-bf9e-be15a57433dc

📥 Commits

Reviewing files that changed from the base of the PR and between 2a76fbc and 211cda9.

📒 Files selected for processing (4)
  • .map/scripts/map_step_runner.py
  • src/mapify_cli/templates/map/scripts/map_step_runner.py
  • src/mapify_cli/templates_src/map/scripts/map_step_runner.py.jinja
  • tests/test_review_verdict_ledger.py

📝 Walkthrough

Walkthrough

The step runner now uses _write_json_file for ledger and objection persistence. The helper accepts dictionary or list payloads. Regression tests verify valid JSON output and no residual temporary files.

Changes

Atomic JSON writes

Layer / File(s) Summary
JSON helper contract and template propagation
src/mapify_cli/templates_src/.../map_step_runner.py.jinja, .map/scripts/map_step_runner.py, src/mapify_cli/templates/.../map_step_runner.py
_write_json_file now accepts dictionary or list payloads in the source template and rendered files.
Atomic persistence call sites and regression tests
src/mapify_cli/templates_src/.../map_step_runner.py.jinja, .map/scripts/map_step_runner.py, src/mapify_cli/templates/.../map_step_runner.py, tests/test_review_verdict_ledger.py
Ledger and objection writes now use _write_json_file. Tests validate parsed JSON, list payload support, and removal of temporary files.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Poem

A rabbit found two files in fright,
And gave them one safe path to write.
Dicts and lists now hop with cheer,
No stray temp files linger here.
JSON rests intact and clear.

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/compassionate-cerf-vwf71g

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.

Bug: non-atomic writes in write_review_verdict_ledger and record_review_objection

2 participants