Research-1127: Single SemVer release stream¶
Question¶
What is the smallest safe migration from the inherited fork suffix and four release-please packages to one ordinary patch-release stream?
Evidence¶
- The source and root manifest identify 3.2.0 as the current baseline; remote tags stop at
v3.0.0, and the repository has no published GitHub release. - The component packages used unqualified tags, so independently generated component releases could collide and all could invoke whole-product release automation.
- GitHub suppresses new workflow runs for most events created with the repository
GITHUB_TOKEN. Keeping release-please's draft release and having an authenticated operator publish it provides a reliable tag andrelease.publishedfan-out without adding a privileged token. A preflight pauses both release-please action phases while an ordinary-SemVer draft exists, so a later master push cannot duplicate or retarget the pending release. - Release-please 17.6.0 and 17.11.2 simulations both selected 3.2.1 through the one-time
release-asfield, including when the complete migration tree was represented as a single squash commit directly above the bootstrap SHA. With a 3.2.1 tag and manifest, retaining that override generated another invalid 3.2.1 cut, while deleting it generated 3.2.2. The release-PR rollover therefore validates and removesrelease-astogether withbootstrap-shabefore the release PR merges. - A normal development checkout also contains Netflix upstream's local
v3.1.0andv3.2.0tags, althoughVMAFx/vmafxadvertises neither tag. Release-please local mode will treat those shared-namespace tags as fork history and can maskbootstrap-sha. Repeating both version simulations in an origin-faithful clone with only the fork's actual tags selected the configured98dc0b2b...bootstrap and the same single 3.2.1 release PR. - Helm chart
versionand Rust crate versions describe independently packaged artifacts. HelmappVersion, the Python distributions, libvmaf, and the node image describe the coordinated VMAFx release and should move together. - The compatibility
vmafdistribution was still dynamically readingcompat/python-vmaf/__init__.pyas3.0.0, even though libvmaf and the fork-local Python packages had reached3.2.1. Making that file a release-please marker removes the last public-package version split while retaining the independent SONAME/API version incore/meson.build. - A clean 1,264-target Meson build places the shared-library chain under
build/src/; the release workflow's formerbuild/libvmaf/copy path did not exist and would have stopped publication before signing. Staging only a dereferencedlibvmaf.sowas also insufficient: the built CLI declaresDT_NEEDED libvmaf.so.3, and GitHub artifact downloads do not preserve symlinks. The repaired stage materializes the unversioned, SONAME, and real names as identical regular files. A verifier parses the ELF SONAME andDT_NEEDED, proveslddresolves the downloaded SONAME file underenv -i, and runs the downloaded CLI for the exact release version before native signing or provenance. The model archive now sorts entries, normalizes ownership and mtimes to the tag commit, and suppresses the gzip timestamp so recovery does not change that asset solely because it ran later. - The
vmaf-mcpproject is not yet present on PyPI (the JSON project endpoint returned HTTP 404 on 2026-08-31). Its first publication therefore depends on a Pending Trusted Publisher forVMAFx/vmafx,supply-chain.yml, and thepypi-publishenvironment; ADR-0166 originally recorded the pre-transfer identity. The matching GitHub environment and exact PyPI Pending Trusted Publisher were both created on 2026-08-31. PyPI now shows the pending row forvmaf-mcp/VMAFx/vmafx/supply-chain.yml/pypi-publish. - Release hashing and signing iterated over unguarded bare
*pathnames. The repaired loops use an option terminator (orfindoutput rooted at./) so a dash-prefixed artifact cannot become an option while SLSA subjects retain their release filenames. - The release workflow produced hashes for the MCP wheel and sdist without consuming them in a provenance job, and generated SBOMs before downloading those distributions. The repaired DAG creates distinct SLSA subjects and names for libvmaf and
vmaf-mcp, scans every native artifact plus an installed Python runtime dependency closure in SPDX and CycloneDX formats, validates package identity, dependency edges, and exact artifact SHA-256 values, signs the SBOMs, and refuses incomplete attachment globs. Syft 1.51.1 was used for the validated inventory shape. - Manual recovery now requires the workflow itself to run at the existing published
vX.Y.Ztag, not merely check that tag out in a master-context run. This keeps the SLSA event SHA/ref identical to the source being attested and preserves the authenticated publication gate. PyPI recovery compares the exact two-filename set and SHA-256 digests before and afterskip-existing, so a same-version rebuild or partial-upload race cannot silently diverge from the index. The package build frontend and hatchling backend are pinned to the live PyPI releases verified on 2026-08-31 (build==1.6.0,hatchling==1.32.0). A local isolated build produced exactlyvmaf_mcp-3.2.1-py3-none-any.whlandvmaf_mcp-3.2.1.tar.gz, with wheel metadataName: vmaf-mcp,Version: 3.2.1, andRequires-Python: >=3.10. Repeating that build with a fixed tag-commitSOURCE_DATE_EPOCHandPYTHONHASHSEED=0produced byte-identical wheel and sdist hashes, making the filename/hash recovery guard usable after partial publication. - The two Docker recovery workflows still accepted an independent image-tag input while checking out the dispatch ref. A run from
masterwith inputv3.2.1could therefore sign and publish non-tag source under the release name, and GitHub-native provenance would describe the dispatch SHA rather than the checked-out tag. Both workflows now gate every build behind the same published-release, ordinary-tag, ref, SHA, checkout, and coordinated version equality used by the artifact workflow. Manual recovery must be dispatched with--ref vX.Y.Z -f tag=vX.Y.Z.
Result¶
Use a single root release-please package with manifest baseline 3.2.0 and force the cutover release to 3.2.1 with a one-time release-as override. Update all coordinated version surfaces from the root package, retain the draft publication gate, and have release-PR rollover remove that override and the bootstrap SHA before merge. Do not synthesize a 3.2.0 tag.
Reproducer¶
jq -e '.packages | keys == ["."]' release-please-config.json
jq -e '. == {".": "3.2.0"}' .release-please-manifest.json
git tag --list 'v3.2.*'
git ls-remote --tags origin 'v3.2.*'
meson setup build core -Denable_metal=disabled && meson compile -C build
test -e build/src/libvmaf.so
mkdir -p artifacts
find build/src -maxdepth 1 \( -type f -o -type l \) \
-name 'libvmaf.so*' -exec cp -L -t artifacts -- {} +
cp build/tools/vmaf artifacts/
scripts/release/verify-native-release-artifacts.sh artifacts 3.2.1