Skip to content

v2.4.0

Choose a tag to compare

@github-actions github-actions released this 25 Aug 08:46
· 119 commits to main since this release
v2.4.0
f5ea5ec

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 for old-pkg@1.0.0 against a config for new-pkg@1.0.0
    looked current forever. The docker case was already covered — a version
    against a digest is incomparable, which is not not_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, because package is a bare name
    carrying no ecosystem and npm, pypi and cargo all produce orderable release
    versions — so npm foo@1.0.0 and pypi foo@1.0.0 were 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 prints srv: 1.0.0 -> 1.0.0. Confusing to read, but not wrong — that
    entry genuinely does need regenerating.

  • pmcp refresh --check-versions now honours --cache-dir. run_refresh
    computed the cache path from --cache-dir and then called check_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-versions at a non-default cache was reading a different file than
    they named, with nothing in the output to say so.

Changed

  • pmcp refresh --check-versions now reports a server whose package it cannot
    look up separately, as unconfirmed rather than as stale.
    A server launched
    as node /opt/srv.js or python -m thing has 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 a Run '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 plain pmcp refresh. Previously these servers were skipped in
    silence. A manifest of only registry-installed (npm/pypi/cargo/docker) servers
    is unaffected.
  • refresh_all now 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 a node/python server 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.