Release Evidence Pack

Purpose

Define the exact evidence bundle required before manual DSAMbayes release sign-off. Substitute the actual release version and candidate SHA; this page is not version-specific.

Audience

  • Release owner preparing sign-off materials
  • Reviewers validating release readiness
  • Maintainers reproducing release gate outcomes

Evidence root and naming

Use one evidence root per candidate release.

Recommended path:

release_evidence/vX.Y.Z/<YYYYMMDD>_<short_sha>/

Example:

release_evidence/v1.3.3/20260714_ab12cd3/

Expected outcome: all sign-off evidence is stored in one deterministic location.

Candidate identity rule:

  1. The candidate hash in 00_release_identity/release_identity.txt, 40_signoff/sign_off_record.md, and the evidence-root short SHA must agree.
  2. If administrative docs or sign-off text change after gate execution, either update the existing bundle without changing candidate identity or rerun the gates into a new evidence root for a new candidate.

Mandatory evidence bundle

All items below are mandatory.

ID Evidence item Required content Source Required path in evidence root
EVD-01 Release identity Candidate commit hash, branch, intended tag, package version git, DESCRIPTION 00_release_identity/release_identity.txt
EVD-02 Changelog proof Top changelog section for release candidate CHANGELOG.md 00_release_identity/changelog_top.md
EVD-03 QG-1 log Lint command output and exit code local command 10_quality_gates/qg1_lint.log, 10_quality_gates/qg1_lint.exit
EVD-04 QG-2 log Style command output and exit code local command 10_quality_gates/qg2_style.log, 10_quality_gates/qg2_style.exit
EVD-05 QG-3 log Unit-test output and exit code local command 10_quality_gates/qg3_tests.log, 10_quality_gates/qg3_tests.exit
EVD-06 QG-4 Stan release evidence log High-budget Stan evidence output and exit code local command 10_quality_gates/qg4_stan_release_evidence.log, 10_quality_gates/qg4_stan_release_evidence.exit
EVD-07 QG-5 package-check log rcmdcheck output, status summary, NOTE rationale if present local command 10_quality_gates/qg5_rcmdcheck.log, 10_quality_gates/qg5_rcmdcheck.exit, 10_quality_gates/qg5_notes_rationale.md
EVD-08 QG-6 validate log Runner validate output and exit code local command 10_quality_gates/qg6_validate.log, 10_quality_gates/qg6_validate.exit
EVD-09 QG-7 run log Runner run output and exit code local command 10_quality_gates/qg7_run.log, 10_quality_gates/qg7_run.exit
EVD-10 QG-8 docs log docs-site build output and exit code local command 10_quality_gates/qg8_docs.log, 10_quality_gates/qg8_docs.exit
EVD-11 Dependency source proof Non-CRAN and file:// dependency source paths, commit hashes, and restore portability decision renv.lock, DESCRIPTION, git 00_release_identity/dependency_sources.md
EVD-12 Validate artefacts Required QG-6 artefacts results/quality_gate_validate 20_runner_artifacts/quality_gate_validate/
EVD-13 Run artefacts Required QG-7 artefacts results/quality_gate_run 20_runner_artifacts/quality_gate_run/
EVD-14 Sign-off record Completed final decision record sign-off template 40_signoff/sign_off_record.md

Exact required artefact paths

EVD-12 validate artefacts (QG-6)

Copy these paths from the run directory:

  • results/quality_gate_validate/00_run_metadata/config.original.yaml
  • results/quality_gate_validate/00_run_metadata/config.resolved.yaml
  • results/quality_gate_validate/00_run_metadata/config.compiled.yaml
  • results/quality_gate_validate/00_run_metadata/session_info.txt

EVD-13 run artefacts (QG-7)

Copy these paths from the run directory:

  • results/quality_gate_run/00_run_metadata/config.resolved.yaml
  • results/quality_gate_run/00_run_metadata/config.compiled.yaml
  • results/quality_gate_run/20_model_fit/model.rds
  • results/quality_gate_run/30_post_run/fitted.csv
  • results/quality_gate_run/30_post_run/observed.csv
  • results/quality_gate_run/40_diagnostics/diagnostics_report.csv

Collection commands

Create evidence structure:

source scripts/r-library-path.sh
dsambayes_set_r_library container
mkdir -p "$R_LIBS_USER"
VERSION="$(awk -F': ' '/^Version:/{print $2}' DESCRIPTION)"
EROOT="release_evidence/v${VERSION}/$(date +%Y%m%d)_$(git rev-parse --short HEAD)"
mkdir -p "$EROOT"/{00_release_identity,10_quality_gates,20_runner_artifacts,40_signoff}

Expected outcome: canonical evidence folders exist.

Capture release identity and changelog proof:

VERSION="$(awk -F': ' '/^Version:/{print $2}' DESCRIPTION)"
EROOT="release_evidence/v${VERSION}/$(date +%Y%m%d)_$(git rev-parse --short HEAD)"
{
  echo "candidate_commit=$(git rev-parse HEAD)"
  echo "candidate_branch=$(git rev-parse --abbrev-ref HEAD)"
  echo "target_tag=v${VERSION}"
  echo "package_version=$(awk -F': ' '/^Version:/{print $2}' DESCRIPTION)"
} > "$EROOT/00_release_identity/release_identity.txt"

