1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Process-global overrides for the env-gated planner features.
//!
//! Each feature has a *default* (whether it's on when nothing is configured) and two
//! ways to override it: an env var (great for the CLI) and an in-process override
//! (for **WASM**, where `std::env::set_var` *panics* on `wasm32-unknown-unknown`, and
//! embedded library callers like the `sim_core` game). Env *reads* are panic-free on
//! wasm, so a getter that consults both is safe there.
//!
//! The override is **tri-state** (`Unset` / `On` / `Off`): `Unset` falls back to the
//! default + env, while `On`/`Off` are definitive. This matters now that `tdemand`
//! defaults ON — a WASM caller must be able to force it *off*, which a plain bool
//! "override OR env" could not express. Set the override once before `solve`.
use ;
// Tri-state override packed into an AtomicU8.
const UNSET: u8 = 0;
const ON: u8 = 1;
const OFF: u8 = 2;
static TDEMAND: AtomicU8 = new;
static TDECOMP: AtomicU8 = new;
static TCONC: AtomicU8 = new;
static ESCALATE: AtomicU8 = new;
/// Set the overrides (e.g. from the WASM `flags` arg). Each bool is definitive for
/// this and subsequent solves — `true` forces the feature on, `false` forces it off
/// (overriding the default), so a later `solve` can't inherit a previous caller's
/// choice. To return a feature to its default + env behavior, use [`clear_overrides`].
/// In-process override for the escalation ladder (see [`escalate`]) — the WASM /
/// embedded analog of `FF_NO_ESCALATE`, since env *writes* panic on wasm32.
/// Definitive until [`clear_overrides`].
/// Clear all in-process overrides back to `Unset` (default + env decide).
/// How much temporal demand guidance to apply. The feature graduated from a single
/// opt-in `FF_TDEMAND` to a **default-on `Numeric`** tier in v0.2 — but only the
/// numeric-goal half, because the predicate-goal-threshold half can regress makespan
/// on renewable-resource concurrency domains (it reads a `(>= (avail) 1)` guard on a
/// net-zero pool as accumulation demand and serializes). So the safe, measured win
/// (multi-round *numeric* goals: `steel >= 2`, `grain >= 10`, `coin >= 15`) is on by
/// default; the structural/predicate half stays explicit.
/// Resolve the active demand tier from the override / env / default.
/// Whether *any* demand seed is built (`Numeric` or `Full`). Predicate-threshold
/// seeding is gated separately on [`demand_mode`] `== Full`; goal-relevance pruning
/// rides any non-`Off` tier (minus `FF_NOREL`).
/// The partition-and-resolve decomposer (temporal path). Opt-in via `FF_TDECOMP`.
/// The on-failure escalation ladder in [`crate::temporal::solve`]: when the
/// default-tier monolithic search fails, retry at the `Full` demand tier, then
/// hand the goal to the decomposer. Each rung runs ONLY after the previous one
/// failed, so no instance that solves today can change its plan — escalation
/// spends extra time on (would-be) failures to convert them into solves.
/// Default ON; `FF_NO_ESCALATE` (or [`set_escalate_override`]`(false)` in-process)
/// disables the ladder alone, and `FF_NO_TDEMAND` (the master "pristine pre-v0.2
/// path" switch) disables it too.
/// The concurrent scheduling phase: repack a temporal plan onto the domain's actor
/// objects to minimise makespan (so more workers finish faster). See [`crate::tsched`].
/// Opt-in via `FF_TCONC`.