8 मिनट पढ़ें

एजेंट कमांड टेस्ट में रिमोट लोकेल सेटिंग

रिमोट लोकेल सेटिंग तारीख, क्रम, दशमलव और टेक्स्ट डिकोडिंग बदलती हैं। वातावरण तय करें, उसे दर्ज करें और जानबूझकर अलग सेटिंग जाँचें।

एजेंट कमांड टेस्ट में रिमोट लोकेल सेटिंग

कोई एजेंट उन्हीं आर्ग्युमेंट और उन्हीं फाइलों पर वही कमांड चला सकता है, फिर भी रिमोट होस्ट पर उसे अलग उत्तर मिल सकता है। गायब इनपुट अक्सर प्रोसेस का लोकेल होता है। यह बदलता है कि सामान्य टूल टेक्स्ट को कैसे वर्गीकृत करते हैं, नामों को किस क्रम में रखते हैं, संख्याएँ और तारीखें कैसे दिखाते हैं, कौन सी एन्कोडिंग चुनते हैं और त्रुटि संदेश कैसे लिखते हैं।

लोकेल को मशीन की सजावट नहीं, टेस्ट डेटा मानें। जब टेस्ट को स्थिर प्रोटोकॉल चाहिए तब इसे तय करें, जब कोड मानवीय परंपराएँ संभालने का दावा करता है तब इसे बदलकर जाँचें, और जब एजेंट किसी प्रोसेस या SSH सीमा को पार करता है तब इसे दर्ज करें। वरना स्थानीय रूप से सफल टेस्ट रिमोट पार्सिंग की गलती छिपा सकता है, जब तक एजेंट गलत पंक्ति, रकम या तारीख पर कार्रवाई न कर दे।

इसका अर्थ हर जगह अंग्रेजी थोपना नहीं है। मशीन इंटरफेस और मनुष्य के इंटरफेस के काम अलग हैं। स्थिर मशीन आउटपुट को स्पष्ट प्रारूप और वातावरण चाहिए। उपयोगकर्ता के लिए आउटपुट का स्थानीयकरण सोच समझकर होना चाहिए। दोनों को मिलाने पर अनुवादित निदान संदेश को स्थिति मानकर पार्स किया जा सकता है, या दशमलव का कॉमा चुपचाप गलत मान बन सकता है।

परिणाम रिमोट प्रोसेस तय करता है

प्रभावी लोकेल उस प्रोसेस का होता है जो वास्तव में कमांड चलाता है। आपके लैपटॉप का लोकेल SSH से चल रहे प्रोग्राम को तब तक नियंत्रित नहीं करता, जब तक कोई व्यवस्था उन वेरिएबल को साफ तौर पर भेजे या सेट न करे। रिमोट इंटरैक्टिव shell भी गैर इंटरैक्टिव कमांड सत्र जैसा हो, यह जरूरी नहीं है।

POSIX.1-2024 प्राथमिकता को साफ परिभाषित करता है। खाली न होने वाला LC_ALL हर श्रेणी को बदल देता है। उसके न होने पर LC_TIME या LC_COLLATE जैसा श्रेणी वेरिएबल अपनी श्रेणी के लिए लागू होता है। जो श्रेणियाँ अब भी सेट नहीं हैं, उनके लिए LANG डिफॉल्ट देता है। इसलिए विरासत में मिला LC_ALL=de_DE.UTF-8 मौजूद हो तो LANG=C का कोई असर नहीं होता।

OpenSSH एक और सीमा जोड़ता है। उसके क्लाइंट मैनुअल के अनुसार SendEnv भेजे जाने वाले स्थानीय वेरिएबल चुनता है, लेकिन सर्वर को उन्हें स्वीकार भी करना होता है। डिफॉल्ट रूप से क्लाइंट कोई वेरिएबल नहीं भेजता। SetEnv स्पष्ट मान भेजने का अनुरोध कर सकता है, पर उसे भी सर्वर की स्वीकृति चाहिए। डेवलपर की निजी SSH कॉन्फिगरेशन में SendEnv LANG LC_* हो सकता है, जबकि एजेंट का stateless SSH सहायक वह कॉन्फिगरेशन न पढ़ता हो। इसका उलटा भी संभव है। किसी भी नतीजे को पहले से सही न मानें।

