anthropics / anthropics/claude-code

Projects: concurrent sessions silently clobber each other's project_write — three losses on one doc in ninety minutes

Aperta
#93,260 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub
area:agents area:tools bug data-loss
Lingua principale
Python
Stelle
145k
Fork
23.1k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

## Summary

`project_write` is a whole-document replace with no compare-and-swap. When two or more sessions work the same project at once — the normal case for agent workloads — each reads, composes, and writes back its whole copy, and whichever lands last silently deletes everything the others added in between. Every session gets a success response. None of them can tell.

This is distinct from #87117 (closed as not planned), which was about one session composing an incomplete write. This is about **individually correct** writes destroying each other.

## What happened

On the night of 9–10 September 2026, one project doc — `claude/open-tasks.md`, a handover doc several sessions read and update — was rewritten whole **three times in about ninety minutes** by different sessions on the same account. Each rewrite was good and current on its own. Each deleted content added minutes earlier by another session: a live-source sweep recording which mailboxes, drafts, chat threads and scheduled tasks had been read, and when.

The document's uuid changed on each write (`f0793cd2` → `f8de655a` → `7a066ec8`), so nothing about the result looked like an overwrite.

It was found only because one session ran a custom check that greps that doc for those recorded reads. Without it the next session would have re-read four live sources for nothing — or, worse, assumed the unrecorded ones were quiet.

## Why client-side rules cannot close this

Every mitigation available to a session protects only the session using it:

- Reading immediately before writing narrows the window; it does not close it.
- A read-splice-PATCH inside a single call (what we do) is safe for that writer and invisible to a whole-file writer landing on top of it.
- An out-of-band mutex (we keep one in a GitHub repo) works only if every session opts in, and unattended runs cannot take it at all, because connector writes there block on an approval prompt nobody answers.

Nothing in the API lets a session say "write this only if the document is still what I read."

## Requested changes

1. **Compare-and-swap on write.** Return a version token from `project_read`, accept it as `if_version` on `project_write`, reject with a conflict when it no longer matches. This closes the class. The memory tool in this same product already works exactly this way.
2. **An append mode** (`project_append`, or `mode: "append"`), making the most common write — adding to a running log or handover doc — non-destructive by construction.
3. **A shrink/delta signal in the write response** (`bytes_before`, `bytes_after`), so a model can see it just removed 60% of a document and repair it in the next turn.

(1) alone would have prevented all three losses. (3) would have made all three visible immediately instead of by luck.

## Impact

Project docs are the cross-session memory Projects tells users to rely on, and cross-session concurrency is the workload agents are built for. Together they produce silent data loss on well-formed calls, with no conflict, no history and no recovery.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

The issue names no implementation files or tests; start by locating the project_read and project_write entry points and their existing tests, then inspect the memory tool's version-token behavior. Done should be demonstrable through tests covering stale-version conflicts, append behavior, and write responses exposing bytes_before and bytes_after.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Ambito
backend-api-design
Tipo di issue
Bug
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.