Governed Desktop Automation

adk-computer-use computer-use-mcp desktop-automation सर्वर के ऊपर एक governance layer है। यह स्वयं कोई actuation नहीं करता: यह observation, approval, mutation, और verification को एक deterministic graph के रूप में व्यवस्थित करता है, और जाँचता है कि external runtime क्या लौटाता है।

Response binding

External runtime authoritative है, लेकिन graph state में प्रवेश करने से पहले उसके responses को locally जाँचा जाता है। ये checks reference graph में हर ComputerUseRuntime implementation के लिए चलते हैं, और MCP adapter अपनी direct-call boundary पर उन्हें दोहराता है। Typed deserialization shape को साबित करता है, provenance को नहीं — ControlLease, TargetReservation, और ExecutionReceipt के पास invariant-enforcing constructor नहीं है, इसलिए किसी दूसरे session से संबंधित well-formed object बिना समस्या parse हो जाता है।

हर response को उस request से वापस bind किया जाता है जिसने उसे उत्पन्न किया था:

प्रतिक्रियाएनवेलप के विरुद्ध जाँचा गया
ControlLeasesession_id, principal_id, agent_id, execution_mode, सक्रिय स्थिति, अवधि-समाप्त न हुआ expires_at, शेष बजट (actions_used < action_budget), और boundaries के भीतर लक्ष्य
TargetReservationsession_id, principal_id, agent_id, execution_group_id, intent_id == action_id, सक्रिय स्थिति, अवधि-समाप्त न हुआ expires_at, और सटीक ऐप/विंडो लक्ष्य-स्कोप
ExecutionReceiptsession_id, action_id, और action_digest को लिफ़ाफ़े के args_digest के विरुद्ध

एक असंगति ComputerUseError::IdentityMismatch उत्पन्न करती है, जो फ़ील्ड को नाम देती है, और प्रतिक्रिया संग्रहीत होने के बजाय अस्वीकार कर दी जाती है।

use adk_computer_use::runtime::binding::validate_lease;

// Refuses a lease that is well-formed but belongs to another session.
validate_lease(&lease, &envelope)?;

नोट: digest उपलब्ध सबसे मज़बूत binding है। args_digest वह है जिसके विरुद्ध approval दिया गया था, इसलिए अलग digest वाला receipt भिन्न काम का वर्णन करता है, भले ही हर identifier मेल खाता हो।

एक वैकल्पिक फ़ील्ड जो वापस आते समय अनुपस्थित हो, उसे under-specification माना जाता है, contradiction नहीं; जो फ़ील्ड present है और अलग है, वह mismatch है।

Execution-time revalidation

Preview mutation authority नहीं है। reference graph सभी mutation inputs को execute node में तुरंत revalidate करता है, execute_action को कॉल करने से ठीक पहले:

इनपुटतत्काल जाँच
ActionEnvelopeRFC 3339 टाइमस्टैम्प, सकारात्मक वैधता विंडो, और now < expires_at
ControlLeaseपहचान, मोड, सक्रिय स्थिति, शेष बजट, समाप्ति, और लक्ष्य सीमाएँ
TargetReservationपहचान, क्रिया-इरादा, सक्रिय स्थिति, समाप्ति, और सटीक लक्ष्य दायरा
अनुमोदनरूट, क्रिया डाइजेस्ट, नीति डाइजेस्ट, और ठीक एक प्राधिकरण स्रोत (grantId या रनटाइम-धारित अनुमोदन)

जब preview वापस आता है, तब भी envelope check चलता है, इसलिए पहले से समाप्त हो चुका preview कभी reservation या approval तक नहीं पहुँचता। यह execution के समय फिर से चलता है क्योंकि approval interrupt, target reservation, या lease acquisition शेष validity window को consume कर सकते हैं।

ComputerUseMcpRuntime, preview_action द्वारा लौटाए गए exact envelope को बनाए रखता है। यदि preview के बाद कोई envelope field बदल जाती है, तो direct execute_action call reject कर दी जाती है, भले ही action ID अभी भी match करती हो।

checkpoint resume के लिए, graph runtime preview को append-only state channel में store करता है। Approval और execution के लिए आवश्यक है कि उस channel में active preview से मेल खाता हुआ ठीक एक preview हो। Resume input state जोड़ सकता है, लेकिन checkpointed value को replace नहीं कर सकता: replacement का प्रयास दूसरी entry बनाता है और reservation या mutation से पहले fail हो जाता है।

Reservation cleanup