sed -n '1,120p' CHANGELOG.md > "$EROOT/00_release_identity/changelog_top.md"

Expected outcome: release_identity.txt and changelog_top.md are populated.

Capture dependency source proof:

VERSION="$(awk -F': ' '/^Version:/{print $2}' DESCRIPTION)"
EROOT="release_evidence/v${VERSION}/$(date +%Y%m%d)_$(git rev-parse --short HEAD)"
{
  echo "# Dependency Sources"
  echo
  echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
  echo
  echo "## DESCRIPTION Remotes"
  awk '/^Remotes:/{flag=1} flag{print} /^[A-Za-z]+:/{if (flag && $1 != "Remotes:") flag=0}' DESCRIPTION
  echo
  echo "## renv non-CRAN sources"
  Rscript - <<'RS'
value_or_empty <- function(x) {
  if (is.null(x)) "" else x
}
lock <- renv:::renv_lockfile_read("renv.lock")
for (pkg in names(lock$Packages)) {
  rec <- lock$Packages[[pkg]]
  source <- value_or_empty(rec$Source)
  remote_url <- value_or_empty(rec$RemoteUrl)
  if (!identical(source, "Repository") || grepl("^file://", remote_url)) {
    cat("- ", pkg, "\n", sep = "")
    cat("  source: ", source, "\n", sep = "")
    if (nzchar(remote_url)) cat("  remote_url: ", remote_url, "\n", sep = "")
    if (!is.null(rec$RemoteSha)) cat("  remote_sha: ", rec$RemoteSha, "\n", sep = "")
  }
}
RS
} > "$EROOT/00_release_identity/dependency_sources.md"

Expected outcome: dependency sources are visible to reviewers. Any file:// source must be accepted as a local-release prerequisite or replaced with a reachable pinned remote before external release.

Capture gate logs and exit codes:

Run these commands inside a container whose R version matches renv.lock (currently 4.5.1). Set the container-specific library before collecting logs.

source scripts/r-library-path.sh
dsambayes_set_r_library container
mkdir -p "$R_LIBS_USER"
VERSION="$(awk -F': ' '/^Version:/{print $2}' DESCRIPTION)"
EROOT="release_evidence/v${VERSION}/$(date +%Y%m%d)_$(git rev-parse --short HEAD)"

Rscript scripts/check.R --lint > "$EROOT/10_quality_gates/qg1_lint.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg1_lint.exit"
Rscript scripts/check.R --style > "$EROOT/10_quality_gates/qg2_style.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg2_style.exit"
Rscript scripts/check.R --test > "$EROOT/10_quality_gates/qg3_tests.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg3_tests.exit"
Rscript scripts/check.R --stan-release-evidence > "$EROOT/10_quality_gates/qg4_stan_release_evidence.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg4_stan_release_evidence.exit"
_R_CHECK_FORCE_SUGGESTS_=false R -q -e 'rcmdcheck::rcmdcheck(args = c("--no-manual"), error_on = "warning")' > "$EROOT/10_quality_gates/qg5_rcmdcheck.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg5_rcmdcheck.exit"
Rscript scripts/dsambayes.R validate --config config/blm_timeseries.yaml --run-dir results/quality_gate_validate > "$EROOT/10_quality_gates/qg6_validate.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg6_validate.exit"
Rscript scripts/dsambayes.R run --config config/blm_timeseries.yaml --run-dir results/quality_gate_run > "$EROOT/10_quality_gates/qg7_run.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg7_run.exit"
( python3 docs-site/build_content.py && cd docs-site && hugo --cleanDestinationDir ) > "$EROOT/10_quality_gates/qg8_docs.log" 2>&1; echo $? > "$EROOT/10_quality_gates/qg8_docs.exit"

Expected outcome: eight gate logs and eight exit-code files are present.

Copy runner artefacts:

VERSION="$(awk -F': ' '/^Version:/{print $2}' DESCRIPTION)"
EROOT="release_evidence/v${VERSION}/$(date +%Y%m%d)_$(git rev-parse --short HEAD)"
mkdir -p "$EROOT/20_runner_artifacts"
cp -R results/quality_gate_validate "$EROOT/20_runner_artifacts/"
cp -R results/quality_gate_run "$EROOT/20_runner_artifacts/"

Expected outcome: runner artefacts are captured under evidence storage.

Evidence review checklist

Before sign-off, reviewers must confirm all items below:

  1. release_identity.txt commit hash matches the commit being tagged.
  2. sign_off_record.md repeats the same candidate hash and evidence-root path.
  3. package_version in release_identity.txt matches the intended release.
  4. changelog_top.md includes the intended DSAMbayes release section aligned with candidate changes.
  5. Every qg*.exit file contains 0.
  6. qg4_stan_release_evidence.log has no unresolved diagnostic-threshold failures.
  7. dependency_sources.md lists every non-CRAN source and any file:// source has an explicit portability decision.
  8. Required QG-6 and QG-7 artefact paths exist.
  9. Completed sign-off record exists at 40_signoff/sign_off_record.md.

Submission and retention

  1. Record the evidence root path in the manual sign-off record and any release review used by the team.
  2. Do not delete evidence for approved releases.
  3. For rejected releases, retain evidence and mark decision as NO-GO in sign-off.