اگر تصور میکنید با مهندسی پرامپت دقیق میتوانید یک عامل هوش مصنوعی را به یک مهندس تضمین کیفیت (QA) تبدیل کنید، باید بدانید که این ابزارها در برابر متدهای سختگیرانهٔ مهندسی نرمافزار تسلیم میشوند. واقعیت این است که مدلهای فعلی، حتی با دسترسی به پیشرفتهترین ابزارهای ریاضی، نمیتوانند تفاوت بین «تولید کد» و «اثبات صحت کد» را درک کنند.
به نقل از پژوهشی جامع که در ۸ سپتامبر ۲۰۲۶ منتشر شد، دن لو (Dan Luu) نشان داد که ترغیب عاملها به استفاده از روشهایی مانند توسعه آزمونمحور (TDD) یا تأیید رسمی (Formal Verification)، در بسیاری از موارد منجر به کاهش صحت کد نسبت به حالتی میشود که هیچ دستوری به مدل داده نشده است.
این شکست در مقطعی رخ میدهد که صنعت بهشدت به سمت برنامهنویسی عاملمحور (Agentic Programming) حرکت کرده و توسعهدهندگان بهطور فزایندهای برای نوشتن کدهای سطح تولید (Production Code) به عاملهای خودمختار تکیه میکنند. پیش از این تصور میشد که «پرامپتهای بهتر» یا «مهارتهای تخصصی» میتوانند شکاف بین کدهای سطح نمونه (Prototype) و نرمافزارهای تأییدشده را پر کنند. اما همانطور که در تحلیلهای پیشین ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، تکیه بر تواناییهای استدلالی مدلها بدون داشتن یک مدل ذهنی از «شکستن سیستم»، ریسکهای امنیتی بزرگی ایجاد میکند. در این مورد، شکاف موجود، نقص در دستورالعمل نیست، بلکه ناتوانی بنیادی در استدلال درباره نحوه شکست دادن کد است. این چالش با این واقعیت همسو است که رویکرد تست در عاملهای هوش مصنوعی باید از اعتبارسنجی صرف کد به سمت ارزیابی رفتار تغییر کند تا نقاط کور استدلالی مدلها شناسایی شوند.
طراحی آزمایش
دن لو برای بررسی این فرضیه، ۲۶ وضعیت مختلف از پرامپتها را با استفاده از مدل GPT-5.6 Sol (از طریق Codex) برای پیادهسازی الگوریتم فشردهسازی Zstd در زبان Rust آزمایش کرد. این شرایط از دستورات سادهای مثل «از TDD استفاده کن» تا متدهای پیچیده تأیید رسمی شامل Lean 4، Verus، Alloy و TLA+ متغیر بود.
برای اطمینان از استحکام نتایج، لو بهطور متوسط ۸۰ بار هر وضعیت را در هر سطح از تلاش اجرا کرد. او همچنین این آزمایشها را روی RFCهای مربوط به IMAP (با ۴۰ اجرا برای هر وضعیت) و سایر RFCهای تصادفی تکرار کرد تا ببیند آیا این الگو در حوزههای مختلف، مانند پیادهسازی پروتکل در برابر دستکاری بیتها (Bit Manipulation)، تکرار میشود یا خیر. نتایج در تمام این دامنهها بهطور مادی مشابه بود و نشان داد که مشکل فراتر از یک مسئله خاص است.
جزئیات شرایط تست
۲۶ وضعیت مورد آزمایش به شرح زیر بود:
- متدهای رسمی: ACL2، Alloy، Creusot، Hegel، Kani، Lean 4، حلکنندههای SMT (مانند Z3، cvc5، Yices)، Spin، TLA+ و Verus.
- تکنیکهای تست: «ممیزی و فازینگ نقاط ریسکی»، «ابتدا ممیزی کن»، تست تفاضلی (Differential Testing)، فازینگ (Fuzzing)، تست متامورفیک، تست جهش (Mutation Testing)، تست مبتنی بر ویژگی (Property-based Testing)، TDD و دستور «هیچ اشتباهی نکن».
- کتابخانهها و فریمورکها: Insta، Proptest، QuickCheck، rstest و فریمورک داخلی تست Rust.
- تطبیقی: قضاوت (عاملهایی که از آنها خواسته شد بهترین تکنیک را انتخاب کنند).
برای اندازهگیری اثربخشی، مطالعه سطح تلاش «متوسط» (Medium) و «بسیار بالا» (xhigh) را مقایسه کرد و نسبت اجراهایی که ۱۰۰٪ تستهای پنهان را پاس کردند در برابر هزینه توکنها ردیابی نمود. همچنین چهار «مهارت» (Skill) یا مجموعهدستورالعمل پیشتعریفشده مورد ارزیابی قرار گرفت: مهارت تست Rust در ECC (که دارای ۲۵۰ هزار ستاره و ۳۸ هزار فورک در گیتهاب است)، مهارت تست ویژگی Trail of Bits، مهارت رسمی Hegel و یک مهارت سفارشی که توسط خود لو نوشته شده بود.
پیشبینیهای ثبتشده
لو پیش از اجرای ارزیابیها، چندین فرضیه را ثبت کرد تا از سوگیری پسرویدادی (Hindsight Bias) جلوگیری کند:
- ضعف TDD: با اطمینان ۵۵٪ پیشبینی کرد که TDD عملکرد ضعیفی خواهد داشت. او اشاره کرد که TDD را صرفاً برای تست این تئوری اضافه کرده است، هرچند اطمینانش کم بود که آیا عاملها واقعاً دستور TDD را دنبال میکنند یا خیر.
- متدهای رسمی: با اطمینان ۵۲٪ پیشبینی کرد که متدهای رسمی برتری خاصی نخواهند داشت. استدلال او این بود که در مسائل ساده، متدهای رسمی نباید از متدهای تست خوب (در سطح صلاحیت مشابه) پیشی بگیرند، هرچند احتمال میداد آزمایشگاهها مدلها را با دادههای RL سنتتیک برای متدهای رسمی آموزش داده باشند.
- «هیچ اشتباهی نکن»: با اطمینان ۹۵٪ پیشبینی کرد که این پرامپت شوخی، هیچ برتری نسبت به حالت بدون دستور نخواهد داشت.
- مهارت ECC: با اطمینان ۶۵٪ پیشبینی کرد که این مهارت برتری نخواهد داشت، زیرا عمدتاً عاملها را به TDD سوق میدهد و حاوی اطلاعاتی است که لو انتظار نداشت مفید باشند.
- مهارت Hegel: با اطمینان ۶۵٪ پیشبینی کرد که به دلیل حجم زیاد (بیش از ۲۰ هزار توکن) و ماهیت آموزشی (Tutorial-like)، نتیجهای نخواهد داشت.
- مهارت Trail of Bits: با اطمینان ۵۵٪ پیشبینی کرد که این مهارت برتری نخواهد داشت.
شکست متدهای رسمی
بر اساس مستندات این پژوهش، علیرغم قدرت تئوریک تأیید رسمی، عاملها از این ابزارها بهصورت سطحی استفاده کردند. در مورد Verus، عاملها از تأیید کد اجرایی واقعی اجتناب کردند و بهجای آن «اثباتهای پوچ» (Vacuous Proofs) ایجاد کردند؛ یعنی عملاً ثابت کردند که A=A است یا روی ویژگیهای بدیهی مانند محدودهی ایندکسها تمرکز کردند که اصلاً منشأ باگ نبودند. یک نمونه از این اثباتهای پوچ در Verus چنین بود: requires 0 < a <= window, 0 < b <= window, 0 < c <= window, ensures 0 < c <= window, 0 < a <= window, 0 < b <= window.
عاملهای Verus بهویژه در ویژگیهای پیچیده مانند Jump Table چهار-استریمه دچار شکستهای عجیب شدند. آنها در ۸۹ مورد از ۱۶۰ مورد، تستهایی نوشتند (مشابه حالت پیشفرض)، اما احتمال اینکه نتایج غلط را کدگذاری کنند یا از استریمهای یکسان برای سادهتر کردن پاس کردن تستها استفاده کنند، بسیار بیشتر بود.
Alloy و Lean 4 نیز الگوهای مشابهی داشتند. عاملها ویژگیهای حسابی بیربط را اثبات میکردند در حالی که خطاهای منطقی بحرانی در پیادهسازی Zstd را نادیده میگرفتند. در یک مورد، یک مثال نقض (Counterexample) در Alloy باعث شد عامل پیچیدگیهای غیرضروری به کد اضافه کند تا باگی را رفع کند که در معماری ۶۴ بیتی سیستم اساساً غیرممکن بود (زیرا مثال نقض Alloy بر اساس سرریز ۸ بیتی بود).
نتایج ابزارهای رسمی خاص
- TLA+: نمرات کمی بالاتر از میانگین در سطح متوسط و بیشتر در سطح xhigh بود. ۱۵۹ مورد از ۱۶۰ عامل یک مدل ماشین-وضعیت ساختند و ۳۰ مورد مدلهای Huffman/FSE/entropy را پیاده کردند، اما هیچکدام از این مدلها منجر به تغییر واقعی در کد Rust نشد.
- Kani: بهترین پوشش در استفاده از متد رسمی روی کد اجرایی را داشت، هرچند بیشتر سطحی بود. تنها در ۱ مورد از ۱۶۰ مورد، Kani توانست یک باگ غیربدیهی را پیدا کند. هزینههای این متد به دلیل خواندن مکرر و گرانقیمت خروجیهای Kani بهطور محسوسی بالاتر بود.
- حلکنندههای SMT: عاملها از Z3، cvc5 و Yices صرفاً بهعنوان پیشنویس برای محاسبات سرتیتر (Header) استفاده کردند. حتی هنگام مدلسازی، آنها نتوانستند از اشتباهات رایج دوری کنند؛ مثلاً بهجای جمع (
+ 0x7F00) از OR بیتی (| 0x7F00) استفاده کردند. - ACL2: اغلب منجر به خطای کمبود حافظه (OOM) شد (با رسیدن به سقف ۱۹۲ گیگابایت). اگرچه نمره آن از حالت پیشفرض بالاتر بود، اما احتمالاً این نتیجه علی و معلولی نبود زیرا اثباتها تأثیری بر صحت کد نداشتند.
- Spin: استفاده از آن سطحی بود و هیچ همبستگی با پاس کردن تستهای پنهان نداشت.
پارادوکس TDD و تستهای مبتنی بر ویژگی
یکی از تکاندهندهترین یافتهها این بود که دستور استفاده از TDD در واقع صحت کد را کاهش داد. عاملهای TDD دو برابر تست بیشتری نوشتند و یک گردشکار تکرارشونده را دنبال کردند، اما بیشتر احتمال داشت تستهای «جعبهسیاه» بنویسند که لبههای سخت (Edge Cases) را نادیده میگرفت. برای مثال، در تست Jump Table برای چهار استریم Huffman، آنها اغلب تستهایی نوشتند که در آن تمام چهار استریم یکسان و بدیهی بودند.
لو اشاره کرد که در ۶۷ مورد از ۱۶۰ مورد، عاملهای TDD پیش از انجام پیادهسازی اساسی، یک یا چند تست شکستخورده داشتند، در حالی که این عدد برای حالت پیشفرض ۰ از ۱۶۰ بود. بر اساس تحلیل یوسی کرینین، دلیل این اتفاق آن است که نوشتن تست پیش از کد، عاملها را به سمت تستهای جعبهسیاه سوق میدهد و شناسایی «موارد سخت» را که تنها با تست جعبهسفید (بررسی مستقیم کد) ممکن است، دشوار میکند.
تستهای مبتنی بر ویژگی (PBT) از طریق کتابخانههایی مثل QuickCheck، Hegel و Proptest نیز شکست خوردند:
- عاملها به ورودیهای کاملاً تصادفی تکیه کردند که تقریباً همیشه به مسیرهای رد ورودی نامعتبر میرسید.
- ویژگیهای بدیهی را بررسی کردند که ارزش اعتبارسنجی واقعی نداشت. در اجراهای QuickCheck، ۶۳ مورد از ۱۶۰ مورد تنها یک ویژگی واحد را بررسی کردند.
- در بسیاری از موارد، صرفاً تستهای واحد (Unit Test) معمولی را درون یک فریمورک PBT نوشتند بدون اینکه از منطق واقعی PBT استفاده کنند.
- Proptest و وضعیت کلی «تست مبتنی بر ویژگی» نمراتی بالاتر از میانگین گرفتند، که احتمالاً به دلیل قابلیت «کوچکسازی» (Shrinking) برای یافتن ورودیهای شکستخورده سادهتر بود که ارزش اندکی اضافه کرد.
برتری حالت «پیشفرض»
وضعیت «پیشفرض» (Default) — جایی که هیچ دستور خاصی برای تست داده نشد — بهطور مداوم عملکردی بالاتر از میانگین داشت. این نشان میدهد که اجبار عاملها به استفاده از فریمورکهای خاص، باعث حواسپرتی آنها یا تشویقشان به بیشبرازش (Overfitting) کد برای پاس کردن تستهای ضعیفی میشود که خودشان نوشتهاند.
حتی مهارتهای تخصصی نیز ضعیف عمل کردند. مهارت ECC در مواردی که عامل واقعاً دستورات TDD آن را دنبال کرد، باعث افت صحت کد شد. نمره خام این مهارت تنها به این دلیل خوب به نظر میرسید که عاملهایی که مهارت را نادیده گرفتند (۷ عامل که آن را نخواندند و ۹ عامل که دیر خواندند) همگی به صحت ۱۰۰٪ رسیدند.
تنها وضعیتی که بهبود جزئی نشان داد، یک مهارت مینیمال بود که توسط لو نوشته شده بود و عاملها را به شناسایی نقاط ریسکی ترغیب میکرد، هرچند حتی این روش هم نتوانست جلوی خطاهای ابتدایی مانند ورودیهای تست پالیندروم (متقارن) را بگیرد.
هزینه سطحینگری
افزودن این تکنیکها هزینه توکنها را بهشدت افزایش داد بدون اینکه کیفیتی اضافه کند. برای مثال، مهارت Hegel هزینهها را ۲۶٪ تا ۴۱٪ افزایش داد زیرا عامل را مجبور میکرد حجم زیادی از تستهای رفتوبرگشتی کمارزش تولید کند و مستندات حجیم را بارها بخواند. این مهارت (۳۴ هزار کاراکتر) و مرجع Rust (۴۵ هزار کاراکتر) در مجموع بیش از ۲۰ هزار توکن بودند که منجر به هزینه اضافی متوسط ۱۶٪ برای سطح medium و ۱۸٪ برای xhigh شد.
سایر متدهای تست
- فازینگ: عموماً بیاثر بود، اما در ۱۰ مورد از ۱۶۰ مورد که عاملها ورودیهای تصادفی ساختاریافته تولید کردند، نیمی از آنها باگهای واقعی را پیدا کردند. این یعنی عاملها «میتوانند» این کار را بکنند اگر بهشدت تحت فشار باشند.
- ممیزی (Audit): در سطح تلاش xhigh بهترین صحت را داشت اما در سطح متوسط ضعیف بود. اکثر عاملها (۱۵۱ از ۱۶۰ مورد) ادعا کردند مشکلی را در ممیزی یافتهاند، اما اغلب همان اشتباهی را تکرار کردند که قبلاً مرتکب شده بودند. ام چو (Em Chu) اشاره کرد که بخش زیادی از توکنها صرف ممیزی میشود، اما این کار تنها زمانی مفید است که عامل از ایجاد زیر-عاملها (Subagents) یا اجرای کد منع شود.
- تست تفاضلی: یکی از بدترین نتایج (رتبه سوم از آخر) را داشت. عاملها نتوانستند دو پیادهسازی مستقل بسازند و بهجای آن، یک کد باگدار را دو بار نوشتند و آنها را با هم مقایسه کردند.
- تست جهش: عاملها عموماً تست جهش واقعی انجام ندادند و بهجای آن، تستهای معمولی را با تغییرات جزئی و بیربط اجرا کردند.
- تست متامورفیک: عاملها ویژگیهای معقولی را بررسی کردند (مثلاً درج فریمهای قابل پرش)، اما نقاطی را که مکرراً در آنها شکست میخوردند نادیده گرفتند. لو اشاره کرد که تست متامورفیک در سطح xhigh کمتر از سطح medium استفاده شد.
تحلیل: نقطه کور تست در مدلهای زبانی
این دادهها نشاندهنده یک شکست سیستماتیک در نحوه آموزش مدلهای زبانی برای کدنویسی است. در حالی که عاملها در بهینهسازی زمان اجرا (Runtime Optimization) مهارت یافتهاند (احتمالاً به دلیل محیطهای RL)، اما فاقد یک مدل ذهنی برای «تست خصمانه» (Adversarial Testing) هستند. آنها به تست بهمثابه یک چکلیست از «کارهایی که باید انجام شود» نگاه میکنند، نه فرآیندی برای کشف حقیقت.
گری برنهارت (Gary Bernhardt) رویکرد هوش مصنوعی به تست را اینگونه توصیف کرد: برداشتن «موارد پاتولوژیک که ۱۵ سال پیش توسط مخالفان Mockها تصور شده بود» و تبدیل آن پاتولوژیها به ستون فقرات استراتژی تست. این مطالعه تأیید میکند که حتی وقتی از عاملها خواسته میشود از کتابخانههای خاص استفاده کنند، آنها صرفاً عادتهای تست ضعیف خود را در یک فریمورک جدید میپیچند.
برای جامعه فنی، این یافته معیار «کدنویسی عاملمحور» را تغییر میدهد. ثابت شد که دادن دسترسی به ابزاری مثل Z3 یا Kani بدون توانایی فرمولبندی «ناورداها» (Invariants) درست، کاملاً بیفایده است. وضعیت فعلی کدنویسی هوش مصنوعی شبیه «اثر چراغ خیابان» است: عاملها باگها را جایی جستوجو میکنند که نور هست (تستهای واحد ساده)، نه جایی که باگها واقعاً حضور دارند (تعاملات پیچیده وضعیت).
گام بعدی شما
- در پروژههای حساس، هرگز به تستهای تولیدشده توسط عاملها برای منطقهای بحرانی تکیه نکنید.
- بهجای دستور به مدل برای «تست کردن»، مجموعهای از تستهای باکیفیت نوشتهشده توسط انسان را به مدل بدهید تا روی آنها تکرار (Iterate) کند.
- منتظر بمانید و ببینید آیا آزمایشگاههای AI محیطهای یادگیری تقویتی (RL) مخصوص تولید تستهای خصمانه را برای حل این شکاف استدلالی پیاده میکنند یا خیر.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو