fix(release): restore the MCP Registry marker and make gate failures diagnosable - #264
Merged
Merged
Conversation
…diagnosable Two independent release-path defects found while auditing the v0.84.1 merge. Both are ports of work already on private master, or fixes to public-only gaps. 1. MCP REGISTRY OWNERSHIP MARKER (blocks every registry publish) Publishing to the MCP Registry has failed since 0.84.0 with HTTP 400: "PyPI package 'graqle' ownership validation failed. The server name must appear as 'mcp-name: io.github.quantamixsol/graqle' in the package README". Root cause: the marker lives in README.md, but pyproject.toml sets readme = "README_PYPI.md". The registry reads the PyPI long_description, not the GitHub README, so the published artifact never carried it. The marker was in the wrong file. Fixed by adding it to README_PYPI.md (CRLF preserved; the diff is 2 lines). VERIFIED IN THE BUILT ARTIFACT: graqle-0.84.1-py3-none-any.whl METADATA now contains the marker, which is what the registry actually reads. Ports tests/test_packaging/test_mcp_name_marker_in_pypi_readme.py from private. It asserts against the pyproject readme POINTER rather than a hard-coded filename, because the defect was a pointer move silently invalidating an assumption about which file ships. Proven by removing the marker: the guard fails, then passes once restored. 2. RELEASE GATE FAILURES WERE UNDIAGNOSABLE Release Gate (PyPI) has been red on every PR. Both provider-exception handlers logged only type(exc).__name__ -- no message, no traceback -- so every failure read as a bare class name and the cause stayed unknown across multiple releases. Now logger.exception with %r, so the operator log carries type, message and traceback. The verdict object is deliberately NOT changed: it is user-facing and the module's IP-redaction contract requires it stay free of internal detail. The two surfaces have opposite requirements and the new test asserts both -- exception text present in the log, absent from the verdict JSON. Proven: reverting to the old logging makes the new test fail. NOT INCLUDED, deliberately: making the gate fail CLOSED (WARN -> BLOCK) on internal error. Research asked for it, and it is the right end state, but it flips a governance contract pinned by four existing tests and documented as the module's "never-crash" behaviour. Changing what a gate does to a release needs an explicit decision, not a drive-by edit. Raised separately. Verified: 92 passed / 1 skipped across test_release_gate + test_packaging. TS scan on the diff: clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
🛡️ GraQle PR Guardian💥 Blast Radius: 4 modules affected
Total blast radius: 4 🏛️ Governance Verdict
|
| Metric | Value |
|---|---|
| Blast Radius | 4 |
| Files Analyzed | 4 |
| Blocked | 0 |
| SHACL Violations | 0 |
| Verdict | WARN |
🔬 Powered by GraQle PR Guardian v0.1.0 · Scan completed 2026-09-23T14:35:50.851832+00:00
harishquantamix
approved these changes
Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two release-path fixes found auditing the v0.84.1 merge
Neither is a regression from #263 — both were already broken and were surfaced by auditing the merge.
1. MCP Registry ownership marker — the wrong README
Publishing to the MCP Registry has failed since 0.84.0 with HTTP 400:
Root cause: the marker lives in
README.md, butpyproject.toml:23setsreadme = "README_PYPI.md". The registry reads the PyPIlong_description, not the GitHub README, so the published artifact never carried the marker. CR-README-01 repointedpyproject.readmeand did not carry the marker across; 0.83.0 published fine, 0.84.0 was the first failure.The marker was simply in the wrong file. Fixed by adding it to
README_PYPI.md— a 2-line diff, CRLF preserved.Verified in the built artifact, not the source:
graqle-0.84.1-py3-none-any.whlMETADATA now contains the marker, which is precisely what the registry reads.Ports
tests/test_packaging/test_mcp_name_marker_in_pypi_readme.pyfrom private master. It asserts against thepyproject.readmepointer rather than a hard-coded filename — the defect was a pointer move silently invalidating an assumption about which file ships, so pinning the filename would miss the next repoint. It also cross-checks the marker againstserver.jsonand keepsREADME.md's copy.Guard proven: removing the marker makes it fail; restoring makes it pass.
This unblocks the registry publish on the next
v*tag.2. Release-gate failures were undiagnosable
Release Gate (PyPI)is red on every PR. Both provider-exception handlers logged onlytype(exc).__name__— no message, no traceback — so the cause stayed unknown across multiple releases.Now
logger.exception(... %r, exc): the operator log carries type, message and traceback.The verdict object is deliberately unchanged. It is user-facing and the module's IP-redaction contract requires it stay free of internal detail. The log and the verdict have opposite requirements; the new test asserts both, so neither can be satisfied by breaking the other.
Guard proven: reverting to the old logging makes the new test fail.
Not included, deliberately
Making the gate fail closed (
WARN→BLOCK) on internal error. Research asked for it and it is the right end state, but it flips a governance contract pinned by four existing tests and documented as the module's "never-crash" behaviour. Changing what a gate does to a release needs an explicit decision with Research naming the semantics — does a timeout block a release, is there an override path — not a drive-by edit. This PR makes the failures diagnosable, which is the prerequisite for deciding that on evidence.🔴 Blocked on the private PR (ABSOLUTE RULE #0)
The release-gate fix has a private counterpart:
quantamixsol/research-development-graqlePR #354. Private has the identical defect, so the fix must land there first or the repos drift.Do not merge this PR until #354 is merged. The MCP marker half is already a port of merged private work (
c80f4ab7).Verification
ip-content-gate(4 paths)trade-secret-wheel-gate --check-monetisationlint-imports(AC-21)sync_manifest_versions.py 0.84.1 --checktests/test_release_gate+tests/test_packagingruff🤖 Generated with Claude Code