diff --git a/openspec/changes/cross-harness-plugin-installer/design.md b/openspec/changes/cross-harness-plugin-installer/design.md index 9936d9f..99e53e5 100644 --- a/openspec/changes/cross-harness-plugin-installer/design.md +++ b/openspec/changes/cross-harness-plugin-installer/design.md @@ -2,9 +2,9 @@ ## Architecture -The cross-harness plugin installer now follows a **shared core + generated native artifacts + Pi package** architecture. The source tree keeps one canonical skill bundle and one shared installer/runtime package. Claude, Codex, and Antigravity plugin directories are generated into `dist/` from committed templates; they are no longer workspace packages under `packages/`. Pi remains a real package because Pi installs packages directly. +The cross-harness plugin installer follows a **shared core + GitHub-root plugin + Pi package** architecture. The source tree keeps one canonical skill bundle at the repository root and one shared installer/runtime package. The repository root is itself the installable plugin for Claude, Codex, and Antigravity (a single GitHub URL works across all three, mirroring `addyosmani/agent-skills`); there are no generated `dist/plugins/` directories or `.tgz` archives. Pi remains a real package because Pi installs packages directly. -``` +```text nsolid-plugin/ ├── packages/ │ ├── core/ # Shared CLI, setup, fallback install, auth, MCP, skills @@ -15,45 +15,47 @@ nsolid-plugin/ │ │ │ ├── mcp/ # MCP config writer module │ │ │ ├── harnesses/ # Per-harness config adapters │ │ │ └── utils/ # Shared utilities -│ │ ├── skills/ # Canonical committed N|Solid skills │ │ ├── scripts/setup.mjs # Shared package entrypoint for explicit setup │ │ └── package.json │ └── pi-plugin/ # Real Pi package; skills materialized only for pack │ ├── package.json # pi.skills plus side-effect-free extension metadata │ ├── index.js # Extension entrypoint; does not launch auth or write MCP config │ └── README.md -├── plugins/templates/ -│ ├── claude/ # Source-only template for generated Claude artifact -│ ├── codex/ # Source-only template for generated Codex artifact -│ └── antigravity/ # Source-only template for generated Antigravity artifact +├── skills/ # Canonical committed N|Solid skills (shared by all harnesses) +├── skill-assets/ # Shared per-skill helper scripts synced into skills// +├── .claude-plugin/ # Root Claude marketplace + plugin manifests (committed) +├── .codex-plugin/ # Root Codex plugin manifest (committed) +├── .agents/plugins/ # Root Codex marketplace manifest (committed) +├── plugin.json # Root Antigravity plugin manifest (committed) +├── .claude-mcp.json # Root plugin-local MCP config (Claude, committed) +├── .mcp.json # Root plugin-local MCP config (Codex, committed) +├── mcp_config.json # Root plugin-local MCP config (Antigravity, committed) ├── scripts/ -│ ├── plugin-generators.mjs # Manifest/wrapper/config generation helpers -│ ├── build-plugin-artifacts.mjs # Generates dist/plugins + dist/artifacts +│ ├── plugin-generators.mjs # Manifest/wrapper/config generation helpers (source of truth) +│ ├── materialize-github-marketplace.mjs # Materializes root marketplace/plugin layout from bundle.json │ └── sync-plugin-assets.mjs # Source hygiene + Pi materialization checks -├── dist/plugins/ # Generated plugin dirs; ignored, not committed -├── dist/artifacts/ # Generated .tgz release/local-install artifacts; ignored ├── bundle.json # Canonical bundle descriptor └── package.json # Workspace root ``` ### Key Architectural Decisions -1. **Shared core stays the behavioral source of truth**: `@nodesource/plugin-core` owns auth, fallback/direct install, MCP config writing, uninstall, doctor, and canonical skill metadata validation. +1. **Shared core stays the behavioral source of truth**: `nsolid-plugin` owns auth, fallback/direct install, MCP config writing, uninstall, doctor, and canonical skill metadata validation. -2. **Claude/Codex/Antigravity are generated artifacts, not source packages**: Marketplace/local plugin bundles are rendered from `plugins/templates//` into `dist/plugins//nsolid-plugin/` and archived under `dist/artifacts/`. This keeps source clean and makes release artifacts reproducible. +2. **Claude/Codex/Antigravity install from the GitHub root, not generated artifacts**: The repository root is simultaneously a Claude marketplace/plugin root (`.claude-plugin/`), a Codex marketplace/plugin root (`.codex-plugin/` + `.agents/plugins/`), and an Antigravity plugin root (`plugin.json`). All point at the same shared `skills/` tree and `scripts/mcp-wrapper.js`. This keeps source clean (one skill tree, committed manifests) and makes a single GitHub URL work across all three harnesses. There is no `dist/plugins/` generation step and no `.tgz` archive. -3. **Pi remains a package**: `packages/pi-plugin` stays in the workspace and materializes `packages/pi-plugin/skills/` during `prepack`, then cleans it in `postpack`/source mode. +3. **Pi remains a package**: `packages/pi-plugin` stays in the workspace and materializes `packages/pi-plugin/skills/` during `prepack` (from the root `skills/`), then cleans it in `postpack`/source mode. -4. **One canonical skill source**: `packages/core/skills/` is the only committed N|Solid skill source. Generated artifacts and Pi pack output receive materialized copies; source-mode package-local `skills/` directories are forbidden by `pnpm plugin:check`. +4. **One canonical skill source**: `skills/` at the repository root is the only committed N|Solid skill source. The GitHub-root plugin and Pi pack output read from it; source-mode package-local `skills/` directories are forbidden by `pnpm plugin:check`. -5. **Auth/setup is separate from install**: Only explicit `nsolid-plugin setup` / `nsolid-plugin login` may open a browser. Native plugin installation, generated install scripts, Pi package activation, and fallback `install --harness` must not launch auth. +5. **Auth/setup is separate from install**: Only explicit `nsolid-plugin setup` / `nsolid-plugin login` may open a browser. Native plugin installation (GitHub root), Pi package activation, and fallback `install --harness` must not launch auth. 6. **Native install vs fallback install**: - - Native install places a generated harness plugin artifact where the harness can load it. + - Native install loads the plugin from the committed GitHub-root manifests (Claude/Codex/Antigravity): the harness clones/reads the repository root, which already contains `.claude-plugin/`, `.codex-plugin/`/`.agents/plugins/`, and `plugin.json`, so there is no build or artifact generation step. - Fallback install (`nsolid-plugin install --harness `) directly copies/links skills and writes MCP config for users without a viable native plugin path; Pi is the exception because its package owns skills, so CLI fallback/setup writes MCP config only. - Setup/auth (`nsolid-plugin setup --harness `) prepares credentials and any harness config that truly needs explicit setup. -7. **Bundle descriptor pattern**: A single `bundle.json` file defines all skills and MCP servers. Builders and fallback installers validate generated artifacts against this descriptor. +7. **Bundle descriptor pattern**: A single `bundle.json` file defines all skills and MCP servers. Root manifest materialization and fallback installers validate the committed root plugin assets against this descriptor. 8. **Cross-platform support**: The installer supports macOS, Linux, and Windows as first-class platforms. All path resolution uses `os.homedir()` + `path.join()` (never string concatenation with `/`). Platform-specific behavior (symlinks, permissions, atomic writes) is abstracted in shared utilities. @@ -144,7 +146,7 @@ export async function doctor(harness: HarnessType, bundlePath: string): Promise< - Initiate OAuth flow (browser + callback server) only for explicit setup/login - Validate tokens with Accounts API - Store credentials securely -- Never run implicitly from native plugin install, package activation, generated install scripts, or fallback `install --harness` +- Never run implicitly from native plugin install (GitHub root), package activation, or fallback `install --harness` **Files:** - `auth-manager.ts` - Main auth orchestrator @@ -175,7 +177,7 @@ export async function clearCredentials(): Promise; - Copy skills for fallback/direct installs from source to `~/.agents/skills/` or harness-specific paths - Create harness-specific symlinks (Unix) or copies/junctions (Windows) for fallback installs - Track fallback-installed skills for uninstall -- Leave generated native artifacts self-contained; artifact materialization is owned by `scripts/build-plugin-artifacts.mjs` +- Leave the GitHub-root plugin's `skills/` untouched; native plugin assets are read from the committed root, not materialized by the core installer. **Files:** - `skill-copier.ts` - Copy skills to canonical location @@ -463,7 +465,7 @@ X-Nsolid-Service-Token = "" ``` **Pi Agent (`~/.pi/agent/mcp.json`):** -> **Note**: Pi package-owned skills come from `@nodesource/pi-plugin`. `nsolid-plugin setup --harness pi` writes MCP config for `pi-mcp-adapter` and disables adapter OAuth auto-detection with `"auth": false` so NodeSource service-token headers are used. +> **Note**: Pi package-owned skills come from `nsolid-pi-plugin`. `nsolid-plugin setup --harness pi` writes MCP config for `pi-mcp-adapter` and disables adapter OAuth auto-detection with `"auth": false` so NodeSource service-token headers are used. ```json { "mcpServers": { @@ -488,51 +490,50 @@ X-Nsolid-Service-Token = "" ## Data Flow -### Artifact Build Sequence +### Root Manifest Materialization Sequence -``` +```text ┌─────────────────────────────┐ -│ pnpm plugin:artifacts │ +│ pnpm plugin:root │ └──────────────┬──────────────┘ │ ▼ ┌─────────────────────────────┐ -│ scripts/build-plugin- │ -│ artifacts.mjs │ +│ scripts/materialize- │ +│ github-marketplace.mjs │ └──────────────┬──────────────┘ │ - ├───────────────┬────────────────┐ - ▼ ▼ ▼ -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Render Claude │ │ Render Codex │ │ Render │ -│ template │ │ template │ │ Antigravity │ -└────────┬────────┘ └────────┬────────┘ └────────┬────────┘ - │ │ │ - ▼ ▼ ▼ + ▼ ┌──────────────────────────────────────────────────────────┐ -│ Copy artifact-local skills from packages/core/skills/ │ -│ Generate manifests, MCP wrappers/config, install scripts │ -│ Validate against bundle.json │ +│ Generate root manifests from bundle.json via │ +│ scripts/plugin-generators.mjs (Claude/Codex/Antigravity) │ +│ Generate scripts/mcp-wrapper.js + plugin-local MCP cfg │ +│ Validate every bundle skill exists at skills/ │ └───────────────────────────┬──────────────────────────────┘ ▼ ┌──────────────────────────────────────────────────────────┐ -│ dist/plugins//nsolid-plugin/ │ -│ dist/artifacts/nsolid--plugin.tgz │ +│ Committed root (no dist/plugins, no .tgz): │ +│ .claude-plugin/{marketplace,plugin}.json │ +│ .codex-plugin/plugin.json + .agents/plugins/marketplace │ +│ plugin.json + mcp_config.json │ +│ .claude-mcp.json + .mcp.json + scripts/mcp-wrapper.js │ └──────────────────────────────────────────────────────────┘ ``` ### Native Plugin Install Sequence -``` +```text ┌─────────────────────────────┐ -│ User installs generated │ -│ native artifact │ +│ User installs from GitHub │ +│ root (claude/codex/agy) │ └──────────────┬──────────────┘ │ ▼ ┌─────────────────────────────┐ -│ Harness stages plugin files │ -│ from artifact-local bundle │ +│ Harness clones/registers │ +│ the root and stages plugin │ +│ files (skills, MCP cfg, │ +│ wrapper) from it │ └──────────────┬──────────────┘ │ ▼ @@ -552,7 +553,7 @@ X-Nsolid-Service-Token = "" ### Fallback Direct Install Sequence -``` +```text ┌─────────────────────────────┐ │ nsolid-plugin install │ │ --harness │ @@ -588,7 +589,7 @@ X-Nsolid-Service-Token = "" ### Setup/Auth Flow Sequence -``` +```text ┌──────────┐ │ setup/ │ │ login │ @@ -638,7 +639,7 @@ X-Nsolid-Service-Token = "" │ │ ▼ │ ┌─────────────────┐ │ -│ Store creds at │ │ +│ Store creds at │ │ │ ~/.agents/.node │ │ │ source-auth.json│ │ └────┬────────────┘ │ @@ -654,7 +655,7 @@ X-Nsolid-Service-Token = "" ### Uninstall Sequence -``` +```text ┌─────────────┐ │ User runs │ │ native or │ @@ -664,9 +665,9 @@ X-Nsolid-Service-Token = "" ▼ ┌─────────────────┐ │ Harness removes │ -│ generated native│ -│ artifact, or CLI│ -│ calls uninstall │ +│ staged plugin, │ +│ or CLI calls │ +│ uninstall │ └──────┬──────────┘ │ ▼ @@ -728,17 +729,18 @@ X-Nsolid-Service-Token = "" ## Design Decisions -### Why shared core + generated native artifacts? +### Why shared core + GitHub-root plugin? **Alternatives considered:** 1. **Single installer CLI only**: Rejected because native harness plugin UX is still valuable where supported. 2. **Five separate hand-maintained plugin packages**: Rejected due to duplicated skills, duplicated manifests, workspace noise, and high drift risk. -3. **Shared core + generated artifacts + Pi package**: Chosen for one source of truth, reproducible native bundles, and package-native Pi support. +3. **Generated artifacts + Pi package (earlier attempt)**: Superseded. Producing `dist/plugins/` and `.tgz` archives added a release step and hid outputs from source, with no marketplace submission requiring archives. +4. **Shared core + GitHub-root plugin + Pi package**: Chosen for one source of truth, a single installable GitHub URL across Claude/Codex/Antigravity, no release-time generation, and package-native Pi support. **Tradeoffs:** -- Release now has an explicit artifact build step (`pnpm plugin:artifacts`). -- Generated outputs are not visible in source until built locally or in CI. -- But: source remains canonical, skills are not duplicated across package folders, and marketplaces/local install flows receive self-contained plugin bundles. +- No release-time artifact build step; root manifests are committed and refreshed with `pnpm plugin:root`. +- The plugin root lives on the default branch; pre-merge QA uses `/tree/` install URLs. +- But: source remains canonical, skills are not duplicated across package folders, and all three native harnesses install from the same committed root. ### Why adapt nsentinel auth flow? @@ -752,14 +754,14 @@ X-Nsolid-Service-Token = "" - Simplify state management (no VSCode state API) - Keep same Accounts API endpoints -### Why `packages/core/skills/` as canonical source? +### Why root `skills/` as canonical source? **Rationale:** - The repository needs exactly one committed N|Solid skill source to avoid divergent copies. -- Generated Claude/Codex/Antigravity artifacts include artifact-local `skills/` directories because their plugin formats expect self-contained bundles. -- Pi package artifacts receive `skills/` only during pack/materialization. +- The GitHub-root plugin reads `skills/` directly from the committed root; no per-artifact copy is needed. +- Pi package artifacts receive `skills/` only during pack/materialization (from the root `skills/`). - Fallback direct installs can still copy/link skills into `~/.agents/skills/` or harness paths when native plugin install is unavailable. -- `pnpm plugin:check` enforces this source/artifact boundary. +- `pnpm plugin:check` enforces this source boundary (no committed package-local skill copies). ### Why JSON for credentials and tracking? @@ -781,35 +783,36 @@ X-Nsolid-Service-Token = "" ## Migration Strategy -The project migrated from hand-maintained per-harness package directories to generated artifacts: +The project migrated from hand-maintained per-harness package directories to the GitHub-root plugin model (having first tried a generated-artifacts approach that was superseded): -1. **Canonical source cleanup**: Keep N|Solid skills only in `packages/core/skills/`; remove generated/package-local skill copies from source. -2. **Artifact templates**: Move Claude/Codex/Antigravity source-only pieces into `plugins/templates//`. -3. **Generated outputs**: Render self-contained plugin directories under `dist/plugins/` and archives under `dist/artifacts/`. -4. **Pi exception**: Keep `packages/pi-plugin` as a real package with `prepack` skill materialization and post-pack/source cleanup. +1. **Canonical source cleanup**: Keep N|Solid skills only at the repository root `skills/`; remove generated/package-local skill copies from source. +2. **Root manifests**: Commit `.claude-plugin/`, `.codex-plugin/` + `.agents/plugins/`, `plugin.json`, and plugin-local MCP configs at the root, all generated from `bundle.json` by `scripts/materialize-github-marketplace.mjs`. +3. **Removed generation**: Delete `plugins/templates/`, `scripts/build-plugin-artifacts.mjs`, and the `dist/plugins/` / `.tgz` flow. +4. **Pi exception**: Keep `packages/pi-plugin` as a real package with `prepack` skill materialization (from root `skills/`) and post-pack/source cleanup. 5. **Auth split**: Remove browser/auth behavior from install paths; make `setup`/`login` the only OAuth entry points. Future changes use this model: -1. **Adding new skills**: Update `packages/core/skills/` and `bundle.json`; run `pnpm plugin:check` and `pnpm plugin:artifacts`. -2. **Adding new MCP servers**: Update `bundle.json` and generator/runtime config helpers; validate generated `.mcp.json`/`mcp_config.json` outputs. -3. **Adding new generated harnesses**: Add a harness adapter if fallback install is needed, a template under `plugins/templates/`, and generator coverage in `scripts/plugin-generators.mjs`. -4. **Updating existing installations**: Re-run native artifact install or fallback install; both paths are idempotent and non-authenticating. +1. **Adding new skills**: Update root `skills/` and `bundle.json`; run `pnpm plugin:root` to refresh root manifests and `pnpm plugin:check`. +2. **Adding new MCP servers**: Update `bundle.json` and generator/runtime config helpers; validate the committed `.claude-mcp.json`/`.mcp.json`/`mcp_config.json` outputs. +3. **Adding new native harnesses**: Add root manifests/generator coverage in `scripts/plugin-generators.mjs` and `scripts/materialize-github-marketplace.mjs`; add a harness adapter only if fallback install is needed. +4. **Updating existing installations**: Re-run native install (GitHub root) or fallback install; both paths are idempotent and non-authenticating. ## Deployment Order -1. **Core and Pi packages** - - Publish/build `@nodesource/plugin-core`. - - Pack/publish `@nodesource/pi-plugin` with materialized skills. +1. **Root plugin (Claude/Codex/Antigravity)** + - Merge root manifests to the default branch (no build step). + - Run `pnpm plugin:root` before merge to refresh manifests from `bundle.json`. + - Installers point at `https://github.com/NodeSource/nsolid-plugin` (default branch) or a `/tree/` URL for QA. -2. **Generated native artifacts** - - Run `pnpm plugin:artifacts`. - - Upload `dist/artifacts/nsolid--plugin.tgz` to releases or use `dist/plugins//nsolid-plugin/` for local install/marketplace staging. +2. **Core and Pi packages** + - Publish `nsolid-plugin` (ships `dist/src/`, root `skills/` copy, `bundle.json`). + - Pack/publish `nsolid-pi-plugin` with materialized skills. 3. **Marketplace submission where available** - - Submit/generated Claude and Codex plugin directories to curated/community marketplace paths when accepted. - - Use generated artifacts/local install paths while curation is pending. - - Use generated Antigravity local/remote plugin install until a curated marketplace path exists. + - The committed root is already a Claude and Codex marketplace root; users add it via `marketplace add NodeSource/nsolid-plugin`. + - Pursue curated/community marketplace inclusion for Claude/Codex where accepted; the GitHub root remains the fallback install source while curation is pending. + - Use Antigravity `agy plugin install ` until a curated marketplace path exists. 4. **Validation** - - Run `pnpm plugin:check`, `pnpm plugin:artifacts:check`, `pnpm lint`, `pnpm test`, and `pnpm test:marketplace` before release. + - Run `pnpm plugin:check`, `pnpm lint`, `pnpm test`, and `pnpm test:marketplace` before release. diff --git a/openspec/changes/cross-harness-plugin-installer/proposal.md b/openspec/changes/cross-harness-plugin-installer/proposal.md index 5be194c..b17224a 100644 --- a/openspec/changes/cross-harness-plugin-installer/proposal.md +++ b/openspec/changes/cross-harness-plugin-installer/proposal.md @@ -10,41 +10,34 @@ Without marketplace presence, adoption is limited to manual installation by user ## Proposed Solution -Create a **generated native artifact + shared core** architecture that supports marketplace submission where available without committing duplicate plugin package trees. +Create a **shared core + GitHub-root plugin + Pi package** architecture. The repository root is itself the installable plugin for Claude, Codex, and Antigravity (mirroring `addyosmani/agent-skills`), so a single GitHub URL works across all three harnesses without committing duplicate plugin package trees or generating `.tgz` archives. ### Shared Core (`packages/core`) - **Bundle descriptor**: validated descriptor defining skills, MCP servers, and metadata. -- **Canonical skills**: `packages/core/skills/` is the only committed N|Solid skill source. +- **Canonical skills**: `skills/` at the repository root is the only committed N|Solid skill source. - **Auth module**: Adapt nsentinel OAuth flow for CLI context (browser redirect + local callback server), invoked only by explicit `setup`/`login`. - **Fallback installer**: `install --harness ` directly installs assets when native plugin install is unavailable; it does not open a browser. - **MCP config writer**: Generate harness-specific MCP configurations for setup/fallback paths. - **Tracking file**: `~/.agents/.nodesource-installed.json` for clean CLI/fallback uninstall. -### Generated Native Artifacts -Claude, Codex, and Antigravity use generated, self-contained artifacts instead of workspace packages: +### GitHub-Root Plugin (Claude / Codex / Antigravity) +The repository root is simultaneously a Claude, Codex, and Antigravity plugin root. The committed root manifests point each harness at the same shared `skills/` tree and `scripts/mcp-wrapper.js`: -1. **Claude Code artifact** (`dist/plugins/claude/nsolid-plugin/`) - - Generated from `plugins/templates/claude/`. - - Contains `.claude-plugin/plugin.json`, MCP wrapper/config, and materialized `skills/`. - - Suitable for local install or marketplace submission when accepted. +1. **Claude Code** — root `.claude-plugin/marketplace.json` + `.claude-plugin/plugin.json` declare a marketplace whose single plugin sources the root (`source: "./"`); the plugin lists `./skills/` and `mcpServers: "./.claude-mcp.json"`. Install: `claude plugin marketplace add NodeSource/nsolid-plugin && claude plugin install nsolid-plugin@nodesource`. -2. **Codex artifact** (`dist/plugins/codex/nsolid-plugin/`) - - Generated from `plugins/templates/codex/`. - - Contains `.codex-plugin/plugin.json`, local marketplace metadata, MCP wrapper/config, and materialized `skills/`. - - Supports `codex plugin marketplace add` local/repo marketplace flows. +2. **Codex CLI** — root `.agents/plugins/marketplace.json` + `.codex-plugin/plugin.json` declare a marketplace whose plugin sources the root (`source: { source: "local", path: "./" }`); the plugin lists `skills: "./skills/"` and `mcpServers: "./.mcp.json"`. Install: `codex plugin marketplace add NodeSource/nsolid-plugin && codex plugin add nsolid-plugin@nodesource`. -3. **Antigravity artifact** (`dist/plugins/antigravity/nsolid-plugin/`) - - Generated from `plugins/templates/antigravity/`. - - Contains `plugin.json`, `mcp_config.json`, `scripts/install.js`, MCP wrapper, and materialized `skills/`. - - Supports `agy plugin install /path/to/plugin` local/remote install. +3. **Antigravity CLI** — root `plugin.json` is the Antigravity plugin root; `mcp_config.json` references `scripts/mcp-wrapper.js`. Install: `agy plugin install https://github.com/NodeSource/nsolid-plugin.git` (or a `/tree/` URL for pre-merge QA). + +Root manifests are generated from `bundle.json` by `scripts/materialize-github-marketplace.mjs` (`pnpm plugin:root`) and committed. There are no generated `dist/plugins/` directories or `.tgz` archives. 4. **Pi Agent package** (`packages/pi-plugin`) - - Remains a real package because Pi installs packages directly. - - Receives materialized `skills/` during package `prepack`; source mode stays clean. + - Remains a real, publishable package because Pi installs packages directly. + - Receives materialized `skills/` during package `prepack`; source mode stays clean (`postpack`/`plugin:clean` removes them). - Package activation is side-effect free; explicit setup writes `~/.pi/agent/mcp.json` with `"auth": false` for `pi-mcp-adapter`. 5. **OpenCode fallback** - - Remains CLI/fallback install only until its plugin distribution model is clearer. + - Remains CLI/fallback install only until its plugin distribution model is clearer. `setup --harness opencode` authenticates and copies skills directly; `install` is no-browser fallback/repair. ### Auth Flow Integration Adapt the nsentinel-vscode-extension OAuth flow: @@ -56,13 +49,13 @@ Adapt the nsentinel-vscode-extension OAuth flow: - Token validation via `/accounts/org/access-token` endpoint where available. ### Installation and Setup Flow -1. Release/build runs `pnpm plugin:artifacts` to generate self-contained Claude/Codex/Antigravity plugin dirs and `.tgz` artifacts. -2. User installs the native plugin artifact through the harness (`claude`, `codex`, or `agy`) or installs Pi through `pi install npm:@nodesource/pi-plugin`. +1. Root manifests are kept in sync with `bundle.json` via `pnpm plugin:root` (committed, not a release-time generation step). `pnpm plugin:root:check` (also run by `pnpm plugin:check`) fails CI if the committed manifests drift. +2. User installs the plugin through the harness from the GitHub root (`claude`/`codex` marketplace add, or `agy plugin install `), or installs Pi through `pi install npm:nsolid-pi-plugin`. 3. Native install places plugin assets only; it must not open a browser or start OAuth. 4. User runs `nsolid-plugin setup --harness ` to authenticate and write any setup-time config. 5. If native install is unavailable, user may run `nsolid-plugin install --harness ` as fallback direct asset installation; this path also must not open a browser. -Research backing this model is documented in `docs/plugin-marketplace-research.md`. +Research backing this model is documented in `docs/plugin-marketplace-research.md` (with an amendment note recording the move from generated artifacts to the GitHub-root model). ## Rollback Plan @@ -70,31 +63,32 @@ If marketplace plugins cause issues: > **Note**: Rollback is an **emergency full cleanup** that removes all NodeSource artifacts including shared credentials. Normal per-harness uninstall (see installation-and-auth.md) **preserves** `~/.agents/.nodesource-auth.json` for re-use across harnesses. -1. **Native artifact uninstall**: Users uninstall generated plugin artifacts through the harness UI/CLI where supported. The harness removes the native plugin directory and its artifact-local skills/config. +1. **Native plugin uninstall**: Users uninstall the GitHub-root plugin through the harness UI/CLI where supported (e.g., `/plugins` in Claude Code, `codex plugin remove`, `agy plugin uninstall`). The harness removes the staged plugin directory and its skills/config. 2. **Fallback/CLI uninstall**: `nsolid-plugin uninstall --harness ` reads `~/.agents/.nodesource-installed.json`, removes tracked MCP entries from harness configs, removes tracked fallback skill links/copies, and preserves shared credentials. 3. **Emergency rollback auth cleanup**: Delete `~/.agents/.nodesource-auth.json` only in full rollback, not normal uninstall. -4. **Marketplace removal**: Users can remove marketplace-installed plugins via harness UI (e.g., `/plugins` in Claude Code) or harness CLI (`codex plugin ...`, `agy plugin uninstall ...`). +4. **Marketplace removal**: Users can remove marketplace-installed plugins via harness UI (e.g., `/plugins` in Claude Code) or harness CLI (`codex plugin remove`, `agy plugin uninstall`). 5. **Fallback**: Shared core can also be invoked directly via `nsolid-plugin uninstall --harness ` for manual cleanup. ## Affected Components -### Packages and Generated Assets -- `packages/core` - Shared CLI/setup/fallback installer logic, auth module, bundle descriptor validation, canonical skills. -- `packages/pi-plugin` - Real Pi Agent package; skills materialized only during pack/release. -- `plugins/templates/claude` - Source template for generated Claude artifact. -- `plugins/templates/codex` - Source template for generated Codex artifact. -- `plugins/templates/antigravity` - Source template for generated Antigravity artifact. -- `scripts/plugin-generators.mjs` - Shared manifest/config/wrapper generation helpers. -- `scripts/build-plugin-artifacts.mjs` - Generates `dist/plugins/` and `dist/artifacts/`. +### Packages and Root Plugin Assets +- `packages/core` - Shared CLI/setup/fallback installer logic, auth module, bundle descriptor validation, bundled skills (shipped in the npm package). +- `packages/pi-plugin` - Real, publishable Pi Agent package; skills materialized only during pack/release. +- `.claude-plugin/` - Root Claude marketplace + plugin manifests (committed). +- `.codex-plugin/`, `.agents/plugins/` - Root Codex plugin + marketplace manifests (committed). +- `plugin.json`, `mcp_config.json` - Root Antigravity plugin manifest + MCP config (committed). +- `.claude-mcp.json`, `.mcp.json` - Root plugin-local MCP configs pointing at `scripts/mcp-wrapper.js` (committed). +- `scripts/plugin-generators.mjs` - Shared manifest/config/wrapper generation helpers (source of truth for root manifests). +- `scripts/materialize-github-marketplace.mjs` - Materializes the root marketplace/plugin layout from `bundle.json`. - `scripts/sync-plugin-assets.mjs` - Source hygiene checks and Pi materialization/cleanup. ### Shared Resources - `bundle.json` - Canonical bundle descriptor (skills + MCP servers). -- `packages/core/skills/` - Canonical committed skill source. +- `skills/` - Canonical committed skill source at the repository root (shared by the GitHub-root plugin and materialized into the Pi package). - `packages/core/src/validate.ts` - Bundle descriptor validation. ### External Dependencies @@ -103,15 +97,15 @@ If marketplace plugins cause issues: - ns-benchmark (Node.js benchmarking) - nsolid-console (N|Solid console integration) - ncm (package vulnerability/quality metrics) -- **Skills**: N|Solid skills from the canonical `packages/core/skills/` bundle +- **Skills**: N|Solid skills from the canonical root `skills/` bundle ### Harness Config Locations Supported platforms: **macOS**, **Linux**, and **Windows**. All paths use `~` as shorthand for the user's home directory (`$HOME` on macOS/Linux, `%USERPROFILE%` on Windows). At runtime, paths are resolved via `os.homedir()` + `path.join()`. -- Claude Code fallback: `~/.claude.json`, `~/.claude/skills/`; native artifact also contains plugin-local `.mcp.json` and `skills/`. -- Codex CLI fallback: `~/.codex/config.toml`, `~/.codex/skills/`; native artifact also contains plugin-local `.mcp.json`, `.codex-plugin/plugin.json`, and `skills/`. +- Claude Code fallback: `~/.claude.json`, `~/.claude/skills/`; the GitHub-root plugin also carries plugin-local `.claude-mcp.json` and `skills/`. +- Codex CLI fallback: `~/.codex/config.toml`, `~/.codex/skills/`; the GitHub-root plugin also carries plugin-local `.mcp.json`, `.codex-plugin/plugin.json`, and `skills/`. - OpenCode fallback: `~/.config/opencode/opencode.jsonc`, `~/.config/opencode/skills/`. - Antigravity fallback: `~/.gemini/antigravity-cli/mcp_config.json`, `~/.gemini/antigravity-cli/skills/`; native install stages plugin-local assets under `~/.gemini/antigravity-cli/plugins/nsolid-plugin/`. - Pi Agent setup: `~/.pi/agent/mcp.json`; Pi package owns `skills/`; NodeSource MCP entries include `"auth": false`. @@ -121,12 +115,13 @@ All paths use `~` as shorthand for the user's home directory (`$HOME` on macOS/L ## Success Criteria ### Functional Requirements -- [ ] `pnpm plugin:artifacts` creates self-contained Claude, Codex, and Antigravity plugin directories plus archives under `dist/`. -- [ ] `packages/core/skills/` is the only committed N|Solid skill source. -- [ ] Pi remains installable as a real package with materialized skills in packed artifacts. +- [ ] `pnpm plugin:root` regenerates the committed root marketplace/plugin manifests from `bundle.json` and they validate; `pnpm plugin:root:check` detects drift. +- [ ] `skills/` at the repository root is the only committed N|Solid skill source. +- [ ] Claude, Codex, and Antigravity install successfully from the GitHub root (`marketplace add NodeSource/nsolid-plugin` / `agy plugin install `). +- [ ] Pi remains installable as a real, publishable package with materialized skills in packed artifacts. - [ ] Auth flow completes successfully only through explicit setup/login (browser OAuth + token storage). -- [ ] Native install, generated install scripts, Pi package activation, and fallback `install --harness` do not open a browser. -- [ ] All skills are discoverable by each supported harness path (native artifact or fallback). +- [ ] Native install, Pi package activation, and fallback `install --harness` do not open a browser. +- [ ] All skills are discoverable by each supported harness path (GitHub-root native or fallback). - [ ] MCP servers are configured/reachable where supported. - [ ] Uninstall/fallback cleanup removes only tracked NodeSource artifacts. - [ ] Doctor command verifies installation health. @@ -135,23 +130,23 @@ All paths use `~` as shorthand for the user's home directory (`$HOME` on macOS/L - [ ] Zero overwrites of existing user configurations (merge, don't replace). - [ ] Idempotent setup and fallback installation. - [ ] Auth tokens stored securely (file permissions 0600; best-effort on Windows where `chmod` has limited effect). -- [ ] Generated manifests/configs pass schema/shape validation. +- [ ] Generated root manifests/configs pass schema/shape validation. - [ ] `pnpm plugin:check` catches stale generated files and accidental package-local skill copies. ### Verification -- [ ] Manual test: Build artifacts, install generated artifact for each native harness, run setup, verify skills and MCPs work. +- [ ] Manual test: refresh root manifests, install from the GitHub root for each native harness, run setup, verify skills and MCPs work. - [ ] Automated test: Bundle descriptor validates against the core schema validator. - [ ] Automated test: Auth flow mocked in CI, real flow tested manually. -- [ ] Automated test: Generated artifacts contain all bundle skills and no auth/browser behavior in install paths. +- [ ] Automated test: Root plugin assets contain all bundle skills and no auth/browser behavior in install paths. - [ ] Automated test: Fallback install/uninstall cycle leaves no unexpected artifacts. - [ ] Integration test: Each harness discovers installed skills. - [ ] Integration test: MCP servers respond to health checks. ### Acceptance Tests -1. **Claude Code**: Generated Claude artifact contains `.claude-plugin/plugin.json`, MCP wrapper/config, and all skills; user installs artifact/marketplace entry, runs setup, and can invoke `ns-analyze-vulnerabilities`. -2. **Codex CLI**: Generated Codex artifact contains `.codex-plugin/plugin.json` with `skills: "./skills/"`, local marketplace metadata, MCP wrapper/config, and all skills; user adds marketplace/artifact, runs setup, and MCP tools are available. +1. **Claude Code**: Root `.claude-plugin/{marketplace,plugin}.json` list all skills and `.claude-mcp.json`; user runs `claude plugin marketplace add NodeSource/nsolid-plugin && claude plugin install nsolid-plugin@nodesource`, runs setup, and can invoke `ns-analyze-vulnerabilities`. +2. **Codex CLI**: Root `.codex-plugin/plugin.json` declares `skills: "./skills/"` and `.mcp.json`, with root `.agents/plugins/marketplace.json`; user runs `codex plugin marketplace add NodeSource/nsolid-plugin && codex plugin add nsolid-plugin@nodesource`, runs setup, and MCP tools are available. 3. **OpenCode**: User uses fallback direct install; skills appear in OpenCode skill discovery and MCP config is merged. -4. **Antigravity**: Generated Antigravity artifact contains `plugin.json`, `mcp_config.json`, `scripts/install.js`, MCP wrapper, and all skills; `agy plugin install` stages the plugin and setup handles auth. -5. **Pi Agent**: User installs `@nodesource/pi-plugin`, runs setup, and Pi has package-owned skills plus MCP config with `"auth": false`. +4. **Antigravity**: Root `plugin.json` + `mcp_config.json` + `scripts/mcp-wrapper.js` + root `skills/`; `agy plugin install https://github.com/NodeSource/nsolid-plugin.git` stages the plugin and setup handles auth. +5. **Pi Agent**: User installs `nsolid-pi-plugin`, runs setup, and Pi has package-owned skills plus MCP config with `"auth": false`. 6. **Auth**: First-time setup triggers browser OAuth; install paths never do. -7. **Uninstall**: User uninstalls native artifact or runs CLI uninstall; only NodeSource artifacts are removed. +7. **Uninstall**: User uninstalls the native plugin or runs CLI uninstall; only NodeSource artifacts are removed. diff --git a/openspec/changes/cross-harness-plugin-installer/specs/installation-and-auth.md b/openspec/changes/cross-harness-plugin-installer/specs/installation-and-auth.md index a206bb1..31e29b8 100644 --- a/openspec/changes/cross-harness-plugin-installer/specs/installation-and-auth.md +++ b/openspec/changes/cross-harness-plugin-installer/specs/installation-and-auth.md @@ -1,21 +1,27 @@ # Installation Flow Specification -## Scenario: Generated native artifacts are built +## Scenario: Root marketplace/plugin manifests are materialized **Given** the repository is in source mode -**When** the release process runs `pnpm plugin:artifacts` -**Then** plugin directories are generated under `dist/plugins/{claude,codex,antigravity}/nsolid-plugin/` -**And** archives are generated under `dist/artifacts/nsolid-{claude,codex,antigravity}-plugin.tgz` -**And** each generated plugin contains all skills from `packages/core/skills/` -**And** each generated plugin contains the harness manifest/config/wrapper files required by its native format -**And** no generated artifact is committed to source control - -## Scenario: Native plugin installation with no existing credentials +**When** the maintainer runs `pnpm plugin:root` +**Then** the root manifests are (re)generated from `bundle.json` and committed at the repository root: +- `.claude-plugin/marketplace.json` and `.claude-plugin/plugin.json` +- `.agents/plugins/marketplace.json` and `.codex-plugin/plugin.json` +- `plugin.json` and `mcp_config.json` (Antigravity) +- `.claude-mcp.json` and `.mcp.json` (plugin-local MCP configs) +- `scripts/mcp-wrapper.js` (shared MCP wrapper) +**And** the materialization validates that every bundle skill exists at `skills//SKILL.md` +**And** the root acts as a single installable plugin for Claude, Codex, and Antigravity (no `dist/plugins/` directories or `.tgz` archives are produced) + +## Scenario: Native plugin installation from the GitHub root with no existing credentials **Given** the user has not previously authenticated with NodeSource **And** no credentials exist at `~/.agents/.nodesource-auth.json` -**When** the user installs a generated Claude, Codex, or Antigravity plugin artifact through the harness -**Then** the harness stages plugin assets from the generated artifact +**When** the user installs the plugin from the GitHub root through the harness +- Claude: `claude plugin marketplace add NodeSource/nsolid-plugin` then `claude plugin install nsolid-plugin@nodesource` +- Codex: `codex plugin marketplace add NodeSource/nsolid-plugin` then `codex plugin add nsolid-plugin@nodesource` +- Antigravity: `agy plugin install https://github.com/NodeSource/nsolid-plugin.git` (or a `/tree/` URL for pre-merge QA) +**Then** the harness clones/registers the root and stages plugin assets (skills, MCP config, wrapper) from it **And** no browser opens **And** no OAuth callback server starts **And** no credentials file is written @@ -62,7 +68,7 @@ ## Scenario: Installation failure during skill copy -**Given** fallback installation or artifact generation has started +**Given** fallback installation has started **When** skill copying fails (e.g., disk full, permission denied) **Then** the operation rolls back partially copied skills where possible **And** an error message is displayed with actionable guidance @@ -159,7 +165,7 @@ ## Scenario: Expired token during native install or fallback install **Given** credentials are missing or expired -**When** a generated native install script, native artifact activation, Pi package activation, or fallback `install --harness` path runs +**When** native plugin activation (GitHub-root install), Pi package activation, or fallback `install --harness` path runs **Then** the path does not open a browser **And** the output or runtime error tells the user to run `nsolid-plugin setup --harness ` @@ -171,7 +177,7 @@ **Given** the plugin is installed natively or through fallback direct install **When** the user uninstalls through the harness UI/CLI or runs `nsolid-plugin uninstall --harness ` -**Then** native uninstall removes the generated plugin directory where the harness owns it +**Then** native uninstall removes the staged plugin directory where the harness owns it **And** fallback uninstall reads `~/.agents/.nodesource-installed.json` when tracking exists **And** tracked NodeSource MCP entries are removed from harness configs **And** tracked NodeSource skill directories, symlinks, and copies are deleted from fallback harness-specific paths (`~/.agents/skills/`, `~/.claude/skills/`, `~/.codex/skills/`, `~/.config/opencode/skills/`, `~/.gemini/antigravity-cli/skills/`, `~/.pi/agent/skills/`) @@ -239,8 +245,8 @@ When no tracking file is present, the uninstaller scans only these predefined pa **When** the user runs the doctor command **Then** the check verifies: - Credentials exist and are valid when authenticated MCP servers are expected -- All bundle skills exist in the relevant native artifact, Pi package, or fallback skill path -- MCP configurations are present in the relevant native artifact or harness config +- All bundle skills exist in the staged GitHub-root plugin, Pi package, or fallback skill path +- MCP configurations are present in the staged plugin or harness config - MCP servers are reachable (health endpoint responds) **And** a green status is reported with summary @@ -253,10 +259,10 @@ When no tracking file is present, the uninstaller scans only these predefined pa ## Scenario: Missing skills -**Given** some skills are missing from the native artifact, Pi package, or fallback skill path +**Given** some skills are missing from the staged GitHub-root plugin, Pi package, or fallback skill path **When** doctor runs **Then** a yellow status lists missing skills -**And** actionable fix: "Rebuild artifacts or re-run fallback installation to restore skills" +**And** actionable fix: "Reinstall the plugin or re-run fallback installation to restore skills" ## Scenario: MCP server unreachable @@ -267,25 +273,26 @@ When no tracking file is present, the uninstaller scans only these predefined pa ## Scenario: Harness cannot discover skills -**Given** skills exist in the native artifact, Pi package, or fallback skill path +**Given** skills exist in the staged GitHub-root plugin, Pi package, or fallback skill path **When** harness skill discovery check fails **Then** a yellow status indicates discovery issue -**And** actionable fix: "Restart harness, rebuild/reinstall the artifact, or check skill path configuration" +**And** actionable fix: "Restart harness, reinstall the plugin, or check skill path configuration" --- # Per-Harness Configuration Mapping Specification -## Scenario: Claude Code native artifact +## Scenario: Claude Code GitHub-root plugin -**Given** the generated Claude artifact exists -**Then** it contains: -- `.claude-plugin/plugin.json` -- `.mcp.json` or equivalent plugin-local MCP config +**Given** the root Claude marketplace and plugin manifests are committed +**Then** the root contains: +- `.claude-plugin/plugin.json` (lists `./skills/` for every bundle skill and `mcpServers: "./.claude-mcp.json"`) +- `.claude-plugin/marketplace.json` (marketplace `nodesource` whose single plugin `source: "./"` points at the root) +- `.claude-mcp.json` (plugin-local MCP config referencing `scripts/mcp-wrapper.js`) - `scripts/mcp-wrapper.js` - `skills//SKILL.md` for every bundle skill -**And** the generated artifact does not contain startup/setup hooks or `scripts/setup.js`. -**And** the artifact install does not write user-level `~/.claude/skills/` unless the user chooses fallback direct install. +**And** the root does not contain startup/setup hooks or `scripts/setup.js`. +**And** `claude plugin marketplace add NodeSource/nsolid-plugin` then `claude plugin install nsolid-plugin@nodesource` installs from the root without writing user-level `~/.claude/skills/` unless the user chooses fallback direct install. ## Scenario: Claude Code fallback configuration @@ -294,17 +301,17 @@ When no tracking file is present, the uninstaller scans only these predefined pa **Then** entries are merged into `~/.claude.json` **And** skills are symlinked (Unix) or junction-linked/copied (Windows) to `~/.claude/skills/`. -## Scenario: Codex CLI native artifact +## Scenario: Codex CLI GitHub-root plugin -**Given** the generated Codex artifact exists -**Then** it contains: -- `.codex-plugin/plugin.json` with `skills: "./skills/"` -- local marketplace metadata for `codex plugin marketplace add` flows -- `.mcp.json` or equivalent plugin-local MCP config +**Given** the root Codex marketplace and plugin manifests are committed +**Then** the root contains: +- `.codex-plugin/plugin.json` with `skills: "./skills/"` and `mcpServers: "./.mcp.json"` +- `.agents/plugins/marketplace.json` (marketplace `nodesource` whose single plugin sources the root via `{ source: "local", path: "./" }`) +- `.mcp.json` (plugin-local MCP config referencing `scripts/mcp-wrapper.js`) - `scripts/mcp-wrapper.js` - `skills//SKILL.md` for every bundle skill -**And** the generated artifact does not contain `hooks/hooks.json` or `scripts/setup.js`. -**And** native install never launches auth/browser. +**And** the root does not contain `hooks/hooks.json` or `scripts/setup.js`. +**And** `codex plugin marketplace add NodeSource/nsolid-plugin` then `codex plugin add nsolid-plugin@nodesource` installs from the root without launching auth/browser. ## Scenario: Codex CLI fallback configuration @@ -320,17 +327,16 @@ When no tracking file is present, the uninstaller scans only these predefined pa **Then** entries are merged under the `mcp` key in `~/.config/opencode/opencode.jsonc` **And** skills are symlinked (Unix) or junction-linked/copied (Windows) to `~/.config/opencode/skills/`. -## Scenario: Antigravity native artifact +## Scenario: Antigravity GitHub-root plugin -**Given** the generated Antigravity artifact exists -**Then** it contains: +**Given** the root Antigravity plugin manifest is committed +**Then** the root contains: - `plugin.json` -- `mcp_config.json` -- `scripts/install.js` +- `mcp_config.json` (referencing `scripts/mcp-wrapper.js`) - `scripts/mcp-wrapper.js` - `skills//SKILL.md` for every bundle skill -**And** the generated artifact does not contain `hooks.json` or `scripts/setup.js`. -**And** `agy plugin install ` stages the plugin under `~/.gemini/antigravity-cli/plugins/nsolid-plugin/` +**And** the root does not contain `hooks.json` or `scripts/setup.js`. +**And** `agy plugin install https://github.com/NodeSource/nsolid-plugin.git` stages the plugin under `~/.gemini/antigravity-cli/plugins/nsolid-plugin/` **And** native install does not launch auth/browser. ## Scenario: Antigravity fallback configuration @@ -344,7 +350,7 @@ When no tracking file is present, the uninstaller scans only these predefined pa **Given** the user installs the Pi package **When** the package is packed or released -**Then** `packages/pi-plugin/skills/` is materialized from `packages/core/skills/` for the package artifact +**Then** `packages/pi-plugin/skills/` is materialized from the root `skills/` for the package artifact **And** source-mode cleanup removes materialized Pi skills after pack **And** Pi package activation is side-effect free: no browser auth, no user-level skill copy/link, and no MCP config write **When** the user runs `nsolid-plugin setup --harness pi` diff --git a/openspec/changes/cross-harness-plugin-installer/tasks.md b/openspec/changes/cross-harness-plugin-installer/tasks.md index 0f66606..acae772 100644 --- a/openspec/changes/cross-harness-plugin-installer/tasks.md +++ b/openspec/changes/cross-harness-plugin-installer/tasks.md @@ -1,5 +1,24 @@ # Tasks +> **Amendment (2026-06-24):** The distribution model changed after validation. +> Tasks describing the **generated-artifact** flow (`scripts/build-plugin-artifacts.mjs`, +> `plugins/templates/`, `dist/plugins/`, `.tgz` archives, `pnpm plugin:artifacts`) are +> **superseded**. Claude/Codex/Antigravity now install from the **GitHub repository root** +> via committed manifests materialized by `scripts/materialize-github-marketplace.mjs` +> (`pnpm plugin:root`). See `design.md` (Architecture, Deployment Order) and +> `proposal.md` (Proposed Solution) for the current model. The completed tasks below are +> retained as a historical record of what was built; only the distribution mechanism +> changed — auth, fallback install, MCP config, skills, adapters, and uninstall logic +> remain accurate. +> +> **Current distribution tasks (GitHub-root model):** +> - [x] Commit root manifests: `.claude-plugin/{marketplace,plugin}.json`, `.codex-plugin/plugin.json`, `.agents/plugins/marketplace.json`, `plugin.json`, `mcp_config.json`, `.claude-mcp.json`, `.mcp.json`, `scripts/mcp-wrapper.js`. +> - [x] Add `scripts/materialize-github-marketplace.mjs` (`pnpm plugin:root`) and regenerate root manifests from `bundle.json`. +> - [x] Remove `scripts/build-plugin-artifacts.mjs`, `plugins/templates/`, and the `dist/plugins` + `.tgz` generation flow. +> - [x] Move canonical skills from `packages/core/skills/` to repository-root `skills/`. +> - [x] Validate root plugin assets in `scripts/test-marketplace-install.js` (Claude/Codex/Antigravity/pi roots). +> - [ ] Merge root manifests to the default branch so the GitHub URL resolves for end users. + ## Phase 1: Project Setup and Core Infrastructure ### Task 1: Initialize monorepo structure ✓ @@ -232,7 +251,7 @@ - `packages/core/src/index.ts` - `packages/core/scripts/check-bundle-sync.mjs` - `packages/core/package.json` -- **Testing**: Run `pnpm --filter @nodesource/plugin-core bundle:check`. In a throwaway HOME, run `NSOLID_HARNESS=claude node packages/core/scripts/setup.mjs` and confirm MCP config has resolved absolute paths. +- **Testing**: Run `pnpm --filter nsolid-plugin bundle:check`. In a throwaway HOME, run `NSOLID_HARNESS=claude node packages/core/scripts/setup.mjs` and confirm MCP config has resolved absolute paths. - **Spec reference**: Variable Expansion in design.md ### Task 22c: Create shared setup script ✓ @@ -322,7 +341,7 @@ - **Files**: - `packages/core/src/cli.ts` - `packages/core/package.json` (add bin entry) -- **Testing**: Run `npx @nodesource/plugin-core doctor --harness claude`. Verify output format and colors. +- **Testing**: Run `npx nsolid-plugin doctor --harness claude`. Verify output format and colors. ### Task 31: Write README documentation ✓ - [x] **Description**: Create comprehensive README.md with installation instructions for each marketplace, authentication flow explanation, troubleshooting guide, and development setup. @@ -485,7 +504,7 @@ This phase supersedes the earlier source-package interpretation of Phase 7 for C - **Testing**: Dry run script, verify timing and clarity. ### Task 40: Final integration testing and bug fixes -- **Description**: Perform end-to-end testing of generated native artifacts, the Pi package, and fallback direct install paths on clean systems (macOS, Linux, and Windows). Document and fix any issues found. Verify all acceptance criteria from proposal.md are met. Pay special attention to platform-specific behavior: path separators, symlink/junction behavior, file permissions, and atomic writes on Windows. +- **Description**: Perform end-to-end testing of the GitHub-root plugin install (Claude/Codex/Antigravity), the Pi package, and fallback direct install paths on clean systems (macOS, Linux, and Windows). Document and fix any issues found. Verify all acceptance criteria from proposal.md are met. Pay special attention to platform-specific behavior: path separators, symlink/junction behavior, file permissions, and atomic writes on Windows. - **Depends on**: Tasks 23-32 and Phase 9b - **Files**: - Update any files with bug fixes