Install the VS Code extension from the npm package
unstaged · index → working-tree · GPT-6 (Codex)
0%0% claimed verified
The npm package bundles its tested VSIX and provides an explicit VS Code installation command without GitHub or Marketplace access. Optional Marketplace installation uses the same extension identity after publication. Packaging is part of prepack; publishing remains an explicit separate action requiring publisher access. Offline npm-to-editor installation was checked in an isolated VS Code profile; no release or normal-profile installation occurred.
Build and allowlist the extension artifact during npm packing so the package works outside this checkout. Keep generated bytes out of source control and make publishing an explicit operation on the reviewed VSIX.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -45,3 +45,7 @@next-env.d.ts
4545
4646# downloadable snapshots of this repo, served by the dev server
4747/public/*.zip
48+
49+# npm-bundled extension artifacts (rebuilt by prepack)
50+/dist/whymark-vscode.vsix
51+/dist/vscode-extension.json
README.md
+16−0read-only10%
intentunspecifiedconfidence unknown
Distinguish the working npm installation path from a Marketplace listing that still needs publisher access and publication. Document authentication and release boundaries without claiming an unpublished extension is available.
381+`spink-dev.whymark` from the Marketplace instead. See the
382+[release guide](extensions/vscode/PUBLISHING.md) for publisher setup and separate
383+npm/Marketplace releases. These commands are implemented locally; neither updated
384+package has been published by this task.
dist/whymark.mjs
+118−42read-only10%
generatedunspecifiedconfidence unknown
Build and allowlist the extension artifact during npm packing so the package works outside this checkout. Keep generated bytes out of source control and make publishing an explicit operation on the reviewed VSIX.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -2,8 +2,8 @@
22/* generated by npm run build:cli — do not edit */
33
44// src/cli/whymark.ts
5−import { existsSync asexistsSync3, mkdirSync as mkdirSync3, readFileSync asreadFileSync6, writeFileSync as writeFileSync4 } from"node:fs";
@@ -2466,39 +2466,94 @@async function qualityCommand(positionals, options) {
24662466 });
24672467}
24682468
2469−// src/lib/skill/install.ts
2470−import { existsSync as existsSync2, lstatSync as lstatSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync5, realpathSync as realpathSync4, writeFileSync as writeFileSync3 } from"node:fs";
2471−import { dirname, join asjoin4, relativeasrelative5, resolve as resolve5,sep as sep3 } from"node:path";
2469+// src/lib/vscode/install.ts
2470+import { spawnSync as spawnSync3 } from"node:child_process";
2471+import { accessSync, constants, existsSync as existsSync2, readFileSync as readFileSync5 } from"node:fs";
2472+import { createHash as createHash2 } from"node:crypto";
2473+import { delimiter, dirname,isAbsolute, joinasjoin4, resolve as resolve5} from"node:path";
2488+for (const root of [process.env.LOCALAPPDATA &&join4(process.env.LOCALAPPDATA, "Programs"), process.env.ProgramFiles]) if (root) candidates.push(join4(root, "Microsoft VS Code", "Code.exe"));
2489+ }
2490+const command = candidates.find(executable);
2491+if (!command) thrownewError("VS Code CLI not found. Install VS Code and add 'code' to PATH, or pass --code <path-to-code>.");
2503+if (!existsSync2(metadataPath)) thrownewError("Extension bundle missing. In a source checkout run npm run package:vscode; otherwise reinstall the whymark npm package.");
2518+if (result.error) thrownewError(`VS Code installation could not complete: ${result.error.message}`);
2519+if (result.status !==0) thrownewError(`VS Code installation failed (${result.signal??result.status}).${options.marketplace?" The extension must be published before Marketplace installation works.":""}`);
2520+ process.stdout.write(`Installed ${metadata.id}. Open the Command Palette and search for Whymark.
2521+`);
2522+}
2523+
2524+// src/lib/skill/install.ts
2525+import { existsSync as existsSync3, lstatSync as lstatSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync6, realpathSync as realpathSync4, writeFileSync as writeFileSync3 } from"node:fs";
2526+import { dirname as dirname2, join as join5, relative as relative5, resolve as resolve6, sep as sep3 } from"node:path";
2527+import { homedir as homedir2 } from"node:os";
Distinguish the working npm installation path from a Marketplace listing that still needs publisher access and publication. Document authentication and release boundaries without claiming an unpublished extension is available.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -2,6 +2,26 @@
22
33Read AI-written changes with the reasons, sources and verification beside the code — directly in VS Code, without starting a web server.
44
5+## Install from npm
6+
7+After the next npm release ships this command:
8+
9+```sh
10+npxwhymark@latestvscodeinstall
11+```
12+
13+It installs the extension bundled in the npm package through VS Code's CLI, with
14+no GitHub access or Marketplace dependency. VS Code must already be installed.
15+Use `--dry-run` to preview or `--code /path/to/code` for a custom installation.
16+Installation is explicit; installing the npm package alone does not change VS Code.
17+The VSIX version is tied to that npm release. Updates through npm require rerunning
18+the command; the installer does not force a downgrade of a newer installed extension.
19+
20+After Marketplace publication, search for **Whymark** by publisher **spink-dev**,
21+or run `npx whymark vscode install --marketplace`. That route installs the published
22+Marketplace version instead of the bundled version. Publisher availability and
23+publication are not yet confirmed.
24+
525## Install locally
626
727From the repository root:
package.json
+10−7read-only10%
intentunspecifiedconfidence unknown
Build and allowlist the extension artifact during npm packing so the package works outside this checkout. Keep generated bytes out of source control and make publishing an explicit operation on the reviewed VSIX.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -1,7 +1,7 @@
11{
22"name": "whymark",
33"version": "0.3.0",
4−"description": "whymark — a file format and reviewer for reading AI-written code changes with the reasoning, sources, and verification attached to each line.",
4+"description": "whymark \u2014 a file format and reviewer for reading AI-written code changes with the reasoning, sources, and verification attached to each line.",
55"author": "Samuel Spink",
66"license": "MIT",
77"bin": {
@@ -14,7 +14,9 @@
1414"spec/whymark-v1.md",
1515"README.md",
1616"LICENSE",
17−".agents/skills/whymark/SKILL.md"
17+".agents/skills/whymark/SKILL.md",
18+"dist/whymark-vscode.vsix",
19+"dist/vscode-extension.json"
1820 ],
1921"engines": {
2022"node": "22.x"
@@ -37,20 +39,21 @@
3739"scripts": {
3840"dev": "next dev --port 43917",
3941"build": "next build",
40−"build:cli": "esbuild src/cli/whymark.ts --bundle --platform=node --format=esm --outfile=dist/whymark.mjs --external:yaml --legal-comments=none --banner:js='/* generated by npm run build:cli — do not edit */'",
42+"build:cli": "esbuild src/cli/whymark.ts --bundle --platform=node --format=esm --outfile=dist/whymark.mjs --external:yaml --legal-comments=none --banner:js='/* generated by npm run build:cli \u2014 do not edit */'",
4143"prepublishOnly": "npm run build:cli",
4244"start": "next start --port 43917",
4345"lint": "eslint",
4446"typecheck": "tsc --noEmit",
45−"test": "npm run build:cli && vitest run",
47+"test": "npm run build:cli && npm run package:vscode && vitest run",
4648"test:watch": "vitest",
4749"test:ui": "node tests/e2e/viewer.mjs",
4850"whymark": "tsx src/cli/whymark.ts",
49−"prepack": "npm run build:cli",
51+"prepack": "npm run build:cli && npm run package:vscode",
Distinguish the working npm installation path from a Marketplace listing that still needs publisher access and publication. Document authentication and release boundaries without claiming an unpublished extension is available.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -41,3 +41,13 @@Review paths and webview messages are untrusted. Gate edits and Git on workspace
4141
4242## Open questions
4343None blocking. Initial extension targets desktop/remote filesystem workspaces; compare refresh is explicit and review source changes refresh automatically.
44+
45+## Distribution follow-up
46+
47+Bundle the tested VSIX plus identity/version/SHA-256 metadata in the npm tarball.
48+Add an explicit `whymark vscode install` command with a preview, launcher override,
49+isolated profile paths and optional Marketplace ID installation. Build the VSIX
50+in prepack and verify a real offline tarball consumer can install it into a clean
51+VS Code profile. Provide an explicit publish command for the already-tested VSIX
52+and a publisher/authentication guide. Publication and publisher provisioning are
53+outside this implementation request.
specs/002-vscode-extension/verification.md
+21−0read-only10%
intentunspecifiedconfidence unknown
Distinguish the working npm installation path from a Marketplace listing that still needs publisher access and publication. Document authentication and release boundaries without claiming an unpublished extension is available.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -61,3 +61,24 @@workspace host, branch/commit input dialogs and Save As dialog interaction were
6161not exercised. API typing uses 1.96; installed-host testing uses 1.138. The save
6262operation behind the dialog is tested with real VS Code APIs. The desktop/remote
6363filesystem extension does not support browser-only virtual workspaces.
64+
65+## npm / Marketplace distribution follow-up
66+
67+The npm file allowlist now includes the built VSIX and identity/digest metadata;
68+`prepack` rebuilds them. `whymark vscode install` invokes the editor CLI with separate
69+arguments and checks the bundled digest before installation. `--dry-run` performs
70+no installation; `--marketplace` selects the extension ID for use after publication.
71+The explicit `publish:vscode` script publishes an already-built VSIX only when run.
72+
73+Verification: 106 tests / 15 files, typecheck and lint passed on Node 22. An actual
74+npm tarball and local yaml tarball were installed offline into a clean consumer;
75+that consumer's CLI installed the bundled VSIX into an isolated VS Code profile,
76+and VS Code listed `spink-dev.whymark@0.1.0`. The normal editor profile was unchanged.
77+Unit checks cover argument boundaries, paths with spaces/metacharacters, preview,
78+missing launchers, nonzero editor exits, Marketplace target selection and corrupt
79+bundled bytes. Windows launcher behavior is implemented but not runtime-tested.
80+
81+The distribution changes were inspected in separate source and behavior passes.
82+Existing staged changes from the extension implementation were preserved. Publisher
83+ownership, authenticated Marketplace publication and end-user Marketplace download
84+are not verified. Neither npm nor Marketplace was published.
src/cli/help.ts
+11−0read-only10%
intentunspecifiedconfidence unknown
Expose editor installation as a discoverable explicit CLI action; npm installation alone must not modify editor extensions.
Verify the actual packed contents and installer boundary: missing launchers, failed processes, corrupted VSIX bytes, argument handling and previews must not silently look like successful installation.
Distinguish the working npm installation path from a Marketplace listing that still needs publisher access and publication. Document authentication and release boundaries without claiming an unpublished extension is available.
specs/002-vscode-extension/PLAN.md
claimed passedcommand
$ npm test
exit 0 in 5.9s
@@ -0,0 +1,70 @@
1+# Distribution and release
2+
3+Two independent channels are supported. The npm package carries a VSIX built during
4+`prepack`; its explicit `whymark vscode install` command checks the packaged digest
5+and invokes the installed VS Code CLI. The digest detects corruption; it is not a
6+publisher signature. No postinstall hook installs extensions.
7+
8+The extension identity is `spink-dev.whymark`, as declared in the extension manifest.
9+Ownership/availability of that publisher must be confirmed before publishing. A
10+private GitHub repository can remain private: consumers install the npm tarball or
11+Marketplace artifact without cloning it. Both public releases expose their packaged
12+code and documentation, even when the source repository stays private.
28+`package:vscode` builds the extension and creates the same VSIX in
29+`.artifacts/whymark-vscode.vsix` and `dist/whymark-vscode.vsix`. It also writes
30+`dist/vscode-extension.json` with identity, version and digest. The npm file allowlist
31+includes both dist files; `prepack` regenerates them so fresh checkouts can publish.
32+Check the tarball before releasing. Version the npm CLI and extension independently;
33+bump `extensions/vscode/package.json` for each Marketplace release, and the root
34+package version for npm releases. Do not reuse an already-published version.
35+
36+## Marketplace setup (one-time)
37+
38+1. Sign in to the [publisher management page](https://marketplace.visualstudio.com/manage).
39+2. Create or obtain access to the publisher ID in the manifest. If `spink-dev` is not
40+ yours, change the manifest publisher before rebuilding and testing both artifacts.
41+3. Configure publishing authentication. Current VS Code guidance recommends Microsoft
42+ Entra ID with workload identity federation for automation. Authorized publishers
43+ can also upload the tested VSIX through the management page.
44+
45+See the [official publishing guide](https://code.visualstudio.com/api/working-with-extensions/publishing-extension).
46+It states that global Azure DevOps PATs retire on December 1, 2026; do not establish
47+a new long-lived PAT-based automation pipeline. No credentials belong in this repo
48+or npm package.
49+
50+## Explicit publication
51+
52+Only after release approval, publish the tested VSIX without rebuilding it:
53+
54+```sh
55+npmrunpublish:vscode----azure-credential
56+```
57+
58+This delegates to `vsce publish --packagePath .artifacts/whymark-vscode.vsix` and
59+requires configured publisher access. Alternatively upload that VSIX in publisher
60+management. This repository does not provision publisher accounts or identities.
61+
62+Publish the npm package separately with `npm publish` after reviewing its packed
63+contents; its prepack lifecycle rebuilds the bundled extension. Neither publication
64+runs as part of normal builds, tests, packing, or installation. No release was made
65+while implementing these commands.
66+
67+After Marketplace publication users can install from the editor UI, run
68+`code --install-extension spink-dev.whymark`, or use
69+`npx whymark vscode install --marketplace`. Marketplace and npm have independent
70+release timing; bundled installation always uses the artifact shipped with npm.
extensions/vscode/scripts/package.mjs
+14−0read-only10%
intentunspecifiedconfidence unknown
Build and allowlist the extension artifact during npm packing so the package works outside this checkout. Keep generated bytes out of source control and make publishing an explicit operation on the reviewed VSIX.
Users should not need the private Git repository to install the editor integration. Resolve the shipped artifact from the npm package, verify its digest, and invoke the editor using separate arguments so whitespace and shell characters remain literal. Preview and explicit profile paths keep installation controllable.
23+if (!explicit && process.platform ==="darwin") candidates.push("/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", join(homedir(), "Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"));
24+if (!explicit && process.platform ==="win32") for (const root of [process.env.LOCALAPPDATA &&join(process.env.LOCALAPPDATA, "Programs"), process.env.ProgramFiles]) if (root) candidates.push(join(root, "Microsoft VS Code", "Code.exe"));
25+const command = candidates.find(executable);
26+if (!command) thrownewError("VS Code CLI not found. Install VS Code and add 'code' to PATH, or pass --code <path-to-code>.");
27+// Windows batch launchers need a shell. Invoke their native CLI directly instead,
28+// preserving paths as arguments rather than interpolating them into cmd.exe.
41+if (!existsSync(metadataPath)) thrownewError("Extension bundle missing. In a source checkout run npm run package:vscode; otherwise reinstall the whymark npm package.");
55+if (result.error) thrownewError(`VS Code installation could not complete: ${result.error.message}`);
56+if (result.status !==0) thrownewError(`VS Code installation failed (${result.signal??result.status}).${options.marketplace?" The extension must be published before Marketplace installation works.":""}`);
57+ process.stdout.write(`Installed ${metadata.id}. Open the Command Palette and search for Whymark.\n`);
58+}
tests/vscode-install.test.ts
+32−0read-only10%
testunspecifiedconfidence unknown
Verify the actual packed contents and installer boundary: missing launchers, failed processes, corrupted VSIX bytes, argument handling and previews must not silently look like successful installation.
Build and allowlist the extension artifact during npm packing so the package works outside this checkout. Keep generated bytes out of source control and make publishing an explicit operation on the reviewed VSIX.
$ npm test