representing guardian review timeouts in protocol types (#17381)

## Summary

- Add `TimedOut` to Guardian/review carrier types:
  - `ReviewDecision::TimedOut`
  - `GuardianAssessmentStatus::TimedOut`
  - app-server v2 `GuardianApprovalReviewStatus::TimedOut`
- Regenerate app-server JSON/TypeScript schemas for the new wire shape.
- Wire the new status through core/app-server/TUI mappings with
conservative fail-closed handling.
- Keep `TimedOut` non-user-selectable in the approval UI.

**Does not change runtime behavior yet; emitting `TimeOut` and
parent-model timeout messaging will come in followup PRs**
This commit is contained in:
Won Park authored and GitHub committed 2026-04-10 20:02:33 -07:00
1 parent 824ec94eab
commit 37aac89a6d
25 files changed
+85 -15

No files matched your search

+1 -1
View File
@@ -716,7 +716,7 @@ async fn maybe_auto_review_mcp_request_user_input(
ReviewDecision::Approved
| ReviewDecision::ApprovedExecpolicyAmendment { .. }
| ReviewDecision::NetworkPolicyAmendment { .. } => MCP_TOOL_APPROVAL_ACCEPT.to_string(),
ReviewDecision::Denied | ReviewDecision::Abort => {
ReviewDecision::Denied | ReviewDecision::TimedOut | ReviewDecision::Abort => {
MCP_TOOL_APPROVAL_DECLINE_SYNTHETIC.to_string()
}
};
+1 -1
View File
@@ -414,7 +414,7 @@ impl GuardianReviewSessionManager {
let snapshot = state.last_committed_fork_snapshot.as_ref()?;
match &snapshot.initial_history {
InitialHistory::Forked(items) => Some(items.clone()),
_ => None,
InitialHistory::New | InitialHistory::Cleared | InitialHistory::Resumed(_) => None,
}
}
+1 -1
View File
@@ -980,7 +980,7 @@ async fn mcp_tool_approval_decision_from_guardian(
| ReviewDecision::ApprovedExecpolicyAmendment { .. }
| ReviewDecision::NetworkPolicyAmendment { .. } => McpToolApprovalDecision::Accept,
ReviewDecision::ApprovedForSession => McpToolApprovalDecision::AcceptForSession,
ReviewDecision::Denied => McpToolApprovalDecision::Decline {
ReviewDecision::Denied | ReviewDecision::TimedOut => McpToolApprovalDecision::Decline {
message: Some(guardian_rejection_message(sess, review_id).await),
},
ReviewDecision::Abort => McpToolApprovalDecision::Decline { message: None },
+1 -1
View File
@@ -488,7 +488,7 @@ impl NetworkApprovalService {
PendingApprovalDecision::Deny
}
},
ReviewDecision::Denied | ReviewDecision::Abort => {
ReviewDecision::Denied | ReviewDecision::TimedOut | ReviewDecision::Abort => {
if let Some(review_id) = guardian_review_id.as_deref() {
if let Some(owner_call) = owner_call.as_ref() {
let message = guardian_rejection_message(session.as_ref(), review_id).await;
+4 -2
View File
@@ -151,7 +151,7 @@ impl ToolOrchestrator {
otel.tool_decision(otel_tn, otel_ci, &decision, otel_source);
match decision {
ReviewDecision::Denied | ReviewDecision::Abort => {
ReviewDecision::Denied | ReviewDecision::TimedOut | ReviewDecision::Abort => {
let reason = if let Some(review_id) = guardian_review_id.as_deref() {
guardian_rejection_message(tool_ctx.session.as_ref(), review_id).await
} else {
@@ -306,7 +306,9 @@ impl ToolOrchestrator {
otel.tool_decision(otel_tn, otel_ci, &decision, otel_source);
match decision {
ReviewDecision::Denied | ReviewDecision::Abort => {
ReviewDecision::Denied
| ReviewDecision::TimedOut
| ReviewDecision::Abort => {
let reason = if let Some(review_id) = guardian_review_id.as_deref() {
guardian_rejection_message(tool_ctx.session.as_ref(), review_id)
.await
@@ -485,7 +485,7 @@ impl CoreShellActionProvider {
EscalationDecision::deny(Some("User denied execution".to_string()))
}
},
ReviewDecision::Denied => {
ReviewDecision::Denied | ReviewDecision::TimedOut => {
let message = if let Some(review_id) =
prompt_decision.guardian_review_id.as_deref()
{