Interactive track-changes review in the markdown preview (clean editor + accept/reject) #29

Closed
opened 2026-06-12 04:30:17 +00:00 by benstull · 1 comment
Owner

Interactive track-changes review in the markdown preview (clean editor + accept/reject)

Summary

Make the rendered markdown preview the single review surface for coauthoring:
the editor stays a clean, zero-annotation writing pane on the left; the preview on
the right shows changes-since-baseline with an annotations on/off toggle, and
lets the human accept/reject the LLM's changes — and only the LLM's — right
inside the preview.

Problem / pain

Today the plugin's review signals are spread across several overlapping surfaces
that collide on the same text: F6's two-pane red/green diff (ctrl+alt+d),
F3's in-editor attribution decorations (the green human border / blue Claude
fill), and F7/F9's rendered preview. In practice the operator opened the F6 diff
and saw F3's blue attribution bleeding into it at the same time — "I don't
understand this." The two-pane raw diff is low-altitude for prose, the in-editor
decorations clutter the writing surface (the human authored most of the document,
so attribution paints everywhere), and there is no single, intuitive place to
answer "what changed, who changed it, and do I keep the LLM's edits?"

Who feels it

The human coauthor (the writer/engineer, PP-1) — the plugin's sole user —
while writing markdown alongside Claude and reviewing what changed.

Desired outcome / value

One clean mental model: write on the left, review on the right. The editor is
distraction-free (zero annotations). The preview, with annotations on, shows every
change since the baseline in one visual language and lets the human keep or revert
the LLM's edits without leaving that pane — so "what did the LLM change, and do I
want it?" is answered in place, in the rendered document, not in a raw diff or a
cluttered editor.

Acceptance — "done right"

  • The editor carries no coauthoring decorations — it is a plain markdown
    editing surface.
  • The preview has an annotations on/off toggle. Off = clean rendered markdown
    (parity with VS Code's built-in preview). On = the annotated view.
  • With annotations on, every change since the F6 baseline is painted in one
    language
    : green = human-authored, blue = LLM-authored, strikethrough =
    deleted
    (deletions reconstructed from the baseline).
  • ✓/✗ accept/reject controls appear on the LLM's (blue) changes only; the
    human's (green) changes carry no controls. ✓ keeps the change (it becomes
    ordinary text); ✗ reverts it in the underlying document. The controls live in
    the preview and drive the edit back into the document.
  • Accepting/rejecting from the preview updates the document and the preview
    consistently; the editor reflects the resulting text with no annotations.

Scope / non-goals

In scope: markdown documents only; the rendered preview as the single review
surface; the annotations on/off toggle; the unified per-author + strikethrough
annotation language; interactive accept/reject of LLM changes from inside the
preview.

Non-goals (firm):

  • Non-markdown review — explicitly dropped. This is a markdown cowriting
    product; code/config files get no review surface.
  • In-editor inline track-changes (annotating the editable editor itself) —
    considered and rejected in favor of the clean-editor / annotated-preview split.
  • Renaming the repo to vscode-markdown-cowriting-plugin — the markdown-only
    identity is affirmed, but the rename is a separate, deliberate gesture (Gitea
    repo, app.json, content repo, session-history paths), explicitly deferred.
  • No change to the sidecar persistence, the cross-rung contract, or
    SCHEMA_VERSION.

