Appearance
Context variables
Every rule is evaluated against a context: a set of variables describing the candidate step. This page is the authoritative list. For a gentler introduction see the guide.
Base variables
Supplied directly for every evaluation.
| Variable | Type | Definition |
|---|---|---|
prev_sum | number | The running total from all previous steps, before the candidate is applied. |
current_value | number | The signed value of the candidate step. Positive is addition, negative is subtraction. Never 0. |
step_index | number | Zero-based position of the current step. 0 is the first step. |
last_step_index | number | Index of the final step of the exercise — that is, total steps minus one. |
Derived variables
Computed from the base variables. You never set these; they are always consistent with the values above.
| Variable | Type | Definition |
|---|---|---|
current_sum | number | prev_sum + current_value — the total that results if the candidate is accepted. |
isLastStep | boolean | true when step_index = last_step_index. |
place | number | null | The single decimal place current_value affects (1, 10, 100, …), or null if it affects more than one. |
formula | number | null | abs(current_value) / place, a digit 1–9. null when place is null. |
digitBefore | number | null | floor(abs(prev_sum) / place) % 10 — the digit of the running total at the affected place. null when place is null. |
How place is determined
A value is atomic when exactly one of its decimal digits is non-zero. place is the positional value of that digit:
current_value | place | formula |
|---|---|---|
7 | 1 | 7 |
-7 | 1 | 7 |
40 | 10 | 4 |
300 | 100 | 3 |
47 | null | null |
-89 | null | null |
105 | null | null |
Sign is ignored throughout: place, formula, and digitBefore are all computed from absolute values. Use current_value > 0 / current_value < 0 to test direction.
The null contract
WARNING
When place, formula, or digitBefore is null, comparisons against them still evaluate. They do not skip the rule, and they do not uniformly fail.
Null behaves as 0 in ordering comparisons and is unequal to every number in equality comparisons. The practical result, for a composite candidate such as +47:
| Form | Example | Result |
|---|---|---|
| Equality | formula = 8 | fails |
| Membership | place IN (1, 10) | fails |
| Lower bound | formula >= 1 | fails |
| Strictly greater | formula > 0 | fails |
| Inequality | formula != 8 | passes |
| Negative membership | place NOT IN (1, 10) | passes |
| Upper bound | formula <= 9 | passes |
| Strictly less | formula < 1 | passes |
So inclusive tests reject composite steps and exclusive tests admit them. This is the single most common source of surprising rule behavior — see the null trap for what it means in practice.
The upside of the inclusive half: a standard pattern rule of the form current_value > 0 AND formula = N AND digitBefore IN (…) automatically fails on composite steps with no special handling. Pattern rules are about atomic techniques, and they self-exclude correctly.
Scope and which variables apply
A rule declares a scope, which decides when it runs:
| Scope | Runs |
|---|---|
step | Against every candidate step. |
last-step | Against the final step only. |
sequence | Once, after a complete candidate sequence has been assembled. |
All the variables above are available in step and last-step scope. A sequence-scope rule is evaluated once with the final step's values in scope, plus whole-sequence values describing the assembled exercise.
INFO
Whole-sequence variables are supplied by the generator rather than by the base context, and the editor's linter does not currently recognize them as known identifiers — expect an "unknown variable" diagnostic even where they work. Prefer step-scope rules unless you specifically need to reason about a finished sequence.
Evaluation outcomes
Every rule evaluates to one of three outcomes:
| Outcome | Meaning |
|---|---|
| Passed | The condition held. |
| Failed | The condition did not hold. For a constraint, this rejects the candidate. |
| Skipped | The rule's IF guard was false, so the rule did not apply. A skipped rule never blocks a candidate, and never counts as a pattern match. |
The distinction between failed and skipped matters for pattern rules: only a passed rule counts as a match toward a recipe's count quotas.
See also
- Built-in functions
- Grammar and precedence
- Decimal places — the practical guide to
place/formula/digitBefore