एक बार reservation accept हो जाने पर, हर terminal path उसे release करने का प्रयास करता है:

  • lease acquisition, authorization, validation, execution, receipt, और verification failures;
  • successful verification; और
  • जब runtime ने reservation लौटाई हो, तब reservation validation या serialization failures।

cleanup सफल होने पर primary failure, primary ही रहता है। यदि cleanup भी fail हो जाए, तो graph दोनों failures को शामिल करने वाली एक deterministic error लौटाता है। otherwise successful verification के बाद होने वाली cleanup failure, छिपाए जाने के बजाय error के रूप में लौटाई जाती है।

Verification commitment नहीं है

ComputerUseRuntime::verify एक VerificationOutcome लौटाता है, boolean नहीं:

परिणामअर्थis_verified()is_committed()status()
Verifiedघोषित पश्च-शर्त को सत्य पाया गयाtruetruecompleted
CommittedUnverifiedरनटाइम ने क्रिया की; पश्च-शर्त का कोई प्रमाण नहींfalsetruecommitted_unverified
Failedकमिट नहीं हुआ, या साक्ष्य पोस्टकंडीशन का खंडन करता हैfalsefalseverification_failed

ग्राफ का verify नोड verified, committed, और एक result.verificationDetail लिखता है जो Verified से कम किसी भी चीज़ की व्याख्या करता है।

महत्वपूर्ण: एक committed receipt इस बात की स्वीकृति है कि action स्वीकार कर लिया गया था और निष्पादित किया गया था। यह इस बात का प्रमाण नहीं है कि intended effect हुआ। verify ने पहले receipt.status == Committed लौटाया था, जिसने committed-but-ineffective action को completed के रूप में रिपोर्ट किया — एक node से जिसका label "verify" था।

क्या evidence माना जाता है

एक postcondition जो digest (valueDigest, contentDigest) घोषित करती है, उसके लिए verification में receipt result पर एक verification.observedDigest आवश्यक है जो उससे मेल खाता हो। केवल existence घोषित करने वाली postcondition के लिए, एक explicit verification.satisfied: true आवश्यक है।

रसीद साक्ष्यपरिणाम
verification.satisfied: falseFailed — एक स्पष्ट नकारात्मक अवलोकन
observedDigest अपेक्षित डाइजेस्ट से मेल खाता हैVerified
observedDigest भिन्न हैFailed
कोई verification object नहींCommittedUnverified
verification मौजूद, कोई observedDigest नहीं, digest अपेक्षितCommittedUnverified

साक्ष्य का अभाव कभी भी सफलता के साक्ष्य के रूप में नहीं माना जाता। यदि computer-use-mcp रसीद जारी करने से पहले सत्यापित करता है, तो यह उसका अनुबंध है; यह adapter इसे मानकर नहीं चलता।

Lease सीमाएँ

एक lease तब तक अस्वीकार की जाती है जब तक कि ये सभी शर्तें पूरी न हों:

जांचअस्वीकृत जब
समाप्तिexpires_at अतीत में है, या RFC 3339 के रूप में पार्स नहीं किया जा सकता
शेष बजटactions_used >= action_budget
लक्ष्य सीमालिफ़ाफ़े का target.app_id एक गैर-रिक्त boundaries.app_ids से अनुपस्थित है
विंडो सीमालिफ़ाफ़े का target.window_id एक गैर-रिक्त boundaries.window_ids से अनुपस्थित है

खाली सीमाएँ का अर्थ है "स्कोप में नहीं" और यह किसी भी लक्ष्य को अधिकृत करता है — किसी प्रतिबंध की अनुपस्थिति का अर्थ कुछ भी नहीं के लिए प्रतिबंध नहीं है।

महत्वपूर्ण: इस वैलिडेटर के पहले संस्करण ने action_budget == 0 की जाँच की थी, जो कुल बजट है, इसलिए action_budget: 1, actions_used: 1 वाला लीज़ पास हो गया जबकि उसने कुछ भी अधिकृत नहीं किया। इसने expires_at या boundaries को भी कभी नहीं पढ़ा, इसलिए एक समाप्त हो चुका लीज़ और किसी अलग एप्लिकेशन के लिए स्कोप किया गया लीज़ दोनों स्वीकार कर लिए गए। एक अपरिवर्तनीय समाप्ति को अनदेखा करने के बजाय अस्वीकार किया जाता है: जिस लीज़ की वैधता स्थापित नहीं की जा सकती, वह वैध नहीं है।