Measured on one machine, 2026-08-14, while preparing 0.9.0.
Four generations of this product were running simultaneously
$ ps -axo pid=,ppid=,args= | grep -i 'commitlore.*mcp'
47260 ~/.local/share/commitlore/v0.8.1/dist/commitlore.mjs
91147 ~/.local/share/commitlore/v0.8.1/dist/commitlore.mjs
79775 ~/.local/share/commitlore/v0.8.1/dist/commitlore.mjs
34918 ~/.claude/plugins/cache/commitlore/commitlore/0.6.0/dist/commitlore.mjs
26878 ~/.claude/plugins/cache/commitlore/commitlore/0.6.0/dist/commitlore.mjs
35102 ~/.local/share/commitlore/dev-3b70a1bebfb3/dist/commitlore.mjs
v0.8.1, 0.6.0 and a dev hash, while the repository and .claude-plugin/plugin.json both say 0.8.2.
~/.claude/plugins/cache/commitlore/commitlore/0.6.0 does not exist on disk. Those two processes are holding a deleted directory's inodes and answering from it.
Why a release does not fix this
There are two distribution paths and only one of them is a release:
- the CLI wrapper
~/.local/bin/commitlore — rewritten by install.sh every time, so anything wired through it follows a new version automatically
- the Claude Code plugin — copied into
~/.claude/plugins/cache/ from the marketplace, and install.sh never touches it
The MCP tools an agent actually calls come from the second. So tagging a release and running the installer leaves the tools the users hold at whatever version their cache last copied.
What doctor sees, and what it does not
#644 landed today and its check fires correctly on the surfaces that are registered:
warn runtime-identity hook identity differs from CLI: hook v0.8.2; entry …/v0.8.2/dist/commitlore.mjs
It cannot see the list above, because config says what was registered and the process table says what is answering. A process holding a deleted install is invisible to every configuration-derived check by construction.
The branch f001-red-multi-runtime (b20f465) was written for exactly this and adds delivery-mcp-runtime-identity, enumerating live runtimes rather than declared ones. It was held until #644 and #636 landed; both have.
Suggested acceptance
doctor reports when a live MCP runtime's version differs from the installed CLI's, rather than staying silent
- the release procedure checks
.claude-plugin/plugin.json against package.json before tagging, so a version bump cannot land on one and not the other
- the release notes say that plugin users need the marketplace refreshed and their session restarted, because until then the old MCP server keeps answering
The pattern this belongs to
Fourth instance today of one shape: a version-pinned path keeps answering after a newer generation arrives, and nothing fails.
Each was found separately. They are the same defect: a comparison whose two sides are not bound to the same generation, resolved silently in favour of the older one.
Not doing
The running processes belong to sessions that must not be interrupted. Updating them is what happens when their owner restarts; the work here is making sure the right version arrives when they do.
Measured on one machine, 2026-08-14, while preparing 0.9.0.
Four generations of this product were running simultaneously
v0.8.1,0.6.0and a dev hash, while the repository and.claude-plugin/plugin.jsonboth say0.8.2.~/.claude/plugins/cache/commitlore/commitlore/0.6.0does not exist on disk. Those two processes are holding a deleted directory's inodes and answering from it.Why a release does not fix this
There are two distribution paths and only one of them is a release:
~/.local/bin/commitlore— rewritten byinstall.shevery time, so anything wired through it follows a new version automatically~/.claude/plugins/cache/from the marketplace, andinstall.shnever touches itThe MCP tools an agent actually calls come from the second. So tagging a release and running the installer leaves the tools the users hold at whatever version their cache last copied.
What doctor sees, and what it does not
#644 landed today and its check fires correctly on the surfaces that are registered:
It cannot see the list above, because config says what was registered and the process table says what is answering. A process holding a deleted install is invisible to every configuration-derived check by construction.
The branch
f001-red-multi-runtime(b20f465) was written for exactly this and addsdelivery-mcp-runtime-identity, enumerating live runtimes rather than declared ones. It was held until #644 and #636 landed; both have.Suggested acceptance
doctorreports when a live MCP runtime's version differs from the installed CLI's, rather than staying silent.claude-plugin/plugin.jsonagainstpackage.jsonbefore tagging, so a version bump cannot land on one and not the otherThe pattern this belongs to
Fourth instance today of one shape: a version-pinned path keeps answering after a newer generation arrives, and nothing fails.
~/.hermes/config.yamlpinsv0.8.2skills, and old version directories are never removed, so a 0.9.0 binary would read 0.8.2 skills silentlyEach was found separately. They are the same defect: a comparison whose two sides are not bound to the same generation, resolved silently in favour of the older one.
Not doing
The running processes belong to sessions that must not be interrupted. Updating them is what happens when their owner restarts; the work here is making sure the right version arrives when they do.