Repository navigation
fix: remove the automatic update notices (#150) - #159
Conversation
Maintainer decision after the board rejected the eighth attempt 3/3 and explicitly recommended removal. gateway.update_server is unchanged; what goes is the gateway VOLUNTEERING a claim it cannot substantiate. Surface enumerated from source rather than assumed: 3 emission sites (catalog_search stale_updates, describe and invoke update_warning across six invoke return paths), the background indexer plus its two server.py lifecycle calls, and FOUR PUBLIC SCHEMA FIELDS across CatalogSearchOutput, SchemaCard, InvokeOutput and ProvisionOutput. Also README:480, which promises the field. Flagged honestly: unlike every prior plan in this series, this one DOES change the protocol surface, and ProvisionOutput.update_warning has a writer outside the three known sites that must be traced rather than assumed dead. Open question left for the board: remove the fields outright, retain them as permanently-None, or deprecate for one release.
…th site Traced before boarding, as the plan itself flagged. provision does not merely carry the field: it calls _get_update_warning at handlers.py:4188 and attaches update_warning at TEN further return paths. Total attachment points are 16 (describe 1, invoke 5, provision 10), not the six originally documented. A removal stopping at describe/invoke would leave provision calling a deleted method -- the half-removal failure the plan warns about.
…ast radius _effective_notice_target and _notice_package_matches_cache have ZERO references in src/ or tests/. The plan claimed they were 'used only by the above'; in fact they were never wired in and are already-dead residue from the abandoned #154 attempts. Also recorded: all deleted machinery is confined to handlers.py, but 15 TEST references depend on _stale_check_cache -- so the test deletions are the larger part of this change, and each needs classifying as 'asserts the removed feature' versus 'asserts update_server'.
The board caught a second undercount. Authoritative count from source: grep -c 'update_warning=' handlers.py = 26, plus 3 _get_update_warning calls. describe 1, invoke 5, provision TWENTY (4200 through 4630). My first draft said 6. My own pre-board correction said 16, because I stopped reading the grep output at 4411 when it continues to 4630. The miscount pattern is itself the finding: provision holds 20 of 26 sites, so the edit is concentrated exactly where I kept failing to look. Implementation must be driven by grep -c reaching zero, not by any hand-enumerated list.
Board review of this PR. gateway.update_server's description still read 'Use this when invoke/describe/provision warn that a newer version is available' -- shipped to every client through tools/list, instructing agents to wait for notices this PR removes. My completeness check could not catch it: the grep searched IDENTIFIERS, and this is PROSE. Added a guard over get_gateway_tool_definitions() so the class of gap is closed, not just this instance. Verified it goes RED against the old wording.
Board review: 1 AGREE / 1 PARTIALLY AGREE / 1 DISAGREE — one real defect, fixedcodex found a blocking defect that my own completeness check structurally could not catch, and it was a good catch. The defect
That string ships to every client through Why my verification missed it: the completeness grep searched identifiers — The fixReworded to say the gateway does not volunteer notices, so nothing will prompt you. More importantly, added I swept the rest of Answers to the other review questions, verified
Verification
|
Minor rather than patch: #159 removes four fields from public tool output (update_warning from describe/invoke/provision, stale_updates from catalog_search), which is a breaking change for a client reading them. Also merges the two duplicate '### Fixed' headings that accumulated under [Unreleased] from three separate PRs, and syncs __init__.__version__, which pyproject alone would have left at 2.1.1.
Closes #150.
Removes the automatic "update available" notices.
gateway.update_serveris unchanged — it still probes, reports, restarts and refuses pinned servers. What goes away is the gateway volunteering a claim it cannot substantiate.Why removal rather than a ninth fix
Eight attempts failed at one joint: pmcp cannot observe which package artifact a running server is executing. Not from
descriptions_cache.version(an upstream snapshot taken at describe time), not fromserverInfo.version(an implementation version — FastMCP 1.x reports the SDK's, mcp 2.x defaults to""), not from the npx/uv runner caches (no server→entry binding; one package was observed cached at 1.2.0, 1.2.1 and 1.2.2 concurrently), and not from spawn argv (npm resolves aftercreate_subprocess_execreturns).The only remaining method — running each server's own
--version— was rejected 3/3 by the review board as disqualifying: it is a full launch of the server's argv with its real credentials, on a schedule. For a manifest entry using@latestit could execute newly published code with those credentials before the operator chose to update. Measured: probing one flag-ignoring server spawned 7 processes and opened 5 sockets. Coverage would have been ~50% even then.The full analysis for all eight attempts is committed under
.consiliency/plans/.What this is: a breaking change to tool output
update_warningandstale_updatesare removed from the schemas, not left permanently empty.server.pyserialises withmodel_dump()and noexclude_none, so those keys are emitted today as explicit nulls — verified — which means their absence is a real wire change for a client doing key-presence checks.The board recommended outright removal over keeping always-
Nonefields or deprecating across a release: a field that can never be populated advertises a capability pmcp no longer has.Scope
update_warning=attachment sitesdescribe1,invoke5,provision20)_get_update_warningcallsserver.py×2)I miscounted the attachment sites twice before the board caught it — first 6, then 16, when the real number is 26.
provisionalone holds 20. The plan was corrected to mandate drivinggrep -cto zero rather than working from any hand-written list, and that is how the edit was performed.Two other findings while implementing:
_effective_notice_targetand_notice_package_matches_cachenever existed onmain(dead residue of the abandoned #154 branch), and the README had two obsolete lines, not the one the plan identified — the second promised "background stale-version indexing is active".Verification
pytest -q→ 2547 passed, 3 skipped, 0 failed (2555 baseline − 11 removed + 3 added)ruff check .,ruff format --check src/ tests/,mypy src— cleangrep -rn 'update_warning|stale_updates|_stale_check_cache|_stale_index|_get_update_warning' src/ tests/returns nothingNeed help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.