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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! 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;
static ESPC: 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`].
/// In-process override for the ESPC penalty loop (see [`espc`]) — the WASM /
/// embedded analog of setting/unsetting `FF_ESPC`. 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`.
/// The ESPC penalty-resolution loop on the PDDL3 metric path (see [`crate::espc`]).
/// **Default ON since 0.5** (graduated: the outer budget is now a deterministic
/// eval pool, `FF_ESPC_EVAL_BUDGET`, so the default run is thread-count and
/// machine independent) — it engages only when the compiled task carries
/// once-only conditional-achievement deadline pairs (openstacks-shaped domains);
/// on tasks without that structure the plain metric B&B runs and this flag is a
/// verified no-op. `FF_NO_ESPC` opts out (restores the pre-0.5 default path);
/// `FF_ESPC` is still accepted for compatibility (now redundant). In-process:
/// [`set_espc_override`].