Archiving a nomologR workflow with nomo_report()
Source:vignettes/reproducible-report.Rmd
reproducible-report.Rmdnomo_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:
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")
#> # A tibble: 8 × 3
#> stage status detail
#> <chr> <chr> <chr>
#> 1 screen completed Candidate items audited exactly as supplied; no data or…
#> 2 factors completed Factor-retention evidence computed; no factor count was…
#> 3 efa completed EFA fitted using explicit researcher factor-count decis…
#> 4 cfa completed Researcher-specified CFA estimated; the model was not r…
#> 5 reliability completed Reliability evidence computed from the retained CFA mod…
#> 6 validity completed Convergent/discriminant evidence computed; no valid/inv…
#> 7 invariance completed Requested invariance evidence computed; diagnostics did…
#> 8 network completed Theory-specified network evidence computed without a on…
nomo_table(run, "decisions")
#> # A tibble: 8 × 10
#> id stage scope observation reason options consequence decision rationale
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 sample_… desi… samp… 800 rows a… Sampl… Contin… Later CFA … "same_s… ""
#> 2 scale_d… desi… Agen… Scale `Age… Item … Review… Screening,… "ag1, a… ""
#> 3 scale_d… desi… Pers… Scale `Per… Item … Review… Screening,… "pe1, p… ""
#> 4 factor_… efa Agen… Parallel a… The E… Inspec… A 1-factor… "1" "Each sc…
#> 5 factor_… efa Pers… Parallel a… The E… Inspec… A 1-factor… "1" "Each sc…
#> 6 cfa_mod… cfa meas… EFA has co… CFA s… Inspec… The CFA wi… "Agency… "Prespec…
#> 7 measure… meas… meas… CFA conver… Invar… Choose… Proceeding… "procee… "Measure…
#> 8 workflo… work… pipe… All reques… The p… Inspec… No additio… "comple… ""
#> # ℹ 1 more variable: source <chr>Render a report
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)
#> [1] TRUEThe 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:
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:
nomo_apa_table(run$results$cfa, "loadings", number = 1)Table 1
Standardized Factor Loadings
| Item | Agency | Persistence |
|---|---|---|
| ag1 | 0.82 | |
| ag2 | 0.75 | |
| ag3 | 0.71 | |
| ag4 | 0.78 | |
| pe1 | 0.77 | |
| pe2 | 0.70 | |
| pe3 | 0.74 | |
| pe4 | 0.69 |
Note. Standardized loadings from a confirmatory factor analysis. Estimated with ML; N = 800. Blank cells are loadings fixed to zero by the model.
nomo_apa_table(run$results$cfa, "fit", number = 2)Table 2
Model Fit
| Model | χ² | df | p | CFI | TLI | RMSEA [90% CI] | SRMR |
|---|---|---|---|---|---|---|---|
| Measurement model | 18.52 | 19 | .488 | 1.000 | 1.000 | 0.000 [0.000, 0.030] | 0.015 |
Note. Estimated with ML; N = 800. CFI = comparative fit index; TLI = Tucker-Lewis index; RMSEA = root mean square error of approximation; SRMR = standardized root mean square residual. Fit indices are reported as evidence, not against fixed cutoffs.
nomo_apa_table(run$results$reliability, number = 3)Table 3
Reliability Estimates
| Construct | ω | α |
|---|---|---|
| Agency | .85 | .85 |
| Persistence | .82 | .82 |
Note. ω = coefficient omega; α = coefficient alpha. Coefficient alpha assumes equal loadings and is reported alongside omega for comparison with published work.
nomo_apa_table(run$results$validity, "convergent", number = 4)Table 4
Average Variance Extracted
| Construct | k | AVE |
|---|---|---|
| Agency | 4 | .59 |
| Persistence | 4 | .53 |
Note. k = number of indicators; AVE = average variance extracted (Fornell & Larcker, 1981), the average proportion of indicator variance the construct explains. The review reference is .50; a value below it prompts a look at the loadings and content coverage. AVE is convergent evidence and is not a reliability coefficient.
nomo_apa_table(run$results$validity, "discriminant", number = 5)Table 5
Construct Correlations and Heterotrait-Monotrait Ratios
| Constructs | r [95% CI] | HTMT2 | HTMT |
|---|---|---|---|
| Agency with Persistence | .46 [.39, .53] | 0.45 | 0.46 |
Note. r = latent correlation from the confirmatory factor analysis, with its 95% confidence interval; the upper limit shows how high the correlation plausibly is (Rönkkö & Cho, 2022). HTMT2 = heterotrait-monotrait ratio based on geometric means, suited to indicators with unequal loadings (Roemer et al., 2021). HTMT = heterotrait-monotrait ratio (Henseler et al., 2015). The review reference for the ratios is 0.85. A ratio below it adds evidence that the constructs are empirically distinct; it does not by itself establish discriminant validity.
nomo_apa_table(run$results$invariance, number = 6)Table 6
Measurement Invariance Across Groups
| Model | χ² | df | CFI | RMSEA | SRMR | ΔCFI | ΔRMSEA | Δχ² (Δdf) | p |
|---|---|---|---|---|---|---|---|---|---|
| Configural | 32.75 | 38 | 1.000 | 0.000 | 0.017 | — | — | — | — |
| Metric | 41.15 | 44 | 1.000 | 0.000 | 0.027 | .000 | 0.000 | 8.40 (6) | .210 |
| Scalar | 106.08 | 50 | .977 | 0.053 | 0.044 | -.023 | 0.053 | 64.92 (6) | < .001 |
Note. Grouping variable: group. Each model adds constraints to the one above it; changes are relative to the preceding model. Changes in fit are reported as evidence and are not compared with fixed cutoffs.
nomo_apa_table(run$results$network, number = 7)Table 7
Theory-Specified Relations
| Hypothesis | Prediction | Estimate [95% CI] | Evidence |
|---|---|---|---|
| H1: Agency -> Persistence | positive | 0.46 [0.39, 0.53] | Concordant |
| H2: Agency -> Performance | positive | 0.39 [0.32, 0.45] | Concordant |
Note. Estimates are on the standardized scale. Evidence describes how each estimate relates to the prediction registered for it; it is evidence about the prediction, not a verdict on the measure.
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:
- researcher inputs and data/sample roles;
- item audit;
- factor-retention evidence;
- EFA;
- CFA;
- reliability;
- convergent/discriminant evidence;
- invariance, if requested;
- nomological-network evidence, if requested;
- workflow decisions and outstanding decisions;
- deviations and post-hoc decisions;
- methods and citations: the methods this workflow actually used, each with its lineage and role, a reference list for those methods, and software citations;
- 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 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:
paused_run <- nomo_run(
data = nomo_demo_network,
scales = scales,
settings = list(factors = list(seed = 2026))
)
nomo_table(paused_run, "stages")
#> # A tibble: 8 × 3
#> stage status detail
#> <chr> <chr> <chr>
#> 1 screen completed "Candidate items audited exactly as supplied; n…
#> 2 factors completed "Factor-retention evidence computed; no factor …
#> 3 efa awaiting_decision "Explicit researcher factor-count decisions are…
#> 4 cfa not_started ""
#> 5 reliability not_started ""
#> 6 validity not_started ""
#> 7 invariance not_started ""
#> 8 network not_started ""
paused_file <- nomo_report(
paused_run,
file = file.path(report_dir, "paused-workflow-audit.html"),
include_plots = FALSE
)
file.exists(paused_file)
#> [1] TRUEMissing 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:
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:
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
# <report_dir> so that the message reads the same on every computer.
cat(gsub(dirname(report_file), "<report_dir>", refusal, fixed = TRUE))
#> Report file already exists: <report_dir>/construct-validation-report.html. Use `overwrite = TRUE` to replace it.The existing report is left as it was. As elsewhere in
nomologR, consequential or destructive behavior is not
silently assumed.