Repository navigation
v2.4.0
Fixed
-
A cached description is now checked against the package that is actually
configured, not just against its version. All three refresh sites —
refresh_server's up-to-date short-circuit,refresh_all, and
check_staleness— paired a cached entry with a server config by name and
then decided freshness by comparing versions alone. Nothing asked whether
the cache still described the same package, so swapping the configured
package at an equal version served the wrong package's tool descriptions
indefinitely: a cache forold-pkg@1.0.0against a config fornew-pkg@1.0.0
looked current forever. The docker case was already covered — a version
against a digest isincomparable, which is notnot_newer— but a
same-ecosystem swap and an npm ↔ pypi ↔ cargo swap were not.Identity is resolved before the comparison at all three sites now. An
unknown side means "cannot confirm identity", and that resolves to
refresh — never to "cannot compare, so skip the check." The second phrasing
is the natural one to reach for and is the same fail-open collapse as
not is_version_newer(...), which shipped three times
(#155, #156, #163) before it was made unrepresentable.The cached entry gained a
package_type, becausepackageis a bare name
carrying no ecosystem and npm, pypi and cargo all produce orderable release
versions — so npmfoo@1.0.0and pypifoo@1.0.0were indistinguishable to
a name comparison. A cache written before this release has no type, reads as
unknown, and refreshes once. Nothing has to be migrated by hand and the cache
format needs no version bump.One cosmetic consequence: a stale report is a
(cached_version, latest_version)pair, so an entry that is stale by identity at an equal
version printssrv: 1.0.0 -> 1.0.0. Confusing to read, but not wrong — that
entry genuinely does need regenerating. -
pmcp refresh --check-versionsnow honours--cache-dir.run_refresh
computed the cache path from--cache-dirand then calledcheck_staleness()
with no arguments, dropping it, so the check silently inspected the default
cache instead of the one that was asked for. Anyone pointing
--check-versionsat a non-default cache was reading a different file than
they named, with nothing in the output to say so.
Changed
pmcp refresh --check-versionsnow reports a server whose package it cannot
look up separately, as unconfirmed rather than as stale. A server launched
asnode /opt/srv.jsorpython -m thinghas no classifiable package, so its
configured identity is unknown, and "cannot confirm identity" resolves to
refresh. That is the right rule — the only alternative is to read "cannot
classify" as "assume it matches", which is the fail-open reading that let a
swapped package look current in the first place — but it would have made such
a server appear under "servers with newer versions" on every run, permanently,
beneath aRun 'pmcp refresh --force' to update.footer that could not settle
it, since the next check still cannot classify the package. So the report is
now split. Servers with a genuinely newer version keep the existing output and
that footer; servers whose current version could not be looked up are listed
under their own heading which says so, notes that this is not the same as
being out of date, and points out that their descriptions are regenerated by
the next plainpmcp refresh. Previously these servers were skipped in
silence. A manifest of only registry-installed (npm/pypi/cargo/docker) servers
is unaffected.refresh_allnow drops an unclassifiable server's cached descriptions when
regeneration fails, where it previously kept them. A server that fails the
identity gate has its cached entry discarded up front and is regenerated; if
that regeneration then fails — the server does not start, a version lookup
times out — neither the failure fallback nor the final merge puts the old
entry back, and the server is left with no cached descriptions until a later
refresh succeeds. For anode/pythonserver this costs something real:
there was never evidence of a package mismatch, only an inability to confirm
one, so a transient startup failure now costs descriptions that were probably
still accurate. Writing back descriptions that may describe a different
package is the outcome this release exists to prevent, so the trade is
deliberate — but it is a trade, not a free win.