fix(marketplace): bump withheld pins + CI pin-staleness gate#182
Conversation
zetetic-team-subagents 2.29.0 -> 2.34.0 (six withheld releases: 2.30.0-2.34.0 incl. the §15 rules, redaction gates, Fable loops) and cortex-viz 2.6.3 -> 2.7.1 (two withheld releases). Root cause: nothing compared marketplace pins against downstream release tags, so releases shipped to zero installs with no signal. Gate: scripts/check_marketplace_pins.py distinguishes PIN_BEHIND_RELEASE (release never delivered) from SELF_PIN_MISMATCH (local pin vs plugin.json), per zetetic-team-subagents#52's two-sided criterion. Workflow runs on PR/push over the manifest AND weekly cron (pins go stale by inaction; inaction never opens a PR) + workflow_dispatch. Verified externally: exit 1 naming both stale pins pre-bump, exit 0 post-bump; 10 unit tests green. Closes #179 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…metadata.description The marketplace name stays cortex-plugins (brand-level umbrella over four plugins); hypermnesia-mcp is one package inside it, renamed at the plugin level only over the directory name collision. Stating this in metadata resolves the naming question at first contact with zero install breakage (a marketplace rename would orphan every plugin@cortex-plugins key on every install). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AssessmentThis addresses the real defect. The github-sourced path is the class that caused the incident, Five clauses from #179 are still open. 1. Fail-open is not implemented (criterion 5) — blocking
Criterion 5 asked for the opposite behaviour, in these words: "a rate-limited or offline GitHub API degrades to silence, never to a red build on an unrelated PR. The offline path is tested." This matters more than it looks because of the trigger set: the workflow runs on every PR touching the manifest, so a transient GitHub blip turns an unrelated PR red, and the standard response to a flaky gate is to stop trusting it — which returns us to manual discipline, the thing the issue exists to remove. Anonymous rate limiting is 60 req/h and the cron is unauthenticated-adjacent if the token is ever absent. 2. Two arms unhandled and untested (criterion 6)
Both were named explicitly in criterion 6. 3. Release count missing from the message (criterion 3)The message gives name, pin, repo and latest tag. Criterion 3 also asked for "the release count between them" — that is what turns the line from a version mismatch into an impact statement ("six releases withheld" is what made #179 legible, and it is exactly the number the PR body computes by hand). 4. Release procedure not documented or wired (criterion 4)Nothing in the diff touches a release workflow or docs. Criterion 4 asked to "state explicitly whether the bump is automated (preferred: a repository-dispatch from the downstream release workflow) or manual-with-a-CI-gate, and wire whichever is chosen." Today it is manual-with-a-CI-gate by default rather than by decision, and the cron gives at most a 7-day detection bound rather than delivery. 5. Deprecated
|
…, frozen audit, server.json leg Addresses the PR #182 review in full: - fail-open: network errors degrade to NOTICE + exit 0 (tested offline path) — a gate that reddens PRs during outages gets disabled and the gap recurs with the gate nominally in place - no-releases arm: releases/latest 404 -> NOTICE, no KeyError - release counts in both stale messages (releases_between / tags_between; degrade to countless message, never None-in-string) - PIN_BEHIND_TAG: local-source pins compared against the repo's own latest semver git tag — detection now ORIGINATES offline, catching the both-manifests-stale state (AP #67 replay is the load-bearing test) - SERVER_JSON_SPLIT: the third leg of the three-way split guarded - frozen-pin allowlist with audit reason: the cortex deprecation shim is explicitly frozen at 4.15.0 by design, not silently passing - release procedure wired: CLAUDE.md Releasing section — the checklist ends at the pin, not the tag - canonical-copy header: AP carries a byte-identical copy with a weekly CI drift check against this file 15 unit tests (unittest-style so AP runs them without pytest). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review addressed in full (commit pushed) + Completion Ledger (§13.2)
Also folded earlier: metadata.description disambiguation (cortex-plugins umbrella vs hypermnesia-mcp package). |
All six items from the previous review are fixed
One thing left: the PR body no longer describes the PRThe body still reads as the first revision. It documents two failure classes and "10 unit tests", while the code now carries That matters beyond tidiness here: SequencingMerge this before cdeust/automatised-pipeline#68. Its |
Closes #179 — releasing a downstream plugin doesn't ship it. Delivery is gated by pins in this repo's
marketplace.json, and nothing watched them.Pins bumped (the six-release gap, closed)
zetetic-team-subagents2.29.0 → 2.34.0 (withheld: 2.30.0, 2.31.0, 2.32.0, 2.32.1, 2.33.0, 2.34.0 — including §15, the redaction gates, the Fable loops)cortex-viz2.6.3 → 2.7.1 (withheld: 2.7.0, 2.7.1)Eight releases reached zero installs. No error, no warning, no diff — the manifests were internally consistent the whole time, which is why nothing noticed.
Failure classes
PIN_BEHIND_RELEASEPIN_BEHIND_TAGSELF_PIN_MISMATCHplugin.jsonSERVER_JSON_SPLITserver.json≠ the primary marketplace pin — the third version-carrying fileTwo-sided by design per cdeust/zetetic-team-subagents#52:
installed < pinandpin < releaseare different defects with different owners, and a one-sided check reports false compliance.Frozen pins are a declared contract
FROZEN_PINSnames the deprecation shim (cortex4.15.0, frozen at the hypermnesia-mcp rename) so "intentionally not advancing" is machine-checked and stated at the use site per §8, rather than passing by accident because two files happen to agree. Manifest coherence is still enforced for frozen entries; only the tag-advance check is skipped.Degraded modes are explicit, never silent
Network failure, rate limiting and releaseless repos emit
NOTICE: … network degradedand the run stays green — a gate that goes red on a GitHub blip gets disabled within a month, and then the six-release gap recurs with the gate nominally in place. The summary line reports that notices occurred, so degraded ≠ verified.One artifact, not two copies
This file is the canonical copy. cdeust/automatised-pipeline carries a byte-identical copy and diffs against
Cortex/mainweekly, so the two cannot drift into a version where one is a no-op. Verified identical at time of writing.Prevention, not just detection
CLAUDE.mdgains a Releasing section: the checklist ends at the pin bump pluscheck_marketplace_pins.pyexiting 0. The gate detects a stale pin; the procedure stops one being created.Completion Ledger (§13.2)
Paths introduced → asserting test
parse_semverv-prefix and baretest_v_prefix_and_bareparse_semvernon-semver →Nonetest_non_semver_nonetest_numeric_not_lexicographic(2.9.0 < 2.10.0)PIN_BEHIND_TAGfires when both manifests agree but the tag is aheadtest_incident_replay_both_manifests_stale_tag_ahead— fails on the pre-fix code (§13 G2)PIN_BEHIND_TAGsilent when currenttest_current_pin_green(negative assertion, §13 G4)test_untagged_repo_no_crash_no_flagtest_frozen_pin_skips_tag_check_keeps_coherencePIN_BEHIND_RELEASEfires, with release counttest_stale_flagged_with_counttest_stale_flagged_count_degradedtest_current_and_ahead_passtest_network_failure_degrades_to_noticeKeyErrortest_no_releases_repo_is_notice_not_keyerrortest_unparseable_tag_reportedSERVER_JSON_SPLITthird leg flaggedtest_three_way_split_third_leg_flaggedserver.json→ passtest_aligned_passes_and_absent_passes§13.1 checklist
server.json, manifestless shim, frozen pin — each mapped abovegit tag; bounded by manifest sizeurlopenas a context manager withAPI_TIMEOUT_S; no leaked handlessubprocess.runwith an argument listGITHUB_TOKENread from env, never logged; workflow ispermissions: contents: readFROZEN_PINSand the canonical-copy coupling are new contracts, declared above and in-file. Cross-platform: git + stdlib onlyNOTICE: … network degraded, surfaced again in the summary linetest_incident_replay_both_manifests_stale_tag_aheadtmp_path; no fixed paths, no sleeps, no networktest_current_pin_green,test_current_and_ahead_pass,test_aligned_passes_and_absent_passesscripts/, tests undertests_py/scripts/CLAUDE.mdReleasing section added; marketplace description corrected for the hypermnesia-mcp renamemetadata.descriptionwas stale on the v4.15.0 rename — corrected here rather than leftVerification quoted
🤖 Generated with Claude Code
https://claude.ai/code/session_016gFqzbbNDwPtFzaoGDti7R