Complete strict effect verifier schemas

This commit is contained in:
Meta Vens 2026-08-29 05:00:15 +02:00
commit 92c7647014
2 changed files with 57 additions and 23 deletions

View file

@ -308,6 +308,11 @@ fn responses_schema_is_strict(schema: &serde_json::Value) -> bool {
{
return false;
}
if map.get("type").and_then(serde_json::Value::as_str) == Some("array")
&& !map.contains_key("items")
{
return false;
}
if schema_map_describes_object(map) {
if map.get("additionalProperties") != Some(&serde_json::Value::Bool(false)) {
return false;
@ -896,6 +901,24 @@ mod tests {
assert!(error.contains("root must have type object"));
}
#[test]
fn strict_schema_projection_rejects_arrays_without_an_item_contract() {
let mut schema = serde_json::json!({
"type":"object",
"required":["findings"],
"properties":{
"findings":{"type":"array", "maxItems":0}
},
"additionalProperties":false
});
let error = project_strict_responses_schema(&mut schema)
.unwrap_err()
.to_string();
assert!(error.contains("not strict"));
}
#[test]
fn attempt_deadline_tracks_the_logical_model_class_not_the_stage_name() -> Result<()> {
let port = CodexConnectorModelPort::new(

View file

@ -2143,6 +2143,28 @@ fn cell_effect_verifier_schema(action_count: usize) -> Result<serde_json::Value>
let verdict = schema
.pointer_mut("/$defs/CellActionEffectVerdict")
.ok_or_else(|| anyhow!("cell effect verifier schema has no verdict definition"))?;
let finding_schema = serde_json::json!({
"type":"object",
"additionalProperties":false,
"required":["mismatch_kind", "repair_guidance"],
"properties":{
"mismatch_kind":{
"enum":[
"subject_swap",
"effect_omission",
"effect_reversal",
"target_substitution",
"invented_outcome",
"wrong_effect_kind"
]
},
"repair_guidance":{
"type":"string",
"minLength":1,
"maxLength":240
}
}
});
*verdict = serde_json::json!({
"oneOf":[
{
@ -2156,7 +2178,11 @@ fn cell_effect_verifier_schema(action_count: usize) -> Result<serde_json::Value>
"maximum":action_count - 1
},
"result":{"const":"match"},
"findings":{"type":"array", "maxItems":0}
"findings":{
"type":"array",
"maxItems":0,
"items":finding_schema.clone()
}
}
},
{
@ -2174,28 +2200,7 @@ fn cell_effect_verifier_schema(action_count: usize) -> Result<serde_json::Value>
"type":"array",
"minItems":1,
"maxItems":6,
"items":{
"type":"object",
"additionalProperties":false,
"required":["mismatch_kind", "repair_guidance"],
"properties":{
"mismatch_kind":{
"enum":[
"subject_swap",
"effect_omission",
"effect_reversal",
"target_substitution",
"invented_outcome",
"wrong_effect_kind"
]
},
"repair_guidance":{
"type":"string",
"minLength":1,
"maxLength":240
}
}
}
"items":finding_schema
}
}
}
@ -5047,6 +5052,12 @@ mod tests {
schema.pointer("/properties/verdicts/maxItems"),
Some(&serde_json::json!(4))
);
assert!(
schema
.pointer("/$defs/CellActionEffectVerdict/oneOf/0/properties/findings/items")
.is_some(),
"even a zero-length findings branch needs an items schema at the provider boundary"
);
let validator = jsonschema::validator_for(&schema).unwrap();
let faithful = serde_json::json!({
"verdicts":[