Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .file_mapping.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"_source_commit": "aa88627921856c9c83ab8edf42c46e506255d3a6-dirty",
"_dest_commit": "fcd1d7eb07ad76dd7f15c61185a2377f15918ac7",
"_generated_at": "2026-09-07T05:52:05Z",
"_source_commit": "6cc9d886c99205e0b3d34f1b96b7eaa893122764-dirty",
"_dest_commit": "4e0fe142e2aeb74b456fbf9e0c0748d7028bdd7c",
"_generated_at": "2026-09-08T05:52:20Z",
"files": {
"imaginaire/__init__.py": "cosmos_framework/__init__.py",
"imaginaire/attention/__init__.py": "cosmos_framework/model/attention/__init__.py",
Expand Down
11 changes: 5 additions & 6 deletions cosmos_framework/data/generator/action/utils/domain_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
"av": 1,
"camera_pose": 2,
"hand_pose": 3,
# Alias for the WebHumanAction (Action100M) Lance hand adapter. Same domain
# as "hand_pose" (shared with embodiment_a) so it reuses the same action2llm/llm2action
# DomainAwareLinear weights rather than training a fresh encoder/decoder.
"webhumanaction_hand": 3,
# WebHumanAction omits the camera prefix from its 48D native hand layout,
# so it must not reuse hand_pose/embodiment_a's camera-inclusive domain 3 projector.
"webhumanaction_hand": 31,
"pusht": 4,
"libero": 5,
"umi": 6,
Expand All @@ -36,7 +35,7 @@
"behavior1k_lerobot": 22, # BEHAVIOR-1K R1Pro mobile bimanual (23D joint action)
"maniparena": 23, # ManipArena x2robot/ex001_6r dual-arm; own 20D EE-direct action projection
# New dedicated slot (not reusing agibot's domain 15): WebHumanAction body
# (camera+head+wrists, yesCam 36D) trains its own action2llm/llm2action
# (ego/head+wrists+fingertips, no camera action, 57D) trains its own action2llm/llm2action
# DomainAwareLinear weights from scratch instead of continuing agibot's.
"webhumanaction_body": 24,
"so101-molmo-midtrain-15hz": 25,
Expand Down Expand Up @@ -72,7 +71,7 @@
"agibotworld": 29,
"embodiment_c_gripper": 29,
"embodiment_c_gripper_ext": 29,
"webhumanaction_body": 36, # camera(9) + head(9) + R_wrist(9) + L_wrist(9)
"webhumanaction_body": 57, # ego/head(9) + [R_wrist(9)+R_fingertips(15)] + [L_wrist(9)+L_fingertips(15)]
"xdof_yam": 20,
"molmoact2_yam": 20,
"abc_yam": 20,
Expand Down
7 changes: 6 additions & 1 deletion cosmos_framework/model/generator/omni_mot_causal_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,12 @@ def _resolve_teacher_forcing_replay_policy(value: Any) -> TeacherForcingReplayPo
if OmegaConf.is_config(value):
value = OmegaConf.to_object(value)
if isinstance(value, dict):
value = TeacherForcingReplayPolicyConfig(**value)
# Drop lazy-config serializer metadata before construction. A config that has been
# round-tripped through an exported checkpoint carries a "_type" marker alongside
# the real fields, and attrs rejects it as an unexpected keyword. In-process
# construction never sees the marker, so this only failed when loading from an
# export -- which is every public run of a causal model.
value = TeacherForcingReplayPolicyConfig(**{k: v for k, v in value.items() if not k.startswith("_")})
if not isinstance(value, TeacherForcingReplayPolicyConfig):
raise TypeError(
"teacher_forcing_replay_policy must resolve to a TeacherForcingReplayPolicyConfig, "
Expand Down
44 changes: 44 additions & 0 deletions cosmos_framework/model/generator/omni_mot_causal_model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2683,3 +2683,47 @@ def test_training_step_resets_flag_on_error(self) -> None:
model.training_step({}, iteration=0)

assert model._bidirectional_step_active is False


@pytest.mark.L0
@pytest.mark.CPU
def test_teacher_forcing_replay_policy_resolves_a_serialized_config_dict() -> None:
"""A config round-tripped through an exported checkpoint must still resolve.

Serializing a config adds a "_type" marker next to the real fields. Passing that
dict straight to attrs raised TypeError("unexpected keyword argument '_type'"), so
every causal model failed to load from an exported artifact while in-process
construction -- which never sees the marker -- kept working.
"""
from cosmos_framework.configs.base.defaults.replay_attention import (
TeacherForcingReplayPolicyConfig,
)
from cosmos_framework.model.generator.omni_mot_causal_model import (
_resolve_teacher_forcing_replay_policy,
)

serialized = {
"_type": "cosmos_framework.configs.base.defaults.replay_attention.TeacherForcingReplayPolicyConfig",
"control_visibility": "current",
"controls_read_strict_past_clean_rgb": True,
"clean_pass_causality": "chunk",
}

resolved = _resolve_teacher_forcing_replay_policy(serialized)

assert isinstance(resolved, TeacherForcingReplayPolicyConfig)
assert resolved.control_visibility == "current"
assert resolved.controls_read_strict_past_clean_rgb is True
assert resolved.clean_pass_causality == "chunk"


@pytest.mark.L0
@pytest.mark.CPU
def test_teacher_forcing_replay_policy_still_rejects_unknown_real_fields() -> None:
"""Stripping the marker must not turn typos into silently ignored fields."""
from cosmos_framework.model.generator.omni_mot_causal_model import (
_resolve_teacher_forcing_replay_policy,
)

with pytest.raises(TypeError, match="control_visibilty"):
_resolve_teacher_forcing_replay_policy({"_type": "x", "control_visibilty": "current"})