लॉगिन की स्टार्टअप फाइलें स्थिति को और उलझाती हैं। कोई वितरण PAM या सिस्टम कॉन्फिगरेशन के जरिए LANG सेट कर सकता है। उपयोगकर्ता की प्रोफाइल इंटरैक्टिव लॉगिन के लिए इसे बदल सकती है। रिमोट कमांड अक्सर उसी स्टार्टअप रास्ते से नहीं गुजरता। उस कमांड से शुरू हुआ कंटेनर अपना लोकेल दे सकता है, और छोटे इमेज में बताए गए लोकेल की फाइलें मौजूद भी नहीं हो सकतीं।

समाधान है कि अंतिम निष्पादन बिंदु पर अपेक्षित वातावरण सेट किया जाए। कमांड को स्थिर लोकेल चाहिए तो forwarding पर निर्भर न रहें। assignment को टूल के साथ रखें:

ssh buildbox 'env LC_ALL=C.UTF-8 TZ=UTC command-to-test --format=plain'

इससे टेस्ट का अनुबंध साफ दिखता है। C.UTF-8 उपलब्ध न होने पर भी गलती ऐसी जगह होती है जहाँ कारण समझ आता है, न कि होस्ट की पसंद चुपचाप विरासत में मिलती है। जब इस लोकेल नाम की उपलब्धता तय न हो, provisioning के दौरान समर्थित लोकेल जाँचें और दस्तावेज में लिखा fallback इस्तेमाल करें।

आउटपुट समझने से पहले वातावरण दर्ज करें

रिमोट विफलता रिपोर्ट में प्रभावी श्रेणियाँ, एन्कोडिंग, समय क्षेत्र, टूल की पहचान और कच्चे bytes होने चाहिए। केवल LANG दर्ज करना काफी नहीं है, क्योंकि LC_ALL या कोई श्रेणी वेरिएबल उसे बदल सकता है। केवल decoded टेक्स्ट रखने से एन्कोडिंग की गलती का सबूत मिट सकता है।

जाँच वाले कमांड से पहले यह छोटा probe चलाएँ:

env | LC_ALL=C sort | sed -n '/^LANG=/p;/^LC_/p;/^TZ=/p'
printf 'charmap='; locale charmap
printf 'decimal='; locale -k decimal_point 2>/dev/null || true
printf 'date='; date +'%Y-%m-%dT%H:%M:%S%z'
printf 'tool='; command -v sort
sort --version 2>/dev/null | sed -n '1p'

सामान्य Linux परिणाम का रूप ऐसा हो सकता है:

LANG=de_DE.UTF-8
LC_NUMERIC=de_DE.UTF-8
TZ=Europe/Berlin
charmap=UTF-8
decimal=decimal_point="," 
date=2026-07-24T143105+0200
tool=/usr/bin/sort
sort (GNU coreutils) 9.5

इस नमूने को expected value न बनाएँ। महत्वपूर्ण बात fields का समूह है। locale के कुछ implementation keyword आउटपुट को अलग तरह से format करते हैं, और दूसरे टूल --version का समर्थन नहीं कर सकते। हर probe का exit status और standard error भी रखें, ताकि अनुपलब्ध feature खाली value न लगे।

एन्कोडिंग की गलती में decode करने से पहले bytes बचाएँ। harness standard output और standard error को अलग फाइलों में लिख सकता है, checksum निकाल सकता है, फिर घोषित एन्कोडिंग से उसकी copy decode कर सकता है। पहले गलत byte के आसपास का hexadecimal आउटपुट, logging layer से डाले गए replacement character से कहीं अधिक उपयोगी होता है।

कमांड किस रास्ते से गया, यह भी दर्ज करें। ssh host command, ssh host sh -lc command, इंटरैक्टिव terminal और agent tool से शुरू प्रोसेस अलग execution path हैं। वे अलग shell, startup file, pseudo terminal और environment filter चुन सकते हैं। विफल रास्ता agent action इस्तेमाल करता है तो उसी रास्ते को दोहराएँ, केवल यह साबित न करें कि हाथ से किया गया login सही चलता है।

परिणाम अलग होने पर यह diagnostic bundle टेस्ट artifact में होना चाहिए। इससे “रिमोट sort कभी कभी बदल जाता है” जैसा अस्पष्ट दावा, ठोस inputs की तुलना बन जाता है।

