Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions crates/webcodex-core/src/validation_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use crate::runner_protocol::{
normalize_cargo_value, normalize_go_test_packages, normalize_rust_test_filter,
CARGO_TEST_MIN_TESTS_MAX,
};
use serde_json::Value;
use sha2::{Digest, Sha256};
Expand Down Expand Up @@ -92,22 +91,6 @@ pub fn structured_validation_target_identity(tool_name: &str, arguments: &Value)
let filter = normalized_rust_test_target_filter(obj.get("filter"))?;
let features = normalized_cargo_target_value(obj.get("features"))?;
let package = normalized_cargo_target_value(obj.get("package"))?;
let require_tests = obj.get("require_tests").and_then(Value::as_bool);
let min_tests = obj.get("min_tests").and_then(Value::as_u64);
if min_tests.is_some_and(|minimum| !(1..=CARGO_TEST_MIN_TESTS_MAX).contains(&minimum)) {
return None;
}
let minimum_tests = match (require_tests, min_tests) {
(Some(true), Some(minimum)) => Some(minimum.max(1)),
(Some(true), None) => Some(1),
(_, minimum) => minimum,
};
// The effective minimum already normalizes require_tests=true and
// min_tests. Preserve only the remaining proof-semantic difference:
// explicit false with no minimum accepts a zero-test execution,
// while omission does not.
let explicit_zero_test_opt_out =
(require_tests == Some(false) && minimum_tests.is_none()).then_some(false);
serde_json::json!({
"tool": tool_name,
"kind": "test",
Expand All @@ -119,8 +102,6 @@ pub fn structured_validation_target_identity(tool_name: &str, arguments: &Value)
"all_features": obj.get("all_features").and_then(Value::as_bool).unwrap_or(false),
"no_default_features": obj.get("no_default_features").and_then(Value::as_bool).unwrap_or(false),
"no_run": obj.get("no_run").and_then(Value::as_bool).unwrap_or(false),
"minimum_tests": minimum_tests,
"require_tests": explicit_zero_test_opt_out,
})
}
"go_test" => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ pub fn accepted_flattened_args_for_spec(spec: &ToolSpec) -> Vec<String> {
for field in runtime_tool_extra_accepted_flattened_args(&spec.name) {
push_unique_flattened_arg(&mut names, field);
}
// These names belong to the generic callRuntimeTool envelope. Concrete
// tools may legitimately use the same words inside canonical `params`
// (plugin_tool uses provider-local `tool` and `arguments`), but they cannot
// be represented unambiguously as top-level flattened fields.
names.retain(|field| !matches!(field.as_str(), "tool" | "params" | "arguments"));
push_unique_flattened_arg(&mut names, TOOL_CALL_RECORDING_SESSION_ID_FIELD);
names
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(super) fn output_schema_for_tool(name: &str) -> Option<Value> {
),
(
"tool_failures",
open_object_schema("Pre-declared result-expectation classification from the session ledger. Default success remains fail-closed; matched negative/observation outcomes are expected evidence. unexpected_count remains raw historical evidence; historical_non_actionable_count identifies resolved validation or structurally proven fail-closed attempts; actionable_unexpected_count is the conservative current blocker projection. Expectation mismatches and unexpected successes remain separate integrity evidence. Compact output includes counts only."),
open_object_schema("Pre-declared result-expectation classification from the session ledger. Default success remains fail-closed; matched negative/observation outcomes are expected evidence. unexpected_count remains immutable raw failed-ToolCall evidence; non_actionable_unexpected_count identifies request-scoped validation evidence assertion failures, resolved/stale validation failures, or structurally proven not-started/non-effect attempts; actionable_unexpected_count is the conservative current blocker projection. Expectation mismatches and unexpected successes remain separate integrity evidence. Compact output includes counts only."),
),
(
"hygiene",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -904,12 +904,13 @@ fn attempt_activity_schema() -> Value {
"properties": {
"meaningful_tool_calls": schema_type("integer", "Count of meaningful (status/manifest-excluding) tool calls."),
"successful_tool_calls": schema_type("integer", "Succeeded meaningful tool calls."),
"failed_tool_calls": schema_type("integer", "Failed meaningful tool calls."),
"failed_tool_calls": schema_type("integer", "Immutable raw failed meaningful ToolCall count, including expected/resolved/non-actionable history."),
"actionable_failed_tool_calls": schema_type("integer", "Failed meaningful ToolCalls that the canonical closeout projection still considers actionable for this attempt."),
"expected_failures": schema_type("integer", "Expected failure tool calls."),
"resolved_failures": schema_type("integer", "Validation failures resolved by the attempt."),
"unresolved_failures": schema_type("integer", "Validation failures still unresolved.")
},
"required": ["meaningful_tool_calls", "successful_tool_calls", "failed_tool_calls", "expected_failures", "resolved_failures", "unresolved_failures"]
"required": ["meaningful_tool_calls", "successful_tool_calls", "failed_tool_calls", "actionable_failed_tool_calls", "expected_failures", "resolved_failures", "unresolved_failures"]
})
}

