spec(0062): native-first coauthoring — VS Code-idiomatic redesign (design-only north star)
Solution Design for a brand-new plugin that re-homes the inner-loop coauthoring experience onto native VS Code surfaces: QuickDiffProvider + native diff editor (any diff), multi-diff editor Keep/Undo (propose/accept), built-in Markdown preview markdown-it extension (rendered preview), Comments API (threads). Carries forward pinned baseline (F6), authorship attribution (F3), cross-rung sidecar (F5), live progress (#60), on-behalf-of identity, and the pure-core/thin-controller discipline. Design-only: no repo/migration commitment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,788 @@
|
||||
---
|
||||
status: draft
|
||||
---
|
||||
# Solution Design: Native-First Coauthoring — a VS Code-idiomatic redesign
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Author(s)** | Ben Stull (with Claude) |
|
||||
| **Reviewers / approvers** | Ben Stull |
|
||||
| **Status** | `draft` |
|
||||
| **Version** | v0.1.0 |
|
||||
| **Source artifacts** | North-star architecture spec (design-only). Lineage: the shipped plugin Epic `benstull/vscode-cowriting-plugin#1` and its Features F1–F12 (the experience this re-homes). Reuses concepts from `coauthoring-inner-loop.md`, `coauthoring-attribution.md`, `coauthoring-propose-accept.md`, `coauthoring-diff-view.md`, `coauthoring-rendered-preview.md`, `coauthoring-cross-rung-format.md`, `coauthoring-live-progress.md`. Supersedes: none (design-only; does not commit a repo or migration). |
|
||||
|
||||
**Change log**
|
||||
|
||||
| Date | Version | Change | By |
|
||||
| --- | --- | --- | --- |
|
||||
| 2026-06-27 | v0.1.0 | Initial draft — brainstorming session 0062 | Ben Stull + Claude |
|
||||
|
||||
---
|
||||
|
||||
## 1. Business Context
|
||||
|
||||
*The business lens — solution-agnostic throughout. No mechanism is proposed until §2.*
|
||||
|
||||
### 1.1 Executive Summary
|
||||
|
||||
A writer working with a machine coauthor needs three things to feel native to
|
||||
their editor: to **see what changed** against a known-good point, to **review and
|
||||
accept or reject the machine's proposed changes** one at a time, and to **read a
|
||||
clean rendered version** of the document with those changes legible. The existing
|
||||
plugin (Epic #1, F1–F12) proved that experience is valuable — but it built each of
|
||||
those three surfaces as bespoke UI (custom webviews, hand-rolled diff rendering,
|
||||
editor decoration overlays) that the writer must *learn*. This design re-homes the
|
||||
same experience onto the surfaces the writer **already knows** — VS Code's own diff
|
||||
editor, Source Control gutter, multi-diff review, and Markdown preview — so the
|
||||
coauthoring loop reads as a built-in capability of the editor rather than a foreign
|
||||
panel grafted onto it. The value is lower cognitive cost for the writer and a
|
||||
dramatically smaller surface for us to build, test, and maintain.
|
||||
|
||||
### 1.2 Background
|
||||
|
||||
The forge (Gitea / rfc-app) is the *outer* loop — durable review and record. The
|
||||
*inner* loop — writing, keystroke by keystroke, with a machine coauthor — lives in
|
||||
the editor. The shipped plugin delivered that inner loop as a standalone VS Code
|
||||
extension on `@cline/sdk`, accreting twelve Features: region threads, char-precise
|
||||
attribution, propose/accept, cross-rung persistence, a diff view, a rendered
|
||||
track-changes preview, an interactive review panel, a preview toolbar, an inline
|
||||
editor diff, and live turn progress. Each Feature solved a real need, but the diff,
|
||||
the accept/reject, and the preview were each implemented as **custom rendering** —
|
||||
webviews with bundled markdown-it/mermaid, sealed message channels, and
|
||||
`TextEditorDecorationType` overlays — reinventing machinery VS Code already ships.
|
||||
The accumulated UI is powerful but idiosyncratic: it does not look or behave like
|
||||
the rest of the editor, and it is large to maintain.
|
||||
|
||||
VS Code, meanwhile, exposes first-class APIs for exactly these three needs. The
|
||||
strategic question this spec answers: *if we designed the plugin from scratch today
|
||||
with "feels like a built-in feature" as the north star, how close to native VS Code
|
||||
patterns could we get, and what would the architecture be?*
|
||||
|
||||
### 1.3 Business Actors / Roles
|
||||
|
||||
| Role | Responsible for (in the business) |
|
||||
| --- | --- |
|
||||
| **Coauthor (human)** | A writer/engineer authoring prose, specs, or docs in their editor. Owns the document; decides what changes land. |
|
||||
| **Coauthor (machine)** | The machine coauthor (Claude, via `@cline/sdk`). Proposes changes on the human's behalf; never lands them unilaterally. |
|
||||
|
||||
### 1.4 Problem Statement
|
||||
|
||||
The coauthoring experience is delivered through UI the writer must learn anew —
|
||||
bespoke panels, custom-rendered diffs, and overlay decorations that do not match,
|
||||
and do not cooperate with, the editor surfaces the writer uses every day. The
|
||||
experience is *foreign to its host*. Separately, that bespoke UI is costly to
|
||||
build and maintain: every surface (diff, accept/reject, preview) is a hand-written
|
||||
renderer with its own bugs, its own test harness, and its own divergence from
|
||||
platform conventions (theming, scroll-sync, accessibility, keyboard model).
|
||||
|
||||
### 1.5 Pain Points
|
||||
|
||||
| # | Pain | Who feels it | Cost / frequency today |
|
||||
| --- | --- | --- | --- |
|
||||
| PP-1 | The diff/accept/preview surfaces don't look or behave like the rest of VS Code — new mental model to learn | Coauthor (human) | Every session; friction on every review |
|
||||
| PP-2 | Custom webview/decoration rendering re-implements platform machinery (theming, scroll-sync, a11y, diff layout) and drifts from it | Maintainer | Ongoing; each Feature added more surface to own |
|
||||
| PP-3 | Accept/reject lives in a bespoke panel rather than where the writer reviews changes natively (the diff) | Coauthor (human) | Every proposal review |
|
||||
| PP-4 | The rendered preview is a sealed webview that can't cooperate with other Markdown extensions the writer already uses | Coauthor (human) | Every preview open |
|
||||
|
||||
### 1.6 Targeted Business Outcomes
|
||||
|
||||
| # | Outcome | Success metric | Baseline → Target | Guardrail (must not regress) | How / when measured |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| BO-1 | The coauthoring loop reads as a built-in editor capability (familiarity, lower learning cost) | Writer can complete a see-diff → review-proposal → read-preview loop using only native surfaces they already know | bespoke panels → native surfaces | The full inner-loop experience (diff, accept/reject, preview, threads, attribution, live progress) is preserved | Dogfooding walkthrough on the design's first build |
|
||||
| BO-2 | The plugin is materially cheaper to build and maintain | Custom-rendering LOC retired in favor of platform APIs | large webview/decoration surface → thin controllers over native APIs | No capability dropped | Code-size + test-surface comparison at build time |
|
||||
|
||||
### 1.7 Scope (business)
|
||||
|
||||
- **In scope:** a from-scratch architecture for the inner-loop coauthoring
|
||||
experience that maximizes use of native VS Code surfaces for the three core needs
|
||||
(see a diff, review proposed changes, read a rendered preview), plus the proven
|
||||
supporting capabilities (region threads, authorship attribution, durable
|
||||
cross-rung persistence, live turn progress, on-behalf-of identity).
|
||||
- **Out of scope:** committing a specific repository, a migration plan from the
|
||||
shipped plugin, or a marketplace release. This is a **design-only north-star**
|
||||
(see §2): repo-and-migration decisions are deferred to a delivery decision, not
|
||||
taken here.
|
||||
- **Non-goals:** changing *what* the coauthoring experience is (the loop is
|
||||
validated); a server or cloud backend (the inner loop stays serverless,
|
||||
git-native); multi-file agent orchestration beyond the single-document loop.
|
||||
|
||||
### 1.8 Assumptions · Constraints · Dependencies
|
||||
|
||||
- **Assumptions:** VS Code's stable APIs (SCM/QuickDiff, diff editor, multi-diff
|
||||
editor, Markdown preview `markdown-it` contribution, Comments, decorations,
|
||||
`TextDocumentContentProvider`, `FileSystemWatcher`) remain available; the machine
|
||||
coauthor runs locally via `@cline/sdk` as in the shipped plugin.
|
||||
- **Constraints:** serverless and git-native (no external store); no secret bytes
|
||||
in artifacts or transcripts (§6.3-handbook); a VS Code extension has **no §9
|
||||
deploy pipeline stage** (it is not a webapp — see §7.2).
|
||||
- **Dependencies:** `@cline/sdk` (loaded via runtime dynamic `import()` — never
|
||||
bundled; a POC-validated fact carried forward). The shipped plugin's pure cores
|
||||
(attribution, anchoring, merge, turn-progress reducer) are the reuse source.
|
||||
|
||||
### 1.9 Business Use Cases
|
||||
|
||||
**BUC-1 — As a human coauthor, I can see what changed in my document since a point I
|
||||
chose, in a familiar diff, so that I can trust what I am about to keep.**
|
||||
|
||||
```gherkin
|
||||
Scenario: BUC-1 — review changes against a chosen point
|
||||
Given I marked the document as "good" at some earlier moment
|
||||
And the document has changed since then
|
||||
When I ask to see what changed
|
||||
Then the changes are shown in the same diff experience I use for everything else
|
||||
```
|
||||
|
||||
- **BUC-1 acceptance criteria:** the human sees an accurate before/after of the
|
||||
document against the chosen point, in their editor's normal diff experience.
|
||||
|
||||
**BUC-2 — As a human coauthor, I can review the machine's proposed changes and accept
|
||||
or reject them one at a time, so that I stay in control of what lands.**
|
||||
|
||||
```gherkin
|
||||
Scenario: BUC-2 — accept or reject proposed changes
|
||||
Given the machine coauthor has proposed changes to my document
|
||||
When I review them
|
||||
Then I can keep or discard each proposed change individually, or all at once
|
||||
And nothing the machine proposed lands until I keep it
|
||||
```
|
||||
|
||||
- **BUC-2 acceptance criteria:** no proposed change alters the document until the
|
||||
human keeps it; each change is independently keepable/discardable; an accept-all
|
||||
and reject-all exist.
|
||||
|
||||
**BUC-3 — As a human coauthor, I can read a clean, rendered version of my document with
|
||||
the changes and authorship made legible, so that I can judge the result as prose,
|
||||
not as markup.**
|
||||
|
||||
```gherkin
|
||||
Scenario: BUC-3 — read the rendered result
|
||||
Given my document has changed and has mixed authorship
|
||||
When I open its rendered preview with annotations on
|
||||
Then I see the document rendered, with changes and authorship visibly marked
|
||||
And I can turn the annotations off to read it clean
|
||||
```
|
||||
|
||||
- **BUC-3 acceptance criteria:** the rendered document shows track-changes and
|
||||
authorship when annotations are on, renders clean when off, in a preview that
|
||||
behaves like the editor's normal Markdown preview.
|
||||
|
||||
**BUC-3a (unhappy) — As a human coauthor, when an anchored thread / attribution /
|
||||
proposal can no longer be confidently placed after edits, I am shown it as orphaned
|
||||
rather than silently moved to the wrong place.**
|
||||
|
||||
---
|
||||
|
||||
## 2. Solution Proposal
|
||||
|
||||
**Build software: a brand-new VS Code extension that delivers the inner-loop
|
||||
coauthoring experience almost entirely through native VS Code surfaces**, keeping
|
||||
the shipped plugin's validated *experience* and its proven *pure cores* while
|
||||
discarding its bespoke *rendering*.
|
||||
|
||||
The unifying idea: **model the coauthored document as a tiny Source Control.** The
|
||||
last point the human marked "good" (the **pinned baseline**, carried from F6) is the
|
||||
SCM *original*; the live document is the working tree; the machine's proposed edits
|
||||
are *pending changes*. Once the relationship is framed as source control, VS Code's
|
||||
own machinery supplies the three core surfaces for free:
|
||||
|
||||
| Core need | Native surface | Replaces (shipped plugin) |
|
||||
| --- | --- | --- |
|
||||
| See any diff | `QuickDiffProvider` gutter bars + the **native diff editor** (`vscode.diff`) against a `cowriting-baseline:` virtual document | F6 custom diff-view controller |
|
||||
| Propose / accept / reject | the **multi-diff editor** with per-change **Keep/Undo** (the "AI edits" review feel), backed by the existing propose/accept model | F4/F10/F12 webview + decoration accept/reject UI |
|
||||
| Rendered preview | **extend the built-in Markdown preview** via a `markdown-it` plugin contribution (authorship + track-changes injected into VS Code's own preview) | F7/F10 sealed webview renderer |
|
||||
| Region threads | the **Comments API** (already native in F2 — kept as-is) | — (already native) |
|
||||
| Live turn progress | notification activity-line + a shared **OutputChannel** + cancellable turn | #60 (kept; already native) |
|
||||
|
||||
**Why this approach over the alternatives.** The do-nothing option (keep the shipped
|
||||
plugin) leaves a foreign-feeling, maintenance-heavy UI. A "polish the webviews"
|
||||
option spends effort making bespoke surfaces *look* native without getting the
|
||||
platform's behavior (theming, scroll-sync, a11y, keyboard model, cooperation with
|
||||
other extensions) — it pays the cost without the benefit. Re-homing onto native
|
||||
surfaces gets the behavior for free and shrinks what we own. The cost is accepting
|
||||
the platform's affordances where they differ from our bespoke ones, and a small
|
||||
stable-API boundary on the per-change Keep/Undo overlay (§6.10, §13).
|
||||
|
||||
**Decision posture:** this is a **design-only north star**. It commits to the
|
||||
architecture and the native-surface mapping; it does **not** commit to a new repo
|
||||
vs. an in-place re-platform, nor to a data migration. Those are taken at delivery
|
||||
(§7.1, Q1 in §13).
|
||||
|
||||
**Solution scope.** *In:* the architecture, surface mapping, data model, contracts,
|
||||
and per-use-case design for the native-first plugin, plus carry-forward of pinned
|
||||
baseline, authorship attribution, cross-rung persistence, live progress, threads,
|
||||
and on-behalf-of identity. *Out:* repo/migration choice, marketplace publish,
|
||||
multi-file orchestration. *Non-goal:* re-deriving the coauthoring experience — it is
|
||||
inherited from F1–F12.
|
||||
|
||||
---
|
||||
|
||||
## 3. Product Personas
|
||||
|
||||
| Product persona | In the plugin | Maps to business role(s) |
|
||||
| --- | --- | --- |
|
||||
| **PP-1 Inner-loop writer** | Pins a baseline, asks the machine to edit, reviews proposed changes in the diff, reads the annotated preview, opens region threads. | Coauthor (human) |
|
||||
| **PP-2 Machine coauthor (Claude)** | Runs a turn via `@cline/sdk`, streams progress, and emits **proposed** edits (never lands them); authored spans carry its provenance. | Coauthor (machine) |
|
||||
|
||||
## 4. Product Use Cases
|
||||
|
||||
```gherkin
|
||||
Scenario: PUC-1 — see the diff against the pinned baseline (realizes BUC-1)
|
||||
Given I run "Cowriting: Pin Review Baseline to Now"
|
||||
When I later edit the document
|
||||
Then the SCM gutter shows change bars against the baseline
|
||||
And "Open Changes" opens the native diff editor (baseline ⟷ live), inline or side-by-side at my choice
|
||||
```
|
||||
|
||||
```gherkin
|
||||
Scenario: PUC-2 — review and accept/reject proposed changes (realizes BUC-2)
|
||||
Given I ask the machine coauthor to edit the document (or a selection)
|
||||
When the turn completes
|
||||
Then the proposed changes open in a multi-diff review (baseline ⟷ proposed)
|
||||
And each change offers Keep / Undo (Accept / Reject)
|
||||
And toolbar actions offer Accept all / Reject all
|
||||
And the document is unchanged until I keep a change
|
||||
```
|
||||
|
||||
```gherkin
|
||||
Scenario: PUC-3 — read the annotated rendered preview (realizes BUC-3)
|
||||
Given my document has changes and mixed authorship
|
||||
When I open the built-in Markdown preview with Cowriting annotations enabled
|
||||
Then track-changes (insert/delete) and authorship colors render inside the native preview
|
||||
And toggling "cowriting.annotations" off renders the document clean
|
||||
```
|
||||
|
||||
```gherkin
|
||||
Scenario: PUC-4 — region thread (realizes BUC-3a; carried from F2)
|
||||
Given I select a region and add a coauthoring thread
|
||||
When I edit around it or reload
|
||||
Then the thread re-anchors; if it cannot be confidently placed it is shown orphaned, never silently moved
|
||||
```
|
||||
|
||||
```gherkin
|
||||
Scenario: PUC-5 — live turn progress (carried from #60)
|
||||
Given I started a machine turn
|
||||
When the machine is working
|
||||
Then a notification shows the live activity line and token count
|
||||
And the "Cowriting: Claude" OutputChannel streams the full text
|
||||
And I can cancel the turn
|
||||
```
|
||||
|
||||
```gherkin
|
||||
Scenario: PUC-6 — reload / external change (realizes BUC-3a)
|
||||
Given I reopen the workspace or an external change lands (a git pull)
|
||||
When the document loads
|
||||
Then baseline, proposals, attributions, and threads re-resolve against current text
|
||||
And anything that cannot be confidently placed is shown orphaned
|
||||
```
|
||||
|
||||
## 5. UX Layout
|
||||
|
||||
The experience is delivered through **native VS Code surfaces**; there is no bespoke
|
||||
panel to wireframe. Described in text (source of truth):
|
||||
|
||||
- **Source Control gutter & viewlet.** A dedicated `SourceControl` named
|
||||
*"Cowriting"* coexists with the real Git SCM. Its `QuickDiffProvider` draws the
|
||||
familiar change bars in the editor gutter against the pinned baseline. Its
|
||||
resource group(s) list the document's pending coauthoring changes; "Open Changes"
|
||||
uses the native diff editor.
|
||||
- **Native diff editor.** `vscode.diff(baselineUri, docUri)` — the writer's normal
|
||||
diff, with the platform's inline/side-by-side toggle, navigation, and a11y.
|
||||
- **Multi-diff review editor.** When the machine proposes edits, a multi-diff editor
|
||||
opens showing baseline⟷proposed, each change carrying **Keep/Undo**; a toolbar
|
||||
carries **Accept all / Reject all**. This is the accept/reject surface.
|
||||
- **Built-in Markdown preview.** The writer's normal "Open Preview to the Side";
|
||||
with Cowriting annotations on, authorship colors and track-changes marks appear
|
||||
*inside* it (contributed `markdown-it` plugin + preview stylesheet). A command/
|
||||
setting toggles annotations.
|
||||
- **Comments gutter.** Region threads via the native Comments API (create on
|
||||
selection, reply, resolve), exactly as F2.
|
||||
- **Notification + OutputChannel.** Live turn progress, with a Cancel action.
|
||||
|
||||
### 5.1 Design tooling decision
|
||||
|
||||
- **Decision:** **Code directly.**
|
||||
- **Rationale:** the entire thesis is to use native VS Code chrome, so there is no
|
||||
net-new bespoke visual surface to explore. Scoring the six-question rubric:
|
||||
Q1 −1 (no net-new surface — native editor chrome), Q2 −1 (UI is specified at
|
||||
wireframe-level prose against known platform surfaces), Q3 −1 (no multi-page
|
||||
visual language), Q4 −1 (VS Code *is* the design system here), Q5 −1 (solo build),
|
||||
Q6 −1 (logic-dominant — wiring pure cores to platform APIs). Total **−6 → Skip
|
||||
Design**. The only "designed" pixels are the preview annotation stylesheet (a
|
||||
small CSS theme using VS Code theme variables), which does not warrant Design.
|
||||
- **Design:** N/A — no bespoke UI surface (native VS Code surfaces only).
|
||||
|
||||
### 5.2 Screen: native surfaces (serves PUC-1…PUC-6)
|
||||
|
||||
Covered in the §5 text above. No custom screen; states map to platform states
|
||||
(diff editor empty/identical, multi-diff empty, preview loading/error) plus the
|
||||
coauthoring **orphaned** state surfaced in the Comments thread / proposal listing.
|
||||
|
||||
## 6. Technical Design
|
||||
|
||||
### 6.1 Invariants
|
||||
|
||||
- **INV-1 (carried from F2/INV-1):** an anchored artifact (thread, attribution,
|
||||
proposal) is **never silently moved** to a wrong span; if it cannot be confidently
|
||||
re-resolved it becomes **orphaned** (visible, flagged).
|
||||
- **INV-2 (carried):** persistence is **git-native and serverless** — diffable,
|
||||
human-resolvable JSON; **no server, no external store**. (The *baseline* is the
|
||||
one exception: it is a throwaway local artifact stored **outside** the repo —
|
||||
INV-7.)
|
||||
- **INV-3 — native-first:** the diff, accept/reject, and rendered-preview surfaces
|
||||
are delivered by **native VS Code APIs**, not bespoke webviews or decoration
|
||||
overlays. New custom rendering requires an explicit, recorded justification
|
||||
(§6.7) that no native surface fits.
|
||||
- **INV-4 (carried):** the persisted artifact is **forward-compatible and
|
||||
cross-rung**: `schemaVersion` present; `anchors`, `provenance`, `attributions`,
|
||||
`proposals`, `threads` share one envelope; **unknown fields are preserved** on
|
||||
read/merge round-trips (the F5 cross-rung contract).
|
||||
- **INV-5 — proposals are pending until kept:** a proposed edit does **not** mutate
|
||||
the document until the human keeps it (Keep in the multi-diff, or Accept). This is
|
||||
the propose-by-default rule (carried from F4), now expressed through the SCM/diff
|
||||
surface.
|
||||
- **INV-6 — pure cores stay vscode-free:** attribution, anchoring, merge, diffing,
|
||||
and the turn-progress reducer are pure modules with no `vscode` import,
|
||||
unit-tested in isolation; controllers are the only `vscode`-aware layer (the
|
||||
shipped plugin's most valuable discipline — carried wholesale).
|
||||
- **INV-7 (carried from F6):** the **pinned baseline** is the diff *original* and is
|
||||
stored **outside** the working tree (global storage keyed by document URI hash),
|
||||
so it never pollutes the repo and works for any file (including untitled).
|
||||
- **INV-8 — provenance carries on-behalf-of identity:** every authored span /
|
||||
message records `provenance` (human git identity, or agent with `onBehalfOf` the
|
||||
human), reused across attributions, proposals, and threads (carried from
|
||||
identity + F3 + F5).
|
||||
- **INV-9 (carried from #60):** a machine turn is **observable and cancellable** —
|
||||
it streams progress and honors an `AbortSignal`; the progress reducer is pure.
|
||||
|
||||
### 6.2 High-level architecture
|
||||
|
||||
The shape mirrors the shipped plugin's most durable pattern: **pure, vscode-free
|
||||
cores** + **thin controllers** that wire those cores to **native surfaces**.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Cores["Pure cores (vscode-free, unit-tested)"]
|
||||
AT[Attribution tracker<br/>char-precise spans]
|
||||
AN[Anchorer<br/>fingerprint + offsets + orphan]
|
||||
MG[mergeArtifacts<br/>union-by-id, unknown-field-safe]
|
||||
DF[Diff/hunk engine<br/>word- & block-level]
|
||||
TP[turnProgress<br/>reducer]
|
||||
RA[renderAnnotations<br/>markdown-it transform]
|
||||
end
|
||||
subgraph Ctrls["Thin controllers (vscode-aware)"]
|
||||
SC[SourceControl + QuickDiffProvider]
|
||||
BP[Baseline provider<br/>TextDocumentContentProvider]
|
||||
PR[Proposal/review controller<br/>multi-diff Keep/Undo]
|
||||
PV[Preview extension<br/>extendMarkdownIt]
|
||||
TC[ThreadController<br/>Comments API]
|
||||
LP[liveProgress relay]
|
||||
ST[SidecarRouter + Store]
|
||||
end
|
||||
subgraph Native["Native VS Code surfaces"]
|
||||
GUT[Gutter dirty-diff + SCM viewlet]
|
||||
DIFF[Native diff editor]
|
||||
MDIFF[Multi-diff review + Keep/Undo]
|
||||
MDPREV[Built-in Markdown preview]
|
||||
COMM[Comments gutter/peek]
|
||||
NOTE[Notification + OutputChannel]
|
||||
end
|
||||
SDK[["@cline/sdk (dynamic import)"]]
|
||||
|
||||
AN --> SC --> GUT
|
||||
BP --> DIFF
|
||||
DF --> PR --> MDIFF
|
||||
AT --> RA --> PV --> MDPREV
|
||||
AN --> TC --> COMM
|
||||
TP --> LP --> NOTE
|
||||
SDK --> PR
|
||||
Cores --- ST
|
||||
Ctrls --- ST
|
||||
```
|
||||
|
||||
- **SourceControl + QuickDiffProvider** — owns the "Cowriting" source control and
|
||||
the gutter dirty-diff; must never write to the user's document.
|
||||
- **Baseline provider** — a `TextDocumentContentProvider` for the
|
||||
`cowriting-baseline:` scheme; serves the pinned baseline text for any doc URI from
|
||||
the out-of-repo baseline store (INV-7).
|
||||
- **Proposal/review controller** — turns the machine's emitted edits into pending
|
||||
proposals, opens the multi-diff review, and applies Keep/Undo (Accept/Reject) by
|
||||
delegating to the propose/accept model; must honor INV-5.
|
||||
- **Preview extension** — contributes `markdown-it` so the pure `renderAnnotations`
|
||||
transform runs inside the built-in preview; owns no webview.
|
||||
- **SidecarRouter + Store** — persistence (carried from F8): repo `.threads/` when
|
||||
in-workspace, global-storage sidecar by URI-hash otherwise; cross-rung envelope.
|
||||
|
||||
### 6.3 Data model & ownership
|
||||
|
||||
| Entity | Owned by | Key fields | System of record |
|
||||
| --- | --- | --- | --- |
|
||||
| Coauthoring sidecar | the extension (sole writer) | `schemaVersion`, `document.path`, `anchors{}`, `provenance`, `attributions[]`, `proposals[]`, `threads[]`, unknown-field passthrough | git-committed `.threads/<path>.json` (in-workspace) or global-storage sidecar (out-of-workspace), per SidecarRouter |
|
||||
| Pinned baseline | the extension | doc URI hash → baseline text + pin reason/time | **out-of-repo** global storage (INV-7) — throwaway, not committed |
|
||||
| Provenance | the extension | `kind` (human/agent), `id`, `email`, `onBehalfOf`, `agent{sdk,model,sessionId}` | embedded in sidecar (INV-8) |
|
||||
|
||||
The envelope is the F5 **cross-rung contract** verbatim (v1.x, additive,
|
||||
unknown-field-preserving) — the sidecar round-trips to the Gitea substrate
|
||||
unchanged. The **baseline is deliberately not** in this envelope: it is local,
|
||||
disposable review state (INV-7), not durable coauthoring metadata.
|
||||
|
||||
```jsonc
|
||||
// .threads/docs/spec.md.json — the cross-rung envelope (carried from F5)
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"document": { "path": "docs/spec.md" },
|
||||
"anchors": { "a1": { "fingerprint": { "text": "…", "before": "…", "after": "…", "lineHint": 42 } } },
|
||||
"attributions": [ { "anchorId": "a1", "provenance": <Provenance>, "span": { "start": 0, "end": 12 } } ],
|
||||
"proposals": [ { "id": "p1", "anchorId": "a1", "status": "pending", // pending|accepted|rejected (INV-5)
|
||||
"granularity": "block", // word|block (carried from #47)
|
||||
"provenance": <Provenance>, "before": "…", "after": "…" } ],
|
||||
"threads": [ { "id": "t1", "anchorId": "a1", "status": "open", "messages": [ … ] } ]
|
||||
// unknown top-level fields preserved verbatim (INV-4)
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 Interfaces & contracts
|
||||
|
||||
- **Baseline provider** — `TextDocumentContentProvider` for `cowriting-baseline:`;
|
||||
`provideTextDocumentContent(uri) → baselineText`. `BaselineStore.pin(docUri,
|
||||
text, reason)` / `get(docUri) → {text, reason} | null` (out-of-repo, INV-7).
|
||||
- **QuickDiffProvider** — `provideOriginalResource(docUri) → cowriting-baseline:`
|
||||
URI (drives gutter bars). Registered on the "Cowriting" `SourceControl`.
|
||||
- **Agent edit seam (carried from F3/F4)** — the single boundary where machine text
|
||||
enters the model: `proposeAgentEdit(docUri, range, newText, provenance)` →
|
||||
produces **pending** `proposals[]` entries (never mutates the doc — INV-5).
|
||||
Block/word granularity via the pure diff engine (`diffToBlockHunks` /
|
||||
`wordEditHunks`, carried from #47/F4). Word-diff splitting reconciled by
|
||||
`matchEvent` (the F4 host fix) lives in the pure engine.
|
||||
- **Proposal/review controller** — `openReview(docUri)` opens the multi-diff
|
||||
(baseline⟷proposed); `keep(proposalId)` = Accept (applies the edit, attributes
|
||||
changed words via the F5/F4 `acceptBlock` path, INV-40-style); `undo(proposalId)`
|
||||
= Reject (drops it); `keepAll()` / `undoAll()` = Accept/Reject all (descending,
|
||||
orphan-skip + report — carried from #46).
|
||||
- **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.
|
||||
- **Turn runner (carried from #60)** — `runEditTurn(prompt, { onProgress,
|
||||
signal, env }) → AgentResult`; pure `turnProgress` reducer; `liveProgress` relay
|
||||
to notification + OutputChannel; `CLAUDE_CODE_AUTO_CONNECT_IDE=0` env carried (the
|
||||
#59 Apple-Events fix).
|
||||
- **ThreadController** (carried from F2) — create/reply/resolve via Comments API.
|
||||
|
||||
### 6.5 Per–Product-Use-Case design
|
||||
|
||||
#### PUC-1 — see the diff against the pinned baseline
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor U as Writer
|
||||
participant C as SCM/QuickDiff ctrl
|
||||
participant B as Baseline provider
|
||||
participant V as Native diff editor
|
||||
U->>C: Pin baseline (cowriting.pinBaseline)
|
||||
C->>B: BaselineStore.pin(docUri, text)
|
||||
U->>U: edits document
|
||||
C-->>U: gutter dirty-diff bars (provideOriginalResource)
|
||||
U->>V: Open Changes
|
||||
V->>B: read cowriting-baseline:docUri
|
||||
V-->>U: native diff (baseline ⟷ live)
|
||||
```
|
||||
|
||||
- **Implementation:** QuickDiffProvider points at the `cowriting-baseline:` URI;
|
||||
the platform renders gutter bars and powers "Open Changes" / `vscode.diff`. No
|
||||
custom diff rendering (replaces F6). Honors INV-3, INV-7.
|
||||
|
||||
#### PUC-2 — review and accept/reject proposed changes
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor U as Writer
|
||||
participant R as Proposal/review ctrl
|
||||
participant S as "@cline/sdk"
|
||||
participant M as Multi-diff editor
|
||||
U->>R: Ask Claude to edit (cowriting.edit)
|
||||
R->>S: runEditTurn(prompt, {onProgress, signal, env})
|
||||
S-->>R: proposed text
|
||||
R->>R: proposeAgentEdit → pending proposals[] (INV-5)
|
||||
R->>M: openReview (baseline ⟷ proposed)
|
||||
U->>M: Keep / Undo per change · Accept all / Reject all
|
||||
M->>R: keep(p)/undo(p)
|
||||
R-->>U: document updated only on Keep; attribution recorded
|
||||
```
|
||||
|
||||
- **Implementation:** the machine never edits the document; it emits **pending**
|
||||
proposals (INV-5). The multi-diff editor is the review surface; Keep = Accept
|
||||
(apply + attribute changed words), Undo = Reject. Accept-all/reject-all carried
|
||||
from #46 (descending, orphan-skip + report). **Stable-API boundary:** the
|
||||
multi-diff editor is stable; per-change inline **Keep/Undo overlays** as Copilot
|
||||
Edits renders them lean on evolving chat-edit APIs — the **stable fallback** is
|
||||
per-hunk **CodeLens** Accept/Reject within the diff (§6.10, §13-Q2).
|
||||
|
||||
#### PUC-3 — annotated rendered preview
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor U as Writer
|
||||
participant P as Built-in MD preview
|
||||
participant E as Preview extension (extendMarkdownIt)
|
||||
participant T as renderAnnotations (pure)
|
||||
U->>P: Open Preview (annotations on)
|
||||
P->>E: render document tokens
|
||||
E->>T: transform(tokens, attributions, proposals)
|
||||
T-->>E: tokens w/ authorship + track-changes marks
|
||||
E-->>P: annotated HTML (preview stylesheet)
|
||||
P-->>U: native preview, annotated
|
||||
```
|
||||
|
||||
- **Implementation:** a contributed `markdown-it` plugin runs the pure
|
||||
`renderAnnotations` transform (carried/adapted from F7/F9/F10 render engines) and
|
||||
a small preview stylesheet using VS Code theme variables. Toggle via
|
||||
`cowriting.annotations`. No webview (replaces F7/F10). Authorship coloring +
|
||||
insert/delete marks; pinned-baseline-clean rule carried (#48): a freshly pinned,
|
||||
zero-diff document renders clean.
|
||||
|
||||
#### PUC-4 / PUC-6 — threads & re-anchoring
|
||||
|
||||
- **Implementation:** ThreadController + Anchorer, carried from F2/F8 unchanged.
|
||||
On load / external change (FileSystemWatcher), every anchor re-resolves
|
||||
(exact-unique → context-disambiguated → orphaned, INV-1). Proposals and
|
||||
attributions ride the same `anchors` primitive, so they re-anchor and orphan by
|
||||
the same ladder.
|
||||
|
||||
#### PUC-5 — live turn progress
|
||||
|
||||
- **Implementation:** carried from #60 verbatim — pure `turnProgress` reducer,
|
||||
`runEditTurn` `onProgress`/`AbortSignal`, `liveProgress` relay to a notification
|
||||
activity-line + token count + the "Cowriting: Claude" OutputChannel; Cancel →
|
||||
`agent.abort()`. `CLAUDE_CODE_AUTO_CONNECT_IDE=0` env (the #59 fix) carried.
|
||||
|
||||
### 6.6 Non-functional requirements & cross-cutting concerns
|
||||
|
||||
- **Security & privacy:** serverless; no secret bytes in sidecars or transcripts
|
||||
(§6.3-handbook). The machine coauthor runs locally; provenance records identity,
|
||||
not credentials. The #59 fix (no spurious macOS automation prompt) is carried via
|
||||
`CLAUDE_CODE_AUTO_CONNECT_IDE=0`.
|
||||
- **Performance & scale:** anchor resolution is O(document) text search per anchor
|
||||
on load/change — fine for human-scale documents; skip non-text/oversized files.
|
||||
Native diff/preview rendering is the platform's, not ours.
|
||||
- **Availability & resilience:** no service; the worst case is an orphaned anchor
|
||||
(handled, INV-1) or a missing baseline (degrade to "no diff yet").
|
||||
- **Observability:** the OutputChannel stream (PUC-5) is the user-facing turn log;
|
||||
no telemetry service (a local extension — §9).
|
||||
- **Accessibility:** inherited from native surfaces — the diff editor, multi-diff,
|
||||
Markdown preview, and Comments all carry VS Code's a11y. This is a primary
|
||||
*reason* for the native-first choice (the bespoke webviews did not).
|
||||
|
||||
### 6.7 Key decisions & alternatives considered
|
||||
|
||||
| Decision | Chosen | Alternatives considered | Why chosen |
|
||||
| --- | --- | --- | --- |
|
||||
| Diff surface | `QuickDiffProvider` + native diff editor against a `cowriting-baseline:` virtual doc | custom webview diff (F6); decoration-only inline diff (F12) | Native gutter + diff editor for free: theming, inline/side toggle, a11y, navigation; zero custom rendering (INV-3) |
|
||||
| Accept/reject surface | **Multi-diff editor with Keep/Undo** (operator-chosen), backed by the propose/accept model | SCM stage/unstage change-group; in-editor CodeLens Accept/Reject; bespoke webview ✓/✗ (F4/F10) | Closest to the modern "AI edits" review feel; reviews all changes in one native surface. Stable fallback: per-hunk CodeLens (§6.10) |
|
||||
| Rendered preview | **Extend the built-in Markdown preview** (`markdown-it` contribution) | sealed custom webview (F7/F10); both surfaces | Native scroll-sync, theming, refresh, and cooperation with other Markdown extensions; deletes the webview (INV-3) |
|
||||
| Baseline storage | out-of-repo global storage by URI hash (carried F6/INV-7) | commit baseline into repo; in-memory only | Never pollutes the repo; works for any file incl. untitled; disposable review state |
|
||||
| Persistence envelope | the F5 cross-rung sidecar contract, unchanged | new format; inner-loop-only sidecar | Round-trips to the Gitea substrate; forward-compatible; already proven (INV-4) |
|
||||
| Core/controller split | pure vscode-free cores + thin controllers (carried) | UI-coupled logic | The shipped plugin's highest-value discipline: unit-testable cores, swappable surfaces (INV-6) |
|
||||
| Scope | design-only north star (no repo/migration commitment) | commit a v2 repo + migration now | Keeps the architecture decision separate from the delivery decision (§2, §7.1) |
|
||||
|
||||
### 6.8 Testing strategy
|
||||
|
||||
- **Unit (vitest, vscode-free):** the pure cores carry their existing suites —
|
||||
attribution spans, anchoring (fingerprint/resolve/orphan/offset shift),
|
||||
`mergeArtifacts` (union-by-id, unknown-field preservation), diff engine
|
||||
(`wordEditHunks` / `diffToBlockHunks`), `turnProgress` reducer, and the new
|
||||
`renderAnnotations` markdown-it transform (token-in → annotated-token-out).
|
||||
- **Integration / E2E (`@vscode/test-electron`):** drive the controllers in the
|
||||
Extension Development Host — pin baseline → assert QuickDiff original; ask-to-edit
|
||||
→ assert pending proposals + multi-diff opened; Keep/Undo → assert document
|
||||
mutation only on Keep + attribution recorded; toggle annotations → assert preview
|
||||
HTML marks; thread create → re-anchor → orphan. Where the harness cannot drive a
|
||||
native surface's chrome directly (multi-diff Keep/Undo, Comments UI, preview DOM),
|
||||
fall back to asserting controller/provider state and the pure transform output —
|
||||
the F2/F6/F7 precedent. **No Playwright** — these are native surfaces, not a
|
||||
webview. E2E are first-class plan tasks (handbook §4 / §6.8).
|
||||
- **Named E2E scenarios this design must pass:** PUC-1 pin→diff; PUC-2
|
||||
propose→review→keep/undo→accept-all; PUC-3 annotate-toggle; PUC-4/6
|
||||
thread→reanchor→orphan; PUC-5 progress→cancel.
|
||||
|
||||
### 6.9 Failure modes, rollback & flags
|
||||
|
||||
- **Orphaned anchor** (INV-1) → shown orphaned at last-known `lineHint`, never moved
|
||||
→ auto-re-anchors if the text reappears → no alert (local).
|
||||
- **Missing baseline** → no QuickDiff original → degrade to "pin a baseline to see
|
||||
changes"; no diff shown, no error.
|
||||
- **Multi-diff Keep/Undo API unavailable/changed** → fall back to per-hunk CodeLens
|
||||
Accept/Reject in the diff editor (§6.10); the propose/accept *model* is unchanged.
|
||||
- **Feature flags / settings:** `cowriting.annotations` (preview annotations on/off),
|
||||
`cowriting.liveProgress.revealOutput` (carried #60). The whole capability is
|
||||
additive — off by absence of a pinned baseline / sidecar.
|
||||
|
||||
### 6.10 Migration & compatibility
|
||||
|
||||
**Design-only — nothing is migrated by this spec.** It defines the target
|
||||
architecture; the repo-and-migration decision is deferred (§2, §7.1, §13-Q1).
|
||||
|
||||
- **Data migration:** none committed here. The persistence envelope is the F5
|
||||
cross-rung contract **unchanged**, so existing `.threads/` sidecars are readable
|
||||
as-is by a native-first build — making an in-place re-platform low-risk *if*
|
||||
later chosen. The baseline (out-of-repo, disposable) needs no migration.
|
||||
- **Backwards compatibility:** the sidecar contract stays v1.x additive
|
||||
(unknown-field-preserving, INV-4); any current consumer keeps working.
|
||||
- **Cutover:** N/A (design-only). If delivered as a v2 re-platform, the natural
|
||||
order is surface-by-surface (diff → preview → accept/reject), each native surface
|
||||
replacing its bespoke predecessor behind the unchanged cores.
|
||||
- **Stable-API boundary (recorded risk):** the native diff editor, SCM/QuickDiff,
|
||||
multi-diff editor, Markdown-preview `markdown-it` contribution, Comments, and
|
||||
decorations are **stable**. The per-change inline **Keep/Undo** overlay as Copilot
|
||||
Edits renders it uses **evolving** chat-edit APIs; the design's stable contract is
|
||||
therefore "multi-diff review + per-hunk Accept/Reject CodeLens," with the
|
||||
Copilot-style inline overlay as a progressive enhancement where the API allows.
|
||||
|
||||
## 7. Delivery Plan
|
||||
|
||||
### 7.1 Approach / strategy
|
||||
|
||||
This is a **design-only north star**: it produces no implementation plan and ships
|
||||
no code. When the operator decides to act on it, the delivery decision (§13-Q1)
|
||||
picks one of:
|
||||
|
||||
- **New app, clean break** — a fresh repo + `app.json` (flotilla provisioning),
|
||||
the shipped plugin frozen; build native-first from the reused cores.
|
||||
- **v2 re-platform in place** — replace bespoke surfaces one at a time behind the
|
||||
unchanged pure cores (diff → preview → accept/reject), reading existing sidecars
|
||||
as-is (low-risk per §6.10).
|
||||
|
||||
Either way the build order follows the surface mapping: stand up the pure cores
|
||||
(mostly carried), then **the diff surface** (smallest, highest-confidence native
|
||||
win), then **the preview extension**, then **the multi-diff accept/reject**
|
||||
(largest API-boundary risk — do it last, with the CodeLens fallback ready). One
|
||||
SPEC → one plan → one execution applies per delivered Feature once decomposed.
|
||||
|
||||
### 7.2 Rollout / launch plan
|
||||
|
||||
A VS Code extension has **no §9 webapp deploy pipeline** (localhost/PPE/prod) — like
|
||||
the shipped plugin, "done" for a delivered Feature = acceptance met + unit and host
|
||||
E2E green; there is no marketplace publish in scope. Rollout, if/when productized,
|
||||
is a marketplace concern out of scope here.
|
||||
|
||||
### 7.3 Risks & mitigations
|
||||
|
||||
| Risk | Likelihood / impact | Mitigation |
|
||||
| --- | --- | --- |
|
||||
| Per-change Keep/Undo overlay relies on evolving chat-edit APIs | M / M | Stable contract = multi-diff + per-hunk CodeLens Accept/Reject; overlay is progressive enhancement (§6.10) |
|
||||
| Two SourceControls (Git + Cowriting) confuse the SCM viewlet | L / M | Multiple SCM providers coexist by design; name it clearly; QuickDiff alone (no full SCM) is the minimal fallback |
|
||||
| Built-in preview can't host interactive ✓/✗ inside the preview | M / L | Accept/reject lives in the multi-diff surface, not the preview; the preview is read/annotate only (a deliberate split) |
|
||||
| Native surfaces are harder to E2E than a queryable webview | M / L | Assert controller/provider state + pure-transform output (F2/F6/F7 precedent) |
|
||||
| Design-only spec stalls (never delivered) | M / L | §13-Q1 names the delivery decision and owner; the architecture stands regardless |
|
||||
|
||||
## 8. Success Metrics & Measurement
|
||||
|
||||
### 8.1 Business success metrics
|
||||
|
||||
| Outcome | Measured by (source) | Baseline captured how | Owner | Review cadence |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| BO-1 (familiarity) | Dogfooding walkthrough: complete diff→review→preview using only native surfaces | The shipped plugin's bespoke-panel flow as the before | Ben | At first native-first build |
|
||||
| BO-2 (cheaper to maintain) | Custom-rendering LOC + test-surface retired vs. capability retained | Current webview/decoration LOC count | Ben | At first native-first build |
|
||||
|
||||
### 8.2 Product success metrics
|
||||
|
||||
| # | Metric (scores PUC-n) | Target | Fed by | Review cadence |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| PM-1 | PUC-1 diff opens in the native diff editor with an accurate baseline⟷live | works for any file incl. untitled | host E2E | per build |
|
||||
| PM-2 | PUC-2 no document mutation until Keep; each change independently keep/undo-able | 100% (INV-5) | host E2E | per build |
|
||||
| PM-3 | PUC-3 annotations render in the built-in preview and toggle clean | on/off both correct | unit + host E2E | per build |
|
||||
|
||||
## 9. Telemetry, Observability & Monitoring
|
||||
|
||||
A local VS Code extension — **no telemetry service, no server monitoring.** The
|
||||
user-facing turn log is the "Cowriting: Claude" OutputChannel (PUC-5). Deliberately
|
||||
omitted: events pipeline, dashboards, alerts, SLOs (nothing is operated as a
|
||||
service). N/A — TEL/SLO/ALR rows are not applicable to a serverless local
|
||||
extension.
|
||||
|
||||
## 10. Operations
|
||||
|
||||
### 10.1 Operational plan
|
||||
|
||||
N/A — a local VS Code extension has no day-to-day operator. The "operator" is the
|
||||
developer running it. No on-call, no runbooks for a service. Routine maintenance is
|
||||
dependency patching (§10.3).
|
||||
|
||||
### 10.2 Support & incident response
|
||||
|
||||
Pre-v1; issues are filed on the plugin's Gitea tracker as today. One line: a bug
|
||||
reaches us as a tracker issue and is triaged in a session.
|
||||
|
||||
### 10.3 Maintenance & lifecycle
|
||||
|
||||
- **Dependency patching:** `@cline/sdk` and dev deps via the normal tracker/Patchwatch flow.
|
||||
- **Backup / restore:** N/A — sidecars are git-committed; the baseline is disposable.
|
||||
- **Capacity & cost:** local; the only cost is the machine coauthor's token usage,
|
||||
surfaced live (PUC-5).
|
||||
- **Deprecation / sunset:** if delivered as a new app, the shipped plugin is frozen
|
||||
(cutover §6.10); this design itself is superseded only by a later architecture spec.
|
||||
|
||||
## 11. Documentation plan
|
||||
|
||||
- **Where docs live:** spec + dev docs → framework repo; this Solution Design →
|
||||
content repo `specs/`; no public-facing site in scope.
|
||||
|
||||
| # | Document | Audience | Location | New / updated |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| DOC-1 | This Solution Design | dev/operator | content repo `specs/coauthoring-native-surfaces.md` | new |
|
||||
| DOC-2 | README "how the coauthoring loop maps to native surfaces" | dev/user | framework repo README | new (at delivery) |
|
||||
|
||||
## 12. Traceability matrix
|
||||
|
||||
| Pain | Business UC | Product UC | Tests | Measured by |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| PP-1, PP-3 | BUC-2 | PUC-2 | host E2E: propose→review→keep/undo→accept-all | PM-2 / BO-1 |
|
||||
| PP-1 | BUC-1 | PUC-1 | host E2E: pin→QuickDiff→native diff | PM-1 / BO-1 |
|
||||
| PP-1, PP-4 | BUC-3 | PUC-3 | unit (renderAnnotations) + host E2E: annotate toggle | PM-3 / BO-1 |
|
||||
| PP-2 | — | PUC-1/2/3 | retired custom-rendering LOC | BO-2 |
|
||||
| (orphaning) | BUC-3a | PUC-4/6 | unit (anchorer) + host E2E: reanchor→orphan | PM-1 |
|
||||
|
||||
## 13. Open Questions & Decisions log
|
||||
|
||||
**Open**
|
||||
|
||||
| # | Question | Owner | Blocks |
|
||||
| --- | --- | --- | --- |
|
||||
| Q1 | New app (clean break) vs. v2 re-platform in the current repo — the delivery decision | Ben | Any implementation plan |
|
||||
| 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 |
|
||||
|
||||
**Resolved**
|
||||
|
||||
| # | Decision | Resolution | Date |
|
||||
| --- | --- | --- | --- |
|
||||
| D1 | Scope / altitude | Design-only north star — architecture + surface mapping, no repo/migration commitment | 2026-06-27 |
|
||||
| D2 | Accept/reject primary surface | Multi-diff editor with Keep/Undo (CodeLens stable fallback) | 2026-06-27 |
|
||||
| D3 | Rendered preview surface | Extend the built-in Markdown preview via a `markdown-it` contribution (no webview) | 2026-06-27 |
|
||||
| D4 | Diff surface | `QuickDiffProvider` + native diff editor against a `cowriting-baseline:` virtual doc | 2026-06-27 |
|
||||
| D5 | Carry-forward from the shipped plugin | Pinned baseline (F6), authorship attribution (F3), cross-rung sidecar (F5), live progress (#60), region threads (F2), on-behalf-of identity, and the pure-core/thin-controller discipline | 2026-06-27 |
|
||||
| D6 | Design tooling | Code directly (rubric −6); no bespoke UI surface | 2026-06-27 |
|
||||
|
||||
## 14. Glossary & References
|
||||
|
||||
- **Pinned baseline** — the human-chosen "good" snapshot used as the diff *original*;
|
||||
stored out-of-repo, disposable (INV-7; from F6).
|
||||
- **QuickDiffProvider** — the VS Code API that supplies gutter dirty-diff bars from a
|
||||
virtual *original* document.
|
||||
- **Multi-diff editor** — VS Code's native multi-change review surface (the "AI edits"
|
||||
review feel); here the accept/reject surface (Keep/Undo).
|
||||
- **Cross-rung sidecar** — the F5 forward-compatible, unknown-field-preserving
|
||||
coauthoring artifact that round-trips between the inner loop and the Gitea
|
||||
substrate.
|
||||
- **Provenance** — the author envelope (human git identity, or agent on-behalf-of a
|
||||
human) reused across attributions, proposals, and threads (INV-8).
|
||||
- **Orphaned** — an anchor that could not be confidently re-resolved; shown, never
|
||||
silently moved (INV-1).
|
||||
- **Pure core / thin controller** — the vscode-free, unit-tested logic vs. the
|
||||
vscode-aware wiring split (INV-6).
|
||||
- **References:** shipped plugin Epic #1 (F1–F12); specs `coauthoring-inner-loop.md`,
|
||||
`coauthoring-attribution.md`, `coauthoring-propose-accept.md`,
|
||||
`coauthoring-diff-view.md`, `coauthoring-rendered-preview.md`,
|
||||
`coauthoring-cross-rung-format.md`, `coauthoring-live-progress.md`. `@cline/sdk`
|
||||
(loaded via runtime dynamic `import()`). VS Code APIs: SCM/`QuickDiffProvider`,
|
||||
diff editor (`vscode.diff`), multi-diff editor, Markdown preview
|
||||
`markdown-it` contribution, Comments, `TextDocumentContentProvider`, decorations.
|
||||
Reference in New Issue
Block a user