Enforce required environment skills before model inference (#51157)

## What changed

- Accept per-environment `skills.required` lists through `environment/add` and `environments.toml`.
- Before inference, require each named skill to be enabled and supplied by the selected environment. Missing skills fail the turn before a model request, including when environment setup fails.
- Stop applying an environment's requirements after it is deselected. Exempt isolated Guardian reviewers, which have no skill catalog.

## Testing

Add tests for available, missing, disabled, and wrong-environment skills, failed environment setup, recovery after deselection, and propagation of TOML requirements to the correct environment.

GitOrigin-RevId: 302ced4774697d2f414f745fe0535e71f747eda2
This commit is contained in:
Adam Perry @ OpenAI
2026-10-05 18:54:17 +00:00
committed by copyberry
parent c9253c4977
commit 42312d4ff4
33 changed files with 615 additions and 78 deletions
@@ -494,7 +494,10 @@ fn environment_states(snapshot: &TurnEnvironmentSnapshot) -> BTreeMap<String, En
const MAX_TOTAL_ERROR_BYTES: usize = 512;
let mut remaining_error_bytes = MAX_TOTAL_ERROR_BYTES;
for environment in &snapshot.environments {
if let TurnEnvironmentState::Failed { selection, error } = environment {
if let TurnEnvironmentState::Failed {
selection, error, ..
} = environment
{
let detail = error
[..error.floor_char_boundary(remaining_error_bytes.min(MAX_ERROR_BYTES))]
.to_string();
@@ -424,6 +424,7 @@ fn failure_context_limits_total_detail_bytes_at_utf8_boundaries() {
let snapshot = TurnEnvironmentSnapshot {
environments: (0..4)
.map(|index| TurnEnvironmentState::Failed {
required_skills: Vec::new(),
selection: TurnEnvironmentSelection {
environment_id: format!("remote-{index}"),
cwd: PathUri::parse("file:///workspace").unwrap(),