Internal (Engineering)

Purpose

Define manual quality gates and release-readiness checks for DSAMbayes. The normal cadence is quarterly; these pages deliberately do not prescribe CI/CD.

Audience

  • Maintainers preparing and validating releases.
  • Reviewers checking evidence before sign-off.

Pages

Page Topic
Testing and Validation Quality-gate execution commands, expected outcomes, and evidence capture
Quality Gates Gate definitions and pass/fail criteria
Runner Smoke Tests Minimal runner validation runs
Repository Size Cleanup Local repository-size findings and cleanup plan
Release Readiness Checklist Gate checklist and sign-off fields
Release Evidence Pack Artefact collection for stakeholder review
Release Playbook Manual, evidence-led quarterly release process
Sign-off Template Release sign-off record template

Subsections of Internal (Engineering)

Quality Gates

Purpose

Define the canonical release-quality gates for DSAMbayes v1.3.3, including commands, pass/fail criteria, and evidence requirements.

Audience

  • Maintainers preparing a release candidate
  • Reviewers signing off release readiness
  • Engineers running local pre-merge quality checks

Gate Matrix

Gate ID Gate Command Pass Criteria Evidence
QG-1 Lint Rscript scripts/check.R --lint Exit code 0, no lint failures, no SKIP: output Terminal log and exit code
QG-2 Style Rscript scripts/check.R --style Exit code 0, no style failures, no SKIP: output Terminal log and exit code
QG-3 Unit tests Rscript scripts/check.R --test Exit code 0, no test failures Terminal log and exit code
QG-4 Stan release evidence Rscript scripts/check.R --stan-release-evidence Exit code 0, high-budget pooled and hierarchical checks pass diagnostic thresholds Terminal log and exit code
QG-5 Package check _R_CHECK_FORCE_SUGGESTS_=false R -q -e 'rcmdcheck::rcmdcheck(args = c("--no-manual"), error_on = "warning")' No ERROR. No unresolved WARNING for release sign-off. Any NOTE requires explicit reviewer acceptance rcmdcheck summary and reviewer decision on NOTEs
QG-6 Runner smoke: validate Rscript scripts/dsambayes.R validate --config config/blm_timeseries.yaml --run-dir results/quality_gate_validate Exit code 0 CLI log and results/quality_gate_validate/00_run_metadata/config.compiled.yaml
QG-7 Runner smoke: run Rscript scripts/dsambayes.R run --config config/blm_timeseries.yaml --run-dir results/quality_gate_run Exit code 0 and core artefacts exist CLI log and selected artefacts under results/quality_gate_run/
QG-8 Docs build check python3 docs-site/build_content.py && (cd docs-site && hugo --cleanDestinationDir) Exit code 0 Build log and generated site output under docs-site/public/

Gate Definitions

QG-1 Lint

Command:

Rscript scripts/check.R --lint

Fail conditions:

  • Non-zero exit code
  • Any lint issue reported
  • Any SKIP: output

QG-2 Style

Command:

Rscript scripts/check.R --style

Fail conditions:

  • Non-zero exit code
  • Any file reported as requiring reformat
  • Any SKIP: output

QG-3 Unit Tests

Command:

Rscript scripts/check.R --test

Fail conditions:

  • Non-zero exit code
  • Any test failure or error

QG-4 Stan Release Evidence

Command:

Rscript scripts/check.R --stan-release-evidence

Fail conditions:

  • Non-zero exit code
  • Any high-budget Stan evidence test failure
  • Any unresolved diagnostic-threshold failure

QG-5 Package Check

Command:

_R_CHECK_FORCE_SUGGESTS_=false \
  R -q -e 'rcmdcheck::rcmdcheck(args = c("--no-manual"), error_on = "warning")'

Fail conditions:

  • Any ERROR
  • Any WARNING for release sign-off

Escalation condition:

  • Any NOTE must be reviewed and explicitly accepted with rationale.

Operational note:

  • Local package checks do not force Suggests because DSAMdecomp is an optional decomposition-only dependency and the upstream available package is telemetry-enabled. Decomposition-specific checks should be run separately against an approved telemetry-free DSAMdecomp install.

QG-6 Runner Smoke: Validate

Command:

Rscript scripts/dsambayes.R validate \
    --config config/blm_timeseries.yaml \
    --run-dir results/quality_gate_validate

Fail conditions:

  • Non-zero exit code
  • Missing results/quality_gate_validate/00_run_metadata/config.resolved.yaml
  • Missing results/quality_gate_validate/00_run_metadata/config.compiled.yaml

QG-7 Runner Smoke: Run

Command:

Rscript scripts/dsambayes.R run \
    --config config/blm_timeseries.yaml \
    --run-dir results/quality_gate_run

Fail conditions:

  • Non-zero exit code
  • Missing results/quality_gate_run/00_run_metadata/config.resolved.yaml
  • Missing results/quality_gate_run/00_run_metadata/config.compiled.yaml
  • Missing results/quality_gate_run/20_model_fit/model.rds
  • Missing results/quality_gate_run/30_post_run/fitted.csv
  • Missing results/quality_gate_run/30_post_run/observed.csv
  • Missing results/quality_gate_run/40_diagnostics/diagnostics_report.csv

