plot_rri_properties() now defaults to a separate-axis dot profile. No
average of Capacity, Connectivity, Kinetics and Memory is calculated.
type = "radar" retains an explicit radar option, without the centre mean.
Groups use facets; missing descriptors are labelled. Invalid scores are
rejected instead of clipped. Existing positional arguments are preserved.plot_rri_recovery_landscape() defaults to raw within-column magnitude and
keeps all-missing columns. Headers report finite-value counts. Missing cells
stay missing even in constant columns. I_norm is labelled absolute final
displacement. Derived labels say "not flagged", not "returned"; they do not
establish equivalence to baseline. Explicitly omitted columns are captioned.plot_rri_recovery_map() aligns keyed scores, checks group-time uniqueness,
uses observed sampling intervals for tile width, marks missing scores and
reports the displayed group count. Event boundaries use exact supplied times;
no coloured overlay distorts the quantitative score fill. Ambiguous recovery
annotations are rejected instead of choosing a purported severity class.plot_rri_accuracy() distinguishes descriptive cluster-mean agreement limits
from row-level limits and confidence intervals. Bootstrap labels state their
conditioning and no longer assert that row intervals must be narrower.
Calibration axes share units and full data ranges; zero-MSE percentage shares
are identified as undefined.plot_rri_properties() no longer places the composite RRI on a fifth spoke.
RRI is built from the plant, soil and microbial domains; Capacity,
Connectivity, Kinetics and Memory are property descriptors built from
different inputs. Drawing them on one radar invited the polygon to be read as
averaging across incommensurable quantities.
The chart now has four axes. The centre shows the mean of the resolved property axes, with the count of resolved axes beneath it, so a mean resting on two axes is not mistaken for one resting on four. An axis whose supporting measurement was absent is excluded from the mean rather than counted as zero. The composite is reported in the subtitle for reference.
simulate_redox_holobiont() now defaults to seed = NULL rather than
seed = 123, so no function in the package touches the random stream unless
a seed is requested. This is what the CRAN Cookbook recommends, and the
earlier justification for keeping a fixed default did not survive checking:
every call in the package's own examples, tests and vignettes passes a seed
explicitly, so nothing depended on it. Users who called the simulator with no
arguments and relied on reproducible output should now pass seed themselves.benchmark_hrri() now restores the RNG kind as well as .Random.seed, so
all three functions that seed behave identically. It could not previously
change the kind, so no behaviour depended on this, but the uniformity makes
the guarantee checkable at a glance rather than function by function.
tests/testthat/test-pipeline-partial.R collected warnings by
superassignment. It now accumulates them in an environment, so a search for
<<- across the package sources and tests returns nothing at all.
inst/scripts/check_model_accuracy.R wrote its figures to a directory
created under the working directory. It now writes to tempdir() unless the
HRRI_OUT environment variable names somewhere else, and prints the
destination. Nothing shipped with the package writes outside the temporary
directory unless asked to.
benchmark_hrri() no longer uses <<-. The assignment resolved to the
function's own frame rather than to .GlobalEnv, so it was not a policy
violation, but confirming that required reading the surrounding code. The
tryCatch() handler now returns the failure as a classed value and the
caller records it. Behaviour is unchanged; the package now contains no <<-.
The only remaining references to .GlobalEnv are the blocks that save and
restore .Random.seed. .Random.seed lives in .GlobalEnv, so any function
that seeds necessarily writes there; these blocks put it back exactly as
found, including on an error exit.
tests/testthat/test-api-surface.R required a \value section on every Rd
topic. That is wrong for a narrative page: HRRI_workflow_example has no
\usage and returns nothing, so the test failed on a correctly written
topic. \value is now required only of function topics, which is the rule
R CMD check itself applies.unzip -o overwrites files but never deletes them. Release 1.0.0 renamed
R/data-redoxrri_example.R to R/HRRI_workflow_example.R, so a tree updated
by extracting over the old one keeps both, and both .Rd files claim
\alias{redoxrri_example}. Duplicate aliases make R CMD INSTALL fail, and
pkgdown::build_site() then renders vignettes against whatever older copy of
the package is already installed, producing a confusing "could not find
function" for a function that is plainly present in the sources.
sync_package.sh, distributed alongside the release, compares a tree against
package_manifest.txt and reports or removes the leftovers.
rri_o2_demand() no longer fails obscurely when every reduced-species column
the caller names is absent from soil_df. The numeric coercion ran before
the validity check, and with no matching columns it attempted a zero-column
replacement, so [<-.data.frame raised a cryptic error instead of the
informative "none of the specified reduced-species columns were found"
message a few lines below. The coercion is now guarded.rri_o2_demand() cited "Ghotbi et al. (2026)" in its details and example
while the reference entry carries no year, the mechanistic review being
unpublished. The in-text citations now read "submitted", matching the
reference.First release candidate. No change to any calculation; this release completes the packaging, documentation and infrastructure.
_pkgdown.yml rebuilt from the actual Rd topics and grouped by task rather
than alphabetically: scoring pipelines, the four hidden states, recovery
signatures, model checking, figures, simulation. All 36 topics are listed
exactly once, which is what the previous index failed at when
rri_accuracy(), plot_rri_accuracy() and rri_domain_influence() were
added without entries and the site build stopped.
GitHub Actions workflows for R CMD check (five platform and version
combinations, run with --as-cran --run-donttest) and for the pkgdown site.
Vignettes are built in CI, so a repeat of the ggtern incompatibility that
once broke vignette building would surface before release.
cran-comments.md, .gitignore, and a .Rbuildignore that keeps all of
the above out of the source tarball.
tests/testthat/test-api-surface.R checks the public interface itself:
every export resolves, S3 methods are registered rather than merely defined,
argument names of the entry points are pinned, every topic has a value and a
runnable example, no example is hidden behind \dontrun, and seeding leaves
the caller's .Random.seed exactly as found. These guard the failure modes
that R CMD check cannot see.
simulate_redox_holobiont() keeps seed = 123 rather than NULL, so that
an unseeded call to an illustrative generator is reproducible. The @param
entry now says so, and explains why it is safe: the RNG kind and
.Random.seed are saved on entry and restored on exit, so the caller's
stream is untouched. The diagnostic functions default to seed = NULL.
The topic redoxrri_example is renamed HRRI_workflow_example. Its former
name implied a dataset, but the package ships no data/ directory and
data(redoxrri_example) would have failed; the page now states plainly that
it is a worked example rather than an object. The old name is kept as an
alias, so existing links still resolve.
Remaining references to the package's former name, "RedoxRRI", replaced with "HRRI" throughout the help pages.
inst/CITATION now matches the current software manuscript: four authors and
the title "HRRI: direction-aware diagnostics for soil-plant-microbiome redox
recovery across hydroclimatic disturbances", consistent with README and the
vignettes.
Manuscript statuses corrected throughout. The mechanistic review is submitted
to Soil Biology & Biochemistry, and the theory paper to Communications Earth
& Environment; the software paper remains in preparation. Applied in README,
the workflow vignette, inst/CITATION and the rri_o2_demand() help page,
which cites the review for its stoichiometric table.
inst/CITATION had the software paper as "Manuscript submitted" while README
and the vignette said "in preparation". Aligned to in preparation, matching
the wording confirmed for README. A single line in inst/CITATION reverses
this if the paper has in fact been submitted.
Added .Rbuildignore, clearing both remaining R CMD check NOTEs:
.github under "checking for hidden files and directories", and
LICENSE.md and _pkgdown.yml under "checking top-level files". These are
development and website files that belong in the repository but not in a
source tarball.
Each directory is listed in two forms, ^docs$ and ^docs/. A pattern
anchored with a trailing $ matches the directory entry but not the files
inside it, which is why an earlier ^\.github$ left the hidden-files NOTE
in place. The patterns were checked against a list of representative paths
before release: every development file is excluded and all fourteen sampled
package files survive.
inst/CITATION, README and the workflow vignette.inst/CITATION still lists the package manuscript under its earlier title
with five authors including Marco Guerreiro, while README and the workflow
vignette follow the current draft: four authors, and the title "HRRI:
direction-aware diagnostics for soil-plant-microbiome redox recovery across
hydroclimatic disturbances". The author list is not something to change by
inference, so both forms are left in place until confirmed. The review
manuscript's status is likewise recorded as in preparation because it has not
been confirmed.The interpretation section was headed "the 25-fold contrast" while its own text, and the example, said 26. The worked example is 33.75 mmol O2 per kg against a 1.3 mmol per kg stock, a ratio of 25.96, so 26 is right and the heading was wrong.
@return did not describe what the function returns. Five elements were
undocumented (n_species_observed, species_coverage, interpretation,
ch4_unit_used, acetate_basis_used), and three columns of components
were listed under names the code does not use: mean_inventory is really
mean_inventory_mmol, fraction_of_total_demand is really
fraction_total_demand, and n_observed was missing. stoich_table was
described as "the full stoichiometric table" when it holds only the species
actually found. All eleven returned elements are now documented under their
real names. R CMD check cannot detect this class of error.
The reference to the mechanistic review was updated to the current draft: four authors, and "disturbances" rather than "disturbance".
Verified DOIs added to the two rate-law references, Stumm and Lee (1961) doi:10.1021/ie50614a030 and Millero, Sotolongo and Izaguirre (1987) doi:10.1016/0016-7037(87)90093-7.
The stoichiometry was checked against the electron balance rather than taken on trust. All eight coefficients are correct at 4 electrons per O2: Fe(II) 1 e- (0.25), Mn(II) 2 e- (0.50), HS- 8 e- (2.00), FeS 9 e- (2.25), FeS2 15 e- (3.75), NH4+ 8 e- (2.00), CH4 8 e- (2.00), acetate 8 e- (2.00) and 1.00 on a carbon basis. The pyrite equation balances on Fe, S, O and H, and releases the 4 mol H+ per mol FeS2 the text claims.
Every documented function now carries an explicit @title. Twenty-nine
roxygen blocks had been relying on the implicit first-line title; six S3
methods documented with @rdname or @describeIn correctly do not have one,
since they inherit the parent topic's title and a second @title would
conflict.
DESCRIPTION cites six published methods references in the form CRAN asks
for, authors (year) <doi:...> with no space after doi:. Every DOI was
resolved against Crossref before being added; none is a placeholder.
The three companion manuscripts are described in README, the workflow
vignette and inst/CITATION, each marked in preparation, with a note that
entries are provisional until publication. They are deliberately absent from
DESCRIPTION: CRAN asks that field to carry only references a reader can
retrieve, so unpublished work belongs in these files instead.
README gained a table mapping each published reference to the specific part of HRRI that rests on it, so a reader can see why each is cited rather than taking the list on trust.
rri_accuracy() no longer modifies the user's global environment.
set.seed() writes .Random.seed into .GlobalEnv, so calling it without
restoring the previous state silently resets a random stream the caller may
have been relying on. The RNG kind and seed are now saved on entry and put
back with on.exit(), matching the pattern simulate_redox_holobiont() and
benchmark_hrri() have always used. This was the only place in the package
that seeded without restoring.Audited against the CRAN Cookbook "Code Issues" chapter. Clean on every
recipe: no T/F for TRUE/FALSE; every set.seed() is behind a
user-supplied argument defaulting to NULL; all cat()/print() calls sit
inside print/summary methods or behind a verbose/print argument;
par() is saved with no.readonly = TRUE and restored via on.exit();
nothing writes to the home filespace or the working directory; no
tempfile() detritus, no installed.packages(), no options(warn = -1),
no parallelism, no software installation from package code.
Both vignettes now restore the ggplot2 theme they set. theme_set() changes
state that persists for the rest of the session; vignettes build in their own
process so nothing outside was affected, but it is the same courtesy CRAN
asks for with par() and options().
All \dontrun{} example wrappers replaced with \donttest{}. \dontrun
is for code that cannot run -- code needing credentials, external
software or hardware. None of these examples was in that category, and the
wrapper meant R CMD check never executed them, so they could drift out of
step with the code without anyone noticing. They are now run under
R CMD check --run-donttest and by CRAN.
The plot_RRI_ternary() example is additionally guarded on the ggplot2
version. Unguarded it would error under ggplot2 >= 4.0.0, where ggtern
cannot be used; it now skips instead.
DESCRIPTION cites the methodological reference and the two sources for the
agreement statistics, as CRAN policy asks. The framework citation is a
repository URL until the manuscript has a DOI, at which point it should be
replaced with <doi:...>.
Vignette building failed with
Error in `plot_theme()`:
! The `tern.axis.ticks.length.major` theme element must be a <rel> object.
The cause is ggtern, not the figure that happened to trigger it. ggtern
patches ggplot2's internal element tree when its namespace is loaded, not
when a ternary plot is drawn. Under ggplot2 >= 4.0.0, which rewrote the plot
object on S7, that patch leaves elements in a form ggplot2 rejects, and every
subsequent ggplot in the session fails in plot_theme().
The previous guard called requireNamespace("ggtern") and wrapped the plot
in try(). That is too late: requireNamespace() loads the namespace, which
is the damage, and try() only catches the ternary plot's own failure. Since
R CMD build builds vignettes in one R session, the gallery vignette's probe
brought down the workflow vignette that followed it.
The ggplot2 version is now checked before ggtern is touched, in a new
internal helper hrri_ggtern_ok(), which never calls
requireNamespace("ggtern") on an incompatible ggplot2. Applied in
plot_RRI_ternary(), the gallery vignette, the redoxrri_example example
and tests/testthat/test-plot_rri_ternary.R -- the test had the same defect,
because skip_if_not_installed() also loads the namespace and would have
poisoned every later test file.
Where ggtern cannot be used the ternary panel is skipped with an explanation, and the same composition is reported numerically, as before.
rri_accuracy() assesses how closely a score tracks a reference target using
statistics appropriate to repeated observations of the same units. A pooled
row-wise correlation over a longitudinal panel is not a valid precision
claim: 480 rows that are 12 trajectories sampled 40 times carry far less
information than 480 independent observations. The function reports the
intra-class correlation, the design effect 1 + (m - 1) * ICC, and the
effective sample size, and obtains intervals by resampling whole
trajectories. It also reports the naive row-resampled interval alongside, so
the cost of ignoring the clustering is shown rather than asserted.
Agreement is reported as Lin's concordance correlation coefficient next to
Pearson's r. The two differ whenever the score is miscalibrated: a score
equal to twice the target plus a constant has r = 1 and concordance near
0.3. Calibration intercept and slope are given so the direction of the
miscalibration is visible. Mean squared error is partitioned into squared
bias, variance mismatch and lack of correlation (Kobayashi and Salam 2000);
the three components sum to MSE exactly, and the residual is returned as an
attribute so a future regression in the arithmetic would be caught.
The permutation null exchanges whole trajectories rather than rows, so each unit keeps its temporal shape. Permuting rows would destroy the shared event-driven signal and make almost any score appear significant.
plot_rri_accuracy() draws the assessment as a four-panel figure:
calibration against the 1:1 line, a Bland-Altman agreement plot with limits
computed from cluster means, the row-resampled and trajectory-resampled
bootstrap distributions side by side, and the exact error partition. Panels
are selectable, and the figure degrades to a list of plots rather than
failing when patchwork is absent.
man/rri_domain_influence.Rd was missing from the 0.99.3 tarball: the
function was exported and had a complete roxygen block, but no Rd file was
generated, which is an "undocumented code objects" warning under
R CMD check. Added.vignettes/HRRI.R, an orphaned knitr output with no corresponding
.Rmd, which R CMD check flags as a file in vignettes/ that builds no
vignette.latent_truth; it now reports
cluster-aware agreement, shows the figure, and states plainly that a target
and a score sharing a generator establish internal consistency of the
estimator and not empirical validation.rri_domain_influence() reports the realised contribution of each domain to
the composite, as an exact variance decomposition
(phi_d = w_d Cov(S_d, R) / Var(R), summing to one). Declared weights and
realised influence diverge whenever domain scores differ in dispersion,
covary with one another, or are missing for some rows; this function makes
that visible instead of leaving it to be inferred from a figure.plot_rri_properties() no longer draws a literal "NA" label at the tip of an
unavailable axis. The label was placed at the same radius as the axis name and
overlapped it, rendering "Capacity" as "CNAacity". Unavailable axes now show
the short spoke only.plot_rri_properties() dropped two spurious warnings: an invalid
label.size argument passed to annotate(), and a removed-rows warning from
plotting an NA vertex.rri_property_scores() now reports which input is missing when a property is
unavailable. Capacity requires soil_df; omitting it is the usual reason
Capacity returns NA. The worked example shows both the complete and the
partial call.R/plot_rri_recovery_landscape.R used a literal em dash inside a string,
which is non-ASCII in executable code. Replaced with \u2014; the rendered
glyph is unchanged.rri_recovery_metrics() gains a section explaining why k_recovery and
t_half are frequently NA. The rate fit requires at least min_pts
recovery observations that fall after the trough, below baseline, and before
the first baseline crossing; short windows routinely leave fewer. The
worked example now uses a 40-day record with a 10-day event so the fit
succeeds, and contrasts it with a short window where the rate is correctly
withheld.M) is now a holobiont state rather than a mineralogical one. It
accumulates from hydrological event load, the Fe-crystallinity ratchet,
persistent plant acclimation (aerenchyma displacement), and microbial
community displacement. Component weights sum to the previous total (0.060),
so overall accumulation rate is unchanged while its causes are distributed
across the three domains.micro_legacy as a simulator state: it accrues under sustained
reduction and relaxes more slowly under oxic recovery, giving the microbial
component an asymmetric (hysteretic) legacy.latent_state now returns micro_legacy and plant_legacy so the memory
decomposition is auditable.latent_truth. All figures, benchmarks and any stored
simulation outputs must be regenerated.attach_hrri_ids(): joins design identifiers onto a score table using a
unique row_id or a complete observation key, falling back to row order only
with an explicit warning. Records the method used in the id_alignment
attribute.@importFrom declarations for all external calls and a worked @examples
block. Regenerated NAMESPACE and all help pages.R CMD check and pkgdown
deployment.test-property-scores.R and corrected two test
expectations that compared per-row domain_coverage and n_domains columns
against scalars.hrri_infer_architecture() as a conditional recovery-curve fit.
Its fitted amplitude and rate are no longer described as mechanistic
accessibility and reservoir exchange kinetics.rri_pipeline() now forwards domain weights and accepts partial soil,
plant or microbial panels.rri_memory_index().