प्रोटोकॉल के लिए लोकेल तय करें, लोगों के लिए नहीं

जब कमांड आउटपुट parser, snapshot, diff, cache key, deployment decision या किसी दूसरे प्रोग्राम में जाता है, तब स्थिर लोकेल रखें। जब आउटपुट किसी व्यक्ति के लिए हो, तब उसका मांगा हुआ लोकेल इस्तेमाल करें। एक कमांड अभी दोनों आउटपुट देता हो, तब भी वे दो अलग interfaces हैं।

हर जगह LC_ALL=C सेट करने की सलाह लोकप्रिय है, क्योंकि इससे कई Unix टूल अनुमान के अनुसार चलते हैं और POSIX सिस्टम में यह उपलब्ध होता है। इसे सार्वभौमिक नियम मानना गलत है। सिस्टम और runtime के अनुसार C लोकेल ASCII पर केंद्रित character model दे सकता है। ऐसी स्थिति में Málaga जैसे नाम पढ़ने वाला प्रोग्राम bytes को अस्वीकार या गलत ढंग से संभाल सकता है, भले क्रम स्थिर हो गया हो।

कई मौजूदा Unix सिस्टम में C.UTF-8 सरल collation को UTF-8 के साथ जोड़ता है, इसलिए यह व्यावहारिक test locale है। फिर भी POSIX इस नाम की उपलब्धता अनिवार्य नहीं करता। macOS, Linux वितरण, कंटेनर और language runtime एक जैसा locale catalog नहीं देते। locale -a बताता है कि होस्ट पर क्या उपलब्ध है, और provisioned test image को लिखना चाहिए कि वह कौन सा नाम देता है।

एक फर्क और साफ रखना जरूरी है: locale stability का अर्थ output format stability नहीं है। LC_ALL तय करने से दो tool version के columns, spacing, warnings या JSON fields समान होने की गारंटी नहीं मिलती। टूल JSON, NUL delimiters, epoch seconds या स्पष्ट format string देता है तो वह interface भी चुनें। locale control एक variable हटाता है, प्रोग्राम को स्थिर नहीं कर देता।

अच्छा wrapper संभावित override साफ करके केवल जरूरी मान जोड़ता है:

run_stable() {
  env -u LANGUAGE -u LC_COLLATE -u LC_CTYPE -u LC_MESSAGES \
      -u LC_MONETARY -u LC_NUMERIC -u LC_TIME \
      LC_ALL=C.UTF-8 TZ=UTC "$@"
}
run_stable sort input.txt

यदि portability में ऐसे सिस्टम आते हैं जिनका env -u नहीं समझता, तो छोटा और स्पष्ट environment बनाएँ। PATH को साफ लिखें और केवल जरूरी application variables रखें। पूरे parent environment को copy करके केवल LANG बदलना ठीक नहीं, क्योंकि इससे category overrides बच जाते हैं।

उपयोगकर्ता के लिए व्यवहार जाँचने वाले टेस्ट इसका उलटा करें। वे जानबूझकर समर्थित locale चुनें और उसी convention को assert करें जो मायने रखता है। जर्मन report test comma decimal और जर्मन month text की अपेक्षा कर सकता है। report के पीछे का parser फिर भी normalized numbers और dates का आदान प्रदान करे।

तारीख को प्रारूप और समय क्षेत्र दोनों चाहिए

Locale और time zone अलग तरह की date failures पैदा करते हैं। LC_TIME नामों और पारंपरिक representations को नियंत्रित करता है। TZ तय करता है कि किसी क्षण के लिए कौन सा civil time होगा। एक को तय करने से दूसरा तय नहीं होता।

GNU Coreutils चेतावनी देता है कि date का आउटपुट बाद में parse करने के लिए अपने आप सुरक्षित नहीं होता। उसका manual generated data के लिए language independent format, Gregorian representation और UTC या Z जैसे स्पष्ट zone की सलाह देता है। यह सलाह उस snapshot से बेहतर है जो संयोग से अंग्रेजी settings में pass हो गया।

Test protocol में स्पष्ट representation चुनें:

env LC_ALL=C.UTF-8 TZ=UTC date +'%Y-%m-%dT%H:%M:%SZ'