Assumptions · constraints · dependencies

  • Mostly assembly of shipped features, not net-new invention:
    • F6 baseline (#17/#19) — kept as the data layer ("what changed since
      when"); the baseline still auto-advances at every machine landing. F6's
      two-pane view is deprecated as a user surface.
    • F7 render/diff engine (#21) — the rendered preview + block/word diff +
      strikethrough deletions already exist.
    • F3 attribution (#6) — kept as the data layer (who authored each span);
      its in-editor decorations are removed.
    • F4 propose/accept (#12) — the accept/reject logic already exists; this
      moves the controls into the preview.
    • F9 authorship preview (#27) — its two preview modes collapse into the one
      annotations on/off toggle.
  • Constraint: the preview is a sealed webview (strict CSP, local assets, no
    network — F7 INV-21). Interactive controls post messages to the extension host,
    which applies/reverts edits; the webview never edits the document directly.
  • Constraint: deletions aren't in the live buffer — they are reconstructed by
    diffing the buffer against the F6 baseline (the baseline preserves the
    original), which is what the F7 engine already does.

Source / signal

Self-originated — capture session vscode-cowriting-plugin-0028 (2026-06-11),
following a brainstorm in session 0027's conversation that started from the
operator finding the F6 two-pane diff (ctrl+alt+d) with F3 attribution bleeding
in confusing. Builds on shipped specs coauthoring-rendered-preview.md (F7/F7.1,
F9), coauthoring-diff-view.md (F6), coauthoring-attribution.md (F3),
coauthoring-propose-accept.md (F4). Epic #1.

Priority (WSJF)

Provisional: Value high (resolves the core "the review UX is confusing"
operator pain and defines the product) · Time-criticality medium · Opportunity
medium ÷ Size mediumprovisional priority/P1. (Decision aid, not
auto-scored.)

Decomposition

Feature → slice checklist:

  • Clean editor — strip F3's in-editor decorations (keep F3 tracking as the
    data layer).
  • One annotation layer — collapse F9's two preview modes into a single
    annotations on/off toggle; unify the visual language (green = human,
    blue = LLM, strikethrough = deleted).
  • Interactive review — ✓/✗ accept/reject controls on the LLM's (blue)
    changes in the preview, posting to the host to apply (✓) / revert (✗) in the
    document; reuse F4's accept/reject logic.
  • Deprecate F6 as a view — remove/hide the two-pane diff command; keep the
    baseline as the data layer the preview reads.
  • Tests — unit (render/attribution/accept-reject seams) + host E2E + manual
    webview smoke.

If the interactive-webview slice proves large on its own, promote this Feature to
an Epic and split the slices into child Features.

Solution notes (optional — NOT a design)

Non-binding hints: the per-author hue + strikethrough is the F9/F7 language already;
the new build is making the preview webview interactive (✓/✗ → postMessage
host applies an edit via the F4 path). The clean-editor change is mostly deletion
(remove the F3 decoration calls). A full Solution Design should be written before
implementation (this captures the intent, not the design).

<!-- Set the type/* label: type/feature --> # Interactive track-changes review in the markdown preview (clean editor + accept/reject) ## Summary Make the **rendered markdown preview the single review surface** for coauthoring: the editor stays a clean, zero-annotation writing pane on the left; the preview on the right shows changes-since-baseline with an **annotations on/off** toggle, and lets the human **accept/reject the LLM's changes — and only the LLM's — right inside the preview.** ## Problem / pain Today the plugin's review signals are spread across several overlapping surfaces that **collide on the same text**: F6's two-pane red/green diff (`ctrl+alt+d`), F3's in-editor attribution decorations (the green human border / blue Claude fill), and F7/F9's rendered preview. In practice the operator opened the F6 diff and saw F3's blue attribution bleeding into it at the same time — "I don't understand this." The two-pane raw diff is low-altitude for prose, the in-editor decorations clutter the writing surface (the human authored most of the document, so attribution paints everywhere), and there is no single, intuitive place to answer "what changed, who changed it, and do I keep the LLM's edits?" ## Who feels it The **human coauthor** (the writer/engineer, PP-1) — the plugin's sole user — while writing markdown alongside Claude and reviewing what changed. ## Desired outcome / value One clean mental model: **write on the left, review on the right.** The editor is distraction-free (zero annotations). The preview, with annotations on, shows every change since the baseline in one visual language and lets the human keep or revert the LLM's edits without leaving that pane — so "what did the LLM change, and do I want it?" is answered in place, in the rendered document, not in a raw diff or a cluttered editor. ## Acceptance — "done right" - The **editor carries no coauthoring decorations** — it is a plain markdown editing surface. - The **preview has an annotations on/off toggle.** Off = clean rendered markdown (parity with VS Code's built-in preview). On = the annotated view. - With annotations **on**, every change since the F6 baseline is painted in **one language**: **green = human-authored, blue = LLM-authored, strikethrough = deleted** (deletions reconstructed from the baseline). - **✓/✗ accept/reject controls appear on the LLM's (blue) changes only**; the human's (green) changes carry no controls. ✓ keeps the change (it becomes ordinary text); ✗ reverts it in the underlying document. The controls live in the preview and drive the edit back into the document. - Accepting/rejecting from the preview updates the document and the preview consistently; the editor reflects the resulting text with no annotations. ## Scope / non-goals **In scope:** markdown documents only; the rendered preview as the single review surface; the annotations on/off toggle; the unified per-author + strikethrough annotation language; interactive accept/reject of LLM changes from inside the preview. **Non-goals (firm):** - **Non-markdown review** — explicitly dropped. This is a *markdown* cowriting product; code/config files get no review surface. - **In-editor inline track-changes** (annotating the editable editor itself) — considered and rejected in favor of the clean-editor / annotated-preview split. - **Renaming the repo** to `vscode-markdown-cowriting-plugin` — the markdown-only identity is affirmed, but the rename is a separate, deliberate gesture (Gitea repo, `app.json`, content repo, session-history paths), explicitly **deferred**. - No change to the sidecar persistence, the cross-rung contract, or `SCHEMA_VERSION`. ## Assumptions · constraints · dependencies - **Mostly assembly of shipped features**, not net-new invention: - **F6 baseline** (#17/#19) — kept as the **data layer** ("what changed since when"); the baseline still auto-advances at every machine landing. F6's two-pane *view* is deprecated as a user surface. - **F7 render/diff engine** (#21) — the rendered preview + block/word diff + strikethrough deletions already exist. - **F3 attribution** (#6) — kept as the **data layer** (who authored each span); its *in-editor decorations* are removed. - **F4 propose/accept** (#12) — the accept/reject *logic* already exists; this moves the controls into the preview. - **F9 authorship preview** (#27) — its two preview modes collapse into the one annotations on/off toggle. - **Constraint:** the preview is a sealed webview (strict CSP, local assets, no network — F7 INV-21). Interactive controls post messages to the extension host, which applies/reverts edits; the webview never edits the document directly. - **Constraint:** deletions aren't in the live buffer — they are reconstructed by diffing the buffer against the F6 baseline (the baseline preserves the original), which is what the F7 engine already does. ## Source / signal Self-originated — **capture session vscode-cowriting-plugin-0028** (2026-06-11), following a brainstorm in session 0027's conversation that started from the operator finding the F6 two-pane diff (`ctrl+alt+d`) with F3 attribution bleeding in confusing. Builds on shipped specs `coauthoring-rendered-preview.md` (F7/F7.1, F9), `coauthoring-diff-view.md` (F6), `coauthoring-attribution.md` (F3), `coauthoring-propose-accept.md` (F4). Epic `#1`. ## Priority (WSJF) Provisional: Value **high** (resolves the core "the review UX is confusing" operator pain and defines the product) · Time-criticality **medium** · Opportunity **medium** ÷ Size **medium** → **provisional priority/P1**. (Decision aid, not auto-scored.) ## Decomposition Feature → slice checklist: - [ ] **Clean editor** — strip F3's in-editor decorations (keep F3 tracking as the data layer). - [ ] **One annotation layer** — collapse F9's two preview modes into a single annotations **on/off** toggle; unify the visual language (green = human, blue = LLM, strikethrough = deleted). - [ ] **Interactive review** — ✓/✗ accept/reject controls on the LLM's (blue) changes in the preview, posting to the host to apply (✓) / revert (✗) in the document; reuse F4's accept/reject logic. - [ ] **Deprecate F6 as a view** — remove/hide the two-pane diff command; keep the baseline as the data layer the preview reads. - [ ] **Tests** — unit (render/attribution/accept-reject seams) + host E2E + manual webview smoke. *If the interactive-webview slice proves large on its own, promote this Feature to an Epic and split the slices into child Features.* ## Solution notes (optional — NOT a design) Non-binding hints: the per-author hue + strikethrough is the F9/F7 language already; the new build is making the preview webview interactive (✓/✗ → `postMessage` → host applies an edit via the F4 path). The clean-editor change is mostly deletion (remove the F3 decoration calls). A full Solution Design should be written before implementation (this captures the intent, not the design).
benstull added the type/featurepriority/P1 labels 2026-06-12 04:30:17 +00:00
Author
Owner

F10 shipped to main via PR #30 (session 0030). Clean zero-annotation editor + the rendered preview as the single interactive review surface: annotations on/off toggle, green=human / blue=Claude / struck=deleted, and ✓/✗ accept-reject of pending F4 proposals routed through the F4 seam. INV-32/33/34; reverses F9 INV-26. 189 unit + 51 host E2E green. Deferred: inline-at-anchor proposal placement (rendered as trailing blocks in v1).

F10 shipped to `main` via PR #30 (session 0030). Clean zero-annotation editor + the rendered preview as the single interactive review surface: annotations on/off toggle, green=human / blue=Claude / struck=deleted, and ✓/✗ accept-reject of pending F4 proposals routed through the F4 seam. INV-32/33/34; reverses F9 INV-26. 189 unit + 51 host E2E green. Deferred: inline-at-anchor proposal placement (rendered as trailing blocks in v1).
Sign in to join this conversation.