Expand Down Expand Up @@ -978,6 +979,7 @@ fn attempt_validation_schema() -> Value {
"latest_kind": nullable_schema("string", "Validation kind of the latest run, when present."),
"latest_at": nullable_schema("integer", "Unix timestamp of the latest run, when present."),
"unresolved_failure_count": schema_type("integer", "Unresolved failure event count from this attempt."),
"evidence_gap_event_count": schema_type("integer", "Inconclusive/request-scoped validation evidence events retained in the current post-mutation window. These are process evidence, not persistent task requirements."),
"validation_events": schema_type("integer", "Validation event count in the current evidence window."),
"stale_failure_count": schema_type("integer", "Failure events from this attempt that predate the latest trusted material workspace-content change."),
"open_failures": array_schema(failure_identity_schema(), "Bounded stable identities for currently unresolved failures in this attempt."),
Expand All @@ -986,7 +988,7 @@ fn attempt_validation_schema() -> Value {
"delta_available": schema_type("boolean", "Whether the validation delta is comparable."),
"delta_reason_code": nullable_schema("string", "Reason code when the delta is not available; null otherwise.")
},
"required": ["status", "latest_status", "unresolved_failure_count", "validation_events", "stale_failure_count", "open_failures", "total_open_failures", "failures_truncated", "delta_available"]
"required": ["status", "latest_status", "unresolved_failure_count", "evidence_gap_event_count", "validation_events", "stale_failure_count", "open_failures", "total_open_failures", "failures_truncated", "delta_available"]
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ pub(super) fn output_schema_for_tool(name: &str) -> Option<Value> {
),
(
"tool_failures",
open_object_schema("Pre-declared result-expectation classification from the session ledger. Default success remains fail-closed; matched negative/observation outcomes are expected evidence. unexpected_count remains raw historical evidence; historical_non_actionable_count identifies resolved validation or structurally proven fail-closed attempts; actionable_unexpected_count is the conservative current blocker projection. Expectation mismatches and unexpected successes remain separate integrity evidence. Never includes raw input payloads, command text, stdout/stderr, tails, or excerpts."),
open_object_schema("Pre-declared result-expectation classification from the session ledger. Default success remains fail-closed; matched negative/observation outcomes are expected evidence. unexpected_count remains immutable raw failed-ToolCall evidence; non_actionable_unexpected_count identifies request-scoped validation evidence assertion failures, resolved/stale validation failures, or structurally proven not-started/non-effect attempts; actionable_unexpected_count is the conservative current blocker projection. Expectation mismatches and unexpected successes remain separate integrity evidence. Never includes raw input payloads, command text, stdout/stderr, tails, or excerpts."),
),
(
"expected_failed_tool_calls",
Expand Down Expand Up @@ -634,13 +634,14 @@ fn validation_evidence_schema() -> Value {
"expected_results": {"type": "integer", "minimum": 0},
"resolved_failure_count": {"type": "integer", "minimum": 0},
"unresolved_failure_count": {"type": "integer", "minimum": 0},
"evidence_gap_event_count": {"type": "integer", "minimum": 0, "description": "Request-scoped/inconclusive validation evidence events in the current post-mutation window. This is historical/process evidence within the window, not a persistent task requirement."},
"stale_failure_count": {"type": "integer", "minimum": 0},
"evidence_after_latest_content_change": {"type": "boolean"},
"boundary_reason": {"type": "string", "enum": ["attempt_start", "workspace_content_changed", "attempt_boundary_unavailable"]}
},
"required": [
"status", "reason", "latest_status", "events_total", "successes", "failures",
"expected_results", "resolved_failure_count", "unresolved_failure_count", "stale_failure_count",
"expected_results", "resolved_failure_count", "unresolved_failure_count", "evidence_gap_event_count", "stale_failure_count",
"evidence_after_latest_content_change", "boundary_reason"
]
})
Expand All @@ -660,6 +661,7 @@ fn validation_evidence_schema() -> Value {
"historical_failures": validation_historical_failures_schema(),
"resolved_failures": validation_failure_set_schema(),
"unresolved_failures": validation_failure_set_schema(),
"evidence_gaps": validation_failure_set_schema(),
"source": { "type": "string", "enum": ["session_ledger"] },
"events_total": { "type": "integer", "minimum": 0 },
"successes": { "type": "integer", "minimum": 0 },
Expand All @@ -674,12 +676,12 @@ fn validation_evidence_schema() -> Value {
"description": "Bounded validation history only; never raw session events."
},
"parser": validation_parser_metadata_schema(),
"cargo_test_zero_tests_run": schema_type("boolean", "True when a successful cargo_test event explicitly reported zero tests run."),
"cargo_test_zero_tests_run": schema_type("boolean", "True when a completed, validator-successful cargo_test execution explicitly reported zero tests run, even if a request-scoped count assertion made the raw ToolResult fail."),
"skipped": schema_type("boolean", "True only when validation summary generation was explicitly skipped by a closeout caller.")
},
"required": [
"available", "status", "reason", "latest", "latest_status", "current_evidence",
"historical_failures", "resolved_failures", "unresolved_failures",
"historical_failures", "resolved_failures", "unresolved_failures", "evidence_gaps",
"source", "events_total", "events", "parser",
"cargo_test_zero_tests_run"
]
Expand Down Expand Up @@ -747,8 +749,10 @@ fn validation_event_schema() -> Value {
"assertion_name": { "type": "string", "minLength": 1, "maxLength": MAX_MODEL_VALIDATION_ASSERTION_NAME_CHARS },
"purpose": { "type": "string", "enum": ["validation", "test", "build", "format", "release"] },
"validation_kind": { "type": "string", "enum": ["format", "check", "test", "build", "release", "validation"] },
"success": { "type": "boolean", "description": "True when the validator/execution ToolResult passed. For structured test validation, this execution fact is distinct from validation proof: zero tests or unavailable test-count metadata can remain successful execution while the evidence verdict is inconclusive." },
"execution_success": { "type": "boolean" },
"success": { "type": "boolean", "description": "Immutable raw ToolResult success recorded by the Workflow Session. A request-scoped evidence assertion can make this false even when validator execution and correctness passed." },
"execution_success": { "type": "boolean", "description": "Derived execution result from authoritative completion state and exit code; independent from request-scoped evidence assertions." },
"validation_passed": { "type": "boolean", "description": "True when the validator/correctness execution itself passed. This can remain true while the invocation's evidence assertion is insufficient." },
"failure_class": { "type": "string", "enum": ["none", "execution_or_correctness", "outcome_unknown", "evidence_assertion", "evidence_insufficient", "expected_result"] },
"expectation_satisfied": { "type": "boolean", "description": "Present for public result expectations; true when the pre-declared expectation matched. This is separate from validation success." },
"failure_kind": { "type": "string", "enum": ["compile_error", "test_failure", "validation_failed", "timeout", "process_exit", "format_diff", "unknown"] },
"failure_category": { "type": "string", "enum": ["compile_error", "test_failure", "validation_failed", "timeout", "process_exit", "format_diff", "unknown"] },
Expand Down Expand Up @@ -789,7 +793,7 @@ fn validation_event_schema() -> Value {
},
"required": [
"tool_name", "execution_source", "identity", "purpose",
"validation_kind", "success", "failure_kind", "failure_category",
"validation_kind", "success", "validation_passed", "failure_class", "failure_kind", "failure_category",
"unresolved_failure", "summary", "cwd", "shell", "execution_state",
"session_id", "stdout_truncated", "stderr_truncated"
]
Expand Down
5 changes: 4 additions & 1 deletion crates/webcodex-tool-contracts/src/tests/flattened_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ fn call_runtime_tool_flattened_args_exclude_testing_and_debug_metadata() {
"assertion_name",
"test_expect_failure_kind",
"allow_cross_project_session",
"tool",
"params",
"arguments",
] {
assert!(
!accepted_fields.contains(field),
"runtime flattened compatibility args must not advertise non-business metadata field {field}"
"runtime flattened compatibility args must not advertise reserved/non-business field {field}"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ fn sample_field_value(field: &str) -> Value {
"expected_head" => json!("a".repeat(40)),
"expected_generation" => json!(1),
"expected_revision" => json!(format!("sha256:{}", "a".repeat(64))),
"expected_generation" => json!(1),
"name" => json!("Private Drop"),
"kind" => json!("note"),
"message" => json!("hello"),
Expand Down
Loading
Loading