intentumdiff-vscode
Architecture of the IntentumDiff VS Code extension (native-first). Use this whenever you work in `plugins/vscode/` — the diff surfaces, CodeLens/Peek/decorations, the review panel webview, intent expl
SKILL.mdskills/intentumdiff-vscode/SKILL.md
GitHubIntentumDiff — VS Code Extension (native-first)
The extension is TypeScript, compiled with tsc only (no bundler). It consumes the engine
over the LiveServer protocol (intentumdiff live-server --stdio, protocol v2) and renders
intent natively in the editor plus one review webview.
Native-first diff (do not rebuild a diff editor)
The native VS Code diff editor is the primary surface:
- Open with
vscode.diff: left = read-onlyintentumdiff-base:document (git show <ref>:<path>via a content provider), right = the real working-tree file (editable). NativediffEditor.hideUnchangedRegionshandles collapse/expand. - Editing the right pane re-runs the engine (debounced
scheduleDocument → diffDocument → handleDiffinextension.ts) and refreshes intent live. - Do NOT reintroduce Monaco,
createDiffEditorwebview embeds, themedia/monaco/bundle, or the retired gap machinery (gapStates,expandGap/collapseGap, floating chevrons, per-sidesetHiddenAreas).
Intent is surfaced via CodeLens + Peek + decorations, not a bespoke editor.
File map (what owns what, all under plugins/vscode/src/)
| Area | Files |
|---|---|
| Extension entry, live-diff wiring, commands, base content provider | extension.ts, baseUri.ts, protocol.ts, gitStatus.ts |
| CodeLens / Peek / hover / inlay (intent on the diff) | intentCodeLens.ts (pure logic), intentCodeLensProvider.ts (vscode provider) |
| Intent "what/why/risk" (deterministic) | intentExplain.ts |
| LLM explainer (BYOK / vscode-lm) | intentLlmExplainer.ts, intentLlmPrompt.ts |
| Release notes | releaseNotes.ts (see intentumdiff-release-notes) |
| Content class (code/docs/config/data/text) | contentClass.ts |
| Change → review entry mapping | mapper.ts, reviewModel.ts |
| Semantic Changes tree | reviewTree.ts |
| The one review webview (Intent / Release Notes / Evidence / Diagnostics + semantic diff + asset diff) | reviewWebviewModel.ts (model + HTML), reviewWebview.ts (controller) |
The review webview (reviewWebviewModel.ts)
One webview, four tabs: Intent, Release Notes, Evidence, Diagnostics, plus an
editable semantic-diff view with per-hunk staging, and the perceptual asset diff for
images. Key model builders: buildReviewPanelModel, renderPanelHtml, dashboardEntry
(attaches an IntentExplanation per entry), entryCard, assetModeViewer.
Risk is derived (see intentumdiff-engine): MEANINGFUL→Behavior, REFACTORING/MOVED→ Internal, non-code content → Content, style/noise excluded, guardrails → critical.
Content classes (contentClass.ts)
Non-code files must not get code framing. contentClassForDiff(diff) →
code | docs | config | data | text from language + metadata.content_type.category +
code-node detection. Drives: relabel MEANINGFUL → Docs/Config/Data/Content, risk content
(not "Behavior"), and suppresses code phrases ("New public API", function nouns) on prose/
config. A .gitignore line addition must read as a Content edit, never "Behavior".
Ungrouped-change handling (ties into the engine's index-space contract)
A change owned by no change_group is a real ungrouped change, not evidence to bury.
coveredChangeIndices(groups, count) (in intentCodeLens.ts) unions in-range group indices;
intentForLine, buildIntentLenses, releaseNotes.buildReleaseNotes, and
reviewModel.reviewEntriesForFile all fall back per-change via kindForChange. In the tree,
reviewEntriesForFile promotes ungrouped changes to first-class Meaningful/Refactor/Moved
entries when a modified file has no shown intent groups (the ungrouped changes are the
story), and otherwise leaves them in the collapsed "Raw evidence" bucket. See
intentumdiff-engine → references/index-space-contract.md.
Theme-native styling (hard rule)
Bind to the editor theme, never a bespoke palette:
- Chrome uses
--vscode-*variables; change categories use the contributedintentumdiff.semanticChanges.*color IDs (+--vscode-diffEditor-*for line backgrounds). - No hardcoded chrome hex literals. No bundled Google Fonts / JetBrains Mono
<link>s — use the editor's font vars. Must read in Dark+, Light+, and High-Contrast. - Codicons only (
codicon codicon-*); never ship custom chrome SVG for icons. - Guardrail reality (verify, don't assume):
test/themeColors.test.tschecks that the contributedintentumdiff.semanticChanges.*color IDs exist inpackage.jsonand that overview-ruler decorations use them — it does not scan the rendered panel/diagnostics HTML for chrome hex literals or custom SVG icons. That gap is real:reviewWebviewModel.tsstyles()andextension.tsrenderDiagnosticsReportHtmlcurrently ship a bespoke dark palette (100+ hardcoded hex) + a customiconSvgchrome icon set, andcolor-scheme:dark— a standing theme-native violation the test does not catch (tracked indocs/BACKLOG.md). When you touch these surfaces, migrate to--vscode-*/codicons and add the missing HTML hex scan to the test; don't trust the test's name to mean it's enforced.
Privacy / BYOK (hard rule — see also plugins/vscode/PRIVACY.md)
- Never bundle an API key or run a paid proxy. The LLM explainer is opt-in
(
intentumdiff.intent.explainer: "llm"), BYOK orvscode-lm/Copilot. - Keys live in VS Code SecretStorage, never settings.json. A cloud consent modal precedes any send.
- Default
codeSharing: "signatures"sends a locally-derived fact sheet (symbol/type names + structural facts, no bodies/literals)."facts"sends counts/enums/flags only."full"(verbatim source) is allowed only to a local endpoint (Ollama/LM Studio/vLLM). - Unit tests do no network.
Build, test, verify
cd plugins/vscode
npm run lint # tsc --noEmit
npm run test # node --test on compiled out/ (unit; no network)
Integration tests gate on INTENTUMDIFF_SKIP_LIVE_DIFF=1.
Panel-render harness (fast visual check without launching VS Code): compile, then run a
small node script that imports out/src/reviewWebviewModel.js, calls buildReviewPanelModel
renderPanelHtmlon a syntheticReviewFile, writespanel.html, and serve it withpython -m http.serverfor the Claude Preview MCP. StubacquireVsCodeApiand strip the CSP meta so it renders in a plain browser. Use this to verify layout/overflow/interaction (swipe, blink, lasso, hotspots) before manual reload.
Pure-TypeScript changes need no maturin/Rust rebuild.