(WIP) Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast#509
Closed
eugenevinitsky wants to merge 2 commits into
Closed
(WIP) Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast#509eugenevinitsky wants to merge 2 commits into
eugenevinitsky wants to merge 2 commits into
Conversation
Road dropout is env noise: it limits how many lane/boundary slots carry data each step, but it must not change the observation interface. The obs vector is now always laid out for the full slot counts, with unused slots zeroed and valid-count features reporting what was kept; the subsample-to-kept content logic is unchanged. Sizing, the backbone slicing, the obs-overlay renderer, and the C layout tests follow. Previously the layout was sized by the post-dropout kept counts, so two envs differing only in dropout had incompatible obs spaces. The inline clean eval (which zeroes dropout) fed a dropout-trained policy longer obs than it was built for, crashing the nightly multi runs with a CUDA gather assert at their first eval. Checkpoints trained with dropout > 0 under the old layout do not load against the new one; dropout-free checkpoints are unaffected (at dropout 0 the layout and fill path are identical). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
[eval.validation_defaults] pinned obs_slots_lane_n/boundary_n = 80 and [eval.behaviors_defaults] pinned obs_slots_partners_n = 32, so any training config with different obs geometry built an eval env whose observations could not be unpacked by the trained policy — the same crash class as the dropout-layout bug, and what actually killed the 2026-07-05 nightly multis after the dropout pin was in place. Obs geometry is the policy interface: eval sections now inherit it from the training env. The policy records the obs length it was built for, and _run_inline raises with a clear message when an evaluator env disagrees, instead of dying ~2h later on an asynchronous CUDA gather assert that poisons the context. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three related changes with one theme — observation geometry is the policy's interface and must be identical between training and eval envs:
obs_slots_*counts; dropout only limits how many slots carry data, zero-padded with the existing valid-count features reporting what was kept. Content selection and its RNG path unchanged; atp=0bit-identical.[eval.validation_defaults]pinnedobs_slots_lane_n/boundary_n = 80and[eval.behaviors_defaults]pinnedobs_slots_partners_n = 32. Any training config with different geometry produced eval observations the policy could not unpack. Those pins are removed; eval envs take geometry from the training config.expected_obs_dim), andEvalManager._run_inlineraises with an actionable message on mismatch — instead of an asynchronous CUDA gather assert ~2h into training that poisons the context and kills the job after the manager already printed "continuing".Why
Both the 2026-07-04 and 2026-07-05 nightly multi runs (trained at 60/40 slots with dropout 0.2/0.3) died at their first inline eval with
ScatterGatherKerneldevice asserts. Night 1 was the dropout-shrunken layout meeting the clean macro; night 2 — after pinning eval dropout — was the section's hard 80/80 slot pins. Same disease: eval env obs shape ≠ policy obs shape. This PR removes both causes and makes any future instance a one-line error at eval start.Notes
dropout > 0under the old layout won't load against the new one (only the two crashed nightly batches exist in that regime). Dropout-free checkpoints unaffected; smoke goldens should not move.num_obsequality for the nightly config verified against the merged eval args (691 == 691).env.obs_dropout_* = 0.0in validation_defaults stays — zeroing noise at eval is semantics, not geometry, and is safe after (1).🤖 Generated with Claude Code