§7.1 now records the 4 de-risking rungs (mockups → throwaway feasibility
spike → vertical slice → full build), riskiest-API-assumption-first, so any
forced design change lands on throwaway code. Adds coauthoring-feasibility-
spike.md: 5 experiments (E1 editable proposals+Keep/Undo, E2 baseline router,
E3 preview authorship, E4 comment loop, E5 discoverability) with PASS/FAIL
criteria; closes open Q2/Q4/Q7 before any plan is written.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
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 E1–E3, 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: ~2–3 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.
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).