Commit Graph

323 Commits

Author SHA1 Message Date
Ben Stull 1564ef562b feat(f11): SLICE-5 — gateway, non-authorable disabling, docs (#43)
Closes the F11 feature: makes the toolbar surface reachable end to end and
guards the edit controls. Per spec §6.4/§6.5/§7.2 SLICE-5.

- package.json: cowriting.showTrackChangesPreview added to editor/title
  (when: editorLangId == markdown) — the minimal right-click → Open Review
  Preview gateway (#41/#42 expand it later).
- trackChangesPreview: the gateway command accepts the tab's resource Uri
  (palette/keybinding still fall back to the active editor); refresh() sends an
  `authorable` flag on both render messages; `editControlsEnabled` test seam.
- webview: disable Pin + Ask-Claude on a non-authorable doc (Annotations stays
  active — reading is always allowed); RenderMessage.authorable.
- host E2E: the editor/title gateway opens the preview + is markdown-guarded;
  edit controls disabled on a non-authorable (read-only-scheme) markdown doc.
- docs: docs/MANUAL-SMOKE-F11.md (live smoke, 10 steps) + README F11 section +
  intro line.

205 unit + 53 host E2E green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:57:28 -07:00
Ben Stull 03b61ed43e feat(f11): SLICE-4 — single adaptive Ask-Claude button + selection mapping (#43, INV-37)
The one Ask-Claude toolbar button now adapts: its label flips on selectionchange
(Edit Selection when live text is selected in the preview, Edit Document
otherwise), and a click resolves the preview selection to a SOURCE range via the
nearest data-src ancestors (INV-36) — the webview's sole mapping duty. A
selection touching no live-source block falls back to document scope. Per spec
§6.5 PUC-2/3 / §7.2 SLICE-4.

- webview (media/preview.ts): nearestSrc() DOM walk + selectionSrcRange()
  block-union; updateAskLabel() on selectionchange + after each render; the
  adaptive click posts { askClaude, scope:"selection", start, end } or falls back
  to document scope. Sealed (INV-21): reads data-src only, posts intent.
- host: runEditAndPropose's range branch (already shared from SLICE-3) records one
  single-range F4 proposal over the resolved block-union.
- host E2E: stubbed selection turn → exactly one proposal over the resolved range
  (turn receives exactly the selected source; replaced == the range; doc
  untouched); an unchanged replacement proposes nothing. (The webview DOM
  selection→data-src lookup is sealed-sandbox → manual smoke, spec §6.8.)

205 unit + 51 host E2E green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:53:14 -07:00
Ben Stull 0d1a5635cb feat(f11): SLICE-3 — Edit Document button + per-hunk proposal path (#43, INV-37)
A whole-document Ask-Claude rewrite is diffed into hunks and surfaced as N
independent F4 proposals (one per changed hunk) — reusing the F4 single-range
model N times, no new model. Per spec §6.4/§7.2 SLICE-3.

- trackChangesModel: pure `diffToHunks(currentText, rewrittenText)` →
  EditHunk[] (vscode-free, deterministic; diffWordsWithSpace, coalescing
  adjacent add/remove runs; offsets index currentText).
- trackChangesPreview: `runEditAndPropose(document, target, instruction)` — the
  shared host routine (selection → one single-range propose; document → diff →
  one propose per hunk; never mutates the doc, INV-10); `askClaude` UI wrapper
  (host showInputBox keeps LLM/secrets out of the sealed webview, INV-8/35);
  injectable `editTurn` + `setEditTurnForTest` seam (no LLM in CI); the
  `askClaude` inbound message branch; `cowriting.editDocument` command for #42
  reuse.
- package.json: register cowriting.editDocument, palette-guarded on markdown.
- webview: ✦ Ask Claude to Edit Document button → { askClaude, scope:"document" }.
- unit: diffToHunks fixtures (zero/one/multi-hunk, wholesale, determinism).
- host E2E: stubbed multi-hunk rewrite → N matching proposals, doc untouched;
  editDocument command registered + markdown-guarded.

205 unit + 49 host E2E green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:51:07 -07:00
Ben Stull 1ef9451e89 feat(f11): SLICE-2 — block-level data-src emission (#43, INV-36)
The pure render layer now emits data-src-start/data-src-end (source char offsets
from BlockWithRange) on every LIVE-source rendered block, in BOTH modes — the
contract the webview's selection→source mapping (SLICE-4) walks the DOM for.
Per spec §6.1 INV-36 / §7.2 SLICE-2.

- trackChangesModel: shared `srcAttr(blk)` helper; threaded through renderOp +
  renderReviewOp + the renderReview loop (removed blocks → "" / no data-src, as
  they have no live source). renderPlain switches from a single whole-document
  markdown pass to per-block `<div data-src-start/end>` wrappers — bare divs (no
  cw- class) so the off/clean preview stays visually clean while becoming a
  selection→source surface. Pure, vscode-free, deterministic (extends INV-22).
- unit (test/trackChangesModel.test.ts): data-src offsets equal
  splitBlocksWithRanges in both modes; removed + proposal blocks carry none;
  off-mode stays cw--free; determinism.

200 unit + 47 host E2E green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:45:02 -07:00
Ben Stull 8b9e61a1da feat(f11): SLICE-1 — Pin baseline toolbar button + reachability (#43)
Homes the orphaned cowriting.pinDiffBaseline command and gives the writer a
reachable Pin control in the preview toolbar. Per spec §7.2 SLICE-1
(docs/superpowers/specs/2026-06-12-f11-preview-toolbar-interaction-surface.md).

- trackChangesPreview: extract onDidReceiveMessage into handleWebviewMessage;
  add the F11 `pinBaseline` intent → DiffViewController.pin(previewedDoc) (the
  bound doc, not activeTextEditor — §6.7); ToolbarMsg union; receiveMessage test
  seam exercising the real message→seam wiring (INV-35).
- webview: ⌖ Pin baseline button in #cw-header posting { type: "pinBaseline" };
  theme-aware toolbar-button CSS (light/dark/high-contrast, disabled state).
- package.json: unhide pinDiffBaseline — commandPalette `when` false →
  editorLangId == markdown (resolves the #34 orphan from the command side).
- host E2E (test/e2e/suite/f11Toolbar.test.ts): pinBaseline message clears the
  change-marks + advances the baseline to `pinned`; palette `when` is reachable.

Also archives the F11 implementation plan to docs/superpowers/plans/.

197 unit + 47 host E2E green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:40:21 -07:00
Ben Stull 5966907089 claim vscode-cowriting-plugin session 0037 (placeholder) + sessions.json entry 2026-06-12 13:33:47 -07:00
Ben Stull 2e3179eaec add sessions/0036/SESSION-0036.0-TRANSCRIPT-2026-06-12T11-01--2026-06-12T12-18.md + replace placeholder/variant SESSION-0036.0-TRANSCRIPT-2026-06-12T11-01--INPROGRESS.md 2026-06-12 12:18:51 -07:00
Ben Stull b2de25ff99 design(f11): preview toolbar as the primary interaction surface
Solution Design for Feature #43 (F11): the F10 review preview's header
gains a Pin baseline button and a single adaptive Ask Claude button
(Edit Selection / Edit Document) beside the existing annotations
checkbox, plus a minimal right-click gateway that opens the preview.

Three forks locked in brainstorming session 0036:
- block-level preview-selection -> source mapping (data-src on blocks
  from BlockWithRange; union of intersected live-source blocks)
- document edit diffed into per-hunk F4 proposals (no model change)
- #43 lands a minimal editor/title -> Open Review Preview gateway
  (#41/#42 expand the menus)

Reuses F4 propose/F3 attribution/F6 baseline seams; sealed webview
posts intent only (INV-35/36/37). Resolves the orphaned pinDiffBaseline
reachability gap. Submitted to the content repo at finalize.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 12:15:44 -07:00
Ben Stull f2b6f369f5 claim vscode-cowriting-plugin session 0036 (placeholder) + sessions.json entry 2026-06-12 11:01:57 -07:00
Ben Stull ac191556a6 add sessions/0035/SESSION-0035.0-TRANSCRIPT-2026-06-12T08-53--2026-06-12T10-58.md + replace placeholder/variant SESSION-0035.0-TRANSCRIPT-2026-06-12T08-53--INPROGRESS.md 2026-06-12 10:58:54 -07:00
Ben Stull 10ad1a6992 claim vscode-cowriting-plugin session 0035 (placeholder) + sessions.json entry 2026-06-12 08:53:43 -07:00
Ben Stull 440d8ff4c9 add sessions/0034/SESSION-0034.0-TRANSCRIPT-2026-06-12T03-28--2026-06-12T03-39.md + replace placeholder/variant SESSION-0034.0-TRANSCRIPT-2026-06-12T03-28--INPROGRESS.md 2026-06-12 03:39:50 -07:00
benstull 3c8b3597dd Merge pull request 'fix #38: undo/redo no longer mis-attributes restored text in the review preview' (#39) from bug/38-undo-wrong-marks-in-preview into main 2026-06-12 10:37:48 +00:00
Ben Stull 469c8c11fc fix #38: don't mis-attribute undo/redo as fresh human authorship in the preview
Undo in the editor rendered wrong marks in the F10 review preview: restored
baseline text (and reverted Claude text) was colored as human-authored. Root
cause — attributionController.onDidChange attributed every non-seam document
change to currentAuthor() (always human) and ignored e.reason, so an undo/redo
that re-inserts text created a fresh human span over it. renderReview is pure;
the wrong marks came from these false author spans.

Fix: on e.reason === Undo|Redo, reconcile span geometry but do NOT attribute the
re-inserted chars — an undo is history navigation, not authorship, so restored
text stays neutral (unattributed) rather than falsely claimed by the human.
applyChange gains an `attributeInserted` flag (default true; false on undo/redo);
seam matching is also skipped on undo/redo (the seam only applies forward edits).

Restored text becomes neutral rather than recovering its exact prior provenance
(e.g. undoing a deletion of Claude's text shows it unattributed, not blue) —
perfect restoration would need an attribution history stack synced to the editor
undo stack (fragile due to edit coalescing); filed mentally as a follow-up. The
neutral behavior removes the misleading marks, which is the reported defect.

Tests: E2E reproduces the mid-edit-undo case (buffer stays dirty so the disk-sync
guard doesn't mask it) and asserts restored text is unattributed; +3 unit tests
for the geometric-only applyChange path. 197 unit + 50 E2E green; typecheck clean.

Closes #38

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 03:37:22 -07:00
Ben Stull 21e889b0a3 claim vscode-cowriting-plugin session 0034 (placeholder) + sessions.json entry 2026-06-12 03:28:36 -07:00
Ben Stull 7e15c887f3 add sessions/0033/SESSION-0033.0-TRANSCRIPT-2026-06-12T03-14--2026-06-12T03-27.md + replace placeholder/variant SESSION-0033.0-TRANSCRIPT-2026-06-12T03-14--INPROGRESS.md 2026-06-12 03:28:06 -07:00
Ben Stull 0ada9ed9da claim vscode-cowriting-plugin session 0033 (placeholder) + sessions.json entry 2026-06-12 03:14:58 -07:00
Ben Stull d70fa91e59 add sessions/0032/SESSION-0032.0-TRANSCRIPT-2026-06-12T01-20--2026-06-12T03-05.md + replace placeholder/variant SESSION-0032.0-TRANSCRIPT-2026-06-12T01-20--INPROGRESS.md 2026-06-12 03:05:57 -07:00
benstull 1a52ac6cb4 Merge pull request 'F6 #34: delete the dead two-pane diff-view UI, keep the baseline data layer' (#37) from task/34-delete-f6-dead-view-code into main 2026-06-12 09:10:37 +00:00
Ben Stull 3520397e41 F6 #34: delete the dead two-pane diff-view UI, keep the baseline data layer
F10 (#29) made the rendered preview the single review surface and hid the F6
two-pane vscode.diff view (command + ctrl+alt+d set when:false). This removes
that now-unreachable view code:

- DiffViewController: drop toggle/findDiffTab/epochLabel/isDiffOpen, the
  `cowriting-baseline:` TextDocumentContentProvider + BASELINE_SCHEME + baselineUri
  + the content-provider change emitter, and the toggleDiffView command. The
  baseline DATA layer is fully intact — ensureBaseline/advance/pin/capture,
  getBaseline, baselineFilePath, onDidChangeBaseline, persistence (INV-19), and
  the machine-landing auto-advance (INV-18) that F7/F10 consume.
- package.json: remove the toggleDiffView command, its commandPalette entry, and
  the ctrl+alt+d keybinding.
- E2E: diffView suite keeps the baseline-data-layer tests, drops the two-pane
  view tests; the F10 + no-workspace suites assert toggleDiffView is now absent
  (was: declared-but-hidden).

Deliberate deviation from the issue's literal acceptance: pinDiffBaseline is
KEPT. The canonical Solution Design (coauthoring-interactive-review.md §6.7)
scopes the removal to the two-pane VIEW only ("keep the controller + baseline
store"); pin() lives in the baseline lifecycle (§6.4), never touches vscode.diff,
and is exercised by live F7 baseline-reset tests. Where the P3 capture draft and
the approved spec conflict, the spec wins (documentation-leads-automation).

194 unit + 49 E2E green; typecheck + build clean. No F7/F10 behavior change.

Closes #34

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 02:10:14 -07:00
benstull fd263ec674 Merge pull request 'F10 #31: render resolved proposals inline at their anchor block' (#36) from feature/31-inline-anchor-proposals into main 2026-06-12 08:33:00 +00:00
Ben Stull 34fa31311c F10 #31: render resolved proposals inline at their anchor block
In the F10 review preview, renderReview now emits each pending proposal whose
anchor resolves as a cw-proposal block immediately after the current-side block
its anchorStart falls in — answering "what is Claude proposing, and where?" by
position — instead of appending all proposals as trailing blocks. Proposals in
the same block are ordered by anchorStart then id (deterministic, INV-33); a
proposal whose anchor doesn't resolve (or precedes all blocks) still trails as a
cw-proposal-unanchored block, never dropped (INV-34).

This implements the inline-at-anchor placement the graduated F10 Solution Design
already specified (coauthoring-interactive-review.md §2/§6.2); the trailing-block
behavior shipped in #29 was a recorded v1 deferral.

Unit: mid-document placement, two proposals in distinct blocks, same-block
ordering determinism, anchored-before-trailing, mixed-set determinism.
E2E: the F10 propose test now asserts the proposal renders before the following
block (in place); accept still lands + clears.

194 unit + 51 E2E green; typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 01:31:52 -07:00
Ben Stull abd0404b9a claim vscode-cowriting-plugin session 0032 (placeholder) + sessions.json entry 2026-06-12 01:20:53 -07:00
Ben Stull 5577386738 add sessions/0031/SESSION-0031.0-TRANSCRIPT-2026-06-12T01-06--2026-06-12T01-10.md + replace placeholder/variant SESSION-0031.0-TRANSCRIPT-2026-06-12T01-06--INPROGRESS.md 2026-06-12 01:11:09 -07:00
Ben Stull 2754bca1fa claim vscode-cowriting-plugin session 0031 (placeholder) + sessions.json entry 2026-06-12 01:06:02 -07:00
Ben Stull d2c7c07c6f add sessions/0030/SESSION-0030.0-TRANSCRIPT-2026-06-11T23-48--2026-06-12T00-42.md + replace placeholder/variant SESSION-0030.0-TRANSCRIPT-2026-06-11T23-48--INPROGRESS.md 2026-06-12 00:42:57 -07:00
benstull 4160890956 Merge pull request 'F10: interactive track-changes review in the markdown preview (#29)' (#30) from f10-interactive-review into main 2026-06-12 07:39:50 +00:00
Ben Stull 0f5bc1b4ce F10 SLICE-4: manual smoke checklist + README F10 section (#29)
Adds docs/MANUAL-SMOKE-F10.md (clean editor → edit → propose → ✓/✗ →
Annotations toggle → status-bar PUC-6 → theming → cleanliness) following the
F7/F9 smoke format. Adds the F10 "write left / review right" section to the
README feature list and notes F6's two-pane diff and F9's authorship view are
retained only as data layers, not separate user surfaces.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:32:46 -07:00
Ben Stull cdeb41ede4 F10 SLICE-4: host E2E for interactive review (open/toggle/propose→accept→reject/clean-editor/hidden-F6/status); update obsolete F9/toggle suites (#29)
Adds test/e2e/suite/f10Review.test.ts covering the F10 flow: open preview
(mode "on", fresh baseline all-unchanged), type → cw-by-human span, propose →
cw-proposal block with ✓/✗, accept → lands + baseline advances + block clears,
reject → vanishes + doc untouched, toggle off → renderPlain has no cw- marks,
status-bar PUC-6 (indicator with no panel, hidden once opened), and the
clean-editor INV-32 facts (retired toggleAttribution, F6 ctrl+alt+d hidden).

Rewrites the obsolete F9 authorship-mode test as an F10 review test
(cw-by-claude in the on-state render; getMode defaults to "on"). Updates
attribution.test.ts (drops the retired isVisible/toggleAttribution toggle,
asserts the toggle is gone) and noWorkspace.test.ts (toggleAttribution +
acceptProposal/rejectProposal are retired, preview-only — INV-32).

Honesty fix in the status-bar seam: hideStatus() clears statusItem.text so
statusText() reports undefined when the indicator is hidden (it previously
returned its stale last value after a panel opened).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:31:54 -07:00
Ben Stull 42d0ec155e F10 SLICE-3: rename preview panel title to 'Review' (#29)
Code-quality polish: the webview panel title read 'Track changes: <name>' but
F10 makes the preview the single review surface. Match the 'Open Review Preview'
command rename.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:24:18 -07:00
Ben Stull 604c558287 F10 SLICE-3: wire ProposalController into the review preview (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:20:00 -07:00
Ben Stull 28c5e9d334 F10 SLICE-3: webview on/off switch + ✓/✗ click→postMessage + proposal CSS (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:20:00 -07:00
Ben Stull f8b36c3452 F10 SLICE-3: preview on/off mode; take ProposalController; renderReview path + accept/reject routing (#29)
Includes the PUC-6 status-bar indicator (updateStatus + show/dispose hooks)
since the constructor subscription references it (one file, no intermediate
broken build).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:19:52 -07:00
Ben Stull fe45569218 F10 SLICE-3: ProposalController.listProposals + onDidChangeProposals + keyFor (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:17:26 -07:00
Ben Stull bda394ea4e F10 SLICE-3: remove superseded public renderAuthorship (salvaged into colorByAuthor) (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:16:57 -07:00
Ben Stull bcacbf062d F10 SLICE-2: fix renderReview author-coloring for duplicate blocks; tidy renderReviewOp + escape proposal id (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:13:54 -07:00
Ben Stull d59f22b22f F10 SLICE-2: add ProposalView + renderReview combined on-state render (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:09:45 -07:00
Ben Stull 0311ad89ba F10 SLICE-2: add renderPlain off-state (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:08:31 -07:00
Ben Stull ebe3d4bab5 F10 SLICE-2: extract colorByAuthor from renderAuthorship sentinels (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:08:10 -07:00
Ben Stull 831710ed0c F10 SLICE-1: retire dead attribution toggle (visible/toggle/isVisible + command)
Code-quality follow-up: with editor decorations gone (Task 1), the visibility
toggle was dead/misleading — nothing reads `visible`. Remove the field,
toggle()/isVisible(), the cowriting.toggleAttribution registration, and its
package.json command + palette declarations (spec §6.2 retires it). renderActive/
render stay — they refresh the orphan status bar on editor switch.
E2E toggle assertions (attribution.test.ts, noWorkspace.test.ts) are updated in SLICE-4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:06:29 -07:00
Ben Stull 5ce8817b15 F10 SLICE-1: hide F6 diff command/keybinding + attribution toggle; retitle preview to 'Open Review Preview' (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:00:21 -07:00
Ben Stull 743de78994 F10 SLICE-1: remove F4 in-editor proposal threads/decorations; bookkeeping via live/unresolved (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 23:59:50 -07:00
Ben Stull 923dcc09d9 F10 SLICE-1: strip F3 attribution editor decorations (keep spansFor) (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 23:58:21 -07:00
Ben Stull 050bb21b84 F10: implementation plan for interactive track-changes review (#29)
Plan for #29 (F10) from specs/coauthoring-interactive-review.md — clean editor +
preview as the single interactive review surface (annotations on/off; ✓/✗ on
pending F4 proposals). 4 slices, 14 tasks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 23:56:00 -07:00
Ben Stull 205355939e claim vscode-cowriting-plugin session 0030 (placeholder) + sessions.json entry 2026-06-11 23:48:29 -07:00
Ben Stull b6d2d8fce2 add sessions/0029/SESSION-0029.0-TRANSCRIPT-2026-06-11T21-32--2026-06-11T21-53.md + replace placeholder/variant SESSION-0029.0-TRANSCRIPT-2026-06-11T21-32--INPROGRESS.md 2026-06-11 21:54:37 -07:00
Ben Stull 6cacf6b072 claim vscode-cowriting-plugin session 0029 (placeholder) + sessions.json entry 2026-06-11 21:33:02 -07:00
Ben Stull 291761ebb4 add sessions/0028/SESSION-0028.0-TRANSCRIPT-2026-06-11T21-25--2026-06-11T21-31.md + replace placeholder/variant SESSION-0028.0-TRANSCRIPT-2026-06-11T21-25--INPROGRESS.md 2026-06-11 21:32:26 -07:00
Ben Stull cae38a8aa6 claim vscode-cowriting-plugin session 0028 (placeholder) + sessions.json entry 2026-06-11 21:25:13 -07:00
Ben Stull 1c38591a61 add sessions/0027/SESSION-0027.0-TRANSCRIPT-2026-06-11T16-16--2026-06-11T20-33.md + replace placeholder/variant SESSION-0027.0-TRANSCRIPT-2026-06-11T16-16--INPROGRESS.md 2026-06-11 20:34:41 -07:00