You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note this is not friendly towards state with default values as we don't expose that in the framework... But I think types + defaults should be easy enough to expose.
I opened #1038 for the first check here: an opt-in build(validate=True) / abuild(validate=True) that raises when an action or a transition condition reads a state key that no action writes and the initial state does not provide. Graph.validate() returns the same list without raising.
To see whether it catches real mistakes, I ran it over the example apps (18 of them build locally; the rest need extra dependencies). It flagged two, both genuine declaration errors:
examples/llm-adventure-game/application.py
- Action `win` reads ['challenges'], but no action writes them and they are not in the initial state.
examples/simulation/application.py
- Action `forecast` reads ['current_timestep'], but no action writes them and they are not in the initial state.
- Condition `current_timestep<simulation_end` on transition `forecast` -> `forecast` reads ['current_timestep'], but no action writes them and they are not in the initial state.
- Condition `current_timestep>=simulation_end` on transition `forecast` -> `terminate` reads ['current_timestep'], but no action writes them and they are not in the initial state.
win declares a module-level list as a state read.
forecast writes current_timestep without declaring it in writes.
Both examples still run, because reads/writes aren't enforced at runtime. That's also why the check is off by default: turning it on would break apps like these. #1038 fixes both examples.
What I left out, and why:
Path-sensitive check (point 1 as written: "does there exist a path that does not provide the required state?"). I prototyped it. On the examples it produced 3 hits, all false positives: the actions guard those reads with state.get(...) or an earlier branch. I think it needs a way to declare optional reads on actions first (conditions already have optional_keys).
Type checks (point 2).
halt_before/halt_after reachability.
Two questions:
Should this stay opt-in, or become a default warning at some point?
Would optional reads on actions (e.g. @action(reads=[...], optional_reads=[...])) be welcome as a follow-up, to unlock the path-sensitive check?
Activity
andreahlert commentedon Mar 28, 2026
Labels migrated to new taxonomy (#692).
YongGoose commentedon Nov 11, 2026
I opened #1038 for the first check here: an opt-in
build(validate=True)/abuild(validate=True)that raises when an action or a transition condition reads a state key that no action writes and the initial state does not provide.Graph.validate()returns the same list without raising.To see whether it catches real mistakes, I ran it over the example apps (18 of them build locally; the rest need extra dependencies). It flagged two, both genuine declaration errors:
windeclares a module-level list as a state read.forecastwritescurrent_timestepwithout declaring it inwrites.Both examples still run, because reads/writes aren't enforced at runtime. That's also why the check is off by default: turning it on would break apps like these. #1038 fixes both examples.
What I left out, and why:
state.get(...)or an earlier branch. I think it needs a way to declare optional reads on actions first (conditions already haveoptional_keys).halt_before/halt_afterreachability.Two questions:
@action(reads=[...], optional_reads=[...])) be welcome as a follow-up, to unlock the path-sensitive check?