Skip to content

paste copies the outgoing bytes before overwriting, instead of refusing above a threshold nobody can tune (#1650) - #1655

Merged
fdaviddpt merged 2 commits into
masterfrom
fix/1650
Aug 14, 2026
Merged

paste copies the outgoing bytes before overwriting, instead of refusing above a threshold nobody can tune (#1650)#1655
fdaviddpt merged 2 commits into
masterfrom
fix/1650

Conversation

@fdaviddpt

Copy link
Copy Markdown
Contributor

Closes #1650

paste over an existing file now copies the outgoing bytes to ~/.cache/supertool/paste-backup/ before the write, and names the copy in the receipt.

Not the guard the issue proposed, and the argument is the point

I filed #1650 asking for a refusal above some shrink ratio or byte-loss floor, with a force token. The agent refused all three and it is right:

  • A refusal must offer force, and paste over an existing file is documented and ordinary. So force gets typed by reflex, and a guard everyone routes around has deleted itself. This repo already has the write-up on that failure mode under the misdirects class.
  • Shrink ratio and byte-loss floor are both the wrong trigger. 8922 bytes replaced by 9000 different bytes loses exactly as much and is exactly as unrecoverable. There is no number to tune, because the trigger is the op's own semantics: paste replaces the whole file. The one number in the diff — an 8 MB copy bound — is a resource limit, not a trigger, and crossing it is disclosed rather than silent.
  • Pre-write disclosure and the copy are the same change. A one-shot CLI has no pre-write moment a caller can observe; the only pre-write intervention available is a refusal. The copy makes the refusal unnecessary.

A copy has no case it was not written for: the write happens either way, and a false positive costs one cache file.

Scope is paste alone, and that is complete for this defect

Probed rather than assumed. Every other mutating op fails on a path that is not there — edit/replace match a string first, vim and replace_lines return file not found. Only paste succeeds either way. Plenty else destroys bytes (vim ggdG empties a file; replace_lines clamps end == total+1 rather than refusing it) — but nothing else can destroy a file the caller believes is not there, which is the #1642 mechanism. A test pins vim refusing a missing path, so a future create-if-missing arm cannot open that hole silently.

Reviewer: 5 accepted, 4 refused

The one that mattered: test_the_store_is_reaped would have passed against a guard that did nothing. Rewritten end to end — real snapshot, utime 8 days stale, gc:run:paste-backup, assert gone and 1 removed.

Three reviewer claims were checked and found false before being refused (_supertool.py is not the largest file in the tree — CHANGELOG.md is 1.8 MB; vim's missing-path and diff-echo cases are unrelated; replace_lines clamps rather than refuses).

Known, documented, not fixed here

A paste rolled back by a validator still leaves a copy, and the receipt prints previous contents kept at PATH above the file was NOT edited. Both sentences are true. Fixing it means reaching into the shared rollback loop, so it is documented in edits.md and the fragment instead.

Windows

The core adds no subprocess and no separator logic. The tests had the platform defect and it was caught pre-commit: every write_text/read_text became write_bytes/read_bytes, because CRLF translation would have made an 8922-byte note 8923 on Windows and turned the identical-rewrite case into a differing one — the #1004 class exactly. Core behaviour on Windows is reasoned, not observed; CI is the authority.

…ipt arrived one step too late (#1650)

Co-Authored-By: Max <noreply>
…he reaper test proved nothing (#1650)

Co-Authored-By: Max <noreply>
@fdaviddpt
fdaviddpt merged commit 5d920af into master Aug 14, 2026
23 checks passed
@fdaviddpt
fdaviddpt deleted the fix/1650 branch August 14, 2026 06:51
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.

paste: overwrites an existing file and reports the size delta afterwards, so an 8.9 KB note was destroyed by a 2 KB write

1 participant