This is a major release. The core engine is unchanged; v2.0.0 layers
a formalized decision/policy/action architecture on top of it and
replaces the old catch-all ctx argument with explicit typed
context objects.
DecisionPoint(): declares a named
checkpoint in the event timeline where a policy can propose an action.
Declared on the schema, not buried in transition logic. Supports
trigger (which event types fire it),
allowed_actions, action_handlers (per-action
state-change functions), an optional condition predicate,
and audit flag.ActionEvent: an action proposed by a
policy enters the normal event timeline and is realized by the same
transition() / stop() path as any other event.
Actions do not mutate state directly.TrajectoryRecord: logged at every
decision point firing. Records the time, decision point id, what state
the policy observed, what it proposed, what was realized, and state
before/after. Captures the full decision audit trail.trajectory_table(): convenience helper
to flatten a list of TrajectoryRecord objects into a tidy
data frame.load_model(): validated assembly
function. Accepts schema, bundle,
policy, trajectory, runtime, and
param_source; validates that all components are mutually
consistent and returns a configured Engine. This is now the
recommended entry point for models with policies or runtime config.ctxctx is removed as a first-class interface. Bundle
callbacks that declared ctx as a formal now receive a hard
error on engine construction. Replace with the following typed objects
(all optional in callback signatures):
SimContext: per-run metadata
(run_id, time_spec, model_id,
scenario_id, horizon).ParamContext: one parameter
realization (draw_id, params named list,
optional provenance). Constructed by
ParamContext().RuntimeContext: reproducibility and
backend settings (seed, replicate_id,
backend, n_workers). Constructed by
RuntimeContext().EnvironmentContext: external signals
for ABM/RL hooks (signals, step_fn,
reset_fn, info). Reserved for future use.sample_params(n) bundle hook: when
present, run_cohort() calls it to draw n
ParamContext objects and runs every entity under every
draw, fully crossing entities × parameter draws × stochastic
replicates.run_cohort() param_draws
argument: alternatively, pass a pre-built list of
ParamContext objects directly.batch$param_draws: drawn contexts are
returned alongside results for reproducibility.refresh_rules(entity, last_event, changes):
bundle hook controlling which processes re-propose after each event.
Returns "ALL" (default) or a character vector of
process_ids. entity is the full
post-transition state; changes is only the delta from the
last transition() call.derive() / derived variables: schema
variables can declare a f function of
(entity, j, t) computed on read rather than stored.
Supports time-aware lookups via snapshot_at_time().schema_validate() type-implied bounds:
default, min, and max values are now cross-checked against the range
implied by the declared type (e.g., nonnegative_integer
must have default ≥ 0; probability must be in [0, 1]).set_schema() gains time_spec and
decision_points arguments: assemble a complete
schema including clock spec and decision points in one call.ModelProvider / PackageProvider /
FileProvider / MLflowProvider:
unexported. Engine$new(provider=) removed.
Engine$new(bundle=) and load_model() are the
only Engine construction paths..Rd files to inline
roxygen2 comments. man/ and NAMESPACE are now
generated artifacts; do not edit by hand.Engine$new(bundle = ...) shortcut. New
bundle parameter to the Engine constructor
accepts a ModelBundle directly, bypassing the
ModelProvider machinery for in-memory / inline models.
Equivalent to writing your own one-method provider, but without the
boilerplate. The provider = ... path is unchanged and
remains the right choice for packaged or pluggable models. Supplying
both bundle and provider is an error.tutorials/01_core_engine_scaffold.Rmd)
updated to use Engine$new(bundle = toy_bundle) directly;
ModelProvider is now a forward-pointer aside rather than a
required first-encounter concept. Vignette title renamed to “Engine and
ModelBundle scaffold”.man/Engine.Rd updated with a Constructor section
documenting the two construction paths.id_string type (no deprecation
alias). Use nonempty_string or a custom
validate function for identifier columns; the supported
type list is now 14 entries.percent type: numeric in [0,
100], honors optional min / max
overrides.set_schema() rewrite with hybrid
vars syntax. Each vars entry is now either a
type-name string (e.g. "count") or a full list spec
(e.g. list(type = "positive_numeric", max = 20)); both
shapes can be mixed in one call. New overwrite = FALSE
argument errors on collision when extending an existing
schema (set overwrite = TRUE to replace). New
remove = argument drops named entries (errors if absent).
Removed the previous replace = and add =
arguments.min /
max or a custom validate function to
tighten.set_schema()
shape, the percent type, and the removal of
id_string.logical, binary,
integer, count,
nonnegative_integer, positive_integer,
numeric, nonnegative_numeric,
positive_numeric, probability,
categorical, ordinal, string,
nonempty_string, id_string.default and coerce fields are now optional in
schema specifications; fluxCore applies appropriate defaults (e.g.,
as.numeric for numeric types, NA_real_ for
numeric defaults).set_schema() helper: simplified
schema creation via named character vector of type mappings; reduces
boilerplate for common use cases..validate_schema() now handles automatic defaults; stricter
type checking and validation rules for new types.schema_spec.md with complete type reference; tutorial
examples showcase both manual and helper-function workflows.default_model_bundle() and
default_entity_schema() from runtime code.PackageProvider now requires explicit
registry input; no hidden fallback bundle is injected.new_entity()
wrapper and standardized on Entity$new(); wrapper
input-normalization behavior is now handled directly in
Entity$initialize().tests/testthat/helper_fixtures.R).refresh_rules() engine boundary validation:
"ALL" (scalar), or"ALL"), valid targeted refresh, and malformed return
structures.refresh_rules
behavior and strict return contract.time_spec runtime
contract introduced in 1.5.1 (single model declaration via
bundle$time_spec, no runtime override).bundle$time_spec; runtime context attempts to override
time metadata now error.time_unit wiring from cohort/engine run
APIs and aligned manual documentation with actual signatures.Finalized ecosystem harmonization for the 1.5.0 coordinated release.
Documentation quality pass: fixed check() example/codoc/Rd usage issues and completed missing manual Rd coverage for exported APIs.
run_cohort() hardening: unnamed entity lists are now auto-named for stable run indexing in examples and batch execution.
Licensing update: switched package license to LGPL-3.
flux_ prefixes from exported
time/schema helpers. New names are set_time_unit(),
time_spec(), time_to_model(),
time_from_model(), schema_validate(),
schema_assert_vars(), schema_var_info(),
schema_assert_types(), and
schema_assert_levels()..Rd pages were renamed/updated to
match the new helper names.var() to avoid masking
stats::var(). Use declare_variable()
instead.var() to
declare_variable() to avoid masking
stats::var() when attaching fluxCore.Entity$meta for bundle/runtime bookkeeping (e.g.,
refresh cadence clocks) without polluting the validated state
schema.fluxCore.time_to_model() now explicitly rejects
time-only inputs (e.g., difftime, hms).
Calendar inputs must be Date or POSIXct
(date+time).schema_validate(),
schema_assert_vars(), schema_var_info(),
schema_assert_types(),
schema_assert_levels().Fix: unit tests updated to use time_unit = ...
argument (avoid accidental partial match to
max_time).
Fix: add strict max_time validation to prevent
silent mis-specified calls.
Fix: test-time-spec.R string literals now use fixed
matching (no invalid escapes).
Add time-axis utilities for deterministic mapping between
calendar time (Date/POSIXct) and numeric model time:
time_spec(), time_to_model(),
time_from_model(), and
set_time_unit().
Change: time metadata is now stored under
ctx$time$unit / ctx$time$origin /
ctx$time$zone (replacing the older
ctx$time_unit field).
Notes: months and years are fixed
approximations (30.4375 and 365.25 days). origin is a
mapping reference, not model baseline.
derive(fn = "count", target = declare_variable(...)) now
uses snapshot_at_time() (was incorrectly calling
snapshot_at() with a time value).derive(fn = 'count', target = declare_variable(...)) now
counts non-missing values in-window (avoids counting schema-default init
placeholders such as NA).run_cohort(backend = 'cluster')
to reduce parallel-backend drift risk.batch.R (remove stray parenthesis)
affecting installation.id argument in
Entity$initialize() (package parse/collate error).Fix: run_cohort() run index ordering is now
entity_id -> param_draw_id -> sim_id (contractual
invariant).
Fix run-index ordering unit test to use a minimal bundle that always proposes a single no-op event (avoids Engine error when no proposals are available).
Set time_unit in the ordering test to avoid
warnings.
run_cohort() now guarantees that
runs[[i]] corresponds to index[i, ] (run_index
alignment invariant). This removes the need for downstream reordering
hacks and is critical for correct entity-level grouping.type and
levels (used by downstream summary code).No functional changes. Version bump to align with fluxForecast 1.0.2.
Clarified documentation around active_followup: it
is a regular state variable and does not automatically stop the
Engine.
run_cohort() context handling:
ctx may be a single list (recycled) or a per-parameter-draw
list-of-ctx (length = n_param_draws).print.flux_state() implemented to match the declared S3
method and remove the NAMESPACE warning.