@@ -477,6 +477,39 @@ def test_pooled_placer_homogeneous_stored_layouts_have_distinct_positions_dicts(
477477 ), f"Layouts { i } and { j } share the same positions dict reference"
478478
479479
480+ def test_pooled_placer_stored_layouts_groups_live_results_by_env ():
481+ """stored_layouts must return a per-env snapshot of the live stored PlacementResults."""
482+ num_envs = 3
483+ solver_params = RelationSolverParams (max_iters = 50 )
484+ placer_params = ObjectPlacerParams (placement_seed = 42 , solver_params = solver_params , apply_positions_to_objects = False )
485+
486+ pool = PooledObjectPlacer (
487+ objects = list (_create_test_objects ()), placer_params = placer_params , pool_size = 12 , num_envs = num_envs
488+ )
489+
490+ grouped = pool .stored_layouts
491+ assert len (grouped ) == num_envs
492+ assert all (isinstance (env_layouts , tuple ) for env_layouts in grouped )
493+ # Each returned result is the same live object the pool stores (no copy), grouped per env.
494+ for cur_env , env_layouts in enumerate (grouped ):
495+ assert list (env_layouts ) == [pooled .result for pooled in pool ._env_pools [cur_env ].layouts ]
496+
497+
498+ def test_pooled_placer_stored_layouts_post_validation_flows_into_accepts ():
499+ """Enriching a stored layout's report in place (the post-validation use case) must change accepts()."""
500+ solver_params = RelationSolverParams (max_iters = 50 )
501+ placer_params = ObjectPlacerParams (placement_seed = 42 , solver_params = solver_params , apply_positions_to_objects = False )
502+
503+ pool = PooledObjectPlacer (objects = list (_create_test_objects ()), placer_params = placer_params , pool_size = 4 )
504+ result = pool .stored_layouts [0 ][0 ]
505+ assert pool .accepts (result )
506+
507+ # Record a failing post-pool check (e.g. a simulation collision test) on the live layout.
508+ result .validation = result .validation .with_check ("sim_collision_free" , False )
509+ assert "sim_collision_free" in result .validation .failed_checks
510+ assert not pool .accepts (result )
511+
512+
480513def test_pooled_placer_homogeneous_sample_without_replacement_count_exceeds_pool_size ():
481514 """sample_without_replacement(count) where count > pool_size must solve a larger batch in one shot."""
482515 solver_params = RelationSolverParams (max_iters = 50 )
@@ -714,10 +747,7 @@ def test_pooled_placer_save_load_round_trip_preserves_layouts(tmp_path):
714747
715748
716749def test_pooled_placer_save_load_round_trip_multi_env_homogeneous (tmp_path ):
717- """A multi-env homogeneous pool's per-env layouts survive the round trip intact.
718-
719- Env-specific (variant) correctness is covered by the heterogeneous round-trip test.
720- """
750+ """A multi-env homogeneous pool's per-env layouts survive the round trip (variants covered separately)."""
721751 num_envs = 3
722752 placer_params = _make_seeded_params ()
723753 pool = PooledObjectPlacer (
0 commit comments