From a5f307fd248643adead7bb913ed5673f18c97743 Mon Sep 17 00:00:00 2001 From: Guilhem Lemouel Date: Tue, 29 Sep 2026 03:43:09 -0700 Subject: [PATCH] docs: state the value precedence the reader would otherwise get backwards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Local review nits. `readGlobalDraftValue`'s doc still described the order the previous commit changed — it read as cell then backend, with the resolved value as a footnote, while the code is cell, then resolved value, then backend. A future edit following the doc would reintroduce the bug the reorder fixed. The `probeUnknown` refusal now says why it stops a read, unlike the listing failure ten lines above which hands reads the addressed path: that branch knows nothing is staged under the name, this one knows something is, so the name is ambiguous rather than merely unresolved. Two rounds have now read the asymmetry as an oversight; it is the stop that keeps the destructive tools, which reach it as reads, off a namesake draft. Co-Authored-By: Claude Opus 5 (1M context) --- .../copilot/chat/global/userDraftAdapter.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/frontend/src/lib/components/copilot/chat/global/userDraftAdapter.ts b/frontend/src/lib/components/copilot/chat/global/userDraftAdapter.ts index 5e79fe6dd5..9175ede400 100644 --- a/frontend/src/lib/components/copilot/chat/global/userDraftAdapter.ts +++ b/frontend/src/lib/components/copilot/chat/global/userDraftAdapter.ts @@ -432,6 +432,12 @@ async function storagePathForChosenName( // Something is staged under this name, and whether the path is also a deployed item's // own is what says which draft the call means. Answering it either way could delete or // deploy an unrelated draft. + // + // Reads stop here too, unlike the listing failure above, which hands them the addressed + // path. That branch knows nothing is staged under the name; this one knows something is, + // so the name is genuinely ambiguous and saying so beats reading whichever item the path + // happens to hold. The destructive tools reach this as reads — they declare no + // `forWrite` — and this is the stop that keeps them off the namesake. throw new Error( `Could not tell whether something is already deployed at "${path}", so the draft staged ` + `under that name cannot be identified. Try again.` @@ -552,9 +558,10 @@ async function fetchBackendDraftValue( return resp.value ?? undefined } -/** Draft VALUE at a resolved target: cell-if-present (the user's freshest in-tab edits) - * else the current user's backend draft. Falls back to what resolving the target already - * read, unless `fresh` — for a caller that has since changed the draft it is reading. */ +/** Draft VALUE at a resolved target, in order: the cell if one is open (the user's freshest + * in-tab edits), else the value resolving the target already read, else the current user's + * backend draft. `fresh` skips the resolved value — for a caller that has since changed the + * draft it is reading. */ export async function readGlobalDraftValue( workspace: string, type: WorkspaceItemType,