Review Buddy
Review Markdown where you read it. Keep feedback attached to its passage, discuss it in
threads, compare document versions, and hand work to your own agent without copying line numbers.
Review Buddy 0.1.5 targets desktop VS Code 1.102.3 or newer. Manual review needs no AI account.
The optional agent workflow needs an agent with local-file/terminal access and Node.js 20.19+.
Direct handoff uses the user's existing Copilot CLI account; Copy prompt instead remains available.
Review Buddy enables the CLI's extension surface for launched sessions so compatible older CLI
versions do not depend on account-specific feature rollout. Direct handoff is verified with
Copilot CLI 1.0.85 and newer; older detected versions fail immediately with Copy prompt guidance.
Right-click a saved .md file, choose Open With… → Review Buddy, select text, and press C
to comment. The document-first review UI is enabled by default, with explicit Light/Dark themes.
Reviews and version snapshots are stored locally in the chosen extension-host or workspace
storage. See privacy and storage and support.
Why
While reading a doc you often want to leave feedback ("tighten this", "is this right?") and then
have Copilot act on it. Here every comment carries its quoted text and heading path, so you can
tell your agent to address the feedback through the review protocol, with its replies appearing
back in the thread.
Features
- Anchored conversations — document and comments scroll independently. A single Comments
control opens the pane; when it is hidden, selecting a comment opens its thread in a bounded popup.
The legacy layout remains available as an opt-out setting.
- Select-to-comment — select rendered text and an add-comment glyph appears in the margin
(never over the text); or press
c. The composer opens in the margin, not over your content.
- Colored highlights and notes — select saved Working-copy text and press
h to apply the
last-used highlight colour, or n to choose yellow, blue, green or rose and add an
optional note and tags. Notes, colour and tags autosave; tags use one integrated chip field with
file, workspace and global suggestions. New tags can remain file-only, become available in the
workspace, or be shared globally. Scope appears only on the Create row: clicking its trailing
File/Workspace/Global action changes the remembered default without creating the tag. Click a
coloured passage directly to open its editor. Navigation from
the local pane or workspace dashboard opens the editor only when that highlight has a note;
highlight-only items just locate/flash. The textarea remains unfocused until you click inside it.
Esc or an outside click closes the editor. The stable Navigate control opens a true
Sections/Highlights tabbed pane. Highlight rows separate section, quote and note, show up to two
tags plus +N, support current-document multi-tag filtering, and share an ellipsis action menu
for editing, navigation and deletion.
Sections, Highlights and Comments each expose a quiet search icon that expands into a compact
current-document search field only when used.
Focus mode hides Review Buddy’s persistent toolbar, panes, splitters and shortcut footer while
retaining comments, highlights, notes, editing, Find and keyboard shortcuts through contextual
UI. In normal and Focus modes, drag either document edge to adjust the 720–1400px reading width;
the edge appears only on hover and a reset icon appears only after modification.
Highlights reuse versioned anchoring and are intentionally separate from threaded comments and
agent handoff.
- Workspace annotation dashboard — run Review Buddy: Open Annotation Dashboard to see
highlights and notes from the current workspace plus every open loose Markdown file in the
current VS Code window. Search tags alongside note and quote text; combine type, colour, document
and multi-tag filters. Manage tags separates workspace and global vocabularies, supports
workspace-to-global promotion, and keeps removing a suggestion separate from deleting assignments.
Switch explicitly from Current project to All projects to search the machine-local index of
Review Buddy documents seen in other projects; Review Buddy never crawls the filesystem.
- Annotation recovery — confidently projected edits show Updated text with original and
current excerpts. Removed or ambiguous passages remain stored and appear as Text removed or
Location unavailable in the Highlights pane and dashboard. Relink to text uses an explicit
select-and-confirm flow that preserves the annotation ID, note, colour, original quote and audited
location history. Selecting a dashboard row opens the exact document annotation. A machine-local
metadata index keeps the view fast and rebuilds from authoritative review stores. Results are
grouped under sticky, collapsible file headers with an Expand/Collapse all toggle.
- Whole-document comments — press Shift+C or run Review Buddy: Comment on Document
when feedback applies to the entire file. These threads are grouped above passage comments,
carry their diff source context when relevant, and never pretend to have a text location.
- Teams/Word-style cards — clearer avatars, author with date/time below, Markdown-rendered bodies with
See more, threaded replies (including Copilot's), and inline Reply / Resolve / Edit /
Delete (no native dialogs). Resolve/Reopen and full-thread controls sit in the card header.
Expanded replies use horizontal separators and the same typography as the original comment.
- Direct Copilot CLI hand-off — Send review queues the short review instruction directly in
a Copilot CLI session without switching terminal apps. Review Buddy remembers the target per
document. When no destination is remembered, Send review first asks for an existing session
ID/prefix; submitting that prompt empty explicitly starts a new session in your chosen external
terminal, while cancelling starts nothing. Active iTerm, Terminal, Windows Terminal, Linux-terminal or custom
launcher sessions receive the prompt through an authenticated localhost bridge loaded inside
Copilot—not by typing into terminal UI. Once/monitoring and Use a sub-agent remain independent;
Use as my default remembers that behavior. Copy prompt instead remains an explicit fallback.
- Agent reply notifications — every new external agent reply can create a VS Code toast and a
persistent toolbar Replies entry beside Comments. The local inbox deduplicates preview/diff
watchers, groups toast bursts per document, navigates to exact threads and retains at most 100
metadata-only entries for 30 days. Right-click an item to mark it read or unread. Configure
reviewBuddy.notifications.agentReplies as always, whenHidden or off.
- Versioned anchoring — immutable original selections plus conservative projections into later
snapshots. Reliably linked passages have no status badge. The card keeps the original quote;
Text changed reveals original/current wording when the passage changes. Unlocated passages
have a plain-language explanation and Link to text, rather than implementation labels.
- Inline block editing — hover or select a block and press
e to edit it in place with a
Markdown-native WYSIWYG editor. Convert blocks between Paragraph, H1-H6 and fenced Code block;
toggle quotes, bulleted/numbered/task lists, indent/outdent, bold, italic, inline code,
strikethrough and links; or use visible Undo/Redo. Markdown typing rules recognize heading,
quote, list, task and fenced-code prefixes. Tables retain their contextual row/column/move tools.
Cmd/Ctrl+Enter or click away to save, Esc to cancel, or use Save / Cancel in the toolbar.
Edits go through VS Code undo/redo and Cmd+S; the editor closes only after the host acknowledges
the edit. A rejected save leaves the draft editable with an inline explanation. The editor is
lazy-loaded on first edit, so reading and commenting stay lightweight.
- Whole-document rich editing — press Shift+E to edit the complete rendered document with
the same Markdown-native toolbar. Saving compares top-level editor blocks and submits only changed,
inserted, deleted or reordered source regions in one atomic
WorkspaceEdit; untouched Markdown
remains byte-for-byte unchanged and the operation is one normal VS Code Undo step. Frontmatter and
raw HTML remain byte-exact protected source blocks inside the rich surface, so the formatting tools
stay available for the rest of the document. Genuinely unmappable structures fail closed with the
draft preserved instead of silently reserializing the file. Double-click only selects text; it
never opens an editor.
- Checklist editing — task items remain real checkboxes in the editor and after saving.
Checked state, nested bullet markers, uppercase
[X] markers, and inline formatting survive
round trips; checkbox changes participate in editor undo/redo. Rendered preview checkboxes update
their exact Markdown marker without rebuilding the document, including while the current file has
unsaved changes when its source hash still matches. Intentionally escaped literal markers remain
ordinary text.
- Light / Dark themes — switch using the toolbar or
reviewBuddy.theme. Changes apply
live across preview, comments, editing, find, code, diagrams, and rendered diff without discarding
reply drafts or committing an open block edit.
- Find and safe Replace — Cmd/Ctrl+F opens a VS Code-style find bar with "X of Y",
match-case and whole-word controls. Expand Replace, use Cmd+Option+F on macOS or Ctrl+H
on Windows/Linux, then replace the current match or all matches atomically. Replacement is
available only on a saved Working copy with no active edit or pending agent iteration. Review
Buddy preserves surrounding Markdown when the rendered match maps unambiguously to one source
span; formatting-spanning, generated or ambiguous matches stay Find-only. Replace all is one
VS Code Undo step. Regex and multiline replacement are not supported.
- Version history per comment — when a change is made for a comment, a version is recorded
and shown on that card as Changes (N); clicking a change opens the rendered diff scrolled to
it. Versions are stored as hash-verified keyframes and deltas in a lazily-read file next to your
comment store. Storage cost depends on the document and the edits, not a fixed per-version size.
- Rendered diff, side-by-side or inline — compare any two points: git refs (
HEAD, Staged,
Working Tree) and recorded versions, with an ADO-style Side by side / Inline toggle.
The version picker includes Staged → Working copy, Committed (HEAD) → Working copy and
Committed (HEAD) → Staged. Git comparisons refresh when the index or references change.
Staged, committed and recorded document snapshots remain text-read-only, but their right-hand
passages can receive version-aware comments and normal thread actions. Recorded origins use the
saved version; HEAD and Staged origins use immutable local comparison snapshots and project into
later working versions. Document editing and relinking remain working-copy-only.
- Mermaid diagrams —
```mermaid blocks render as diagrams (lazy-loaded) with pan, zoom and
fit controls. Select Pan before dragging a diagram; otherwise it keeps the normal pointer.
Select text within a rendered diagram and use C, H or N to comment, highlight or add a
note using the exact matching Mermaid source text. Only the selected words are painted. Press
E over a diagram to edit only its Mermaid body; the fence is preserved.
- Toggle preview ↔ source — Cmd+Alt+E
(Ctrl+Alt+E on Windows/Linux).
- Review navigation history — deliberate jumps from comments, links, Find, notifications and
diff changes can be revisited with Option+←/→ on macOS or
Alt+←/→ on Windows/Linux. Ordinary scrolling is not recorded.
- Document navigation — the stable Navigate control opens a left pane with true Sections
and Highlights tabs. Sections is a clean nested H1-H4 outline for jumping through the document;
headings with descendants have persisted disclosure controls. Read checkboxes share one fixed
left column and remain hidden until their row is hovered/focused or they are completed/partially
completed. Partial parents use a persistent empty box rather than an indeterminate minus,
and a parent checks itself automatically when every child branch is complete,
while quiet badges show active comment counts. Parent badges aggregate descendant comments so
collapsed branches still reveal outstanding review work; resolved comments are excluded.
Progress/filter/bulk controls stay out of the way.
Selecting a section places its heading at a comfortable responsive reading inset, highlights it
with a text-only accent tint until the next non-scroll user action, and keeps the currently
focused section selected and visible in the rail as the document scrolls.
Highlights lists the current document's coloured annotations and notes. Comparisons place
Navigate at the far left, keep read-state checkboxes editable as review metadata, and add
independent Anchors and Highlights visibility controls. Their version labels move with the
reduced document viewport when Navigate opens, and historical/Git highlights are projected onto
the selected right-hand source. Compact headers retain primary actions and move secondary controls
into one chevron menu. Pane visibility, width and active tab persist.
Usage
Make it the default .md editor so opening any Markdown file shows the commentable preview:
"workbench.editorAssociations": {
"*.md": "reviewBuddy.preview"
}
Or open a single file without changing settings: right-click the file → Open With… →
Review Buddy (or run Review Buddy: Open in Commentable Preview). To
view it side-by-side with the source, open the source in a second editor group.
Upgrading an earlier local installation
Back up existing reviews, disable earlier local shivang.markdown-preview-comments or
shivang.review-buddy installations, then reload after installing
review-buddy-markdown.review-buddy-markdown. Existing global reviews remain at their original paths and are
reused; workspace sidecars and document-version numbers do not change. Conflicting stores are
reported without choosing or overwriting one.
Explicit reviewBuddy.* preferences take precedence; otherwise previously configured
markdownComments.* values remain effective. Old commands and saved-version URI schemes remain
available as compatibility aliases when the previous extension is absent. Old default-editor
associations are updated without changing unrelated associations.
Adding & handing off comments
- Save the document, select rendered text → click the margin add-comment glyph (or press
c)
→ write → Comment.
- Use each card to Reply / Resolve / Edit / Delete.
- Use Send review, or its monitoring variant. The prompt points to the comment store's
extension-maintained
reviewInstructions: document/tool paths, current-mode rules, command
argument arrays and the completion-request shape. The agent discovers current feedback at run
time and processes one thread before starting the next. It must not append replies directly.
Monitoring is an explicit choice for that agent session, not a persistent flag in the JSON.
For direct Send review handoffs, the session bridge—not an agent-authored shell script—watches the
exact review store for actionable feedback and queues a monitor wake in the parent session. A
delegated handoff reuses the same idle sub-agent through the parent on every wake. Copied/manual
prompts retain the supported watcher or bounded-wait fallback. Both paths ignore the agent's own
writes and require explicit reporting when monitoring cannot continue. While active, the handoff
control reads Monitoring and its menu provides status plus Stop monitoring; the inactivity
countdown remains internal rather than adding a low-value timer to the UI.
Monitoring stops manually, when Once is sent, when the destination changes or clears, when the
Copilot session closes, or after one hour without actionable user feedback. Expiry clears the
status and creates one VS Code notification.
Bridge monitoring is intentionally lightweight: one operating-system file-watch handle, one timer
and a small state record per monitored document. Idle CPU usage is effectively zero; the store is
read only after a file-change event and bursts are debounced. A tiny localhost status check runs
every 30 seconds only while a Review Buddy view is visible.
The handoff dropdown exposes two explicit axes: Review type (Once or Keep monitoring) and
Run with (Main agent or Sub-agent), followed by one Send review action. Hover help explains
each choice. Persistent default, destination and launch-terminal choices use the same model in a
separate Handoff settings dialog.
On first use, Review Buddy asks before installing its user-scoped Copilot CLI bridge under
~/.copilot/extensions/review-buddy (or the configured reviewBuddy.copilot.home). Each CLI
session creates an ephemeral localhost endpoint with a private random token stored in a
user-readable registry file. The bridge enqueues messages and returns an acknowledgement; it does
not emulate terminal input. Review Buddy-launched sessions start with Copilot --allow-all, and the
bridge switches a selected live session to allow-all before enqueueing the review so an automated
run does not stop at tool, path or URL prompts. Managed enterprise policy may reject that transition;
when it does, Review Buddy reports the failure and does not claim delivery. Existing sessions opened
before installation or an update must be restarted once. If a chosen terminal cannot be launched,
Review Buddy copies the exact launch command and keeps the review prompt pending instead of claiming
it was sent.
Reviewing highlights across a workspace
Run Review Buddy: Open Annotation Dashboard. The dashboard includes highlights and notes only,
never threaded comments, and does not mix unrelated machine-wide review data. Its local index stores
document path/name, annotation ID, colour, tags, section, timestamps and bounded quote/note excerpts.
Review stores remain authoritative; opening the dashboard rebuilds its current-window scope.
File groups can be collapsed individually or together; the document dropdown remains available for
direct filtering. Tag selection is OR within tags and AND with search, type, colour and document.
Manage tags reports scope-aware annotation/document usage. Workspace changes affect that workspace;
global changes affect indexed documents everywhere. Dashboard results themselves remain limited to
the current project by default. All projects searches the persisted machine-local annotation
index and labels results with their project; it includes reviewed documents already known to Review
Buddy rather than scanning every repository.
Workspace scope follows the stable project boundary: an explicit multi-root workspace first,
otherwise the nearest Git repository, otherwise the opened non-home folder. Opening a repository
subfolder therefore retains the repository vocabulary, while opening the home directory does not
combine unrelated repositories into one tag scope.
The first saved baseline is v1. Saving different Markdown creates another version. A completed
Copilot iteration handles one thread and creates one version only when the saved document
changed; intermediate saves between begin and complete do not create extra versions.
Answer-only replies retain the existing version and have no change chip. They use a durable
completion receipt, so interrupted delivery and identical retries do not duplicate replies.
Numbering is per file, not per workspace or Git branch. Unsaved edits are projected for display
but do not become snapshots; save before adding comments or starting an agent iteration.
Copying the generic prompt is allowed while editing. Internal anchor status names and snapshot
numbers are not shown as routine card badges. Location confidence is separate from whether the
conversation is open/resolved or whether Copilot has addressed its feedback.
The visible version UI is the comment-attributed change history: expand Changes (N) on a card,
click a change, and compare recorded versions through the rendered From/To view. These same version
records carry the rendered projections and anchor metadata used internally, so there is one counter
and one timeline rather than a second hidden snapshot history.
New Copilot versions are attributed explicitly to their one iteration thread; arbitrary manual
edits are no longer assigned to comments from timing or proximity guesses. Change rows show the
version and label. Exact time and older inferred/shared attribution remain available in hover and
keyboard-accessible descriptions, without the prominent "likely" / "also for" badges.
Changes starts collapsed in pane, popup and full-thread views, while retaining deliberate
expansion choices. Diff revision labels occupy a separate, clipped row instead of overlapping
the controls. The controls wrap in compact windows and version menus stay inside the viewport.
Diff changes use red/green fills and word highlights, not vertical change rails or extra rail
padding. Native Markdown blockquote styling is retained and explicitly themed in all three
document surfaces.
Diff and review actions share one full-width toolbar: comparison/navigation controls on the left,
review actions on the right. Comment navigation and the resolved filter live with the comments
pane. Version labels are compact; timestamps remain available on hover. Opening a change selects
its predecessor/result pair in both the content and picker instead of displaying "All Changes."
Original/current quote excerpts are limited to three lines each and use the full card width,
including hidden-pane popups. Open full comparison uses the recorded original and displayed/current
version; unavailable original snapshots are not fabricated. The original quote remains available
in the full thread.
The bottom hint strip starts with a readable All shortcuts keycap button, followed by only the
primary contextual C, H and E actions. The modal includes document comments, notes,
thread navigation, Find/Replace, review navigation and F6/Shift+F6 movement between toolbar,
Navigate, document, comments and shortcut help. Navigate tabs, section trees, comment/notification
lists and dashboard groups support the expected arrow, Home/End, Enter, Space and Escape behavior.
Typing fields retain normal text entry and Ctrl/Cmd+F remains Find.
Web links use the system opener; local Markdown references open in the commentable preview,
and heading references navigate to stable, duplicate-safe heading IDs. Executable link schemes
such as javascript: and command: are not supported.
Each anchor retains its original version, selected quote, and half-open UTF-16 range in the
rendered-text projection. Its current range, current quote, and status are calculated across
versions. Every version reconstructs both raw Markdown and the exact canonical rendered projection;
rendered offsets are deliberately not presented as source line/column coordinates. A thread's
open/resolved state is independent of its anchor status.
Older stores can import uniquely matching quotes into v1; that is an imported baseline, not a
reconstruction of their unavailable original document. Unidentifiable legacy locations remain
unverified. Outdated/ambiguous locations never fall back to fuzzy matching in the versioned preview.
Large diffs are partitioned at unique, order-stable lines and words before bounded character
alignment, so an unrelated rewrite does not invalidate every comment. Duplicate landmarks are
not tie-broken arbitrarily. A uniquely matched quote with a certified interior also keeps repeated
boundary punctuation from absorbing an appended sentence.
If the extension cannot confidently locate a passage, use Link to text, select its intended
passage in the saved current document, then confirm. Change linked text in the comment's
actions menu also allows correcting an existing link. Escape/Cancel abandons the selection;
document editing is suspended while choosing the new location.
Relinking changes attachment metadata only: it preserves the original quote, conversation,
timestamps and first verified origin, records an audit entry, and does not create a document
version. A previously unverified comment does not acquire fabricated original context. A changed
document/conversation, stale selection or pending agent iteration rejects the operation explicitly.
An interrupted delivery can be retried safely.
The repair is new user feedback for pending; the next Copilot response records which location
revision it addressed, preventing repeated processing of the same repair. The begin response
includes the verified current location, so an agent need not guess from an old quote.
Saved-version comparisons use attachment locations for that revision rather than projecting the
latest missing location backwards. Older comparisons remain read-only and offer Open current
document when a location needs attention. A comment created later is identified as such.
New history records maintain compact location deltas; pruning carries them forward. Older histories
are reconstructed conservatively, and missing intermediate evidence never authorizes a fuzzy guess.
Intentional deletion does not force relinking: the conversation can still be discussed or resolved.
The extension does not launch an AI agent by itself. The copied prompt asks Copilot to use the
bundled dist/iteration.js tool (Node.js required):
node <iteration.js> pending --document <file> --store <comments.json>
node <iteration.js> begin --document <file> --store <comments.json> --expected-hash <fresh-sha256> --threads <one-id> --intent-policy document
node <iteration.js> hash --document <file>
node <iteration.js> complete --document <file> --store <comments.json> --request <request.json>
The completion request contains iterationId, the final saved file's expectedHash, and
replies: [{ "commentId": "...", "body": "..." }], containing exactly the one iteration thread.
That thread gets one reply with
iterationId, baseVersion, version, and a UTC timestamp; parent updatedAt is unchanged.
An identical completion retry does not duplicate a version or reply. Review iterations honor the
stored document Agent/Ask mode, regardless of old per-thread intent; classic handoffs use
--intent-policy per-comment. A mode change during an iteration rejects completion.
After completion, discover pending feedback and the current hash again before starting another
thread. pending is read-only and excludes resolved or already-answered threads unless new user
feedback has arrived.
The tool persists snapshots even with the preview or VS Code closed. Without this protocol,
external replies are displayed but do not create duplicate versions or infer comment ownership:
missed intermediate file states cannot be recovered. The extension cannot attribute arbitrary disk
writes to Copilot; begin/complete define that boundary explicitly.
Stale hashes, changed/resolved/deleted selected threads, overlapping iterations, or conflicting
retries fail explicitly and leave data intact. Cancel Pending Copilot Iteration (also available
in the preview) abandons a pending iteration and checkpoints any saved partial edits. It does
not undo edits. Re-read the document and pending feedback after cancellation; the generic prompt
itself is reusable.
If a new comment is rejected because its selection is stale or storage is busy, the composer
keeps the draft; closing it and selecting text again restores that draft rather than losing it.
Storage
By default comments are stored machine-locally in the extension's storage (keyed by the file's
path), keeping your workspace clean — they are personal to your machine and not shared via git.
Prefer to share them with a repo? Set the location to workspace and they live in a sidecar file
next to the document (<file>.md.comments.json). Comments and history follow explicit VS Code
file renames. External filesystem renames cannot be identified reliably; move both stores
deliberately instead of relying on same-content guesses. Complete/cancel an iteration before
renaming its file because copied prompts contain its original absolute paths.
One unified history file lives beside the comment store as .versions.json (schema v4). It stores
periodic keyframes plus compact line deltas for both raw Markdown and canonical rendered
projections, with SHA-256 verification for each reconstructed value. The same records contain
anchor metadata, attribution, guarded iteration provenance, reply-only completion receipts,
historical location deltas and explicit attachment audit/delivery records.
Existing v1/v2/v3 histories remain readable; the next mutation writes v4 without renumbering or
discarding old snapshots. Back up stores before upgrading; older extension builds must not write
the upgraded history. Comment stores remain schema v3, with additive reviewInstructions and
locationRevision metadata; replies may record the location revision they addressed.
Anchor-origin, completion-receipt and pending-iteration base versions are pinned and never pruned. Other old versions
are retained up to the 500-version / 2 MiB navigation caps; pruning rebases surviving raw and
projection chains into keyframes. A single document or projection above 64 MiB fails explicitly.
History writes use unique temporary files and an exclusive .versions.json.lock. Every mutation
re-reads the latest file inside the lock so editor and diff sessions cannot overwrite each other.
Interrupted reply delivery is journaled and retried on the next checkpoint/completion. Existing
.versions.json diff history and <comments.json>.history.json anchor history are merged
transactionally on first use; the old anchor file is renamed .migrated only after the unified
file is durable.
The comment store is a small JSON document (schema v3):
{
"version": 3,
"document": "design-notes.md",
"comments": [
{
"id": "c_ab12cd",
"quote": "under two minutes",
"prefix": "aha\" moment in ",
"suffix": ".",
"headingPath": ["Overview"],
"author": "you",
"status": "open",
"createdAt": "2026-07-10T00:00:00.000Z",
"updatedAt": "2026-07-10T00:00:00.000Z",
"replies": [
{ "author": "you", "body": "Can we make this the headline metric?", "createdAt": "2026-07-10T00:00:00.000Z" },
{ "author": "copilot", "body": "Yes — added.", "createdAt": "2026-07-10T00:06:00.000Z" }
]
}
]
}
The example omits generated reviewInstructions for brevity. In v3 the root message is
replies[0]; legacy v1/v2 root bodies are still read correctly. Existing copiedAt and attribution
metadata are preserved, but no longer used to present a misleading "Sent" state.
Settings
| Setting |
Default |
Description |
reviewBuddy.author |
automatic |
Author name stamped on new comments and replies. Review Buddy asks once on the first attributed action and saves the answer as a user setting. When blank, it uses Git user.name, the signed-in GitHub account, or You. |
reviewBuddy.storage.location |
global |
Where comments are stored: global (machine-local, clean workspace) or workspace (sidecar next to the file, shareable via git). |
reviewBuddy.showResolved |
false |
Show resolved comments in the preview. |
reviewBuddy.theme |
light |
Explicit light or dark preview theme, independent of the editor theme. Applies live in classic and review UI. |
reviewBuddy.experimental.reviewUi |
false |
Enable the document-first review UI. Save/cancel in-place document edits and reload the window after changing this window-scoped setting. |
Experimental document-first review UI
The document-first design is enabled by default. Its compatibility setting is:
"reviewBuddy.experimental.reviewUi": true
It provides independently scrolling document/comments regions, self-contained thread cards with
per-thread reply boxes, and one document-wide Agent / Ask selector (Agent by default).
Clicking a card locates its passage without moving the comments pane. The two rendered-diff
document columns remain linked. Light remains the default even in a dark editor theme; choosing
Dark is explicit.
Comment navigation and Find reveal the actual quoted/matched text, including passages near the end
of long paragraphs and inside horizontally scrolling tables. Diff scroll position survives
realignment and working-document refreshes, including large inserted/deleted regions.
With Comments hidden, clicking a highlight opens a viewport-bounded thread popup. It shifts upward
near the bottom edge; long threads scroll internally so replies and actions stay reachable.
Thread popups and new-comment composers adapt to window resizing without clearing drafts.
The popup uses the same card renderer as the pane and includes the same Resolve and full-thread
controls. Replies start collapsed in both the pane and hidden-pane popup, with an expandable reply
count; your explicit per-thread expansion choice is remembered. The popup keeps the original comment
fully readable, and Open in full view still displays all replies.
Comments is the rightmost toolbar control. Bulk selection has been removed; individual
comment/reply deletion remains available.
Quoted context and actions share one compact header rather than separate rows. Resolve's icon and
label turn green on hover without a filled background; the Agent/Ask menu matches its button's width.
The Agent/Ask dropdown is an accessible in-preview menu with keyboard navigation, a selected-item
indicator and a keyboard-only focus ring, rather than a browser/OS select popup.
Preview colour sources
Light and Dark are based on VS Code's built-in Light Modern / Dark Modern colour pairs, independent
of the surrounding editor theme. Values were verified against theme-defaults/themes/light_modern.json
and dark_modern.json, and the native markdown-language-features/media/markdown.css and
highlight.css. Fenced syntax uses the installed Visual Studio highlight styles with the native
preview's token overrides.
| Surface |
Light |
Dark |
| Document background / foreground |
#ffffff / #3b3b3b |
#1f1f1f / #cccccc |
| Inline code background / foreground |
#0000001f over white / #3b3b3b |
#3c3c3c / #d0d0d0 |
| Code block background |
#f8f8f8 |
#2b2b2b |
| Links |
#005fb8 |
#4daafc |
Both foreground and background are explicit. This prevents VS Code's injected opposite-theme inline
code colour from leaking onto the preview's selected theme.
Document mode and drafts
In-place editing validates complete Markdown block boundaries before applying or relocating an edit.
It cannot retarget a stale paragraph onto matching text inside a heading, fence, or table fragment.
Wide-table editing preserves GFM column alignment, reveals the selected cell, and provides
mouse- and keyboard-operable Rows/Columns/Move controls. Diff document editing remains disabled;
commenting and replies remain available.
Document mode is saved as optional documentIntent metadata in the comment store. The new UI's
copy prompt uses it for every selected thread, without rewriting old per-comment intents or
timestamps. Turning the feature off preserves the classic per-comment behavior. Invalid stored mode
metadata requires an explicit Agent/Ask choice before copying; it never silently becomes Agent.
Changing the selector does not run an agent or copy anything automatically.
Unsent drafts and selected-thread state can follow the document between open review views.
They use the VS Code webview-state/host bridge, not the Copilot comment store. Focus, modal state,
and viewport layout remain local to each view. Older persisted bulk-selection fields are discarded
without clearing drafts or expansion state.
Development
Before changing UI, read the UI instructions.
They define the shared design language, component ownership, interaction rules and visual checks
for all contributors, including parallel feature branches.
npm install
npm run build # bundle extension + webview (esbuild); copies codicons + mermaid
npm run test:unit # Node/jsdom unit tests (pure logic + DOM logic)
npm run test:history # focused history, anchoring, persistence, and review UI coverage
npm run test:webview # builds, then runs the real-Chromium e2e harnesses
npm test # isolated native VS Code UI + real-store/edit/undo integration tests
# package + install into VS Code (build runs automatically via vscode:prepublish):
rm -f *.vsix && npx --yes @vscode/vsce package --allow-missing-repository --skip-license
code --install-extension review-buddy-markdown-0.1.5.vsix --force # then reload the window
Press F5 in VS Code to launch an Extension Development Host and try it live.
Set VSCODE_EXECUTABLE_PATH to the installed VS Code Insiders executable to run integration tests
there rather than downloading stable VS Code. VSCODE_TEST_USER_DATA selects an isolated test profile.
On managed machines where package-manager/registry access is prohibited, use existing dependencies
and direct binaries (node esbuild.js, ./node_modules/.bin/tsc) rather than the installer commands.
The review launchers below never install packages or download an editor.
Architecture
Two layers; only the extension host touches disk, the webview talks via postMessage.
- Host:
src/extension.ts (activate/commands), src/editorProvider.ts
(CustomTextEditorProvider — the only surface, opens .md as the preview), src/webviewHost.ts
(CommentSession), src/webviewHtml.ts (one production preview/diff HTML builder), src/store/ (CommentStore abstraction: fileStore.ts,
factory.ts, keying.ts), src/sidecar.ts (store file I/O + migration), src/render.ts
(markdown-it → HTML, source-line mapping, mermaid emit), src/prompt.ts (Copilot prompt +
delta), src/documentMode.ts (mode compatibility), src/reviewState.ts (acknowledged shared draft patches),
src/anchor.ts (text-quote anchoring + bounded fuzzy), src/blockSource.ts
(block↔line mapping + edit plan), src/find/search.ts, src/types.ts.
- History:
src/history/ provides unified raw/rendered keyframe-delta history, anchor mapping,
attribution, guarded iteration provenance, and the independent iteration CLI.
src/versionView.ts exposes read-only virtual documents
and native version comparison. The extension API exposes openVersionPair and
showOriginalVersion for consumers using the same history model.
- Webview:
src/webview/ — main.ts (orchestrator), layout.ts (gutter collision + responsive
mode), gutter.ts (margin cards), card.ts (card component), commentBody.ts (safe Markdown
render), sidebar.ts (panel), dom.ts (text-map + CSS Highlight-API paint + hit-testing),
find.ts, blockEdit.ts + pm*.ts (ProseMirror block editor, lazy), tokens.css + styles.css.
The default review UI uses reviewLayout.ts, reviewCard.ts, reviewUi.ts and the gated
reviewTokens.css / reviewBase.css / review.css sheets in that same bundle.
- Build:
esbuild.js → dist/extension.js, dist/webview.js, dist/webview.css,
dist/blockeditor.js (lazy), dist/iteration.js (standalone Node CLI), and copies
dist/mermaid.min.js (lazy) + dist/codicon.{css,ttf}.
Testing
- Unit (
test/*.test.ts, Node --test + jsdom): pure logic and DOM logic.
- Browser e2e (
scripts/*-e2e.cjs, playwright-core via installed Edge/Chrome): loads the
actual bundled dist/webview.js and drives real gestures under the production CSP. These exist
because VS Code webviews are opaque to the OS accessibility tree — UI automation can't
drag-select or double-click inside them, so webview interactions are verified here.
- Integration (
@vscode/test-electron): an isolated editor profile exercises production UI
code inside a real webview, real temporary comment/history files, live file updates, document
mode, draft sharing, in-place edits, WorkspaceEdit/undo/redo, closed-preview iteration
completion, and native immutable version documents/diff tabs. A test-only driver is compiled
to a temporary location; no test command/eval API is shipped in the extension.
The large fixture is a synthetic README of approximately 330 KB and 11,000 lines. The history
suite covers large rewrites, insertion boundaries, deletion, duplicate blocks, heading changes,
formatting, code fences, Unicode, multi-block selections, and restoring deleted text. The browser
suites use an installed browser (Edge on Windows); MPC_CHROMIUM_EXECUTABLE overrides discovery.
Browsers are closed on success and failure rather than left running after a failed assertion.
scripts/copilot-iteration-scenario.cjs provides an opt-in real Copilot trial. Run prepare
with a new absolute artifact directory, submit 01-ask.prompt.txt to Copilot, then run after-ask,
submit 02-update.prompt.txt, run after-update, submit 03-followup.prompt.txt, and run verify.
It checks exact file changes, unchanged parent timestamps, preserved original anchors, and one
version per iteration. Ordinary tests never invoke a paid model automatically.
For the live external-iteration integration case, set MPC_LIVE_REVIEW_DIR to a trial awaiting
its third prompt before running npm test. The isolated preview writes live-ready.json; run
the third Copilot prompt only after that signal. The test checks the pending indicator and the
new reply/version appearing without a manual refresh. MPC_CAPTURE_INSIDE=1 enables a local
debugging connection for scripts/capture-insiders.cjs; the capture attaches to the existing
isolated window, not another browser window. The test runner closes its window afterward.
Design docs and decisions live in design/ (see design/decisions-log.md). Reinstalling a VSIX
does not update already-open windows — reload the window to pick up a new build.
UI design workbench
Run node scripts/review-workbench.cjs and open the printed loopback URL. It builds and serves the
same production UI assets and HTML as VS Code, with an isolated memory-backed host. There are no
alternate card/layout implementations or prototype-only CSS overrides. UI refinements happen once.
The workbench does not modify your real documents, comments, or installed extension.
Run node scripts/review-devhost.cjs to open an isolated real VS Code development host with the
feature enabled and the same sample document/comments. It uses a cached editor (or
VSCODE_EXECUTABLE_PATH), never downloads one, and preserves the sample/profile under
.vscode-test/review-devhost/. Your normal VS Code profile and installed extension are unchanged.
This isolated profile does not copy your existing global comment stores.
For native integration tests, set VSCODE_EXECUTABLE_PATH to an existing VS Code executable when
downloads are not permitted, then run node out/test/runTest.js after compiling/building.
This runner creates and removes its own temporary profile.
Set MPC_NATIVE_SHOTS to an output directory to also capture the actual isolated VS Code window's
light preview/diff and light/dark editor states. This optional test-only capture enables a loopback
debugging port for that disposable profile; neither the production extension nor the normal
development launcher exposes a debugging endpoint.
See the design brief and preserved-feature inventory
and integration contract for scope and verification.
License
MIT — see LICENSE.