---
title: "Transformation Replay and Detailed Posterior Predictive Checks"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Transformation Replay and Detailed Posterior Predictive Checks}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(gp3bayes)
```

## Replay recorded transformations

```{r}
sim <- simulate_hierarchical_binary_data(
  n_participants = 16,
  trials_per_participant = 8,
  n_items = 8,
  seed = 2030
)

contract <- create_model_contract(
  family = "binary",
  outcome_col = "selected",
  participant_col = "participant_id",
  item_col = "item_id",
  trial_col = "trial_id",
  condition_col = "condition",
  predictors = c("participant_covariate", "trial_covariate"),
  interaction = c("condition", "participant_covariate")
)

prepared <- prepare_hierarchical_binary_data(
  sim$data,
  contract,
  condition_levels = c("control", "treatment"),
  scale_predictors = c("participant_covariate", "trial_covariate")
)

recipe <- create_transformation_recipe(prepared)
recipe

replay_audit <- validate_transformation_replay(prepared)
replay_audit
```

The recipe stores the already-approved mapping, condition coding, scaling
centres/scales, formula, and model-matrix columns. It does not learn a new
transformation from new data.

```{r, fig.width=7, fig.height=4.5}
plot(replay_audit)
```

For prediction data, replay is explicit:

```{r}
raw_again <- invert_transformation_recipe(prepared$data, recipe)
replayed <- apply_transformation_recipe(
  raw_again,
  recipe,
  input_scale = "raw",
  require_outcome = TRUE
)
head(replayed)
```

Unseen condition values, missing required transformed predictors, or a duration
unit inconsistent with the stored source unit produce errors rather than silent
recoding.

## Detailed binary PPC

```{r, eval=FALSE}
binary_detail <- check_binary_ppc_details(
  fit_binary,
  draws = 500,
  calibration_bins = 10,
  sparse_cell_min = 3
)

binary_detail$calibration
binary_detail$participant_rates
binary_detail$item_rates
binary_detail$sparse_cells

plot(binary_detail, type = "calibration")
plot(binary_detail, type = "condition")
plot(binary_detail, type = "participant")
```

The detailed binary object exposes calibration gaps, participant and item event
rates, participant-condition sparsity, and replicated all-zero/all-one
participant patterns. These are descriptive discrepancy checks, not a single
pass/fail goodness-of-fit test.

## Detailed duration PPC

```{r, eval=FALSE}
duration_detail <- check_duration_ppc_details(
  fit_duration,
  draws = 500,
  quantiles = c(0.50, 0.90, 0.95),
  tail_threshold = 2000
)

duration_detail$quantile_table
duration_detail$participant_medians
duration_detail$item_medians
duration_detail$within_participant_condition_ratios

plot(duration_detail, type = "ecdf")
plot(duration_detail, type = "log_ecdf")
plot(duration_detail, type = "condition")
plot(duration_detail, type = "tail")
```

Raw- and log-scale distributions are both retained because a lognormal model
can appear reasonable on one scale while still missing substantively important
tail or grouping structure. Persistent discrepancies request model-contract
review and never trigger an automatic likelihood switch.
