Treat an installed Claude plugin as an upgrade, not as a reason to stop - #688
Merged
Conversation
wire_claude_code returned as soon as `claude plugin list` mentioned commitlore. So a release reached the CLI wrapper and never the plugin cache: the wrapper reported the new version while the tools an agent actually calls stayed at whatever version installed them. Four generations accumulated that way, and v1.0.0 joined them without displacing one -- wrapper 1.0.0, cache 0.8.0. It did not fail. It declined to try, and reported that as skipped. `marketplace update` is the step that was missing, and adding a marketplace that is already present is a no-op, so even the path that did run could not have seen a new version. Every existing installer test reads install.sh as text, which is why this survived: the file contained every string it needed to contain and the control flow never ran. The regression executes the function against a fake `claude` and asserts on which subcommands it invoked. Verified by restoring the early return -- only `plugin list` runs, and both cases fail. This does not make a running session load the new plugin; a host keeps the runtime it loaded. It makes the release arrive, which is the half that was ours. Limit: already installed is the upgrade case, never a skip Blast: system Undo: easy Certainty: firm Provenance: authored Record-Id: r-660plug
CommitLore — record lintTrailers: clean — 1 commit in Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR. |
This was referenced Aug 15, 2026
MongLong0214
added a commit
that referenced
this pull request
Aug 15, 2026
claude-code appeared in neither hosts nor notDetected. install.sh defines has_claude_code and wire_claude_code and calls neither; the enumeration had no branch for it. So the plugin cache went untouched by every release and nothing said so -- notDetected: [] read as "every host was detected", which is how a missing host stays missing. That is worse than #660, which at least reported the wrong thing. This reported nothing, so there was nothing to disbelieve. The enumeration now handles it the way it handles Hermes: refresh the marketplace, then install, healthy only when the install succeeds. Adding a marketplace that is already present is a no-op, so without the refresh a reinstall reinstates the same version -- that is the whole of #660, and it also means #688's fix to wire_claude_code was correct and unreachable. The guard took three attempts and each failure is worth more than the fix. Filtering hosts by "no underscore" dropped wire_claude_code along with wire_codex_mcp -- the guard excluded the case it existed for. Then checking that the name appears in the enumeration passed while claude-code appeared only inside a helper nothing called, which is the defect itself wearing the test as clothes. It now asserts on dispatch: notDetected.push('<host>') or a row in the candidate table, both written only where a host is actually handled. The shell/CLI name difference for gemini is written down rather than worked around. A guard that cannot express a legitimate difference becomes noise and then gets deleted. Limit: a host is wired or reported undetected, never absent Blast: system Undo: easy Certainty: firm Provenance: authored Record-Id: r-689host
MongLong0214
added a commit
that referenced
this pull request
Aug 15, 2026
Five fixes have been sitting on main since v1.0.0 and none of them has reached
anyone. They are all defects at the install and distribution boundary, and that
boundary has exactly one delivery mechanism: a release.
#683 the release workflow failing on a release that already exists
#684 hermes install refusing the config it wrote
#687 the skills root taken from the running bundle instead of --data-root
#688 an installed plugin treated as a reason to stop rather than upgrade
#690 claude-code wired by nothing, in neither hosts nor notDetected
Measured rather than assumed: re-installing with main's install.sh still left the
plugin cache at 0.8.0 and claude-code out of both lists, because the enumeration
that #690 fixed is compiled into the binary being installed -- and that binary is
v1.0.0.
dist is unchanged and the canonical digest is identical to before the bump. The
version is read from package.json at runtime rather than compiled in. Rebuilt
through the canonical builder and verified rather than assumed, the same as
v1.0.0.
Thirty-eight pins across nine files. The installers and READMEs carry the tag in
URLs that resolve only once the tag exists, so this is one commit and the tag
goes on it.
This is the first release cut under release-gate 6c, which asks for an upgrade
over the previous version rather than a fresh install. The five fixes above are
why that section exists.
Limit: a distribution-boundary fix reaches nobody until it is released
Blast: system
Undo: costly
Certainty: firm
Provenance: authored
Record-Id: r-rel101
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Toward #660 — the half that is this product's.
A release reached the CLI wrapper and never the plugin cache. The wrapper
reported the new version while the tools an agent calls stayed at whatever
version installed them. Four generations accumulated that way, and v1.0.0
joined them without displacing one — wrapper
1.0.0, cache0.8.0.It did not fail. It declined to try, and reported that as skipped.
marketplace updateis the missing step. Adding a marketplace that is alreadypresent is a no-op, so even the path that did run could not have seen a new
version.
Why no test caught it
Every existing installer test reads
install.shas text. The file containedevery string it needed to contain; the control flow never ran. That is the same
blindness release-gate §6c is about — a fresh install works, an upgrade does not,
and nothing that starts from nothing can tell.
test/install-plugin-upgrade.test.tsexecutes the function against a fakeclaudeand asserts on which subcommands it invoked. Negative control: restoringthe early return leaves only
plugin list, and both cases fail.What this does not do
It does not make a running session load the new plugin — a host keeps the
runtime it loaded, and that is outside this product. It makes the release
arrive, which is the half that was ours.
Towardrather thanCloses: #660's condition iscommitlore doctor --only mcp-runtime-identityreporting zero unusable runtimes, and that cannot beobserved until an install runs on a machine with stale generations.