تصور کنید یک عامل هوشمند تمام کدهای شما را بازنویسی کند و بدون اینکه متوجه شوید، دهها خطای کوچک اما آبروسوز را به مخزن کدتان بفرستد. برای هر توسعهدهندهای که در پروژههای متنباز فعالیت میکند، یک درخواست تغییر (PR) اشتباه، نه تنها وقت مدیر پروژه را میگیرد، بلکه اعتبار حرفهای او را هم میسوزاند.
به همین دلیل است که ویشال حبیب در مسیر اتوماسیون مشارکتهای متنباز، مفهومی به نام «قانون توقف» (Kill Rule) را تعریف کرد. او کشف کرد که برای محافظت از شهرت یک مشارکتکننده، داشتن یک قانون توقف از پیش تعریف شده ضروری است. حبیب طی ۶ هفته، ۴۴ اصلاحیه باگ را در سرورهای مختلف پروتکل زمینهٔ مدل (MCP) ادغام کرد و در نهایت کل این چرخه را با ابزاری به نام mcp-doctor — یک ابزار تحلیل ایستا (Static Linter) برای سرورهای MCP — خودکار کرد.
این رویکرد در حالی مطرح میشود که صنعت به سمت کدنویسی عاملمحور (Agentic) حرکت میکند؛ جایی که هوش مصنوعی دیگر فقط تکههای کد پیشنهاد نمیدهد، بلکه کل چرخهٔ حیات یک PR را مدیریت میکند. برای اکثر توسعهدهندگان، سپردن یک مخزن کد به یک عامل بر اساس «حس خوب» (Vibes)، ریسکی غیرقابل قبول است. همانطور که در تحلیلهای قبلی ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، یک PR اشتباه هزینه زمانی برای مدیر پروژه دارد و اعتبار حرفهای نویسنده را تخریب میکند. این نگرانیها بهویژه پس از آنکه آسیبپذیریهای سیستماتیکی در سرورهای MCP گوگل و مایکروسافت افشا شد، اهمیت بیشتری یافت.
طبق گزارش حبیب، او برای کاهش این ریسک یک خط قرمز و خط مبنای سختگیرانه تعیین کرد: عامل باید بتواند اصلاحات انسانی قبلی را با دقت حداقل ۶۰٪ بازتولید کند و هیچ PRی تولید نکند که یک انسان از ارسال آن خودداری کند. این چارچوب، فرآیند اتوماسیون را به مجموعهای از گیتهای سختگیرانه تبدیل کرد.
کالبدشکافی باگ
این عامل برای حل یک مشکل بسیار خاص در سرورهای پایتونی MCP طراحی شده بود. وقتی پارامتری به صورت name: str = None نوشته میشود، این کد یک طرح ابزار (Tool Schema) تولید میکند که مقدار پیشفرض را به صورت "type": "string", "default": null اعلام میکند.
برخی از چارچوبهای عاملمحور، این مقدار پیشفرض اعلام شده را برای هر فیلد اختیاری صراحتاً به سرور بازمیگردانند. وقتی این اتفاق میافتد، کلاینت پیش از آنکه ابزار حتی اجرا شود، یک خطای اعتبارسنجی دریافت میکند. راه حل ساده است: تغییر نوع پارامتر به str | None. اگرچه این تغییر کوچک به نظر میرسد، اما اثرش در دنیای واقعی گسترده است؛ برای مثال، پروژه telegram-mcp در ۱۱۱ ابزار از ۱۳۱ ابزارش همین باگ را داشت. این نوع نقصها در توصیفات ابزارها میتواند مشابه حفرههای امنیتی «مسمومسازی ابزار» باشد که در آن توصیفات نادرست منجر به رفتارهای پیشبینینشده در عاملها میشود.
گیت اول: آزمون بازپخش
حبیب ابتدا عامل را روی کدهایی تست کرد که درست قبل از ادغام یک اصلاحیه شناختهشده بودند. هدف این بود که ببیند آیا وصله (Patch) تولید شده توسط AI با راه حل پذیرفتهشده توسط مدیر پروژه مطابقت دارد یا خیر.
- در تلاش اول، عامل شکست خورد چون تمام انواع اصلاحات را همزمان اعمال میکرد و ۵۷ یادداشت
TODO: describe this parameterغیرضروری در قالب استابهای docstring به کد اضافه میکرد. یک PR پر از یادداشتهای TODO، همان PRی است که یک انسان هرگز آن را ارسال نمیکند. - برای حل این مشکل، حبیب پرچم
--fix-onlyرا معرفی کرد تا هر اجرا را به یک نوع اصلاح محدود کند و تضمین کند که هر PR تنها حاوی یک تغییر باشد. - پس از این تعدیل، عامل روی ۱۵ مورد از اصلاحات ادغامشدهی null-default تست شد. در ۱۴ مورد از ۱۵ مورد، عامل دقیقاً همان پارامترهایی را تغییر داد که مدیر پروژه ادغام کرده بود. در یک مورد، خروجی تولید شده با فایل ادغامشده کاملاً یکسان (Byte-identical) بود.
- در مورد پانزدهم، تمام ابزارهای ثبتشده مطابقت داشتند. تنها تفاوتها مربوط به ۱۵ تابع بود که به عنوان ابزار MCP ثبت نشده بودند (که انسان آنها را برای یکدستی اصلاح کرده بود) و یک ابزار LangChain که همین باگ را داشت. در این مورد هیچ ویرایش اشتباهی صورت نگرفت.
گیت دوم: تست روی مخازن ناشناخته
از آنجایی که تست اول دوری بود — یعنی از باگهایی استفاده میکرد که قبلاً توسط mcp-doctor پیدا شده بودند — حبیب چرخه را روی یک نمونه تصادفی از حدود ۱۶۰ مخزن فعال پایتونی MCP که هرگز ندیده بود اجرا کرد. او متوجه شد این باگ در دنیای واقعی کمتر از حد انتظار است و تنها در ۳ مخزن (حدود ۲٪) ظاهر شد. یک جستجوی هدفمند در کدها در نهایت ۱۶ مورد دیگر را یافت که مجموعاً ۱۹ هدف را تشکیل دادند.
برای جلوگیری از اجرای کدهای احتمالا مخرب از سرورهای غریبه — مانند سروری که تابع main() آن یک رشته لاگین را علیه یک API واقعی تناسب اندام (Fitness API) شروع میکرد — او از تکنیک «استابینگ» (Stubbing) استفاده کرد. او امضای دقیق ابزار را روی یک استاب کپی کرد، آن را با همان SDK که مخزن استفاده میکرد ثبت کرد و آن را با مقدار null روی یک کلاینت در حافظه (In-memory) فراخوانی کرد. این کار تضمین کرد که هیچ کدی از مخزن اصلی اجرا نشود. تمام ۱۹ مورد، باگ را بازتولید کردند.
او همچنین تایید کرد که این باگ در تمام نسخههای SDK مورد استفاده وجود دارد، از جمله نسخههای mcp 1.9 ،1.30 و 2.3 و همچنین fastmcp 2.12 ،3.0 و 4.1.
اصلاح قوانین و سختگیرانهتر کردن گیتها
حتی با موفقیت در بازپخش، حلقه خام در مواجهه با دادههای ناشناخته با «قانون توقف» برخورد کرد. دو مورد از ۱۹ مخزن منجر به شکست میشدند: یکی یک بنچمارک تشخیص امنیتی بود که ۶۱ مورد از ۶۴ فایل علامتگذاری شده، سرورهای «ابزار benign» مصنوعی بودند که به عنوان دادههای تست استفاده میشدند؛ مورد دیگر اصلاحی بود که یک تست اسنپشات طرح (Schema Snapshot Test) را میشکست و طبق راهنمای CONTRIBUTING نیاز به بازسازی اسنپشات داشت. علاوه بر این، دو PR برای ارسال مستقیم بیش از حد بزرگ بودند و به ترتیب ۱۷۲ و ۱۳۲ پارامتر را شامل میشدند.
این شکستها منجر به دستورات سختافزاری و کدگذاریشدهی جدید برای عامل شد:
- فیلتر دادههای آزمایشی (Fixture Filter): عامل باید README را بخواند و مسیرهای مربوط به دادههای تست، بنچمارکها، مثالها و کدهای Vendored را شناسایی و حذف کند.
- مسیریابی بر اساس حجم (Size Routing): اگر یک تغییر بیش از ۳۰ پارامتر را در بر بگیرد، عامل باید به جای PR، یک «Issue» پیشنویس کند تا مدیر پروژه تصمیم بگیرد چگونه با این تغییر بزرگ برخورد کند.
- گام تست (Test Step): عامل باید تستهای مخزن را قبل و بعد از اصلاح اجرا کند. اگر یک اسنپشات طرح شکست خورد، باید آن را طبق فایل
CONTRIBUTINGبازسازی کند. هرگونه شکست جدید دیگر، باعث حذف پیشنویس میشود.
طراحی انسان-در-حلقه (Human-in-the-Loop)
با وجود تمام این اتوماسیونها، سیستم طوری طراحی شده که در نهایت متوقف شود. مهارت Claude Code که برای این اصلاحات استفاده شده (fix-upstream) هرگز کد را پوش (Push) نمیکند، PR باز نمیکند یا به طور خودکار کامنت نمیگذارد. عامل فقط تا مرحله ایجاد یک شاخه (Branch) محلی و نوشتن توضیحات PR پیش میرود.
این یعنی تصمیم نهایی و قضاوت با انسانی است که نامش روی PR ثبت میشود. عامل بخشهای کند و مکانیکی — بازتولید، وصله زدن و تست — را انجام میدهد و انسان گیت کیفیت نهایی را مدیریت میکند. این یک انتخاب طراحی دائمی است، نه یک شبکه ایمنی موقت.
کشف یک باگ در ابزار اصلی
در اولین اجرای واقعی روی ۵ مخزن، عامل از ارسال PR برای یک چارچوب معاملاتی خودداری کرد. عامل کشف کرد که در SDK رسمی پایتونِ MCP، خودِ این اصلاح باعث شکست فراخوانیهای سالم میشود. SDK هرگاه نوع پارامتر دقیقاً str نباشد، آرگومان رشتهای را پیش از اعتبارسنجی رمزگشایی (JSON-decode) میکند.
در نتیجه، تغییر str به str | None باعث میشد پارامترهایی که یک رشته JSON میگیرند (مثلاً '{"BTC-USDT": "..."}') به یک دیکشنری رمزگشایی شده و سپس رد شوند، در حالی که متن لیترا ل "null" به طور بیصدا به None تبدیل میشد. بسته مستقل fastmcp این رفتار را نداشت و به همین دلیل در تستهای اولیه بازپخش شناسایی نشده بود.
عامل همچنین متوجه شد که اسکنر فایلی به نام significance_test.py را نادیده گرفته است که ۸ ابزار را ثبت کرده بود اما به دلیل نامش رد شده بود. هر دو موضوع به باگهای واقعی در mcp-doctor تبدیل شدند (شماره ۱۰۸ و ۱۰۹) که همان بعدازظهر اصلاح و منتشر شدند.
حبیب تایید کرد که هیچیک از اصلاحات قبلی او پارامتری را که متن JSON میگیرد تغییر نداده بود. در تست پیشرو روی ۱۹ مخزن، قانون جدید به درستی از تغییر ۷ پارامتر که واقعاً JSON میگرفتند، خودداری کرد.
این فرآیند ثابت میکند که ارزشمندترین خروجی یک عامل هوش مصنوعی، اغلب «امتناع از اقدام» است. با طراحی برای «توقف»، توسعهدهندگان میتوانند از قدرت AI برای کارهای سنگین استفاده کنند بدون اینکه دقت لازم برای مشارکتهای حرفهای در متنباز را فدا کنند.
گام بعدی شما
- اگر از عاملهای کدنویسی استفاده میکنید، برای هر تسک یک «قانون توقف» (Kill Rule) تعریف کنید تا از ارسال کدهای ناقص جلوگیری شود.
- در اتوماسیونهای AI، به جای اعتماد به خروجی، گیتهای اعتبارسنجی (مانند اجرای تستهای واحد) را اجباری کنید.
- برای پروژههای بزرگ، از عامل بخواهید ابتدا یک Issue باز کند و تحلیل خود را بنویسد، نه اینکه مستقیماً کد را تغییر دهد.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو