Gathering Exact Graph Freeze Timing¶
src/joint_graph/exact/gathering.py must mirror the live
src/environments/gridworlds/gathering/env.py step order exactly, or the
joint-graph artifacts drift away from replay buffers and OM training fails.
Regression fixed on 2026-04-22¶
The exact gathering_successors(...) helper used to remove apples for any
agent that was "not newly frozen" at the end of the step. That was subtly
wrong for agents that started the step frozen:
- the live env collects apples before decrementing freeze timers
- a frozen-at-start agent therefore cannot collect on that turn
- the next observation may show that agent active again while an apple is still present underneath it
The exact builder was deleting those apples one step too early, so
legal_joint_graph.pkl and derived env_transition_graph.pkl were missing a
small set of valid Gathering observations. This surfaced in OM preparation as
dataset states from wm/D.pkl that could not be found in the graph.
Correct collection rule¶
During exact successor generation, an agent may collect an apple only if both of these are true:
- it was not frozen at the start of the step
- it was not newly tagged into a frozen state during the step
That matches the runtime env's "collect, then decrement timers" ordering.
Cache invalidation¶
notebooks/utils/dynamics.py now writes a
legal_joint_graph.metadata.pkl sidecar next to legal_joint_graph.pkl.
The metadata records:
- env module/name
- expected public-state width
- exact builder identity and source hash
- seed and builder kwargs used to construct the graph
If the sidecar is missing or mismatched, the legal graph is rebuilt instead of being silently reused. This is important whenever exact-graph semantics change without changing the public-state width.