आउटपुट का रूप 2026-07-24T12:31:05Z है। टेस्ट को current clock के बजाय कोई fixed instant चाहिए तो उसे tool के supported option से दें, या application को clock उपलब्ध कराएँ। Locale control समय को रोक नहीं सकता।

दूसरे प्रोग्राम द्वारा parse होने वाले data में %c, %x, %X, %a और %b से बचें। ये जानबूझकर locale conventions या translated names माँगते हैं। कुछ systems में numeric directives भी calendar details ला सकते हैं। GNU manual ऐसे locales दर्ज करता है जो कुछ directives के लिए alternative calendar इस्तेमाल करते हैं। इसलिए केवल digits जैसा दिखने वाला year भी तब तक universal contract नहीं है, जब तक format और चुना locale उसे तय न करें।

Week number भी जाल है। Calendar year, ISO week based year और local week conventions नए साल के आसपास अलग प्रश्नों के उत्तर देते हैं। Business rule किसका उपयोग करता है, यह लिखें और सीमा वाली dates जाँचें। Locale pin गलत %Y-%V combination को सही नहीं करेगा।

मनुष्य के लिए reports को system की सीमा पर dates format करनी चाहिए। Stored या transmitted instant को स्थिर रूप में रखें, फिर display के लिए reader का locale और zone लगाएँ। एजेंट को कई hosts के timestamps की तुलना करनी हो तो epoch values या offsets वाले RFC 3339 style strings माँगें। उससे यह अनुमान न लगवाएँ कि 03/04/26 का मतलब 4 मार्च है या 3 अप्रैल।

उपयोगी date matrix में अंग्रेजी month names वाला एक locale, अलग month names वाला एक locale, UTC, daylight saving transition वाला एक zone और clock change तथा year boundary के आसपास की dates शामिल हों। उद्देश्य दुनिया के हर locale को गिनना नहीं है। उद्देश्य ऐसे code को पकड़ना है जिसने developer की convention मान ली।

क्रम वही होना चाहिए जिसकी उपभोक्ता को जरूरत है

अनपेक्षित run रोकें
Remote output गलत assumption दिखाए तो active session तुरंत revoke करें।

Text का एक प्राकृतिक क्रम नहीं होता। Byte order, Unicode code point order और भाषा आधारित collation अलग sequences देते हैं। Test तब विफल होते हैं जब वे एक की उम्मीद करके दूसरा चलाते हैं।

GNU sort manual कहता है कि comparisons सामान्यतः LC_COLLATE के चुने sequence से होते हैं। Script को पारंपरिक क्रम चाहिए तो manual खास तौर पर LC_ALL=C की सलाह देता है। वह यह भी बताता है कि केवल LC_COLLATE सेट करना असुरक्षित है, यदि LC_ALL उसे बदलता हो या character categories incompatible encodings इस्तेमाल करती हों।

यह fixture देखें:

Zebra
apple
zebra
Ångström
ábaco

C style locale आम तौर पर encoded bytes के हिसाब से क्रम देता है, जिसमें uppercase ASCII lowercase ASCII से पहले और ASCII से बाहर UTF-8 sequences बाद में आते हैं। Language locale case या accents को अलग collation levels पर compare कर सकता है। किसी अनुमानित order को cross platform article या test में न चिपकाएँ। वास्तविक supported locale चलाएँ और वही semantic property assert करें जिसकी जरूरत है।

Reproducible manifest या golden file के लिए byte based order आम तौर पर ठीक है। हर path portable character set तक सीमित हो तो LC_ALL=C सेट करें, वरना verified UTF-8 locale इस्तेमाल करके program में ordering function लिखें। Spanish, Swedish या German readers को दिखाई जाने वाली list में binary order खराब व्यवहार है। pinned data version वाली locale aware collation library इस्तेमाल करें, क्योंकि operating system का collation data code बदले बिना भी बदल सकता है।

Sorting और joining के नियम समान होने चाहिए। GNU Coreutils कहता है कि sort और join को consistent locales और options के साथ चलाएँ। एक collation में sorted file, दूसरी collation वाले join को unsorted दिख सकती है, जिससे matches छूटते हैं या diagnostics आते हैं। यही बात comm, duplicate removal, merge operations और बराबर values के पास पास होने की धारणा रखने वाली pipelines पर लागू होती है।

