feat(vscode): Phase 1 - skill bundle + Marketplace-ready extension shell#312
feat(vscode): Phase 1 - skill bundle + Marketplace-ready extension shell#312PhillyUrbs wants to merge 4 commits into
Conversation
Greptile SummaryThis PR introduces Phase 1 of the VS Code extension: a new
Confidence Score: 4/5Safe to merge with one wiring fix: the vscode-specific placeholder entry in utils.js is bypassed, so {{model}} renders as 'the model' instead of 'Copilot' in all generated skill content. The placeholder lookup for the vscode provider resolves to PROVIDER_PLACEHOLDERS['agents'] (model: 'the model') rather than the newly-added PROVIDER_PLACEHOLDERS['vscode'] (model: 'Copilot') because placeholderProvider: 'agents' takes precedence in factory.js. Every {{model}} occurrence in the generated vscode SKILL.md and reference files will produce a generic model reference rather than the Copilot-specific one. The rest of the build pipeline, filtering logic, async I/O, and test coverage are solid. scripts/lib/utils.js and scripts/lib/transformers/providers.js — the PROVIDER_PLACEHOLDERS['vscode'] entry and the placeholderProvider value are inconsistent with each other. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[bun run build] --> B[readSourceFiles: skill/]
B --> C{For each PROVIDER}
C --> D[createTransformer config]
D --> E[Transform skills → dist/provider/]
E --> C
C -->|vscode provider| F[dist/vscode/.github/skills/impeccable/]
C -->|done| G[buildVSCodeExtension]
F --> G
G --> H[Copy skills/ from .github/skills/]
G --> I[Write package.json]
G --> J[Write extension.js]
G --> K[Copy LICENSE + README.md]
G --> L[Write .vscodeignore]
H & I & J & K & L --> M[dist/vscode/ — VSIX-ready]
C -->|all except buildVSCodeExtension flag| N[assembleUniversal]
N --> O[dist/universal/]
O --> P[universal.zip]
subgraph UserInstall [User runs: Impeccable: Install Skill to Workspace]
Q[installSkill called] --> R[Copy dist/vscode/skills/impeccable → .github/skills/impeccable/]
R --> S[Read SKILL.md from installed location]
S --> T[Read existing .github/copilot-instructions.md]
T --> U{Has IMPECCABLE block?}
U -->|Yes| V[Replace managed block only]
U -->|No / empty| W[Append or create managed block]
V & W --> X[Write merged copilot-instructions.md]
end
M --> Q
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[bun run build] --> B[readSourceFiles: skill/]
B --> C{For each PROVIDER}
C --> D[createTransformer config]
D --> E[Transform skills → dist/provider/]
E --> C
C -->|vscode provider| F[dist/vscode/.github/skills/impeccable/]
C -->|done| G[buildVSCodeExtension]
F --> G
G --> H[Copy skills/ from .github/skills/]
G --> I[Write package.json]
G --> J[Write extension.js]
G --> K[Copy LICENSE + README.md]
G --> L[Write .vscodeignore]
H & I & J & K & L --> M[dist/vscode/ — VSIX-ready]
C -->|all except buildVSCodeExtension flag| N[assembleUniversal]
N --> O[dist/universal/]
O --> P[universal.zip]
subgraph UserInstall [User runs: Impeccable: Install Skill to Workspace]
Q[installSkill called] --> R[Copy dist/vscode/skills/impeccable → .github/skills/impeccable/]
R --> S[Read SKILL.md from installed location]
S --> T[Read existing .github/copilot-instructions.md]
T --> U{Has IMPECCABLE block?}
U -->|Yes| V[Replace managed block only]
U -->|No / empty| W[Append or create managed block]
V & W --> X[Write merged copilot-instructions.md]
end
M --> Q
Reviews (4): Last reviewed commit: "fix(vscode): preserve user instructions,..." | Re-trigger Greptile |
Bugbot finding on PR pbakaus#312: SKILL.md and reference/*.md baked .vscode-ext/skills/impeccable/scripts/... paths into setup steps, but the install command only wrote SKILL.md to the workspace and never copied the scripts or reference files. Setup steps that run 'node .vscode-ext/skills/...' or link reference/*.md siblings failed with ENOENT. - Provider configDir: .vscode-ext -> .github, so {{scripts_path}} bakes in as .github/skills/impeccable/scripts, matching the layout the install command materializes in the workspace. - buildVSCodeExtension copies from .github/skills/ instead of .vscode-ext/skills/; .vscodeignore updated to exclude .github/ staging. - extension.js install command copies the entire skills/impeccable/ tree (SKILL.md + reference/ + scripts/) into .github/skills/impeccable/ then writes .github/copilot-instructions.md mirroring SKILL.md so Copilot Chat auto-loads it. require('vscode') is lazy inside activate() so installSkill is unit-testable. - Release-mode sync filter (.codex/.vscode-ext exclusion) switched to filter by the buildVSCodeExtension flag; the configDir-name filter would no longer exclude vscode now that its configDir is .github, which would overwrite the github provider's tracked harness output. - Tests: assert installed paths match what SKILL.md references, simulate installSkill against a tmp workspace, assert SKILL.md + reference/ + scripts/ + copilot-instructions.md all land in .github/, assert prior installs are replaced not merged, assert no .vscode-ext/ strings remain in bundled markdown.
|
Addressed the Cursor Bugbot finding ("Bundled skill scripts path mismatch") in 68edc70. Root cause: the install command only wrote SKILL.md into the workspace's Fix (kept inside Phase 1 scope):
Test coverage added: simulates I don't have Bun on this machine so the local build + test gate didn't run; relying on CI here. Happy to add a screenshot of the install command running against a real workspace if useful. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 68edc70. Configure here.
… tests Addresses the remaining Cursor Bugbot + Greptile review findings on PR pbakaus#312: - Silent overwrite (Bugbot Medium + Greptile P1): installSkill no longer clobbers .github/copilot-instructions.md. The skill is written into an IMPECCABLE:BEGIN/END managed block; existing user content is preserved (appended above the block on first install, block replaced in place on re-install). New mergeInstructions() helper is pure + exported for unit testing. - Core tests require missing build (Bugbot High): tests/vscode-extension.test.js now builds dist/vscode in a guarded beforeAll when extension.js is absent, so the core suite no longer assumes the Build step ran first. No CI YAML change needed. - Synchronous file I/O (Greptile P2): installSkill and its helpers use fs.promises throughout; activate() awaits the command. Extension host event loop is no longer blocked. - engines regex (Greptile P2): VSCODE_ENGINES_MIN_1_95 now also accepts 2.x+ (^2.0.0) while still rejecting <1.95. Tests added: preserves pre-existing instructions, idempotent re-install (single managed block), mergeInstructions unit matrix (empty/blockless/prior-block).
|
Worked through the rest of the Bugbot + Greptile review in c6d49c5. Summary of each finding and how it's addressed: 1. Path mismatch (Bugbot High, original 2. Core tests require missing build (Bugbot High) - real: CI runs 3. Silent overwrite of 4. Synchronous file I/O blocks the extension host (Greptile P2) - 5. engines regex rejects New test coverage: preserves pre-existing instructions, idempotent re-install (asserts a single managed block after two installs), and a I verified the generated |
Bugbot finding on PR pbakaus#312: SKILL.md and reference/*.md baked .vscode-ext/skills/impeccable/scripts/... paths into setup steps, but the install command only wrote SKILL.md to the workspace and never copied the scripts or reference files. Setup steps that run 'node .vscode-ext/skills/...' or link reference/*.md siblings failed with ENOENT. - Provider configDir: .vscode-ext -> .github, so {{scripts_path}} bakes in as .github/skills/impeccable/scripts, matching the layout the install command materializes in the workspace. - buildVSCodeExtension copies from .github/skills/ instead of .vscode-ext/skills/; .vscodeignore updated to exclude .github/ staging. - extension.js install command copies the entire skills/impeccable/ tree (SKILL.md + reference/ + scripts/) into .github/skills/impeccable/ then writes .github/copilot-instructions.md mirroring SKILL.md so Copilot Chat auto-loads it. require('vscode') is lazy inside activate() so installSkill is unit-testable. - Release-mode sync filter (.codex/.vscode-ext exclusion) switched to filter by the buildVSCodeExtension flag; the configDir-name filter would no longer exclude vscode now that its configDir is .github, which would overwrite the github provider's tracked harness output. - Tests: assert installed paths match what SKILL.md references, simulate installSkill against a tmp workspace, assert SKILL.md + reference/ + scripts/ + copilot-instructions.md all land in .github/, assert prior installs are replaced not merged, assert no .vscode-ext/ strings remain in bundled markdown.
… tests Addresses the remaining Cursor Bugbot + Greptile review findings on PR pbakaus#312: - Silent overwrite (Bugbot Medium + Greptile P1): installSkill no longer clobbers .github/copilot-instructions.md. The skill is written into an IMPECCABLE:BEGIN/END managed block; existing user content is preserved (appended above the block on first install, block replaced in place on re-install). New mergeInstructions() helper is pure + exported for unit testing. - Core tests require missing build (Bugbot High): tests/vscode-extension.test.js now builds dist/vscode in a guarded beforeAll when extension.js is absent, so the core suite no longer assumes the Build step ran first. No CI YAML change needed. - Synchronous file I/O (Greptile P2): installSkill and its helpers use fs.promises throughout; activate() awaits the command. Extension host event loop is no longer blocked. - engines regex (Greptile P2): VSCODE_ENGINES_MIN_1_95 now also accepts 2.x+ (^2.0.0) while still rejecting <1.95. Tests added: preserves pre-existing instructions, idempotent re-install (single managed block), mergeInstructions unit matrix (empty/blockless/prior-block).
c6d49c5 to
ca56d83
Compare

