F4: propose/accept diff flow — pending proposals, ✓/✗ review, seam-applied acceptance (Feature #12) #13
@@ -12,7 +12,8 @@ catalog (a pure, key-free SDK call) in a notification and the
|
||||
"Cowriting (Cline SDK)" output channel.
|
||||
|
||||
Features shipped so far: F2 region-anchored threads (Feature #4), F3 live
|
||||
human/Claude attribution (Feature #6).
|
||||
human/Claude attribution (Feature #6), F4 propose/accept diff flow
|
||||
(Feature #12).
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -67,13 +68,36 @@ Attribution" output channel) rather than silently moved or discarded.
|
||||
- **`Cowriting: Ask Claude to Edit Selection`** — select text → enter an
|
||||
instruction → a live `@cline/sdk` turn runs on the built-in `claude-code`
|
||||
provider (rides your local Claude Code Pro/Max login; the extension stores no
|
||||
credentials). The replacement lands in the buffer as a Claude-attributed span.
|
||||
credentials). As of F4 the turn ends in a **proposal** (see below); accepted
|
||||
text lands as a Claude-attributed span.
|
||||
- **`Cowriting: Toggle Attribution`** — show/hide attribution decorations.
|
||||
- `cowriting.applyAgentEdit` _(palette-hidden)_ — the single machine-edit
|
||||
ingress seam. Tests drive this directly so CI requires no LLM.
|
||||
|
||||
Design: `vscode-cowriting-plugin-content/specs/coauthoring-attribution.md`.
|
||||
|
||||
## F4 — Propose/accept diff flow (Feature #12)
|
||||
|
||||
Claude's edits arrive as **pending proposals** — propose-by-default, the
|
||||
document never changes without your say-so. A proposal renders two ways at
|
||||
once: an **amber tint** on the target range, and a "Claude proposes" comment
|
||||
thread showing a fenced `diff` of current → proposed text with two actions:
|
||||
|
||||
- **✓ Accept Proposal** — applies the replacement through the `applyAgentEdit`
|
||||
seam, so it lands Claude-attributed (F3) — and the proposal disappears.
|
||||
- **✗ Reject Proposal** — the document is untouched; the proposal disappears.
|
||||
|
||||
Pending proposals persist git-natively in the same sidecar (`proposals[]`,
|
||||
sharing the F2/F3 `anchors` fingerprints), survive reload, and re-anchor as
|
||||
surrounding text changes. If the **target text itself** changes, the proposal
|
||||
goes **stale** (status-bar count, accept disabled — never applied by guess);
|
||||
undo the change and it becomes decidable again. `cowriting.proposeAgentEdit`
|
||||
_(palette-hidden)_ is the programmatic propose ingress E2E drives — no LLM in
|
||||
CI.
|
||||
|
||||
Design: `vscode-cowriting-plugin-content/specs/coauthoring-propose-accept.md`.
|
||||
Live smoke: [`docs/MANUAL-SMOKE-F4.md`](docs/MANUAL-SMOKE-F4.md).
|
||||
|
||||
## Develop
|
||||
|
||||
- `npm run watch` — rebuild on change.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# F3 manual smoke — live `claude-code` turn (spec §6.8)
|
||||
|
||||
> **As of F4 (#12)** the edit-selection turn ends in a **proposal** — the
|
||||
> direct-apply behavior in §2 step 4 now happens on **✓ Accept Proposal**. The
|
||||
> full propose→accept smoke is [`MANUAL-SMOKE-F4.md`](./MANUAL-SMOKE-F4.md);
|
||||
> §1's scripted smoke is unchanged (it drives the SDK turn only, no editor).
|
||||
|
||||
The live turn is deliberately NOT in CI (unit + host E2E drive the seam). It
|
||||
gets this documented smoke, run once per machine that has Claude Code
|
||||
installed and signed in (Pro/Max). The extension itself holds no credentials
|
||||
@@ -37,9 +42,9 @@ the model id, a non-empty `sessionId`, and exits 0.
|
||||
with a clear error (`runEditTurn` throws on any non-`completed` run
|
||||
status); in-editor, the command shows an error notification and NO edit is
|
||||
applied.
|
||||
- Buffer edited mid-turn: start an edit-selection turn, type elsewhere in the
|
||||
document before it completes → warning notification "document changed", no
|
||||
partial application (stale `expectedVersion`, spec §6.9).
|
||||
- Buffer edited mid-turn: superseded by F4 — the turn ends in a proposal, so a
|
||||
mid-turn edit can't race an application; the proposal simply renders where
|
||||
its target re-resolves (or stale if the target itself changed — F4 INV-11).
|
||||
|
||||
## Smoke log
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Manual smoke — F4 propose/accept (live turn)
|
||||
|
||||
Pre-req: Claude Code installed + signed in (the `claude-code` provider rides
|
||||
that login — the extension holds no credentials, INV-8). Run on a real machine,
|
||||
not CI.
|
||||
|
||||
1. `npm run build`, then F5 (the EDH opens the committed `sandbox/` playground).
|
||||
2. Open `playground.md`, select a sentence → right-click → **Ask Claude to Edit
|
||||
Selection** → give an instruction.
|
||||
3. ✅ A **proposal** appears: the selection gets an amber tint and a "Claude
|
||||
proposes" comment thread shows a `diff` of current → proposed. **The document
|
||||
text is unchanged** (INV-10).
|
||||
4. Click **✓ Accept Proposal** in the thread title. ✅ The replacement lands and
|
||||
renders Claude-tinted (the F3 attribution substrate); the proposal disappears.
|
||||
5. Repeat with another selection and click **✗ Reject Proposal**. ✅ The document
|
||||
is untouched; the proposal disappears.
|
||||
6. Propose again, then save and reload the window. ✅ The pending proposal is
|
||||
restored at its re-resolved range.
|
||||
7. Failure path: edit the proposed-on text, then try Accept. ✅ Refused with a
|
||||
warning ("target text changed"); undo your edit → Accept works.
|
||||
@@ -8,8 +8,10 @@ open in your dev window (#8).
|
||||
Play here:
|
||||
|
||||
1. Type a sentence below — it renders with the human left-border as you type.
|
||||
2. Highlight it → right-click → **Ask Claude to Edit Selection** — the
|
||||
replacement lands Claude-tinted.
|
||||
2. Highlight it → right-click → **Ask Claude to Edit Selection** — Claude
|
||||
**proposes** a diff (amber tint + a "Claude proposes" thread); click
|
||||
**✓ Accept Proposal** and it lands Claude-tinted, or **✗ Reject Proposal**
|
||||
to discard.
|
||||
3. Edit inside the tinted span — it splits character-precisely.
|
||||
4. Save, then peek at `sandbox/.threads/playground.md.json` — the git-native
|
||||
attribution record. Reopen the file: spans re-resolve.
|
||||
|
||||
Reference in New Issue
Block a user