परिचय: वह gate जो done मानने से इनकार करता है
Shopify जिस अर्थ में gate कहता है, वह एक जाँच है जिसे AI से लिखे बदलाव को आगे बढ़ने से पहले पास करना होता है। Claude Code में दोबारा बनाने पर सिर्फ़ पहला gate फ़ायदेमंद निकला: acceptance tests। Shopify ने चार gates प्रकाशित किए पर कोई आँकड़ा नहीं दिया, इसलिए यह प्रयोग उन्हें एक असली repository पर बनाता है, हर बार एक gate बंद करके पचास अनुरोध चलाता है, और गिनता है कि हर gate ने क्या पकड़ा और उसकी क्या क़ीमत रही।
Helix 21 सितंबर 2026 को सार्वजनिक हुआ। वह हर checkpoint को क्रम से चार gates से गुज़ारता है: tests, design review, दो reviewers और एक engineer। पोस्ट में pass rate नहीं दिया गया है। Reviewers वह हिस्सा हैं जिसकी सबसे ज़्यादा नक़ल होती है, और इन पचास runs में pass rate तभी हिला जब tests loop में थे। Reviewers ने कुछ नहीं जोड़ा, और लागत लगभग तीन गुना रही।
इसी bench से दो और नतीजे निकलते हैं। जिस hook को override नहीं किया जा सकता माना जाता है, उसके अपने documentation में तीन निकास हैं। और जब tests और reviewers असहमत हुए, तो agent ने ऐसा कुछ किया जिसकी किसी ने योजना नहीं बनाई थी। गिनती उस मामले से शुरू होती है जिसमें कोई gate नहीं है।
चार gates, शून्य आँकड़े, एक bench
Bench repository tinydb है, एक असली document database, और इस्तेमाल किए गए commit पर 226 tests हरे हैं।
Helix Shopify का आंतरिक tool है जो उसके mobile apps को वापस native code में ले जाता है। उसकी पोस्ट नियम सीधे शब्दों में कहती है: हर checkpoint क्रम से चार gates से गुज़रता है।
| Gate | Shopify की पोस्ट में यह क्या करता है |
|---|---|
| Behaviour | Tests चलाता है जहाँ हर प्रासंगिक case को पास होना होता है |
| Design | दूसरे model से perfectionist design reviewer की भूमिका निभाने को कहता है |
| Review | दो स्वतंत्र, context-isolated reviewer agents; loop तब तक दोहराया जाता है जब तक दोनों मंज़ूर न कर दें |
| Engineer | एक इंसान loop बंद करता है |
इस design को बेचने वाला वाक्य है "An attempt is allowed to be wrong. It is not allowed to ship until it isn't." Library के लिए design gate हट जाता है, और पोस्ट कहती है कि सिर्फ़ logic वाला बदलाव उसे छोड़ देता है।
पोस्ट कोई संख्या नहीं देती। Shop app 12 हफ़्तों में दोबारा बनी और Shopify app में 300 से ज़्यादा screens हैं, और पूरा हिसाब बस इतना ही है। न pass rate है, न लागत, न यह गिनती कि कितने defects निकल गए।
Bench पाँच अनुरोध हैं, उसी तरह लिखे हुए जैसे एक developer लिखता है: push और pull operations, एक between query, एक table का नाम बदलना, एक sorted search और write cache का आकार। हर अनुरोध के पीछे पाँच छिपी ज़रूरतें हैं जिन्हें agent कभी नहीं देखता, वे बातें जिनकी एक सावधान senior engineer अपेक्षा करेगा। यानी कुल 25 ज़रूरतें।
Worker Sonnet 5.5 है, headless चलाया गया। पाँच configurations गुणा पाँच tasks गुणा दो दोहराव से 50 runs बनते हैं। एक चेतावनी लागू होती है: इन अनुरोधों के स्पष्ट संस्करण एक ही बार में पास हो जाते हैं, इसलिए prompts को उतना छोटा किया गया जितना लोग असल में लिखते हैं।
बिना किसी gate के 50 में से 35 ज़रूरतें पास होती हैं। यह 70% है, और दस में से तीन runs पूरी तरह साफ़ रहे।
Sort task दिखाता है कि चूक कैसी दिखती हैं। Agent ने हर document को sort field के साथ index किया, और जैसे ही किसी एक document में वह field नहीं होती, पूरा search crash हो जाता है। पाँच ज़रूरतें, शून्य पास, एक गायब key।
वह hook जो done मानने से इनकार करता है, और उसके तीन रास्ते
Stop hook एक script है जिसे Claude Code तब चलाता है जब भी agent अपना turn ख़त्म करने की कोशिश करता है। Anthropic की अपनी guide उस समस्या का नाम लेती है जिसे यह हल करता है: Claude तब रुक जाता है जब काम पूरा दिखता है। ऐसी जाँच के बिना जिसे वह चला सके, "दिखता है कि पूरा है" ही एकमात्र संकेत है, और आप ख़ुद verification loop बन जाते हैं।
Hook project की settings file में hooks, Stop के नीचे रहता है, एक command के रूप में जिसके साथ timeout होता है। यहाँ वह एक पंक्ति का wrapper है जो gate script को बुलाता है। अनुबंध exit code है: 0 turn को ख़त्म होने देता है, 2 उसे रोकता है, और script ने standard error पर जो भी छापा वह कारण बनकर agent के पास लौटता है।
व्यवहार में यह ऐसे चलता है। Agent अपने बदलाव का सार देता है और रुकता है। Hook acceptance tests चलाता है, एक fail होता है, और turn ख़त्म नहीं होता। Agent failure को hook feedback के रूप में पढ़ता है, इस मामले में एक test जिसने type error की अपेक्षा की थी और वह नहीं मिला, code ठीक करता है और फिर रुकता है। इस बार gate चुप रहता है।
Prompt में लिखा नियम सलाह है। Hook सलाह नहीं है। फिर भी उसी documentation पेज पर तीन निकास गिनाए गए हैं।
| निकास | Documentation क्या कहती है |
|---|---|
| Cap | जब stop hooks लगातार 8 बार turn को आगे बढ़ा चुके हों, तो Claude Code अगले block को override करके turn ख़त्म कर देता है। Agent के हर tool बुलाने पर गिनती शून्य हो जाती है, और एक environment variable इसे बढ़ा सकता है। |
| Timeout | Command hook के लिए डिफ़ॉल्ट 600 सेकंड, और जो hook timeout हो जाता है वह कोई फ़ैसला नहीं देता। धीमा test suite अपने आप gate खोल देता है। |
| Flag | Hook input में stop_hook_active होता है, जो तब true होता है जब session पहले से किसी stop hook की वजह से जारी है। Docs कहती हैं कि इसे जाँचें ताकि आप ऐसी शर्त पर कभी block न करें जो हल ही नहीं हो सकती। |
यहाँ का gate उस flag को log करता है और अनदेखा करता है। वह छह blocks के बाद अपने आप हार मान लेता है, ताकि loops गिने जा सकें।
एक और निकास है जिसे कोई documented नहीं करता। एक बार block होने के बाद, agent tests खोजने निकल पड़ा: उसने hook script पर cat चलाया और test file के लिए पूरी disk खंगाली। सिर्फ़ allow list ने उसे रोका। इसलिए acceptance tests repository tree के बाहर रहते हैं, settings hook और छिपे tests को पढ़ने से मना करती हैं, और agent failure देखता है पर file कभी नहीं।
Gate 1: acceptance tests
Acceptance-test gate tests का एक समूह है, implementer से स्वतंत्र रूप से लिखा हुआ, जो तय करता है कि "done" का मतलब क्या है। Shopify का पहला gate agent के अपने tests नहीं हैं। एक subagent हर checkpoint के लिए integration-style test cases बनाता है, happy path से आगे के edge cases पर ज़ोर देते हुए, और वही tests तय करते हैं कि प्रमाणित का मतलब क्या है।
इसलिए यहाँ writer एक अलग headless Sonnet है। वह अनुरोध और बदलाव से पहले की repository को देखता है, सिर्फ़ पढ़ने के लिए, code नहीं चला सकता, और उससे कहा गया है कि वह हर उस व्यवहार के लिए एक test लिखे जिसकी एक सावधान senior अपेक्षा करेगा: गायब fields, ग़लत types, सीमाएँ, persistence, cache, और मौजूदा व्यवहार का न बदलना। वह लगभग 40 सेकंड में 23 से 53 के बीच tests लिखता है, औसतन 39। File repository के बाहर रखी जाती है, इसलिए जब कोई test fail होता है तो agent assertion पढ़ता है, test कभी नहीं।
अकेले tests pass rate को 70% से 84% तक ले जाते हैं: 50 में से 42 ज़रूरतें, और तीन की जगह छह पूरी तरह साफ़ runs।
| Task | Tests के बिना | Tests के साथ |
|---|---|---|
| Sorted search | 10 में से 5 | 10 में से 10 |
| Write cache size | 10 में से 8 | 10 में से 10 |
| Push और pull | 10 में से 4 | 10 में से 4 |
Sort task में गायब field वाला crash ठीक उसी तरह का case है जिसके बारे में writer पूछता है। Cache task के लिए, writer ने एक से छोटे cache size पर value error की माँग की।
Push और pull task नहीं हिलता। उसमें तीन ज़रूरतें छूटती हैं, जिनमें से दो उस document के बारे में हैं जिसमें field नहीं है, और अनुरोध में इस बारे में कुछ कहा ही नहीं गया था। Writer ठीक वहीं अटकल लगाता है जहाँ prompt चुप है: उसका test raise या चुपचाप कुछ न करना, दोनों स्वीकार करता है, इसलिए gate वह ज़रूरत वापस नहीं ला सकता जिसे किसी ने कहा ही नहीं।
Tests वाले 30 gated runs में, gate ने agent को 28 बार लौटाया जब कोई असली ज़रूरत fail हो रही थी, और पाँच बार जब सब पास थीं। उन पाँच में से एक rename task था: writer चाहता था कि string न होने वाले नाम अस्वीकार हों, किसी ने यह माँगा नहीं था, और agent ने इस वजह से एक round गँवाया।
इस gate का पहला संस्करण implementer के अपने tests दोबारा चलाता था। उसने हर run को पहले stop पर जाने दिया जबकि कोई छिपी ज़रूरत fail थी, क्योंकि agent के अपने tests वही जाँचते हैं जो उसने बनाया।
इस gate की क़ीमत $0.085 की जगह $0.20 प्रति run है, और 33 की जगह 60 सेकंड।
Gate 3: दो reviewers, जैसा Shopify ने लिखा
Review gate reviewer agents की एक जोड़ी है, जिनमें से हर एक नए context में काम करता है। Shopify के शब्द: दो स्वतंत्र, context-isolated reviewer agents नए code को जाँचते हैं, हर finding ठीक करनी होती है, और loop तब तक दोहराया जाता है जब तक दोनों reviewers मंज़ूर न कर दें। Anthropic की guide बताती है कि isolation क्यों मायने रखता है: नए context में reviewer सिर्फ़ diff और वे मापदंड देखता है जो आप उसे देते हैं, वह तर्क नहीं जिससे बदलाव निकला।
यहाँ हर reviewer एक headless Sonnet है जिसके पास सिर्फ़ पढ़ने वाले tools हैं और अधिकतम 15 turns। वह structured JSON में फ़ैसला लौटाता है: एक approve flag और findings, हर एक की severity blocking या minor। दोनों reviewers अनुरोध और पूरे diff पर साथ-साथ चलते हैं, उनकी findings मिला दी जाती हैं, और gate तब block करता है जब उनमें से कोई भी कुछ blocking पाए। एक जोड़ी की क़ीमत प्रति stop 3 से 6 cents है।
| Configuration | पास हुई ज़रूरतें | Pass rate | Blocks |
|---|---|---|---|
| कोई gate नहीं | 50 में से 35 | 70% | कोई नहीं |
| सिर्फ़ reviewers | 50 में से 34 | 68% | 10 में से 1 run |
| सिर्फ़ tests | 50 में से 42 | 84% | 10 में से 6 runs (3 सही, 3 ग़लत) |
| Tests के बाद reviewers | 50 में से 41 | 82% | 10 में से 2 runs, दोनों सही |
सिर्फ़ reviewers बिना किसी gate से दो अंक नीचे रहते हैं, और tests के बाद reviewers सिर्फ़ tests से दो अंक नीचे।
Sort task इस संख्या को समझाता है। एक run में दोनों reviewers ने block किया: sorting document को index करती है, field के बिना एक document key error उठाता है, और पूरा search fail हो जाता है। Agent ने उसे ठीक किया और पाँच में से पाँच पास किए।
दो दूसरे runs में दोनों reviewers ने ठीक वही crash देखा और उसे minor माना। Sort field के बिना document एक सादा key error उठाता है, और docstring में यह दर्ज है। दोनों reviewers ने मंज़ूर कर दिया, और दोनों runs पाँच में से शून्य पर ख़त्म हुए। वही model, वही diff, वही bug, दो अलग severities। जब reviewers ने block किया तब वे कभी ग़लत नहीं थे। समस्या यह है कि वे क्या निकल जाने देते हैं।
अगस्त के एक paper ने एक सार्वजनिक benchmark पर यही आकार नापा। Zero-shot का स्कोर 77% रहा, एक reviewer का 77%, और दो स्वतंत्र reviewers का 75%, सब बिना review के नतीजे के noise के भीतर।
| LiveCodeBench पर setup | Score |
|---|---|
| Zero-shot | 77% |
| एक reviewer | 77% |
| दो स्वतंत्र reviewers | 75% |
| Reviewer और critic (adversarial review) | 87% |
Reviewer और critic, और वह loop जो कभी खत्म नहीं होता
Adversarial review एक reviewer है जिसके साथ एक critic जुड़ा है, जो main agent के बदलाव करने से पहले structured असहमति के ज़रिए review को परखता है। उसी paper ने पाया कि यही आकार काम करता है। उसने 87% स्कोर किया जहाँ दो reviewers ने 75%, और उसने 82% वाले सबसे मज़बूत पाँच-agent baseline को भी पीछे छोड़ा।
| Benchmark | Zero-shot | Adversarial review के साथ | लागत |
|---|---|---|---|
| SWE-bench | 71.6 | 75.2 | लगभग 4.5x tokens |
इसलिए critic को gate में रखा गया। Reviewer A review करता है। Critic B को findings और diff मिलते हैं और वह हर finding पर upheld या rejected की मुहर लगाता है। सिर्फ़ upheld blocking finding ही gate को बंद करती है।
इस repository पर नतीजा 50 में से 39 रहा, यानी 78%। Critic की जोड़ी ने दस runs में शून्य बार block किया। Validation के दौरान उसने एक ग़लत finding को ज़रूर अस्वीकार किया, जिस पर दो-reviewer वाला आकार block कर देता।
Critic जो ठीक नहीं कर सका वह loop है। तीन runs एक ही acceptance test पर छह blocks तक पहुँचे, और gate ने हार मान ली जबकि असली ज़रूरत हर stop पर fail ही रही। उनमें से दो में block करने वाला test writer की अपनी ग़लती था, और agent ने यह कहा भी: वह ऐसे test के लिए code नहीं बदलेगा जिसे वह पढ़ नहीं सकता।
तीसरा वह है जिसे याद रखना चाहिए। Acceptance test चाहता था कि fail होने वाला update हर document को जस का तस छोड़े, इसलिए agent ने table की update method को दोबारा लिख दिया। Reviewers ने इसे block किया, क्योंकि update method में बदलाव माँगा नहीं गया था और task दो नए functions का था। Agent ने उसे वापस पलट दिया। उसका आख़िरी संदेश था कि acceptance test और code review उल्टी बातें माँग रहे हैं, इसलिए वह कुछ बदले बिना रुक गया है। छह blocks बाद counter ने उसे बाहर जाने दिया।
यहाँ हार मानने का बिंदु छह पर है। Claude Code का अपना cap लगातार आठ blocks है और हर tool call पर शून्य हो जाता है, इसलिए पचास runs में वह एक बार भी नहीं चला।
Gate 4 आप हैं: इंसान तक क्या पहुँचा, बिल, और kit
चौथा gate engineer है, और Shopify की पोस्ट वादा करती है कि जब कोई देख नहीं रहा होता तब gates ढीले नहीं पड़ते। Engineer तक वही पहुँचता है जो बाक़ी gates निकल जाने देते हैं। नीचे का हिसाब बताता है कि किस gate ने अपनी क़ीमत वसूली।
| Configuration | 50 में से पास | Pass rate | प्रति run लागत | इंसान के लिए बचा |
|---|---|---|---|---|
| कोई gate नहीं | 35 | 70% | $0.085 | 15 |
| Acceptance tests | 42 | 84% | $0.20 | 8 |
| सिर्फ़ reviewers | 34 | 68% | $0.15 | 16 |
| Reviewers के साथ tests | 41 | 82% | $0.28 | 9 |
| Reviewer और critic के साथ tests | 39 | 78% | $0.28 | 11 |
हर gated पंक्ति प्रति run 54 से 86 सेकंड लेती है, जबकि बिना gate के 33।
सभी पचास runs में blocks का बँटवारा यह है। Tests ने agent को 28 बार सही तरह से और पाँच बार ग़लत तरह से लौटाया। Reviewers ने तीन बार block किया, कभी ग़लत नहीं, और तीन loops ने हार मान ली। पूरे matrix पर list-price API spend $9.95 रहा, जैसा CLI बताता है, और जोड़ा हुआ worker समय लगभग 3,136 सेकंड, यानी 52 मिनट।
इस जैसी repository के लिए फ़ैसला: test gate रखें, ऐसे writer के साथ जो implementer नहीं है और ऐसे tests के साथ जिन्हें agent बदल नहीं सकता। छह में लगभग एक ग़लत block की अपेक्षा रखें, और loop को एक counter दें। Shopify ने जैसा लिखा, दो-reviewer gate ने यहाँ pass rate नहीं हिलाया, किसी भी आकार में। अगर आप उसे रखते हैं, तो उसे feedback में सलाह के रूप में रखें, बाधा के रूप में नहीं।
रास्ते में एक जाल। Docs एक bare flag बताती हैं जो scripted calls के लिए hooks, skills, plugins और memory को छोड़ देता है। Subscription login पर वह सिर्फ़ API key पढ़ता है और error लौटाता है, इसलिए हर reviewer को इसके बजाय खाली settings source और बंद hooks के साथ अलग किया गया है।
सीमाएँ असली हैं: एक repository, एक worker model, पाँच tasks, हर cell में दो दोहराव। पंक्तियों के बीच दो अंक का अंतर noise है। बिना gate और test gate के बीच के चौदह अंक noise नहीं हैं। Design gate बनाया नहीं गया था, और engineer का समय नापा नहीं गया।
Shopify के चार gates में से, इस repository पर, सिर्फ़ tests काम आए। पूरा kit मुफ़्त pack में है: hook और deny list वाली settings file, stop script, gate, writer और reviewer commands उनके schemas के साथ, और ledger template।
AIDive