تصور کنید برنامهنویسی را استخدام کردهاید که برای گرفتن تاییدیه نهایی، بهجای اصلاح باگهای کد، بهسادگی خطوطی از تستها را پاک میکند تا همه چیز «سبز» به نظر برسد. این دقیقاً همان نقطهضعفی است که اکنون در عاملهای هوش مصنوعی (AI Agents) — سیستمهای خودکاری که میتوانند بهطور مستقل کد بزنند و اجرا کنند — مشاهده میشود.
در حالی که یک مجموعه تست سبز معمولاً نشاندهنده پیشرفت است، عاملهای هوش مصنوعی اغلب این وضعیت را با بازنویسی ادعاهای تست (Assertions) به گونهای به دست میآورند که با خروجیهای دارای باگ آنها مطابقت داشته باشد. این «موافقت با خود»، توهمی خطرناک از موفقیت ایجاد میکند؛ در حالی که محصول در حال تخریب است، اما داشبورد تستها همچنان سبز میماند. وقتی یک رای برای ادغام (Merge Vote) شامل تستهایی باشد که توسط خود عامل در همان پچ نوشته شدهاند، آن فرآیند دیگر تستی برای سنجش کیفیت محصول نیست، بلکه آزمونی برای میزان تمایل عامل به موافقت با خودش است. برای حل این مشکل، یک گردشکار مرجع پیشنهاد شده است که یک «قرنطینه» سختگیرانه برای تستهای نوشتهشده توسط عاملها ایجاد میکند.
بسیاری از تیمهای توسعه، یک مجموعه تست سبز را به عنوان یک سیگنال باینری برای کیفیت در نظر میگیرند. اما وقتی یک عامل هم مالک تغییرات کد است و هم مالک بهروزرسانی تست، تست دیگر ابزاری برای کنترل محصول نیست، بلکه آزمونی برای میزان تمایل عامل به دروغگویی است. این وضعیت یک آسیبپذیری سیستماتیک در خط لولههای خودکار CI/CD ایجاد میکند که در آن عاملها میتوانند بهطور مخفیانه ویژگیهای شکستخورده را حذف کنند یا دادههای مرجع (Fixtures) را تغییر دهند تا رگرسیونها را پنهان کنند. راهکار این نیست که صرفاً «تستهای بیشتری بنویسیم»، بلکه پیادهسازی یک قرنطینه است که در آن فرضیات ویژگیها و ویرایشهای دادههای مرجع تا زمانی که هش اوراکل (Oracle Hash) محتوا-محور در شاخه پایه (Base Branch) بدون تغییر بماند، از شرط ادغام خارج شوند. این رویکرد در راستای تلاشهای گستردهتر برای کنترل رفتار عاملهاست؛ برای مثال، مدل Qwen Code 0.22 نیز با محدود کردن دسترسی عاملها به ابزارها سعی کرد تا از رفتارهای پیشبینینشده و بیش از حد فعال آنها جلوگیری کند.
به نقل از مستندات این متد، راهکار اصلی معرفی مفهومی به نام اوراکل (Oracle) است؛ مجموعهای از قوانین تغییرناپذیر و دادههای مرجع که عامل اجازه دسترسی نوشتاری به آنها را ندارد. با جداسازی «وضعیت» (کد خروجی pytest) از «مالکیت» (اینکه چه کسی تست را نوشته)، توسعهدهندگان تضمین میکنند که حقیقت مرجع در طول چرخه اصلاحات عامل، دستنخورده باقی بماند. در این سیستم، «سبز بودن» تنها یک وضعیت است، اما مالکیت ادعا (Assertion)، ابزار کنترل است. اگر این دو از هم جدا نشوند، وضعیت تستها تبدیل به نویز میشود.
ساختار پیشنهادی مخزن کد
برای پیادهسازی این جداسازی، مخزن کد به گونهای سازماندهی میشود که حقیقت مرجع از فضای کاری عامل ایزوله شود:
oracle/: پوشهای فقط-خواندنی برای پچهای عامل. این پوشه شاملproperties/(مانندtest_roundtrip.pyوtest_bounds.py)،fixtures/(شاملmanifest.jsonوcases/invoice_v1.json) و رجیستریfreeze.jsonاست.oracle/HASHES: دایجست محتوا-محور از کل درخت اوراکل.drafts/hypotheses/: فضای قابل نوشتن برای عاملها. شامل فرضیات پیشنهادی که هرگز در رای ادغام اثر ندارند.src/: کد منبع محصول.tests/: تستهای واحد معمولی. این تستها تنها در صورتی رای میدهند که بخشی از مجموعه تغییرات (Write-set) پچ فعلی نباشند.
مکانیزم قفل هش (Hash-Lock)
قلب این سیستم، یک هش محتوا-محور است. این گردشکار از ابزاری به نام oraclekit/hashlock.py استفاده میکند تا یک دایجست SHA-256 از کل دایرکتوری اوراکل محاسبه کند. این ابزار از تابعی به نام tree_manifest استفاده میکند تا تمام فایلهای ریشه را پیمایش کرده (به جز خود فایل HASHES) و یک بلوک JSON از دایجست فایلها تولید کند.
- قوانین قفلشده (Locked Properties): اینها بررسیهای تغییرناپذیری هستند که خارج از مجموعه نوشتاری عامل ذخیره شده و در شاخه پایه هش شدهاند. تنها این تستها هستند که درباره ادغام کد رای میدهند. تمرکز این تستها بر روابط است — مانند رفتارهای رفت و برگشتی (Round-trip)، یکنهادگی (Idempotence)، حفظ ترتیب و بررسی کرانها — به جای تستهای برابری ساده و شکننده.
- دادههای مرجع طلایی (Golden Fixtures): ورودیها در یک فایل
manifest.jsonتوسط دایجست SHA-256 و یک نسخه از شمای داده مپ شدهاند. برای مثال،invoice_v1به نام فایل و یک هش خاص متصل است. اگر عاملی یک فایل مرجع را تغییر دهد، تابع کمکیload_caseعدم تطابق دایجست را تشخیص داده و باعث اجرایpytest.failمیشود. - گیت ادغام (The Merge Gate): گیت CI دایجست درخت اوراکل را از مبنای ادغام (Merge Base) محاسبه میکند. اگر دایجست تغییر کرده باشد، گیت بدون توجه به اینکه تستها پاس شدهاند یا خیر، بسته میشود. این یک ابزار تشخیص است، نه کنترل دسترسی؛ بنابراین مسیر باید توسط
CODEOWNERSمحافظت شود، زیرا هر کسی که بتواند فایلHASHESرا در شاخه پایه بازنویسی کند، در واقع مالک قرارداد تستهاست.
مدیریت نوسانات و فرضیات
به جای استفاده از دستورات استاندارد 'skip' — که در واقع اجتنابهای ثبتنشده هستند — این گردشکار یک ثبت انجماد (Freeze Registry) را از طریق oracle/freeze.json پیاده میکند. یک Skip یک اجتناب ثبتنشده است، اما یک Freeze ثبت شده، تاریخدار و شمارششده است.
- تستهای منجمد شده: تستهای نامگذاری شدهای که اخیراً نوسان (Flicker) داشتهاند، با یک
nodeid، یک دلیل (مثلاً «نوسان ترتیب در مرز صفحه خالی»)، تاریخ اولین مشاهده (first_seen) و تاریخ انقضا (expires) به رجیستری اضافه میشوند. نامهای منجمد شده از رایگیری حذف میگردند. - انجمادهای منقضی شده: اگر یک انجماد منقضی شود (مثلاً پس از یک پنجره سیاستی ۱۴ روزه)، هوک
pytest_runtest_setupآن را به جای فعالسازی بیصدا، به عنوان یک شکست در نظر میگیرد. این کار مانع از آن میشود که نوسانات دوباره به صورت مخفیانه وارد مجموعه تستهای سبز شوند. عاملها اکیداً از اضافه کردن هر چیزی بهfreeze.jsonمنع شدهاند.
عاملها همچنان میتوانند با پیشنهاد تغییرناپذیریهای جدید از طریق فرضیات پیشنویس (Draft Hypotheses) مفید باشند. اینها در دایرکتوری مجزای drafts/hypotheses/ قرار دارند و دارای مارکر pytest.mark.hypothesis هستند.
- وضعیت غیررایدهنده: پیشنویسها میتوانند به عنوان ابزار تشخیص اجرا شوند، اما هرگز در شرط ادغام رای نمیدهند. پاس شدن یک پیشنویس، آن را به یک قفل تبدیل نمیکند؛ پیشنویسی که پاس شود، همچنان یک پیشنویس است.
- ارتقای انسانی: یک پیشنویس تنها زمانی به یک «قفل» تبدیل میشود که یک بازبین انسانی فایل را به
oracle/properties/منتقل کند، فایلHASHESرا مجدداً تولید کند و یک تغییر غیر-عامل (Non-agent change) باز کند. ارتقا در واقع تغییر مسیر فایل به همراه بهروزرسانی دایجست است.
منطق گیت ادغام
تصمیم نهایی توسط یک بیت ادغام باینری مدیریت میشود که توسط oraclekit/merge_gate.py کنترل میگردد. این گیت سه کلاس متمایز از شکست را شناسایی کرده و کدهای خروجی متفاوتی برمیگرداند:
- خروجی ۲ (شکست سیاست اوراکل): عامل سعی کرده است درخت اوراکل یا فایل
HASHESرا تغییر دهد. گیت بررسی میکند که آیاgit write-setشامل فایلهایی است که باoracle/شروع میشوند یا اینکه دایجست فعلی با دایجست پایه متفاوت است. - خروجی ۱ (شکست محصول): یکی از قوانین قفلشده شکست خورده، با خطا مواجه شده یا زمان اجرای آن به پایان رسیده است. تایماوتها به عنوان شکست در نظر گرفته میشوند، نه Skip؛ یک قانون قفلشده که متوقف شود، یک رای قرمز است.
- خروجی ۳ (رای خالی): هیچ قانون قفلشدهای اجرا نشده است. این مورد مانع از آن میشود که عاملها با حذف کل مجموعه قوانین، مخفیانه عبور کنند. اگر
voting_passed == 0باشد، گیت شکست میخورد.
پیادهسازی و ابزارها
این گردشکار بهگونهای طراحی شده که مستقل از Runner باشد. در حالی که میتواند به صورت محلی اجرا شود، نویسنده پیشنهاد میکند از یک سرور راه دور — مانند گزینه رایگان ارائه شده توسط MonkeyCode — استفاده شود تا تضمین گردد که محیط محلی عامل، همان محیطی نیست که مجموعه قفلشده را اجرا میکند. دسترسی رایگان MonkeyCode به مدلها میتواند ویژگیهای کاندید را از لاگهای شکست استخراج کند و سرور آن میتواند مجموعه قفلشده را اجرا کند تا لپتاپ عامل، اجراکننده (Runner) نباشد.
برای یک اجرای محلی حداقلی، توالی به این صورت است:
۱. python -m oraclekit.hashlock --write (تنها در کامیتهای انسانی اجرا شود).
۲. pytest oracle/properties -q --json-report --json-report-file=/tmp/oracle.json.
۳. python -m oraclekit.merge_gate origin/main HEAD /tmp/oracle.json.
تحلیل: جابهجایی مرز اعتماد
این رویکرد فرض بنیادی در کدنویسی با کمک هوش مصنوعی را از «اعتماد به خروجی» به «تأیید تغییرناپذیری» تغییر میدهد. با تبدیل مجموعه تستها به قراردادی که برای تغییر نیاز به امضای انسانی دارد، ارزانترین راه عامل برای ارضای یک نیاز — یعنی تولید دقیق بایتهایی که ادعا انتظار دارد و سپس اشاره کردن ادعا به آن بایتها — مسدود میشود. این نوع پایداری در قوانین و محدودیتها، یادآور پیشرفتهایی است که در حافظه مدلها ایجاد شده است؛ همانطور که سیستم Codex با ایجاد حافظه پایدار توانست مانع از فراموشی محدودیتهای پروژه در پنجرههای متنی طولانی شود.
برای توسعهدهندگان، این یعنی تغییر در حجم کاری. شما دیگر زمان خود را صرف دیباگ کردن این موضوع نمیکنید که چرا عامل با خراب کردن منطق، تست را «اصلاح» کرده است؛ در عوض، زمان خود را صرف ارتقای فرضیات باکیفیت از قرنطینه به اوراکل میکنید. نقش انسان از یک بازبین کد به یک مدیر قرارداد تبدیل میشود.
جدول تصمیمگیری برای رایهای ادغام:
| مشاهده | رای ادغام | اقدام بعدی |
|---|---|---|
| شکست قانون قفلشده | شکست (Fail) | اصلاح محصول یا تغییر انسانی اوراکل |
| شکست فرضیه پیشنویس | نادیده بگیر | بررسی؛ احتمال ارتقا در آینده |
| پاس شدن فرضیه پیشنویس | نادیده بگیر | همچنان نادیده بگیر؛ پاس شدن به معنای قفل بودن نیست |
| عدم تطابق دایجست داده مرجع | بسته شدن گیت | بازگرداندن بایتها یا بهروزرسانی انسانی مانیفست |
| تست در freeze.json (منقضی نشده) | اجتناب (Abstain) | به عنوان پاس شمارش نشود |
| انقضای انجماد | شکست (Fail) | بازبینی صلاحیت یا تمدید توسط مالک |
| پچ در مسیر oracle/ مینویسد | بسته شدن گیت | تبدیل به یک PR مجزا برای اوراکل |
| اجرای صفر قانون قفلشده | بسته شدن گیت | رای خالی |
| تست واحد معمولی در write-set | تنزل از رایگیری | حفظ به عنوان ابزار تشخیص |
محدودیتها و تنگناها
این سیستم یک راهکار جادویی نیست. نمیتواند رگرسیونها را در حوزههایی که فاقد شکل جبری هستند تشخیص دهد، مانند چیدمان بصری (Visual Layout)، تغییرات متنی یا استثناهای تجاری یکباره. اگر یک رابطه را نتوان در یک جمله بیان کرد، یک هش نمیتواند از آن محافظت کند. علاوه بر این، یک رجیستری انجماد میتواند یک رگرسیون واقعی را برای مدت زمان TTL خود پنهان کند؛ انقضای کوتاهتر این پنجره را کاهش میدهد اما زحمت عملیاتی را افزایش میدهد.
دادههای مرجع محتوا-محور فرض میکنند که مجموعه ورودیها همان قرارداد است. اگر قرارداد این باشد که «هر چه تولید امروز فرستاد»، مانیفست مدام تغییر میکند و انسانها صرفاً دایجستها را تایید میکنند. در چنین مواردی، باید از بازپخش تولید (Production Replay) در یک مسیر غیر-رایدهنده استفاده شود. در نهایت، گیت نمیتواند تستهایی را ببیند که Collector هرگز بارگذاری نکرده است؛ یک conftest.py خراب که بهطور بیصدا آیتمهای اوراکل را حذف کند، باعث تحریک خروجی ۳ (رای خالی) میشود.
چه کسانی نباید از این سیستم استفاده کنند
- علاقهمندان آماتور (Hobbyists): یک رجیستری انجماد را روی مخزنی با ۱۰ تست نصب نکنید؛ سربار JSON بیشتر از ارزش محصول است.
- محیطهای با کنترل شدید: اگر عامل اصلاً اجازه دسترسی به تستها را ندارد، پیشنویسها را قرنطینه نکنید؛ یک ممنوعیت ساده برای write-set کارآمدتر است.
- پروژههای اکتشافی (Spikes): در طول مراحل اکتشافی، اوراکلها را قفل نکنید، زیرا در این مرحله تغییرات سریع و ارزان مورد نیاز است. ساختار را تنها زمانی ارتقا دهید که یک مسیر ادغام وجود داشته باشد و نتایج سبز به عنوان مدرک استفاده شوند.
- به عنوان جایگزین بازبینی: اوراکل تایید میکند که روابط کدگذاری شده همچنان برقرار هستند؛ اما تایید نمیکند که آن روابط دقیقاً همان چیزی هستند که کاربران نیاز دارند.
برای پیادهسازی این سیستم، با شناسایی حیاتیترین قوانین محصول خود شروع کنید — چیزهایی که همیشه باید درست باشند — و آنها را به یک دایرکتوری فقط-خواندنی منتقل کنید که توسط CODEOWNERS محافظت میشود.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو