| name | Create OOD Robustness Tests |
| description | This skill should be used when the user asks to "create OOD tests", "test out-of-distribution robustness", "inject observation noise", "apply domain shift", "simulate actuator failure", "zero out action channels", "test agent outside training distribution", or "expose overfitting to training conditions". Do NOT hallucinate parameters outside the boundaries of Create OOD Robustness Tests. |
| version | 0.1.0 |
Create OOD Robustness Tests
Synthesize out-of-distribution (OOD) observation domains and actuator failure scenarios to expose overfitting and measure true generalization beyond the training distribution.
Step 1 — Observation Noise Injection
Inject additive Gaussian noise into the observation tensor immediately before the Actor network consumes it:
def noisy_obs_wrapper(obs, scale):
return obs + torch.randn_like(obs) * scale
scales = [0.0, 0.01, 0.05, 0.1, 0.2, 0.5, 1.0]
results = {}
for scale in scales:
rewards = eval_policy(policy, env, noise_fn=lambda o: noisy_obs_wrapper(o, scale), n_episodes=50)
results[scale] = (np.mean(rewards), np.std(rewards))
Plot Noise Scale (X-axis) vs Mean Reward (Y-axis) with std shading.
Acceptance criterion: Reward degrades gracefully (smooth curve), not catastrophically (step-function collapse at low noise). A collapse at scale=0.01 reveals no noise robustness.
Step 2 — Domain Shift Alterations
Manually override physics parameters beyond the Domain Randomization ranges generated by the Env Engineer:
env.model.body_mass[robot_body_id] *= 3.0
env.model.geom_friction[floor_id] *= 0.1
Run 30 evaluation episodes per perturbation level. Record:
mean_reward at $1\times$, $2\times$, $3\times$ perturbation
- First timestep of policy failure (if any)
If the agent oscillates uncontrollably at $3\times$: The Domain Randomization ranges are too narrow. Flag this to the Env Engineer with the exact failure threshold.
Step 3 — Action Perturbations (Actuator Failure Simulation)
Force-zero random action vector channels dynamically to simulate a broken motor:
def actuator_failure_wrapper(action, failure_rate=0.1):
mask = (torch.rand_like(action) > failure_rate).float()
return action * mask
rewards = eval_policy(policy, env, action_fn=actuator_failure_wrapper, n_episodes=50)
Sweep failure_rate from 0.0 to 0.5. Evaluate whether the agent discovers secondary compensations:
- Does mean reward decrease linearly with failure rate? (graceful degradation — good)
- Does reward instantly collapse at any failure? (brittle single-channel dependency — bad)
Log which channels, when zeroed, cause the largest performance drop. These are single points of failure in the policy.
Step 4 — Report
Produce an OOD Robustness Report containing:
- Noise injection curve with std bands
- Physics perturbation failure threshold (the exact multiplier where policy breaks)
- Actuator failure curve and identified single points of failure
- Go/No-Go verdict for deployment in uncontrolled environments
Additional Resources
Reference Files
references/ood_test_patterns.md — Domain shift protocols, noise schedules, and actuator failure taxonomies
Scripts
scripts/noise_sweep.py — Gaussian noise injection sweep with reward plotting
scripts/actuator_failure.py — Action masking wrapper with failure rate sweep