Pre-release fixes: anchor sdist includes, and stop retrying non-idempotent writes - #30
Conversation
[tool.hatch.build.targets.sdist] listed "src/", "docs/", "tests/" and friends without a leading slash. Hatchling matches those at any depth, and .claude/worktrees/agent-*/ contains full copies of this repo, so each nested checkout's own docs/, src/ and tests/ were swept in: 1350 extra files, 2 MiB instead of 434 KiB. Some of those copies predate the commit that replaced real example identifiers with placeholders, so the sdist carried tenant values that no longer exist anywhere in the tracked tree. The wheel was unaffected — it builds from `packages` — and `git ls-files` came back clean, so this was invisible to a source audit and only showed up when the built artifact itself was inspected. Anchored every pattern with a leading slash. Verified: sdist identifier matches 35 -> 0, wheel 0, contents now exactly src/tests/packs/docs/examples plus the intended root files.
…otency key The retry loop keyed only on status: `if status in _RETRYABLE and attempt < max_retries`, with no notion of whether repeating the request was safe. Network errors were treated the same way. So a 429/503/504 or a dropped connection on a POST, PATCH or DELETE re-sent a request the server may already have applied. That is not hypothetical for this API. Bound actions such as the LLP-utilisation recalculation take no arguments and mutate on every invocation, so there is no harmless repeat — one gateway 503 could recalculate twice and nothing in the log would say so. The header plumbing for Idempotency-Key already existed and simply was never a precondition for retrying. Retry now requires either a read-only method or a supplied Idempotency-Key, which is what allows a gateway or a future server-side implementation to collapse the duplicate. Otherwise the error surfaces: a visible transient failure the caller can retry deliberately beats an invisible double-write. DELETE and PUT are deliberately excluded despite being idempotent by HTTP semantics — a repeat there surfaces as a 404 or overwrites a concurrent change, and that is not a call an automatic retry should make for the caller. Behaviour change, called out in the changelog. 23 tests; no existing test depended on a mutation being retried.
Second fix added to this PRBoth changes here are things that must be true before 0.7.0 publishes, so they're Non-idempotent requests were being auto-retriedFound by an independent Codex security review of the downstream MCP server, then This is not hypothetical for this API: bound actions like the LLP-utilisation The Now: retry requires a read-only method or a supplied Behaviour change, deliberately. A transient 503 on a write that previously
|
Overview
Blocks the 0.7.0 PyPI release. The sdist was packaging 1350 files it shouldn't,
including pre-sanitisation copies of docs that still carry real tenant identifiers.
[tool.hatch.build.targets.sdist]listed"src/","docs/","tests/"and friendswith no leading slash. Hatchling matches those at any depth, and
.claude/worktrees/agent-*/holds full copies of this repo — so every nestedcheckout's own
docs/,src/andtests/came along.Why it was invisible
git ls-files | grep <identifiers>→ clean. The offending files are git-ignored.packages, not the sdist include list..claude/worktrees/agent-*/docs/configuration.mdand
docs/multi-company.md, from before the commit that replaced real exampleGUIDs with placeholders.
Worth remembering as a general point: for a package that ships an sdist, the source
tree being clean is not the same as the artifact being clean.
Changes
Anchored every pattern with a leading slash, plus a comment explaining why and the
one-liner to re-verify after touching the list.
Test plan
uv build; sdist identifier matches 35 → 0, wheel 0srctestspacksdocsexamples+ README/LICENSE/NOTICE/CHANGELOG/pyprojectuv run pytest— 1075 passed, 5 skippedv0.7.0after this mergesFollow-up, not in this PR
.claude/worktrees/holds 1350 files of stale agent scratch from earlier sessions.Harmless once the sdist ignores it, but worth clearing out.