- Confirm that the working tree contains only intended changes.
- Update
CHANGELOG.md. - Set the same version in:
pyproject.toml;src/diffractscout/__init__.py;CITATION.cff.
- Update screenshots, validation counts, paper statements, and source-lineage notes when affected.
python scripts/check_release.pyThe default output directory is dist. It must be empty; the preflight never
deletes or overwrites existing distributions. When dist/ already contains
artifacts, use an empty directory outside the checkout, for example:
python scripts/check_release.py --dist-dir /tmp/diffractscout-release-distThis checks required files, version consistency, bibliography keys, compilation,
tests, the offline demo, analytic benchmark, manifest verification, wheel and
sdist creation, Twine metadata, and a source-independent install/run of the
newly built wheel. A successful full run writes an ignored
build/release-preflight/release_acceptance.json receipt bound to the exact
current tracked and non-ignored source fingerprint (including intended new
files, but excluding ignored build/workflow artifacts). The standalone
--stage release --strict gate is
fail-closed until that receipt exists and still matches; a run using
--skip-tests or --skip-wheel never writes it.
The preflight fingerprints the source both before and after execution and
refuses a receipt if source changed while tests were running. In GitHub tag
workflows the strict gate additionally requires a clean checkout; a local
uncommitted release candidate may be tested, but it cannot be mistaken for a
taggable commit.
Retain scientific and JOSS preflight artifacts:
diffractscout benchmark -o build/release-benchmark
python scripts/joss_readiness.py --stage release --strict --output build/joss-readinessThe release stage deliberately ignores public-age, impact, external-engagement, and archive-DOI gates while still rejecting release-structure, version, license, ledger, repository, and paper-structure defects. Run the submission stage separately to retain the honest JOSS blocker snapshot.
Additional GUI smoke check on Linux:
xvfb-run -a python -c \
"from diffractscout.gui import create_app; app=create_app(); app.update(); app.destroy()"Inspect the generated wheel:
python -m zipfile -l dist/diffractscout-*.whlCreate a new environment outside the repository and install the wheel:
python -m venv /tmp/diffractscout-wheel-test
/tmp/diffractscout-wheel-test/bin/python -m pip install dist/diffractscout-*.whl
/tmp/diffractscout-wheel-test/bin/python -m diffractscout demo -o /tmp/diffractscout-demo
/tmp/diffractscout-wheel-test/bin/python -m diffractscout verify /tmp/diffractscout-demoWindows paths should use the environment's Scripts\python.exe.
For a local preflight whose normal temporary directory is inaccessible or lies
inside the checkout, set DIFFRACTSCOUT_CLEAN_WHEEL_ROOT to a writable directory
outside the repository. The smoke test rejects an import that resolves outside
the newly created environment. CI installs dependencies into that new
environment. An offline local audit may additionally set
DIFFRACTSCOUT_CLEAN_WHEEL_SYSTEM_SITE_PACKAGES=1; this reuses the already
validated dependency environment but still installs the wheel with no source
path and runs pip-check, demo, verify, benchmark, and quick-export outside the
checkout. The receipt records which mode was used.
Review:
docs/SCIENTIFIC_CONTRACTS.md;docs/SOURCE_LINEAGE.md;docs/VALIDATION.md;- dependency licenses;
NOTICE.md;AUTHORS.md;paper/paper.mdand its AI disclosure;- author, affiliation, funding, acknowledgements, and archive metadata.
The human release owner should inspect representative CSV/XLSX/provenance output and confirm that diagnostic errors are visible and scientific boundaries remain accurate.
The exact JOSS draft is generated by .github/workflows/draft-pdf.yml. When Docker is available locally:
bash scripts/build_paper.shRender and inspect the PDF:
python /home/oai/skills/pdfs/scripts/render_pdf.py paper/paper.pdf \
--out_dir /tmp/diffractscout-paper-render --dpi 200The bundled publication helpers create the repository when it is absent, replace a local bundle/file origin with the intended GitHub URL, push the current branch, and configure repository topics:
DIFFRACTSCOUT_PUBLISH_DRY_RUN=1 bash scripts/publish_github.sh
bash scripts/publish_github.sh D-sudoasd DiffractScout --private$env:DIFFRACTSCOUT_PUBLISH_DRY_RUN = "1"
.\scripts\publish_github.ps1
Remove-Item Env:DIFFRACTSCOUT_PUBLISH_DRY_RUN
.\scripts\publish_github.ps1 -Owner D-sudoasd -Repository DiffractScout -Visibility privateThe dry run still checks GitHub CLI authentication and repository visibility, then prints the planned create/remote/push/edit commands without changing local or remote state.
Pushing a version tag matching the package version triggers .github/workflows/release.yml. The workflow repeats the release preflight, which builds the wheel and source distribution, validates distribution metadata with Twine, and smoke-tests the built wheel; it then packages the analytic benchmark, offline demo, and readiness report with scripts/archive_tree.py, computes SHA256SUMS.txt, and creates the GitHub Release. The archive helper uses sorted paths, a timestamp fixed by SOURCE_DATE_EPOCH, a single safe root, symbolic-link rejection, and atomic replacement so the scientific evidence archives are reproducible for a fixed source and runtime stack.
.github/workflows/monthly-audit.yml reruns the release and scientific checks on the first day of each month and retains deterministic evidence archives for 90 days. .github/dependabot.yml proposes monthly Python and GitHub Actions updates. Timer-triggered audit runs are maintenance evidence; they do not substitute for substantive public commits, validation, support records, issues, pull requests, or releases during the six-month period.
After CI passes on the release commit:
- merge the release pull request;
- delete the merged feature branch after confirming the PR head SHA is represented in the default branch;
- create a new annotated tag matching the package version, for example
v0.4.0; never move an existing tag; - push the tag;
- create GitHub release notes from
CHANGELOG.md; - attach distribution files and checksums when appropriate;
- for ordinary pre-submission releases, retain the verified GitHub Release artifacts and public CI URL;
- after successful JOSS review, create the final tag if needed and archive that exact repository state with Zenodo or an equivalent service;
- add the post-review software archive DOI to
CITATION.cff, the bibliography, GitHub Release, and the JOSS review issue; - rebuild the JOSS draft and run
--stage publication --strictafter archive metadata changes.
Remote branch deletion is a separate destructive action. Delete only branches that are merged, have no unique unreviewed commits, are not protected/default/current branches, and have been explicitly selected for cleanup.