Assertions में intent दिखना चाहिए। Order जरूरी नहीं है तो incidental order का snapshot रखने के बजाय sets या maps compare करें। Byte order protocol है तो test में उसे calculate करके label करें। Localized order feature है तो accents, case variants और punctuation वाले fixtures रखें, जो उसे binary sorting से साफ अलग करें।

एजेंट exploratory sort चलाकर पहली पंक्ति को “सबसे छोटी” या “अगली” item मान सकता है और गलती बढ़ा सकता है। Action contract में ordering rule लिखें। “Semantic version के अनुसार पहला release चुनो” और “remote locale के अनुसार पहला filename चुनो” अलग निर्देश हैं।

दशमलव कॉमा shell pipeline को चुपचाप तोड़ता है

LC_NUMERIC locale aware functions और कुछ command options के decimal point और grouping conventions तय करता है। 1,25 किसी व्यक्ति के लिए सही display हो सकता है, लेकिन 1.25 चाहने वाले parser के लिए invalid है। इससे भी खराब स्थिति में permissive parser केवल prefix स्वीकार करके बिना तेज error के 1 लौटा सकता है।

GNU sort -n numeric prefix पहचानते समय locale का thousands separator और decimal point इस्तेमाल करता है। Python के locale.format_string, locale.atof और संबंधित functions भी LC_NUMERIC मानते हैं। Python का सामान्य float() और कई data formats ऐसा नहीं करते। इन दोनों families के बीच साफ सीमा के बिना text भेजने पर ऐसा bug बनता है जो केवल कुछ settings में दिखता है।

Protocol numbers को normalized रखें। JSON numbers period इस्तेमाल करते हैं, command flags सामान्यतः fixed grammar दर्ज करते हैं और database wire formats अपनी representation तय करते हैं। Comma या grouped number को केवल display के लिए format करें, calculation और serialization पूरा होने के बाद।

Parser को ऐसी values से test करें जिनमें silent truncation साफ दिखे:

0.5
1.25
1234.75
-0.125

फिर comma decimal वाले locale में वही operation चलाएँ। Tool localized input स्वीकार करने के लिए बना है तो comma वाले equivalent fixtures दें और ambiguous grouping को reject करें। वह fixed grammar देता है तो command का locale सेट करके assert करें कि comma input साफ error देता है।

हर comma को period से बदलकर arbitrary output को “ठीक” न करें। Comma field separator, thousands grouping या text का हिस्सा हो सकता है। Structured output mode या declared locale समझने वाला parser इस्तेमाल करें। Producer कोई grammar प्रकाशित नहीं करता तो उसके human output को automation के लिए अनुपयुक्त मानें।

Shell arithmetic भी गलत भरोसा दे सकती है। Shell खुद fixed syntax इस्तेमाल कर सकता है, जबकि बुलाया गया awk, printf, spreadsheet converter या language runtime केवल कुछ operations में locale लागू करता है। हर command को login shell में अलग जाँचने के बजाय पूरी pipeline को एक environment में test करें।

Money के लिए और कड़ा व्यवहार चाहिए। Minor units या explicit currency वाला decimal type store करें, फिर केवल rendered value को localize करें। कोई amount limit पार हुई या नहीं, यह तय करने वाले agent को normalized numeric value दें, न कि reader के लिए बनी report scrape करवाएँ।

एन्कोडिंग की गलती decoding से पहले शुरू होती है

जोखिम वाला rerun approve करें
Locale test external change कर सकता हो तो हर key use पर approval जरूरी करें।

Locale प्रोसेस को बता सकता है कि byte sequences को characters कैसे माना जाए। LC_CTYPE character classification को प्रभावित करता है और अक्सर codeset से जुड़ा होता है। इसलिए text split करने, character classes match करने, case बदलने, display width निकालने या bytes और strings में conversion करने वाले tools प्रभावित होते हैं।

दोनों machines पर UTF-8 होना यह सिद्ध नहीं करता कि हर process UTF-8 इस्तेमाल करता है। Remote service C locale में शुरू हो सकती है, minimal container में generated locale data नहीं हो सकता, या language runtime अपना UTF-8 mode चालू कर सकता है। Python documentation साफ कहता है कि कुछ systems पर preferred encoding केवल अनुमान हो सकती है, और Python UTF-8 Mode उस query के लिए locale encoding को अनदेखा कर सकता है।

