FE-1271: Fire predicate transitions in the same step their guard becomes true - #9096
Conversation
…mes true Boolean guard lambdas were converted to a stochastic rate of Infinity and run through the exp(-rate * timeSinceLastFiringMs) firing test. Since timeSinceLastFiringMs is 0 on the first frame and resets to 0 on firing, Infinity * 0 = NaN silently failed the test: predicate transitions could not fire in the first frame nor in two consecutive frames, so a persistently-true guard fired only every other frame. Boolean lambda results now bypass the stochastic exp() test and fire directly when true. The numeric-rate path is unchanged.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryLow Risk Overview In Regression coverage was added in Reviewed by Cursor Bugbot for commit fc90a42. Bugbot is set up for automated code reviews on this repo. Configure here. |
Requested by Chris Feijoo · Slack thread
🌟 What is the purpose of this PR?
Before: a predicate (boolean guard) transition whose guard was true could not fire in the very first simulation frame, and could never fire in two consecutive frames — a persistently-true guard fired only every other frame (every 2·dt), even though the docs say a true guard "fires immediately".
After: a true guard fires in the same simulation step it becomes true, including the first frame and every consecutive frame while it stays true. Stochastic-rate transitions behave exactly as before.
How: boolean guard results were converted to a stochastic rate of
Infinityand pushed through theexp(-rate * timeSinceLastFiringMs) <= U1firing test.timeSinceLastFiringMsis 0 on the first frame and resets to 0 on firing, andInfinity * 0 = NaNsilently fails that test. Predicate results now bypass the stochastic test and fire directly when the guard is true; the numeric-rate path is untouched.Fixes FE-1271
🔗 Related links
🔍 What does this change?
compute-possible-transition.ts: boolean lambda results no longer map to anInfinityrate — a true guard fires directly, a false guard doesn't; only numeric rates go through theexp()testcompute-possible-transition.test.ts: a true guard fires withtimeSinceLastFiringMs = 0(the case the test helper's1.0default was masking); a false guard never firescompute-next-frame.test.ts: a persistently-true predicate transition fires on every frame from frame 1 onwards@hashintel/petrinaut-core(patch)Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
🛡 What tests cover this?
timeSinceLastFiringMs = 0and consecutive-frame firing (see above)@hashintel/petrinaut-coreunit suite (839 tests) passes❓ How to test this?
Generated by Claude Code