Skip to content

fix(release): derive the version from the tag, completing #93's rung 1 - #94

Merged
dmarx merged 2 commits into
mainfrom
claude/version-from-release-tag
Aug 16, 2026
Merged

fix(release): derive the version from the tag, completing #93's rung 1#94
dmarx merged 2 commits into
mainfrom
claude/version-from-release-tag

Conversation

@dmarx

@dmarx dmarx commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Rebased onto #93. This PR originally carried both rungs; #93 has since landed rung 2, so this is now only what #93 explicitly deferred:

Rung 1 would be better — derive the version from the tag with hatch-vcs, so there is only one source. Deliberately not bundled here: the publish checkout is actions/checkout@v4 at the default fetch-depth: 1 with no tags fetched, so switching without also setting fetch-depth: 0 would resolve to a 0.1.dev… version and fail the release a second time. Worth its own PR.

This is that PR, with the tag fetch that makes it safe. #93's assertion is kept untouched.

Why both rungs, not just #93's

DP-5's ladder puts derive the projection above guard the property, and rung 2 alone leaves two copies of one fact in place — it just makes their disagreement loud. Deriving removes the second copy; the guard then catches anything that could still go wrong (a shallow checkout, a build-backend change). They're complementary, not alternatives, and the workflow comment now says so.

The change

  • pyproject.toml: dynamic = ["version"], hatch-vcs in build requires, [tool.hatch.version] source = "vcs".
  • publish.yml: fetch-depth: 0 on the build checkout — git describe needs tags, and without this the derived version silently becomes a 0.1.dev… fallback, replacing a loud drift with a quiet one. This is precisely what fix(release): bump to 0.4.0, and make the tag and the version agree #93 flagged.
  • No [tool.hatch.build.hooks.vcs] version file: nothing in the package reads its own version, and writing one out would reintroduce exactly the hand-maintained copy this removes.

Verification

case result
clean checkout on the 0.4.0 tag luria-0.4.0-py3-none-any.whl — no .devN, no local segment
working tree (untagged) 0.4.1.dev3+g0a80de972 — correctly unuploadable, PyPI rejects local segments
pip install -e . works — dynamic version doesn't break dev installs
test suite 425 pass
luria lint clean

A downstream data point

An adopting project was running pip install luria (0.3.0) while its CI pinned dmarx/luria/actions/generate@main. Local lint and CI lint were executing different code, with nothing in either reporting it — because pip install --upgrade luria is a no-op while the release is missing. That's the cost of the quiet failure mode, separate from the release itself being absent.

Notes

@dmarx
dmarx force-pushed the claude/version-from-release-tag branch from 5f17045 to c0205e2 Compare August 16, 2026 14:51
@dmarx dmarx changed the title fix(release): derive the published version from the release tag fix(release): derive the version from the tag, completing #93's rung 1 Aug 16, 2026
claude added 2 commits August 16, 2026 15:14
release tag. It deferred rung 1 — deriving the version — because switching to
hatch-vcs without also fetching tags would have failed the release a second
time by resolving to a `0.1.dev` fallback.

This is rung 1, with the tag fetch that makes it safe.

`pyproject.toml` declares `dynamic = ["version"]` with hatch-vcs reading
`git describe`, so there is one source for the version rather than two that
can disagree. The publish checkout takes `fetch-depth: 0`. No VCS version
file is generated: nothing in the package reads its own version, and writing
one out would reintroduce the hand-maintained copy this removes.

a recurrence loud rather than a PyPI rejection reached after the environment
gate. The two are complementary, and DP-5's own ladder puts derive above
guard rather than instead of it.

A downstream data point for why the quiet failure matters: an adopting
project ran `pip install luria` (0.3.0) while its CI pinned
`dmarx/luria/actions/generate@main`. Local lint and CI lint were executing
different code with nothing reporting it, because `pip install --upgrade
luria` is a no-op while the release is missing.

Verified: a clean checkout on the 0.4.0 tag builds
`luria-0.4.0-py3-none-any.whl` — no `.devN`, no `+g` local segment, which
matters because PyPI rejects local segments outright. A working-tree build
produces `0.4.1.dev3+g0a80de972`, correctly unuploadable. 425 tests pass and
`pip install -e .` still works.

The ADR keeps its temporary code, as #88 did — `luria concretize` assigns
the real number where merges serialize.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpK3k2WhH9Pnc3i6TjLMVv
@dmarx
dmarx force-pushed the claude/version-from-release-tag branch from c0205e2 to 116496c Compare August 16, 2026 15:15
@dmarx
dmarx merged commit ceffb69 into main Aug 16, 2026
4 checks passed
dmarx pushed a commit that referenced this pull request Aug 16, 2026
Merging #94 minted the fifty-third decision, and two acknowledgements that
had been quoting `ADR-053` as a fixture immediately stopped applying:

  record/decisions.d/ADR-014.md:26: annotation names ADR-053, which does resolve
  tests/test_adr_index.py:17:      annotation names ADR-053, which does resolve

Self-inflicted, and worth more than a trim. ADR-014's own comment records
that ADR-032 left the same list for the same reason — "when a real
thirty-second decision arrived and that specimen began to resolve" — and
line 89 anticipated this exact case, treating the annotation as the
mitigation. The annotation is the thing that rots.

So the list is trimmed, and ADR-014 now says why trimming is the symptom
fix: specimens come from the real sequence at all, and `FX-` exists so they
need not. Applying FX- across the remaining specimens is deliberately NOT
bundled — several sit inside hand-written link targets that the FX remote
would want to construct, which produces a new warning class and wants its
own pass.

The test's fixture moves to ADR-404, which is outside any plausible
sequence, with a comment recording why 053 left.

428 tests pass; lint clean, no stale directives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpK3k2WhH9Pnc3i6TjLMVv
dmarx added a commit that referenced this pull request Aug 16, 2026
* fix(record): ADR-053 is a real decision now, not a specimen

Merging #94 minted the fifty-third decision, and two acknowledgements that
had been quoting `ADR-053` as a fixture immediately stopped applying:

  record/decisions.d/ADR-014.md:26: annotation names ADR-053, which does resolve
  tests/test_adr_index.py:17:      annotation names ADR-053, which does resolve

Self-inflicted, and worth more than a trim. ADR-014's own comment records
that ADR-032 left the same list for the same reason — "when a real
thirty-second decision arrived and that specimen began to resolve" — and
line 89 anticipated this exact case, treating the annotation as the
mitigation. The annotation is the thing that rots.

So the list is trimmed, and ADR-014 now says why trimming is the symptom
fix: specimens come from the real sequence at all, and `FX-` exists so they
need not. Applying FX- across the remaining specimens is deliberately NOT
bundled — several sit inside hand-written link targets that the FX remote
would want to construct, which produces a new warning class and wants its
own pass.

The test's fixture moves to ADR-404, which is outside any plausible
sequence, with a comment recording why 053 left.

428 tests pass; lint clean, no stale directives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpK3k2WhH9Pnc3i6TjLMVv

* docs: regenerate views after rebase

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpK3k2WhH9Pnc3i6TjLMVv

* fix: link the bare ADR-053 reference in the changelog fragment

Surfaced by the rebase: ADR-053 did not exist when the fragment was written,
so the reference was correctly bare. It resolves now, and both the docs lint
and tests/test_doc_refs.py say so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpK3k2WhH9Pnc3i6TjLMVv

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants