Tech-debt tracker for the // cargo-deps: lockfile store introduced by #313 (#256): items Codex raised after the substantive rounds, deferred per the scope decision on that PR. Each is a shape of the same class — concurrent first-time publishers on one store entry — and the structural answer is one: validate and decide under the claim, and let a loser wait for the specific file it needs, not for any file.
Both fail loudly (--locked refuses a mismatched file and names it), never silently; they need two concurrent first-time builders meeting a stale-scheme file, which today only a cross-version CI cache produces.
Tech-debt tracker for the
// cargo-deps:lockfile store introduced by #313 (#256): items Codex raised after the substantive rounds, deferred per the scope decision on that PR. Each is a shape of the same class — concurrent first-time publishers on one store entry — and the structural answer is one: validate and decide under the claim, and let a loser wait for the specific file it needs, not for any file.ensure_cargo_lockfile!classifies a stored file as stale (_lockfile_names_rootfalse) before claiming, and keepsreplace = truewhile resolving. Two processes that both classify the same file as stale can therefore both resolve; the second to acquire the claim overwrites the first's fresh publication, and the two build different graphs. Fix: re-check_lockfile_names_rootwhile holding the claim and publish only if the entry is still stale; otherwise replay the (now fresh) entry. (thread: Pin // cargo-deps: builds to a persisted Cargo.lock; --locked, --offline, resolution in the key (#256) #313 (comment))isfile(stored)), so its--lockedbuild fails with the hint. Fix: the wait loop should wait until the entry names the root (_lockfile_names_root), with the samewaitbound.Both fail loudly (
--lockedrefuses a mismatched file and names it), never silently; they need two concurrent first-time builders meeting a stale-scheme file, which today only a cross-version CI cache produces.