You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
packaging: every extra but mcp is unbounded, and the lockfile hides the next 2.0 #103
Each is one major release away from the failure #101 documented: mcp>=1.2 resolved to 2.0.0 for anyone installing fresh, mcp.server.fastmcp no longer existed there, and grapharc[mcp] was broken on arrival.
Why nothing catches it
uv.lock pins the working versions, so the dev environment and every local pytest resolve to what already works. Only a resolver starting from pyproject.toml — that is, a real user running pip install grapharc[...] — sees the new major. The gap is structural, not an oversight: the lockfile's whole job is to keep development reproducible, and that is exactly what hides this.
CI's clean-environment wheel check is the one job that caught #101, and it caught it only because the broken import made a subpackage unwalkable. An extra whose SDK changed shape without breaking import would sail through.
What to consider
A scheduled job (weekly, plus workflow_dispatch) that resolves and installs from pyproject.toml with --upgrade rather than from the lockfile, then imports every subpackage the way ci.yml's build job already does. It must not gate pull requests — an upstream release is not a reason to redden someone's unrelated PR — so it should open or update an issue on failure instead.
Worth deciding alongside it: whether new extras get a ceiling by default. #101's pin is documented as deliberate (raising it means porting off FastMCP), which is the right shape for a bound — a ceiling with a reason attached, not a reflex.
Acceptance criteria
A resolve that ignores uv.lock and takes the newest release of every extra runs on a schedule, imports every subpackage from the built wheel, and reports a failure somewhere a maintainer will see it without it blocking unrelated pull requests.
Closed by #129, with #116 having covered the first half.
Verified by running the job rather than trusting the if: condition.upstream-drift is gated to schedule/workflow_dispatch, so it is skipped on pull requests and would have merged never having executed. Dispatched on the branch, it re-resolved every range from scratch and moved a lot — 1,926 lines of uv.lock, including two major bumps:
Suite green and the wheel walk clean against those. So as of today the package survives the newest release of every extra — which is the thing this issue said nothing could tell you.
What now exists
Acceptance criterion
resolve ignoring uv.lock, newest release of every extra
The walk now lives in scripts/wheel_import_walk.py, shared by build (against what uv.lock pins) and upstream-drift (against what upstream has since released), rather than as two copies of a heredoc.
It caught something on its first run, which is the best argument for it: pointed at the wheel then in dist/, it reported grapharc.examples.plan_research missing — correct, that wheel predated #115.
Still open, on purpose: the ceilings
The eight unbounded extras are unchanged. This issue argues a bound should be "a ceiling with a reason attached, not a reflex", and adding eight at once is the reflex — it would also refuse users upgrades that are fine, as websockets 16 and xxhash 4 just demonstrated. Detection is closed; if you want a pinning policy, that is worth its own issue with the reason recorded per pin, the way #101's mcp pin documents porting off FastMCP.
Activity
ci: a failing drift run reports to the issue tracker, not the Actions…
ci: run the suite weekly against re-resolved dependencies (#116)
Shashankss1205 commentedon Sep 26, 2026
Closed by #129, with #116 having covered the first half.
Verified by running the job rather than trusting the
if:condition.upstream-driftis gated toschedule/workflow_dispatch, so it is skipped on pull requests and would have merged never having executed. Dispatched on the branch, it re-resolved every range from scratch and moved a lot — 1,926 lines ofuv.lock, including two major bumps:Suite green and the wheel walk clean against those. So as of today the package survives the newest release of every extra — which is the thing this issue said nothing could tell you.
What now exists
uv.lock, newest release of every extrauv lock --upgrade(#116)schedule/workflow_dispatchThe walk now lives in
scripts/wheel_import_walk.py, shared bybuild(against whatuv.lockpins) andupstream-drift(against what upstream has since released), rather than as two copies of a heredoc.It caught something on its first run, which is the best argument for it: pointed at the wheel then in
dist/, it reportedgrapharc.examples.plan_researchmissing — correct, that wheel predated #115.Still open, on purpose: the ceilings
The eight unbounded extras are unchanged. This issue argues a bound should be "a ceiling with a reason attached, not a reflex", and adding eight at once is the reflex — it would also refuse users upgrades that are fine, as
websockets 16andxxhash 4just demonstrated. Detection is closed; if you want a pinning policy, that is worth its own issue with the reason recorded per pin, the way #101'smcppin documents porting off FastMCP.