QG-8 Docs Build Check

Command:

python3 docs-site/build_content.py
(cd docs-site && hugo --cleanDestinationDir)

Fail conditions:

  • Non-zero exit code
  • docs-site/build_content.py fails before content mirroring completes
  • Hugo build aborts before site generation
  • Missing docs-site/public/index.html

Command Reference

Recommended environment setup before running gates:

# Navigate to your local DSAMbayes checkout and select the host library
cd /path/to/DSAMbayes
source scripts/r-library-path.sh
dsambayes_set_r_library host
mkdir -p "$R_LIBS_USER" .cache
export XDG_CACHE_HOME="$PWD/.cache"
export _R_CHECK_FORCE_SUGGESTS_=false

Optional consolidated local gate (does not replace all release gates):

Rscript scripts/check.R --docs
Rscript scripts/check.R --smoke
Rscript scripts/check.R --stan-recovery
Rscript scripts/check.R --stan-release-evidence
Rscript scripts/check.R --release
Rscript scripts/check.R --all

Profile meanings:

  • --docs runs the local docs/link sanity helper against README and the tracked docs surfaces.
  • --smoke runs the fast unit path plus the minimal Stan-backed smoke subset.
  • --stan-recovery runs the full-gated DGP coefficient-recovery file only, intended for targeted numerical evidence refreshes.
  • --stan-release-evidence runs high-budget pooled and hierarchical Stan checks with diagnostic thresholds for release-candidate evidence.
  • --release runs lint, style, unit tests, minimal Stan smoke, docs sanity, and coverage.
  • --all remains the legacy lint + style + tests + coverage profile.

None of these profiles replaces rcmdcheck, runner smoke checks, or the docs-site build.

Evidence Requirements

Minimum evidence bundle per release candidate:

  1. Full terminal output and exit code for each gate QG-1 to QG-8.
  2. Runner smoke artefacts under results/quality_gate_validate/.
  3. Runner smoke artefacts under results/quality_gate_run/.
  4. rcmdcheck summary with explicit handling of NOTEs.
  5. Confirmation that no gate result is SKIP.

Evidence review should reference:

Failure and Escalation Rules

  1. Any gate failure blocks release tagging.
  2. Do not proceed to sign-off with unresolved ERROR or WARNING.
  3. NOTEs require written rationale and reviewer acceptance.
  4. If a gate fails due to environment setup, fix the environment and re-run the full affected gate. DSAMdecomp absence alone is not a blocker for QG-4 because the canonical package check flow treats it as an optional Suggests dependency.
  5. If a gate fails due to product code, raise a remediation change and re-run from QG-1.

Sign-off Criteria

Release sign-off requires all of the following:

  1. QG-1 to QG-8 passed.
  2. No SKIP outcomes across mandatory gates.
  3. Evidence bundle completed and reviewed.
  4. Final decision recorded in sign-off-template.md.

Testing and Validation

Purpose

Define the canonical testing and validation workflow for DSAMbayes v1.3.3, from local pre-merge checks through release-quality gates.

Audience

  • Engineers running local checks before merge
  • Maintainers preparing release candidates
  • Reviewers validating release evidence

Validation layers

Layer Objective Primary command(s) Output proof
Lint Catch style and static issues early Rscript scripts/check.R --lint Exit code 0, no lint failures
Style Enforce formatting compliance on changed files Rscript scripts/check.R --style Exit code 0, no reformat-required files
Unit tests Catch behavioural regressions in package logic Rscript scripts/check.R --test Exit code 0, no test failures
Minimal smoke Keep a cheap Stan-backed safety check in the routine local loop Rscript scripts/check.R --smoke Exit code 0, fast unit tests plus minimal Stan smoke pass
Stan smoke Exercise the broader compiled Stan suite beyond the minimal smoke tier Rscript scripts/check.R --stan-smoke Exit code 0, Stan smoke tests enabled
Stan recovery evidence Re-run the full coefficient-recovery file under the nightly Stan gate Rscript scripts/check.R --stan-recovery Exit code 0, full-Stan DGP recovery tests pass
Stan release evidence Re-run high-budget pooled and hierarchical evidence checks for release candidates Rscript scripts/check.R --stan-release-evidence Exit code 0, targeted high-budget Stan evidence passes diagnostic thresholds
Docs sanity Catch local docs-link breakage and high-value contract drift Rscript scripts/check.R --docs Exit code 0, docs sanity checks pass
Package check Validate package-level install and check behaviour R -q -e 'rcmdcheck::rcmdcheck(...)' No ERROR; no unresolved WARNING
Runner validate Validate config and data contracts without fitting Rscript scripts/dsambayes.R validate ... Exit code 0, metadata artefacts
Runner run Validate end-to-end runner execution and artefacts Rscript scripts/dsambayes.R run ... Exit code 0, core run artefacts
Docs build Validate docs-site/Hugo buildability python3 docs-site/build_content.py && (cd docs-site && hugo --cleanDestinationDir) Exit code 0, successful site build

