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 किया जाता है जिसने उसे उत्पन्न किया था:
| प्रतिक्रिया | एनवेलप के विरुद्ध जाँचा गया |
|---|---|
ControlLease | session_id, principal_id, agent_id, execution_mode, सक्रिय स्थिति, अवधि-समाप्त न हुआ expires_at, शेष बजट (actions_used < action_budget), और boundaries के भीतर लक्ष्य |
TargetReservation | session_id, principal_id, agent_id, execution_group_id, intent_id == action_id, सक्रिय स्थिति, अवधि-समाप्त न हुआ expires_at, और सटीक ऐप/विंडो लक्ष्य-स्कोप |
ExecutionReceipt | session_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 को कॉल करने से ठीक पहले:
| इनपुट | तत्काल जाँच |
|---|---|
ActionEnvelope | RFC 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 | घोषित पश्च-शर्त को सत्य पाया गया | true | true | completed |
CommittedUnverified | रनटाइम ने क्रिया की; पश्च-शर्त का कोई प्रमाण नहीं | false | true | committed_unverified |
Failed | कमिट नहीं हुआ, या साक्ष्य पोस्टकंडीशन का खंडन करता है | false | false | verification_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: false | Failed — एक स्पष्ट नकारात्मक अवलोकन |
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को भी कभी नहीं पढ़ा, इसलिए एक समाप्त हो चुका लीज़ और किसी अलग एप्लिकेशन के लिए स्कोप किया गया लीज़ दोनों स्वीकार कर लिए गए। एक अपरिवर्तनीय समाप्ति को अनदेखा करने के बजाय अस्वीकार किया जाता है: जिस लीज़ की वैधता स्थापित नहीं की जा सकती, वह वैध नहीं है।