Classify a functional strategy's reproducibility tier
Source:R/strategy-preflight.R
ledgr_strategy_preflight.Rdledgr_strategy_preflight() statically inspects a function(ctx, params)
strategy before execution. It classifies the strategy into ledgr's
reproducibility tiers:
Value
A ledgr_strategy_preflight object with fields tier, allowed,
reason, unresolved_symbols, package_dependencies,
qualified_package_dependencies, attached_package_dependencies,
worker_dependencies, ambient_rng_symbols, and notes.
Details
tier_1: self-contained strategy logic using only explicitparams, base/recommended R references, and ledgr's exported public namespace.tier_2: inspectable strategy logic that also uses package-qualified calls outside the active R distribution, such aspkg::fn(), or resolved immutable non-function closure objects that ledgr does not store as standalone replayable artifacts.tier_3: strategy logic with unresolved free symbols, user helpers, forbidden nondeterministic calls, or global assignment that ledgr cannot recover from stored run metadata.
The preflight is static analysis, not proof of semantic reproducibility. Dynamic dispatch, mutable captured environments, and dynamically constructed code remain user responsibilities.
Tier 3 strategies fail before execution with condition classes
ledgr_strategy_tier3 and ledgr_strategy_preflight_error; there is no
force = TRUE override on ledgr_run() or ledgr_sweep(). Covered
forbidden calls include direct wall-clock/process-environment calls such as
Sys.time(), Sys.Date(), and Sys.getenv(), visible indirection such as
do.call("Sys.time", list()), dynamic lookup/evaluation helpers such as
get(), eval(), and assign(), global assignment with <<-, and visible
context mutation such as attr(ctx, "secret") <- 1.
Ambient strategy RNG calls such as runif(1) are Tier 2 under the execution
seed contract for ordinary sequential runs, but they are not certified for
resume or parallel equivalence. Strategies that need pulse-specific
stochastic inputs in those paths should derive them from ctx$pulse_seed
without reading ambient .Random.seed. Custom indicator generation has a
stricter deterministic feature contract; do not infer indicator RNG policy
from strategy preflight.
Articles
Reproducibility model:
vignette("reproducibility", package = "ledgr")
system.file("doc", "reproducibility.html", package = "ledgr")