From 2391632973b6de1e6259eb6b1d6e6658c58e0a50 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Wed, 1 Jul 2026 11:06:21 -0400 Subject: [PATCH] feat(#1855): add Claude plugin marketplace manifest Add .claude-plugin/marketplace.json so Claude-plugin-compatible runtimes (ZCODE et al.) discover gsd-core from a custom marketplace source. The canonical version lives at plugins[0].version and tracks package.json via the release version-sync. Refactor scripts/sync-manifest-versions.cjs so VERSIONED_MANIFESTS entries are {path, versionKey} dot-path descriptors (default 'version'); register marketplace.json with versionKey 'plugins.0.version'. getByPath/setByPath reject __proto__/constructor/prototype (prototype-pollution guard). plugin.json / gemini-extension.json behavior is unchanged. - tests/issue-1855-marketplace-manifest.test.cjs: schema + version-sync guard - tests/issue-844-manifest-version-sync.test.cjs: updated for descriptor shape - VERSIONING.md + auto-backmerge VERSION_STAMP_MANIFESTS: include marketplace.json - docs/how-to/install-on-your-runtime.md: marketplace discovery how-to --- .claude-plugin/marketplace.json | 20 ++ .github/workflows/auto-backmerge.yml | 2 +- VERSIONING.md | 8 +- docs/how-to/install-on-your-runtime.md | 9 + scripts/sync-manifest-versions.cjs | 79 ++++-- .../issue-1855-marketplace-manifest.test.cjs | 231 ++++++++++++++++++ .../issue-844-manifest-version-sync.test.cjs | 50 ++-- tests/workflow-maintainer-skip.test.cjs | 15 +- 8 files changed, 369 insertions(+), 45 deletions(-) create mode 100644 .claude-plugin/marketplace.json create mode 100644 tests/issue-1855-marketplace-manifest.test.cjs diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 000000000..43bc4907e --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,20 @@ +{ + "name": "gsd-core", + "description": "Marketplace for GSD Core — meta-prompting, context engineering, and spec-driven development system for AI coding agents.", + "owner": { + "name": "open-gsd", + "url": "https://github.com/open-gsd" + }, + "plugins": [ + { + "name": "gsd-core", + "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.", + "version": "1.7.0-rc.1", + "source": "./", + "author": { + "name": "open-gsd", + "url": "https://github.com/open-gsd" + } + } + ] +} diff --git a/.github/workflows/auto-backmerge.yml b/.github/workflows/auto-backmerge.yml index 3548234c5..d9cb9be9e 100644 --- a/.github/workflows/auto-backmerge.yml +++ b/.github/workflows/auto-backmerge.yml @@ -115,7 +115,7 @@ jobs: # filter those out. A substantive change still parks: it leaves # non-"version" lines (deps in package.json; resolved/integrity in the # lockfile when a dependency actually changes). - VERSION_STAMP_MANIFESTS='package.json package-lock.json .claude-plugin/plugin.json gemini-extension.json' + VERSION_STAMP_MANIFESTS='package.json package-lock.json .claude-plugin/plugin.json .claude-plugin/marketplace.json gemini-extension.json' DROPPED=$(printf '%s\n' "$DROPPED" | while IFS= read -r f; do [ -n "$f" ] || continue case " $VERSION_STAMP_MANIFESTS " in diff --git a/VERSIONING.md b/VERSIONING.md index 7c3a53493..1ba485a44 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -131,13 +131,17 @@ match `package.json`: - `.claude-plugin/plugin.json` — Claude Code plugin manifest (issue #766) - `gemini-extension.json` — Gemini CLI extension manifest (issue #775) +- `.claude-plugin/marketplace.json` — Claude plugin marketplace manifest; its + version lives at `plugins[0].version` and is stamped via a nested versionKey + descriptor (issue #1855) The `version` npm lifecycle script (`scripts/sync-manifest-versions.cjs --stage`) stamps these files automatically on every `npm version` call, and stages them so they are included in the release commit alongside `package.json`. -To add a new manifest that must track the package version, register its path in -the `VERSIONED_MANIFESTS` array in `scripts/sync-manifest-versions.cjs`. A +To add a new manifest that must track the package version, register its path +(and, if its version field is not top-level, its dotted `versionKey`) in the +`VERSIONED_MANIFESTS` array in `scripts/sync-manifest-versions.cjs`. A regression test (`tests/issue-844-manifest-version-sync.test.cjs`) enforces this: it scans all committed JSON files for a matching `version` field and fails if any are missing from the registry. diff --git a/docs/how-to/install-on-your-runtime.md b/docs/how-to/install-on-your-runtime.md index daed18174..bd11f0756 100644 --- a/docs/how-to/install-on-your-runtime.md +++ b/docs/how-to/install-on-your-runtime.md @@ -102,6 +102,15 @@ The `gsd-tools` binary (installed as part of the `@opengsd/gsd-core` npm package Node.js (`node`) must also be available on your `PATH`. The plugin's always-on guard hooks (wired in `hooks/hooks.json`) are invoked as `node "${CLAUDE_PLUGIN_ROOT}/hooks/