Block-granularity proposals: one change per paragraph/header/bullet, not per word #47
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
When Claude edits a document, each suggested change is one proposal per changed
block — a whole paragraph, header, or bullet — rather than one proposal per
changed word. A reviewer sees a handful of block-sized decisions, not a
scatter of word-level ones.
Problem / pain
F11's Ask Claude to Edit Document diffs a whole-document rewrite into
proposals at word granularity:
diffToHunks(src/trackChangesModel.ts) runsdiffWordsWithSpaceand flushes a hunk on every unchanged token, so each changedword (or short run) becomes its own independent ✓/✗ proposal (INV-37, "per-hunk").
A single paragraph where Claude changed three words scattered across it surfaces
as three separate proposals; a light copy-edit pass over a document explodes
into dozens of tiny blue blocks. It's too much to review — the reviewer is
forced to adjudicate word-fragments out of the context of the sentence they live
in, instead of deciding "do I want Claude's version of this paragraph?"
Who feels it
Writers reviewing Claude's document-level edits — anyone using Ask Claude to
Edit Document, where one rewrite currently fans out into many word-level
proposals. The finer the edit, the worse the review tax.
Desired outcome / value
A reviewer adjudicates Claude's changes at the unit they actually think in —
the paragraph / header / bullet — so a document edit produces a small number of
meaningful, in-context decisions instead of a flood of word-fragment ones. Makes
the document-edit flow genuinely reviewable, and pairs with bulk-accept (#46) to
make "take Claude's pass" tractable.
Acceptance — "done right"
block is a paragraph, header, or bullet / list item (the unit the existing block
splitter already recognizes).
Claude's whole version of that block — accepting it replaces the block, not just
the changed words inside it.
surface).
for the whole fence, never word-refined or split (consistent with INV-23 in the
preview renderer).
proposal, anchored so it can be accepted (no un-resolvable zero-width proposal).
unchanged (the accepted block lands Claude-attributed, baseline advances,
proposal clears); this changes only how the rewrite is cut into proposals,
not the accept mechanism.
<ins>/<del>rendering within a block isunaffected — the reviewer still sees exactly what changed inside the block;
only the proposal/decision unit becomes the block.
M proposals (one per changed block), each spanning its block; an unchanged
block yields none; a changed fenced block stays one atomic proposal.
Scope / non-goals
hunks to block-level (the
diffToHunksfan-out path, F11/#42); reusing theexisting block model; preserving the F4 accept seam and the intra-block
<ins>/<del>rendering.single proposal (no fan-out to coarsen); no change to the inline diff
rendering granularity (words still shown inside the block); no new accept
mechanism; no "accept all" (that's #46); no configurable/toggleable granularity
(block is the chosen unit, not a setting) unless the design surfaces a need.
Assumptions · constraints · dependencies
decision with per-block for document edits — the spec/invariant is updated as
part of this work.
diffBlocks,paragraph/header/bullet, code & mermaid fences atomic) — block-level hunking
should reuse that block model rather than invent a second notion of "block".
whole block, so accepting it attributes the entire block to Claude via the
seam — including words that didn't change. The design step decides whether that
is acceptable (simplest, matches "Claude's version of this block") or whether
unchanged spans within an accepted block should retain prior attribution.
whole lists; tables; blockquotes; nested blocks); how adjacent
changed+inserted blocks group; anchoring of inserted/blank-bordered blocks
(the current
anchorInsertiontrick is word-oriented — block insertions need anequivalent); whether very large blocks warrant any fallback.
(#43, INV-37) document edit → per-hunk proposals (the behavior this changes),
#42 (Ask Claude to Edit Document — the N-proposal source), #46 (accept-all —
complementary: fewer proposals and one-gesture accept).
Source / signal
Self-originated — capture session vscode-cowriting-plugin-0040 (operator ask:
"When Claude suggests changes, a single change should be for a paragraph (or
header, or bulletpoint), not individual words. It's too much to review").
Priority (WSJF)
Value (high — makes Claude's document edits actually reviewable; directly removes a
"too much to review" pain) · Time-criticality (low–med) · Opportunity-enablement
(med — unlocks the document-edit flow alongside #42/#46) ÷ Size (med — reuses the
block model, but block hunking + insertion anchoring + the attribution decision
are real work) → favorable score.
priority/P1.Decomposition
diffToBlockHunks(or reworkeddiffToHunks) that emits one hunk spanning each changed block, reusing the existing block splitter; code/mermaid fences atomic.anchorInsertion).runEditAndProposedocument scope) to mint per-block proposals via the F4 seam; selection path untouched.Solution notes (optional — NOT a design)
The likely shape is a block-aware replacement for
diffToHunks: split bothbaseline-vs-rewrite into the existing block units, and for each block that differs
emit a single hunk covering the whole block (its source range → Claude's block
text), keeping fenced blocks atomic. Intra-block
<ins>/<del>rendering stays asit is — only the proposal cut changes. Inserted blocks need a block-level anchoring
analogue to today's word-oriented
anchorInsertion. The accept seam and thepreview are otherwise untouched. Non-binding — the design step settles the block
taxonomy, insertion anchoring, and the attribution semantics.
Shipped as SLICE-2 of the document-edit flow (#50, session 0044). Document edits now propose one F4 proposal per changed block (INV-39 supersedes INV-37); accepting a block attributes only the words Claude changed, unchanged spans keep prior authorship (INV-40); inserted blocks anchor + accept (INV-41); fences atomic (INV-23). 214 unit + 69/5 host E2E green.