Retrospective: R011 (the final-release pull request for 0.1.0)#

Status: ready for the final release on the branch release-0.1.0-final (from main at 84f7742, the merge of pull request #5 with R010; the tag v0.1.0rc1 points there and 0.1.0rc1 is on TestPyPI). R011 is step 9 of the release checklist (Release process, “The final-release pull request”), done in one step by one implementer. Nothing is published by it: the merge, the tag v0.1.0, the GitHub Release and the upload are the orchestrator’s (on the author’s behalf), and the PyPI deployment waits for the author’s approval. NOTICE is unchanged: its wording (O3) awaited the author when R011 was written; the author confirmed it as drafted on 2026-10-01.

Afterwards (R012, the tag day; Retrospective: R012 (the tag day of 0.1.0)). The tag v0.1.0 is pushed on 2026-10-02 (UTC), so R012 moved the release date to 2026-10-02 (the CHANGELOG heading and date-released) and ran the packaging and repo checks again, as the notes below describe. It recorded the author’s decisions of 2026-10-01 in GOVERNANCE.md: O3 is closed (the NOTICE wording confirmed as drafted; NOTICE unchanged) and Zenodo is not connected for 0.1.0, so 0.1.0 has no DOI; and the licence expression: the author raised no objection by the tag day, and the approval of the pypi deployment is the final confirmation. Where this retrospective says the release date is 2026-10-01 or that O3 is open, it describes the state of R011.

What changed#

Item

Where

VERSION 0.1.0; version: 0.1.0 (date-released: 2026-10-01 unchanged)

VERSION, CITATION.cff

The CHANGELOG section [0.1.0rc1] renamed [0.1.0] - 2026-10-01 under the empty [Unreleased]; the summary’s install line pip install dyng; a “Final release (R011)” entry; the link references [Unreleased]: .../compare/v0.1.0...main and [0.1.0]: .../compare/v0.0.1...v0.1.0

CHANGELOG.md

The status texts the release candidate wrote for its own state, brought to the release: the status block and the install lines (pip install dyng from PyPI), the status paragraph and the supported versions (main and the latest minor release, 0.1.x; 0.1.0rc1 not supported), the “0.1 release candidate” wording, “Where we are”, the status line and the 0.1.0 row

README.md, docs/index.md, docs/getting_started/install.md, SECURITY.md, CONTRIBUTING.md, SUPPORT.md, docs/roadmap.md, docs/developer/plan.md

The release certificate, carried over from 0.1.0rc1

benchmarks/results/0.1.0/

The smoke test of 0.1.0rc1 from TestPyPI (checklist step 8)

benchmarks/results/0.1.0/README.md

python ci/wheel_check.py --release-metadata --release-date 2026-10-01 passes (VERSION, CHANGELOG and CITATION.cff agree).

The certificate: carried over#

The library did not change since the release candidate: git diff 84f7742 HEAD touches no path of the library scope (cpp/include, cpp/src, cpp/CMakeLists.txt, tools, cmake, the root CMakeLists.txt and CMakePresets.json, docs/references.bib). So benchmarks/results/0.1.0rc1/ was copied to benchmarks/results/0.1.0/, and the gates (sssp 132 / 132 gated regions, cycle_count 78 / 78), the golden replays (4950 / 4950 and 144 / 144) and the sssp golden mutations stand, with the equivalence record of R010 for the measured commit d13d393. The checks whose scope this pull request touches were run again from fresh clones of the branch and recorded with parity/certify.py check --version 0.1.0, replacing the release candidate’s records of the same names:

Check

Scope

Why again

Commit

distributions (release.yml’s select for v0.1.0, ci/wheels.sh, twine check --strict, ci/wheel_check.py, fresh Python 3.12 / 3.13 venvs)

packaging

VERSION, CHANGELOG.md, CITATION.cff, README.md

261d03d

asan, tsan (the sanitizer presets’ test suites)

tests

README.md (its C++ quickstart is a test)

261d03d

check-parity (ci/check.sh --parity), gpu_local (ci/gpu_local.sh), mutation-ctests (ctest --preset dev-cuda -L mutation, in the same build)

repo; tests

the whole tree (the documents)

the commit of this retrospective

Then parity/certify.py write --version 0.1.0 on the committed final tree wrote parity.json naming 0.1.0 and the final commit; it checks every measured commit against it in the paths of its scope.

After the review (below, “The review round”), whose fixes change README.md and documents of the repo scope, all six checks of this table were run again from a fresh clone of the commit of the fixes (the commit of this retrospective) and recorded in place of the records above; the certificate (benchmarks/results/0.1.0/README.md, “Checks”) names the commit, the date and the logs of each.

Results#

Check

Result

select with GITHUB_REF_NAME=v0.1.0

kind=package, version=0.1.0, prerelease=false (a final release: publish-pypi runs after the approval); v0.1.0rc1 and v0.1.0-rc.1 refused

ci/wheels.sh

dyng-0.1.0.tar.gz (0.79 MB), dyng-0.1.0-cp312-abi3-manylinux_2_28_x86_64.whl (1.51 MB); twine check --strict and ci/wheel_check.py --platform manylinux_2_28_x86_64 --require-libgomp passed; Version: 0.1.0 and the licence expression in METADATA and PKG-INFO

The wheel alone in fresh Python 3.12 and 3.13 venvs

the whole suite 396 passed, 4 skipped; the cibuildwheel test subset 253 passed, 1 skipped; the README quickstart prints the README’s output; dyng --version 0.1.0

asan / tsan presets

595 / 595 (26 skipped) and 520 / 520 (42 skipped), the same counts and skips as for 0.1.0rc1

ci/check.sh --parity, ci/gpu_local.sh, the mutation CTests, ci/docs.sh, ci/python.sh

run on the commit of this retrospective, after it; their results are in the certificate (benchmarks/results/0.1.0/README.md, “Checks”)

Smoke test of 0.1.0rc1 from TestPyPI

passed on Python 3.12 and 3.13 (below)

The smoke test of 0.1.0rc1 (checklist step 8)#

The orchestrator installed 0.1.0rc1 from TestPyPI on 2026-10-01 on Python 3.12 and 3.13 and reported install, sssp and cycle_count compute and update, the citation and the command line working, with the correct licence expression in the metadata. R011 repeated it on this machine with both host backends: fresh venvs on Python 3.12.14 and 3.13.15, pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ dyng==0.1.0rc1, from an empty directory: dyng.show_config(), sssp and cycle_count compute and update on sequential and openmp (equal results), dyng.citation(), dyng --version (0.1.0rc1) and the License-Expression of the installed metadata. Both passed; the record is in benchmarks/results/0.1.0/README.md.

Deviations and decisions (each with the same intent)#

  1. The CHANGELOG section was renamed, not followed by a new [0.1.0] section: nothing in the library changed since 0.1.0rc1, so a separate section would only list the version and the documents. The renamed section keeps the record of 0.1.0rc1 and adds a “Final release (R011)” entry; the link reference [0.1.0rc1] is dropped with its heading (the tag v0.1.0rc1 stays, and the summary names it).

  2. The order of the checks. The packaging and tests checks ran at 261d03d (the version and the status texts), before this retrospective and the developer plan’s status line, which are outside their scopes; the repo checks (ci/check.sh --parity, ci/gpu_local.sh) ran after the last change outside benchmarks/results/, so this retrospective names their results by reference to the certificate. The mutation CTests ran in the ci/gpu_local.sh clone (the same dev-cuda build) rather than in the sanitizer clone.

  3. Step 8 on one machine. The smoke test was run on the GPU machine (the CPU wheel’s host backends); no separate CPU-only machine is available to this milestone. The wheel has no CUDA backend, so the two runs test the same code; the hosted CI’s sdist and wheel jobs cover other machines.

  4. A retrospective of its own (R011) instead of a fourth step of R010, since the final release is its own milestone.

The review round#

Independent reviewers (release-manager lens) confirmed five findings; each is fixed here:

Finding

Fix

The README’s Status table still said the Python package was “to be published with 0.1.0”

the row in the released state: on PyPI since 0.1.0 (pip install dyng); CUDA plugin wheels follow in 0.1.x

The orchestrator note said a release-date fix re-records only distributions; CHANGELOG.md and CITATION.cff are also in the repo scope (parity.json, code_paths.repo is the whole tree but benchmarks/results), so check-parity and gpu_local would go stale too

the note corrected (below): a date change re-runs and re-records distributions, check-parity and gpu_local, then certify.py write again

The orchestrator note let O3 and the licence expression’s objection window wait until the author’s approval of the pypi deployment; release.md step 10 requires them before the tag is pushed (pushing v0.1.0 uploads NOTICE and the License-Expression to TestPyPI, and neither the tag nor the 0.1.0 file names can be replaced)

the note follows step 10 (below); GOVERNANCE.md’s O3 now says “before the tag v0.1.0 is pushed”

The certificate’s README, copied from 0.1.0rc1, described the release candidate’s check records as if they were this directory’s

a sentence at the top of its section “What was run, and how” says those records were replaced by the R011 runs; the two bullets say which statements are the release candidate’s

install.md called 0.0.1 the current PyPI version; release.md’s readiness pointer left out R011

“The PyPI release 0.0.1 was only the name reservation”; the pointer names this retrospective

Not done here: moving the release date. The reviewers suggested setting the CHANGELOG heading and date-released to the realistic tag day in this pull request. That day is not known: the tag waits for O3, which only the author can settle, and ci/wheel_check.py --release-date today must pass on the day of the tag. So the date stays 2026-10-01 (the day of this pull request) and the note below says exactly what a later tag day costs. (The tag day became 2026-10-02; R012 made the change.)

The licence row of the approvals log (GOVERNANCE.md, 2026-09-30) says the expression stands “pending objection before the final PyPI approval”. It is a log entry and is left as written; release.md step 10 is the binding deadline (the objection window closes before the tag). R012 logged the outcome in a row of its own: no objection by the tag day; the pypi approval is the final confirmation.

Notes for the orchestrator#

  • Merge with a merge commit (ADR 0019), then tag v0.1.0 on main: the certificate names the branch commit, which stays reachable through the merge. Before pushing the tag run python ci/wheel_check.py --release-metadata --release-date today: the release date was 2026-10-01 (UTC). If the tag falls on a later day (likely, since it waits for O3, next item), change the CHANGELOG heading’s date and date-released in a small pull request first (release.md step 10). CHANGELOG.md and CITATION.cff are in the packaging scope and in the repo scope (the whole tree but benchmarks/results/), so on the tree of that pull request run again, from a fresh clone, and record with parity/certify.py check --version 0.1.0: distributions (release.yml’s select for v0.1.0, ci/wheels.sh, twine check --strict, ci/wheel_check.py, fresh 3.12 / 3.13 venvs), check-parity (ci/check.sh --parity) and gpu_local (ci/gpu_local.sh); then parity/certify.py write --version 0.1.0 on the committed tree and commit the certificate. (README.md does not change, so the tests records stand.) Done in R012: the tag day is 2026-10-02; the date was changed and these checks were run again and recorded (Retrospective: R012 (the tag day of 0.1.0); release.md, A tag day later than the final-release pull request).

  • Before the tag v0.1.0 is pushed (step 10, and before the release date is fixed): the author settles O3, the NOTICE wording, which ships in every distribution and is unchanged here (GOVERNANCE.md, open decisions), and the licence expression’s objection window ends. Pushing the tag starts release.yml, which uploads the 0.1.0 files, with NOTICE and the License-Expression in them, to TestPyPI; the release tags ruleset forbids moving the tag and the 0.1.0 file names cannot be uploaded again, so nothing can be changed after the push. If NOTICE changes, the packaging and repo checks are run again and recorded (as for a date change) before the tag. Settled: the author confirmed the NOTICE wording as drafted on 2026-10-01 (O3 closed, NOTICE unchanged), and raised no objection to the licence expression by the tag day; the pypi approval is the final confirmation (GOVERNANCE.md, approvals log).

  • Zenodo archives only GitHub Releases published after it is switched on. Decided: the author does not connect Zenodo for 0.1.0 (2026-10-01), so 0.1.0 has no DOI; Zenodo may be connected later (checkpoint A4), and the releases after that get DOIs.

  • After the release (step 14): bump VERSION to 0.1.1.dev0 or 0.2.0.dev0 in a pull request, announce, and carry over the R010 note on parity/cycle_count_perf.py (repeat flagged runs like the other harnesses).