Environment setup

Run all commands from repository root:

# Navigate to your local DSAMbayes checkout
cd /path/to/DSAMbayes
source scripts/r-library-path.sh
dsambayes_set_r_library host
mkdir -p "$R_LIBS_USER" .cache
export XDG_CACHE_HOME="$PWD/.cache"

Expected outcome: checks run in a repo-scoped environment with reproducible library and cache paths.

Dependency source portability

Before a release candidate is signed off, verify all non-CRAN dependency sources in renv.lock and DESCRIPTION.

The preferred release path is a pinned private GitHub remote for optional decomposition dependencies. A local fallback may restore those dependencies from sibling checkouts:

/home/user/Documents/GITHUB/tandpds/DSAMdecomp
/home/user/Documents/GITHUB/tandpds/teller

If any entries remain as file:// sources in renv.lock, release evidence must record the required local paths and pinned commit hashes. For an external release or clone-portable handoff, prefer reachable pinned remotes before sign-off.

When validating either dependency source path, use telemetry-disabled restores:

export GITHUB_PAT="<token with access to private tandpds repos>"
export DSAMDECOMP_DISABLE_TELEMETRY=1
export DSAMBAYES_DISABLE_TELEMETRY=1
export USE_BUNDLED_LIBUV=1
XDG_CACHE_HOME="$PWD/.cache" \
  Rscript -e 'renv::restore(packages = c("teller", "DSAMdecomp"), prompt = FALSE)'

Expected outcome: teller and DSAMdecomp restore and load from the recorded sources. If private GitHub authentication is unavailable, or a local fallback path is missing, hold the release until dependency sources are reproducible in the release environment.

Local validation workflows

Developer fast path (pre-merge)

Use the explicit local ladder:

Rscript scripts/check.R --test
Rscript scripts/check.R --smoke
Rscript scripts/check.R --docs
Rscript scripts/check.R --release

Expected outcomes:

  • --test stays fast and runs the unit path only.
  • --smoke runs the unit path plus a minimal Stan-backed subset: one cheap BLM MCMC smoke, one pooled deployment-artifact smoke on a real pooled fit, and tiny run_from_yaml() runner smokes including pooled deployment_model.rds roundtrip coverage.
  • --docs runs the local docs/link sanity helper against README and the tracked docs surfaces.
  • --release runs lint, style, unit tests, minimal Stan smoke, docs sanity, and coverage as a broader local code gate.

Implementation note:

  • scripts/check.R --all remains a legacy convenience gate for lint, style, tests, and coverage only.
  • scripts/check.R --docs is the explicit docs/link drift check.
  • scripts/check.R --release is the clearer code-focused local release profile.
  • Neither profile replaces rcmdcheck, runner smoke checks, or docs build.

Stan-specific note:

  • use Rscript scripts/check.R --stan-smoke for the broader opt-in compiled Stan suite
  • use --stan-smoke-full for the fuller nightly variant
  • use --stan-recovery when you need a targeted rerun of the DGP recovery evidence without invoking the rest of the full Stan suite
  • use --stan-release-evidence for the high-budget release-candidate lane covering the warning-prone pooled and hierarchical paths

Release-candidate full path

Run mandatory gates in this exact order:

Rscript scripts/check.R --lint
Rscript scripts/check.R --style
Rscript scripts/check.R --smoke
Rscript scripts/check.R --stan-release-evidence
_R_CHECK_FORCE_SUGGESTS_=false \
  R -q -e 'rcmdcheck::rcmdcheck(args = c("--no-manual"), error_on = "warning")'
Rscript scripts/dsambayes.R validate --config config/blm_timeseries.yaml --run-dir results/quality_gate_validate
Rscript scripts/dsambayes.R run --config config/blm_timeseries.yaml --run-dir results/quality_gate_run
python3 docs-site/build_content.py
(cd docs-site && hugo --cleanDestinationDir)

Expected outcome: all gates complete with exit code 0, with no unresolved release blockers.

Local package-check note:

  • DSAMdecomp remains an optional Suggests dependency. Canonical local rcmdcheck runs set _R_CHECK_FORCE_SUGGESTS_=false so release gates do not depend on installing a telemetry-enabled decomposition package.

Runner smoke-test expectations

Minimum release smoke expectations:

  1. scripts/check.R --smoke succeeds, proving at least one cheap Stan MCMC path, pooled deployment-artifact coverage on a real pooled fit, and tiny runner fit paths.
  2. validate command succeeds and writes metadata artefacts.
  3. run command succeeds and writes model, fitted/observed output, and diagnostics artefacts.
  4. Required runner artefact paths exist under results/quality_gate_validate/ and results/quality_gate_run/.

For matrix and exact artefact paths, use Runner Smoke Tests.

Evidence capture requirements

Before sign-off, capture:

  1. Full command logs and exit codes for all mandatory gates.
  2. Runner smoke artefacts from validate and run directories.
  3. Candidate commit hash and top changelog section.

Use Release Evidence Pack as the authoritative bundle contract.

Failure handling

  1. Any gate failure is a release blocker until resolved.
  2. Re-run the full failed gate after remediation.
  3. If rcmdcheck emits NOTE, record reviewer rationale explicitly.
  4. If runner artefacts are missing, inspect resolved config and outputs.* flags.

Runner Smoke Tests

Purpose

Define the minimal reproducible smoke-test matrix for the YAML runner validate and run commands, including exact commands and expected artefacts.

Audience

  • Maintainers preparing release evidence
  • Engineers triaging runner regressions
  • Reviewers confirming gate QG-5 and QG-6

Test scope

This smoke suite is intentionally small. It proves:

  • CLI argument handling for validate and run
  • Config resolution and runner pre-flight path
  • End-to-end artefact writing for one full run

This smoke suite does not replace unit tests or full package checks.

Preconditions

Run from repository root:

# Navigate to your local DSAMbayes checkout
cd /path/to/DSAMbayes
source scripts/r-library-path.sh
dsambayes_set_r_library host
mkdir -p "$R_LIBS_USER" .cache
export XDG_CACHE_HOME="$PWD/.cache"

Expected outcome: commands resolve local package/library paths and use repo-scoped Stan cache.

Install DSAMbayes locally if needed:

R -q -e 'install.packages(".", repos = NULL, type = "source")'

Expected outcome: library(DSAMbayes) succeeds in the same shell session.

Smoke-test matrix

Test ID Command Config Run directory Expected result
SMK-VAL-01 validate config/blm_timeseries.yaml results/smoke_validate_blm Exit code 0; metadata artefacts written.
SMK-VAL-02 validate config/cre_geo_panel.yaml results/smoke_validate_cre Exit code 0; metadata artefacts written.
SMK-RUN-01 run config/blm_timeseries.yaml results/smoke_run_blm Exit code 0; core fit, post-run, and diagnostics artefacts written.

Canonical commands

SMK-VAL-01

Rscript scripts/dsambayes.R validate \
    --config config/blm_timeseries.yaml \
    --run-dir results/smoke_validate_blm

Expected outcome: validation completes without Stan fitting and prints Status: ok.

SMK-VAL-02

Rscript scripts/dsambayes.R validate \
    --config config/cre_geo_panel.yaml \
    --run-dir results/smoke_validate_cre

Expected outcome: validation completes for the geo-panel CRE config and prints Status: ok.

SMK-RUN-01

Rscript scripts/dsambayes.R run \
    --config config/blm_timeseries.yaml \
    --run-dir results/smoke_run_blm

Expected outcome: full pipeline completes and prints Run complete with a resolved run directory.

Expected artefacts

Validate artefacts (SMK-VAL-01 to SMK-VAL-02)

For each validate run directory, these files are required:

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

Failure rule: missing any required file is a smoke-test failure.

Run artefacts (SMK-RUN-01)

Required core artefacts:

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

Recommended additional checks for stronger confidence:

  • 40_diagnostics/diagnostics_summary.txt

Failure rule: missing any required core artefact is a smoke-test failure.

Verification helper commands

Check validate artefacts quickly:

for d in results/smoke_validate_blm results/smoke_validate_cre; do
  test -f "$d/00_run_metadata/config.original.yaml" || echo "MISSING: $d config.original.yaml"
  test -f "$d/00_run_metadata/config.resolved.yaml" || echo "MISSING: $d config.resolved.yaml"
  test -f "$d/00_run_metadata/config.compiled.yaml" || echo "MISSING: $d config.compiled.yaml"
  test -f "$d/00_run_metadata/session_info.txt" || echo "MISSING: $d session_info.txt"
done

Expected outcome: no MISSING: lines.

Check core run artefacts quickly:

d="results/smoke_run_blm"
test -f "$d/00_run_metadata/config.resolved.yaml" || echo "MISSING: config.resolved.yaml"
test -f "$d/00_run_metadata/config.compiled.yaml" || echo "MISSING: config.compiled.yaml"
test -f "$d/20_model_fit/model.rds" || echo "MISSING: model.rds"
test -f "$d/30_post_run/fitted.csv" || echo "MISSING: fitted.csv"
test -f "$d/30_post_run/observed.csv" || echo "MISSING: observed.csv"
test -f "$d/40_diagnostics/diagnostics_report.csv" || echo "MISSING: diagnostics_report.csv"

Expected outcome: no MISSING: lines.

Failure triage

  1. If validate fails, run the same command again with a clean run directory path and inspect CLI error output.
  2. If run fails before fitting, inspect both 00_run_metadata/config.resolved.yaml and 00_run_metadata/config.compiled.yaml to confirm the authored and compiled values.
  3. If run fails during fitting, verify local Stan toolchain and cache path from Install and Setup.
  4. If artefacts are missing after success exit code, inspect outputs.* flags in the resolved config and confirm any compile-time artifacts in config.compiled.yaml.

Evidence capture

