تصور کنید ابزاری را توسعه دادهاید که در محیط تست شما بینقص کار میکند، اما به محض نصب توسط کاربر، در همان ثانیه اول کرش میکند. این کابوس دقیقا همان اتفاقی است که تیم AgentWatch با پیادهسازی یک «گیت انتشار» (Release Gate) سختگیرانه از آن گریخت. این ابزار که بخشی از اکوسیستم agentsec-ecosystem (مخزن: agentsec-ecosystem/agentwatch) است، تا آستانه انتشار نسخه v0.2.0 پیش رفته بود؛ نسخهای که طبق بررسیها برای اکثریت کاربران غیرقابل استفاده بود.
بسیاری از خط لولههای نرمافزاری بر این باورند که اگر تستها در محیط CI پاس شوند، پکیج برای انتشار ایمن است. با این حال، محیطهای CI اغلب به توسعهدهندگان «دروغ» میگویند؛ زیرا هر وابستگی ممکنی، از جمله موارد اختیاری (Optional Extras) را نصب میکنند. این موضوع یک نقطه کور ایجاد میکند که در آن پکیج در آزمایشگاه کار میکند اما در یک نصب پاک و واقعی در دنیای بیرون، میشکند.
برای حل این مشکل، تیم AgentWatch یک پیششرط برای انتشار تعریف کرد: خط لوله (Workflow) از انتشار هر آرتیفکتی که دستور verify-release نتواند آن را در یک محیط کاملاً پاک تایید کند، خودداری میکند. این بدان معناست که پکیج باید بدون هیچگونه پیشنیاز اختیاری نصب شود تا اجازه ورود به رجیستری را داشته باشد. اگر رابط خط فرمان (CLI) نتواند اجرا شود، هیچ چیزی منتشر نخواهد شد.
کالبدشکافی یک باگ نامرئی
طبق مستندات پروژه، این شکست در آخرین مرحله از فرآیند انتشار v0.2.0 رخ داد. در حالی که خط لوله انتشار پیش از آن فایل Wheel را ساخته بود، SBOM را تولید کرده بود، چکسامها (Checksums) را نوشته بود و همه موارد را با استفاده از Sigstore به صورت بدون کلید (Keyless) امضا کرده بود، اما در آخرین گام متوقف شد: X Verify the release before publishing.
سیستم با خطای ModuleNotFoundError: No module named 'cryptography' کرش کرد. بررسی Traceback نشاندهنده یک شکست کلاسیک در زنجیره Importها بود:
- فایل
bin/agentwatch(خط ۳) ماژولagentwatch.cli.mainرا فراخوانی میکرد. - فایل
cli/main.py(خط ۷۱) ماژولagentwatch.demo(به طور خاص توابعpurge_demo،render_demoوrun_demo) را وارد میکرد. - فایل
demo.py(خط ۲۲) ماژولagentwatch.adapters.claude_codeرا فراخوانی میکرد. این موضوع یادآور چالشهای مدیریت ابزارهای هوش مصنوعی است، مشابه آنچه در بررسی مکانیزمهای کنترل Claude Code برای جلوگیری از ادعاهای نادرست در رفع باگها مشاهده شد. - فایل
adapters/__init__.py(خط ۵) پکیج adapters را وارد میکرد. - فایل
adapters/a2a_proxy.py(خط ۳۶) ماژولagentwatch.agent_cardرا فراخوانی میکرد. - فایل
agent_card.py(خط ۲۶) کلاسInvalidSignatureرا از کتابخانه cryptography در ابتدای ماژول وارد میکرد.
از آنجا که کتابخانه cryptography یک پیشنیاز اختیاری (تحت برچسب [signing]) بود، یک نصب استاندارد با دستور pip install agentsec-agentwatch آن را شامل نمیشد. تبدیل این مورد به یک وابستگی اجباری اشتباه بود، زیرا اکثر کاربران هرگز عملیات امضا را انجام نمیدهند. با این حال، توسعهدهنده با قرار دادن Import در ابتدای ماژول، به طور تصادفی یک وابستگی اختیاری را به وابستگی اجباری تبدیل کرد. نتیجه این بود که CLI برای هر کسی که از ویژگیهای امضا استفاده نمیکرد، غیرقابل استفاده شد و حتی با دستور ساده --help کرش میکرد.

