Motivation & Context
workflow checkpoint state that contains dict subclasses (defaultdict, Counter, OrderedDict) loses its type through a save/load round-trip: it comes back as a plain dict. the encode path uses isinstance(value, dict) and reconstructs a plain dict on decode, even though the module documents full python object fidelity and the unpickler allowlist already covers collections types.
workflows that resume from a checkpoint crash or silently change behavior when their state was a defaultdict or Counter (missing-key defaulting, counter arithmetic).
Reproduction
from collections import Counter
# executor state: {"counts": Counter({"a": 2})}
# save via FileCheckpointStorage, then load:
type(state["counts"]) # dict, not Counter
new tests in the PR build the round-trip and assert the subclass survives.
Expected behavior
dict subclasses round-trip with their type intact.
env: python main
Motivation & Context
workflow checkpoint state that contains dict subclasses (defaultdict, Counter, OrderedDict) loses its type through a save/load round-trip: it comes back as a plain dict. the encode path uses isinstance(value, dict) and reconstructs a plain dict on decode, even though the module documents full python object fidelity and the unpickler allowlist already covers collections types.
workflows that resume from a checkpoint crash or silently change behavior when their state was a defaultdict or Counter (missing-key defaulting, counter arithmetic).
Reproduction
new tests in the PR build the round-trip and assert the subclass survives.
Expected behavior
dict subclasses round-trip with their type intact.
env: python main