--- title: "GPCM scope and current limitations" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{GPCM scope and current limitations} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ``` `mfrmr` includes a bounded implementation of the Generalized Partial Credit Model (GPCM; Muraki 1992). The estimator and the main package-native reporting routes are available, but several outputs still carry caveats because score-side semantics under free discrimination differ from the Rasch-family case. This vignette documents which helpers are available, which are caveated, and what remains restricted. ## Checking the support boundary `gpcm_capability_matrix()` is the canonical reference. It returns one row per helper family with a `Status` column drawn from `supported`, `supported_with_caveat`, `blocked`, and `deferred`, plus the rationale and the evidence trail behind each classification. ```{r capability-supported} library(mfrmr) gpcm_capability_matrix("supported")[, c("Area", "Status")] ``` ```{r capability-with-caveat} gpcm_capability_matrix("supported_with_caveat")[, c("Area", "Status")] ``` ```{r capability-blocked} gpcm_capability_matrix("blocked")[, c("Area", "Status", "Boundary")] ``` ```{r capability-deferred} gpcm_capability_matrix("deferred")[, c("Area", "Status")] ``` The matrix is intentionally conservative. A row stays in `blocked` or `deferred` even when some lower-level component already runs, because the scope statement reflects the validation evidence rather than the raw code path. ## What works today The following routes are validated for bounded `GPCM`: - **Fitting and core summaries** via `fit_mfrm(model = "GPCM", step_facet = ...)`. The validated default keeps `slope_facet == step_facet`, with the direct `MML` engine. - **Posterior scoring and information** via `predict_mfrm_units()`, `sample_mfrm_plausible_values()`, `compute_information()`, and `plot_information()`. - **Curve and category views** via `plot(fit, type = c("wright", "pathway", "ccc", "ccc_surface"))`, `category_structure_report()`, and `category_curves_report()`. - **Slope-aware simulation specifications** via `build_mfrm_sim_spec()` and `simulate_mfrm_data()`. ## What works with caveats The following are exposed for `GPCM` but should be read as exploratory screens rather than as Rasch-style invariance evidence: - `diagnose_mfrm()` and the residual and unexpected-response stack: `unexpected_response_table()`, `displacement_table()`, `measurable_summary_table()`, `rating_scale_table()`, `interrater_agreement_table()`, `facet_quality_dashboard()`, `plot_qc_dashboard()`, `plot_marginal_fit()`, `plot_marginal_pairwise()`. - `reporting_checklist()` and `precision_audit_report()` route to the supported direct tables and plots only. `build_visual_summaries()` and `run_qc_pipeline()` bundle those screens and return a support caveat; they do not imply FACETS score-side compatibility. - `build_apa_outputs()`, `build_mfrm_manifest()`, `build_mfrm_replay_script()`, and `export_mfrm_bundle()` run as package-native reproducibility/reporting routes and return an explicit GPCM support caveat. - `evaluate_mfrm_design()`, `evaluate_mfrm_diagnostic_screening()`, `evaluate_mfrm_signal_detection()`, and `predict_mfrm_population()` can consume bounded GPCM simulation contracts. Treat the resulting planning summaries as model-based forecasts rather than validation of Rasch-family fair-score invariance. - `build_misfit_casebook()` inherits the exploratory screening framing of its underlying sources. - `fair_average_table()` and `estimate_bias()` use the slope-aware element-conditional GPCM kernel. Read their `caveat` fields before quoting SE, t, or probability columns. `diagnose_mfrm()` now carries the same slope-aware fair-average table used by `fair_average_table()`, so visual summaries and QC checks can route it without recomputing a substitute table. ## What is intentionally restricted The FACETS compatibility score-side exports remain restricted under `GPCM` because the free discrimination parameter changes the relationship between the latent measure and the expected category. Specifically: - `facets_parity_report()` and `facets_output_file_bundle(include = "score")` still depend on a FACETS-style compatibility score contract that is not generalized to free discrimination. `build_linking_review()` is deferred under `GPCM` for the same reason. The underlying `audit_mfrm_anchors()` and `detect_anchor_drift()` helpers can still be called directly as exploratory support. ## Recommended substitutes When a restricted helper is needed for a `GPCM` report, the practical paths are: - Refit with `model = "PCM"` if the discrimination-free assumption is defensible for the data. The full APA / fair-average / parity stack becomes available, and `compare_mfrm()` quantifies the loss in fit. - Keep the report on the `GPCM` fit itself but draft the manuscript section around the package-native GPCM outputs: `summary(fit)` for parameters, `diagnose_mfrm()` for residual fit, `facet_quality_dashboard()` for the per-facet quality summary, `build_apa_outputs()` for caveated manuscript text, `build_visual_summaries()` / `run_qc_pipeline()` for caveated screening bundles, and `compute_information()` for precision evidence. - Generate the reproducibility manifest and replay script from the `GPCM` fit with `build_mfrm_manifest()` and `build_mfrm_replay_script()`, then keep the support caveat in the exported bundle. ## A worked example The `example_core` dataset includes a small synthetic block that supports a bounded `GPCM` fit: ```r library(mfrmr) toy <- load_mfrmr_data("example_core") fit_gpcm <- fit_mfrm( data = toy, person = "Person", facets = c("Rater", "Criterion"), step_facet = "Criterion", score = "Score", model = "GPCM", method = "MML" ) summary(fit_gpcm) diag_gpcm <- diagnose_mfrm(fit_gpcm) summary(diag_gpcm) info <- compute_information(fit_gpcm) plot_information(info) fair <- fair_average_table(fit_gpcm, diagnostics = diag_gpcm) fair$caveat plot_fair_average(fair, draw = FALSE) vis <- build_visual_summaries(fit_gpcm, diag_gpcm) vis$support_status qc <- run_qc_pipeline(fit_gpcm, diag_gpcm, include_bias = FALSE) qc$support_status apa <- build_apa_outputs(fit_gpcm, diag_gpcm) apa$support_status manifest <- build_mfrm_manifest(fit_gpcm, diagnostics = diag_gpcm) manifest$support_status replay <- build_mfrm_replay_script(fit_gpcm, diagnostics = diag_gpcm) replay$support_status tables <- build_summary_table_bundle(summary(fit_gpcm)) apa_table(tables, which = "overview") ``` The fit, summary, residual diagnostics, and information helpers all run under `GPCM`. `fair_average_table(fit_gpcm)`, `plot_fair_average()`, `build_visual_summaries()`, `run_qc_pipeline()`, and summary-table handoff from supported summaries also run and return explicit caveats where needed. `build_apa_outputs(fit_gpcm)`, `build_mfrm_manifest(fit_gpcm)`, and `build_mfrm_replay_script(fit_gpcm)` run as package-native outputs and record `supported_with_caveat` status. ## Roadmap The boundary above is a release-scope statement, not a permanent design choice. FACETS-compatibility score exports, linking reviews, posterior predictive checks, and full joint-uncertainty fair-average intervals for free-discrimination polytomous models remain future work. Until then, the matrix returned by `gpcm_capability_matrix()` is the binding contract.