Skip to content

Commit cd4e151

Browse files
authored
fix: compose release document normalization
Systematically harden release-document normalization, immutable evidence binding, archive parity, and the normal release workflow.
1 parent f28a849 commit cd4e151

12 files changed

Lines changed: 925 additions & 213 deletions

.github/workflows/publish.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ jobs:
286286
run: uv run python scripts/check_artifacts.py dist/*
287287
- name: Install and smoke-test each exact artifact
288288
run: uv run python scripts/check_clean_install.py dist/*
289+
- name: Verify the immutable release as a copied standalone repository
290+
run: python scripts/check_repository_independence.py
289291
- name: Record immutable artifact digests
290292
run: sha256sum dist/* > artifact-sha256.txt
291293
- name: Retain only the verified release bundle

AGENTS.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,17 @@ Post-stable invariants:
157157
12. Keep `CHANGELOG.md` release-only: do not maintain an unmanaged `Unreleased`
158158
section. Record changes in Conventional Commits and let Release Please own
159159
the newest canonical dated release section after the changelog preamble.
160-
The version gate must reject any `Unreleased` level-two heading before merge
161-
or release.
160+
Use only canonical Markdown for level-two changelog headings; raw HTML H2
161+
parsing is renderer-dependent and must fail the version gate before merge or
162+
release. The same gate must reject any `Unreleased` level-two heading.
162163
13. A validated release-evidence block binds one canonical publication workflow
163-
run to its machine-readable identity marker and may contain no other Actions
164-
run URL. Keep preparatory implementation, CI, Release Please, failed-attempt,
164+
run URL without an attempt suffix to its machine-readable identity marker and
165+
may contain no other Actions run URL. Record attempt provenance as plain
166+
text. Keep preparatory implementation, CI, Release Please, failed-attempt,
165167
and recovery history outside that block. The document gate must reject
166-
non-canonical, wrapped, malformed, or contradictory workflow URLs regardless
167-
of prose or Markdown labeling.
168+
non-canonical, wrapped, encoded, control-obfuscated, malformed, or
169+
contradictory workflow URLs regardless of prose or Markdown labeling, and
170+
bind each source occurrence to exactly one rendered navigation destination.
168171

169172
## Repository independence
170173

@@ -289,8 +292,10 @@ workflow after maintainer authorization.
289292
Build wheel and source distribution into a clean output directory. Inspect
290293
their metadata and file lists, install each exact artifact independently
291294
outside the source tree, assert version and public imports, and run mocked-call
292-
smokes. Generated artifacts, local environments, and credentials must never be
293-
committed.
295+
smokes. Require every reviewed sdist member to match the release checkout byte
296+
for byte, and rerun the copied standalone repository verification in the
297+
immutable-tag build before retaining digests. Generated artifacts, local
298+
environments, and credentials must never be committed.
294299

295300
## Release and documentation rules
296301

ARCHITECTURE.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ sdist, and PyPI metadata are immutable, the README uses an unversioned install
133133
command and publication-neutral release language that remains accurate before
134134
and after a release. Source-document and artifact checks reject approval,
135135
unpublished, exact-version installation, and versioned release-link text; each
136-
artifact long description must also exactly match the source README.
136+
artifact long description must also exactly match the source README. Artifact
137+
inspection additionally requires every reviewed source-distribution member to
138+
match the release checkout byte for byte.
137139

138140
Release Please v5.0.0 is pinned to the immutable commit whose action metadata
139141
uses `node24`. The workflow semantic contract fixes that SHA and runtime
@@ -146,7 +148,8 @@ Conventional Commits and never maintain an `Unreleased` placeholder. The
146148
version gate rejects that structurally incompatible placeholder, accepts Release
147149
Please's native linked form and legacy dated history, and validates repository,
148150
previous tag, candidate tag, and calendar date without rewriting generated
149-
history.
151+
history. Raw HTML level-two headings are rejected rather than interpreted with
152+
renderer-specific error recovery.
150153

151154
The PyPI publisher remains directly in `publish.yml` and is pinned to its
152155
reviewed Node 24 maintenance release. Pinning its exact SHA prevents a syntactic
@@ -165,11 +168,14 @@ ambiguous external state and is forbidden.
165168
Immutable run, tag, commit, registry, and digest records live only in the
166169
validated release-evidence blocks in `ROADMAP.md` and `RELEASING.md`. Each
167170
block binds only the canonical publication run through its machine-readable
168-
identity; preparatory implementation, CI, Release Please, failed-attempt, and
169-
recovery history stays outside the block. The checker rejects every other run
170-
identity plus wrapped or malformed Actions URLs, so Markdown wording cannot
171-
disguise a contradictory workflow. Architecture documents mechanisms and
172-
boundaries, not a second historical ledger.
171+
identity, without an attempt suffix; attempt provenance remains plain text.
172+
Preparatory implementation, CI, Release Please, failed-attempt, and recovery
173+
history stays outside the block. The checker rejects every other run
174+
identity and binds every source occurrence to exactly one rendered Markdown or
175+
HTML navigation destination after bounded normalization. Wrapped, encoded,
176+
control-obfuscated, malformed, or contradictory Actions URLs fail closed, so
177+
prose and renderer syntax cannot disguise a workflow identity. Architecture
178+
documents mechanisms and boundaries, not a second historical ledger.
173179

174180
The scheduled/manual default-branch smoke is an operational canary only; it
175181
does not prove the release commit. `COMETAPI_KEY` is exposed only to the

RELEASING.md

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,17 @@ authorization failure.
202202
Conventional Commits carry pending changes, and Release Please owns the newest
203203
canonical dated section immediately after the preamble. The version gate rejects
204204
any unmanaged `Unreleased` level-two heading so the generated layout remains
205-
valid on every patch release.
205+
valid on every patch release. Use only canonical Markdown for level-two
206+
headings; raw HTML H2 semantics vary by renderer and therefore fail closed.
206207

207208
Each validated release-evidence block contains the immutable release identity
208-
and only its canonical publication workflow. Preparatory implementation CI,
209-
Release Please, failed-publication, and recovery history remains outside the
210-
block. The document gate rejects every different run identity and every wrapped
211-
or malformed Actions URL regardless of prose or Markdown labeling.
209+
and only its canonical publication workflow URL without an attempt suffix.
210+
Record attempt provenance as plain text. Preparatory implementation CI, Release
211+
Please, failed-publication, and recovery history remains outside the block. The
212+
document gate binds every source occurrence to exactly one rendered navigation
213+
destination and rejects every different run identity plus wrapped, encoded,
214+
control-obfuscated, or malformed Actions URLs regardless of prose or Markdown
215+
labeling.
212216

213217
Release mode (`check_version.py --require-releasable-docs`) also fails closed
214218
until project authorship, the canonical GitHub repository URL, the copyright
@@ -225,7 +229,8 @@ description. The README therefore uses the unpinned
225229
PRs and post-release evidence changes must not introduce approval, unpublished,
226230
or exact-version availability statements. Artifact inspection applies the same
227231
policy to wheel `METADATA` and sdist `PKG-INFO`, so source and registry-facing
228-
descriptions cannot drift.
232+
descriptions cannot drift. Artifact inspection also requires every reviewed
233+
source-distribution member to match the release checkout byte for byte.
229234

230235
## Workflow responsibilities
231236

@@ -290,7 +295,9 @@ descriptions cannot drift.
290295
against the exact pre-publication digests and Trusted Publisher provenance
291296
before a clean install explicitly from `https://pypi.org/simple/`. The exact
292297
release live model is the canonical active model enforced by the workflow
293-
checker and cannot be overridden by repository variables.
298+
checker and cannot be overridden by repository variables. Before digest
299+
retention, the immutable-tag build also copies the checkout into an empty
300+
parent and completes the standalone repository verification there.
294301
Because the unused Release Please or recovery path is intentionally skipped,
295302
every job after the selector must use `always() && !cancelled()`, reject
296303
reruns, and require each direct dependency's result to equal `success`. This
@@ -556,8 +563,8 @@ authorized.
556563
`64c7cb87745032703b3374cc562ea00b979416c54908862dbcebd116b2dc44c8`.
557564
Both files match the retained pre-publication digest record. PyPI Integrity
558565
API provenance identifies repository `cometapi-dev/cometapi-python`, workflow
559-
`publish.yml`, environment `pypi`, release commit `576e7503`, and release
560-
[run attempt 1](https://github.com/cometapi-dev/cometapi-python/actions/runs/30429821548/attempts/1).
566+
`publish.yml`, environment `pypi`, release commit `576e7503`, and release run
567+
attempt 1.
561568
- An independent post-workflow verification downloaded both public files,
562569
verified both provenance records with `pypi-attestations==0.0.29`, installed
563570
`cometapi==0.1.1` from `https://pypi.org/simple/`, verified the public version
@@ -612,8 +619,8 @@ authorized.
612619
`21c8edc0586610de1a9a8cd39b54ed23d2b1e20552100f69f53938cb7678da3d`.
613620
Both files match the retained pre-publication digest record. PyPI Integrity
614621
API provenance identifies repository `cometapi-dev/cometapi-python`, workflow
615-
`publish.yml`, environment `pypi`, release commit `710c5649`, and release
616-
[run attempt 1](https://github.com/cometapi-dev/cometapi-python/actions/runs/30515861246/attempts/1).
622+
`publish.yml`, environment `pypi`, release commit `710c5649`, and release run
623+
attempt 1.
617624
- An independent post-workflow verification downloaded both public files,
618625
verified both provenance records with `pypi-attestations==0.0.29`, installed
619626
`cometapi==0.1.2` from `https://pypi.org/simple/`, verified the public version
@@ -670,8 +677,8 @@ authorized.
670677
`07ded54606d50f44b689dad38cf93a74e1175370efaa33be84a3c01240d48e66`.
671678
Both files match the retained pre-publication digest record. PyPI Integrity
672679
API provenance identifies repository `cometapi-dev/cometapi-python`, workflow
673-
`publish.yml`, environment `pypi`, release commit `45429f37`, and release
674-
[run attempt 1](https://github.com/cometapi-dev/cometapi-python/actions/runs/30550536000/attempts/1).
680+
`publish.yml`, environment `pypi`, release commit `45429f37`, and release run
681+
attempt 1.
675682
- Independent post-workflow verification downloaded both public files,
676683
verified both provenance records with `pypi-attestations==0.0.29`, installed
677684
`cometapi==0.1.3` from `https://pypi.org/simple/`, verified the public version

ROADMAP.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,8 @@ and source-distribution SHA256
579579
`64c7cb87745032703b3374cc562ea00b979416c54908862dbcebd116b2dc44c8`.
580580
Both files matched the retained pre-publication digest record. Their PyPI
581581
Integrity API provenance names repository `cometapi-dev/cometapi-python`,
582-
workflow `publish.yml`, environment `pypi`, release commit `576e7503`, and
583-
[run attempt 1](https://github.com/cometapi-dev/cometapi-python/actions/runs/30429821548/attempts/1).
582+
workflow `publish.yml`, environment `pypi`, release commit `576e7503`, and run
583+
attempt 1.
584584
An independent post-workflow verification downloaded both public files,
585585
verified their provenance with `pypi-attestations==0.0.29`, installed
586586
`cometapi==0.1.1` from the public simple index, checked version and public
@@ -651,8 +651,8 @@ and source-distribution SHA256
651651
`21c8edc0586610de1a9a8cd39b54ed23d2b1e20552100f69f53938cb7678da3d`.
652652
Both files match the retained pre-publication digest record. Their PyPI
653653
Integrity API provenance names repository `cometapi-dev/cometapi-python`,
654-
workflow `publish.yml`, environment `pypi`, release commit `710c5649`, and
655-
[run attempt 1](https://github.com/cometapi-dev/cometapi-python/actions/runs/30515861246/attempts/1).
654+
workflow `publish.yml`, environment `pypi`, release commit `710c5649`, and run
655+
attempt 1.
656656
An independent post-workflow verification downloaded both public files,
657657
verified both provenance records with `pypi-attestations==0.0.29`, installed
658658
`cometapi==0.1.2` from the public simple index, verified the public version and
@@ -716,8 +716,7 @@ and source-distribution SHA256
716716
Both public files match the retained pre-publication digest record. PyPI
717717
Integrity API provenance identifies repository
718718
`cometapi-dev/cometapi-python`, workflow `publish.yml`, environment `pypi`,
719-
release commit `45429f37`, and release
720-
[run attempt 1](https://github.com/cometapi-dev/cometapi-python/actions/runs/30550536000/attempts/1).
719+
release commit `45429f37`, and release run attempt 1.
721720
An independent post-workflow verification downloaded both public files,
722721
verified both provenance records with `pypi-attestations==0.0.29`, installed
723722
`cometapi==0.1.3` from `https://pypi.org/simple/`, verified the public version

0 commit comments

Comments
 (0)