تصور کنید یک برنامهنویس ارشد را استخدام کردهاید که هم کد میزند و هم خودش آن را تأیید میکند؛ احتمالاً هر دو بخش را با یک دیدگاه خوشبینانه میبیند. Verdict دقیقاً با شکستن این چرخه متولد شده است تا ثابت کند عاملهای هوش مصنوعی زمانی بیشترین بازدهی را دارند که اجازه نداشته باشند باگهایی را که مییابند، خودشان اصلاح کنند.
به نقل از گزارش منتشر شده در ۵ سپتامبر ۲۰۲۶، این پروژه تغییری بنیادین در رویکرد عاملهای تضمین کیفیت (QA) ایجاد کرده است. در حالی که اکثر ابزارهای فعلی، مخازن کد را از ابتدا بررسی کرده و اغلب دچار توهم (Hallucination) — شبیه به دوستی که خاطرهای را اشتباه تعریف میکند — میشوند و موفقیت کاذبی را گزارش میدهند، Verdict نقش داور را از مجری جدا میکند. این سیستم از رویکرد «LGTM» (به نظر من خوب است) فاصله گرفته و به سمتی حرکت کرده است که دارای یک تاکسونومی (طبقهبندی) سختگیرانه از شکستها و یک تاریخچه اجرای امضا شده است. این رویکرد برای مقابله با نقصهای ساختاری در مهارتهای عاملهاست، چرا که گزارشهای اخیر Snyk نشان میدهد بخش قابل توجهی از مهارتهای عمومی عاملهای هوش مصنوعی دارای نقصهای امنیتی هستند.
همانطور که در تحلیلهای پیشین ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، استقلال لایههای نظارتی برای جلوگیری از سوگیری ضروری است. در Verdict، یک چارچوب کتابخانهای استاندارد، مواردی مثل برچسبهای زمانی، SHAها، تعداد تستها و پوشش تغییرات (Diff Coverage) را اندازهگیری میکند، در حالی که مدل هوش مصنوعی تنها در نقش «داور» قرار دارد و هیچ دسترسی به ابزار ویرایش (Edit tool) یا تلهمتری شبکه ندارد. یک اعتبارسنج سختگیرانه نیز هر وضعیتی را که ادعای موفقیت بیش از مقدار اندازهگیریشده واقعی داشته باشد، رد میکند. این تلاش برای ایجاد شفافیت در اقدامات عاملها، یادآور پروتکل Elara است که سعی دارد با ثبت سوابق روی زنجیره، خطاهای عملیاتی عاملها را کاهش دهد.
طبق گزارش dev.to، این سیستم بر اساس یک فایل وضعیتِ تغییر-محور (Delta-based) عمل میکند. هر اجرا، نتایج را به چهار دسته تقسیم میکند:
- جدید (NEW)
- همچنان باز (STILL_OPEN)
- حلشده (RESOLVED)
- پسرفت (REGRESSED) که در اولویت بررسی قرار دارد و ابتدا رتبهبندی میشود.
هر یافته در این سیستم دارای یک شناسه (ID) پایدار و یک مقدار «عمر» (Age) است تا ردیابی تغییرات در طول زمان ممکن باشد.
طبقهبندی خطاها
تستهای شکستخورده (Red tests) در این سیستم به دستههای دقیقی تقسیم میشوند:
- نقایص واقعی: باگهای واقعی در کد.
- انتظارات قدیمی: تستهایی که منسوخ شدهاند و باید شامل یک ارجاع (Citation) باشند.
- ناپایدار/محیطی: شکستهای مربوط به زیرساخت و محیط اجرا.
- لرزان (Flaky): تستهایی که بهجای حذف، با یک تاریخ انقضا قرنطینه میشوند. این استراتژی دقیقاً با رویکرد قرنطینه در برابر حذف برای مدیریت تستهای ناپایدار در LLMها همسو است تا از دست رفتن دادههای تست جلوگیری شود.
هر اجرا با یکی از چهار حکم «پاس»، «پاس با ریسک»، «مسدود» یا «شکست» به پایان میرسد. نکته کلیدی این است که در حالت «پاس»، سیستم باید صراحتاً نام ببرد که چه بخشهایی تست نشدهاند.
حفاظهای فنی و ممیزی داخلی
برای تضمین استقلال، توسعهدهنده یک حفاظ Bash در حالت سختگیرانه (Strict-mode) و یک هوک (Hook) پیاده کرده است که تمام عملیات نوشتن را به ریشه QA محدود میکند. این کار مانع از آن میشود که عامل با اصلاح کدی که در حال داوری آن است، در واقع «تکالیف خودش را تصحیح کند».
وقتی این عامل را برای بررسی خودش به کار گرفتند، ۷۹ نقص در چارچوب داخلیاش یافت. جالب اینجاست که عامل در یک چرخه تکراری، سه بار متوالی برای اصلاحاتِ یافتههای قبلی، نقص جدید ثبت کرد. این حلقه تنها زمانی شکست خورد که فرآیند تغییر کرد و مدل مجبور شد محورهایی را که اصلاحات روی آنها اثر نگذاشته نام ببرد و یک نقطه خاص روی آن محور را تست کند.
علاوه بر این، کاتالوگ جهش (Mutation Catalogue) که برای امتیازدهی به مجموعه تست استفاده میشد، دو بار اشتباه شمارش شد؛ بار اول از روی تستها و بار دوم از روی لیست اصلاحات. تنها پس از شمارش مستقیم از روی کد بود که عامل توانست چهار شکاف را پیدا کند که هیچ لیست اصلاحاتی نمیتوانست به آنها دسترسی داشته باشد.
آزمون استرس در دنیای واقعی
برای تست روی کدهای ناشناخته، این عامل روی کتابخانه itsdangerous در یک کلون تازه اجرا شد. در ۱۸ دقیقه، سیستم حکم «پاس با ریسک» صادر کرد و ۹ یافته اثباتشده را شناسایی کرد، از جمله:
- بحرانی: پذیرش رشتههای base64 غیرکانونیک در تأیید امضا؛ به طوری که چهار رشته توکن متمایز به یک Payload یکسان اشاره میکردند.
- بحرانی: وجود مرز max_age تعریفنشده که باعث میشد مراحل تست از ۱ به ۱۱ بپرند (در حالی که max_age=10 بود) و مرز حساس را نادیده بگیرند.
- بحرانی: دفاع در برابر حمله زمانبندی (timing-attack) با استفاده از
hmac.compare_digestکه میتوانست با یک بررسی تساوی ساده (==) جایگزین شود بدون اینکه مجموعه تست شکست بخورد. - جزئی: دکمپرس کردن zlib بدون محدودیت روی ورودیهای تأییدنشده (تبدیل ۳۹ کیلوبایت به ۳۰ مگابایت)، هرچند با یک شمارنده فراخوانی، تعداد صفر فراخوانی روی امضای بد اندازهگیری شد.
- جزئی: استفاده از تست زیررشته (Substring) در
_base64_alphabetبهجای تست مجموعه (Set)، که باعث میشد ۱۲ مورد از ۲۰۰۰ مقدار امضا شده در رفتوبرگشت (Round-trip) شکست بخورند. - جزئی: سه مورد کوچکتر شامل یک docstring که وعده «هرگز شکست نمیخورد» را برای فراخوانیای میداد که خطا ایجاد میکرد، یک پیکربندی پوشش (Coverage) اشتباه و پارامتری که هیچ چیزی را تأیید (Assert) نمیکرد.
این جداسازی وظایف باعث میشود عامل بهجای ارائه یک وصله (Patch)، یک لیست مرتب از اصلاحات را برگرداند. در اجرای بعدی، سیستم با تزریق مجدد نقص اصلی، تأیید میکند که مجموعه تست اکنون شکست میخورد تا مطمئن شود تستها واقعاً کار میکنند، و سپس اصلاحیه را میسنجد تا ببیند باگ برطرف شده است یا خیر.
برای توسعهدهندگان، این رویکرد پیشفرض «خودمختاری کامل» (End-to-End) عاملها را به چالش میکشد. حذف توانایی نوشتن کد از عامل، اعتبار ممیزی را افزایش میدهد و هوش مصنوعی را از یک برنامهنویس احتمالاً سوگیرانه، به یک حسابرس سختگیر و مستقل تبدیل میکند.
کاربران میتوانند این ابزار را از طریق بازارچه پلاگینها یا حالت بدون رابط کاربری با دستور uvx --from verdict-qa-mcp verdict-run . آزمایش کنند. این پروژه تحت لایسنس MIT در گیتهاب در دسترس است، به پایتون ۳.۹ به بالا نیاز دارد و تنها از کتابخانههای استاندارد (stdlib) استفاده میکند.
گام بعدی شما
- اگر از عاملهای کدنویس برای تست استفاده میکنید، دسترسی آنها به ویرایش کد در مرحله QA را قطع کنید.
- معماری «داور-مجری» را در گردشکارهای CI/CD خود برای کاهش نرخ توهمات مدل پیاده کنید.
- ابزار Verdict را روی یک کتابخانه کوچک بازمتن اجرا کنید تا تفاوت ممیزی مستقل را با ابزارهای End-to-End مقایسه کنید.
اما تأثیر این جداسازی بر هزینههای استنتاج در مقیاس بزرگ حتی پیچیدهتر است — به تحلیل ما درباره بهینهسازی هزینههای GPU مراجعه کنید.




گفتگو