Skip to content

FE-1271: Fire predicate transitions in the same step their guard becomes true - #9096

Merged
kube merged 1 commit into
mainfrom
claude/fe-1271-predicate-transitions-fire-every-frame
Jul 24, 2026
Merged

FE-1271: Fire predicate transitions in the same step their guard becomes true#9096
kube merged 1 commit into
mainfrom
claude/fe-1271-predicate-transitions-fire-every-frame

Conversation

@claude

@claude claude Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

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 Infinity and pushed through the exp(-rate * timeSinceLastFiringMs) <= U1 firing test. timeSinceLastFiringMs is 0 on the first frame and resets to 0 on firing, and Infinity * 0 = NaN silently 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 an Infinity rate — a true guard fires directly, a false guard doesn't; only numeric rates go through the exp() test
  • Regression unit tests in compute-possible-transition.test.ts: a true guard fires with timeSinceLastFiringMs = 0 (the case the test helper's 1.0 default was masking); a false guard never fires
  • Regression test in compute-next-frame.test.ts: a persistently-true predicate transition fires on every frame from frame 1 onwards
  • Changeset for @hashintel/petrinaut-core (patch)

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • modifies an npm-publishable library and I have added a changeset file(s)

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change
    • the user docs already describe the fixed behavior ("fires immediately"); this makes the engine match them

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

🛡 What tests cover this?

  • New: predicate firing at timeSinceLastFiringMs = 0 and consecutive-frame firing (see above)
  • Existing: full @hashintel/petrinaut-core unit suite (839 tests) passes

❓ How to test this?

  1. Checkout the branch
  2. Build a net with a predicate transition whose guard is always true (e.g. a self-loop) and run the simulation
  3. Confirm the transition fires on the very first frame and on every subsequent frame, rather than every other frame

Generated by Claude Code

…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.
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Jul 24, 2026 4:45pm
petrinaut Ready Ready Preview, Comment Jul 24, 2026 4:45pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Jul 24, 2026 4:45pm

@claude claude Bot assigned kube Jul 24, 2026
@github-actions github-actions Bot added area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team labels Jul 24, 2026
@claude
claude Bot marked this pull request as ready for review July 24, 2026 16:55
@claude
claude Bot requested a review from kube July 24, 2026 16:55
@cursor

cursor Bot commented Jul 24, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Localized simulation-engine firing logic with targeted regression tests; stochastic transitions are untouched.

Overview
Predicate (boolean guard) transitions now fire in the same simulation step when the guard is true, including the first frame and every frame while the guard stays true. Previously, true guards were treated as an infinite stochastic rate and passed through exp(-rate × timeSinceLastFiringMs); with timeSinceLastFiringMs === 0 after a firing (or on frame one), that produced NaN and blocked firing, so persistently-true predicates only fired every other frame.

In compute-possible-transition.ts, boolean lambda results bypass the exponential firing test: a true guard fires immediately, a false guard does not. Numeric-rate (stochastic) transitions are unchanged.

Regression coverage was added in compute-possible-transition.test.ts (guard true at timeSinceLastFiringMs = 0, false guard never fires) and compute-next-frame.test.ts (always-true predicate fires on frames 1–4). A patch changeset was added for @hashintel/petrinaut-core.

Reviewed by Cursor Bugbot for commit fc90a42. Bugbot is set up for automated code reviews on this repo. Configure here.

@kube
kube added this pull request to the merge queue Jul 24, 2026
Merged via the queue into main with commit 54cc7eb Jul 24, 2026
61 checks passed
@kube
kube deleted the claude/fe-1271-predicate-transitions-fire-every-frame branch July 24, 2026 17:36
This was referenced Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

2 participants