npm, Cargo, Composer और pip सभी एक ही semver shorthand को अलग-अलग तरह से समझते हैं, और मेरे द्वारा टेस्ट किए गए तेरह range expressions में से केवल दो ही चारों में एक समान व्यवहार करते हैं।

मैंने प्रत्येक मैनेजर के लिए अलग-अलग parsers लिखे, उनके आधिकारिक specs का पालन किया, और फिर हर range को उन्नीस version numbers के मैट्रिक्स के विरुद्ध चलाया। 13 × 19 ग्रिड (247 cells) ने एक खंडित तस्वीर पेश की: केवल 17 cells ने ही हर टूल से एक जैसा "हाँ" या "नहीं" उत्तर दिया, और उन 17 में से अधिकांश एकमत रूप से अस्वीकृत (rejections) थे। संक्षेप में, टूल्स "हाँ" की तुलना में "नहीं" पर कहीं अधिक सहमत होते हैं।

टूल्स में भिन्नता क्यों है

चारों मैनेजर Semantic Versioning का पालन करने का दावा करते हैं, फिर भी प्रत्येक अपने स्वयं के shorthand नियम जोड़ता है।

  • Caret (^) और dot-x – npm caret को सपोर्ट करता है; pip caret और dot-x दोनों को नज़रअंदाज़ कर देता है। अकेले यही बात npm और pip के बीच 49-cell का मतभेद पैदा करती है।
  • Bare versions – Cargo एक साधारण 1.2.3 को caret range के रूप में मानता है, जिसका अर्थ है "1.x के साथ संगत (compatible)"। npm और Composer उसी स्ट्रिंग को exact match के रूप में पढ़ते हैं, और केवल 1.2.3 को ही स्वीकार करते हैं।
  • Tilde (~) – Cargo का tilde minor version को पिन करता है (~1.2, 1.2.* से मेल खाता है लेकिन 1.3.0 से नहीं)। Composer का tilde *major* version को पिन करता है (~1.2, 1.*` से मेल खाता है)। दोनों व्याख्याएँ किसी भी ऐसे version पर अलग हो जाती हैं जो minor component को बदलता है।

Pre-release हैंडलिंग एक और आश्चर्य पैदा करती है। ^1.2.3 जैसा range 2.0.0-rc.1 को शामिल नहीं करता है, भले ही इसका numeric भाग upper bound से कम हो। नियम यह है: pre-releases को तब तक बाहर रखा जाता है जब तक कि range में स्पष्ट रूप से pre-release identifier का उल्लेख न किया गया हो।

एकमात्र सुरक्षित cross-tool syntax

प्रयोग से पता चलता है कि explicit inequality ranges—जैसे कि >=1.2.0 <2.0.0—npm, Cargo, Composer और pip में एक ही तरह से व्यवहार करते हैं। प्रत्येक मैनेजर दोनों सीमाओं (boundaries) को literal numeric limits के रूप में मानता है, जिसमें कोई छिपा हुआ caret या tilde semantics नहीं होता है।

यदि आपको "कोई भी 1.x version जो कम से कम 1.2 हो" व्यक्त करने की आवश्यकता है, तो इसे पूरी तरह से लिखें। इसमें कुछ अतिरिक्त characters लगते हैं; लेकिन यह गारंटी देता है कि जहाँ भी कोड चले, वहाँ resolution पूर्वानुमेय (predictable) हो।

जब shorthand का उपयोग करना अभी भी सही है

Single-language projects के लिए shorthand अभी भी आकर्षक है। एक शुद्ध npm ecosystem के भीतर, ^1.2.3 संक्षेप में "भविष्य के minor और patch releases के साथ संगत" होने को दर्शाता है। यही बात Cargo के caret या Composer के tilde के लिए भी लागू होती है जब आपको पता हो कि consuming tool नहीं बदलेगा। खतरा तब पैदा होता है जब एक ही manifest का उपयोग विभिन्न भाषाओं के बीच किया जाता है, या जब कोई CI job कई ecosystems से dependencies खींचता है।

निष्कर्ष

Cross-language compatibility के लिए semver shorthand पर भरोसा करना एक जुआ है। यह सुनिश्चित करने का एकमात्र विश्वसनीय तरीका कि version constraint का हर जगह एक ही अर्थ है, explicit inequalities लिखना है। जब आपको संक्षिप्तता (brevity) की आवश्यकता हो, तो एक ही ecosystem के भीतर रहें; जब आपको निरंतरता (consistency) की आवश्यकता हो, तो स्पष्टता के लिए shorthand का त्याग कर दें।