Boundaries पर स्पष्ट रूप से decode करें। Command contract UTF-8 कहता है तो bytes पढ़कर strict error policy से UTF-8 decode करें। Platform default decoder बुलाकर उम्मीद न रखें। Unix में arbitrary filenames संभव हों तो याद रखें कि operating system boundary पर filename byte sequence है। उसे सामान्य text में जबरन बदलने पर जानकारी खो सकती है। उपलब्ध होने पर runtime की filesystem encoding और reversible error strategy इस्तेमाल करें।

Error replacement display के लिए उपयोगी है, निर्णय के लिए खतरनाक। दो अलग invalid byte strings एक ही visible replacement character बन सकती हैं। Test को byte offset पर fail होना चाहिए, original output बचाना चाहिए और छोटा hex window दिखाना चाहिए। इससे पता चलता है कि producer ने legacy encoding दी, sequence काटी या text channel से binary data लौटाया।

Character classes के सीधे fixtures भी चाहिए। अलग locales में [[:alpha:]], case conversion और whitespace recognition अलग characters शामिल कर सकते हैं। POSIX समझाता है कि LC_CTYPE तय करता है कि byte sequences characters कैसे बनते हैं और कौन से characters classes में आते हैं। Locale sensitive range से names साफ करने वाला script remote host पर अलग text स्वीकार या हटा सकता है।

मानवीय text के लिए Unicode aware application code और protocol identifiers के लिए स्पष्ट ASCII rules इस्तेमाल करें। Ambient locale को यह तय न करने दें कि environment variable name, token या wire field क्या हो सकता है। दूसरी ओर, किसी व्यक्ति के नाम पर ASCII only filter लगाकर उसे validation न कहें।

छोटे encoding test set में plain ASCII, precomposed accented text, combining marks से बना वही visible text, दूसरी writing system और raw bytes की अनुमति होने पर जानबूझकर invalid byte sequence रखें। Protocol boundary पर bytes और decoding के बाद characters assert करें। यह अलगाव failure को समझने योग्य बनाता है।

छोटा locale matrix धारणाएँ पकड़ लेता है

पूरा agent session trace करें
Sessions journal हर agent run को group करता है और तुरंत revoke करने देता है।

अधिकांश deterministic command tests को एक pinned locale में चलाएँ, फिर assumptions तोड़ने के लिए चुना गया छोटा variation suite चलाएँ। हर installed locale test करना समय खर्च करता है और coverage फिर भी कमजोर रहती है, क्योंकि कई locales प्रासंगिक conventions साझा करते हैं।

Behavior के अनुसार variants चुनें:

  1. Portable byte behavior और parse न होने वाले translated diagnostics के लिए C इस्तेमाल करें।
  2. Period decimal और साधारण से अलग collation वाला उपलब्ध UTF-8 locale लें।
  3. Comma decimal और अलग date names वाला उपलब्ध UTF-8 locale लें।
  4. Product समर्थन करता हो तो encoding assumptions दिखाने वाला locale या runtime mode जोड़ें।
  5. Date cases को UTC और daylight saving वाले एक zone के साथ चलाएँ।

इन locales को test image में provision करें। Runner में locale data न होने के कारण skipped test pass नहीं है। Setup fail होने पर locale -a print करें और required catalog को image definition का हिस्सा बनाएँ।

Matrix को process launch के पास रखें। Python में global locale बदलने के बजाय copied environment को subprocess.run दें:

import os
import subprocess

