Release process¶
vibe-qc is independently versioned. Development changes land on the canonical GitLab main branch through the existing contributor and review process. Released tags are immutable. Do not rewrite published history or move a release tag to repair documentation or packaging metadata.
Contributor evidence¶
Follow the repository’s CONTRIBUTING.md and developer test guidance. A change
needs the relevant tests and validation comparisons, with commands, selected
source revision and results recorded for review. A release blocker or a fix to
an incorrect numerical result requires an independent check before closure.
Add ordinary release notes as individual Markdown fragments under
changelog.d/; do not edit CHANGELOG.md directly. Validate them with
python scripts/assemble_changelog.py --check. The release owner assembles
them into [Unreleased] when preparing a release, following
changelog.d/README.md. Preserve released changelog sections and their pins.
AI-assisted changes follow the same disclosure, attribution, licensing and validation requirements as other contributions. Assistance does not replace review or evidence. See the existing contributor policy for the full contract.
Pre-flight environment integrity¶
A gate is evidence about the tree the interpreter actually loaded, not the tree you mean to tag, so the release lane checks the environment before it runs the blocking tier. Four failures have each produced a false result here, and none of them announces itself:
An editable install silently replaced by a copy. A wheel-based reinstall can leave
import vibeqcresolving intosite-packagesrather thanpython/vibeqc/, so later edits are invisible to pytest and a green suite against a stale copy looks like any other green suite. Restore withpip install -e . --no-build-isolation, and confirmvibeqc.__file__resolves inside the checkout being gated.A stale
build/basis_library/overlay. The overlay is preferred over the committed library, so a basis missing from it does not resolve at all, and the error names the basis rather than the overlay. Regenerate it withbash scripts/setup_basis_library.sh.A stale
.pycthat survived an edit made inside the same second. CPython’s timestamp invalidation has one-second granularity, so a checkout or rebase that rewrites a source file within the same second the cache was written leaves the cache looking current and the old code running. Suspect it when a value read back does not match the file in front of you, and clear it withfind python -name __pycache__ -type d -prune -exec rm -rf {} +.A compiled core built from another tree. The installed distribution version records the release line the core was built from, so it catches a core from an earlier line; it cannot tell two builds apart inside one
.dev0cycle. Compare the extension’s timestamp with the newestcpp/source as well, and rebuild when the core is older.
The candidate pipeline also runs the changelog guard.
changelog_guard.py check compares every released CHANGELOG.md section with
its SHA-256 pin, and changelog_guard.py audit --require-tagged 1 compares each
pin with the same section at its own git tag. The audit needs the tags, so it
runs in the candidate pipeline rather than in the blocking tier, whose clone may
be shallow, and --require-tagged makes a clone without tags fail instead of
passing without having compared anything. An entry for unreleased work belongs
under [Unreleased]; a deliberate change to an already released section needs
changelog_guard.py pin vX.Y.Z --amended "<reason>" in the same commit.
The blocking gate is the T1 tier, the same invocation the candidate
pipeline runs, so pre-flight and CI cannot disagree about what green means.
That equivalence holds only while the local environment matches CI’s: the
viewer installed into the release venv, for example, makes the local gate run
files CI skips. A new red on a loaded machine is not yet a regression; re-run
it in isolation with scripts/test_gate/gate_verdict.py --reverify before
reading it as one.
Candidate CI explicitly removes VIBEQC_ALLOW_STALE_CORE, records the loaded
package, source SHA, core hash and linked-library versions in
test-results/native-runtime.json, and checks the fresh core before T1.
Candidate artifacts also retain the matching core and CMake cache under
test-results/native-core/. The receipt records native source and linked
dependency paths. This is not a standalone runtime: any independent reuse
must qualify the interpreter, dependencies and data before calculations.
After T1 it reports the release-impact selection against VIBEQC_RELEASE_BASE;
these informational calls do not feed T2 results to the T0/T1 verdict. Update
that CI variable to the previous released tag when preparing a patch.
The release-core sentinel is already included in T1.
Viewer producer/consumer gate¶
After the candidate’s T1 gate, CI installs the pinned viewer and runs the
producer/consumer selection as an unprivileged user under Xvfb. The selection
includes the original seven contract files plus test_relocalize.py,
test_wavefunction_gradient.py, test_manifest_root_blocks.py,
test_plot_renderers.py and the pending-QVF submission case in
test_controller_state.py (#363).
VIBEQC_RELOCALIZE_PYTHON points to the candidate’s installed interpreter so
the six external-worker relocalization cases execute. A native import
preflight must succeed before pytest. Review the retained
test-results/viewer-contract.xml and the job’s skip summary: a passing
protocol-only run with a missing QC core is not integration acceptance.
Maintainer publication¶
The release owner selects scope and version only after the required gates pass. The agentic loop coordinates the source tag and supported publication jobs. Site-specific commands, accounts, destinations and gate-operation runbooks are maintained in the private operations repository. Contributor source archives do not contain or install those operational scripts.
A public source snapshot has its own commit identity and records the original source revision and per-file checksums. It contains no private development ancestry. A correction is published as a new snapshot or patch release; existing source tags remain unchanged. Public availability is established by successful anonymous access and the publication verification report.
The GitHub publication policy explains which releases and qualified main revisions are exported, the checks before each update, and the current automation status. Main publication is separate from cutting a release.
The core release lane retains its T1 and candidate validation requirements. Ordinary main pushes do not replace release-gate evidence. The manual publishes from the qualified release; companion versions are validated at their selected pins. Moving operational configuration does not authorize a tag or deployment.
Documentation cadence¶
Review documentation with each behavior change. Contributor guidance and reference examples should match the selected source revision. The public manual is published through the existing qualified-release gate; the private operator runbook records the publication procedure and periodic review schedule.