यह वह tool है जिसे Claude Code तब call करता है जब उसे किसी fail हुए GitNest check को फिर से चलवाना हो। नीचे इसे ठीक वैसे ही दिखाया गया है जैसे osFoundry का live MCP endpoint इसे tools/list में दिखाता है (catalogue के लिए token की ज़रूरत नहीं):
{
"name": "propose_gitnest_check_rerun",
"description": "Ask the repository owner to retry one finished check on a specific composed change-set version. Approval rechecks repository access, version, commit and check state.",
"inputSchema": {
"type": "object",
"properties": {
"repository_id": {"type": "string"},
"change_set_id": {"type": "string"},
"check_name": {"type": "string", "maxLength": 200},
"expected_change_set_version": {"type": "integer", "minimum": 1},
"expected_composition_oid": {"type": "string"},
"idempotency_key": {"type": "string", "minLength": 8, "maxLength": 128}
},
"required": ["repository_id", "change_set_id", "check_name",
"expected_change_set_version", "expected_composition_oid", "idempotency_key"],
"additionalProperties": false
},
"annotations": {"readOnlyHint": false, "openWorldHint": false, "destructiveHint": true},
"securitySchemes": [{"type": "oauth2", "scopes": ["osfoundry:write"]}]
}
इसका read वाला साथी दो arguments लेता है: list_gitnest_checks {repository_id, change_set_id}, "bounded check status for the current composed commit of a change set"। फ़ैसले के लिए दो और reads काम आते हैं: list_gitnest_saved_results (limit 1–50) और read_gitnest_work (kind में tasks, changes या runs)। तीनों osfoundry:read हैं और readOnlyHint: true रखते हैं।
सिर्फ़ एक check दोबारा चलाने के लिए छह required fields काफ़ी ज़्यादा हैं। CI बटन को बस एक job ID चाहिए। जो दो fields ज़्यादा हैं, यानी version और commit, यह पोस्ट उन्हीं के बारे में है। इस Mac पर कोई claude binary installed नहीं है, इसलिए client का काम checks_sim.py करता है। code और उसका पूरा output code/ में है।
जब agent checks पढ़ता है, तो "green" का मतलब क्या है?
कुछ भी propose करने से पहले agent को check list सही पढ़नी होती है। osFoundry की GitNest UI किसी commit के check runs का सार एक छोटे pure function (check-runs.ts में summarise) से निकालती है। उसके tests का क्रम ही नियम है:
- एक भी run नहीं है तो
none, कभीpassedनहीं। - कोई भी
failure,timed_outयाcancelledहो तोfailed। - जो कुछ भी अभी
successनहीं है, वह state कोrunningपर रखता है, उस status समेत जिसे client पहचानता नहीं। - इसके बाद ही
passed।
script इस नियम को port करती है और उसकी तुलना उन दो shortcuts से करती है जो model अपने आप लिख देता है:
== verdict ==
case summarise no-failure ratio
no checks none green green
all passed passed 2 green green
one queued running 1/2 green red
one failed failed: e2e red red
one timed out failed: e2e green red
one cancelled failed: e2e green red
unknown status running 1/2 green red
shortcut wrong: no-failure 5/7, ratio 1/7
"कुछ fail नहीं हुआ, तो green है" वाला तरीका 7 में से 5 cases में गलत है। यह बिना जाँचे commit को green कहता है, queue में पड़े check को green कहता है और timeout को भी green कहता है। ratio वाला check (passed == total) बेहतर है, लेकिन शून्य checks पर 0 == 0 होता है और यह भी green कह देता है। GitNest के code comments इसी case को सबसे भ्रामक बताते हैं, क्योंकि जिस commit पर कोई check नहीं चला, वह verify हुआ ही नहीं। UI इसे "No checks have run against this commit" के रूप में दिखाती है, बिना tick के।
अगर आप Claude Code से "क्या green है?" का जवाब चाहते हैं, तो ये चार नियम उसे CLAUDE.md में दें। tool status लौटाता है, फ़ैसला नहीं।
rerun के साथ version और commit क्यों जाते हैं?
क्योंकि approve करने वाला व्यक्ति एक खास commit देख रहा होता है, और उसके click करने से पहले change set बदल सकता है।
GitNest में change set को saved results से जोड़कर एक commit बनाया जाता है। अगर उसे दोबारा compose किया जाए, किसी नए saved result या खिसके हुए base की वजह से, तो उसे नया version और नया composed commit मिलता है, और उसके checks फिर से शुरू होते हैं। rerun का proposal किसी इंसान का इंतज़ार करता है। अगर उसमें सिर्फ़ "rerun e2e on cs_4e81a0" लिखा हो, तो approval उस वक़्त change set जो भी है उस पर e2e चला देगा, जो शायद ऐसा commit हो जिसे owner ने कभी देखा ही नहीं।
checks_sim.py इसी इंतज़ार को model करती है। हर trial एक proposal है। agent version 3, commit A पढ़ता है, जिसमें e2e fail है। owner का review time log-normal है, जिसका median 8 मिनट है। यह एक assumption है, measurement नहीं। इंतज़ार के दौरान change set Poisson process की तरह recompose होता है, औसतन हर 45 मिनट में, और recompose के बाद checks चलने में 4 मिनट लगते हैं। 10% trials में दूसरे Claude Code session ने वही failure पढ़कर अपनी key के साथ अपना proposal भेजा, और owner दोनों को approve करता है। approval के समय तीन guards, हर एक के 10,000 trials:
== approval-time guards (n=10000, review median 8 min, recompose mean every 45 min, 10% second session) ==
guard ran on reviewed commit ran on unreviewed commit duplicate run refused (stale) refused (not finished)
none 7789 1411 1764 0 0
version+oid 7789 0 740 2435 0
full 7789 0 0 2435 740
बिना guard के 1,411 approvals ने ऐसे commit पर check दोबारा चलाया जिसे owner ने review नहीं किया था, और 1,764 ने ऐसा check queue किया जो पहले से queue में था या चल रहा था। approval के समय version और commit की तुलना करने से unreviewed runs 0 हो जाते हैं, और बदले में 2,435 पुराने cards reject होते हैं। बचे हुए 740 duplicates दूसरे sessions के हैं: वही version, वही commit, लेकिन पहला approval check को पहले ही दोबारा queue कर चुका था। तीसरा guard, "क्या यह check अब भी finished है?", इन्हें पकड़ता है। tool description में यही पूरा set लिखा है: "Approval rechecks repository access, version, commit and check state."
recompose rate वह input है जिस पर सबसे कम भरोसा है, इसलिए तीन rates पर बिना guard वाली row यह रही:
== sensitivity: unreviewed-commit runs with guard 'none' ==
recompose every 15 min unreviewed 2449 duplicates 3128
recompose every 45 min unreviewed 1411 duplicates 1764
recompose every 180 min unreviewed 452 duplicates 1208
हर तीन घंटे में बदलने वाला change set भी हर 10,000 में 452 गलत-commit runs देता है। happy path पर guard की कोई कीमत नहीं: reviewed commit वाली गिनती तीनों rows में 7,789 है।
version और commit दोनों क्यों?
इस model में दोनों हमेशा साथ बदलते हैं, इसलिए अकेले किसी एक का score भी वही आता। लेकिन दोनों अलग सवालों का जवाब देते हैं। version change set का अपना counter है, जो उसका content बदलने पर बदलता है। commit वह है जिस पर checks असल में चले, और card पर यही "Reviewed commit: …" के रूप में छपता है। client से दोनों भेजवाने का मतलब है कि server किसी भी एक के आधार पर मना कर सकता है, और owner card पर internal counter नहीं, commit hash पढ़ता है। schema version को integer ≥ 1 के रूप में enforce करता है। commit एक free string है, इसलिए उसकी जाँच server पर होती है।
call से पहले schema क्या पकड़ लेता है?
script jsonschema से arguments को live inputSchema के ख़िलाफ़ validate करती है:
== propose_gitnest_check_rerun arguments ==
ok PASS
no oid REJECT 'expected_composition_oid' is a required property
version 0 REJECT 0 is less than the minimum of 1
version as string REJECT '3' is not of type 'integer'
two checks REJECT ['e2e', 'lint'] is not of type 'string'
check 201 chars REJECT 'ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
key 7 chars REJECT 'abcdefg' is too short
extra 'force' REJECT Additional properties are not allowed ('force' was unexpected)
required: repository_id, change_set_id, check_name, expected_change_set_version, expected_composition_oid, idempotency_key
इनमें से दो rejections design का हिस्सा हैं, सिर्फ़ साफ़-सफ़ाई नहीं। check_name string है, list नहीं, इसलिए "सब कुछ दोबारा चलाओ" का मतलब है हर check के लिए एक card, और owner हर एक पर अलग फ़ैसला करता है। और additionalProperties: false की वजह से जो model अपनी तरफ़ से "force": true जोड़ दे, उसे चुपचाप ignore होने वाले flag की जगह error मिलता है।
idempotency key इस बात से बननी चाहिए कि proposal किस बारे में है, attempt से नहीं। script "rerun-" + sha256(change_set_id, version, oid, check_name)[:32] इस्तेमाल करती है:
key retry same: True key after recompose same: False len 38
response खो जाने के बाद retry वही key भेजता है और दूसरा card नहीं बनता। recompose से key बदल जाती है, इसलिए नए commit का proposal नया card होता है, और यही सही है।
ये tools कितने भारी हैं, और server कितनी दूर है?
== tools/list ==
59 tools, 48140 B via json.dumps, 12722 tok (cl100k)
list_gitnest_checks 612 B 158 tok readOnly=True destructive=False scope=osfoundry:read
list_gitnest_saved_results 707 B 182 tok readOnly=True destructive=False scope=osfoundry:read
read_gitnest_work 685 B 189 tok readOnly=True destructive=False scope=osfoundry:read
propose_gitnest_check_rerun 1011 B 268 tok readOnly=False destructive=True scope=osfoundry:write
all 13 gitnest tools 11227 B 3009 tok
13 GitNest tools catalogue के लगभग एक-चौथाई tokens लेते हैं (tiktoken cl100k_base से गिने गए, इसलिए इन्हें अनुमान मानें)। जापान में इस Mac से live endpoint पर हर तरह की दस unauthenticated calls:
$ python3 probe.py
initialize HTTP 200 308 B median 566 ms min 326 max 807
capabilities: {"tools": {"listChanged": false}}
tools/list HTTP 200 45368 B median 722 ms min 420 max 1406
tools/call list_gitnest_checks HTTP 401 337 B median 552 ms min 409 max 903
401 में error_description="Connect osFoundry to continue" और एक resource_metadata URL होता है, और यही Claude Code को उसके OAuth flow में भेजता है। initialize कोई push advertise नहीं करता, इसलिए client को कुछ नहीं बताता कि retry approve हो गया या check पूरा हो गया। check का इंतज़ार यानी आपकी मशीन पर runner का काम और एक इंसान का click, मिनटों का मामला, milliseconds का नहीं। सस्ता pattern यह है कि propose करने के बाद turn खत्म करें, और जब user कहे कि उसने approve कर दिया, तब एक बार list_gitnest_checks call करें।
check असल में चलाता कौन है?
osFoundry नहीं। GitNest का runner panel कहता है कि checks "run on your machine, not ours"। एक registered runner अपने token से poll करता है (OSF_RUNNER_TOKEN=… osfoundry-runner --api https://api.osfoundry.io), और runner के बिना checks "stay queued"। retry approve करने से check सिर्फ़ दोबारा queue होता है। Claude Code के पास runner token कभी नहीं होता, और read tools local bindings और credentials शामिल नहीं करते। agent देख सकता है कि e2e fail हुआ। आपके और आपके runner के बिना वह कुछ भी execute नहीं करवा सकता।
अगर आप इसे खुद जोड़ रहे हैं
- verdict वाला नियम client के instructions में डालें, सिर्फ़ अपनी UI में नहीं। "कोई check नहीं" और "अनजान status" ही वे जगहें हैं जहाँ agents green बता देते हैं।
- rerun में वह commit लिखवाएँ जिस पर review हुआ था, और तुलना approval के समय करें, proposal के समय नहीं।
- approval के समय check की अपनी state भी दोबारा जाँचें। version और commit एक ही failure के दो proposals नहीं पकड़ते।
- एक proposal में एक ही check लें। list देने से flaky test का retry एक ऐसा blanket rerun बन जाता है जिसे किसी ने चुना ही नहीं।
- idempotency key को (change set, version, commit, check) से बनाएँ, ताकि retries एक हो जाएँ और recomposes नहीं।
- execution को platform और agent दोनों से दूर रखें: token runner के पास, बटन इंसान के पास।
checks panel वाला change-set review page GitNest page पर है। protocol के बारे में जानने के लिए MCP glossary entry देखें।
Top comments (0)