def run_case(locale_name):
    child_env = os.environ.copy()
    child_env.update({"LC_ALL": locale_name, "TZ": "UTC"})
    return subprocess.run(
        ["./agent-command", "inspect", "fixtures/names.txt"],
        env=child_env,
        check=False,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

Python locale manual कहता है कि अधिकतर systems में setlocale() thread safe नहीं है और program wide property बदलता है। Tests के बीच इसे बदलने से parallel cases एक दूसरे को प्रभावित कर सकते हैं। Child environment tested command को isolate करता है और remote execution से मेल खाता है।

Assertions में exit status, standard output bytes, standard error bytes और parsed meaning अलग रखें। LC_MESSAGES failure बदले बिना diagnostic language बदल सकता है। English phrase “No such file” match करने वाला test error condition नहीं, translation catalog test कर रहा है। Exit codes, structured error fields या stable identifiers को प्राथमिकता दें।

Variation fail हो तो category के अनुसार कारण छोटा करें। पहले LC_ALL clear करें, फिर LANG और individual categories सेट करके पता करें कि time, collation, numeric formatting, messages या character handling में से किसने बदलाव किया। Production में एक LC_ALL value हो, तब भी category variables अच्छे diagnostic tools हैं।

Parsing, process launch, SSH, reporting या fixtures बदलने वाली pull requests पर छोटा matrix चलाएँ। Scheduled run अधिक operating systems और tool versions देख सकता है। हर failure के साथ environment probe बचाएँ, ताकि rerun स्मृति पर निर्भर न हो।

एजेंट कार्रवाई को execution contract चाहिए

Autonomous agent locale ambiguity को बढ़ाता है, क्योंकि वह plausible output को प्रभाव डालने वाली action में जोड़ सकता है। Listing का क्रम बदले तो agent दूसरी file चुन सकता है। Decimal parser truncate करे तो वह गलत limit compare कर सकता है। Date zone boundary पार करे तो वह गलत दिन के record पर काम कर सकता है।

Remote command tools को चार भागों वाला स्पष्ट contract दें: वे कौन सा environment सेट करते हैं, कौन से bytes या structured data लौटाते हैं, कौन सी exit information बचाते हैं और कौन सी shell semantics इस्तेमाल करते हैं। Implementation के साथ output बदलता हो तो tool versions या capability probes भी शामिल करें। Prompt किसी अस्पष्ट process boundary को ठीक नहीं कर सकता।

Agent के output देखने से पहले success का अर्थ तय करें। Zero exit status का अर्थ command पूरा होना हो सकता है, record मिलना नहीं। कुछ tools partial result को warning के साथ देते हैं, दूसरे सफलता पर भी progress standard error में लिखते हैं। तीनों channels बचाएँ, फिर stated grammar वाला parser तय करे कि result उपयोग योग्य है या नहीं। Localized message की भाषा देखकर language model से सफलता का अनुमान न लगवाएँ।

Unsupported locales को setup error बनाएँ, execution surprise नहीं। LC_ALL=fr_FR.UTF-8 से शुरू command के host में वह locale न हो तो shell या runtime warning के बाद fallback कर सकता है, या program fail हो सकता है। Harness पहले locale -a या runtime capability check से locale की पुष्टि करे, चुना नाम दर्ज करे और required behavior exercise न होने पर रुक जाए। Provisioning में चुना fallback नियंत्रित है, agent action के बीच चुना fallback hidden state है।

Interpreter layers को भी अलग जाँचें। Local process SSH argument बनाता है, remote login service user shell शुरू करती है और target program के arguments पढ़ने से पहले shell command string parse करता है। Environment assignment और quoting किसी भी layer पर बदल सकते हैं। Argument based remote execution API उपलब्ध हो तो उसे चुनें। केवल shell string हो तो serialized command को ठीक उसी रूप में test करें और spaces, single quote, newline तथा ASCII से बाहर text जैसे कठिन fixtures रखें। Locale pin quoting bug नहीं सुधारता, लेकिन quoting bug locale assignment को गलत command पर लगा सकता है।

बार बार parse होने वाले command output को छोटा versioned protocol मानें। Raw bytes की fixture रखें, expected locale और tool family लिखें और parser के अनजान shapes reject करें। Tool upgrade shape बदले तो parser और fixture साथ update करें। Agent से एक और display format “समझने” को कहना आकर्षक लग सकता है, पर writes तक जाने वाले commands के लिए स्पष्ट protocol अधिक सुरक्षित है।

SSH में client forwarding के संयोग पर निर्भर होने के बजाय remote environment सेट करने वाला command चुनें। सही layer पर quote करें और spaces, quotes तथा ASCII से बाहर text वाले values test करें। Preferred locale पाने के लिए login shell न जोड़ें, क्योंकि वह aliases, startup scripts और दूसरी state भी लाता है।

Review के लिए raw results उपलब्ध रखें। Sallyport bundled sp-ssh helper से SSH actions चला सकता है, जबकि SSH keys उसके encrypted vault में रहती हैं, और Activity journal हर call दर्ज करता है। इससे command output locale से स्वतंत्र नहीं होता, लेकिन उपयोगी सीमा बचती है: agent को result मिलता है, उसे result पाने वाला credential नहीं मिलता।

Action external state बदल सकती है तो write से पहले parsed value validate करें। Read command से explicit format माँगें, decode न होने वाले bytes reject करें और proposed action के साथ recorded locale लगाएँ। Human approval तभी अर्थपूर्ण है जब card वही value दिखाए जो system ने वास्तव में parse की है।

मौजूदा suite को सुधारने का पहला कदम ठोस है। हर remote command खोजें जिसका output parse या snapshot होता है। Failures में environment probe जोड़ें, remote process पर locale और time zone तय करें, फिर एक comma decimal locale और अलग collation वाला एक locale adversarial cases के रूप में जोड़ें। चौंकाने वाली failures वही assumptions हैं जिन्हें आपका local shell छिपाता रहा है।

सामान्य प्रश्न

क्या SSH मेरा local locale अपने आप remote host पर भेज सकता है?

केवल तब, जब client चुने variables भेजे और server उन्हें स्वीकार करे। OpenSSH default रूप से कोई environment variable नहीं भेजता, इसलिए forwarding मानने के बजाय remote command में जरूरी locale सेट करें।

Tests में LC_ALL=C इस्तेमाल करें या C.UTF-8?

Input portable ASCII तक सीमित हो और byte order contract हो तो C इस्तेमाल करें। UTF-8 संभालना हो तो उपलब्ध C.UTF-8 जैसा locale चुनें, लेकिन provisioning में उसका ठीक नाम जाँचें क्योंकि POSIX इसे अनिवार्य नहीं करता।

LANG=C command output को स्थिर क्यों नहीं बनाता?

खाली न होने वाला LC_ALL, LANG को override करता है और category variables अपना behavior बदल सकते हैं। Conflicting variables हटाएँ या वास्तविक launched process में LC_ALL सेट करें।

कौन से locale variables sorting और numbers बदलते हैं?

LC_COLLATE collation नियंत्रित करता है और LC_NUMERIC locale aware operations के decimal तथा grouping conventions। LC_CTYPE भी जरूरी है, क्योंकि compare या classify करने से पहले tool को characters समझने होते हैं।

Locale सेट करने से time zone का अंतर भी ठीक होता है?

नहीं। TZ अलग सेट करें और स्पष्ट date format चुनें। Stable test को आम तौर पर C.UTF-8 जैसे locale और UTC जैसे zone दोनों चाहिए।

CI image में locales न हों तो behavior कैसे test करें?

ठीक locale catalog को runner image में provision करें और अनुपस्थित होने पर setup fail करें। locale -a print करने से image diagnose होती है, लेकिन case चुपचाप skip करने से risk छिपता है।

क्या JSON output हमेशा locale से स्वतंत्र होता है?

JSON grammar fixed punctuation इस्तेमाल करता है, लेकिन producer localized dates या numbers को string fields में रख सकता है। केवल braces नहीं, field contract और parser test करें।

Tests को raw command bytes क्यों रखने चाहिए?

Decoder logs लिखे जाने से पहले invalid sequences बदल या हटा सकता है। Raw standard output और error पहले bad byte का स्थान और असली encoding पहचानने का सबूत बचाते हैं।

क्या parallel tests में process locale बदल सकते हैं?

ऐसा करने से बचें। कई runtimes में locale process wide state है और Python के अनुसार setlocale() अधिकतर systems में thread safe नहीं है। हर child process को अपना environment दें।

Command test suite को कितने locale variants चलाने चाहिए?

Main suite को एक pinned locale में चलाएँ और behavior के अनुसार छोटा matrix चुनें, जैसे byte order, comma decimal, अलग date names और UTF-8 handling। एक ही assumption जाँचने वाले अधिक locale names उपयोगी नहीं हैं।

Sallyport

Sallyport आपके AI एजेंट के लिए API कॉल और SSH कमांड चलाता है। कुंजियाँ आपके Mac पर एक लोकल वॉल्ट में रहती हैं; आप हर रन को स्वीकृत करते हैं और हर क्रिया एक सीलबंद जर्नल में दर्ज होती है।

© 2026 Sallyport · Apache-2.0 के तहत ओपन सोर्स · Oleg Sotnikov