Rules & actions
Rules are the endogenous decision channel: a Rule pairs a state-contingent guard with an ordered action program, so decisions (raise capital, acquire an asset, kill a program) live in the model rather than in host patch code. Actions are a closed, serializable family (ActionStmt subtypes) applied by apply_action!; the engine fires enabled rules each step via fire_rules!.
ReactiveDynamics.Rule — Type
Rule(id, guard, action; fire_mode = :every_tick, enabled = true)The endogenous decision channel (ADR 0010 §A, CONTRACT §12) — a (guard, action, fire_mode) triple evaluated once per tick at a fixed point in _step! (step 10, via fire_rules!). guard is an Expr/literal resolving to a Bool (fire once when true) or a numeric v (fire rand(rng, Poisson(v)) times, so the RNG-threaded rate stays deterministic); action is any ActionStmt. fire_mode ∈ {:every_tick, :once} — an :once rule latches its enabled flag off after it first fires. enabled is run-state reset by _reinit! (§4 D7). Unlike a transition's stateless per-tick guard, a Rule has no bound token, so its action must be one of the population/global verbs (SetTokens, not SetField).
ReactiveDynamics.ActionStmt — Type
Abstract supertype of the closed, serializable action whitelist (ADR 0010 §C / ADR 0011, CONTRACT §12). The concrete family is {SetSpecies, SetParams, SetField, SetTokens, AddToken, Activate, Deactivate, Invoke, Log, Seq} (plus the internal RawExpr legacy bridge). An ActionStmt is a declarative, eval-free record of a state mutation; apply_action! dispatches on the concrete type to perform it, and the closed set is the trust boundary for eval-free (de)serialization. Actions are the payload of a Rule (the endogenous decision channel) or a transition post-action; Seq composes them.
ReactiveDynamics.SetSpecies — Type
SetSpecies(name, value, mode = :set)Action (ActionStmt) that writes a plain-species pool column of state.u: for species name, evaluate value (an Expr/literal, through the seeded closure path) and either set it (mode = :set) or increment it (mode = :inc).
ReactiveDynamics.SetParams — Type
SetParams(assigns)Action (ActionStmt) that writes one or more model parameters in state.p. assigns is a vector of name => value-expr pairs; each value is evaluated through the seeded closure path.
ReactiveDynamics.SetField — Type
SetField(field, value)Action (ActionStmt) that writes field on the FIRING transition instance's bound token(s) (ADR 0008 §D), evaluating value in the firing context. This is a transition post-action ONLY — a standalone Rule has no bound token, so apply_action! errors on it; use SetTokens for a Rule (validated at build).
ReactiveDynamics.SetTokens — Type
SetTokens(predicate, assigns)Action (ActionStmt) that writes assigns (field => value-expr pairs) over the token population selected by predicate — the population generalization of SetField (ADR 0011 §A). Because it carries its own predicate it is legal in a Rule. Matched tokens are iterated in the (species, creation_index) total order (§9.2), and each value is evaluated IN THE SELECTED TOKEN's context (so @field(name) reads that token's own current attribute). predicate is a TokenPredicate (ADR 0008); a (kind, clauses) tuple form is also accepted.
ReactiveDynamics.AddToken — Type
AddToken(kind, fields)Action (ActionStmt) that creates a structured token of a registry-registered kind (ADR 0006 §C) — the acquisition lever. fields is a vector of name => value-expr pairs; the values are evaluated, passed to the kind's registered constructor, and the new token is entangled into the network's structured container.
ReactiveDynamics.Activate — Type
Activate(transition)Action (ActionStmt) that soft-activates a transition line (ADR 0004 soft gate) by setting its latching transActivated flag true. transition is matched by transName/transHash. Lowers to activate!.
ReactiveDynamics.Deactivate — Type
Deactivate(transition)Action (ActionStmt) that soft-deactivates a transition line (ADR 0004 soft gate) by clearing its latching transActivated flag. transition is matched by transName/transHash. Lowers to deactivate!.
ReactiveDynamics.Invoke — Type
Invoke(fn, args = Any[])Action (ActionStmt) — the general-code escape hatch (ADR 0011 §B). Lowers to registry[fn](state, transition, args…): the serialized action carries only the NAME fn, resolved against the per-network host-function registry (never eval'd); the body is trusted host Julia bound by obligations O1–O4. args value-exprs are evaluated before the call; the result is discarded.
ReactiveDynamics.Log — Type
Log(msg)Action (ActionStmt) that appends msg to the state log (via log). If msg is an Expr/Symbol it is evaluated in context first, otherwise it is logged as-is.
ReactiveDynamics.Seq — Type
Seq(stmts)Action (ActionStmt) that composes a vector of ActionStmts, applied in order. The composite that lets one Rule or transition post-action perform several mutations.
ReactiveDynamics.apply_action! — Function
apply_action!(state, transition, a::ActionStmt)Perform the action a against state, dispatching on the concrete ActionStmt type — the eval-free lowering table for the closed action family (ADR 0010 §C / ADR 0011 §C). transition is the firing transition instance for a transition post-action, or nothing when the action comes from a Rule; it carries through to the seeded-closure value eval (params/observables/time/Sample). SetField requires a non-nothing transition (it writes bound tokens); AddToken/Invoke resolve their name against the per-network registry and never eval. Seq applies its statements in order.
ReactiveDynamics.fire_rules! — Function
fire_rules!(state)Evaluate every enabled Rule in state.rules once, in order — the endogenous decision channel, invoked at _step! step 10 (ADR 0010 §A/§D). For each rule, the guard is evaluated (nothing transition context): a Bool fires the action 0/1 times, a numeric v fires it rand(state.rng, Poisson(v)) times (RNG-threaded for determinism). A :once rule that fired latches its enabled flag off (reset by _reinit!, §4 D7). Returns state.
ReactiveDynamics.activate! — Function
activate!(state, t::Symbol)Soft-activate the transition line named t (matched by transName/transHash) on a live state, by setting its latching transActivated gate true (ADR 0004 soft gate). Errors if no transition matches. The imperative twin of the Activate action.
ReactiveDynamics.deactivate! — Function
deactivate!(state, t::Symbol)Soft-deactivate the transition line named t (matched by transName/transHash) on a live state, by clearing its latching transActivated gate (ADR 0004 soft gate). Errors if no transition matches. The imperative twin of the Deactivate action.
ReactiveDynamics.set_guard! — Function
set_guard!(state, t::Symbol, guard)Attach a stateless per-tick guard to the transition named t (ADR 0010 §B). guard is an Expr/literal (e.g. :(cash >= phase3_cost)) compiled to the seeded closure and AND-ed with the latching transActivated gate in sample_transitions! — a transition whose guard evaluates false makes no genesis proposal that tick. Errors if no transition matches.
Per-program ledger
Cost/reward/valuation actions accumulate into a per-program ledger — the model's accounting side. These read the ledger a finished (or in-progress) run has built up.
ReactiveDynamics.ProgramLedger — Type
ProgramLedger(species, creation_index)Per-program (per-structured-token) ledger accumulator (CONTRACT §12, MVP finding D — the attribution logic lives in src/ledger.jl). Tracks one structured token's running economics: cost_incurred (capital burned on its behalf), reward_realized (reward credited when a transition it was bound to finished successfully), valuation (current mark-to-market), and entries — the append-only (t, kind, amount, transition_name) audit trail. species/creation_index identify the program. Per-program rows plus the state's unattributed_cost/unattributed_reward buckets sum exactly to the aggregate ledger rows.
ReactiveDynamics.program_ledger — Function
program_ledger(state) -> DataFramePer-program (per-structured-token) cost/reward/valuation summary for a finished (or in-progress) run, in the deterministic (species, creation_index) token order (§4 D4) — the engine-level replacement for the BD demo's post-hoc reconstruction (MVP finding D). Columns:
program the token's stable network identity (AlgebraicAgents.getname) species the token's CURRENT species/kind (:removed if soft-retired) creation_index the per-species monotonic creation index (ADR 0006 §E) — the order key cost_incurred total capital burned on behalf of this program (sum of its bind-cost shares) reward_realized total reward credited when a transition it was bound to finished successfully valuation current mark-to-market = the species' specValuation (0 when none — see header) net rewardrealized − costincurred (the realized economics to date)
The per-program cost_incurred summed over ALL programs PLUS state.unattributed_cost equals the sum of the aggregate :valuation_cost rows (likewise reward). Pass the live state; only the structured tokens that have ever existed appear.
ReactiveDynamics.program_ledger_entries — Function
program_ledger_entries(state, token_name) -> Vector{Tuple{Float64,Symbol,Float64,String}}The append-only per-event audit trail for one program: (t, kind, amount, transition_name) rows (kind ∈ (:cost, :reward)), in attribution order. Empty for an unknown/never-bound program.