راهکار فنی: وارد کردن تنبل (Lazy Imports)
راه حل، پیادهسازی «وارد کردن تنبل» بود. توسعهدهنده Importها را به داخل تنها تابعی که واقعاً از آنها استفاده میکرد، یعنی _verify_signature منتقل کرد.
به جای Import در سطح ماژول، اکنون این تابع نیازهای خود را مدیریت میکند:
from cryptography.exceptions import InvalidSignaturefrom cryptography.hazmat.primitives import hashesfrom cryptography.hazmat.primitives.asymmetric import ec, ed25519, padding, rsa
این تغییر تضمین میکند که کتابخانه تنها زمانی درخواست شود که مسیر تایید امضا واقعاً اجرا شود. در این حالت، سایر موارد از جمله بارگذاری ماژول، استارتآپ CLI و وارد کردن آداپتورها، دیگر اهمیتی نمیدهند که آیا cryptography وجود دارد یا خیر.
تضمین عدم تکرار با Meta-Path Hook
برای جلوگیری از بازگشت این باگ (Regression)، تیم یک تست تخصصی اضافه کرد که عمداً ماژول را مسدود میکند. این اثباتی است بر اینکه CLI حتی در صورت نبود وابستگی میتواند Import شود. این تست از یک کلاس Blocker استفاده میکند که در sys.meta_path قرار میگیرد:
- متد
find_specبررسی میکند که آیا نام ماژولcryptographyاست یا باcryptography.شروع میشود. - اگر پیدا شود، خطای
ModuleNotFoundError("cryptography blocked for test")را صادر میکند. - سپس تست تلاش میکند تا
import agentwatch.cli.mainرا اجرا کند.
اگر کسی دوباره Import را به ابتدای ماژول منتقل کند، این تست در CI قرمز میشود. در همین حال، ۲۶ تست A2A card در صورت حضور cryptography همچنان پاس میشوند و تضمین میکنند که خودِ ویژگی امضا خراب نشده است.
چرا تستهای استاندارد شکست خوردند؟
مجموعه تستهای موجود در پروژه از نظر ساختاری قادر به شناسایی این مشکل نبودند. این مجموعه تستها مستحکم هستند — SBOM را تایید میکنند، محتویات Wheel را بررسی میکنند و نسخهبندی را اجبار میکنند — اما هر محیط تست، Extras را نصب میکند. تنظیمات توسعه و کارهای کیفی CI همگی وابستگیها را در دسترس داشتند.
این موضوع یک شکاف بحرانی در DevSecOps مدرن را برجسته میکند: تفاوت میان «تست پاس شده» و «نصب کاربردی». این تضاد میان وضعیت ایدهآل تست و واقعیت عملیاتی، مشابه ابهامات عملیاتی در گردشکارهای AI است که به دلیل استفاده از برچسبهای واحد برای پایان عملیات رخ میدهد. تنها دو جایی که این دسته از باگها میتوانند ظاهر شوند عبارتند از:
۱. یک نصب پاک در خط لوله انتشار (گام verify-release).
۲. بررسی نصب از رجیستری در یک venv تازه پس از انتشار.
خط لوله AgentWatch یک شکست عمومی احتمالی را به یک اجرای ناموفق داخلی و یک اصلاح سریع (PR #495) تبدیل کرد.
معماری حاصله
بدون گام verify-release ،نسخه v0.2.0 به عنوان ابزاری شکسته به PyPI میرفت. این نسخه دارای یک Wheel امضا شده، دارای SBOM و گواهی Provenance بود، اما برای اکثریت کاربران در هنگام Import کرش میکرد.
در عوض، تیم عملیات Re-tag را انجام داد و نسخه v0.2.1 را منتشر کرد. این نسخه با هشت دارایی — شامل Wheel، sdist، SBOM و چکسامها که هر کدام بسته Sigstore خود را داشتند — منتشر شد و در اولین تلاش به درستی کار کرد.
این معماری تمرکز را از «اعتماد به ساخت» به «تایید مرزها» تغییر میدهد. با قرار دادن یک گیت در جایی که محیط دیگر «دروغ» نمیگوید، تیم تضمین کرد که ابزار واقعاً اختیاری است. اگر خط لوله فعلی شما بدون بررسی Import در محیط پاک به ساخت اعتماد میکند، انتشار بعدی شما در واقع یک قمار روی درخت وابستگیهایتان است.
گام بعدی شما
- اگر از CI/CD استفاده میکنید، یک مرحله «نصب پاک» (Clean Install) را به خط لوله خود اضافه کنید تا وابستگیهای پنهان را شناسایی کنید.
- برای کاهش زمان استارتآپ و جلوگیری از خطاهای وابستگی، از Lazy Import در توابع غیرضروری استفاده کنید.
- بررسی کنید آیا در پروژه شما وابستگیهای اختیاری در سطح Global وارد شدهاند یا خیر.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو