Diagnostics Gates
For the workflow interpretation of these checks, start with Stage 4: Computation and Sampler and Stage 5: Model Adequacy. This page is the threshold and policy reference.
Use this page when you need exact gate thresholds, status aggregation, or YAML policy semantics. It does not replace substantive model review: a model can clear threshold tables and still be a poor basis for interpretation.
Geographic FE/RE/CRE models also have separate pre-fit panel design diagnostics, including same-date geographic contrasts and conditional design support.
Editable gate profiles
Edit config/diagnostic_gates.yml to define team reporting thresholds. The
shipped BLM, RE and CRE examples reference this complete profile:
Relative paths resolve from the model YAML directory, including when runme.R
applies CLI data or holiday overrides. The file is validated before compilation,
including --mode=validate. Each profile requires schema_version: 1, a
non-empty profile name and description, and the complete thresholds mapping.
For example, one entry in that mapping is:
The profile controls reporting, not the likelihood, priors, numerical design
checks or estimator support. Strict > and < comparisons are used; equality
does not breach a threshold, and failure takes precedence. Equal warn/fail
thresholds have no warning band. fail: null makes a finite result warning-only.
Non-finite evidence for an evaluated check cannot pass; checks that do not apply
remain skipped with reasons. MCMC gates are skipped for MAP. Empty or entirely
skipped evidence is not PASS and has unknown publishability.
Unknown or duplicate keys, incomplete mappings, non-finite thresholds, invalid
domains and reversed warn/fail ordering are errors. warn is required and
numeric; fail must be explicitly numeric or null. Do not combine a gate file
with inline pareto_k_warn/pareto_k_fail or abs_corr_warn/abs_corr_fail.
An explicit file controls all configurable gate classifications, including
failures in publish mode. Without a file, the package resolves the existing
mode and inline thresholds into a named default profile. policy_mode still
controls existing structural/preflight policies that are outside this file.
A gate file cannot relax estimator-specific rank or support requirements.
The runner freezes the resolved profile before fitting and records its source,
content hash and hash algorithm in 40_diagnostics/diagnostic_gates.resolved.yaml.
The hash uses rlang::hash; it is labelled rlang_hash, not SHA-256. Editing a
profile during sampling does not change the active run. Version-control the
profile with the model configuration; change its name when issuing a new team
policy. The resolved snapshot contains provenance fields and is an output
artifact; use the four authored fields above when creating a new input profile.
| Profile key | Statistic and scope | Breach direction |
|---|---|---|
design_max_vif |
Maximum correlation-based VIF on fitted population design X, excluding intercept | > |
design_condition_number |
Existing condition number on fitted population design X | > |
mcmc_divergence_count |
Post-warmup divergent transition count | > |
mcmc_max_rhat |
Maximum split R-hat across the existing monitored parameter set | > |
mcmc_min_ess_bulk |
Minimum bulk effective sample size across monitored parameters | < |
mcmc_min_ess_tail |
Minimum tail effective sample size across monitored parameters | < |
mcmc_bfmi_min |
Minimum energy BFMI across chains | < |
mcmc_treedepth_rate |
Fraction of transitions at the maximum treedepth | > |
bayesian_pareto_k_max |
Maximum PSIS Pareto-k; optional model-selection availability applies | > |
residual_ljung_box_p |
Minimum residual Ljung-Box p-value across groups | < |
residual_max_abs_acf |
Maximum absolute residual ACF across groups | > |
posterior_boundary_hit_rate |
Maximum posterior boundary-hit fraction | > |
design_min_within_variation |
Existing minimum hierarchical within-variation ratio | < |
design_baseline_media_abs_corr |
Maximum absolute configured baseline/media correlation | > |
VIF interpretation
VIF is a collinearity diagnostic, not a hypothesis test. The default warning
above 10 and failure above 30 reuse the existing preflight thresholds. The
report records the maximum and limiting term; diagnostic_vif.csv retains
per-term values, statuses, limits and design scope. vif_bar.png uses the same
resolved rule. Fewer than two population predictors is not applicable; singular
or constant predictors cannot produce a passing VIF gate.
This population-design VIF is distinct from CRE between-design VIF in
cre_estimability_vif.csv. Those estimator-specific diagnostics and safeguards
remain unchanged. The standard diagnostic-report API remains unsupported for
FE; FE runs retain their existing dedicated estimator artifacts. FE configs
reject diagnostics.gates_file and do not produce a standard gate snapshot.
No generic FE gate packet or new estimator qualification is implied.
Terminal output
Rscript runme.R and the package CLI print grouped diagnostic results, observed
values, threshold rules, limiting terms/parameters/chains where available,
skipped reasons and recovery guidance. The report is derived from the same
structured checks saved to CSV. Colours supplement explicit PASS/WARN/FAIL/
SKIPPED words; plain and redirected output remain readable. A diagnostic FAIL
is distinct from a failed fit: retain and inspect the fitted model and reports.
Existing CLI codes remain 0 for completion without diagnostic failure, 1 for
completed runs needing failure review, and 2 for execution/configuration errors.
Model selection for time-ordered data
PSIS-LOO and WAIC treat pointwise observations as conditionally exchangeable. That assumption is not generally appropriate for time-ordered MMM data, where nearby weeks can remain dependent after conditioning on the fitted model.
Use the runner’s expanding-window blocked CV or leave-future-out CV as the primary evidence when selecting among time-series MMM specifications. Treat PSIS-LOO, WAIC, and Pareto-k outputs as supplementary fit and influence diagnostics. They do not establish future-period predictive performance, causal validity, or a publish-gate pass on their own.
Purpose
dsambayesplus runs a deterministic diagnostics framework after model fitting. Each diagnostic check produces a pass, warn, or fail status. The resolved gate profile controls the configurable thresholds. This page defines the check taxonomy, threshold tables, policy modes, identifiability gate, and the overall status aggregation rule.
How to use this page
- Use Stage 4: Computation and Sampler to understand which checks are non-negotiable before trusting the posterior.
- Use this page to see the exact dsambayesplus thresholds and artifact semantics.
- Use Stage 5: Model Adequacy before treating a passing diagnostics table as permission for decomposition, model comparison, or optimisation.
Policy modes
Without an explicit gate file, the diagnostics framework resolves these preset modes from diagnostics.policy_mode:
| Mode | Intent | Threshold behaviour |
|---|---|---|
explore |
Rapid iteration during model development | Relaxed fail thresholds; many checks can only warn, not fail |
publish |
Default production mode for shareable outputs | P0 sampler and integrity checks can fail; condition-number, residual, boundary and within-variation P1 checks are warn-only |
strict |
Audit-grade gating for release candidates | Tightest thresholds; rank deficit fails rather than warns |
The mode is resolved by diagnostics_policy_thresholds(mode) in R/diagnostics_thresholds.R.
Check taxonomy
Checks are organised into phases:
| Phase | Scope | When evaluated |
|---|---|---|
P0 |
Data integrity and critical MCMC reliability | Pre-fit and post-fit publish gates |
P1 |
Design conditioning, residual behaviour and identifiability | Pre-fit and post-fit model-review checks |
P2 |
Supplementary model-selection evidence | Post-fit predictive scoring |
Each check row includes:
| Field | Meaning |
|---|---|
check_id |
Unique identifier |
phase |
P0, P1 or P2 |
severity |
Check priority recorded by the diagnostics registry |
status |
pass, warn, fail, or skipped |
metric |
Metric name |
value |
Observed value |
threshold |
Applied threshold description |
message |
Human-readable explanation |
Design checks
| Check ID | Metric | Pass | Warn | Fail |
|---|---|---|---|---|
pre_response_finite |
non_finite_response_count |
== 0 |
n/a | > 0 |
pre_design_constants_duplicates |
constant_plus_duplicate_columns |
== 0 |
n/a | > 0 |
pre_design_rank_deficit |
rank_deficit |
== 0 |
> 0 (publish) |
> 0 (strict) |
pre_design_condition_number (P1) |
kappa_X |
≤ warn |
> warn |
> fail |
Condition number thresholds by mode
| Mode | Warn | Fail |
|---|---|---|
explore |
10,000 | ∞ (cannot fail) |
publish |
10,000 | 1,000,000 (warn-only; fail disabled) |
strict |
10,000 | 1,000,000 |
P0 sampler checks (MCMC only)
| Check ID | Metric | Direction | Warn | Fail |
|---|---|---|---|---|
post_rhat_max |
max_rhat |
Lower is better | 1.01 | 1.01 |
post_ess_bulk_min |
min_ess_bulk |
Higher is better | 400 | 200 |
post_ess_tail_min |
min_ess_tail |
Higher is better | 200 | 100 |
post_ebfmi |
min_ebfmi |
Higher is better | 0.30 | 0.20 |
post_treedepth_saturation |
treedepth_hit_fraction |
Lower is better | 0.00 | 0.01 |
post_divergences |
divergent_fraction |
Lower is better | 0.00 | 0.00 |
Mode adjustments for sampler checks
dsambayesplus treats any Rhat above 1.01 as a failure in publish and strict
modes, following the rank-normalised, folded Rhat guidance in
Vehtari et al. (2021) and the
Stan warnings guide. In
explore mode, the fail threshold is deliberately relaxed to 1.10, while
the warning threshold remains 1.01.
P1 residual checks
| Check ID | Metric | Direction | Warn | Fail |
|---|---|---|---|---|
post_residual_ljung_box_p_min |
resid_lb_p |
Higher is better | 0.05 | 0.01 |
post_residual_max_abs_acf |
resid_acf_max |
Lower is better | 0.20 | 0.40 |
Mode adjustments for residual checks
| Mode | resid_lb_p warn |
Raw fail boundary / effective state | resid_acf warn |
Raw fail boundary / effective state |
|---|---|---|---|---|
explore |
0.05 | 0.00 (cannot fail) | 0.20 | ∞ (cannot fail) |
publish |
0.05 | 0.01 (warn-only; fail disabled) | 0.20 | 0.40 (warn-only; fail disabled) |
strict |
0.10 | 0.05 | 0.15 | 0.30 |
In publish mode, values beyond the raw residual fail boundary remain warn.
The persisted threshold field states that failure is disabled and retains the
raw boundary for triage. Non-residual P0 failures can still make the overall
run fail.
P1 boundary hit check
| Check ID | Metric | Direction | Warn | Fail |
|---|---|---|---|---|
post_boundary_hit_rate_max |
boundary_hit_frac |
Lower is better | 0.05 | 0.20 |
In explore mode, boundary hits cannot fail. Publish mode retains the raw
fail > 0.20 boundary for triage but records values beyond it as warn.
Failure is disabled for this check in publish mode. In strict mode,
thresholds tighten to warn > 0.02, fail > 0.10.
P1 within-group variation check
| Check ID | Metric | Direction | Warn | Fail |
|---|---|---|---|---|
pre_within_variation_ratio_min |
within_var_min_ratio |
Higher is better | 0.10 | 0.05 |
This check applies to hierarchical models and flags groups where within-group
variation is extremely low relative to between-group variation. In explore
mode, the fail threshold is zero (cannot fail). Publish mode retains the raw
fail < 0.05 boundary for triage but records values below it as warn;
failure is disabled for this check. Strict mode applies warn < 0.15 and
fail < 0.10.
Identifiability gate
The P1 pre_identifiability_baseline_media_corr check measures the maximum
absolute correlation between baseline terms and media terms in the design
matrix. It is configured via diagnostics.identifiability in YAML:
Term detection
- Media terms: explicitly listed in
media_terms. - Baseline terms: union of
baseline_terms, generated time-component terms, and matches frombaseline_regexpatterns. - Both sets are intersected with actual design-matrix columns and filtered to remove constant columns.
Thresholds by mode
| Mode | Warn | Fail |
|---|---|---|
explore |
0.80 | ∞ (cannot fail) |
publish |
0.80 | 0.95 |
strict |
0.70 | 0.85 |
Skip conditions
The identifiability gate reports skipped when:
identifiability.enabled: false- No configured media terms found in the design matrix
- No baseline terms detected from configured terms/regex
- All resolved baseline or media terms are constant
Overall status aggregation
The overall diagnostics status is determined by diagnostics_overall_status():
- If any check has
status == "fail"→ overall status is fail. - If any check has
status == "warn"(and none fail) → overall status is warn. - Otherwise → overall status is pass.
Checks with status == "skipped" do not affect the overall status.
P2 rows use the emitted post_model_selection_method, post_psis_loo,
post_psis_loo_options_ignored, post_psis_loo_time_dependence,
post_psis_loo_elpd, post_psis_loo_looic and
post_psis_loo_pareto_k identifiers. They record supplementary predictive
evidence and do not override P0 or P1 failures.
The runner also emits post_sampler_params_available when sampler parameters
can be inspected and post_sampler_unavailable_for_optimise for the explicit
MAP not-applicable path. These identifiers are part of the persisted report;
they are not substitute MCMC diagnostics for a MAP fit.
Runner artefact output
The diagnostics framework produces:
| Artefact | Location | Content |
|---|---|---|
diagnostics_report.csv |
40_diagnostics/ |
Full check table with all fields |
diagnostics_summary.txt |
40_diagnostics/ |
Human-readable summary of overall status and failing checks |
Interpretation guidance
skipped: no evaluated evidence; this is not a gate pass.pass: no enabled check breached its configured threshold. This does not establish substantive adequacy, causal validity or suitability for the intended decision.warn: review recommended; the model may have quality concerns but does not block the configured policy.fail: at least one enabled check breached a fail threshold; resolve it before using the result for decisions.
Common remediation actions
| Diagnostic area | Warning signs | Actions |
|---|---|---|
| High Rhat | > 1.01 |
Increase MCMC iterations or warmup; simplify model |
| Low ESS | < 400 bulk or < 200 tail |
Increase iterations; check for multimodality |
| Divergences | Any non-zero fraction | Increase adapt_delta; reparameterise model |
| High condition number | kappa > 10,000 |
Reduce collinearity; remove redundant terms |
| Residual autocorrelation | High ACF or low Ljung-Box p | Add time controls (trend, seasonality, holidays) |
| Boundary hits | > 5% of draws |
Review boundary specification; widen or remove constraints |
| High baseline-media correlation | > 0.80 |
Add controls to separate baseline from media; consider alternative model specifications |
Cross-references
- Model Classes, which diagnostics apply to each class
- Response Scale Semantics, residuals are computed on model scale
- Config Schema,
diagnostics.*YAML keys - Output Artefacts, diagnostics artefact paths
- Diagnostics Plots, visual diagnostic outputs