--- title: "Archiving a nomologR workflow with nomo_report()" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Archiving a nomologR workflow with nomo_report()} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} library(nomologR) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", message = FALSE, warning = FALSE ) # Rendering an HTML report requires pandoc. Chunks that render reports are # skipped, with this explanation, when pandoc is unavailable. pandoc_ok <- rmarkdown::pandoc_available() report_dir <- tempfile("nomologR-reports-") dir.create(report_dir) ``` `nomo_report()` is the final presentation and provenance layer in the `nomologR` workflow. It does **not** rerun the analyses. It renders the evidence and researcher decisions already stored in a `nomo_run` object. ## A workflow to archive This example uses `nomo_demo_network` and supplies every consequential decision up front, as a researcher following a preregistered plan might: ```{r run} scales <- list( Agency = c("ag1", "ag2", "ag3", "ag4"), Persistence = c("pe1", "pe2", "pe3", "pe4") ) h <- nomo_hypotheses( "Agency -> Persistence" = positive(min = .20), "Agency -> Performance" = positive() ) run <- nomo_run( data = nomo_demo_network, scales = scales, mode = "research", decisions = list( factor_count = list( value = c(Agency = 1, Persistence = 1), rationale = "Each scale was written to measure one construct." ), cfa_model = list( value = nomo_model(scales), rationale = "Prespecified two-construct measurement model." ), measurement_model = list( value = "proceed", rationale = "Measurement evidence reviewed before planned downstream tests." ) ), settings = list( factors = list(seed = 2026), invariance = list(group = "group", levels = c("configural", "metric", "scalar")), network = list(hypotheses = h) ) ) nomo_table(run, "stages") nomo_table(run, "decisions") ``` ## Render a report ```{r render, eval = pandoc_ok} report_file <- nomo_report( run, file = file.path(report_dir, "construct-validation-report.html"), title = "Construct validation audit: Agency and Persistence" ) file.exists(report_file) ``` The HTML file is self-contained, so it can be archived, attached to a project record or thesis appendix, or shared with a collaborator without a separate figures directory or a network dependency. The `title` argument becomes the document title. For a thesis committee or a collaborator who works in Word, give the file a `.docx` extension instead: ```r nomo_report(run, file = "construct-validation-report.docx") ``` The Word document carries the same tables, figures, and interpretation contract as the HTML report. Sections that collapse in HTML, such as the full evidence trace, are shown expanded, and it uses Word's default styles. `nomo_report()` works the same from the console, a script, or a chunk inside your own R Markdown or Quarto document, such as a thesis chapter. This article renders reports from its own chunks and needs no special setup. Rendering a report from inside another document nests two renders that share knitr's state, so `nomo_report()` isolates them: the report is rendered with knitr's default chunk options, which its template then sets for itself, and your document's options are restored afterwards. Your chunk options therefore do not change the report, and rendering the report does not change your document. ## Tables for a manuscript A report archives a workflow. A thesis or manuscript needs tables. `nomo_apa_table()` formats the evidence in a result as a table in APA 7 style — a bold number, an italic title, no vertical rules, and notes below — which knits directly into an R Markdown or Quarto document: ```{r apa-loadings} nomo_apa_table(run$results$cfa, "loadings", number = 1) ``` ```{r apa-fit} nomo_apa_table(run$results$cfa, "fit", number = 2) ``` ```{r apa-reliability} nomo_apa_table(run$results$reliability, number = 3) ``` ```{r apa-convergent} nomo_apa_table(run$results$validity, "convergent", number = 4) ``` ```{r apa-discriminant} nomo_apa_table(run$results$validity, "discriminant", number = 5) ``` ```{r apa-invariance} nomo_apa_table(run$results$invariance, number = 6) ``` ```{r apa-hypotheses} nomo_apa_table(run$results$network, number = 7) ``` Notice the leading zeros. APA 7 drops the zero before a decimal point only for a statistic that *cannot* exceed 1, so the rule follows the statistic rather than the value it happens to take. Reliability coefficients, correlations, CFI, and *p* values lose it; TLI, RMSEA, SRMR, and standardized loadings keep it, because each can exceed 1 — TLI is not bounded above, and a standardized loading does in an improper solution. Many published tables print standardized loadings without the zero; these tables follow the rule as written. The notes keep the package's reference-value language. Fit indices are reported as evidence rather than against fixed cutoffs, and the hypotheses table describes how each estimate relates to its prediction without calling any of them a pass or a fail. A hypothesis specified after the data were seen is marked with a note saying it is exploratory. The discriminant table is not the familiar matrix of correlations with the square root of AVE on its diagonal. That Fornell-Larcker comparison often misses constructs that are not distinct (Henseler et al., 2015). Instead, each pair of constructs gets one row: its latent correlation with a confidence interval, whose upper limit shows how high the correlation plausibly is (Rönkkö & Cho, 2022), beside the heterotrait-monotrait ratios HTMT2 and HTMT. AVE is convergent evidence, so it has a table of its own. To collect them in one place, `nomo_report(run, apa_tables = TRUE)` appends a *Manuscript tables* appendix. It holds the tables for every result the run has, numbered in the order the report presents them. A table that does not apply, such as the construct pairs of a one-construct model, is left out. ## What the report contains The report mirrors the full guided workflow: 1. researcher inputs and data/sample roles; 2. item audit; 3. factor-retention evidence; 4. EFA; 5. CFA; 6. reliability; 7. convergent/discriminant evidence; 8. invariance, if requested; 9. nomological-network evidence, if requested; 10. workflow decisions and outstanding decisions; 11. deviations and post-hoc decisions; 12. methods and citations: the methods this workflow actually used, each with its lineage and role, a reference list for those methods, and software citations; 13. reproducibility information and session details. The methods table is built from `nomo_methods(run)`, which returns only the methods the run used; a method the package offers but the workflow did not use is not cited. The [research basis](research-basis.html) article explains the lineage labels. A final evidence-trace appendix keeps each autogenerated recommendation on the same row as the component, metric, reference, severity, and observation that produced it. ## Reports from incomplete workflows A report can also be rendered from a paused or blocked workflow: ```{r paused} paused_run <- nomo_run( data = nomo_demo_network, scales = scales, settings = list(factors = list(seed = 2026)) ) nomo_table(paused_run, "stages") ``` ```{r paused-report, eval = pandoc_ok} paused_file <- nomo_report( paused_run, file = file.path(report_dir, "paused-workflow-audit.html"), include_plots = FALSE ) file.exists(paused_file) ``` Missing stages are labeled as incomplete or not requested rather than silently disappearing. This is useful when a researcher wants to archive why an analysis stopped or which consequential decision remained unresolved. ## Plots and session information The default includes a compact, nonredundant set of plots and full `sessionInfo()` output. Both can be turned off, as in the paused report above: ```r nomo_report( run, file = "compact-report.html", include_plots = FALSE, include_session = FALSE ) ``` ## Overwriting is explicit Existing reports are protected. Rendering to a file that already exists stops with an error unless `overwrite = TRUE` is supplied. Here the error is caught so that its message can be shown: ```{r overwrite, eval = pandoc_ok} refusal <- tryCatch( nomo_report(run, file = report_file), error = function(e) conditionMessage(e) ) # This article writes its reports to a temporary directory, shown here as # so that the message reads the same on every computer. cat(gsub(dirname(report_file), "", refusal, fixed = TRUE)) ``` The existing report is left as it was. As elsewhere in `nomologR`, consequential or destructive behavior is not silently assumed. ```{r cleanup, include=FALSE} unlink(report_dir, recursive = TRUE) ```