Status: open · ships after
c9-plugin-layer.md(C.9) in the impact-vs-cadence sequence — not a hard block; diagnostics on existing recipes work without entry-point hints, but landing C.9 first reduces false positives on framework files.Motivator: humans-in-IDEs surface for codemap's recipe outputs. Diagnostics-as-squigglies for
untested-and-dead,components-touching-deprecated,boundary-violations,unimported-exports,high-complexity-untested,deprecated-symbolscallers. Hover provider oversymbols.signature+doc_comment+complexity+ caller-count fills a gaptsserverdoesn't (codemap-unique metadata, not types). Code lens for fan-in / complexity / coverage. Code actions hooked torecipe.actionstemplate.Tier: XL effort. Two paired components:
codemap-lspserver +codemap-vscodeextension. Server alone is incomplete — extension is required to consume the customcodemap/analysisCompletenotification + render status bar / tree views.Implementation libraries:
vscode-languageserverfor the server side;vscode-languageclientfor the paired VSCode extension. Both Microsoft-official LSP libraries on top of which the codemap-specific diagnostic-push behavior is built.Roadmap: § Core substrate & platform · soft ordering after C.9
Nothing in-tree yet — start with Slice 1 only: codemap-lsp stdio server + one recipe (untested-and-dead) → Diagnostic[] via new --format lsp-diagnostic formatter. Resolve Q1 repo structure first (default bias: Option 1 stay flat — add lsp/ + editors/vscode/ without monorepo conversion per § Repo-structure tradeoffs). Do not implement definition / references handlers (L.1).
| File | What to read |
|---|---|
src/application/output-formatters.ts |
Add formatLspDiagnostic beside formatSarif / formatAnnotations |
src/application/query-engine.ts |
Recipe row execution — server reuses, no SQL in LSP layer |
src/application/show-engine.ts |
Hover symbol lookup |
src/application/watcher.ts |
File-change → reindex → republish diagnostics |
src/application/recipes-loader.ts |
Recipe ids for diagnostic code mapping |
templates/recipes/untested-and-dead.sql |
Slice 1 diagnostic source |
package.json |
Add codemap-lsp bin entry (flat layout) |
formatLspDiagnostic + minimal lsp/server.ts → run untested-and-dead → push diagnostics for one open file. Manual VSCode launch.json attaches to stdio — no extension yet. Verify squiggle on fixture dead export.
VSCode extension package; six-recipe bundle; marketplace publish; textDocument/definition / references; new CLI verdict verb.
# After formatLspDiagnostic lands
bun test src/application/output-formatters.test.ts
bun src/index.ts query --recipe untested-and-dead --format lsp-diagnostic # CLI parity first
# After codemap-lsp binary lands (Slice 1)
# integration test: stdio LSP client sends textDocument/diagnostic → assert Diagnostic[] shape
# Per-slice: bun run typecheck on touched src/ + lsp/Extension E2E (vscode-test) starts at Slice 2. Full recipe set at Slice 3.
These are committed to v1. Questions opened against them must justify against the linked decisions.
| # | Decision | Source |
|---|---|---|
| L.1 | Diagnostic-push shape, NOT request-handler shape. No textDocument/definition / references / hover types / workspace/symbol. tsserver dominates those for JS/TS users; competing is wasted surface. |
This plan § Shape; roadmap.md § Floors (no LSP engine) |
| L.2 | Moat-A discipline: every diagnostic must be the --format lsp-diagnostic rendering of a bundled recipe. Reviewer test: "is this finding queryable via query --recipe X?" If no recipe drives the diagnostic, it's rejected. |
Moat A |
| L.3 | Moat-B aligned: server consumes shipped engines (application/show-engine.ts, application/impact-engine.ts, application/watcher.ts); does NOT re-extract structure inside the protocol layer. |
Moat B |
| L.4 | Bun/Node binary, not Rust. Keep the toolchain consistent; reuse engines via direct imports. | Operational — repo is TS |
| L.5 | Server + extension is the unit, not either alone. Custom codemap/analysisComplete notification requires the paired extension to render status bar / tree views; LSP-only consumption (no extension) is reduced UX, not v1. |
This plan § Motivator |
| L.6 | No JS execution at index time survives — server speaks LSP, doesn't eval recipe SQL or extension-injected code. |
Floors "No JS execution at index time" |
| L.7 | Ships AFTER C.9 per cadence. Not a hard block — (d) ships valid diagnostics on existing recipe outputs without (b); but landing (b) first means untested-and-dead / unimported-exports diagnostics inherit cleaner inputs from day one. |
c9-plugin-layer.md § Shipping cadence; § What C.9 sharpens |
- Agents use MCP, not LSP — a request-handler shim wrapping
show/impactfor agent UX was a dead end. tsserverdominates standard pull requests (textDocument/definition,references,hover types,workspace/symbol) for JS/TS.- Valuable shape: diagnostic-push —
diagnostic(LSP 3.17 pull),code_action,code_lens,hover, customcodemap/analysisComplete— plus a paired VSCode extension. Recipes render asDiagnostic[](squigglies), not go-to-def. - Moat-A discipline: diagnostics are
--format lsp-diagnosticrenderings of bundled recipes; reviewer test: "is this finding queryable viaquery --recipe X?"
| Rev | Proposal | Outcome |
|---|---|---|
| v1 | Thin shim over show/impact engines; ship before C.9 | Rejected — assumed C.9 is_entry rides on LSP Location[] responses |
| v2 | Orthogonal to C.9; ship before C.9 | Correctly rejected request-handler shape; wrongly dropped diagnostic-push entirely |
| v2.5 | Defer until concrete consumer | Incomplete — conflated rejected shape with high-value diagnostic-push |
| v3 | Diagnostic-push server + VSCode extension; ships after C.9 | Current plan — server + extension is one unit (L.5) |
Implement: initialize, did_open, did_change, did_save, diagnostic (pull), code_action, code_lens, hover, custom codemap/analysisComplete.
Explicitly skip: definition, references, documentSymbol, workspace/symbol — tsserver covers these.
Diagnostic codes map 1:1 to recipe ids from --recipes-json. Paired extension: tree views, status bar via custom notification, settings for issue toggles + git ref scope.
Each gets a "Resolution" subsection below as it crystallises (mirrors c9-plugin-layer.md / research-note § 6 pattern).
- Q1 — Repo structure (flat vs monorepo). Add
lsp/+editors/vscode/to current flat layout (no workspaces; Option 1)? Convert to monorepo first (packages/codemap+packages/codemap-lsp+packages/codemap-vscode; Option 2)? Combine convert + (d) impl in one PR (Option 3)? Trade-offs in § Repo-structure tradeoffs below. - Q2 — LSP server framework.
vscode-languageserver(Microsoft official, well-documented)?vscode-jsonrpc(lower-level, more control)? Custom over stdio? Bias towardvscode-languageserverfor compatibility. - Q3 — Extension-to-server transport. Stdio (LSP convention)? Or skip LSP entirely and have extension call codemap MCP/HTTP directly? L.1 already locks LSP shape, so this is "stdio vs IPC" not "LSP yes/no" — bias toward stdio.
- Q4 — Which recipes become diagnostics in v1. Candidate list:
untested-and-dead,unimported-exports,components-touching-deprecated,boundary-violations(shipped PR #72),high-complexity-untested,deprecated-symbolscallers (need the call-site row fromcalls, not the symbol row fromsymbols). Ship all 6 in v1 or start narrow? - Q5 — Diagnostic severity mapping.
Errorforboundary-violations?Warningforuntested-and-dead/unimported-exports?Informationforhigh-complexity-untested/deprecated-symbolscallers? Per-recipe configurable viainitializationOptions? - Q6 — Hover provider scope. Hover on every indexed symbol with
signature+doc_comment+complexity+ caller-count? Or only on symbols that have at least one of those (avoid noise on plain locals)? Coverage % when available? - Q7 — Code lens scope. Fan-in count above functions? Complexity? Coverage? All three? Lens ON/OFF per kind via settings?
- Q8 — Custom notification shape.
codemap/analysisCompletepayload —total_issues+ per-recipe counts? Or richer structure? Must remain stable across versions (extension reads it). - Q9 — Settings / initializationOptions surface. Toggle each recipe ON/OFF (
issueTypes-style array)? Severity overrides?changedSincegit ref to scope diagnostics to PR-changed files? - Q10 — Auto-update / version-mismatch handling. Extension bundles a binary version; what if user has a different
codemapCLI installed globally? Warn? Use bundled? Use user's? Resolution chain (project-installed → bundled → globally-installed → download) needs to be specified. - Q11 — Marketplace publisher name.
stainless-code(matches GH org)? Other? One-time decision; renaming a publisher is hard. - Q12 — Open VSX (VSCodium / Cursor / Theia) parity. Publish to both VSCode Marketplace and Open VSX, or VSCode-only? Cursor users → likely yes for Open VSX.
Two paired components; engines stay shipped (no re-extraction).
┌─────────────────────────────────────────┐
│ codemap-lsp (stdio server) │
│ │
editor ──┤ vscode-languageserver / jsonrpc │
stdio │ │
│ ┌───────────────────────────────────┐ │
│ │ Diagnostic provider │ │
│ │ ↳ runs N recipes via shared │ │
│ │ query engine, emits │ │
│ │ Diagnostic[] per file URI │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ Hover provider │ │
│ │ ↳ findSymbolsByName + format │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ Code lens provider │ │
│ │ ↳ calls / complexity / coverage │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ Code action provider │ │
│ │ ↳ recipe.actions → quick-fix │ │
│ └───────────────────────────────────┘ │
│ ┌───────────────────────────────────┐ │
│ │ Watcher (chokidar via │ │
│ │ application/watcher.ts) │ │
│ │ ↳ on file change → reindex → │ │
│ │ re-run diagnostics → │ │
│ │ publishDiagnostics + emit │ │
│ │ codemap/analysisComplete │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
│
▼
shared engines (existing, unchanged)
LSP handlers implemented:
initialize/initialized/shutdown(lifecycle; readsinitializationOptionsfor issue toggles)did_open/did_change/did_save(file-change debouncing)textDocument/diagnostic(LSP 3.17 pull) +publishDiagnosticspush for live updatestextDocument/hovertextDocument/codeLenstextDocument/codeAction- Custom:
codemap/analysisCompletenotification (push to extension)
LSP handlers NOT implemented (per L.1):
textDocument/definitiontextDocument/referencestextDocument/documentSymbolworkspace/symbol
┌───────────────────────────────────────┐
│ codemap-vscode extension │
│ │
│ vscode-languageclient/node │
│ ↳ stdio → codemap-lsp binary │
│ │
│ Status bar (live issue count) │
│ ↳ fed by codemap/analysisComplete │
│ │
│ Tree views │
│ ↳ codemap.deadCode │
│ ↳ codemap.complexity │
│ ↳ codemap.boundaries │
│ │
│ Commands │
│ ↳ codemap.runRecipe │
│ ↳ codemap.audit │
│ ↳ codemap.refresh │
│ │
│ Settings UI │
│ ↳ recipe toggles │
│ ↳ severity overrides │
│ ↳ changedSince git ref │
│ │
│ Binary resolution │
│ ↳ user setting > local node_modules │
│ ↳ > PATH > auto-download │
└───────────────────────────────────────┘
Per tracer-bullets — ship one vertical slice end-to-end before expanding.
- Slice 1: minimum viable diagnostic push.
codemap-lspbinary that runs ONE recipe (untested-and-dead) and pushesDiagnostic[]for it. Manual VSCodelaunch.jsonconfig to run against the binary; verify squigglies appear. No extension, no install flow yet. - Slice 2: paired extension MVP. Minimal
codemap-vscodeextension that connects to the binary viavscode-languageclient/node, displays squigglies. F5-debug from VSCode; not yet packaged. - Slice 3: 6 recipes + severity mapping. Add the 5 other diagnostic-shaped recipes (Q4); resolve severity per Q5.
- Slice 4: hover + code lens + code actions. Wire the three remaining LSP capabilities (Q6, Q7); code actions consume
recipe.actionstemplate. - Slice 5: custom notification + extension UI.
codemap/analysisCompletenotification; status bar + tree views + commands in extension. - Slice 6: settings + binary resolution.
initializationOptions(Q9) + extension's binary resolver (Q10). - Slice 7: marketplace publish. First publish (one-time; see § Marketplace publishing below for the flow). Tag-triggered CI workflow.
- Slice 8: docs + agent rule update. Per
docs/README.mdRule 10, update bundled agent rule + skill in lockstep — agents need to know the LSP binary exists, what it surfaces, and that the diagnostic codes correspond to recipe IDs.
Cross-referenced by
c9-plugin-layer.mdQ5/Q8 (community plugin packaging) anddocs/roadmap.mdBacklog (structural decision tracker). All structural-conversion analysis lives here — other docs link, never restate.
- Single TS package at repo root:
name: "@stainless-code/codemap"inpackage.json;src/is the only TS source root;bun src/index.tsis the dev entry; published to npm as one package with onebin: codemap. - No workspace tooling. No
workspacesfield, nopackages/directory, notsconfig.references.tsdownbuilds a single bundle todist/. - Multiple consumer-facing surfaces already coexist in this flat structure: CLI (
codemap), MCP server (codemap mcp), HTTP server (codemap serve), watch mode (codemap watch). All ship as one binary; transport is acmd-*.tsdispatch, not a separate package.
Three upcoming surfaces would each ship a second binary or second publishable artifact:
- (d) LSP diagnostic-push server + paired VSCode extension —
codemap-lspBun/Node binary +codemap-vscodeextension package (published to VSCode Marketplace + Open VSX, NOT npm). - (b) C.9 community plugins — per c9-plugin-layer Q5/Q8, the plugin contract may want plugins as separate npm packages (e.g.
codemap-plugin-nextjs) so framework-specific knowledge lives outside core. - Docs site (Fumadocs / similar) — a React-based docs site rendering existing
docs/*.mdcontent, deployed to Vercel or similar. Fumadocs is multi-framework (Next.js / Astro / Vite-based: Tanstack Start / Waku / React Router); the canonical adapter for "read existing markdown without MDX rewrite" is@fumadocs/local-md(mirrorsfuma-nama/fumadocs/examples/next-local-md). Fumapress (fumapressCLI +@fumapress/core) is the May-2026 zero-config Waku-based variant — preview-oriented per its tagline, not yet the production path. Adds a secondpackage.json(deployable web artifact) but does NOT itself force monorepo conversion: the site lives as a flatwebsite/dir with its ownpackage.json, reading markdown from../docs/. Conversion only triggers if the site needs to import codemap's TS engines (live recipe runner, interactive schema explorer, WASM CLI demo).
Any one alone can ship in the current flat layout. Combinations start to strain it (especially (1) + (2), or (3) with engine-import requirements).
| Option | Cost | Benefit |
|---|---|---|
1: Stay flat — add lsp/ + editors/vscode/ dirs |
Zero refactor. Relative imports from lsp/ into src/application/* work today. One additional bin: { "codemap-lsp": "..." } in main package.json. Extension is its own package.json (different name, different version, published to VSCode Marketplace not npm — already independent of CLI versioning regardless of layout choice). |
Simplest path. No risk to existing code. Ships (d) without prerequisite work. Loses: independent versioning between CLI and LSP server (one changeset bumps both). Loses: clean package boundary if a third-party wants to consume engines as a library (no @stainless-code/codemap-core to import). |
| 2: Convert to monorepo first (separate refactor PR) | ~1-2 days of churn. Touches every import in src/, every test path, every doc reference (bun src/index.ts → bun packages/codemap-cli/src/index.ts or aliased), every script reference (scripts/*.ts), every changeset config (per-package). CI scripts updated. Risk surface unrelated to (d) value. Reviewer reaction to "refactor PR with no user-visible value" is generally negative. |
Independent versioning per package. Clean packages/codemap-core exposing engines. Ready for C.9 community plugins. Standard pattern (oxc, tsgo, biome, vitest). Bun workspaces + changesets handle locked-or-independent versioning natively. |
| 3: Convert as part of (d) impl | Bigger PR (refactor + new feature combined). Harder to review. | Convert once, justify once with the new packages it creates. Avoids the "refactor PR with no user-visible value" review pushback. |
| Tool | Layout | Why |
|---|---|---|
| knip (upstream) | Single npm package; VSCode extension lives in a completely different repo | Choice — extension maintainer is a different contributor; full repo-split rather than monorepo |
| oxc (upstream) | Monorepo (pnpm workspaces): napi/parser, napi/transform, napi/resolver, crates/oxc_* (Rust), editors/vscode |
Ships many tools (parser, formatter, linter, resolver) as separable packages — natural workspace fit |
| tsgo / typescript-go (upstream) | Monorepo (Go modules + npm packages) | Multi-binary + multi-language |
| biome (upstream) | Monorepo (pnpm workspaces): packages/@biomejs/biome, packages/@biomejs/js-api, editors/vscode, editors/intellij, crates/* (Rust core) |
Multiple language editors + Rust core + JS bindings |
| vitest (upstream) | Monorepo (pnpm workspaces): packages/vitest, packages/browser, packages/coverage-*, packages/vite-node, packages/ui |
Many separable concerns ship together |
Pattern: monorepo is dominant when a tool ships 3+ independently-publishable artifacts. Single-package wins when there's just one (knip).
For codemap, the artifact count grows from 1 (today: CLI) to:
- 2 after Fumadocs site deploys (CLI + docs site as deployable web artifact) OR after (d) ships (CLI + VSCode extension)
- 3 after both Fumadocs + (d) ship (CLI + docs site + VSCode extension)
- 4+ if (d) extracts
codemap-corefor the LSP server to import cleanly OR if the docs site needs engine imports - 5+ if C.9 community plugins ship as packages
Inflection point is roughly between 3 and 4 artifacts — Fumadocs by itself doesn't tip the scale, but Fumadocs + (d) does.
Convert (Option 2 or 3) when any of these triggers fire — not preemptively:
- C.9 community plugins ship as separate packages. Strong signal — community contributors expect to install
codemap-plugin-nextjs, not patch a directory in core. Workspace tooling makes this hygienic; flat layout fights it. - A user asks "I want to consume the engines as a library." Triggers extraction of
codemap-core. If the ask comes after (d) ships, extracting alongsidecodemap-lspjustifies the conversion. - A second consumer-facing distro ships (e.g.
codemap-serverlong-running daemon decoupled from CLI). Workspaces let it iterate independently. - Locked versioning across packages becomes painful with the hand-script approach in Option 1 (e.g. CLI bumps without LSP server changes still need a changeset entry for the LSP package — annoying enough times that the workspace tooling pays for itself).
- Docs site needs to import codemap source. Markdown-only Fumadocs site (using
@fumadocs/local-mdto read../docs/*.md) ships as a flatwebsite/dir — NOT a trigger by itself. Trigger fires only when the site adds a live recipe runner, an interactive schema explorer, a WASM CLI demo, or anything else that imports from codemap's TS source. Then workspace tooling becomes the cleanest path: extract@stainless-code/codemap-core, import from the website package.
Mirrors the doc's other "wait for two consumers / two asks" disciplines (roadmap.md § history table backlog, audit verdict thresholds).
- Option 1 if (d) ships before any of the five triggers above. (d) alone doesn't justify conversion — the VSCode extension is separately published anyway, and the LSP binary can be a second
binentry in the existingpackage.json. Markdown-only Fumadocs site (flatwebsite/dir) also doesn't trigger conversion. This is the recommended starting position. - Option 2 (separate refactor PR before (d) impl) if a community-plugin contributor is in flight when (d) starts, or if
codemap-coreextraction is asked for explicitly (e.g. docs site needs live runners). - Option 3 (convert as part of (d) impl) if Option 2's "refactor with no user-visible value" PR shape is unacceptable to reviewers.
- User-repo monorepo awareness (separate concept — discovering
pnpm-workspace.yamlin indexed projects). Tracked indocs/roadmap.mdBacklog "Monorepo / workspace awareness." - Splitting
templates/agents/into a separate package. Templates ship in the main codemap package viafiles: ["templates"]; no consumer signal for a separate package today. - VSCode-extension repo split (knip's pattern — separate repo). Out of scope; codemap's extension lives alongside core.
- Docs site dir-name choice (
website/vsapps/docs/vsdocs-site/). Bias towebsite/until conversion fires —apps/*implies workspaces (cohort norm signal);website/doesn't. Rename toapps/docs/only when actually converting.
One-time setup captured here so the (d) impl PR doesn't have to rediscover it. References: VSCode publishing docs, Open VSX docs.
- Azure DevOps organization at dev.azure.com (free; Microsoft account).
- Marketplace publisher at marketplace.visualstudio.com/manage — pick publisher ID per Q11. Publisher ID is in the marketplace URL forever.
- Personal Access Token (PAT) in Azure DevOps:
- User Settings → Personal Access Tokens → New Token
- Scope: Organization = "All accessible organizations"; Marketplace = ✅ Manage
- Max expiration 1 year (Microsoft enforces); calendar-reminder for renewal
- Open VSX namespace at open-vsx.org per Q12 — separate token; same
.vsixfile works on both marketplaces.
package.json— must includename,displayName,description,version,publisher,repository.directory,engines.vscode,categories,activationEvents,main,contributesREADME.md— becomes the marketplace pageLICENSECHANGELOG.md— shows in marketplace "Changelog" tabicon.png— 128×128 minimum (no icon → rejected).vscodeignore— excludesrc/,node_modules/,*.config.ts, source maps, etc. (without it, extension ships with bundlednode_modules≈ 100MB)
cd editors/vscode
bun run build # produce dist/extension.js
bunx vsce package # creates codemap-vscode-X.Y.Z.vsix locally — INSPECT before publish
bunx vsce publish # uploads to VSCode Marketplace (live in ~5 min)
bunx ovsx publish *.vsix # uploads to Open VSX (Cursor / VSCodium / Theia users)Tag-triggered (e.g. vscode-v0.1.0 → git tag vscode-v0.1.0 && git push --tags):
# .github/workflows/publish-vscode.yml
on:
push:
tags: ["vscode-v*"]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- working-directory: editors/vscode
run: bun run build
- working-directory: editors/vscode
run: bunx vsce publish -p ${{ secrets.VSCE_PAT }}
- working-directory: editors/vscode
run: bunx ovsx publish -p ${{ secrets.OVSX_PAT }}GH secrets: VSCE_PAT, OVSX_PAT.
Two patterns; pick one:
- Locked (extension version always matches CLI) → simpler users; one mental model; needs hand-bump or script in changeset hook
- Independent → extension iterates separately; needs "this extension version requires CLI ≥ X" docs
Bias: locked. Relevant to Q1 — monorepo workspaces makes locked versioning trivial via changesets; flat layout needs a hand-script.
- PAT expiration (1 year max, Microsoft enforces). Calendar reminder.
- First publish review (24-48h gate; subsequent versions are instant).
- Extensions can't be unpublished — only deprecated + hidden. Pick the name carefully (Q11).
engines.vscodetoo high locks out old VSCode users for no reason. Use^1.96.0-ish, not the latest.- Cursor compatibility — Cursor uses Open VSX by default; skipping Open VSX (Q12 = no) means Cursor users can't install codemap without manual
.vsixinstall.
- Unit: each LSP handler (diagnostic, hover, code lens, code action) —
*.test.tsper touched file (perverify-after-each-step). - Integration: spin up the LSP server in a child process; send LSP messages over stdio; assert response shapes.
tower-lspstyle integration test (Bun side: roll our own; small surface). - Extension:
vscode-test(Microsoft's E2E test framework for extensions) — launch a VSCode instance with the extension loaded, open a fixture project, assert squigglies appear. - Golden fixture:
fixtures/golden/lsp-fixture/containing project that exercises each diagnostic-emitting recipe. Expected diagnostic count + locations per recipe codified inscenarios.json.
| Item | Mitigation |
|---|---|
| Non-goal: standard LSP request handlers (definition / references). | Per L.1; rejected. |
| Non-goal: verdict-shaped CLI verb fronting the LSP server. | Per L.2; recipes drive output. The LSP binary is a transport, not a new verb. |
| Non-goal: runtime tracing / live execution data. | Per Floor "No runtime tracing". Static recipes only. |
| Risk: XL surface (~3-4k LoC) — slip risk. | Slice cadence per § Implementation slices. Each slice is shippable (extension MVP works against one recipe before adding 5 more). If the plan stalls, partial slices still deliver. |
| Risk: marketplace approval delays first publish. | First publish = 24-48h review; plan slice 7 explicitly. Subsequent versions are instant. |
| Risk: extension vs CLI version drift. | Locked versioning (per § Versioning); changeset hook bumps both. Q1 (monorepo) makes this trivial; flat layout needs a small script. |
Risk: false-positive squigglies on untested-and-dead for framework files. |
(b) C.9 lands first per § 5 cadence; reduces FP class. Until then, extension settings let users disable specific diagnostic codes (issueTypes array). |
| Risk: plan abandoned mid-iteration. | Per docs/README.md Rule 8, close as Status: Rejected (YYYY-MM-DD) — <reason>. Design surface captured either way. Engines stay as-is; nothing extracted. |
| Risk: binary size / startup time on user machines. | Bun-based binary is small (~10MB stripped); VSCode-bundled binary distribution (one binary per platform; download lazily) keeps install footprint thin. Cold-start sub-100ms still applies on the LSP did_open path. |
docs/plans/c9-plugin-layer.md— C.9 plan (lands before this plan; sharpens diagnostic precision via entry-point awareness)docs/architecture.md— engine reference (application/show-engine.ts,application/impact-engine.ts,application/watcher.ts)docs/golden-queries.md— golden-query test pattern (LSP fixture follows the same shape)docs/README.mdRule 3 — plan-file convention (this file's location)docs/README.mdRule 10 — agent rule lockstep update (Slice 8).agents/rules/tracer-bullets.md— slice cadence- LSP libraries:
vscode-languageserver,vscode-languageclient,vscode-test(E2E),vsce+ovsx(publishing)