Projects tool: project_write silently destroys document content, with no append mode, no version history, and no recovery

Status Closed — not planned
Maintainer reply None cached
Activity 2 comments · opened Aug 16, 2026 · closed Aug 19, 2026

Summary

project_write performs a whole-document replacement with no merge, no append mode, no diff preview, no version history, and no undo. If the model composes a write that does not carry the full prior content forward, every unwritten section is permanently deleted, silently, and the tool returns a normal success response ("replaced": true).

There is no signal at any point that content was destroyed.

What happened

A retro entry was appended to a project doc (guides/session-retros.md) via project_write. The content parameter carried only the new entry. Every prior entry in the document was deleted. The tool returned success. The loss was discovered roughly two hours later by a different session re-reading the file for an unrelated reason.

project_search confirmed the RAG index also holds only the surviving content, so there is no recovery path from any session or surface.

This is the fifth occurrence of this exact failure on this user's account (8 Aug, 13 Aug x2, 14 Aug, 16 Aug 2026). Each occurrence produced a written procedural rule; each subsequent occurrence happened anyway. Notably, the fourth occurrence happened while writing a retro entry about the third.

Why prompt-level mitigation keeps failing

Composing a content string does not feel like a destructive operation. There is no confirmation step, no diff, and no visible indication that anything is being removed. The failure mode is not carelessness about a known-dangerous call; it is that the call does not present as dangerous. Five documented rules on the client side have not closed it, which suggests the guard belongs in the tool, not in the instructions.

Requested changes, roughly in order of value

  1. An append/prepend mode. project_append(path, content) or a mode: "append" | "replace" parameter on project_write. Most writes to a running log, changelog, or retro trail are appends. Making the common case non-destructive removes most of the exposure.
  2. Version history with restore. Even a small ring buffer of prior revisions per doc would have made this recoverable. Right now a destructive write is final.
  3. A destructive-write signal in the response. Return the byte/line delta, e.g. {"replaced": true, "bytes_before": 24011, "bytes_after": 1804, "shrunk_by": "92%"}. A model that sees a 92% shrink in the tool result can catch and repair its own mistake in the next turn. Today the result is indistinguishable from a normal update.
  4. Optional: require a content hash or read_token from a recent project_read of the same path in order to write, so a write composed without reading the current state fails loudly instead of succeeding destructively.

Any one of (1) or (3) would likely have prevented this instance. (2) would have made it recoverable.

Impact

Project docs are the user-facing, cross-session memory for Projects. They are exactly the thing users are told to put durable work into. A tool that can silently and irrecoverably empty one on a well-formed call is a data-loss bug, not a usability issue.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