Files
vscode-cowriting-plugin-con…/specs/coauthoring-feasibility-spike.md
T

132 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
status: draft
---
# Feasibility Spike Plan — Coediting Markdown with a Machine (native surfaces)
| | |
| --- | --- |
| **Companion to** | `coauthoring-native-surfaces.md` (Solution Design) — §7.1 rung 2 |
| **Type** | Throwaway discovery **prototype** (handbook §5.3) — code is disposable |
| **Goal** | Prove the API-dependent design assumptions on the **real** VS Code surfaces, cheaply, **before** the full build — so post-ship iteration is polish, not design |
| **Non-goal** | Production code, real Claude/SDK wiring (except E4), persistence durability, polish, breadth |
| **Status** | `draft`**in progress: E1/E3/E5 done, E2/E4 remain** |
---
## Status (2026-07-01, session 0063)
Three of the five experiments are built and passed in `vscode-cowriting-prototype`:
- **E1 — PASS with pivot.** VS Code does **not** render extension CodeLens inside
a diff editor; per-hunk CodeLens works in a normal editor, and tweak-then-Keep
attributes machine words vs. writer edits correctly. Folded back into the
Solution Design as **D18** (the review surface is the live buffer itself,
in-buffer pending changes — see `coauthoring-native-surfaces.md` v0.2.0).
- **E3 — PASS.** The `markdown-it` contribution renders author-colored marks +
deletions in the built-in preview, theme-aware, with a working toggle.
- **E5 — PASS.** Title-bar + status-bar entry points read as obvious without the
Source Control pane.
- **E2 (baseline router: QuickDiff vs git `HEAD` + snapshot) and E4 (comment →
reply → offer → proposal) are not built yet** — now the riskiest unvalidated
assumptions and the spike's remaining work.
## Why this exists
Static mockups validated the *look* and *state coverage*; they prove **nothing**
about whether VS Code's native surfaces actually behave as the spec assumes. Twice
already, an unexamined assumption would have forced a redesign (the diff can't
recolor per author; the Comments API can't render in the preview). The remaining
high-risk assumptions can only be settled by **building on the real API**. This spike
does exactly that and nothing more: each experiment returns a **PASS / PASS-with-
fallback / FAIL**, and any FAIL becomes a spec delta folded back into
`coauthoring-native-surfaces.md` before a plan is written.
## Shape & guardrails
- **One throwaway VS Code extension** (`vscode-cowriting-prototype`), run in the
Extension Development Host. **Delete it when the spike ends** — none of this code
graduates.
- **The machine is stubbed** for E1E3, E5 (a function returning canned `before/after`
edits) so we test *VS Code feasibility and feel*, not the SDK. E4 may use a minimal
real call only if cheap.
- **Time-box: ~23 focused days.** If an experiment can't be made to PASS or
PASS-with-fallback inside its slice, that is itself the finding — record it and move
on.
- **No persistence/durability work**, no anchoring ladder, no cross-rung format — those
are not API-risk; defer to the build.
## Experiments (riskiest first)
### E1 — Editable proposed side + Keep/Undo *(highest risk)*
- **Assumption (INV-12, Q2, Q7):** the machine's proposal can be reviewed in a
multi-diff / diff editor whose **proposed side is writable**, the writer can tweak it
before keeping, and **per-change Keep/Undo** works.
- **Build:** open a diff between a read-only baseline (`cowriting-baseline:` virtual
doc) and a **writable** proposal doc (untitled/in-memory) seeded with a canned edit;
attach Keep/Reject actions (try the multi-diff overlay; fall back to per-hunk
**CodeLens**). Edit the proposal side; on Keep, apply to the "live" doc and attribute
machine-vs-tweak by diffing final ↔ canned ↔ baseline.
- **PASS:** proposed side is editable; Keep applies the *tweaked* text; attribution
splits correctly; live doc untouched until Keep.
- **Decides:** Q2 (stable ceiling vs CodeLens fallback), Q7 (Keep/Undo after free
cross-hunk edits). **If FAIL:** the accept/reject surface design changes — know now.
### E2 — Baseline router (git HEAD + snapshot)
- **Assumption (INV-7):** a `QuickDiffProvider` against a `cowriting-baseline:` doc
shows gutter bars + "Open Changes"; the original resolves from **git `HEAD`** when
tracked and from a **snapshot** otherwise; the diff goes **clean on commit /
Mark-Reviewed**.
- **Build:** register the provider; for a repo file read `HEAD` via the Git extension
API and recompute on `repository.state.onDidChange`; for a `~/Downloads` / untitled
file use a stored/in-memory snapshot. Commit (git) and "Mark Changes as Reviewed"
(snapshot) → confirm the diff clears.
- **PASS:** both modes render the expected diff; both resets clear it; works for an
untitled doc.
### E3 — Preview authorship via markdown-it
- **Assumption (PUC-3, D11):** a contributed `markdown.markdownItPlugins` /
`extendMarkdownIt` plugin injects per-span **authorship colors + deletions** into the
**built-in** Markdown preview, toggled by a setting/command, with no custom webview.
- **Build:** contribute the plugin; feed canned attributions/changes; render
green/blue + strikethrough; toggle `cowriting.annotations` on/off.
- **PASS:** marks render inside the native preview; toggle works; deletions show;
scroll-sync intact. **If FAIL:** authorship-surface design changes.
### E4 — Comment → reply → offer → proposal loop
- **Assumption (PUC-8, D10):** a Comments-API thread on a coedited doc can fire a turn,
post a **machine reply `Comment`**, and convert an accepted **offer** into a pending
proposal (E1's surface). Also: a **preview selection → native thread on source** via
the markdown-it token `.map` (D15).
- **Build:** create a thread on selection (and from a preview selection mapped to
source); on add, run a stubbed-or-minimal turn; post a reply comment with an
"Make this edit" action that opens an E1 proposal.
- **PASS:** reply appears in-thread; offer→proposal works; preview-initiated thread
lands on the correct source range. *(Feel/latency notes captured.)*
### E5 — Discoverability (title bar + status bar)
- **Assumption (INV-13):** the editor **title-bar** actions (`editor/title` menus) and
a **`StatusBarItem`** (`✦ Coediting · N changes`, click → review) are visible and
obvious without the Source Control pane; everything gates on `cowriting.isCoediting`.
- **Build:** contribute the menus + status-bar item gated on the context key; enter/exit
coediting flips them.
- **PASS:** a first-time (non-git) user can find "review changes" without opening Source
Control. *(Cheapest experiment — fold into the others.)*
## Output
A short **findings report** (PASS / PASS-with-fallback / FAIL per experiment, with the
feel notes for E1/E4) and, for any non-PASS, a concrete **spec delta** applied to
`coauthoring-native-surfaces.md` — explicitly resolving open questions **Q2, Q4, Q7**.
Then the code is deleted and delivery moves to rung 3 (vertical slice).
## Mapping to the design
| Experiment | Validates | Closes |
| --- | --- | --- |
| E1 | INV-12 · editable proposals + Keep/Undo | Q2, Q7 |
| E2 | INV-7 · baseline router (HEAD + snapshot) | — |
| E3 | PUC-3 / D11 · preview authorship | — |
| E4 | PUC-8 / D10 / D15 · comment loop + preview-initiated thread | — |
| E5 | INV-13 · title-bar / status-bar discovery | — |
| (any FAIL needing a non-native surface) | INV-3 escape hatch | Q4 |