For release evidence, capture:

  1. Full terminal logs and exit codes for SMK-VAL-01 to SMK-RUN-01.
  2. Directory listings for each smoke run directory.
  3. The required artefacts listed above.

Store and review evidence with:

Repository Size Cleanup

Current state

Local inspection on 2026-04-04 found:

  • .git size: about 1.4G
  • packed objects: about 1.35 GiB
  • loose objects: 0
  • garbage objects: 0

This means the size is in committed history, not in disposable local Git metadata.

Largest historical contributors found so far:

  • results/: about 635 MiB
  • .Rlib/: about 444 MiB
  • .cache/: about 279 MiB
  • assets/: about 183 MiB
  • code_review/: about 125 MiB

Largest file classes found so far:

  • .rds: about 1.0 GiB
  • .pdf: about 184 MiB
  • .a: about 131 MiB
  • .so: about 118 MiB

The main current tracking gap is code_review/benchmarks/**/cache/, which is still versioned in HEAD.

Goal

Reduce future repository growth immediately, then decide separately whether to rewrite history to shrink existing clones.

Phase 1: Stop future growth

This phase is low risk and should be merged first.

Ignore rules

The repository should ignore:

  • /.Rlib/
  • /.cache/
  • /results/
  • /code_review/benchmarks/**/cache/
  • /assets/books/

/.Rlib/, /.cache/, and /results/ were already ignored before this note. The new additions are:

  • /code_review/benchmarks/**/cache/
  • /assets/books/

Remove cached benchmark artifacts from Git index

This removes tracked cache files from HEAD without deleting the local copies:

git rm -r --cached code_review/benchmarks/parity_blm/cache
git rm -r --cached code_review/benchmarks/parity_hierarchical/cache
git commit -m "chore: stop tracking benchmark caches"

Current tracked files that should be removed from the index:

code_review/benchmarks/parity_blm/cache/main/dsambayes/1.2.0/models/bayes_lm_updater_revised.rds
code_review/benchmarks/parity_blm/cache/refactor/dsambayes/1.2.0/models/bayes_lm_updater_revised_0d26146603.rds
code_review/benchmarks/parity_hierarchical/cache/main/dsambayes/1.2.0/models/hierarchical_1.rds
code_review/benchmarks/parity_hierarchical/cache/main/dsambayes/1.2.0/models/hierarchical_1.stan
code_review/benchmarks/parity_hierarchical/cache/refactor/dsambayes/1.2.0/models/hierarchical_1_centered_offset.stan
code_review/benchmarks/parity_hierarchical/cache/refactor/dsambayes/1.2.0/models/hierarchical_1_centered_offset_665e33077c.rds

Validation after Phase 1

Run:

git status --short
git check-ignore -v --no-index code_review/benchmarks/parity_blm/cache/main/dsambayes/1.2.0/models/example.rds
git check-ignore -v --no-index assets/books/example.pdf

Expected result:

  • benchmark cache files are ignored
  • local cache files remain on disk
  • repository history size does not materially shrink yet

Phase 2: Shrink existing history

This phase is disruptive and should only happen after coordination with every collaborator and any CI jobs or deployment hooks that clone this repository.

Safety rules

  • Freeze merges to main during the rewrite window.
  • Ask every collaborator to stop pushing until the rewrite is complete.
  • Create a backup mirror before modifying history.
  • Use a temporary clone or mirror for the rewrite, not an active working copy.

Suggested backup

cd ..
git clone --mirror DSAMbayes-Charles-Dev DSAMbayes-Charles-Dev.git-backup

Suggested rewrite target set

