Pools & meters

Ranged value

ranged-value-1

Tests included

This contract defines the behaviour of values with a range: a health bar, stamina, or experience.

It decides what your health bar or XP bar does when it overfills, hits zero, or fills into the next level.

Use in your game

Opens the authoring tool with this contract added and its questions unanswered. Or download the ZIP and add it later.

What is in the ZIP

The ZIP holds the contract and its acceptance tests. In the authoring tool, choose Add contract and pick this ZIP. If you keep your design as files, put them in contracts/ and fill in the answers there.

Questions

Up to 15 questions. Some appear only after earlier answers.

  1. Can this value hold a fraction, or is it always a whole number?
  2. A change contains part of a point. What happens to that part?
  3. Landing exactly on a line or limit: does that count as reached?
  4. Starting again at a limit is a lap. What happens when a change would push this value above its marked top?
  5. A change would pull this value below its marked bottom. What happens?
  6. One move passes more than one mark (a line or a band edge). Which marks report?
  7. The bottom or top moves while this value holds a number. What happens to the value?
  8. Something sets this value to a number outside its range. What happens?
  9. A set jumps across one or more marks. Do they report?
  10. Starting over at a limit is a lap. After a lap, what happens to the extra?
  11. After a lap, the extra can reach the same limit again. Can one change cause more than one lap?
  12. Does a lap clear any saved fraction?
  13. This value cannot pay the full cost of an action. What happens?
  14. A drift is a change that happens with nobody acting. Two or more drifts can run in the same step. How do they combine?
  15. A change would pass a limit. Do marks read the result before or after the limit handles it?

Try the answers

Pick answers to see which rules and tests apply. Nothing is saved here: the ZIP and the authoring tool start unanswered.

Can this value hold a fraction, or is it always a whole number?

Choices for Can this value hold a fraction, or is it always a whole number?
The stored value is always whole. A health bar can show 7 or 8, never 7.5.

A change with a fractional part passes through small-change before any limit or mark reads it. Every absolute stored target and mark must resolve to a whole number.

Fractions stay exactly as sent. An oxygen meter can rest at 7.5.

Every finite change lands at full precision. No saved-fraction store exists.

Why this is asked

Whole and fractional values handle small changes differently. A health bar may show only whole points while oxygen keeps decimals.

A change contains part of a point. What happens to that part?

Asked when
Number kind is Whole number.
If not asked
This value keeps fractional changes exactly as sent.
Choices for A change contains part of a point. What happens to that part?
Use the nearer whole change, with an exact half going up the scale. A health gain of 2.5 becomes 3.

Round the signed change to the nearest integer; ties go toward positive infinity. Discard the difference.

Use the nearer whole change, with an exact half going away from zero. A karma loss of 2.5 becomes −3.

Round to the nearest integer; ties choose the integer with the greater absolute magnitude. Discard the difference.

Drop the fractional part toward zero. A poison drain of 0.7 health does nothing that step.

Remove the signed fractional part toward zero and discard it.

Every nonzero change moves at least one whole point. Chip damage of 0.1 removes 1 health.

Round every non-integer signed change away from zero and discard the difference.

Save leftover fractions until they make a whole point. Two hits worth 0.5 poise each add 1 poise together.

Move the whole part now. Add only the signed fractional remainder to one saved-fraction store. Remove complete multiples of fraction-step toward zero, move by that many whole units, and keep the remainder. Sets always clear the store; named resets and starting over at a limit use their own clearing choices.

Landing exactly on a line or limit: does that count as reached?

Choices for Landing exactly on a line or limit: does that count as reached?
Yes, touching it counts. Health falling to exactly 25 fires a warning set at 25.

A rising mark at t is reached at value greater than or equal to t; a falling mark is reached at value less than or equal to t. An exact landing may consume a limit.

No, the value must pass it. Health must fall below 25 before a warning set at 25 fires.

A rising mark at t is reached only above t; a falling mark is reached only below t. An exact landing does not consume a limit.

Starting again at a limit is a lap. What happens when a change would push this value above its marked top?

Choices for Starting again at a limit is a lap. What happens when a change would push this value above its marked top?
Stop at the top and lose the extra. A large health pickup fills the bar and wastes the surplus.

Store max, discard the excess, and report it to no one. The change otherwise happened.

Refuse the whole gain. A health pickup that would overfill the bar adds no health.

Leave the value and saved fraction unchanged and report the refusal. Fire no mark.

Fill to the top and return the extra. A healing rule can pass unused healing to a shield.

Store max and report the positive excess to the caller. This contract does not route it. A change with nobody acting has no caller, so its extra is dropped.

The marked top is only a landmark. A score can keep rising after it passes its goal.

Store the complete result above max. The declared top remains citable and still defines shares.

Start a lap at the top. Filling an XP bar reports a level and returns the bar to its lap target.

Reaching is decided by exact-landing. Report a lap and move to lap-lands-on. Section 3 alone defines leftover handling and report order.

A change would pull this value below its marked bottom. What happens?

Choices for A change would pull this value below its marked bottom. What happens?
Stop at the bottom and lose the extra. A lethal hit leaves health at zero.

Store min, discard the excess, and report it to no one.

Refuse the whole loss. A hit that would cross the bottom deals no damage.

Leave the value and saved fraction unchanged and report the refusal. Fire no mark.

Empty to the bottom and return the shortfall. A shield can report how much damage still needs another rule.

Store min and report the positive shortfall to the caller. This contract does not route it. A change with nobody acting has no caller, so the shortfall is dropped.

The marked bottom is only a landmark. A debt meter can keep falling below zero.

Store the complete result below min. The declared bottom remains citable.

Start a lap at the bottom. Losing the last combo point can report a break and refill the meter.

Reaching is decided by exact-landing. Report a lap and move to lap-lands-on. Section 3 alone defines leftover handling and report order.

One move passes more than one mark (a line or a band edge). Which marks report?

Asked when
the lines list has at least one row, or the bands list has at least one row.
If not asked
No mark exists, so no move can pass one.
Choices for One move passes more than one mark (a line or a band edge). Which marks report?
Report every crossed mark in travel order. One large hit can report wounded, critical, then empty health.

Report every armed line and band edge whose reached state changes in its direction. Order by position along the path; row order breaks ties. Update all mark state.

Report only the crossed mark nearest the landing value. One large hit can report empty health and suppress earlier warnings.

Bare lines and band edges compete by distance to the landing value; row order breaks ties. Report only the winner, but update every reached, arm, and band state along the full path.

The bottom or top moves while this value holds a number. What happens to the value?

Asked when
the min value is supplied as a reference, or the max value is supplied as a reference.
If not asked
The bottom and top are fixed numbers, so neither limit moves.
Choices for The bottom or top moves while this value holds a number. What happens to the value?
Follow a moving top by filling to it. Raising maximum health from 100 to 120 also raises current health to 120.

A max change stores the new max. A min-only change keeps the value unless it falls below the new min, then stores that min.

Keep the current number while it still fits. Raising maximum health from 100 to 120 leaves current health at 70.

Preserve the value inside the new range; otherwise clamp it to the limit it is outside, even if an ordinary change may pass that limit.

Keep the same share of the range. Raising a half-full health bar from 100 to 200 moves its health from 50 to 100.

Compute the old normalized share immediately before the limit move and store the same share of the new range. An empty old range uses the new min. Whole-number targets round to nearest with ties away from zero. Saved fraction is unchanged.

Keep the number if it fits; otherwise move to a named safe number. A lowered stamina cap can move an outside value to 80.

Preserve the value inside the new range. Otherwise store out-of-range-lands-on, which must resolve inside the new range.

Do not move the held number now. Lowering a score's marked top to 100 can leave a held score of 120 unchanged.

A held number outside a moved limit is legal only where the matching ordinary edge answer lets the value pass that limit.

Something sets this value to a number outside its range. What happens?

Asked when
the sets list has at least one row.
If not asked
No named set puts this value directly at a target number.
Choices for Something sets this value to a number outside its range. What happens?
Move to the limit the target passed. A refill aimed at 120 leaves a 100-point health bar at 100.

Above max store max; below min store min. The rejected target is not a raw result. A set does not hand back extra or start a lap.

Refuse the set and keep the old number. An invalid checkpoint refill leaves health unchanged.

Leave the value and saved fraction unchanged, fire no mark, and report refusal to the caller.

Store the target even outside the range. A score set to 120 can stay above its marked top of 100.

Store the target exactly. It is legal beyond a limit only where the matching ordinary edge answer lets the value pass that limit.

A set jumps across one or more marks. Do they report?

Asked when
the sets list has at least one row.
If not asked
No named set crosses a line or changes a band.
Choices for A set jumps across one or more marks. Do they report?
Report crossed marks after a successful set. Refilling oxygen to full can clear the low-air warnings on the way up.

After storing the accepted target, test lines and band edges along the movement. jumped-lines selects reports. A rejected or clamped target is never a raw result.

Update mark state without reports. Respawning at full health does not replay every health warning.

Recompute line reached state and line-geometry band state from the stored target. Event-edged bands keep their state. Report nothing.

Starting over at a limit is a lap. After a lap, what happens to the extra?

Asked when
At the ceiling is Start a lap, or At the floor is Start a lap.
If not asked
Neither limit starts this value over, so no lap leaves extra.
Choices for Starting over at a limit is a lap. After a lap, what happens to the extra?
Keep using the extra after the lap. An XP award of 120 can fill a 100-point bar and put 20 into the next level.

Keep the amount past the consuming limit and apply it in the same direction after the lap movement. Section 3 defines the sequence.

Throw the extra away after the lap. A 120-point stagger hit fills one 100-point meter and loses the remaining 20.

Discard the leftover after one lap and report it to no one (see the settlement order).

After a lap, the extra can reach the same limit again. Can one change cause more than one lap?

Asked when
At the ceiling is Start a lap, or At the floor is Start a lap.
If not asked
Neither limit starts this value over, so one change cannot lap it.
Choices for After a lap, the extra can reach the same limit again. Can one change cause more than one lap?
Start over again while enough extra remains. A 250-point XP award can report two levels on a 100-point bar.

Repeat while carried leftover reaches the limit, subject to the 32-lap cap in section 3. This requires carrying the extra.

Allow at most one lap from each change. A 250-point combo gain reports one lap even if more would fit.

The originating change causes at most one lap (see the settlement order).

Does a lap clear any saved fraction?

Asked when
Small change is Save the fraction and At the ceiling is Start a lap, or Small change is Save the fraction and At the floor is Start a lap.
If not asked
No lap can clear saved fractions; either this value does not lap or it does not save fractions.
Choices for Does a lap clear any saved fraction?
Clear the saved fraction after every lap. Breaking a stagger meter removes the 0.4 poise still waiting.

A lap clears the saved fraction.

Keep the saved fraction across a lap. Leveling up keeps the 0.4 XP still waiting.

A lap leaves the signed saved-fraction store unchanged.

This value cannot pay the full cost of an action. What happens?

Asked when
the costs list has at least one row.
If not asked
No cost checks this value before changing it; every change simply happens, and bands and limits still apply.
Choices for This value cannot pay the full cost of an action. What happens?
Refuse the action and spend nothing. A tired player cannot dodge without the full stamina cost.

Report refusal and shortage to the caller. Leave the value, saved fraction, and every mark unchanged.

Spend what remains and report the amount paid. A tired player can use the last stamina for a weaker dodge.

Move to the limiting edge, test marks normally, and report the approved positive magnitude. The game's rule decides the partial action.

A drift is a change that happens with nobody acting. Two or more drifts can run in the same step. How do they combine?

Asked when
the drifts list has at least two rows.
If not asked
Fewer than two drifts can run together, so no combination choice applies.
Choices for A drift is a change that happens with nobody acting. Two or more drifts can run in the same step. How do they combine?
Add the drifts' signed amounts and move once. Oxygen drain of 3 and recovery of 1 produce one loss of 2.

Clip each eligible contribution to its own stop, sum the clipped amounts, resolve small-change once, and test marks once.

Run only the largest drift. Health regeneration of 4 beats poison damage of 2 for that step.

Compare clipped absolute magnitudes; row order breaks a tie. A skipped ramp does not advance for that step.

Run each drift in written order. Poison can damage health before regeneration heals it in the same step.

Settle every eligible row separately in row order. Each row follows section 3 from start to finish.

A change would pass a limit. Do marks read the result before or after the limit handles it?

Asked when
the lines list has at least one row, or the bands list has at least one row.
If not asked
No line or band exists, so nothing reads a result beyond a limit.
Choices for A change would pass a limit. Do marks read the result before or after the limit handles it?
Marks read the number the value keeps. A hit aimed at −20 leaves health at 0, so warnings read 0.

The outward part of the move tests its stored endpoint, or the consuming limit on a lap. It never tests beyond a limit.

Marks read the result before the limit fixes it. A hit aimed at −20 lets health warnings read −20 before health returns to 0.

The outward part of the move tests the raw candidate. It may observe a number the value never stores. A refused change has no observable raw result.

Numbers and rules7 numbers, 13 rules

Numbers

Each setting takes a number, or a reference to a named value in your tuning. Stay inside any range shown.

Min

min

This value's marked bottom. Keep it even when the value may fall lower.

Written as
a number or a citation

Max

max

This value's marked top. Keep it even when the value may rise higher.

Written as
a number or a citation

Initial

initial

The number held when this value is created, or a citation read at creation. Later resets are listed separately.

Written as
a number or a citation

Fraction step

fraction-step

How much saved fraction releases one whole point.

Applies when Small change is Save the fraction.

Anchor

anchor

The resting point a drift approaches from either side.

Written as
a number or a citation

Applies when some drifts row has direction Toward the anchor.

Lap lands on

lap-lands-on

Where the value lands during a lap.

Written as
a number or a citation

Applies when At the ceiling is Start a lap, or At the floor is Start a lap.

Out of range lands on

out-of-range-lands-on

Where the value lands when a moved limit leaves it outside the new range.

Written as
a number or a citation

Applies when When a limit moves is Pull it to a declared number.

Rules

  • max > min
  • initial >= min
  • initial <= max
  • fraction-step > 0
  • anchor >= min
  • anchor <= max
  • lap-lands-on >= min
  • lap-lands-on <= max
  • out-of-range-lands-on >= min
  • out-of-range-lands-on <= max
  • Keeping the same share needs a real floor and ceiling; close both limits or choose another response to a moving limit.

    Forbidden when When a limit moves is Keep the share and At the ceiling is No ceiling, or When a limit moves is Keep the share and At the floor is No floor.

  • This moving-limit answer can place the value directly on either consuming edge, but a limit move never starts a lap; change the moving-limit or lap answer.

    Forbidden when When a limit moves is Refill to the new ceiling and At the ceiling is Start a lap, or When a limit moves is Refill to the new ceiling and At the floor is Start a lap.

  • Another lap needs leftover from the first; carry it forward or allow only one lap.

    Forbidden when More than one lap is Lap again while it fits and The extra after a lap is Drop it.

Lists9 lists

Some settings are lists of rows.

A reference points to a number or a rule in your design. For a number, use its address in your tuning. For a rule, use its file and heading, such as 02-mechanics.md#recovery. Each field's description says what it needs.

Reading notes

reading-notes

List the game prose a reader needs before trusting this adoption. Use at most one row.

An empty list means: No advance reading is required.

Each row is: read-first.

Every field
FieldKindWhen it appearsMeaning
read-first reference Required Point to the game prose a reader needs first, such as which of a soft and hard ceiling the game calls full.

Quantity unit

quantity-unit

Name the game-owned unit used by absolute values. Use at most one row.

An empty list means: This contract gives the quantity no named unit.

Each row is: unit.

Every field
FieldKindWhen it appearsMeaning
unit string Required The unit for every absolute number and citation, such as kg or XP. This contract neither interprets nor converts it.

Lines

lines

List the named marks this value reports crossing.

An empty list means: No crossing is reported.

Each row is: id, value-kind, value, value-key, line-unit, direction, refire, times, rearm, rearm-declared-in, repeat, counts-at-line, starts-armed.

Every field
FieldKindWhen it appearsMeaning
id string Required Name this mark in the game's words, such as low-health or full.
value-kind choice: number, citation Required Whether this mark uses a fixed number or points to a number the mark follows wherever it goes.
value number Present when row value kind is Number. The fixed number where this mark sits.
value-key reference Present when row value kind is Citation. Point to the number where this mark sits. Read it fresh at each comparison.
line-unit choice: number, share-of-the-ceiling Optional Use a fixed number or a share of the marked top. A share sits at that share of the fresh top; it can fall between whole points and is only compared, never stored. Omitting this field means number.
direction choice: rising, falling, both Required Which direction may report this crossing.
refire choice: every-crossing, once, a-set-number-of-times Required Report every crossing, once per arm, or a fixed number of times per arm.
times integer Present when row refire is A set number of times. The positive whole number of reports allowed per arm.
rearm choice: on-reset, on-event, after-a-wait, never Present when row refire is Once or A set number of times. What restores this line's full allowance.
rearm-declared-in reference Present when row rearm is On reset or On event or After a wait. Point to the reset, event, or wait that restores the line.
repeat choice: restart-the-wait, keep-the-first-wait, add-to-the-wait Present when row rearm is After a wait. Choose what another crossing does while the wait is running.
counts-at-line choice: at-the-line-counts, must-pass-the-line Optional Override the value-wide exact-landing answer for this line.
starts-armed choice: armed, disarmed Optional Whether this line starts able to report. Omission means armed.

Sets

sets

List each refill, direct assignment, or recomputed total. Use a set when the movement should be audible to lines and bands.

An empty list means: Nothing sets the value outright; laps, resets and limit moves remain their own movements.

Each row is: id, mode, target-key, trigger-declared-in, enabled-while.

Every field
FieldKindWhen it appearsMeaning
id string Required Name the set, such as surface-refill or inventory-total.
mode choice: set-to-target, recompute Required Use a named target or a rule's computed result.
target-key reference Required Point to the target number or the rule that computes it.
trigger-declared-in reference Required Point to the event or rule that offers this set.
enabled-while reference Optional Point to an optional condition that allows this set.

Bands

bands

List named on-or-off states between marks, such as overheated or low-warning.

An empty list means: This value keeps no named state.

Each row is: id, enter-on, enter-value-kind, enter-value, enter-value-key, enter-unit, enter-direction, enter-declared-in, leave-on, leave-value-kind, leave-value, leave-value-key, leave-unit, leave-direction, leave-declared-in, repeat, starts, blocks-change, counts-at-line.

Every field
FieldKindWhen it appearsMeaning
id string Required Name this state in the game's words.
enter-on choice: line, event Required Whether a line or named event turns the state on.
enter-value-kind choice: number, citation Present when row enter on is Line. Whether the entering line uses a fixed number or points to a number the mark follows wherever it goes.
enter-value number Present when row enter value kind is Number. The fixed entering line.
enter-value-key reference Present when row enter value kind is Citation. Point to the entering line. Read it fresh at each comparison.
enter-unit choice: number, share-of-the-ceiling Present when row enter on is Line. Use a fixed number or a share of the marked top. A share sits at that share of the fresh top; it can fall between whole points and is only compared, never stored.
enter-direction choice: rising, falling Present when row enter on is Line. The direction that turns the state on.
enter-declared-in reference Present when row enter on is Event. Point to the event that turns the state on.
leave-on choice: line, event, after-a-wait Required Whether a line, event, or wait turns the state off.
leave-value-kind choice: number, citation Present when row leave on is Line. Whether the leaving line uses a fixed number or points to a number the mark follows wherever it goes.
leave-value number Present when row leave value kind is Number. The fixed leaving line.
leave-value-key reference Present when row leave value kind is Citation. Point to the leaving line. Read it fresh at each comparison.
leave-unit choice: number, share-of-the-ceiling Present when row leave on is Line. Use a fixed number or a share of the marked top. A share sits at that share of the fresh top; it can fall between whole points and is only compared, never stored.
leave-direction choice: rising, falling Present when row leave on is Line. The direction that turns the state off.
leave-declared-in reference Present when row leave on is Event or After a wait. Point to the leaving event or wait length.
repeat choice: restart-the-wait, keep-the-first-wait, add-to-the-wait Present when row leave on is After a wait. Choose what another entry does while the wait is running.
starts choice: in, out, read-from-initial Required Whether this state starts on, off, or follows the starting value.
blocks-change choice: none, blocks-rises, blocks-falls, blocks-all Optional Which incoming plain changes, costs, or drifts are blocked while this state is on. Omission means none.
counts-at-line choice: at-the-line-counts, must-pass-the-line Optional Override exact-landing for both line edges.

Costs

costs

List each action that checks whether this value can pay before it changes.

An empty list means: No action checks this value before it changes; every change simply happens, and bands and limits still apply.

Each row is: id, direction, amount-key, action-declared-in, answer.

Every field
FieldKindWhen it appearsMeaning
id string Required Name this cost in the game's words, such as dodge or cast-spell.
direction choice: rising, falling Required Whether paying moves toward the top or bottom.
amount-key reference Required Point to the non-negative cost.
action-declared-in reference Required Point to the action that receives refusal, shortage, or paid-amount reports.
answer choice: refuse-the-action, take-what-fits Optional Override the value-wide cost answer for this action.

Drifts

drifts

List each drift, such as draining, recovery, or cooling.

An empty list means: This value never changes on its own.

Each row is: id, direction, cadence, moment-declared-in, step-amount-key, amount-kind, amount-declared-in, stops-at-key, at-stop.

Every field
FieldKindWhen it appearsMeaning
id string Required Name this drift in the game's words.
direction choice: rises, falls, toward-the-anchor Required Move upward, downward, or toward the shared resting point.
cadence choice: per-game-step, per-real-second, per-turn, at-a-named-moment Required Choose when one contribution is made.
moment-declared-in reference Present when row cadence is At a named moment. Point to the named moment.
step-amount-key reference Required Point to the positive amount per occurrence.
amount-kind choice: fixed, depends-on-state, grows-while-it-runs Required Whether the amount stays fixed, reads state, or grows while running.
amount-declared-in reference Present when row amount kind is Depends on state or Grows while it runs. Point to the state mapping or growth rule.
stops-at-key reference Required Point to the number where this drift stops.
at-stop choice: lands-exactly, overshoots-then-returns Required Land exactly, or briefly pass the stop before returning when the row runs alone.

Interrupts

interrupts

List the conditions and pauses that control a drift. Every row for one drift must allow it before it runs.

An empty list means: No listed condition or pause controls a drift.

Each row is: id, drift, kind, condition-declared-in, event-declared-in, pause-length-key, pause-length-kind, pause-length-declared-in, repeat-event.

Every field
FieldKindWhen it appearsMeaning
id string Required Name this interruption.
drift string Required Name the drift this row controls.
kind choice: off-while-condition, runs-only-while-condition, paused-after-event Required Stay off during a condition, run only during it, or pause after an event.
condition-declared-in reference Present when row kind is Off while condition or Runs only while condition. Point to the condition or to a band on this value.
event-declared-in reference Present when row kind is Paused after event. Point to the event that starts the pause.
pause-length-key reference Present when row kind is Paused after event. Point to the pause length.
pause-length-kind choice: fixed, depends-on-state Present when row kind is Paused after event. Whether the pause stays fixed or reads state.
pause-length-declared-in reference Present when row pause length kind is Depends on state. Point to the rule for the changing pause.
repeat-event choice: restart-the-wait, keep-the-first-wait, add-to-the-wait Present when row kind is Paused after event. Choose what another event does while the pause is running.

Resets

resets

List named moments that put this value back, such as respawn, a new day, or turn start. Use a reset when this return must always stay silent.

An empty list means: Only creation applies the starting value.

Each row is: id, happens-at, sets-value-to-key, clears-saved-fraction, re-arms-lines, resets-bands.

Every field
FieldKindWhen it appearsMeaning
id string Required Name this reset moment in the game's words.
happens-at reference Required Point to the rule naming the moment.
sets-value-to-key reference Optional Point to the stored target. Omission uses the starting value — with a cited initial, the number read at creation.
clears-saved-fraction choice: yes, no Present when Small change is Save the fraction. Whether this reset clears the saved fraction.
re-arms-lines choice: yes, no Required Whether cited lines regain their full allowance.
resets-bands choice: return-to-starts, recompute-from-target, keep Optional Choose how named states respond. return-to-starts silently restores every band's declared start; recompute-from-target silently recomputes every line-geometry band against the reset target; keep preserves every band's state. Event-edged bands keep their state under both recompute-from-target and keep. Omission means keep; that is this definition's chosen default, not a forced choice.

For builders

Exact mechanism wording and 96 pack tests

Exact mechanism wording

This is the one normative authority for event order. Questions describe choices; they do not redefine this sequence.

An operation is one change the machine settles from start to finish: a plain change, cost, set, drift step or composed drift batch, lap movement, limit move, or reset. An imposed change is a plain change that happens without checking whether the value can pay it. Residue is the signed fraction saved for later. A mark is a line or one edge of a band. A leg is one visible stretch of movement with its own start and end. Each operation has an id supplied by its row or cited game rule and settles fully before the next begins. A lap sequence's outward, reset, and leftover legs retain their originating operation id; leg position and lap count distinguish their reports.

A band is line-geometry only when both its edges are lines. A band with any event or wait edge is event-edged. An event-edged band keeps its state under every silent recompute (a set, a reset, or a limit move). A reset's explicit return-to-starts is a restore, not a recompute, and applies to every band.

1. Block. If an active band blocks the operation's direction and the operation is an imposed change, cost, or drift, discard it. Report blocked to its source; a drift records the block but has no receiver. Stop this operation. Remove a blocked drift before several drifts combine. Blocks never stop sets, resets, limit moves, or lap movements. 2. Resolve provisionally. Fractional handling computes a provisional movement and new residue without committing either. A whole change leaves residue untouched. An absolute repositioning computes its destination and applies its own clearing rule; it does not pass through small-change. 3. Check capacity for a cost. Compare provisional movement with the room toward the named limit. Refusal discards movement and residue together. take-what-fits recomputes both from the approved amount and never keeps a fraction from the refused part. 4. Find the raw candidate. A change adds provisional movement to the held value. A set uses its accepted or clamped stored target. A lap movement, limit move, or reset uses its own absolute destination. 5. Apply the edge. A raw candidate strictly past a limit uses that limit's answer. Exact landing is ordinary unless start-a-lap applies, in which case exact-landing decides whether it consumes. Refusing the whole change discards provisional movement and residue, leaves the store untouched, reports refusal, and stops. Sets, resets, and limit moves use their own target rules. Drifts use the clipping exception below. 6. Commit. Store the final value and new residue together. No partly settled state is visible. 7. Test marks for each leg. The outward leg ends at the final value or consuming limit. A lap then has a lap leg, followed by each carried leftover as a new lap operation returning to step 1. Test lines and band edges on every leg. Recompute reached state from each stored endpoint in both directions; only a false-to-true transition in the row's direction reports. A both line keeps one reached state per direction. With raw reading, only the outward leg tests the raw candidate; reset and leftover legs test stored values. At a consuming limit, report outward marks, including a line on the limit, then the lap, then lap-leg marks. Apply jumped-lines separately to every leg. 8. Report. Every report carries before, after, direction, leg position, and operation id. A crossing or band transition also carries its row id. A lap carries its count. lap-cap-reached carries committed state. Returned extra carries its amount. A cost or block carries refusal, shortage, approved amount, or blocked as applicable. Raw-reading reports use the tested raw candidate as after; other reports use the stored endpoint. Direction is rising, falling, or unchanged.

Every comparison reads the stored value at full precision, never a rounded display number. Every cited limit, mark and stop is read fresh at each comparison. Creation is not a movement or report. At creation, line and band-edge reached state is stored without reporting; lines use their declared arm state, and bands use their declared starting state. A share mark sits at the declared share multiplied by the fresh value at max; that position may be fractional and is compared, never stored. A line-geometry band that answers read-from-initial starts in exactly when the initial value sits on the reached side of its entering edge and not on the reached side of its leaving edge, each side read per that edge's declared direction, with an exact landing counted as this value's exact-landing answer or the row's counts-at-line override directs. An event-edged band that answers read-from-initial starts out. A silent recompute of a line-geometry band's state (a set, a limit move, or recompute-from-target) applies the same two-sided test against the value it recomputes from.

Lap loop. A single originating operation may settle at most 32 laps. Before lap 33, reject the continuation, report lap-cap-reached, drop the remaining leftover, and keep the state committed by lap 32. A statically provable repeated lap state is a package error, but the runtime cap remains the termination guard. After each lap report, re-read either cited limit and check the lap target against the fresh range. If a limit moved, apply the limit-move ruling below; any limit-moved band report occurs before the lap leg. A limit move never repositions the value during this loop. Under clear-it, a lap clears the saved fraction after the consuming movement and before carried leftover is applied. Under one-lap-per-change, a second reach of the same consuming limit is stored without consuming and further excess is dropped.

Drift clipping. A rising drift is eligible only below its stop; a falling drift only above it; a drift toward the anchor uses the matching test for its current direction. Clip each contribution to its stop before combining drifts. overshoots-then-returns is observable only when that row settles alone: its raw path may expose the overshoot, then a silent correction stores the stop, reports no mark, and recomputes reached state from the stored stop. A drift reaching a consuming limit clips there without consuming it.

Sets. A set has no raw result. Marks see only a successful stored outcome. Clamping a target stores the nearer limit; raw reading never sees the rejected target. A successful set clears residue. A refused set does not.

Resets. A reset stores its target, recomputes and stores every line's reached state from that target, and applies its arm, band, and fraction choices silently. Band state follows the row's resets-bands answer, not an automatic recompute. For a band that answers read-from-initial, return-to-starts restores the state stored at creation. It reports no crossing.

Limit moves. A moving limit never fires a bare line. After the limit and any resulting current-value change settle, recompute and store every line's reached state and every line-geometry band's state against the new positions. Event-edged bands keep their state. A line-geometry band that enters or leaves this way reports the state change with cause limit-moved; a bare line reports nothing. The saved fraction is not cleared. A limit move that lands the value exactly on a consuming edge does not consume.

Continuous drift. A per-real-second drift accrues continuously. Each settlement contributes its rate multiplied by elapsed cited-clock time, and fractional accrual passes through small-change.

Sets, resets, and limit moves at one moment settle in the order the citing game rules fire them. A game rule that fires several at once must state their order.

Share-preserving limit moves. keep-the-share is one absolute repositioning. A whole-number target rounds to nearest, with ties away from zero. Residue is unchanged.

A band id may be cited anywhere this adoption's own game asks for a condition (contracts.<adoption>.bands.<id>). Other adoptions still may not cite it.

Verification pack

sha256:995be0ad12bc80c0f420ab42cf566f79a8543cc212533df2168fa0c3381b9fe3

The format calls an adoption with its matching pack Checked: the tests travel with it, but a game has not necessarily passed them. Without the pack the adoption is Promised: the builder still owes the chosen behavior.

96 pack tests

Placeholders are filled from the adoption's answers, values, rows, and verification inputs.

an in-range change applies exactly

change-applies

scenarioonce

Applies for every adoption

An in-range change moves Instance by its amount Bind resolution phrase, in one commit with no partly settled state observable. A mark whose reached state did not change does not report. The edges are stated at Value cite min and Value cite max; this test restates neither number.

Given

Instance holding a stored value strictly between Value cite min and Value cite max, with enough room that the change below stays in range, and with no active band blocking the change's direction

When
  • one imposed change with signed amount d is applied to Instance
Then
  • the stored Instance value changes by d Bind resolution phrase
  • the value and residue, when residue exists, commit together and no partly settled state is observable
  • no mark whose reached state did not change reports
Diagnostics
  • Instance-value-before-after
  • Instance-mark-log
a fractional change resolves as declared

fractional-change-resolves

scenarioonce

Applies when Small change is Nearest or Nearest away from zero or Drop the fraction or Always a whole unit.

Instance holds whole numbers, so a change carrying a fraction resolves before it reaches the value: what moves is Bind resolution phrase. The part resolved away is gone; no later change is larger or smaller for it.

Given

Instance holding a whole stored value, with room in range for the change below, and a record naming the amount offered and the amount that reached the value

When
  • positive and negative changes carrying fractions, including exact halves, are offered to Instance
Then
  • the amount that reaches Instance is Bind resolution phrase
  • the stored value is whole after every change
  • the resolved-away part is discarded and changes no later operation
Diagnostics
  • Instance-change-record
  • Instance-value-before-after
saved fractions release whole multiples toward zero

fractional-change-saves-residue

scenarioonce

Applies when Small change is Save the fraction.

Instance splits a fractional change: the whole part moves at once and the signed remainder waits as residue. Whenever that residue contains complete multiples of Value cite fraction step, those multiples leave toward zero as whole-unit movement and the remainder stays. A whole change leaves residue alone. The test restates neither the step nor any limit.

Given

Instance holding a whole stored value with signed residue zero, enough room for the changes below, and a record naming each offered amount, movement, and residue afterwards, and with no active band blocking the change's direction

When
  • a run of positive and negative fractional changes is applied, including a whole change and residue that reaches at least one complete multiple of Value cite fraction step
Then
  • the whole part of each fractional change moves Instance at once and only its signed fractional remainder enters residue
  • complete multiples of Value cite fraction step are removed from residue toward zero and move that many whole units in the matching direction
  • a whole change moves in full and leaves residue unchanged
  • the stored value remains whole
  • residue after each change equals the offered signed fractional remainders minus the complete multiples of Value cite fraction step already released, and each released multiple moved that many whole units
Diagnostics
  • Instance-change-record
  • Instance-residue
  • Instance-value-before-after
a fractional value has no saved-fraction store

fractional-value-keeps-no-store

scenarioonce

Applies when Number kind is Fractional.

A fractional Instance keeps every finite change at full precision. It has no saved-fraction store, so residue is never observable.

Given

Instance holding any fractional stored value with room for finite positive and negative changes

When
  • finite changes with fractional amounts settle
Then
  • every finite change lands at full precision
  • no saved-fraction store exists
  • no residue is ever observable
Diagnostics
  • Instance-value-before-after
  • Instance-state-record
every comparison reads the stored value

comparisons-read-stored-value

scenarioonce

Applies for every adoption

Whatever Instance shows the player, every comparison reads its stored value at full precision. Lines, bands, limits, drift stops, and costs never read a rounded display number, and each cited position is read fresh.

Given

a moment when the number shown for Instance differs from the stored value because the display is rounded, shortened, or abbreviated; a display that always matches storage has nothing to check here

When
  • a line, band edge, limit, drift stop, or cost comparison is made
Then
  • the comparison reads the stored Instance value at full precision
  • every cited position is read fresh for that comparison
  • the displayed number decides nothing
Diagnostics
  • Instance-comparison-log
  • Instance-value-before-after
creation stores mark state silently

creation-is-silent

scenarioonce

Applies for every adoption

Creation is not a movement and reports nothing. Instance silently stores every line's reached state, gives lines their declared arm state or the armed default, and gives bands their declared starts.

Given

creation of Instance at Value cite initial

When
  • initial line and band state is stored
Then
  • creation is not a movement and reports nothing
  • every line's reached state is stored silently
  • lines take their declared arm state, or armed when starts-armed is omitted
  • bands take their declared starts
Diagnostics
  • Instance-line-state
  • Instance-line-allowance
  • Instance-band-state
  • Instance-mark-log
an exact landing counts as reached

exact-landing-counts

scenarioonce

Applies when Exact landing is At the line counts.

For Instance, touching a line or consuming limit counts as reaching it. An armed line at that position, matching the direction of travel and with allowance remaining, reports on that landing, and a limit answered start-a-lap consumes the change. This value-wide answer is tested at a line or band that declares no counts-at-line of its own.

Given

Instance on the unreached side of a declared line or consuming limit, at a line or band that declares no counts-at-line of its own

When
  • one change lands exactly on that position
Then
  • the position counts as reached in the direction of travel
  • an armed line at that position, matching the direction of travel and with allowance remaining, reports on that landing
  • a limit answered start-a-lap consumes the change
Diagnostics
  • Instance-mark-log
  • Instance-operation-record
an exact landing does not count as reached

exact-landing-must-pass

scenarioonce

Applies when Exact landing is Must pass the line.

For Instance, touching a line or consuming limit is not enough. It becomes reached only after the stored or tested path passes strictly beyond it.

Given

Instance on the unreached side of a declared line or consuming limit, at a line or band that declares no counts-at-line of its own

When
  • one change lands exactly on that position and a later change passes it
Then
  • the exact landing does not count as reached
  • the later movement strictly past the position is the first movement that may report or consume
Diagnostics
  • Instance-mark-log
  • Instance-operation-record
excess stops at the ceiling

ceiling-stops-change

scenarioonce

Applies when At the ceiling is Stop at the ceiling.

A rising change that overshoots Value cite max leaves Instance exactly on that edge. The excess is lost and reported to no one. This test restates neither number.

Given

Instance holding any value at or below Value cite max

When
  • an imposed rising change would take Instance above Value cite max
Then
  • the stored value is exactly Value cite max
  • the excess is discarded and reported to no one
  • the change otherwise happened
Diagnostics
  • Instance-value-after
  • Instance-edge-record
excess stops at the floor

floor-stops-change

scenarioonce

Applies when At the floor is Stop at the floor.

A falling change that undershoots Value cite min leaves Instance exactly on that edge. The shortfall is lost and reported to no one. This test restates neither number.

Given

Instance holding any value at or above Value cite min

When
  • an imposed falling change would take Instance below Value cite min
Then
  • the stored value is exactly Value cite min
  • the shortfall is discarded and reported to no one
Diagnostics
  • Instance-value-after
  • Instance-edge-record
an overshooting change is refused whole at the ceiling

ceiling-refuses-change

scenarioonce

Applies when At the ceiling is Refuse the whole change.

A change that would carry Instance above Value cite max is refused whole and the refusal is reported to the caller. Value and residue stay as they were, and no mark reports, not even partway to the edge.

Given

Instance holding stored value v and, when present, residue r

When
  • an imposed rising change would take Instance above Value cite max
Then
  • the change is refused and the stored value remains v
  • residue remains r
  • no mark reports
  • the refusal is reported to the caller
Diagnostics
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-refusal-record
an undershooting change is refused whole at the floor

floor-refuses-change

scenarioonce

Applies when At the floor is Refuse the whole change.

A change that would carry Instance below Value cite min is refused whole and the refusal is reported to the caller. Value and residue stay as they were, and no mark reports, not even partway to the edge.

Given

Instance holding stored value v and, when present, residue r

When
  • an imposed falling change would take Instance below Value cite min
Then
  • the change is refused and the stored value remains v
  • residue remains r
  • no mark reports
  • the refusal is reported to the caller
Diagnostics
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-refusal-record
ceiling excess is handed back

ceiling-returns-extra

scenarioonce

Applies when At the ceiling is Hand back the extra.

A caller's rising change fills Instance to Value cite max and receives the positive extra that did not fit. This contract does not route it. The same change with nobody acting has no caller, so its extra is dropped.

Given

Instance holding v with positive room h below Value cite max

When
  • a caller applies rising change d greater than h, and the same change is also run with nobody acting
Then
  • the stored value is exactly Value cite max
  • the caller receives positive extra d minus h
  • the operation with nobody acting has no caller, so the same extra is dropped
Diagnostics
  • Instance-value-after
  • Instance-returned-extra
floor shortfall is handed back

floor-returns-extra

scenarioonce

Applies when At the floor is Hand back the extra.

A caller's falling change empties Instance to Value cite min and receives the positive shortfall that did not fit. This contract does not route it. The same change with nobody acting has no caller, so its shortfall is dropped.

Given

Instance holding v with positive room h above Value cite min

When
  • a caller applies falling change of magnitude d greater than h, and the same change is also run with nobody acting
Then
  • the stored value is exactly Value cite min
  • the caller receives positive shortfall d minus h
  • the operation with nobody acting has no caller, so the same shortfall is dropped
Diagnostics
  • Instance-value-after
  • Instance-returned-extra
the ceiling does not hold the value down

ceiling-is-landmark

scenarioonce

Applies when At the ceiling is No ceiling.

The value at Value cite max does not hold Instance down. A rising change passes it in full; the top remains a citable landmark and still defines shares.

Given

Instance holding v

When
  • a rising change d makes v plus d exceed Value cite max
Then
  • the stored value is exactly v plus the change, resolved as this value's number-kind directs — through its small-change answer where that question is asked — with no limit applied
  • nothing is stopped, refused, returned, or lapped
  • Value cite max remains a citable landmark and still defines shares
Diagnostics
  • Instance-value-after
  • Instance-mark-log
the floor does not hold the value up

floor-is-landmark

scenarioonce

Applies when At the floor is No floor.

The value at Value cite min does not hold Instance up. A falling change passes it in full; the bottom remains a citable landmark.

Given

Instance holding v

When
  • a falling change d makes v plus d fall below Value cite min
Then
  • the stored value is exactly v plus the change, resolved as this value's number-kind directs — through its small-change answer where that question is asked — with no limit applied
  • nothing is stopped, refused, returned, or lapped
  • Value cite min remains a citable landmark
Diagnostics
  • Instance-value-after
  • Instance-mark-log
reaching the ceiling starts a lap

ceiling-starts-lap

scenarioonce

Applies when At the ceiling is Start a lap.

When a rising change consumes Value cite max, Instance reports outward marks, then the lap, then any marks on the leg to Value cite lap lands on. The reports keep one operation id and distinguish their legs. This test restates neither position.

Given

Instance below Value cite max, with the armed marks this adoption can place on the outward and lap legs and an operation record carrying before, after, direction, leg position, operation id, and lap count

When
  • one rising change reaches Value cite max as exact-landing directs
Then
  • the outward leg ends at the consuming ceiling
  • outward marks report first, as this value's jumped-lines answer directs, then the lap
  • after the lap report, cited limits are read fresh
  • where either cited limit moved, any limit-moved band report occurs before the lap leg
  • a limit move never repositions the value during the lap loop
  • the lap leg stores Value cite lap lands on and any marks on it report after the lap
  • all reports retain the originating operation id and distinguish leg position
Diagnostics
  • Instance-operation-record
  • Instance-lap-log
  • Instance-mark-log
reaching the floor starts a lap

floor-starts-lap

scenarioonce

Applies when At the floor is Start a lap.

When a falling change consumes Value cite min, Instance reports outward marks, then the lap, then any marks on the leg to Value cite lap lands on. The reports keep one operation id and distinguish their legs. This test restates neither position.

Given

Instance above Value cite min, with the armed marks this adoption can place on the outward and lap legs and an operation record carrying before, after, direction, leg position, operation id, and lap count

When
  • one falling change reaches Value cite min as exact-landing directs
Then
  • the outward leg ends at the consuming floor
  • outward marks report first, as this value's jumped-lines answer directs, then the lap
  • after the lap report, cited limits are read fresh
  • where either cited limit moved, any limit-moved band report occurs before the lap leg
  • a limit move never repositions the value during the lap loop
  • the lap leg stores Value cite lap lands on and any marks on it report after the lap
  • all reports retain the originating operation id and distinguish leg position
Diagnostics
  • Instance-operation-record
  • Instance-lap-log
  • Instance-mark-log
extra continues after a lap

lap-carries-extra

scenarioonce

Applies when The extra after a lap is Carry it onto the new value.

After a lap, Instance carries the leftover onto the new value. It settles as another leg in the original direction, from step 1, under the originating operation id.

Given

a change whose movement continues past a consuming limit

When
  • Instance reports its first lap
Then
  • the leftover past the consuming limit is applied after the lap movement, in the original direction
  • that leg returns to settlement step 1, keeps the originating operation id, and tests its own marks
Diagnostics
  • Instance-operation-record
  • Instance-lap-log
extra is dropped after a lap

lap-drops-extra

scenarioonce

Applies when The extra after a lap is Drop it.

After one lap, Instance drops the leftover. It is reported to no one and produces no further leg.

Given

a change whose movement continues past a consuming limit

When
  • Instance reports its first lap
Then
  • the leftover is discarded after that lap
  • it is reported to no one and causes no further leg or lap
Diagnostics
  • Instance-operation-record
  • Instance-lap-log
carried extra laps again up to the runtime cap

lap-repeats-with-cap

scenarioonce

Applies when More than one lap is Lap again while it fits.

Carried leftover may lap Instance again while it fits, but one originating operation settles at most 32 laps. Before lap 33, continuation is rejected, lap-cap-reached records the state committed by lap 32, and the remaining leftover is dropped.

Given

carried leftover large enough to reach the same consuming limit repeatedly, including a run that would require a thirty-third lap

When
  • the originating change settles
Then
  • Instance reports another lap whenever the carried leftover reaches the limit
  • at most 32 laps settle for the originating operation
  • before lap 33 continuation is rejected, lap-cap-reached reports with the state committed by lap 32, and all remaining leftover is dropped
Diagnostics
  • Instance-lap-log
  • Instance-lap-cap-reached
  • Instance-value-after
one change causes at most one lap

lap-stops-after-one

scenarioonce

Applies when More than one lap is One lap per change and The extra after a lap is Carry it onto the new value.

One originating change can report only one lap. A second reach of the same consuming limit is stored without consuming, and further excess is dropped.

Given

a change with carried leftover large enough to reach the same consuming limit a second time

When
  • the originating change settles
Then
  • exactly one lap reports
  • the second reach is stored without consuming
  • further excess is dropped
Diagnostics
  • Instance-lap-log
  • Instance-value-after
one change drops leftover after its only lap

lap-stops-after-one-and-drops

scenarioonce

Applies when More than one lap is One lap per change and The extra after a lap is Drop it.

One originating change reports exactly one lap. Because this adoption drops leftover, that leftover is reported to no one and cannot cause a second consumption.

Given

a change with leftover beyond a consuming limit and enough amount to reach that limit again if the leftover were carried

When
  • the originating change settles
Then
  • exactly one lap reports
  • the leftover is dropped and reported to no one
  • no second consumption occurs
Diagnostics
  • Instance-lap-log
  • Instance-operation-record
  • Instance-value-after
a lap clears saved residue

lap-clears-residue

scenarioonce

Applies when A lap clears saved fraction is Clear it.

A lap clears Instance residue once the consuming movement commits and, where leftover is carried, before that leftover is resolved.

Given

Instance holding nonzero signed residue before a consuming movement

When
  • the movement commits and reports a lap
Then
  • residue is zero once the consuming movement commits, and where leftover is carried, before that leftover is resolved
Diagnostics
  • Instance-residue-trace
  • Instance-lap-log
a lap keeps saved residue

lap-keeps-residue

scenarioonce

Applies when A lap clears saved fraction is Keep it.

Residue is unchanged by the Instance lap itself, measured immediately after the lap movement and before any carried leftover settles.

Given

Instance holding nonzero signed residue before a consuming movement

When
  • the movement commits and reports a lap
Then
  • residue is unchanged by the lap itself, measured immediately after the lap movement and before any carried leftover settles
Diagnostics
  • Instance-residue-before-after
  • Instance-lap-log
the Row.id line fires on crossing

line-crosses-fixed-position

scenarioper lines row

Applies when row value kind is Number.

The Row.id line uses Bind position phrase. A Bind movement direction reports when its reached state changes from false to true, provided the line is armed and has allowance. Its declared starting arm state applies; omission means armed.

Given

Instance holding a value on the unreached side of Row.id at Bind position phrase, with the line in its declared starting arm state; omission of starts-armed means armed

When
  • one Bind movement direction changes Row.id from unreached to reached
Then
  • Row.id reports exactly once if it is armed and still has allowance
  • the report carries before, after, direction, leg position, operation id, and row id
  • reached state is recomputed from the stored endpoint in both directions
Diagnostics
  • Instance-mark-log
  • Instance-line-state
  • Instance-value-before-after
the Row.id line follows and fires at its cited position

line-crosses-cited-position

scenarioper lines row

Applies when row value kind is Citation.

The Row.id line uses Bind position phrase, with Row.value key read fresh whenever it is compared. A Bind movement direction reports when reached state changes from false to true, provided the line is armed and has allowance. Its declared starting arm state applies; omission means armed. The test names the address and restates no number.

Given

Instance holding a value on the unreached side of Row.id at Bind position phrase, with the line in its declared starting arm state and the cited number recorded before comparison; omission of starts-armed means armed

When
  • one Bind movement direction changes Row.id from unreached to reached
Then
  • Row.value key is read fresh for the comparison and this test restates no number
  • Row.id reports exactly once if it still has allowance
  • the report carries before, after, direction, leg position, operation id, and row id
Diagnostics
  • Instance-comparison-log
  • Instance-mark-log
  • Instance-line-state
the Row.id line is a share of the ceiling

line-uses-ceiling-share

scenarioper lines row

Applies when row line unit is Share of the ceiling.

Row.id states a share rather than an absolute position. Its line follows that share of Value cite max, read fresh at comparison time; this test restates neither number.

Given

the marked top at Value cite max recorded before comparison and Row.id armed

When
  • a Bind movement direction crosses the share declared by Row.id
Then
  • the line position is the row's declared share multiplied by the fresh value at Value cite max
  • the position may be fractional; it is compared, never stored
  • the crossing reports once if allowance remains
Diagnostics
  • Instance-comparison-log
  • Instance-mark-log
Row.id uses its own exact-landing answer

line-exact-landing-override

scenarioper lines row

Applies when row counts at line is At the line counts or Must pass the line.

The Row.id row overrides the value-wide exact-landing choice. Its at-the-line-counts answer makes an exact landing reach the line; its must-pass-the-line answer requires movement strictly past it.

Given

Row.id armed and unreached in its reporting direction

When
  • one movement lands exactly on Row.id and another strictly passes it
Then
  • where this row declares at-the-line-counts, an exact landing counts as reaching the line
  • where this row declares must-pass-the-line, an exact landing does not reach the line and the movement must pass it
  • the row's declared answer overrides Instance's value-wide exact-landing answer
Diagnostics
  • Instance-mark-log
  • Instance-line-state
Row.id fires again on each crossing

line-refires-every-crossing

scenarioper lines row

Applies when row refire is Every crossing.

For Row.id, each leg whose reached state for a reported direction goes false to true fires exactly one report, while a true-to-false leg reports nothing. Bind sequence result.

Given

Row.id armed and unreached

When
  • Instance crosses Row.id in a reporting direction, returns to unreached, and crosses again
Then
  • each leg whose reached state for a reported direction goes false to true fires exactly one report for that leg, and a leg whose transition is true to false reports nothing
  • Bind sequence result
Diagnostics
  • Instance-mark-log
  • Instance-line-state
Row.id keeps separate reached state for both directions

line-both-directions-keep-state

scenarioper lines row

Applies when row direction is Both.

A both-direction line keeps one reached state per direction. In a cross-down, cross-up, cross-down sequence, each qualifying false-to-true transition reports while refire allowance remains; one shared state is not legal.

Given

Row.id armed with allowance and its rising and falling reached states recorded separately

When
  • Instance crosses Row.id down, up, and down again
Then
  • each direction keeps its own reached state
  • each qualifying false-to-true transition in either direction reports while the line's refire allowance remains
  • no shared single reached state is legal
Diagnostics
  • Instance-crossing-log
  • Instance-mark-log
  • Instance-line-state
Row.id fires once, then waits to re-arm

line-fires-once-per-arm

scenarioper lines row

Applies when row refire is Once and row rearm is On reset or On event or After a wait.

Row.id reports once per arm. Across two crossings without re-arming, only the first reports. Its re-arm rule is: Bind rearm phrase.

Given

Row.id armed with its full allowance

When
  • Instance makes two qualifying crossings without re-arming, then Bind rearm phrase
Then
  • only the first crossing reports before re-arming
  • after the declared re-arm, the next qualifying crossing reports once again
Diagnostics
  • Instance-mark-log
  • Instance-line-allowance
Row.id fires its declared number of times per arm

line-fires-set-number

scenarioper lines row

Applies when row refire is A set number of times and row rearm is On reset or On event or After a wait.

Row.id may report Row.times times per arm. Further qualifying crossings stay silent until Bind rearm phrase restores the full allowance.

Given

Row.id armed with a fresh allowance of Row.times

When
  • Instance makes more than Row.times qualifying crossings without re-arming, then reaches Bind rearm phrase
Then
  • exactly Row.times crossings report before the allowance is exhausted
  • the declared re-arm restores the full allowance of Row.times
Diagnostics
  • Instance-mark-log
  • Instance-line-allowance
Row.id handles another crossing during its re-arm wait

line-wait-rearm-repeat

scenarioper lines row

Applies when row rearm is After a wait.

While Row.id waits to re-arm under Row.rearm declared in, another crossing Bind repeat phrase. The test names the wait address and restates no duration.

Given

Row.id waiting to re-arm under Row.rearm declared in

When
  • another qualifying crossing occurs before the wait finishes
Then
  • the new crossing Bind repeat phrase
  • the line remains unable to exceed its current allowance until the resulting wait completes
Diagnostics
  • Instance-line-wait
  • Instance-line-allowance
a move crossing several marks reports as declared

jumped-lines-reports

scenarioonce

Applies when Jumped lines is All in order or Only the nearest.

When one leg of Instance crosses several marks, Bind report phrase. Bind state phrase. A crossed band edge updates its band state under both answers whether or not its report is selected. If this adoption has fewer than two marks, it has no multi-mark case to run.

Given

one leg that crosses at least two armed bare lines or band edges with allowance; an adoption with fewer than two marks has no multi-mark case and this scenario is vacuous

When
  • the leg settles
Then
  • Bind report phrase
  • Bind state phrase
  • a band edge crossed on the leg updates its band state under both answers, whether or not its report is the selected one
Diagnostics
  • Instance-mark-log
  • Instance-mark-state
marks read the final value at an edge

marks-read-final-value

scenarioonce

Applies when Lines read is The final value.

When a change passes a limit, Instance marks read the final outward endpoint: the stored value, or the consuming limit on a lap. A mark at or past the reached limit never observes the raw candidate, and every report from that leg carries the stored endpoint or consuming limit as its after value.

Given

a change whose raw candidate passes a limit and a mark at or past the limit the change reaches

When
  • the change settles without refusal
Then
  • outward marks test the stored endpoint or the consuming limit
  • no outward mark observes a number beyond the limit
  • every report from that leg carries the stored endpoint, or the consuming limit, as its after value — never the raw candidate
Diagnostics
  • Instance-operation-record
  • Instance-mark-log
marks read the raw result at an edge

marks-read-raw-result

scenarioonce

Applies when Lines read is The raw result.

When a change passes a limit, Instance marks on the outward leg read the raw candidate and report it as after. Refusal exposes no raw result; lap and leftover legs read stored endpoints.

Given

a change whose raw candidate passes a limit and a mark that only that candidate reaches

When
  • the change settles without refusal
Then
  • outward marks test the raw candidate before the edge handles it
  • their reports use that tested candidate as after
  • a refused change exposes no raw result, and lap and leftover legs test stored endpoints
Diagnostics
  • Instance-operation-record
  • Instance-mark-log
the Row.id band enters at its fixed line

band-enters-at-fixed-line

scenarioper bands row

Applies when row enter on is Line and row enter value kind is Number.

Row.id enters when a Row.enter direction leg reaches the entering line at Row.enter value, read as its enter-unit directs — the declared number itself unless the row declares share-of-the-ceiling, where it is that share of the fresh value at Value cite max. It reports the state change subject to the value's jumped-lines answer.

Given

Row.id out and Instance on the non-entered side of the entering line at Row.enter value, read as its enter-unit directs — the declared number itself unless the row declares share-of-the-ceiling, where it is that share of the fresh value at Value cite max

When
  • one Row.enter direction leg changes the entering edge from unreached to reached
Then
  • Row.id enters and reports once, subject to jumped-lines
  • the report carries the row id and operation evidence
Diagnostics
  • Instance-band-state
  • Instance-mark-log
the Row.id band enters at its cited line

band-enters-at-cited-line

scenarioper bands row

Applies when row enter on is Line and row enter value kind is Citation.

Row.id enters when a Row.enter direction leg reaches the cited entering line Row.enter value key, read fresh. The test names the address and restates no number.

Given

Row.id out and Instance on the non-entered side of the cited entering line Row.enter value key

When
  • one Row.enter direction leg changes the entering edge from unreached to reached
Then
  • Row.enter value key is read fresh and this test restates no number
  • Row.id enters and reports once, subject to jumped-lines
Diagnostics
  • Instance-band-state
  • Instance-comparison-log
  • Instance-mark-log
the Row.id band leaves at its fixed line

band-leaves-at-fixed-line

scenarioper bands row

Applies when row leave on is Line and row leave value kind is Number.

Row.id leaves when a Row.leave direction leg reaches the leaving line at Row.leave value, read as its leave-unit directs — the declared number itself unless the row declares share-of-the-ceiling, where it is that share of the fresh value at Value cite max.

Given

Row.id in and Instance on the non-leaving side of the leaving line at Row.leave value, read as its leave-unit directs — the declared number itself unless the row declares share-of-the-ceiling, where it is that share of the fresh value at Value cite max

When
  • one Row.leave direction leg changes the leaving edge from unreached to reached
Then
  • Row.id leaves and reports once, subject to jumped-lines
Diagnostics
  • Instance-band-state
  • Instance-mark-log
the Row.id band leaves at its cited line

band-leaves-at-cited-line

scenarioper bands row

Applies when row leave on is Line and row leave value kind is Citation.

Row.id leaves when a Row.leave direction leg reaches the cited leaving line Row.leave value key, read fresh. The test names the address and restates no number.

Given

Row.id in and Instance on the non-leaving side of the cited leaving line Row.leave value key

When
  • one Row.leave direction leg changes the leaving edge from unreached to reached
Then
  • Row.leave value key is read fresh and this test restates no number
  • Row.id leaves and reports once, subject to jumped-lines
Diagnostics
  • Instance-band-state
  • Instance-comparison-log
  • Instance-mark-log
the Row.id band enters on its event

band-event-enters

scenarioper bands row

Applies when row enter on is Event.

The event at Row.enter declared in turns Row.id on. This event edge is not inferred from the held number.

Given

Row.id out

When
  • the event at Row.enter declared in occurs
Then
  • Row.id enters and records that event as its cause
Diagnostics
  • Instance-band-state
  • Instance-band-event-record
the Row.id band leaves on its declared event or wait

band-event-or-wait-leaves

scenarioper bands row

Applies when row leave on is Event or After a wait.

Row.id leaves when Bind leave phrase. Its state is controlled by that declared edge, not inferred from the held number.

Given

Row.id in

When
  • Bind leave phrase
Then
  • Row.id leaves and records the declared cause
Diagnostics
  • Instance-band-state
  • Instance-band-event-record
the Row.id band handles another entry during its wait

band-wait-repeat

scenarioper bands row

Applies when row leave on is After a wait.

While Row.id waits to leave, another entry Bind repeat phrase. The wait address is Row.leave declared in; this test restates no duration.

Given

Row.id in with the wait at Row.leave declared in running

When
  • its entering edge occurs again before the wait finishes
Then
  • the new entry Bind repeat phrase
  • Row.id remains in until the resulting wait completes
Diagnostics
  • Instance-band-state
  • Instance-band-wait
the Row.id band starts as declared

band-starts-as-declared

scenarioper bands row

Applies when row starts is In or Out.

At creation, Row.id Bind start phrase and reports nothing. The starting value is cited at Value cite initial; this test restates no number.

Given

creation of Instance at Value cite initial

When
  • the initial band state is stored
Then
  • Row.id Bind start phrase
  • creation reports no mark
Diagnostics
  • Instance-band-state
  • Instance-mark-log
the Row.id band reads its starting state from the initial value

band-starts-from-initial

scenarioper bands row

Applies when row starts is Read from initial and row enter on is Line and row leave on is Line.

At creation, Row.id reads Value cite initial against both its line edges: in exactly when the entering side holds and the leaving side does not. Creation reports nothing. An event-edged band that answers read-from-initial starts out; the event-entered case is checked by its own template.

Given

creation of Instance at Value cite initial, with the line geometry for Row.id recorded

When
  • the initial band state is stored
Then
  • Row.id starts in exactly when Value cite initial sits on the reached side of its entering edge and not on the reached side of its leaving edge, each per that edge's declared direction
  • creation reports no mark
Diagnostics
  • Instance-band-state
  • Instance-comparison-log
  • Instance-mark-log
the event-entered Row.id band starts out

event-entered-band-starts-out

scenarioper bands row

Applies when row starts is Read from initial and row enter on is Event.

An event-edged band that answers read-from-initial starts out; Row.id enters by an event, so there is no line geometry to read against the starting value. Creation reports nothing.

Given

creation of Instance with the Row.id entering event not yet observed

When
  • the initial band state is stored
Then
  • Row.id starts out: an event-edged band that answers read-from-initial starts out
  • creation reports no mark
Diagnostics
  • Instance-band-state
  • Instance-mark-log
the event-left Row.id band starts out

event-left-band-starts-out

scenarioper bands row

Applies when row starts is Read from initial and row leave on is Event or After a wait.

Row.id leaves by an event or a wait, so it is event-edged whatever its entering edge, and an event-edged band that answers read-from-initial starts out. Creation reports nothing. Together with the event-entered template this covers every event-edged shape.

Given

creation of Instance where Row.id leaves by an event or a wait

When
  • the initial band state is stored
Then
  • Row.id starts out: a band with any event or wait edge is event-edged, and an event-edged band that answers read-from-initial starts out
  • creation reports no mark
Diagnostics
  • Instance-band-state
  • Instance-mark-log
the Row.id band blocks its selected movements

band-blocks-selected-movement

scenarioper bands row

Applies when row blocks change is Blocks rises or Blocks falls or Blocks all.

While Row.id is in, blocks-rises blocks rising imposed changes, costs, and drifts; blocks-falls blocks falling ones; blocks-all blocks both directions — each as far as this adoption can construct the attempt. Blocking happens before settlement, and a blocked drift records the block but has no receiver. Each set, reset, limit move, and lap movement this adoption can construct settles unblocked; if it can construct none, that clause asserts nothing.

Given

Row.id in

When
  • of the movements this adoption can construct: where this row answers blocks-rises, a rising change, cost, and drift are each attempted; where it answers blocks-falls, a falling change, cost, and drift are each attempted; where it answers blocks-all, changes, costs, and drifts are attempted in both directions; a movement kind this adoption cannot construct asserts nothing here
  • each of a set, a reset, a limit move, and a lap movement that this adoption can construct settles; an adoption that can construct none of them asserts nothing here
Then
  • each attempted selected imposed change, cost, and drift is discarded before fractional handling and records blocked
  • a blocked drift has no receiver and contributes nothing to a composed batch
  • each of a set, a reset, a limit move, and a lap movement that this adoption can construct settles unblocked; an adoption that can construct none of them asserts nothing here
Diagnostics
  • Instance-blocked-record
  • Instance-operation-record
the event-entered Row.id band keeps state through silent recomputes

event-entered-band-survives-silent-recompute

scenarioper bands row

Applies when row enter on is Event.

Because Row.id has an event entering edge, each silent recompute this adoption can perform — a silent set, a reset declaring recompute-from-target, or a cited limit move — preserves its state. Where none can be performed, this test asserts nothing. The band stays in until its own leaving edge occurs.

Given

Row.id in after the event at Row.enter declared in

When
  • each silent recompute this adoption can perform — a set whose value answers does-a-set-fire-lines with silent, a reset row declaring recompute-from-target, a limit move on a cited limit — settles; where the adoption can perform none, this test asserts nothing
Then
  • Row.id remains in unless its own leaving edge occurs
Diagnostics
  • Instance-band-state
  • Instance-operation-record
the event-edged Row.id band keeps state through silent recomputes

event-left-band-survives-silent-recompute

scenarioper bands row

Applies when row leave on is Event or After a wait.

Because Row.id has an event or wait leaving edge, each silent recompute this adoption can perform — a silent set, a reset declaring recompute-from-target, or a cited limit move — preserves its state. Where none can be performed, this test asserts nothing. Only its declared edges change it.

Given

Row.id in a known state before recomputation

When
  • each silent recompute this adoption can perform — a set whose value answers does-a-set-fire-lines with silent, a reset row declaring recompute-from-target, a limit move on a cited limit — settles; where the adoption can perform none, this test asserts nothing
Then
  • Row.id keeps its prior state through every recompute
Diagnostics
  • Instance-band-state
  • Instance-operation-record
Row.id fires once and never re-arms

line-once-never-rearms

scenarioper lines row

Applies when row refire is Once and row rearm is Never.

Row.id reports on its first qualifying crossing and never re-arms. Later crossings still update reached state but do not report.

Given

Row.id armed with its fresh allowance

When
  • Instance makes two or more qualifying crossings over the run
Then
  • only the first crossing reports
  • no event or passage of time restores its allowance
Diagnostics
  • Instance-mark-log
  • Instance-line-allowance
Row.id has one fixed lifetime allowance

line-set-number-never-rearms

scenarioper lines row

Applies when row refire is A set number of times and row rearm is Never.

Row.id has a lifetime allowance of Row.times reports. It never re-arms after that allowance is exhausted.

Given

Row.id armed with lifetime allowance Row.times

When
  • Instance makes more than Row.times qualifying crossings over the run
Then
  • exactly Row.times crossings report
  • the exhausted allowance is never restored
Diagnostics
  • Instance-mark-log
  • Instance-line-allowance
Row.id uses its explicit starting arm state

line-starts-armed-as-declared

scenarioper lines row

Applies when row starts armed is Armed or Disarmed.

A Row.id row that explicitly starts armed can report its first qualifying crossing if it has allowance. A row that explicitly starts disarmed Bind disarmed phrase. When starts-armed is omitted, line-crosses-fixed-position and line-crosses-cited-position check the default armed state.

Given

creation of Instance with Row.id declaring an explicit starting arm state

When
  • the first qualifying crossing occurs
Then
  • a row that explicitly starts armed can report its first qualifying crossing if it has allowance
  • a row that explicitly starts disarmed Bind disarmed phrase
  • creation itself reports nothing
Diagnostics
  • Instance-line-allowance
  • Instance-mark-log
the Row.id entering line is a share of the ceiling

band-enter-share-follows-ceiling

scenarioper bands row

Applies when row enter unit is Share of the ceiling.

Row.id places its entering line at a declared share of Value cite max, read fresh for the comparison. This test restates neither number.

Given

Row.id out and the marked top at Value cite max recorded before comparison

When
  • a movement crosses the entering share declared by the row
Then
  • the entering position is the row's share multiplied by the fresh value at Value cite max
  • the entering position may be fractional; it is compared, never stored
  • Row.id enters if the directional reached state changes
Diagnostics
  • Instance-comparison-log
  • Instance-band-state
the Row.id leaving line is a share of the ceiling

band-leave-share-follows-ceiling

scenarioper bands row

Applies when row leave unit is Share of the ceiling.

Row.id places its leaving line at a declared share of Value cite max, read fresh for the comparison. This test restates neither number.

Given

Row.id in and the marked top at Value cite max recorded before comparison

When
  • a movement crosses the leaving share declared by the row
Then
  • the leaving position is the row's share multiplied by the fresh value at Value cite max
  • the leaving position may be fractional; it is compared, never stored
  • Row.id leaves if the directional reached state changes
Diagnostics
  • Instance-comparison-log
  • Instance-band-state
Row.id uses its own exact-landing answer

band-exact-landing-override

scenarioper bands row

Applies when row counts at line is At the line counts or Must pass the line.

The Row.id row overrides the value-wide exact-landing choice for each line edge this row has (a band may have only one). Its at-the-line-counts answer counts an exact landing; its must-pass-the-line answer requires movement strictly past the edge.

Given

Row.id once approaching each line edge this row has (a band may have only one)

When
  • one movement lands exactly on an edge and another strictly passes it
Then
  • where this row declares at-the-line-counts, an exact landing counts as reaching each line edge this row has (a band may have only one)
  • where this row declares must-pass-the-line, an exact landing does not reach a line edge and the movement must pass it
  • the row's declared answer overrides Instance's value-wide exact-landing answer
Diagnostics
  • Instance-band-state
  • Instance-mark-log
the Row.id set stores its target without a raw result

set-stores-target-without-raw-result

scenarioper sets row

Applies for every adoption

Row.id reads Bind mode phrase at Row.target key when Row.trigger declared in offers it. A set with a declared enabling condition is offered only while that condition holds. Bind settlement phrase: it has no raw result and does not pass through small-change. This test names the addresses and restates no number.

Given

Row.id enabled, with target source Row.target key and trigger Row.trigger declared in

When
  • the trigger offers Bind mode phrase
Then
  • a set with a declared enabling condition is offered only while that condition holds
  • Bind settlement phrase
  • the set has no raw result and marks can observe only its successful stored outcome
  • fractional small-change handling is not applied
Diagnostics
  • Instance-set-record
  • Instance-value-before-after
an outside set stores the nearer limit

outside-set-clamps

scenarioonce

Applies when A set outside the range is Pull it to the nearer limit.

A set outside the range stores the nearer passed limit. It exposes no rejected target as a raw result, hands back no extra, and starts no lap. The limits are Value cite min and Value cite max; this test restates neither number. Where no declared set can target outside the range, it asserts nothing.

Given

named sets targeting once above Value cite max and once below Value cite min, where this adoption's declared sets can construct such targets; an adoption whose sets can never target outside the range asserts nothing here

When
  • each set settles
Then
  • the high target stores exactly Value cite max and the low target stores exactly Value cite min
  • neither rejected target is a raw result
  • the set returns no extra and starts no lap
Diagnostics
  • Instance-set-record
  • Instance-value-after
an outside set is refused whole

outside-set-refuses

scenarioonce

Applies when A set outside the range is Refuse the set.

A set outside the range is refused whole. Instance keeps its value and residue, and no mark fires. The test cites Value cite min and Value cite max and restates neither number.

Given

Instance holding value v and, when present, residue r; a named set targets outside Value cite min and Value cite max

When
  • the set is offered
Then
  • the set is refused to its caller
  • the stored value remains v and residue remains r
  • no mark reports or changes state from movement
Diagnostics
  • Instance-set-record
  • Instance-value-before-after
  • Instance-residue-before-after
an outside set stores its target as sent

outside-set-stores-as-sent

scenarioonce

Applies when A set outside the range is Store it as sent.

An outside set stores its target exactly as sent, but only beyond an ordinary edge that allows Instance to pass. The target is the stored outcome, not a separate raw result.

Given

a named set whose target is beyond a limit whose ordinary edge answer allows the value to pass

When
  • the set settles
Then
  • the exact target is stored
  • the set exposes no separate raw result
Diagnostics
  • Instance-set-record
  • Instance-value-after
a successful set reports crossed marks

set-fires-marks-as-change

scenarioonce

Applies when Does a set fire lines is Treat it as a change.

A successful set tests marks along its stored movement and reports them as jumped-lines directs. Because a set crossing no line can store the same value under either answer, this test also reads the operation record that distinguishes mark testing from silent recompute.

Given

a named set whose accepted stored target crosses at least one mark, plus a set whose target crosses no mark, with an operation record distinguishing reports from silent state updates

When
  • each set settles
Then
  • crossed marks test the successful stored movement and report as jumped-lines directs
  • the operation record identifies this answer even when the absence of a crossing makes the stored result indistinguishable from a silent recompute
Diagnostics
  • Instance-set-record
  • Instance-mark-log
  • Instance-mark-state
a successful set recomputes marks without reports

set-updates-marks-silently

scenarioonce

Applies when Does a set fire lines is Silent.

A successful set silently recomputes bare lines and line-geometry bands from its stored target. Event-edged bands keep state and nothing reports. The operation record is required because a set crossing no line can leave the same stored value under either answer.

Given

a named set whose accepted stored target crosses marks, with an operation record naming silent recomputation

When
  • the set settles
Then
  • bare-line reached state and line-geometry band state recompute from the stored target
  • event-edged bands keep state and no mark reports
  • the operation record distinguishes silent recompute from treat-it-as-a-change even when no line was crossed
Diagnostics
  • Instance-set-record
  • Instance-mark-log
  • Instance-mark-state
the Row.id set clears residue when it succeeds

successful-set-clears-residue

scenarioper sets row

Applies when Small change is Save the fraction.

A successful Row.id set clears Instance residue in the same commit. The target comes from Row.target key; this test restates no number. A refused set leaves residue unchanged.

Given

Instance holding nonzero signed residue with Row.id enabled

When
  • Row.id successfully stores its target from Row.target key
Then
  • residue becomes zero in the same commit as the stored target
Diagnostics
  • Instance-set-record
  • Instance-residue-before-after
the affordable Row.id cost pays exactly

cost-pays-exactly

scenarioper costs row

Applies for every adoption

When affordable and unblocked, Row.id moves Instance Bind direction phrase by the amount at Row.amount key after small-change resolves it, updating residue accordingly. The report to Row.action declared in carries no refusal and no shortage. This test names the addresses and restates no number.

Given

Instance with enough room Bind direction phrase to pay the non-negative amount at Row.amount key, and with no active band blocking the change's direction

When
  • the action at Row.action declared in attempts Row.id
Then
  • the stored value moves Bind direction phrase by the amount at Row.amount key after small-change resolves it, and residue updates accordingly
  • the report to the action carries no refusal and no shortage
  • marks test the paid movement normally
Diagnostics
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-cost-record
  • Instance-mark-log
the value-wide cost answer refuses an unaffordable action

value-wide-cost-refuses

scenarioonce

Applies when Not enough room is Refuse the action.

For a cost row without an override, an unaffordable cost is refused whole. Movement and provisional residue are discarded together; value, residue, and every mark stay unchanged, and the caller receives the shortage.

Given

a cost row without an answer override, insufficient room for its full provisional movement, stored value v, residue r when present, and unchanged mark state m

When
  • the cost is attempted
Then
  • the action is refused with its positive shortage
  • movement and provisional residue are discarded together
  • stored value v, residue r, and all mark state m remain unchanged
Diagnostics
  • Instance-cost-record
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-mark-state
the value-wide cost answer takes what fits

value-wide-cost-takes-what-fits

scenarioonce

Applies when Not enough room is Take what fits.

For a cost row without an override, an unaffordable cost takes only what fits. Instance moves to the limiting edge, recomputes residue from the approved amount only, reports the positive amount paid, and tests marks normally.

Given

a cost row without an answer override and insufficient room for its full provisional movement

When
  • the cost is attempted
Then
  • the stored value moves to the limiting edge
  • movement and residue are recomputed from only the approved amount
  • the caller receives the positive amount paid and marks test that movement normally
Diagnostics
  • Instance-cost-record
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-mark-log
the Row.id override refuses an unaffordable action

cost-row-override-refuses

scenarioper costs row

Applies when Not enough room is Take what fits and row answer is Refuse the action.

Row.id overrides the value-wide cost answer. When it cannot be paid in full, it refuses the action at Row.action declared in, reports the shortage, and changes neither value nor residue.

Given

insufficient room to pay Row.id in full, with stored value v and residue r when present

When
  • the action at Row.action declared in attempts the amount at Row.amount key
Then
  • the row's refuse-the-action answer wins over the value-wide answer
  • the caller receives refusal and shortage
  • value, residue, and every mark remain unchanged
Diagnostics
  • Instance-cost-record
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-mark-state
the Row.id override takes what fits

cost-row-override-partial

scenarioper costs row

Applies when Not enough room is Refuse the action and row answer is Take what fits.

Row.id overrides the value-wide cost answer. When full payment does not fit, Instance moves to the limiting edge, recomputes residue from the approved part only, and reports the positive amount paid to Row.action declared in.

Given

insufficient room to pay Row.id in full

When
  • the action at Row.action declared in attempts the amount at Row.amount key
Then
  • the row's take-what-fits answer wins over the value-wide answer
  • Instance moves to the limiting edge and reports the positive amount paid
  • movement and residue are recomputed from only that approved amount
  • marks test that movement normally
Diagnostics
  • Instance-cost-record
  • Instance-value-before-after
  • Instance-residue-before-after
  • Instance-mark-log
Row.id moves the value on its own

drift-moves-value

scenarioper drifts row

Applies for every adoption

Instance changes on its own under Row.id. Each time Bind cadence phrase, its contribution is Bind resolution phrase, then clipped to Row.stops at key, so it Bind direction phrase by no more than Bind amount phrase. The amount and stop are stated at their addresses; this test restates neither number.

Given

Instance away from Row.stops at key, with Row.id eligible, every interrupt row for it allowing it, and no other drift eligible

When
  • Bind cadence phrase, with nobody acting
Then
  • the contribution is Bind resolution phrase, then clipped to Row.stops at key, so Instance Bind direction phrase by no more than Bind amount phrase
  • the operation commits once with no partly settled state observable
  • marks test the movement once
Diagnostics
  • Instance-value-before-after
  • Instance-drift-log
  • Instance-mark-log
Row.id accrues continuously from elapsed clock time

continuous-drift-uses-elapsed-time

scenarioper drifts row

Applies when row cadence is Per real second.

Row.id accrues continuously. It multiplies the rate at Row.step amount key by elapsed cited-clock time, not frame count, and sends fractional accrual through small-change. This test restates no rate.

Given

Row.id eligible over equal cited-clock durations rendered with different frame counts

When
  • each duration settles
Then
  • each contribution is the rate at Row.step amount key multiplied by elapsed cited-clock time
  • equal elapsed time produces equal provisional movement regardless of frame count
  • fractional accrual passes through small-change
Diagnostics
  • Instance-clock-trace
  • Instance-drift-log
Row.id runs only at its named moment

named-moment-drift-uses-citation

scenarioper drifts row

Applies when row cadence is At a named moment.

Row.id contributes only when the moment at Row.moment declared in occurs. Passing time alone does not run it.

Given

Row.id eligible before the moment at Row.moment declared in

When
  • time passes without that moment, then the named moment occurs
Then
  • Row.id contributes nothing before the moment
  • it contributes once when the cited moment occurs
Diagnostics
  • Instance-drift-log
  • Instance-event-log
Row.id uses its declared changing amount rule

declared-drift-amount-rule

scenarioper drifts row

Applies when row amount kind is Depends on state or Grows while it runs.

Row.id does not use one fixed contribution. It Bind shape phrase, with the base at Row.step amount key. The test names both addresses and restates neither number nor rule.

Given

Row.id eligible at two states or two points in its run for which Row.amount declared in gives different amounts

When
  • one contribution settles in each case
Then
  • each contribution Bind shape phrase
  • Row.step amount key supplies the declared base amount and this test restates neither the amount nor the rule
Diagnostics
  • Instance-drift-log
  • Instance-value-trace
Row.id stops where its row says it stops

drift-stops

scenarioper drifts row

Applies for every adoption

Both at-stop answers leave Instance stored at Row.stops at key, so the stored value cannot distinguish them. This probe reads the at-stop step record: Bind landing phrase. Once stored at that address, Row.id is ineligible and offers nothing. The test restates no stop or amount.

Given

Instance less than one Row.id contribution from Row.stops at key, Row.id eligible and alone, and an at-stop step record naming the offered amount, every intermediate value, the correction, and the stored value afterwards

When
  • the next offered contribution would pass Row.stops at key
Then
  • the step record names the amount offered before clipping or correction
  • Bind landing phrase
  • the stored value is exactly Row.stops at key under either answer
  • after an overshoot, correction reports no mark and recomputes reached state from the stored stop
  • Row.id is ineligible and offers nothing while the value rests at its stop
Diagnostics
  • Instance-at-stop-step-record
  • Instance-offered-amount
  • Instance-intermediate-value
  • Instance-value-after
Row.id clips at the consuming ceiling without lapping

drift-clips-at-consuming-ceiling

scenarioper drifts row

Applies when At the ceiling is Start a lap and row direction is Rises.

A Row.id contribution that reaches the consuming ceiling at Value cite max clips there without consuming it. It can report marks on that leg, but it never reports a lap. The test restates no limit.

Given

Row.id eligible below the consuming ceiling at Value cite max, with its offered contribution large enough to pass it, with Row.stops at key at or beyond Value cite max, so the ceiling is the binding stop

When
  • the drift settles alone
Then
  • the drift clips at Value cite max
  • no lap reports and no lap movement occurs
  • marks test the clipped drift leg normally
Diagnostics
  • Instance-drift-log
  • Instance-lap-log
  • Instance-mark-log
Row.id clips at the consuming floor without lapping

drift-clips-at-consuming-floor

scenarioper drifts row

Applies when At the floor is Start a lap and row direction is Falls.

A Row.id contribution that reaches the consuming floor at Value cite min clips there without consuming it. It can report marks on that leg, but it never reports a lap. The test restates no limit.

Given

Row.id eligible above the consuming floor at Value cite min, with its offered contribution large enough to pass it, with Row.stops at key at or below Value cite min, so the floor is the binding stop

When
  • the drift settles alone
Then
  • the drift clips at Value cite min
  • no lap reports and no lap movement occurs
  • marks test the clipped drift leg normally
Diagnostics
  • Instance-drift-log
  • Instance-lap-log
  • Instance-mark-log
Row.id approaches the anchor from either side

drift-approaches-anchor

scenarioper drifts row

Applies when row direction is Toward the anchor.

Row.id uses Value cite anchor only to choose its side: it rises below the anchor and falls above it. Eligibility and clipping use Row.stops at key; while stored at that stop the row is ineligible. Where the stop sits on a consuming limit, the drift clips there without consuming it.

Given

Instance once below and once above Value cite anchor, with Row.id eligible because the value is away from Row.stops at key, every interrupt row allowing it, and no other drift eligible

When
  • one contribution settles from each side
Then
  • the lower value rises below the anchor and the higher value falls above it, so the anchor chooses the side's direction
  • each contribution clips at Row.stops at key and never passes that stop
  • the row is ineligible while stored exactly at Row.stops at key
  • where the stop sits on a consuming limit, the drift clips there without consuming it
Diagnostics
  • Instance-drift-log
  • Instance-value-trace
eligible drifts add before one settlement

drifts-add-together

scenarioonce

Applies when Drifts together is Add them up.

When several Instance drifts run together, each eligible contribution clips to its own stop, then the signed amounts add. The combined movement resolves small-change and tests marks once.

Given

at least two eligible drifts at one step, after blocked rows are removed and each contribution is clipped to its own stop

When
  • the step settles
Then
  • the signed clipped contributions are summed
  • small-change resolves once and marks test once for the combined movement
Diagnostics
  • Instance-drift-batch-record
  • Instance-value-before-after
  • Instance-mark-log
only the largest eligible drift settles

largest-drift-wins

scenarioonce

Applies when Drifts together is Only the largest.

When several Instance drifts run together, only the largest clipped absolute contribution settles. Row order breaks a tie, and a skipped growing drift does not advance its ramp.

Given

at least two eligible drifts at one step, including equal clipped absolute magnitudes and a growing row that can be skipped

When
  • the step settles
Then
  • only the greatest clipped absolute magnitude settles
  • row order selects an exact tie
  • a skipped growing row does not advance its ramp for that step
Diagnostics
  • Instance-drift-batch-record
  • Instance-ramp-state
eligible drifts settle separately in row order

drifts-settle-in-row-order

scenarioonce

Applies when Drifts together is In row order.

When several Instance drifts run together, they settle separately in written row order. Each row sees the prior row's committed state and tests its own marks.

Given

at least two eligible drifts at one step whose separate settlements produce observable intermediate value or mark differences

When
  • the step settles
Then
  • each eligible row settles from block through report in written row order
  • each row sees the state committed by the prior row and tests marks separately
Diagnostics
  • Instance-drift-batch-record
  • Instance-value-trace
  • Instance-mark-log
Row.id controls its drift through a condition

condition-interrupt-controls-drift

scenarioper interrupts row

Applies when row kind is Off while condition or Runs only while condition.

Row.id Bind allow phrase, using the condition at Row.condition declared in. Every interrupt row naming Row.drift must allow it before that drift runs.

Given

the condition at Row.condition declared in observed once false and once true, with every other interrupt row for Row.drift allowing it

When
  • Row.drift reaches an occurrence in each condition state
Then
  • Row.id Bind allow phrase
  • the drift runs only when this row and every other row naming Row.drift allow it
Diagnostics
  • Instance-interrupt-state
  • Instance-drift-log
Row.id pauses its drift after an event

pause-interrupt-controls-drift

scenarioper interrupts row

Applies when row kind is Paused after event.

After Row.event declared in, Row.id pauses Row.drift and Bind length phrase. A repeated event Bind repeat phrase. Every row naming the drift must allow it before it resumes.

Given

Row.drift otherwise allowed by every interrupt row

When
  • the event at Row.event declared in occurs twice before the pause completes
Then
  • Row.id Bind length phrase and prevents Row.drift from running during the wait
  • the second event Bind repeat phrase
  • Row.drift runs again only after this and every other row naming it allow it
Diagnostics
  • Instance-interrupt-state
  • Instance-pause-record
  • Instance-drift-log
Row.id reads its state-dependent pause rule

state-dependent-pause-length

scenarioper interrupts row

Applies when row pause length kind is Depends on state.

Row.id reads the state-dependent pause rule at Row.pause length declared in, using the base at Row.pause length key. The test names both addresses and restates neither duration nor rule.

Given

two states for which Row.pause length declared in gives different pause lengths

When
  • the event at Row.event declared in starts Row.id in each state
Then
  • each wait follows Row.pause length declared in using the base at Row.pause length key
  • this test restates neither duration nor rule
Diagnostics
  • Instance-pause-record
  • Instance-interrupt-state
Row.id combines with every interrupt on its drift

interrupt-conjunction-holds

scenarioper interrupts row

Applies for every adoption

Even while Row.id allows Row.drift, another row for that drift can forbid it. The drift runs only when every row naming it allows it; where this adoption has no such pair, this test asserts nothing.

Given

another interrupt row naming Row.drift and currently forbidding it while Row.id allows it; where this adoption has no such pair, this test asserts nothing

When
  • the drift reaches an occurrence while those row states hold
Then
  • Row.drift does not run
  • every interrupt row for one drift must allow it before it runs
Diagnostics
  • Instance-interrupt-state
  • Instance-drift-log
the Row.id reset returns the value silently

reset-returns-silently

scenarioper resets row

Applies for every adoption

At Row.happens at, Row.id silently returns Instance to its named target, or to Value cite initial when sets-value-to-key is omitted (with a cited initial, the number read at creation). Where this adoption declares any line or band, crossing one on the return path reports nothing. The reset does not lap or pass through small-change.

Given

Instance away from the target used by Row.id

When
  • the moment at Row.happens at occurs
Then
  • Row.id stores its sets-value-to-key target when present, otherwise Value cite initial (with a cited initial, the number read at creation)
  • where this adoption declares any line or band, the return path crossing one reports nothing
  • the reset reports no lap
  • the return is one absolute repositioning and does not pass through small-change
Diagnostics
  • Instance-reset-record
  • Instance-value-after
  • Instance-mark-log
the Row.id reset handles residue as declared

reset-handles-residue

scenarioper resets row

Applies when Small change is Save the fraction.

When Row.id settles, it Bind residue phrase.

Given

Instance holding nonzero signed residue before Row.id

When
  • the reset at Row.happens at settles
Then
  • Row.id Bind residue phrase in the same silent commit
Diagnostics
  • Instance-reset-record
  • Instance-residue-before-after
the Row.id reset restores mark state as declared

reset-handles-lines-and-bands

scenarioper resets row

Applies for every adoption

Row.id Bind arm phrase. Band states respond as the row's resets-bands answer directs; a row that omits resets-bands keeps every band's state, which is this definition's documented default. All state changes are silent.

Given

changed line allowances and band states before Row.id

When
  • the reset at Row.happens at settles
Then
  • Row.id Bind arm phrase
  • band states respond as the row's resets-bands answer directs, and a row that omits resets-bands keeps every band's state — that omission is this definition's documented default
  • every line's reached state is recomputed and stored from the reset target
  • all state changes are silent
Diagnostics
  • Instance-reset-record
  • Instance-line-allowance
  • Instance-band-state
  • Instance-mark-log
the Row.id reset applies its explicit band choice

reset-applies-explicit-band-choice

scenarioper resets row

Applies when row resets bands is Return to starts or Recompute from target or Keep.

An explicit return-to-starts restores declared band starts; recompute-from-target recomputes line geometry and keeps event-edged bands; keep preserves every band's prior state unchanged. The presence gate prunes a row that omits resets-bands; the general reset template checks that omission's documented keep default.

Given

for return-to-starts, band states different from their declared starts; for recompute-from-target, line-geometry band states different from what the reset target would produce; for keep, a prior band state that differs from what both return-to-starts and recompute-from-target would produce, where this adoption can construct one; where it cannot, keep is checked only as no band state changing

When
  • the reset at Row.happens at settles
Then
  • where this row declares return-to-starts, it restores every band to its declared starts state
  • where this row declares recompute-from-target, it recomputes every line-geometry band from the reset target and keeps every event-edged band
  • where this row declares keep, it preserves every band's prior state unchanged
  • the change is silent
Diagnostics
  • Instance-reset-record
  • Instance-band-state
  • Instance-mark-log
a moving ceiling refills the value

limit-move-refills-ceiling

scenarioonce

Applies when When a limit moves is Refill to the new ceiling.

Where Value cite max is cited and moves, Instance fills to the fresh max. Where Value cite min is cited and moves alone, the held value stays unless it falls below the fresh min. An adoption citing only one limit exercises only that clause. A limit move never laps and never clears residue.

Given

Instance holding any value while each cited limit this adoption can move is exercised separately

When
  • each cited limit this adoption can move settles in its own case
Then
  • where Value cite max is a cited limit that moves, the fresh max is stored as the value
  • where Value cite min is cited and moves alone, the value is kept unless it falls below the fresh min
  • an adoption citing only one limit exercises only that clause
  • neither movement starts a lap and residue is unchanged
Diagnostics
  • Instance-limit-move-record
  • Instance-value-before-after
a moving limit keeps the held number when it fits

limit-move-keeps-number

scenarioonce

Applies when When a limit moves is Keep the number.

A moving limit leaves Instance's number alone while it fits. If it no longer fits, the value clamps to the moved limit even where an ordinary change could pass it. Residue stays and no lap starts.

Given

Instance holding values once inside and once outside the range made by a cited limit move

When
  • the limit move settles
Then
  • an inside value remains unchanged
  • an outside value clamps to the fresh limit it passed even if an ordinary change could pass that limit
  • residue is unchanged and no lap starts
Diagnostics
  • Instance-limit-move-record
  • Instance-value-before-after
a moving limit preserves the value's share

limit-move-keeps-share

scenarioonce

Applies when When a limit moves is Keep the share.

A moving limit keeps Instance at the same normalized share of Value cite min to Value cite max. Bind number phrase. An old range collapsed to nothing by cited limits uses the fresh min, though range-nonempty makes that unreachable for declared numbers. Residue is unchanged.

Given

Instance at a known normalized share immediately before a non-empty old range changes

When
  • the cited limit move settles
Then
  • one absolute repositioning stores the same normalized share in the new range
  • Bind number phrase
  • an old range collapsed to nothing by cited limits uses the fresh min; the declaration rule range-nonempty makes this unreachable for declared numbers
  • residue is unchanged
Diagnostics
  • Instance-limit-move-record
  • Instance-share-calculation
  • Instance-value-before-after
an outside value moves to its declared safe number

limit-move-uses-declared-number

scenarioonce

Applies when When a limit moves is Pull it to a declared number.

A limit move keeps Instance's number when it still fits. Otherwise it stores the fresh safe number at Value cite out of range lands on. The test names the address and restates no number.

Given

Instance once inside and once outside the fresh range after a cited limit move

When
  • each limit move settles
Then
  • the inside value remains unchanged
  • the outside value stores Value cite out of range lands on
  • the target is read fresh and lies inside the new range
  • residue is unchanged and no lap starts
Diagnostics
  • Instance-limit-move-record
  • Instance-value-before-after
a moving limit leaves the held number alone

limit-move-leaves-number-alone

scenarioonce

Applies when When a limit moves is Leave the number alone.

A moving limit does not reposition Instance. A held number may remain beyond the moved landmark only where the matching ordinary edge answer permits it. Residue stays and no lap starts.

Given

Instance holding a number that a cited limit moves past, with the matching ordinary edge answer allowing the value beyond that limit

When
  • the limit move settles
Then
  • the stored number remains unchanged even outside the fresh landmark
  • residue is unchanged and no lap starts
Diagnostics
  • Instance-limit-move-record
  • Instance-value-before-after
a limit move never fires the Row.id bare line

limit-move-never-fires-bare-line

scenarioper lines row

Applies when When a limit moves is Refill to the new ceiling or Keep the number or Keep the share or Pull it to a declared number or Leave the number alone.

After a limit move, Instance refreshes the reached state of bare line Row.id but never fires it. Where either limit answers start-a-lap, a limit move landing the value exactly on that edge does not consume it.

Given

a cited limit move that changes Row.id reached state

When
  • the limit and any resulting held-value change finish settling
Then
  • Row.id stores fresh reached state but reports nothing
  • where either limit answers start-a-lap, a limit move landing the value exactly on that edge does not consume it
Diagnostics
  • Instance-limit-move-record
  • Instance-mark-log
  • Instance-mark-state
a limit move recomputes the Row.id band as its edge kind directs

limit-move-recomputes-band

scenarioper bands row

Applies when When a limit moves is Refill to the new ceiling or Keep the number or Keep the share or Pull it to a declared number or Leave the number alone and row enter on is Line and row leave on is Line.

After a limit move, line-geometry band Row.id recomputes and stores its fresh state. Where that state changed, it reports the change with cause limit-moved; an unchanged state reports nothing.

Given

a cited limit move with the prior Row.id state recorded

When
  • the limit and any resulting held-value change finish settling
Then
  • Row.id recomputes and stores its fresh line-geometry state
  • where that fresh state differs from the prior recorded state, Row.id reports the change with cause limit-moved; where it does not differ, Row.id reports nothing
Diagnostics
  • Instance-limit-move-record
  • Instance-mark-log
  • Instance-mark-state
the limits hold after every operation

limits-hold

generalonce

Applies for every adoption

For every operation in this adoption's verification scope — Inputs scopeBind min clause, and Bind max clause. A cited limit whose answer is no-floor or no-ceiling remains a landmark. The adoption supplies scope and seeds through verification inputs; each half of the oracle is the one its own edge answer permits.

Holds

after every operation, Bind min clause, and Bind max clause. A cited limit whose answer is no-floor or no-ceiling remains a landmark

Seeds

Inputs seeds

Scope

Inputs scope

Diagnostics
  • Instance-value-trace
  • Instance-first-violating-operation

Use this contract in your game ↑