fix(distribution): publish hypermnesia-mcp-viz identity - #107
Conversation
cdeust
left a comment
There was a problem hiding this comment.
Maintainer review (via Claude Code cross-harness pass). Direction approved — do not revert the rename. hypermnesia-mcp-viz is the intended identity, consistent with the hypermnesia-mcp rename of Cortex. Remaining blockers are about completing it, not undoing it:
- Atomic sequencing with cdeust/Cortex#351. That PR renames the marketplace entry; this one renames the plugin. Merged separately, each breaks the other during the window. Merge both together, in a coordinated release.
- Migration path for existing installs. Anything pinned to
cortex-viz@cortex-pluginsbreaks, and the MCP tool prefix changes (plugin:cortex-viz:*→plugin:hypermnesia-mcp-viz:*), which invalidates existing permission allowlists, docs, and skill/agent references to the old prefix. Add an explicit migration note (README + CHANGELOG): uninstall/reinstall command and the prefix change. - README install command must be true at merge time —
claude plugin install hypermnesia-mcp-viz@cortex-pluginsonly works once #351's marketplace change is live (follows from 1). - Non-blocking: the removed
cortex-vizconsole alias is a real regression for third-party hosts (Cursor/Windsurf configs invoking the binary directly) — document it in the CHANGELOG.
Clean otherwise: no stdio transport code touched, read-only PG contract intact, .codex-plugin/gemini-extension.json are additive.
cdeust
left a comment
There was a problem hiding this comment.
Second cross-harness pass (Claude Code, Opus 5). Head reviewed: d90966e5 — i.e. including the migration docs commit pushed after the earlier maintainer review. Verdict: REQUEST CHANGES, on one blocker nobody has raised yet: at version 2.8.0 this release is physically unshippable.
Resolved by d90966e5 — confirmed fixed
- Migration path (previous blocker 2) —
README.mdnow carries a "Migrating fromcortex-viz" block withclaude plugin uninstall cortex-viz@cortex-plugins→marketplace update→install hypermnesia-mcp-viz@cortex-plugins, and names the console-command removal for Cursor/Windsurf/VS Code. Good. - CHANGELOG (my B2) — the self-contradicting "existing
cortex-vizcommand remains compatible" sentence is gone, replaced by a Breaking publication rename entry that also states the coordinated-release constraint. Good. - Coordination note (previous blocker 3) —
README.mdnow says the install name only becomes available once this repo and cdeust/Cortex#351 are released together. Good, and stronger than the reciprocal statement, which #351 still lacks. - Console-alias regression (previous non-blocking 4) — now documented. Good.
Still blocking
B1 — cortex_viz/identity.py:10 + pyproject.toml:7: version held at 2.8.0 while the artifact's contents change. Highest-severity finding; raised by neither review so far.
PyPI hypermnesia-mcp-viz 2.8.0 was published 2026-08-03T13:26:14Z (re-verified today; it is the only version on the index). I downloaded the published wheel and read its entry_points.txt:
[console_scripts]
cortex-viz = cortex_viz.__main__:main
hypermnesia-mcp-viz = cortex_viz.__main__:main
This PR changes what 2.8.0 contains — drops a console script, renames the plugin identity — without bumping it. scripts/check_distribution_artifact.py:43 pins version == VERSION and passes locally; Release.yaml's publish step is then rejected by PyPI with 400 "File already exists" on any v2.8.0 re-tag. The rename can never reach PyPI at this version number.
Fix: bump cortex_viz/identity.py:10 to 2.9.0 (removing a published console entry point is breaking — 3.0.0 is defensible), and propagate to pyproject.toml:7, .claude-plugin/plugin.json:4, .claude-plugin/marketplace.json (both metadata.version and plugins[0].version), .codex-plugin/plugin.json:3, gemini-extension.json:3, server.json, and the two README badges (README.md:15). The new CHANGELOG entry sits under ### Changed of the existing ## [2.8.0] section and needs to move with it.
B2 — skills/cortex-visualize/SKILL.md:39,45,65 still document tool identifiers that do not exist — and d90966e5 has now propagated the same wrong notation into README, CHANGELOG and a test that pins it.
The real Claude Code tool names are derived as mcp__plugin_<plugin.json name>_<mcpServers key>__<tool>. Both segments move in this PR (plugin.json:2 and plugin.json:29), so after merge they are exactly:
mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__open_visualization
mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__get_methodology_graph
SKILL.md writes hypermnesia-mcp-viz:open_visualization({}); the new README/CHANGELOG migration text tells users to move allowlists from plugin:cortex-viz:* to plugin:hypermnesia-mcp-viz:*. Neither form is a resolvable tool name, so a user who rewrites a settings.json allowlist from these instructions writes a string that matches nothing — silently, since an unresolvable MCP tool name is dropped by the host without error. Worse, the new tests/test_distribution_identity.py::test_breaking_plugin_migration_is_explicit asserts "plugin:cortex-viz:*" in text and "plugin:hypermnesia-mcp-viz:*" in text, which freezes the incorrect notation as a contract — the same shape as the mistake that orphaned the zetetic agents (agents/*.md declare mcp__plugin_hypermnesia-mcp_cortex__*, which does not exist on the running host).
Fix: use the full mcp__plugin_..._...__tool identifiers in SKILL.md, README and CHANGELOG; relax that test to assert the full form; and add a test asserting the documented strings equal plugin.json's name × mcpServers-key composition. That composition test is the only durable guard against a third rename repeating this.
B3 — README.md:175 still says pip uninstall cortex-viz, and that distribution has never existed.
curl https://pypi.org/pypi/cortex-viz/json → 404 (re-verified today). The only real conflict is a local editable install. State the actual check instead — which cortex-viz — since the genuine residue is a uv tool/pipx shim left by the published 2.8.0 wheel.
B4 — merge atomicity with cdeust/Cortex#351 (previous blocker 1) — confirmed, and escalated.
The installed cortex-plugins pin for this plugin is {"name": "cortex-viz", "source": {"source": "github", "repo": "cdeust/cortex-viz"}} — no ref, no tag, no commit pin. It tracks the default branch, so the moment this merges to main, every existing cortex-viz@cortex-plugins install pulls a plugin.json whose name no longer matches the entry it was installed under. There is no window to plan inside — merge is the shipping event. The PR body's "tag, registry publication and downstream marketplace pin changes are deferred until this source PR merges" is therefore not a safety argument. The durable fix is a ref pin on the Cortex side.
Agreed with the earlier maintainer review
- Rename direction is settled intent; I do not recommend reverting.
- Blocker 1 (atomic sequencing) → confirmed, escalated as B4 above.
- Blocker 2 (migration path) → was correct; now fixed by
d90966e5, with the residualpip uninstallerror carried over as B3. - Blocker 3 (README install command not yet true) → confirmed; now explicitly disclaimed in the README.
- Non-blocking 4 (console-alias removal is a real third-party-host regression) → confirmed with evidence: the published 2.8.0 wheel demonstrably ships
cortex-viz, so users have it on PATH. - "No stdio transport code touched, read-only PG contract intact, Codex/Gemini manifests additive" → confirmed:
cortex_viz/__main__.pydiff is docstring-only,FastMCP(name=DISTRIBUTION_NAME)unchanged, no infrastructure file touched.
Refuted / sharpened
- The prefix claim
plugin:cortex-viz:*→plugin:hypermnesia-mcp-viz:*is directionally right but under-specified, and that under-specification has now been committed to the repo (B2). Two independent fields change, not one, and the resolvable identifier ismcp__plugin_<name>_<serverKey>__<tool>. - "Clean otherwise" does not hold: B1 makes the release unshippable at its current version number.
Non-blocking
.claude-plugin/marketplace.json(new) declares marketplacehypermnesia-mcp-viz-marketplacecontaininghypermnesia-mcp-vizwith"source": "./", whilecortex-pluginswill also carry it — a user with both added must always disambiguate with@marketplace. Valid, but pick one publication path.cortex_viz/__main__.py:1andcortex_viz/server/mcp_tools.py:1,3still saycortex-vizin docstrings. Cosmetic; cheap sweep given the PR claims total identity coverage..agents/plugins/marketplace.json:15sets"authentication": "ON_INSTALL"for a plugin that authenticates nothing (read-only local PG +~/.claudefiles). Likely copied boilerplate.core/layout_engine.py:67andcore/tile_renderer.py:78are one-line edits each, insideexcept ImportErrorinstall hints — strictly identity-related, no rendering path touched. Nothing rides along.- Test adequacy: insufficient for a HIGH-stakes identity change.
scripts/check_distribution_artifact.py:74-85is genuine artifact verification (opens the built wheel, readsMETADATA+entry_points.txt), andtests/test_distribution_identity.py:53-54fails on revert. But every other assertion compares manifests toDISTRIBUTION_NAMEimported fromidentity.py:8— flip that one constant and all cross-manifest checks move together and still pass. The suite proves mutual consistency, not correctness of the chosen identity: no test covers B1 (version immutability vs. PyPI) or B2 (tool-name composition).
Claude Desktop
Unchanged — never supported, no regression, no overclaim. git grep -in "claude desktop|claude_desktop|\.mcpb|\.dxt" over the whole PR tree returns zero hits; the repo ships no manifest.json/.mcpb on either side of the diff; claude_desktop_config.json has no mcpServers. The README never names Desktop. Roadmap gap, not a defect here.
Could not verify
- Claude Code's exact behaviour when a marketplace entry name diverges from the fetched
plugin.jsonname (hard load failure vs. silent stale-name retention). The divergence is certain; the user-visible mode is not. - The PR-body claim "installed Claude and Codex MCP handshakes reported
hypermnesia-mcp-viz2.8.0 and two tools" — note it would report exactly that onmaintoday too, sinceFastMCP(name=DISTRIBUTION_NAME)already resolved tohypermnesia-mcp-vizbefore this PR. As stated, the claim does not evidence what it appears to. - Whether
uv tool/pipxshims from 2.8.0 leave an orphanedcortex-vizbinary after upgrade (asserted as a risk in B3, not empirically tested).
CI at review time: 11/11 SUCCESS.
…ade note The [3.0.0] - 2026-08-04 CHANGELOG heading read as a Keep a Changelog publication claim, but no v3.0.0 git tag, PyPI upload, GitHub release, or MCP Registry entry exist for it, and none ever will — PyPI stayed on 2.8.0 throughout. Users going 2.8.0 -> 3.1.0 would never see a 3.0.0 section on PyPI/GitHub releases, but that section carries the breaking distribution-identity rename (#107) their upgrade depends on. The 3.0.0 heading is annotated (not deleted or redated — it still records when the work landed) as cut-but-never-published, pointing readers to 3.1.0 as the version that actually ships it. 3.1.0 gains an explicit upgrade note stating the breaking change and the exact uninstall/install commands, for a reader who has never heard of 3.0.0. README's raw-MCP install section and docs/ROADMAP.md's "not planned" note both asserted or implied 3.0.0 was an installable version; both corrected to 3.1.0 with the same never-published context. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… commits (#130) * docs(changelog): document undocumented commits, promote Unreleased to 3.1.0 Two merged PRs landed on main without a CHANGELOG entry: #110 (the codebase-intelligence bridge silently disappearing on a clean marketplace install because ap_bridge's discovery filtered on a retired plugin key) and #129 (trace_impact.py's oversized query orchestration split along its real seams, rules/coding-standards.md §4.2). Both are added under Unreleased in their evidenced chronological position, then Unreleased is promoted to [3.1.0] - 2026-08-10, leaving a fresh empty Unreleased. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(release): bump version to 3.1.0 across distribution surfaces pyproject.toml declared 3.0.0 (the breaking-rename major) while 24 commits had landed since v2.8.0, four of them feat (#111 trace streaming, #120 wiki graph endpoint, #122 static export, #123 per-domain export) with no breaking change among them — SemVer calls for a minor bump on top of the already-cut 3.0.0, not a repeat of the same number. Version aligned to 3.1.0 across pyproject.toml, cortex_viz/identity.py, server.json (both the server and package version fields), the Claude/Codex/Gemini plugin manifests, this repo's own Claude marketplace metadata/pin, and uv.lock. `python -m scripts.check_distribution_artifact` passes against the built wheel: "distribution identity OK: hypermnesia-mcp-viz 3.1.0". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: sync README badge and ROADMAP to 3.1.0 Follow-up to the version bump. The README version badge and the ROADMAP's "Current version" / "Last updated" line are not covered by check_distribution_artifact but would otherwise ship stale against the 3.1.0 release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(changelog): mark 3.0.0 as never tagged/published, add 3.1.0 upgrade note The [3.0.0] - 2026-08-04 CHANGELOG heading read as a Keep a Changelog publication claim, but no v3.0.0 git tag, PyPI upload, GitHub release, or MCP Registry entry exist for it, and none ever will — PyPI stayed on 2.8.0 throughout. Users going 2.8.0 -> 3.1.0 would never see a 3.0.0 section on PyPI/GitHub releases, but that section carries the breaking distribution-identity rename (#107) their upgrade depends on. The 3.0.0 heading is annotated (not deleted or redated — it still records when the work landed) as cut-but-never-published, pointing readers to 3.1.0 as the version that actually ships it. 3.1.0 gains an explicit upgrade note stating the breaking change and the exact uninstall/install commands, for a reader who has never heard of 3.0.0. README's raw-MCP install section and docs/ROADMAP.md's "not planned" note both asserted or implied 3.0.0 was an installable version; both corrected to 3.1.0 with the same never-published context. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Summary
Publish the visualizer consistently as
hypermnesia-mcp-vizacross Python,the console entry point, Claude Code, Codex, Gemini, MCP metadata, and release
automation. The breaking identity change now ships as version 3.0.0 because
2.8.0 is already immutable on PyPI.
No active
cortex-vizPython distribution or console alias is introduced.Migration documentation names the actual owner of the old console shim and
uses Claude's full manifest-composed MCP tool names. The PRD bridge now
discovers only
ai-architect-mcp-spec; a deprecatedprd-spec-generatorinstallation is ignored.
Type of change
Verification
107/merge) passes the built-artifact check.Compatibility and migration
Claude Code remains the primary/full host; Codex is additive and Gemini is
third. Existing Claude Code installs must run:
The published
hypermnesia-mcp-viz2.8.0 wheel owned the oldcortex-vizconsole shim; there was no
cortex-vizPyPI distribution to uninstall.Upgrading that same Python distribution to 3.0.0 removes its legacy entry
point. Current docs provide an ownership probe for any remaining manual shim.
Deployment order
maincommit SHA.cdeust/Cortex#351to that durablemainSHA in its marketplace,contract test, and changelog; rerun its CI.
Cortex#351, then publish 3.0.0.Cortex#351must not merge while it points at this PR's pre-squash head. Keepthe interval between steps 1 and 2 short because the old marketplace entry
tracks this repository's default branch until the corrected marketplace lands.
Reviewer checklist