Out-of-workspace authoring (global-storage sidecar fallback) #25
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Out-of-workspace authoring (global-storage sidecar fallback)
Summary
Let the human ask Claude to author into any file, not just files under the
opened workspace folder — extending threads, live attribution, and propose/accept
(F2/F3/F4) to out-of-workspace and untitled documents by falling back to a
global-storage sidecar (keyed by URI hash, like F6's baseline) when there is no
committable
.threads/home.Problem / pain
The diff view (F6, #19) and the rendered preview (F7, #21) were broadened to work
on any file — in-folder, out-of-folder, or untitled — because they persist
nothing in the repo (F6's baseline lives in VS Code global storage keyed by URI
hash; F7 persists nothing). But the authoring surfaces — F2 threads, F3
attribution, F4 "Ask Claude to Edit Selection" — still refuse any document that
isn't a saved
file:underworkspaceFolders[0], because they persist agit-native
.threads/<repo-relative-path>.jsonsidecar under the workspace root(
store.tssidecarPath), which has no home for an out-of-workspace file.The result is a surprising asymmetry: you can diff/preview a file the extension
isn't anchored to, but you cannot ask Claude to edit it — and until the
session-0022 fix the refusal even misreported the reason ("select some text"
instead of "this file is outside your workspace folder").
Who feels it
opened outside the workspace folder (a doc from a sibling repo, a scratch file)
or an untitled buffer, and expecting the same "ask Claude to edit" affordance the
diff/preview already offer there.
Desired outcome / value
The human can select text and ask Claude to edit it in any document the editor
will show — so the authoring loop matches the (already universal) diff/preview
loop, removing the "why does it work here but not there?" friction. Authoring on a
workspace file is unchanged; authoring on an out-of-workspace/untitled file simply
works, with its state kept where a repo sidecar can't live.
Acceptance — "done right"
outside the workspace folder and on an untitled buffer, not just
in-workspace files.
.threads/git-native sidecar (INV-2 preserved) — no migration, no behaviorchange for the existing flow.
attributions / proposals) in global storage keyed by a hash of the document
URI, mirroring F6's baseline storage and INV-19 (never the repo).
spans/threads for a global-storage doc the same way it does for a sidecar doc.
seam pattern.
Scope / non-goals
In scope: a hybrid persistence model — in-workspace
file:docs keep therepo
.threads/sidecar; out-of-workspacefile:docs anduntitled:buffers usea global-storage sidecar keyed by URI hash. One storage abstraction the three
authoring controllers (thread / attribution / proposal) share. Accurate scope in
the
editSelectionguard (the session-0022 messaging already distinguishes theconditions; this widens what's accepted).
Out of scope / non-goals: uniform global storage (moving in-workspace docs
off the committable sidecar — explicitly rejected: it would lose committable
threads/attribution, the point of INV-2); migrating existing repo sidecars;
cross-rung sharing of global-storage artifacts (see below); per-author coloring or
any UI change beyond accepting more documents.
Assumptions · constraints · dependencies
(propose/accept), and the F6 #17/#19 global-storage-by-URI-hash precedent
(
BaselineStore, INV-19). Parent: Epic #1.as a committed file. A global-storage sidecar is not a committed file, so
out-of-workspace authoring artifacts are not cross-rung-shareable — which is
acceptable (an out-of-repo file isn't shared via the repo anyway), but the design
must state it explicitly.
out-of-workspace file orphans its artifact (the repo sidecar, by contrast, moves
with the file in git). The design should call this out.
load-bearing change, so this Feature needs a Solution Design before
implementation (handbook §3.4 R3).
SCHEMA_VERSIONandthe cross-rung contract format are unchanged (the artifact shape is identical —
only where it is stored differs).
Source / signal
Capture session vscode-cowriting-plugin-0023. Originated during F7 manual
testing (sessions 0021 / 0022): "Ask Claude to Edit Selection" was refused on
vscode-cowriting-plugin-content/issues/diff-view-toggle.md(outside the EDHsandbox/root). Session 0022 (PR #24) fixed the misleading message and thestartsWithprefix-collision; this Feature is the follow-on the operator chose —extend authoring to any file via global storage (the "global storage like F6"
fork). See memory
editselection-workspace-membership.md.Priority (WSJF)
Provisional: Value 3 · Time-criticality 2 · Opportunity-enablement 2 ÷ Size 3 ≈
2.3.
priority/P2— a real UX consistency win, not urgent; sequence after theopen F7 follow-up #22 unless the operator reprioritizes.
Decomposition (Feature → slice checklist)
.threads/forin-workspace
file:docs and global storage (URI-hash key) otherwise — shared bythe thread / attribution / proposal controllers (today
CoauthorStoreisworkspace-root-bound).
selectionRejection/ controller membershipaccept out-of-workspace
file:+untitled:docs, routing them to theglobal-storage store.
documenting the move/rename orphaning caveat.
buffer (open → propose via seam → accept → reload restores), reusing the F2–F6
harness.
global-storage artifacts.
Solution notes (optional — NOT a design)
Non-binding: the cleanest shape is likely an interface the controllers depend on
(e.g.
SidecarStore) with two implementations — the existing repo-rootedCoauthorStoreand aGlobalSidecarStoremirroringBaselineStore's URI-hashkeying — selected per document by the same
isUnderRootpredicate added in #24.The artifact JSON is identical either way, so
mergeArtifacts/ the cross-rungformat (F5) need no change. To be settled in the Solution Design.
Shipped to
mainin PR #26 (session 0025). Hybrid persistence: in-workspace files keep the committable.threads/sidecar byte-for-byte (INV-2); out-of-workspacefile:+untitled:route to a global-storage sidecar keyed bysha256(uri)(INV-19/24/25). 150 unit + 41 host-E2E tests green. Non-shippable (no marketplace publish) — done = merge + tests green.