Commit Graph

75 Commits

Author SHA1 Message Date
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 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 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 3b45e784c1 test(f7.1): host E2E — changed flowchart augments emitted source (#22)
Adds a renderHtmlFor test seam to TrackChangesPreviewController.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:34:42 -07:00
Ben Stull 6702490497 feat(f7.1): render augmented mermaid diff in changed-block branch (#22)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:33:12 -07:00
Ben Stull e938572ebc feat(f7.1): sequence participant/message diff + rect emission (#22)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:32:08 -07:00
Ben Stull 96931f245d feat(f7.1): sequence-diagram parser (#22)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:31:44 -07:00
Ben Stull 1454c7792a feat(f7.1): flowchart node/edge diff + styling emission (#22)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:31:09 -07:00
Ben Stull 78352c2922 feat(f7.1): flowchart parser (#22)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:30:32 -07:00
Ben Stull d8ce4f12e1 feat(f7.1): mermaid diff dispatcher + type detection (#22)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:29:36 -07:00
Ben Stull e0118bb835 feat(f9): webview segmented mode toggle + authorship legend + author CSS
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 14:38:50 -07:00
Ben Stull 399e3c5f70 feat(f9): preview gains authorship mode + attribution dep + setMode wiring
Per-panel mode (default changes); refresh branches to renderAuthorship reading
AttributionController.spansFor; webview setMode message; extension.ts reorders the
F7 controller after attribution. getMode/setMode test seams.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 14:38:05 -07:00
Ben Stull a84d72e69b feat(f9): AttributionController.spansFor — authorship spans for the preview
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 14:36:36 -07:00
Ben Stull 95eaf78891 feat(f9): renderAuthorship — inline author spans + atomic fence badges (INV-26/27/28)
PUA sentinel injection through markdown-it; adjacent-span ordering handled;
code/mermaid fences atomic with a block-level author badge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 14:36:19 -07:00
Ben Stull 82d7c52983 feat(f9): splitBlocksWithRanges — block offsets aligned to the source
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 14:34:40 -07:00
Ben Stull 7892e2fe87 feat(f8): wire SidecarRouter; authoring commands live folder-less (#19 precedent)
Spec §6.4: construct GlobalSidecarStore + SidecarRouter (CoauthorStore when root);
remove the no-root early-return + command stubs so F2/F3/F4 are real folder-less;
renderIfOpen gated by isAuthorable; editor-context menus widened to untitled;
export sidecarRouter on CowritingApi. activate now always returns the API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:13:26 -07:00
Ben Stull 7387366e28 refactor(f8): controllers depend on SidecarRouter + isAuthorable (key via keyOf)
Spec §6.4: constructor store CoauthorStore→SidecarRouter, rootDir→string|undefined;
isInRoot/isTracked gate → isAuthorable(scheme); per-doc key via store.keyOf(docIdentity).
Seam + artifact logic unchanged. currentAuthor omits git email when no root (fail-open).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:11:39 -07:00
Ben Stull 94aaff71e9 refactor(f8): VersionGuard depends on SidecarStore not CoauthorStore
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:08:27 -07:00
Ben Stull dca12f4f50 feat(f8): SidecarRouter — keyOf + per-document routing (spec §6.2)
Routes by #24's isUnderRoot: in-workspace file: → CoauthorStore (repo-relative key,
.threads/), out-of-folder file: + untitled: → GlobalSidecarStore (URI-string key).
keyOf is the single document identity. vscode-free; CoauthorStore conforms
structurally (unmodified, INV-2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:08:01 -07:00
Ben Stull bc77cee0bd feat(f8): isAuthorable + widened selectionRejection (file|untitled)
Spec §6.4: replace the scheme!=file / !isUnderRoot rejections with a single
!isAuthorable branch. isUnderRoot retained as a routing input. Per-condition
messaging (#24) kept for no-editor / empty-selection / non-{file,untitled}.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:06:58 -07:00
Ben Stull 515acb4868 feat(f8): SidecarStore interface + GlobalSidecarStore (sha256 key, untitled in-memory)
Spec §6.2/§6.4: out-of-workspace file: → <globalStorage>/sidecars/<sha256(uri)>.json
(INV-19/24); untitled: → in-memory only (F6 degrade). update() carries the INV-16
newer-major throw + anchor prune; consumeSelfWrite is a no-op (outside the .threads
watcher). Mirrors src/baselineStore.ts; vscode-free, unit-tested.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 13:06:08 -07:00
Ben Stull 0bdee1c286 fix(edit-selection): accurate per-condition warnings + path-boundary workspace check
cowriting.editSelection collapsed four distinct failures (no editor / no
selection / unsaved / outside the workspace folder) into one misleading
"select some text in a workspace document first" warning — so editing a
selection in a file OUTSIDE the EDH workspace root (e.g. a content-repo file
while the EDH opens sandbox/) was rejected as if no text were selected.

- New pure, vscode-free src/workspacePath.ts: isUnderRoot() (separator-bounded
  membership, fixing a latent startsWith() prefix collision where a sibling
  whose name prefixes the root — e.g. vscode-cowriting-plugin-content vs
  vscode-cowriting-plugin — falsely matched) + selectionRejection() (one
  message per condition). Unit-tested (8 cases), incl. the reported bug.
- Wire isUnderRoot into all five membership checks: extension.ts (editSelection
  guard + renderIfOpen) and the thread/attribution/proposal controllers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 12:12:18 -07:00
Ben Stull 1ab3cc5348 feat(f7): register showTrackChangesPreview command + keybinding, wire controller (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:46:49 -07:00
Ben Stull 8bf4b17e4a feat(f7): TrackChangesPreviewController (sealed webview, test seam) (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:46:17 -07:00
Ben Stull 81a8370c41 feat(f7): additive onDidChangeBaseline event on DiffViewController (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:45:46 -07:00
Ben Stull 6c3b137ebb feat(f7): per-block error-chip fallback (PUC-6, #21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:44:13 -07:00
Ben Stull 3b0ec4f53e feat(f7): render annotated track-changes HTML (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:43:38 -07:00
Ben Stull 6ffbf67871 feat(f7): block-level diff with atomic fences (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:42:51 -07:00
Ben Stull 247a450e10 feat(f7): block splitter for the render engine (#21)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 08:42:11 -07:00
Ben Stull e617f504e7 feat(f6): diff-view toggle on any file — global storage, untitled in-memory (#19)
F6 no longer requires a workspace file. It gets its own diffable predicate
(any file: or untitled:) decoupled from F2 isTracked, keys baselines by a
sha256 of the document URI, and stores them in VS Code GLOBAL storage
(context.globalStorageUri) — always present, never the repo (INV-19). Untitled
buffers have no durable identity → in-memory baseline only (lost on reload).

DiffViewController is now constructed before the workspace-root check and its
commands are always live (never stubbed) — the machine-landing advance wiring
stays in the with-root branch since the seam only fires on workspace files.
BaselineStore generalized to key-by-hash (Baseline.docPath → uri).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 07:47:05 -07:00
Ben Stull 17976809bf feat(f6): wire DiffViewController into activation (SLICE-3)
F6 §6.2. BaselineStore from context.storageUri (in-memory fallback), advance
subscribed to the seam's onDidApplyAgentEdit, ensureBaseline on first sight in
renderIfOpen, diffViewController on the CowritingApi, commands stubbed in the
no-folder path (#8 precedent).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 07:15:53 -07:00
Ben Stull 64e993992d feat(f6): toggle UX — vscode.diff open/close via tab groups (SLICE-3)
F6 §6.5 PUC-1. Detects the baseline diff tab (original scheme cowriting-baseline,
modified == the doc) to close-and-reveal; else opens vscode.diff with an epoch
title. Live document on the right — editor state preserved by construction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 07:15:04 -07:00
Ben Stull 4f2fc6fa96 feat(f6): DiffViewController — baseline lifecycle + content provider (SLICE-2)
F6 §6.2/§6.4, INV-18/INV-19. ensure/advance/pin capture buffer text, persist
via BaselineStore, refresh the open diff via onDidChange. Storage-unavailable
degrades to in-memory + one warning. toggle UX lands in SLICE-3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 07:13:30 -07:00
Ben Stull 281eb09883 feat(f6): onDidApplyAgentEdit — the single machine-landing signal (SLICE-2)
F6 §6.2/§6.4, INV-9/INV-18. Additive EventEmitter on the seam owner, fired
after a real (non-no-op) applyEdit succeeds. Seam signature/return unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 07:12:31 -07:00
Ben Stull 6f0b903596 feat(f6): BaselineStore — vscode-free per-doc baseline persistence (SLICE-1)
F6 §6.2/§6.3, INV-19. One JSON per docPath under VS Code workspace storage,
never the repo. Mirrors CoauthorStore; unit-tested round-trip/paths/overwrite.

Also lands the F6 implementation plan
(docs/superpowers/plans/2026-06-11-f6-diff-view-toggle.md).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 07:11:42 -07:00
Ben Stull 4c947acc43 fix: proposal threads disable the reply input — decide-only, INV-12
Playing with F4, the operator hit VS Code's default "Reply…" box on a
proposal thread: no submit command is wired for cowriting.proposals, so
typed text had nowhere to go. Proposals are decide-only (accept/reject in
the title bar); discussion belongs in a coauthoring thread. Set
canReply=false so the dead input never renders, and expose canReply on the
test-facing RenderedProposal with an E2E assertion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:26:11 -07:00
Ben Stull 452f5d193f feat: mergeArtifacts — deterministic union-by-id with surfaced conflicts (F5 SLICE-3, INV-17, #14)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:03:15 -07:00
Ben Stull ef7d9403c0 feat: VersionGuard — newer-major sidecars are read-only with one warning (F5 SLICE-2, INV-16/PUC-4, #14)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:01:30 -07:00
Ben Stull ef4ec8dbe9 feat: currentAuthor() carries git user.email — fail-open identity (F5 SLICE-2, #14)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:00:03 -07:00
Ben Stull 746071a585 feat: isNewerMajor + store write-refusal backstop (F5 SLICE-2, INV-16, #14)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 22:59:04 -07:00