drm_family_dpq() returns the {d, p, q} closures and atom metadata for a
fitted model's model_type. It is the single source of truth that
fitted_distribution() and downstream consumers (planned: quantile
residuals, predict(type = "quantile"), exceedance()) route through, so
the public-to-native parameter conversion is not re-derived in each caller.
Details
As of DO-T3 batch D, all 18 fitted model_type values are promoted
(status = "reference"): "gaussian", "student", "skew_normal",
"lognormal", "gamma", "tweedie", "beta", "zero_one_beta",
"beta_binomial", "binomial", "cumulative_logit", "poisson",
"zi_poisson", "nbinom2", "truncated_nbinom2", "hurdle_nbinom2",
"zi_nbinom2", and "biv_gaussian".
"skew_normal" promotion is a distributional-output-axis result only
(DG2/DG3 for {d,p,q} correctness); it does not certify the skew_normal
family's own fit-quality status (diagnostic_hold in check_drmTMB()),
which is a separate axis and is unchanged – see the firewall note beside
drm_family_dpq_skew_normal(). "biv_gaussian" is MARGINAL-only: its
{d,p,q} describe one response's marginal N(mu_k, sigma_k) (exact,
independent of rho12), never the joint bivariate distribution – see
drm_family_dpq_biv_gaussian() and fitted_distribution()'s response
argument, which selects k.
The d/p/q closures take (y_or_u, params), where params is a wide,
one-row-per-observation data frame. This signature is frozen (CP1): a
family needing extra per-row context beyond its dpars – binomial/
beta_binomial trials, cumulative_logit ordinal cutpoints (CP1..CPk),
truncation bounds, mixture weights – attaches it as an extra params
column inside fitted_distribution_params(), never by changing the
closure signature.