Remove historical content for paths that are local caches or generated outputs:

  • /.Rlib/**
  • /.cache/**
  • /results/**
  • /code_review/benchmarks/**/cache/**
  • /assets/books/**

Suggested workflow with git filter-repo

Use a fresh mirror clone:

cd ..
git clone --mirror <remote-url> DSAMbayes-Charles-Dev.git-rewrite
cd DSAMbayes-Charles-Dev.git-rewrite
git filter-repo \
  --path-glob '.Rlib/**' \
  --path-glob '.cache/**' \
  --path-glob 'results/**' \
  --path-glob 'code_review/benchmarks/**/cache/**' \
  --path-glob 'assets/books/**' \
  --invert-paths
git reflog expire --expire=now --all
git gc --prune=now --aggressive

Then verify size:

git count-objects -vH
du -sh .

Publish rewritten history

Only after verification:

git push --force --mirror

If branch protections block force-pushes, temporarily adjust them before the rewrite window and restore them immediately after.

Collaborator recovery after rewrite

Every collaborator should re-clone. If someone must salvage local work, they should:

git fetch origin
git switch main
git reset --hard origin/main

Re-cloning is still safer than trying to reuse an old clone after a large rewrite.

Phase 3: Optional future hardening

If large binary artifacts must remain versioned in future, move them to Git LFS. Do not use Git LFS for ephemeral caches, run outputs, or package libraries that should stay untracked.

  1. Merge the .gitignore change.
  2. Remove tracked benchmark cache files from the index with git rm --cached.
  3. Confirm CI and docs are unaffected.
  4. Decide whether the current 1.4G .git size justifies a history rewrite.
  5. If yes, schedule a short maintenance window and perform the rewrite from a mirror clone.

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.

Release Readiness Checklist

Purpose

Provide the mandatory go or no-go checklist before manually creating a DSAMbayes release tag. It supports the normal quarterly release cycle; it does not require CI/CD or a rapid release cadence.

How to use this checklist

  1. Complete this checklist after running all release-quality gates.
  2. Record evidence paths for each item.
  3. If any mandatory item fails, decision is NO-GO.
  4. Copy final decision details into Release Sign-off Template.

Mandatory checklist

ID Check Pass criteria Evidence required
RL-01 Candidate commit fixed Single candidate commit hash selected and recorded, with matching sign-off metadata 00_release_identity/release_identity.txt, 40_signoff/sign_off_record.md
RL-02 Version metadata aligned DESCRIPTION version equals intended release version 00_release_identity/release_identity.txt
RL-03 Changelog aligned Top CHANGELOG.md section matches candidate scope 00_release_identity/changelog_top.md
RL-04 QG-1 lint passed Exit code 0, no lint failures 10_quality_gates/qg1_lint.log, 10_quality_gates/qg1_lint.exit
RL-05 QG-2 style passed Exit code 0, no style failures 10_quality_gates/qg2_style.log, 10_quality_gates/qg2_style.exit
RL-06 QG-3 tests passed Exit code 0, no test failures 10_quality_gates/qg3_tests.log, 10_quality_gates/qg3_tests.exit
RL-07 QG-4 Stan release evidence passed Exit code 0; diagnostic thresholds passed 10_quality_gates/qg4_stan_release_evidence.*
RL-08 QG-5 package check passed No ERROR; no unresolved WARNING 10_quality_gates/qg5_rcmdcheck.log, 10_quality_gates/qg5_rcmdcheck.exit
RL-09 QG-6 validate passed Exit code 0; required validate artefacts present 10_quality_gates/qg6_validate.*, 20_runner_artifacts/quality_gate_validate/
RL-10 QG-7 run passed Exit code 0; required run artefacts present 10_quality_gates/qg7_run.*, 20_runner_artifacts/quality_gate_run/
RL-11 QG-8 docs build passed Exit code 0; docs-site build completed 10_quality_gates/qg8_docs.*
RL-12 Dependency sources recorded Non-CRAN and file:// dependency sources, revisions, and portability decisions are recorded; no credentials are included 00_release_identity/dependency_sources.md
RL-13 Evidence bundle complete All mandatory evidence items present Evidence root directory
RL-14 Exceptions resolved or accepted All exceptions documented with owner and approval 40_signoff/sign_off_record.md
RL-15 Final sign-off recorded Decision, approver, and timestamp completed 40_signoff/sign_off_record.md

Required runner artefact checks

Validate artefacts that must exist:

  1. 20_runner_artifacts/quality_gate_validate/00_run_metadata/config.original.yaml
  2. 20_runner_artifacts/quality_gate_validate/00_run_metadata/config.resolved.yaml
  3. 20_runner_artifacts/quality_gate_validate/00_run_metadata/config.compiled.yaml
  4. 20_runner_artifacts/quality_gate_validate/00_run_metadata/session_info.txt

Run artefacts that must exist:

  1. 20_runner_artifacts/quality_gate_run/00_run_metadata/config.resolved.yaml
  2. 20_runner_artifacts/quality_gate_run/00_run_metadata/config.compiled.yaml
  3. 20_runner_artifacts/quality_gate_run/20_model_fit/model.rds
  4. 20_runner_artifacts/quality_gate_run/30_post_run/fitted.csv
  5. 20_runner_artifacts/quality_gate_run/30_post_run/observed.csv
  6. 20_runner_artifacts/quality_gate_run/40_diagnostics/diagnostics_report.csv

Decision rules

  1. GO only if every checklist item RL-01 to RL-15 passes.
  2. NO-GO if any mandatory item fails or evidence is incomplete.
  3. HOLD if no hard failure exists but final approval is pending.
  4. Tag creation is allowed only after GO decision is recorded.
  5. A NOTE or expected low-budget smoke-test sampler warning is not a blanket exception: its source and reviewer treatment must be recorded. QG-4 high-budget diagnostic-threshold failures always block release pending an explicit human decision.

Completion record template

Use this section when running the checklist.

Field Value
Release version <fill>
Candidate commit hash <fill>
Checklist executor <fill>
Checklist completion date (UTC) <YYYY-MM-DD>
Checklist result (GO/NO-GO/HOLD) <fill>
Evidence root path <fill>
Sign-off record path <fill>

Audit continuity reference

For programme-level historical traceability, also review:

  • refactoring_plan/release_readiness_checklist_v1.2.md

This page is the operational checklist for current release execution.

Release Playbook

Purpose

Define the deliberate, evidence-led release process for DSAMbayes. It supports the normal quarterly release cycle and material ad-hoc releases. It is not a CI/CD process and does not imply continuous deployment or a high release cadence.

The point is to make the infrequent release decision reproducible and reviewable, not to automate it for its own sake.

Roles and release boundary

  • Release owner: fixes the candidate commit, runs or coordinates the gates, and prepares the evidence bundle.
  • Reviewer: independently checks the evidence and records the GO, NO-GO, or HOLD decision. The reviewer should be different from the release owner when practical.
  • Maintainers: resolve failures or explicitly approve a documented exception.

One release has one candidate commit. Do not make product, dependency, or documentation changes after gates begin. If a change is required, create a new candidate and rerun the affected gates.

Preconditions

Before starting:

  1. The intended version is consistent in DESCRIPTION and CHANGELOG.md.
  2. The candidate commit is identified and the working tree is clean apart from deliberately excluded local evidence and run artefacts.
  3. The local R runtime and package library are recorded. The current tested baseline is R 4.5.1; DESCRIPTION declares the supported runtime floor. The floor is a compatibility policy, not a claim that every R version has been exercised for every release.
  4. Required non-CRAN dependencies, including DSAMdecomp, are reachable at the recorded revision. Record the source and commit SHA in the evidence bundle. Do not record credentials.
  5. No Stan template, prior, boundary-default, or fit-semantics change is released without the required human model review.

Manual release flow

1. Freeze and identify the candidate

git status --short
git rev-parse HEAD
git rev-parse --abbrev-ref HEAD

Record the full SHA, branch, intended tag, package version, R version, and platform in 00_release_identity/release_identity.txt of the evidence bundle. Use the current package version rather than editing this playbook for each release.

2. Prepare the local environment

source scripts/r-library-path.sh
dsambayes_set_r_library container
mkdir -p "$R_LIBS_USER" .cache
export XDG_CACHE_HOME="$PWD/.cache"
export _R_CHECK_FORCE_SUGGESTS_=false
export DSAMDECOMP_DISABLE_TELEMETRY=1
export DSAMBAYES_DISABLE_TELEMETRY=1
export USE_BUNDLED_LIBUV=1

R -q -e 'install.packages(".", repos = NULL, type = "source")'
R --version

Use a local container only when it makes the environment easier to reproduce; it is evidence capture, not a CI service. Its R version must match renv.lock (currently 4.5.1); record the image and digest if one is used. The helper selects .Rlib-container-r<active-R-version>/; never mount a host library as the container package library.

3. Create the evidence root

Use the layout defined in Release Evidence Pack. The evidence root is local working material until the release owner decides how it will be retained. It must not contain .env, credentials, private data, or unredacted tokens.

4. Run the mandatory gates once, against the frozen candidate

Run QG-1 to QG-8 from Quality Gates, capturing both complete logs and exit codes. The canonical commands are:

Rscript scripts/check.R --lint
Rscript scripts/check.R --style
Rscript scripts/check.R --test
Rscript scripts/check.R --stan-release-evidence
_R_CHECK_FORCE_SUGGESTS_=false \
  R -q -e 'rcmdcheck::rcmdcheck(args = c("--no-manual"), error_on = "warning")'
Rscript scripts/dsambayes.R validate \
  --config config/blm_timeseries.yaml --run-dir results/quality_gate_validate
Rscript scripts/dsambayes.R run \
  --config config/blm_timeseries.yaml --run-dir results/quality_gate_run
python3 docs-site/build_content.py
(cd docs-site && hugo --cleanDestinationDir)

scripts/check.R --release is a useful local consolidation check, but it does not replace rcmdcheck, the two runner checks, the docs-site build, or the high-budget --stan-release-evidence gate.

5. Interpret warnings correctly

The release decision is based on the mandatory gates, not on a search for a silent terminal.

  • A non-zero exit code, missing required tool, test failure, unresolved package WARNING, failed diagnostic threshold, or missing required runner artefact is a blocker.
  • rcmdcheck NOTEs require written review and acceptance; they are not silently waived.
  • Low-budget Stan smoke tests can emit deliberately exercised sampler warnings. They are not release evidence and must be recorded as expected test-fixture behaviour if observed. The high-budget QG-4 diagnostics are the release evidence and may not be waived without an explicit human decision.
  • Any new, unexplained warning is a HOLD until it is understood or removed.

6. Review and sign off

Complete the Release Readiness Checklist and copy Release Sign-off Template into the evidence bundle. A GO requires all mandatory checks to pass, the candidate SHA to match throughout, and the reviewer to sign the decision.

7. Tag and publish manually

Only after GO:

git tag -a vX.Y.Z -m "DSAMbayes vX.Y.Z"
git push origin vX.Y.Z

Create any GitHub release and publish any docs mirror as separate manual acts. Record what was published, by whom, and when. No automatic deployment follows from tagging.

8. Retain the decision record

Retain the signed evidence bundle for approved and rejected candidates. Record post-release defects as a new hotfix candidate; do not retag or rewrite the published release history.

Go/no-go rules

  1. GO only when QG-1 to QG-8 pass and the sign-off record is complete.
  2. HOLD when evidence is incomplete, a warning is unexplained, or approval is pending.
  3. NO-GO for any release blocker. Fix the issue, select a new candidate SHA, and rerun the affected gates.

Hotfixes

For a post-release defect, branch from the affected tag, make the smallest safe change, update the version and changelog, and run the same manual process. The smaller scope does not remove the evidence or human-review requirement.

Sign-off Template

Purpose

Provide the final approval record for a DSAMbayes release candidate after all mandatory evidence has been reviewed.

Instructions

  1. Copy this template into the candidate evidence bundle as 40_signoff/sign_off_record.md.
  2. Complete every field.
  3. Use GO, NO-GO, or HOLD for the decision.
  4. If any exception is accepted, record explicit rationale and owner.
  5. Copy the candidate commit hash and evidence-root path directly from 00_release_identity/release_identity.txt; do not introduce a second candidate hash during sign-off.

Release identification

Field Value
Release version vX.Y.Z
Package version (DESCRIPTION) <fill>
Candidate commit hash <fill>
Candidate branch <fill>
Intended tag <fill>
R version and platform <fill>
Container image/digest (if used) <fill or n/a>
DSAMdecomp source and revision <fill or n/a>
Changelog section verified <yes/no>
Evidence root path <fill>

Decision summary

Field Value
Decision <GO/NO-GO/HOLD>
Decision date (UTC) <YYYY-MM-DD>
Decision timestamp (UTC) <YYYY-MM-DDTHH:MM:SSZ>
Release owner <name>
Primary approver <name>
Secondary reviewer (if used) <name or n/a>

Decision rationale:

<fill>

Quality gate outcomes

Gate ID Outcome (pass/fail) Evidence file(s) Reviewer notes
QG-1 Lint <fill> 10_quality_gates/qg1_lint.log, 10_quality_gates/qg1_lint.exit <fill>
QG-2 Style <fill> 10_quality_gates/qg2_style.log, 10_quality_gates/qg2_style.exit <fill>
QG-3 Unit tests <fill> 10_quality_gates/qg3_tests.log, 10_quality_gates/qg3_tests.exit <fill>
QG-4 Stan release evidence <fill> 10_quality_gates/qg4_stan_release_evidence.log, 10_quality_gates/qg4_stan_release_evidence.exit <fill>
QG-5 Package check <fill> 10_quality_gates/qg5_rcmdcheck.log, 10_quality_gates/qg5_rcmdcheck.exit <fill>
QG-6 Runner validate <fill> 10_quality_gates/qg6_validate.log, 10_quality_gates/qg6_validate.exit <fill>
QG-7 Runner run <fill> 10_quality_gates/qg7_run.log, 10_quality_gates/qg7_run.exit <fill>
QG-8 Docs build <fill> 10_quality_gates/qg8_docs.log, 10_quality_gates/qg8_docs.exit <fill>

Mandatory artefact checks

Artefact Present (yes/no) Path Notes
Original config (validate) <fill> 20_runner_artifacts/quality_gate_validate/00_run_metadata/config.original.yaml <fill>
Resolved config (validate) <fill> 20_runner_artifacts/quality_gate_validate/00_run_metadata/config.resolved.yaml <fill>
Compiled config (validate) <fill> 20_runner_artifacts/quality_gate_validate/00_run_metadata/config.compiled.yaml <fill>
Session info (validate) <fill> 20_runner_artifacts/quality_gate_validate/00_run_metadata/session_info.txt <fill>
Resolved config (run) <fill> 20_runner_artifacts/quality_gate_run/00_run_metadata/config.resolved.yaml <fill>
Compiled config (run) <fill> 20_runner_artifacts/quality_gate_run/00_run_metadata/config.compiled.yaml <fill>
Model object (run) <fill> 20_runner_artifacts/quality_gate_run/20_model_fit/model.rds <fill>
Fitted values (run) <fill> 20_runner_artifacts/quality_gate_run/30_post_run/fitted.csv <fill>
Observed values (run) <fill> 20_runner_artifacts/quality_gate_run/30_post_run/observed.csv <fill>
Diagnostics report (run) <fill> 20_runner_artifacts/quality_gate_run/40_diagnostics/diagnostics_report.csv <fill>

Exceptions and risk acceptance

Record every exception. If there are none, write none.

ID Exception Reason Risk owner Expiry date Approved (yes/no)
EX-01 <fill or none> <fill> <fill> <YYYY-MM-DD or n/a> <fill>

Required follow-up actions

Record actions that must happen after release decision.

ID Action Owner Due date Tracking link
ACT-01 <fill or none> <fill> <YYYY-MM-DD or n/a> <fill or n/a>

Final approval signatures

Role Name Signature mode Date (UTC)
Release owner <fill> <typed/e-sign> <YYYY-MM-DD>
Approver <fill> <typed/e-sign> <YYYY-MM-DD>
Additional approver (optional) <fill or n/a> <typed/e-sign or n/a> <YYYY-MM-DD or n/a>

Final decision statement

<Release vX.Y.Z is approved for tagging and publication.>

or

<Release vX.Y.Z is not approved. See exceptions and actions.>