From 1e54abdd8d45aee1f21aa7dfd60820a384061b1b Mon Sep 17 00:00:00 2001 From: BenStullsBets Date: Sun, 28 Jun 2026 07:09:58 -0700 Subject: [PATCH] =?UTF-8?q?spec(0062):=20resolve=20Q5=20=E2=80=94=20Option?= =?UTF-8?q?=201=20(preview=20authorship)=20+=20editable=20proposals=20(INV?= =?UTF-8?q?-12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Authorship lives in the annotated preview (D11); native diff stays author-blind. Crucially, the review's proposed side is WRITABLE (INV-12, D12): the writer tweaks the machine's suggestion before Keep ('close, but a few human edits'), the live doc is untouched until Keep (INV-5), and on Keep machine words vs writer tweaks are attributed separately by diffing final<->machine-original<->baseline. This keeps authorship clean AT CREATION, so post-hoc in-editor authorship (opts 2/3) is unnecessary and deferred. New open Q7: per-change Keep/Undo semantics after free cross-hunk editing. Co-Authored-By: Claude Opus 4.8 (1M context) --- specs/coauthoring-native-surfaces.md | 42 ++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/specs/coauthoring-native-surfaces.md b/specs/coauthoring-native-surfaces.md index ef6b8e7..c805471 100644 --- a/specs/coauthoring-native-surfaces.md +++ b/specs/coauthoring-native-surfaces.md @@ -156,8 +156,9 @@ Scenario: BUC-2 — keep or reject, change by change ``` - **BUC-2 acceptance criteria:** no proposed change alters the document until the - writer keeps it; each change is independently keepable/discardable; keep-all and - reject-all exist. + writer keeps it; each change is independently keepable/discardable; the writer can + **edit a proposed change before keeping it**, and those edits are attributed to the + writer; keep-all and reject-all exist. **BUC-3 — As a writer, I can tell who wrote which parts of my document and read a clean rendered version, so that I can judge the result as finished prose.** @@ -223,7 +224,7 @@ already know: | What the writer needs | Native surface that delivers it | What it gives them, for free | | --- | --- | --- | | See what changed (BUC-1) | Source-control gutter change bars + the **native diff editor** against a virtual *baseline* document | The exact diff experience they use for everything else: inline/side-by-side, navigation, accessibility | -| Keep/reject changes (BUC-2) | The **multi-diff review editor** with per-change **Keep/Undo** | One native surface to sweep all of the machine's changes, accepting or discarding each | +| Keep/reject — and **tweak** — changes (BUC-2) | The **multi-diff review editor** with per-change **Keep/Undo** and a **writable proposed side** | One native surface to sweep all of the machine's changes — editing the proposal in place before keeping or discarding each (INV-12) | | Authorship + rendered result (BUC-3) | The **built-in Markdown preview**, extended via a `markdown-it` plugin to inject authorship + change marks | Native rendering, scroll-sync, theming, and cooperation with the writer's other Markdown extensions | | Discuss a passage — and have the machine respond (BUC-5) | The **Comments API** — threaded comments where, on a coedited document, the machine replies in-thread and offers an edit | The familiar review-comment experience, in the gutter, that can turn a remark into a proposed change | | Follow + stop the machine (BUC-4) | A progress **notification** + a shared **OutputChannel**, with Cancel | Live, stoppable, legible machine work | @@ -286,9 +287,11 @@ Scenario: PUC-2 — keep/reject the machine's proposed changes (realizes BUC-2) Given I ask the machine to revise the document (or a selection) When the turn completes Then the proposed changes open in a multi-diff review (baseline ⟷ proposed) + And the proposed side is editable, so I can tweak the machine's wording before keeping it And each change offers Keep / Undo (Accept / Reject) And toolbar actions offer Keep all / Reject all And my document is unchanged until I keep a change + And on keep, the machine's words are attributed to the machine and my tweaks to me ``` ```gherkin @@ -441,6 +444,14 @@ coauthoring **displaced** state surfaced in the thread / proposed-change listing color scoping — §6.7). Authorship (human vs. machine) is shown on a surface the extension renders: the annotated preview (and optionally a decoration-based track-changes editor), never by recoloring the native diff. +- **INV-12 — proposed changes are editable before they are kept:** the review + surface presents the machine's proposal on a **writable** side, so the writer can + tweak it in place before keeping it (the common "close, but a few human edits" + case). The live document stays untouched until Keep (INV-5 still holds); on Keep, + the words the machine proposed are attributed to the machine and the writer's + tweaks to the writer — so authorship is correct **at the moment the change is + made**, never reconstructed afterward. Editing happens at review time; once kept, + the text is just text (no lingering "trapped proposal" state to untangle). ### 6.2 High-level architecture @@ -545,7 +556,13 @@ state (INV-7), not durable coauthoring metadata. - **Review controller** — `openReview(docUri)` opens the multi-diff (`baseline ⟷ proposed`); `keep(proposalId)` = Accept (applies the edit, attributes changed words); `undo(proposalId)` = Reject (drops it); `keepAll()` / `undoAll()` - = Keep/Reject all (apply descending, skip + report any displaced change). + = Keep/Reject all (apply descending, skip + report any displaced change). The + **proposed side is a writable scratch document** (untitled / in-memory) seeded with + the machine's text (INV-12); the left side (baseline) is read-only. `keep` diffs + the **final** (possibly writer-tweaked) proposal against the baseline, applies it + to the live document, and attributes machine-proposed words to the machine and + writer tweaks to the writer by comparing *final ↔ the machine's original proposal*. + The live document is untouched until `keep` (INV-5). - **Preview extension** — `extendMarkdownIt(md) → md.use(cowritingPlugin)`; the plugin invokes the pure `renderAnnotations(tokens, attributions, proposals, options)` transform, gated by the `cowriting.annotations` setting/command. @@ -615,6 +632,14 @@ sequenceDiagram multi-diff editor is stable; per-change inline **Keep/Undo overlays** as some AI tools render them lean on evolving editor APIs — the **stable fallback** is per-hunk **CodeLens** Keep/Reject within the diff (§6.10, §13-Q2). +- **Editable before keep (INV-12):** the proposal renders on the **writable** side of + the review, so the writer can tweak the machine's wording ("close, but a few human + edits") before keeping. `keep` attributes the machine's words and the writer's + tweaks separately by diffing *final ↔ machine-original ↔ baseline*. Because editing + happens on the proposal (a scratch doc), not the live document, INV-5 holds and + authorship is correct at creation — the preview (Option 1, the authorship surface) + then shows clean green/blue with no post-hoc untangling. *Open detail (§13-Q7):* + how per-change Keep/Undo behaves once the writer has freely edited across hunks. #### PUC-3 — annotated rendered preview @@ -717,6 +742,8 @@ sequenceDiagram | Persistence envelope | one forward-compatible, unknown-field-preserving sidecar (INV-4) | a bespoke per-feature format; preview-only ephemeral state | Round-trips to an outer review forge; survives reload; one shared `anchors`/`provenance` primitive | | Core/controller split | pure vscode-free cores + thin controllers | UI-coupled logic | Unit-testable cores, swappable surfaces; the surface can change without touching the logic (INV-6) | | Decision vs attribution unit | block = decision unit (keep/reject); word = attribution unit | per-word proposals (too granular to decide on); per-file (all-or-nothing) | The writer decides at a readable grain (a paragraph) while authorship stays word-precise | +| Authorship surface | **Option 1** — the annotated preview is the authorship view (green/blue track-changes incl. deletions); native diff stays author-blind | Option 2 (in-editor decorations); Option 3 (owned author-colored track-changes diff that replaces native diff) | Preview shows author-colored changes for near-zero maintenance; editable proposals (INV-12) keep authorship clean *at creation*, so in-editor / post-hoc authorship rendering is unnecessary. Opts 2/3 deferred | +| Editing proposals | the proposed side of the review is **writable**; pre-Keep tweaks are absorbed and attributed (machine vs. writer) at Keep (INV-12) | machine proposal read-only (tweak only after accepting) | Most revisions are "close, but a few human edits"; editing at review time keeps authorship clean at creation and avoids messy post-acceptance untangling | | Coediting activation | opt-in per document via "Coedit this Document with Claude"; every surface gated on the active coediting set (INV-10) | always-on for all markdown; opt-in per workspace/folder | Per-document opt-in is the only grain that avoids hijacking Comments/SCM/preview for the writer's other files while keeping single-file precision | | Authorship in the diff | the native diff is **author-blind** (what changed); authorship is shown in the preview, optionally a decoration track-changes editor (INV-11) | recolor machine changes inside the native diff editor | **Not possible:** `diffEditor.*` colors are global theme tokens with no per-author scoping; `inlineEdit.*`/chat tokens differentiate accept-state not author; decorations over the diff pane composite over green/red and are unreliable (vanish on tab-switch). Verified against the VS Code API (§13-Q5) | | Comment → machine response | on a coedited doc, a comment fires a turn that replies + offers an edit → pending proposal | comment is inert (human-only threads) | Turns the familiar review-comment gesture into a coediting action without a new surface; the opt-in gate (INV-10) keeps it from firing on other docs | @@ -880,7 +907,7 @@ a bug reaches us as a tracker issue. | Q2 | Per-change Keep/Undo: how far can the stable API go before falling back to per-hunk CodeLens? | Ben | PUC-2 build (last surface) | | Q3 | One "Cowriting" SourceControl vs. QuickDiff-only (no full SCM viewlet entry) — how much SCM presence is wanted | Ben | PUC-1 build | | Q4 | Does any need genuinely require a webview the native surfaces can't serve (INV-3 escape hatch)? | Ben | Per-surface build | -| Q5 | Authorship (human vs. machine) cannot live in the native diff (INV-11, verified). Which surface carries it — the annotated preview only, a preview **plus** in-editor authorship decorations, or an **owned author-colored track-changes view** that replaces the native diff for review? | Ben | PUC-3 build / authorship-surface scope | +| Q7 | Once the writer freely edits the proposal across hunks (INV-12), how do per-change Keep/Undo behave — do per-hunk actions survive arbitrary edits, or does free editing collapse the change set to a single Keep/Reject-all? | Ben | PUC-2 build | **Resolved** @@ -896,6 +923,8 @@ a bug reaches us as a tracker issue. | D8 | Comments can summon the machine | On a coedited doc, a comment fires a turn that replies in-thread + offers an edit → pending proposal (BUC-5, INV-5); inert on non-coedited docs | 2026-06-27 | | D9 | Native diff is author-blind | Verified the diff editor has no per-author color API; authorship lives in the preview (and optionally a decoration track-changes editor), not the native diff (INV-11) | 2026-06-27 | | D10 | Comment trigger | While a document is in coediting mode, **every** new comment summons the machine (no per-comment gate); coediting mode is the control, "Stop editing with Claude" the off switch | 2026-06-27 | +| D11 | Authorship surface (Q5) | Option 1 — the annotated preview is the authorship view; native diff stays author-blind; in-editor decorations (opt 2) and an owned track-changes diff (opt 3) are out of scope | 2026-06-27 | +| D12 | Editable proposals | The review's proposed side is writable; the writer tweaks before Keep; machine words vs. writer tweaks are attributed at Keep (INV-12); live doc untouched until Keep (INV-5) | 2026-06-27 | ## 14. Glossary & References @@ -922,4 +951,5 @@ a bug reaches us as a tracker issue. multi-diff editor, Markdown preview `markdown-it` contribution, Comments, `TextDocumentContentProvider`, decorations. *Prior art (patterns proven in earlier coauthoring work, reused here on their own merits): baseline pinning, char-precise - attribution, the portable coauthoring sidecar, and live turn progress.* + attribution, the portable coauthoring sidecar, live turn progress, and editable + proposals (tweak-before-keep with mixed human/machine authorship).*