Skip to content

fix(emit): terminal is written once — refuse overwrite without force, atomic writes (F4) - #28

Merged
SollanSystems merged 1 commit into
mainfrom
fix/emit-write-safety
Jul 5, 2026
Merged

SollanSystems merged 1 commit into
mainfrom
fix/emit-write-safety

Conversation

@SollanSystems

Copy link
Copy Markdown
Owner

Summary

Closes external-review finding F4: emit.terminate silently overwrote terminal_state.json, and nothing in emit.py wrote atomically — README's "written once" claim was unenforced.

  • terminate() now raises EmitError when the terminal file already exists; the deliberate escape hatch is the new keyword-only force=True.
  • Whole-file writes (state.json, terminal_state.json) go through a same-directory temp file + os.replace, so a crash mid-write can never leave truncated JSON. Appends (RUNLOG, receipts) remain appends.
  • README's terminal_state.json line now states the enforcement instead of asserting it.

Test plan

  • fallback mode: 254 passed, 11 skipped / jsonschema mode: 259 passed, 6 skipped
  • adversarial verifier: Succeeded→FailedBlocked overwrite refused with file byte-identical; force=True overwrites and revalidates; no temp-file litter after success, refusal, or validation-failure paths
  • langgraph recipe consistent with the new semantics

🤖 Generated with Claude Code

terminate() silently overwrote an existing terminal_state.json, so a
second call could replace an honest Succeeded/FailedBlocked record. It
now refuses when the terminal file exists unless force=True (the
documented deliberate-overwrite escape hatch), naming the written-once
contract in the error.

Whole-file writes for state.json and terminal_state.json now go through
a temp file in the same directory then os.replace, so a crash mid-write
can never leave truncated JSON, and the temp file is removed on failure
(no *.tmp litter). Appends (RUNLOG, receipts) stay appends.

README documents the enforcement at the terminal_state.json line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 5, 2026 22:54
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@SollanSystems
SollanSystems merged commit 56dc816 into main Jul 5, 2026
6 checks passed
@SollanSystems
SollanSystems deleted the fix/emit-write-safety branch July 5, 2026 22:55
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.

2 participants