--- title: "Adding designs and formats" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Adding designs and formats} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ## Add an engine through the registry `latin_rectangle()` is the worked example: its engine, declaration and tests were added after the generic registry infrastructure, without adding a branch to replay, schema, printing, layout or drawing dispatchers. 1. Write independent scientific tests first. Specify counts and labels from the requested inputs, not from the result's own summary. Check geometry, replications, model rank/efficiency where relevant, and corrupted fixtures. State the construction family, sampling limitations and a finite search budget. A fixed-seed snapshot alone is not scientific validation. 2. Add an exported `R/fct_.R` function. Validate types, counts, products, labels and options before allocating large data or calling `resolve_seed()`. Call `local_design_seed()` once the effective seed is known. Do not detach packages, print status, change options or call Shiny. Use classed conditions. 3. Return through `new_fieldhub_design()`, with `infoDesign$id_design` and its effective seed, common field-book keys and a complete named parameter list. Include choices that change output and supplied data needed for replay. 4. Add one declaration in `R/result_design_registry.R`: stable snake-case key, public engine name, required columns (or a pure column-resolver function), and optional title/layout/render handlers. A fixed-coordinate book with a `TREATMENT` column can use `field_book_layouts` and `draw_registered_layout`. Declare specialized handlers only if the generic contract does not fit. Never add metadata-directed `eval()` or dispatch to arbitrary saved names. 5. Regenerate Rd/NAMESPACE with `devtools::document()`. Add fixed-seed calls to `tests/testthat/helper-catalogue.R` and the result-class expectations. Test explicit/automatic seeds, errors without RNG leakage, replay, layouts, labels containing spaces/punctuation, locations and format round-trips. Review and accept only the new snapshots; existing outputs must stay fixed. The Latin rectangle test also checks the additive row/column/treatment model rank independently with `model.matrix()` and `qr()`. Its two-row case is saturated, so the help explicitly warns that residual variation cannot be estimated from that model. It is not advertised as a uniformly sampled Latin rectangle, an optimized design, or a balanced incomplete-block design. ## Expose the design in the app The scientific engine does not depend on the app. To add a page, supply these declarations/adapters; do not copy a server module: | File | Addition | |---|---| | `R/app_registry.R` | Label, navigation group, engine, module/spec key and a unique server order | | `R/app_design_specs.R` | Shared controls, upload shape, values and the existing classic/spatial workflow family | | `R/app_design_args.R` | Plain `design_args_(values, data)` mapping to public API arguments; use exact `[[` lookup and numeric normalization | | `R/app_classic_workflow_registry.R` or spatial equivalent | Output identifiers, layout choices, table/heatmap columns, simulation and export settings | The shared `mod_design_ui()` and `mod_design_server()` do not change. Tests must compare raw-control and uploaded-data paths against direct API calls, construct the UI without starting a server, and verify that every registry entry uses the generic module. Do not commit Shiny server or browser tests. Manually verify a real session, invalid-input recovery, simulation and downloads before release. Help topics are derived from the app registry; do not maintain a second list. ## Add an import/export format Add a reviewed entry to `fieldhub_format_registry()` in `R/io_design_formats.R`: extension, media type, positive format version, reader and/or writer. A missing reader means write-only. Public `design_formats()`, `read_design()` and `write_design()` dispatch from these declarations and need no new branches. Readers must return a complete recorded result that passes the common schema and known-engine validator. Parse data, never execute source. Writers receive a validated result and a temporary filename, not the user's final destination. Version incompatible format changes and define whether old versions are read, migrated or rejected. Do not call a bare CSV table lossless if labels, classes, parameters or RNG settings cannot be recovered from it. Add round-trip checks across every engine, malformed/truncated/unknown-version fixtures, path and overwrite guards, and assertions that imports do not consume randomness or reconstruct the experiment. Preserve existing destinations on serialization failure. Optional new-format dependencies belong in Suggests with an actionable dependency condition; no automatic installation. ## Review checklist Run the scoped tests first, then the complete plain-R suite and macOS goldens, full package check with vignettes, changed-line lint and unchanged core coverage gate. Use the release benchmark comparison when scientific/engine work changes. Update both NEWS files, reference validation, architecture guidance and examples. Check minimal-dependency installation so script users do not require Shiny. Record actual local and CI evidence separately; consult `RELEASING.md` before publishing or assigning a release tag.