From 3415e70dc6f2b447c80dc4b00a016088f7e3222f Mon Sep 17 00:00:00 2001 From: Igor Lins e Silva <4753812+igorls@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:32:37 -0300 Subject: [PATCH 1/3] chore: bump plugin manifests to 3.3.0 and fix owner URL Aligns marketplace.json and both plugin.json files with version.py / pyproject.toml (already at 3.3.0) so `/plugin update` reflects the v3.1.0/v3.2.0/v3.3.0 tags that had been landing without manifest bumps. Also updates marketplace.json `owner.url` from the stale github.com/milla-jovovich path to the current github.com/MemPalace org. Refs #874 --- .claude-plugin/marketplace.json | 4 ++-- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6b23ccf..cbe6307 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -2,14 +2,14 @@ "name": "mempalace", "owner": { "name": "milla-jovovich", - "url": "https://github.com/milla-jovovich" + "url": "https://github.com/MemPalace" }, "plugins": [ { "name": "mempalace", "source": "./.claude-plugin", "description": "AI memory system — mine projects and conversations into a searchable palace. 19 MCP tools, auto-save hooks, guided setup.", - "version": "3.0.14", + "version": "3.3.0", "author": { "name": "milla-jovovich" } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 20b2cb2..ba5759a 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mempalace", - "version": "3.0.14", + "version": "3.3.0", "description": "Give your AI a memory — mine projects and conversations into a searchable palace. 19 MCP tools, auto-save hooks, and guided setup.", "author": { "name": "milla-jovovich" diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 23d3ee7..9017d9b 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mempalace", - "version": "3.0.14", + "version": "3.3.0", "description": "Give your AI a memory — mine projects and conversations into a searchable palace. 19 MCP tools, auto-save hooks, and guided setup.", "author": { "name": "milla-jovovich" From 06240c73b3b2a4fbb00409ff41d87fd5bc33932f Mon Sep 17 00:00:00 2001 From: Igor Lins e Silva <4753812+igorls@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:32:44 -0300 Subject: [PATCH 2/3] ci: add version guard to catch tag/manifest drift Fails a tag push if `vX.Y.Z` does not match `mempalace/version.py` (the single source of truth per CLAUDE.md), and fails PRs that touch any version file without keeping all five in sync (pyproject.toml, version.py, .claude-plugin/marketplace.json, .claude-plugin/plugin.json, .codex-plugin/plugin.json). Prevents the class of bug described in #874, where v3.1.0/v3.2.0/v3.3.0 tags all landed pointing at commits that still carried manifest version 3.0.14, blocking `/plugin update` for end users. Refs #874 --- .github/workflows/version-guard.yml | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/version-guard.yml diff --git a/.github/workflows/version-guard.yml b/.github/workflows/version-guard.yml new file mode 100644 index 0000000..ea9e730 --- /dev/null +++ b/.github/workflows/version-guard.yml @@ -0,0 +1,85 @@ +name: Version Guard + +on: + push: + tags: ['v*'] + pull_request: + paths: + - 'pyproject.toml' + - 'mempalace/version.py' + - '.claude-plugin/marketplace.json' + - '.claude-plugin/plugin.json' + - '.codex-plugin/plugin.json' + - '.github/workflows/version-guard.yml' + +jobs: + check-versions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Extract versions from all sources + id: versions + run: | + set -euo pipefail + py_version=$(grep -E '^__version__' mempalace/version.py | cut -d'"' -f2) + pyproject_version=$(grep -E '^version' pyproject.toml | head -1 | cut -d'"' -f2) + marketplace_version=$(jq -r '.plugins[0].version' .claude-plugin/marketplace.json) + plugin_version=$(jq -r '.version' .claude-plugin/plugin.json) + codex_version=$(jq -r '.version' .codex-plugin/plugin.json) + + echo "py_version=$py_version" >> "$GITHUB_OUTPUT" + echo "pyproject_version=$pyproject_version" >> "$GITHUB_OUTPUT" + echo "marketplace_version=$marketplace_version" >> "$GITHUB_OUTPUT" + echo "plugin_version=$plugin_version" >> "$GITHUB_OUTPUT" + echo "codex_version=$codex_version" >> "$GITHUB_OUTPUT" + + { + echo "## Detected versions" + echo "" + echo "| Source | Version |" + echo "| --- | --- |" + echo "| mempalace/version.py | \`$py_version\` |" + echo "| pyproject.toml | \`$pyproject_version\` |" + echo "| .claude-plugin/marketplace.json | \`$marketplace_version\` |" + echo "| .claude-plugin/plugin.json | \`$plugin_version\` |" + echo "| .codex-plugin/plugin.json | \`$codex_version\` |" + } >> "$GITHUB_STEP_SUMMARY" + + - name: Verify all sources agree + env: + PY: ${{ steps.versions.outputs.py_version }} + PYPROJECT: ${{ steps.versions.outputs.pyproject_version }} + MARKETPLACE: ${{ steps.versions.outputs.marketplace_version }} + PLUGIN: ${{ steps.versions.outputs.plugin_version }} + CODEX: ${{ steps.versions.outputs.codex_version }} + run: | + set -euo pipefail + fail=0 + check() { + local name="$1" value="$2" expected="$3" + if [[ "$value" != "$expected" ]]; then + echo "::error file=$name::version mismatch — expected $expected, got $value" + fail=1 + fi + } + # All five must agree with each other (use version.py as the reference, per CLAUDE.md) + check "pyproject.toml" "$PYPROJECT" "$PY" + check ".claude-plugin/marketplace.json" "$MARKETPLACE" "$PY" + check ".claude-plugin/plugin.json" "$PLUGIN" "$PY" + check ".codex-plugin/plugin.json" "$CODEX" "$PY" + exit $fail + + - name: Verify tag matches manifest (tag pushes only) + if: startsWith(github.ref, 'refs/tags/v') + env: + PY: ${{ steps.versions.outputs.py_version }} + run: | + set -euo pipefail + tag_version="${GITHUB_REF_NAME#v}" + if [[ "$tag_version" != "$PY" ]]; then + echo "::error::tag $GITHUB_REF_NAME does not match manifest version $PY" + echo "Bump mempalace/version.py, pyproject.toml, and all plugin manifests before tagging." + exit 1 + fi + echo "Tag $GITHUB_REF_NAME matches manifest version $PY" From 162edf39fe431ebd9c82656fa0b497f2175f2b6c Mon Sep 17 00:00:00 2001 From: Igor Lins e Silva <4753812+igorls@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:34:54 -0300 Subject: [PATCH 3/3] ci: let semver pre-release tags bypass strict manifest match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tags matching `vX.Y.Z-*` (e.g. v3.4.0-rc1, v1.0.0-beta.2) are treated as internal/staging builds. They skip the tag-vs-manifest check because pre-releases do not flow to end users via `/plugin update`, which reads the manifest on the default branch. Stable tags `vX.Y.Z` still require all five version sources to match exactly, so the protection against the #874 drift remains intact. The cross-file consistency check on PRs is unchanged — all manifests must still agree with mempalace/version.py whenever any version file moves. --- .github/workflows/version-guard.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/version-guard.yml b/.github/workflows/version-guard.yml index ea9e730..9cb30fe 100644 --- a/.github/workflows/version-guard.yml +++ b/.github/workflows/version-guard.yml @@ -77,9 +77,25 @@ jobs: run: | set -euo pipefail tag_version="${GITHUB_REF_NAME#v}" + + # Semver pre-release tags (v3.4.0-rc1, v1.0.0-beta.2, ...) are treated + # as internal/staging and are not validated against the manifest. They + # do not flow to end users via `/plugin update`, which reads the + # manifest on the default branch. + if [[ "$tag_version" == *-* ]]; then + echo "Pre-release tag $GITHUB_REF_NAME — skipping strict manifest match." + { + echo "" + echo "> Pre-release tag detected: \`$GITHUB_REF_NAME\`." + echo "> Manifest ($PY) is not required to match. Pre-releases are not published via \`/plugin update\`." + } >> "$GITHUB_STEP_SUMMARY" + exit 0 + fi + if [[ "$tag_version" != "$PY" ]]; then echo "::error::tag $GITHUB_REF_NAME does not match manifest version $PY" - echo "Bump mempalace/version.py, pyproject.toml, and all plugin manifests before tagging." + echo "Bump mempalace/version.py, pyproject.toml, and all plugin manifests before tagging a stable release." + echo "For an internal/staging tag, use a semver pre-release suffix (e.g. v${PY}-rc1)." exit 1 fi echo "Tag $GITHUB_REF_NAME matches manifest version $PY"