Phase 1 of the VS Code extension plan in #311: a new
vscodeprovider that emits a Marketplace-packageable extension shell from the same transformer factory as the other harnesses.Closes nothing yet - leaves #311 open for Phases 2-4.
What's in this PR
8 files, no behavior change for existing providers:
scripts/lib/transformers/providers.js- adds thevscodeprovider entry. Uses configDir.vscode-extfor the harness folder name; the literal.vscodeis reserved for workspace settings.scripts/lib/transformers/index.js- exports the new transformer.scripts/build.js- wires the vscode provider through the existing factory; emitsdist/vscode/withpackage.json,extension.js,skills/impeccable/SKILL.md+reference/*.md,LICENSE,README.md,.vscodeignore.scripts/lib/utils.js,scripts/test-suites.mjs- small wiring.tests/vscode-extension.test.js- asserts the emitted extension shape (publisher, name, main, engines, bundled skill files).package.json- addsbuild:extension:vscodescript that just routes toscripts/build.js.AGENTS.md- one-line addition ofvscodeto the Generated Provider Output Policy list.Generated extension shape
dist/vscode/:package.json- publisherpbakaus, nameimpeccable, displayNameImpeccable, engines.vscode^1.95.0, categories["Chat", "AI"], licenseApache-2.0, activationEvents["onStartupFinished"], main./extension.js.extension.js- minimal CommonJS entrypoint. Registers the bundled SKILL.md so Copilot Chat picks it up; top-of-file comment documents the API choice for the targeted engines version.skills/impeccable/SKILL.md+reference/*.md- same transform output the github provider produces.LICENSE,README.md,.vscodeignore.Verification
Build + test was run by the coding agent on the original PR in the PhillyUrbs fork (PhillyUrbs#1). After rebasing onto current
main, the changes were re-pushed - the rebase was conflict-free and none of the 7 intervening upstream commits touch the Phase 1 files. I'll let this PR's CI re-runbun run buildandbun run testas the live verification; happy to attach local logs if useful.I also smoke-tested the built VSIX locally in VS Code Insiders - extension loads cleanly and
/impeccableshows up in Copilot Chat.Confirmed NOT touched
Per the issue's "no behavior fork" principle:
cli/engine/detect-antipatterns.mjsand the rest ofcli/engine/.github/hooks/extension/site/,functions/plugin/and any tracked.claude/,.cursor/,.codex/etc. harness foldersDeferred to later phases
Phases 2-4 from #311 are intentionally out of scope here:
vscode.DiagnosticCollectionprovider, populated on save, honoring.impeccable/config.jsonand inline<!-- impeccable-disable -->comments.workspace.onWillSaveTextDocument, matching the Cursorhook-before-edit.mjsconsent model. Off by default.vscode.lm.registerTool), command-palette wrappers for high-traffic sub-commands, and anImpeccable: Initcommand.Notes for review
pbakaus.impeccable+ display nameImpeccable; happy to change either before publish.^1.95.0(Copilot Chat APIs stable). Lower if you want broader reach.icons/or generate a fresh one before publish.scripts/release.mjspattern from Chrome can be extended forvsce publish.Refs #311.
Note
Medium Risk
New generated extension and workspace file writes on install, but existing providers are gated by flags and covered by integration tests; no changes to detector/CLI runtime.
Overview
Adds a
vscodeprovider and build step that emits a VSIX-ready package atdist/vscode/(documented in AGENTS.md as separate from root harness folders).buildVSCodeExtensionwrites the extension manifest, generatedextension.js, Marketplace README/LICENSE, and copies transformed skills from staging.github/skills/intoskills/. Theimpeccable.installSkillcommand installs the full skill tree under.github/skills/impeccable/and merges SKILL.md into a managed block in.github/copilot-instructions.md(preserving user content outside the markers).The vscode provider uses
configDir: '.github'so{{scripts_path}}resolves to workspace paths the install step creates;buildVSCodeExtension: truekeeps it out of the universal zip and root harness sync (avoiding collision with the GitHub Copilot provider).package.jsonaddsbuild:extension:vscode; core CI includestests/vscode-extension.test.jsfor package layout, path baking, and install/merge idempotency.Reviewed by Cursor Bugbot for commit ca56d83. Bugbot is set up for automated code reviews on this repo. Configure here.