تصور کنید یک برنامهنویس ساعتها با یک عامل هوش مصنوعی دربارهی اصلاح یک باگ بحث میکند، اما در نهایت میفهمد هیچ فایلی تغییر نکرده است. این کابوس زمانی رخ میدهد که نشان سبز «متصل» (Connected) در رابط کاربری، در واقع یک دروغ باشد.
به نقل از تحلیل فنی عمیقی که در ۲۳ سپتامبر ۲۰۲۶ در وبسایت dev.to منتشر شد، دلیل شکست ۱۵ دقیقه نخستِ راهاندازی عاملهای کدنویس معمولاً کیفیت مدل یا ضعف در پرامپت نیست، بلکه ناتوانی عامل (Agent) در نوشتن روی دیسک است. این عامل شبیه به کارآموزی است که دستورات را میفهمد اما کلید ورود به بایگانی را ندارد. در واقع، فرآیند روی یک پرسش خاموش متوقف میشود: «آیا این پردازش میتواند در جایی که شما فکر میکنید مخزن (Repo) قرار دارد، فایلی بنویسد؟» اگر پاسخ منفی باشد، تمام پرامپتهای بعدی صرفاً یک نمایش تئاتریکال است؛ زیرا مدل روی دیسکی عملیات انجام میدهد که شما هرگز آن را نمیبینید.
این اصطکاک زمانی رخ میدهد که توسعهدهنده به یک دستدادن (Handshake) در وبساکت بیشتر از یک عملیات سادهی نوشتن روی دیسک اعتماد میکند. شما مسیر مخزن را کپی و پیست میکنید، رابط کاربری میگوید «آماده است» و عامل با اعتمادبهنفس تغییراتی را پیشنهاد میدهد، درست مثل یک کارآموز با اعتمادبهنفس در روز اول کاری. اما این تغییرات اغلب در پوشهی /tmp، یک محیط Read-only (فقط خواندنی) یا یک باکس ریموت مینشینند که لپتاپ محلی شما هرگز به آن دسترسی نخواهد داشت. در این لحظه باید پرسید: آیا شکست مربوط به مدل بود، یا پرامپت، یا یک قانون در gitignore و یا یک UID (شناسه کاربر) که اجازه نوشتن در دایرکتوری نامگذاری شده را ندارد؟
همانطور که در تحلیل قبلی ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، اعتماد کورکورانه به لایههای انتزاعی رابط کاربری میتواند منجر به خطاهای سیستمی شدید شود. در اینجا، تجربه توسعهدهنده شبیه به استخدام شرکت باربری است که عکسی از یک خیابان اشتباه در زیر باران میفرستند و با لایک و شست رو به بالا میگویند «ما رسیدیم». کامیون شلوغ به نظر میرسد و چت دوستانه است، اما وسایل شما هنوز زیر باران در پیادهرو ماندهاند. شما ساعتها وقت صرف دیباگ لایهی اشتباه میکنید و قهوهتان را مینوشید، چون مدل در حال روایت پچی است که هرگز وجود نداشته و هرگز درخت کاری (Working Tree) را لمس نکرده است.
کالبدشکافی جلسات «تسخیرشده»
شکستها بسته به محیط متفاوتاند و به همین دلیل است که ربع اول ساعتِ شروع کار، شبیه به یک محیط تسخیرشده و مرموز به نظر میرسد. در لپتاپ محلی، ممکن است عامل محیطی را به ارث ببرد که در آن مسیر کاری فعلی (CWD) به جای ریشهی مخزن که شما توصیف کردید، آخرین تب باز در ادیتور باشد. در جلسات رایگانِ ریموت، نام میزبان (Hostname) ممکن است رسمی به نظر برسد، اما فضای متصل شده (Mount) اغلب خالی، Read-only یا متعلق به یک آزمایش قبلی است. این چالش در انتخاب میان زیرساختهای محلی و ابری همواره وجود دارد، موضوعی که در تحلیل ما دربارهی تعادل میان تأخیر و دسترسی در مدلهای محلی و ابری به تفصیل بررسی شده است.
عاملهای مدرنِ مبتنی بر مرورگر و مکانیزمهای فراخوانی تابع (Tool-calling) — مثل یک پیشخدمت که سفارش شما را یادداشت میکند اما هرگز به آشپزخانه نمیبرد — این سردرگمی را تشدید میکنند. یک فراخوانی HTTP موفق شبیه به «کار کردن» است، اما ممکن است فقط یک آرگومان JSON زیبا را در لاگها سریالیزه کند، نه اینکه فایلی را روی دیسک بنویسد. این وضعیت یک اثر «نمایش رادیویی» ایجاد میکند؛ جایی که راوی با اعتمادبهنفس صحبت میکند، اما هیچ صحنهای در واقعیت وجود ندارد. این پدیده دقیقاً همان جایی است که تفاوت میان لاگهای توهمی و رسیدهای واقعی در ارزیابی عملکرد AI نمایان میشود. ما به دموهای جدیدی نیاز نداریم که هرگز از تب مرورگر خارج نمیشوند و همچنان «بهکار گرفته شده» به نظر میرسند؛ ما به مدرکی نیاز داریم که ثابت کند تب مرورگر و دیسک، یک شخصیت واحد در این داستان هستند.
گردشکار قناری (Canary Workflow)
برای حل این مشکل، نویسنده یک «پروب قناری» پیشنهاد میکند؛ اسکریپت کوچکی که پیش از ارسال هر توکنی در چت، در شلِ عامل اجرا میشود. هدف این است که مجوزهای نوشتن و اجرا با استفاده از خودِ سیستمعامل به عنوان داور نهایی ثابت شود. این یک داشبورد سلامتِ سازنده یا ادعای یک صفحه فرود (Landing Page) نیست؛ بلکه قناریای است که در همان شلی که عامل قرار است از آن استفاده کند، با سیستمعامل بحث میکند.
پروب Bash: این گردشکار به صورت یک اسکریپت کدگذاری شده است. این اسکریپت از
set -euo pipefailاستفاده کرده و یک برچسب زمانی (date -u +%Y%m%dT%H%M%SZ) را برای ایجاد یک فایل منحصربهفرد ثبت میکند. اسکریپت مواردی چونhostname(نام میزبان)،id -un(نام کاربر)،id -u(شناسه کاربر) وpwd -P(مسیر واقعی) را بررسی میکند. همچنین به طور خاص تأیید میکند کهnodeو دستورgit rev-parse --show-toplevelدر دسترس هستند. سپس اسکریپت سعی میکند فایلی بسازد، اندازه آن را باtest -sچک کند و مجوزهای آن را باchmod u+xتغییر دهد. در نهایت، یک قطعه کد کوچک Node.js را روی دیسک مینویسد و اجرا میکند تا تأیید شودfs.accessSyncمسیر را قابل نوشتن گزارش میکند و سپس تمام آثار خود را پاک میکند. نویسنده پیشنهاد میکند این اسکریپت را به صورت./canary-before-chat.sh .یا با هدف قرار دادن مسیرهای خاص مانند./canary-before-chat.sh ./apps/webاجرا کنید تا مطمئن شوید هدف با ریشهی مخزنی که در یک Code Review از آن دفاع میکنید، مطابقت دارد.جایگزین Node.js: برای گردشکارهای مبتنی بر جاوااسکریپت، از یک پروب
.mjsاستفاده میشود تا از مشکلات کوتینگ (Quoting) در Bash در ایمیجهای عجیب جلوگیری شود. این پروب از ماژولهایnode:fs،node:osوnode:pathاستفاده میکند. نکته حیاتی این است که از پرچم نوشتن اختصاصی{ flag: 'wx' }استفاده میکند. اگرwxخطا دهد، به این معناست که کسی بقایای یک جلسه کرششده را در دایرکتوری رها کرده است، که این خود اطلاعات ارزشمندی است. این پروبos.hostname()،os.userInfo().uidوprocess.versionرا گزارش کرده و سپس فایل را حذف (unlink) میکند. این روش زمانی ترجیح داده میشود که عامل تمایل به استفاده از جاوااسکریپت دارد.دروغسنج: پس از اینکه عامل ادعا کرد پچ اعمال شده است، توسعهدهنده باید یک دروغسنج ارزانقیمت را از ترمینال خود اجرا کند. به جای اینکه از مدل بپرسید «آیا فایل را نوشتی؟» — که اغلب منجر به تولید «داستانهای تخیلی» (Fan Fiction) توسط مدل میشود — توسعهدهنده باید دستور
find . -name "dx-canary-$(date +%s)" -maxdepth 3 -printوgit status --short | headرا اجرا کند. اگرfindهیچ نتیجهای برنگرداند، جلسه صرفاً یک نمایش رادیویی بوده است. آیا واقعاً میخواهید درباره وضعیت React بحث کنید در حالی که سیستمفایل قبلاً حقیقت را به شما گفته است؟
عیبیابی پروب
وقتی قناری شکست میخورد، نتایج به جای دیباگ پیچیدهی مدل، به اقدامات ساده و خستهکنندهای ختم میشوند. نویسنده یک جدول تصمیمگیری را برای تبدیل مشاهدات به اقدامات پیشنهاد میکند:
- میزبان و PWD شبیه لپتاپ من است اما هدف سرور بود: این یعنی شما هرگز شل محلی را ترک نکردید. اقدام: جلسه ریموت را باز کنید و قناری را دوباره در آنجا اجرا کنید.
- هدف ریشهی git نیست: عامل دایرکتوری همسایهای را ویرایش خواهد کرد. اقدام: به ریشهی مخزن
cdکنید یا جلسه را رد کنید. - خطای Write fails with 'permission denied': وضعیت متصل، قابل نوشتن نیست. اقدام: مالکیت (Ownership) را اصلاح کنید یا فضای کاری دیگری انتخاب کنید.
- نبود Node یا Git: روایت مدل در چت تخیلی است. اقدام: زنجیره ابزارها (Toolchain) را نصب کنید یا میزبان را تغییر دهید.
- قناری مینویسد اما find آن را از لپتاپ من نمیبیند: دو سیستمفایل متفاوت در حال اشتراک یک گفتگو هستند. اقدام: ادغام وضعیت git محلی با ادعاهای ریموت را متوقف کنید.
- CANARY_PASS: دیسک با رابط کاربری موافق است. اقدام: اکنون اولین پرامپت مجاز است.
ریسکهای محیط ریموت
در سرورهای رایگان، اهمیت این پروب بیشتر میشود، زیرا مسیر شبکه و مسیر سیستمفایل به سرعت با هم اشتباه گرفته میشوند. یک ترمینال لپتاپ ممکن است طوری به نظر برسد که انگار یک Cloud Shell را هدایت میکند، در حالی که شما مثل یک راهرونده در خواب، در حال نوشتن در پوشهی ~/Downloads هستید. یک تب مرورگر میتواند به نظر برسد که به کلون شما متصل است، در حالی که مسیر کاری سرور /home/ubuntu است، بدون هیچ مخزنی و بدون بیتِ نوشتن (Write bit). پروب قناری این بحران هویت را به یک فایل تبدیل میکند که میتوانید آن را لیست کنید، و این تنها چراغ سبزی است که من در دقیقه اول به آن اعتماد میکنم.
وقتی میخواهم از بخش ریموت بدون راهاندازی VM شخصی استفاده کنم، از گزینه سرور رایگان MonkeyCode با دسترسی به مدلهای رایگان آن استفاده میکنم. افشای رابطه: این مقاله به عنوان بخشی از فعالیتهای ترویجی محصول MonkeyCode تهیه شده است. من ادعایی درباره نام مدل، سهمیه توکن یا عدد آپتایم نمیکنم، زیرا این جزئیات تغییر میکنند و شما باید خودتان آنها را تأیید کنید. اما متد مذکور قابل انتقال است: همان کاربر، همان CWD، همان بیت نوشتن، و تنها پس از آن، یک پرامپت.
محدودیتها و موازنه ها
این ریتوال یک ابزار زمخت است. تضمین نمیکند مدل یک معماری خاص را دنبال کند، یک باکس مشترک را برای اسرار (Secrets) تأیید نمیکند و ثابت نمیکند که رفرکتور بعدی مدل هوشمندانه است. حتی ممکن است در دایرکتوریای پاس شود که شما هرگز نباید آن را اکسپوز میکردید، که این بدتر از یک خطای Permission شدید در دقیقه اول است.
همچنین فرض میکند محیط دارای Bash، دستور id و باینری Node است. یک ایمیج Slim بدون Node، اسکریپت را با شکست مواجه میکند حتی اگر یک گردشکار فقط پایتونی کاملاً درست کار میکرد. در این موارد، توسعهدهندگان باید بلوک Node را حذف کرده و قناری را با استفاده از printf و test -w بنویسند تا زمانی که دیسک پاسخ دهد.
برخی توسعهدهندگان باید این مرحله را رد کنند: کسانی که Workstation شناختهشده دارند و یک Makefile دارند که هر روز محیط را Smoke-test میکند، یا کسانی که سیاستهای امنیتیشان حتی انداختن یک فایل قناری روی یک سرور رایگان مشترک را ممنوع میکند. همچنین اگر امیدوار بودید این پروب به یک دروازه آمادگی برای محیط Production تبدیل شود، باید آن را رد کنید، زیرا اینطور نیست و هرگز نخواهد بود. این رویکرد یادآور این نکته است که مدیریت پرامپتها در محیط تولید باید مانند کد در Git مدیریت شود تا از تبدیل شدن آنها به بدهی فنی جلوگیری شود.
این متد با استفاده از سرورهای رایگان MonkeyCode و دسترسی به مدلهای رایگان آن تست شده است. در حالی که این مقاله بخشی از همکاری با MonkeyCode است، متد مذکور در هر پلتفرمی قابل اجراست. شرط اصلی این است که دیسک باید پیش از اولین پرامپت، وارد گفتگو شود.
در نهایت، ۱۵ دقیقه چت درباره پچی که هرگز دیسک را لمس نکرده، پژوهش نیست، بلکه بررسی یک لباس مبدل است. آیا شما Pull Request کسی را میپذیرید که اصلاً مخزن را Clone نکرده اما پیامهای Slack بسیار شیک و متقاعدکنندهای میفرستد؟ تنها شیئی که انسان و عامل هر دو میتوانند به آن اشاره کنند، فایلی روی دیسک است. اگر یک شل موقت باز دارید، ابتدا تست نوشتن را اجرا کنید و اجازه دهید گفتگو تنها پس از وجود فایل شروع شود.
گام بعدی شما
- اسکریپت قناری را به عنوان بخشی از
setup.shپروژههای خود اضافه کنید تا پیش از شروع کار با عامل، دسترسیها تأیید شوند. - هرگاه عامل ادعای اعمال تغییرات را کرد، به جای پرسیدن از مدل، از دستور
git status --shortدر ترمینال مستقل استفاده کنید. - در محیطهای ریموت، ابتدا با یک دستور
touch test_fileساده، قابلیت نوشتن را در مسیر موردنظر بسنجید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو