پرش به محتوای اصلی
پرش به محتوای مقاله

چرا ساختارهای مبهم مخزن مانع عملکرد صحیح عامل‌های کدنویس می‌شود؟

·۱۲ شهریور ۱۴۰۵۸ دقیقه مطالعه
راهنما
قرارداد کاری: قراردادهای مخزن تولید برای عامل‌های کدنویسی هوش مصنوعی
قرارداد کاری: قراردادهای مخزن تولید برای عامل‌های کدنویسی هوش مصنوعی
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

جایگزینی استراتژی «پرامپت‌های طولانی» با «قراردادهای ساختاری مخزن»؛ یعنی به جای اینکه به مدل بگوییم چه کند، محیطی می‌سازیم که مدل نتواند اشتباه کند.

یک وصله (Patch) که در ظاهر درست به نظر می‌رسد، می‌تواند کل سیستم تولید را متوقف کند، اگر عامل (Agent) مسیر داده‌ای اشتباهی را انتخاب کرده، یک جزء موجود را تکرار کرده، یک مورد رد (Denial Case) را نادیده گرفته یا یک رابط عمومی را بدون توجه به اثرات جانبی تغییر داده باشد. راهکار این مشکل، نوشتن پرامپت‌های طولانی‌تر نیست، بلکه طراحی مخزن کد به عنوان یک «قرارداد کاری» بین کد و عامل است.

به نقل از راهنمایی که در ۳ سپتامبر ۲۰۲۶ در dev.to منتشر شد، کلید حل این بحران در تبدیل قراردادهای ضمنی به دستورالعمل‌های مرئی، محدود و تست‌شده است. اکثر توسعه‌دهندگان با عامل‌ها مثل جعبه‌های جادویی رفتار می‌کنند که باید کد را «به طور خودکار بفهمند»، اما در واقعیت، عامل‌ها زمانی دچار مشکل می‌شوند که مرزها نامرئی باشند یا مالکیت کد مبهم باشد. این وضعیت یک شکاف خطرناک ایجاد می‌کند که در آن عامل ممکن است یک رابط عمومی را تغییر دهد بدون اینکه متوجه تأثیرات پایین‌دستی آن شود. این چالش‌ها در واقع ریشه در همان محدودیت‌های استقلال عامل‌ها در محیط‌های عملیاتی دارد که باعث می‌شود خروج آن‌ها از محیط دمو به محیط تولید دشوار شود. برای پل زدن بر این شکاف، تیم‌ها باید از «دانش قبیله‌ای» ضمنی به سمت مستندات صریح و قابل خواندن برای عامل حرکت کنند.

تصور کنید مخزن کد شما مثل یک شهر است — اگر تابلوی راهنمایی نباشد و قوانین منطقه‌بندی محرمانه بماند، یک پیمانکار جدید احتمالاً به طور تصادفی وسط منطقه مسکونی، یک آسمان‌خراش می‌سازد. قراردادهای مخزن دقیقاً مثل همین تابلوها و قوانین منطقه‌بندی برای ابزارهایی مثل Claude Code یا Cursor عمل می‌کنند تا عامل دقیقاً بداند هر ویژگی به کجا تعلق دارد و کدام بررسی‌ها باید پیش از ادغام (Merge) پاس شوند.

نقشه‌برداری از قلمرو

یک عامل باید بتواند مرزهای مهم را در عرض چند دقیقه پیدا کند. این راهنما توصیه می‌کند به جای یک فایل عظیم، یک نقشه فشرده در README ریشه قرار دهید که به اسناد عمیق‌تر لینک شود. یک ساختار معمولی شامل موارد زیر است:

  • apps/: جداسازی سطوح وب و موبایل.
  • packages/: منطق مشترک رابط کاربری (UI)، داده‌ها و تنظیمات.
  • server/: مسیرهای مجزا برای Routeها، سرویس‌ها و Jobها.
  • tests/: پوشه‌های اختصاصی برای تست‌های قرارداد و Fixtureها.
  • docs/: سوابق معماری و تصمیمات.

قرارداد کاری: قراردادهای مخزن تولید برای عامل‌های کدنویسی هوش مصنوعی

نام‌گذاری به تنهایی قرارداد نیست. هر دایرکتوری نیاز به یک قانون مالکیت دارد. برای مثال، پوشه routes/ باید مالک اعتبارسنجی انتقال داده (Transport Validation) و نگاشت پاسخ (Response Mapping) باشد، در حالی که services/ مالک عملیات محصول است. پوشه data/ می‌تواند مالک دسترسی به لایه ماندگاری (Persistence) باشد و jobs/ مالک کارهایی باشد که عمرشان از یک درخواست (Request) بیشتر است. اگر یک بازبین انسانی نتواند تشخیص دهد چه زمانی تغییری این قوانین را نقض کرده، ساختار پوشه‌ها صرفاً جنبه زیبایی دارد و به جای شفافیت، عدم قطعیت را افزایش می‌دهد. از ایجاد پوشه‌هایی که فقط برای ظاهر هستند پرهیز کنید؛ اگر هیچ‌کس نتواند توضیح دهد چه چیزی در services/ در مقابل routes/ قرار می‌گیرد، این لایه اضافی فقط واژگان را زیاد می‌کند بدون اینکه عدم قطعیت را کاهش دهد.

حقایق و دستورات اجرایی

مستندات باید به صورت «حقایق اجرایی» ثبت شوند. فایل README ریشه باید لیست دقیقی از دستورات نصب، توسعه، تست، Type، Lint، Build و Migration را که واقعاً کار می‌کنند، شامل شود. ذکر پیش‌نیازها — مانند سرویس‌های محلی مورد نیاز، Fixtureها، نام تنظیمات یا حالت‌های تست — مانع از توهم (Hallucination) عامل در ابداع دستورات خیالی می‌شود.

قراردادهای قوی باید قابلیت کپی-پیست داشته باشند. راهنما پیشنهاد می‌کند دستورات متمرکز برای تست‌های سرور، بررسی‌های UI و آرتیفکت‌های تولید لیست شوند. این کار تضمین می‌کند که عامل پیش از تلاش برای اجرای کل مجموعه تست‌ها، بررسی‌های خاص مربوط به مرز تغییر یافته را اجرا کند. برای مثال:

  • تست‌های متمرکز سرور: <دستور مخزن برای مسیر تست سرور>
  • بررسی‌های UI: <دستور مخزن برای سطح اپلیکیشن تغییر یافته>
  • بررسی‌های Type و Build: <دستور مخزن برای آرتیفکت تولید>

برای مخزنی که بررسی نکرده‌اید، دستورات ابداع نکنید. هدف ثبت دستورات واقعی است، نه اینکه مستندات کامل به نظر برسند. مقادیر محرمانه (Secret) را از مثال‌ها حذف کنید و کلیدهای تنظیمات را فقط با نام مستند کنید. یک عامل همچنین باید بداند کدام فایل‌ها تولید شده‌اند (Generated)، کدام Migrationها نیاز به بررسی دارند و آیا تغییرات در Lockfile مورد انتظار است یا خیر، تا یک وظیفه بی‌خطر به یک تغییر Build توجیه‌نشده تبدیل نشود.

اجرای مالکیت مرزها

قراردادهای محیط تولید باید مسیر درخواست را خوانا کنند. یک Route باید وظایف را تفویض کند تا همه کارها را خودش انجام ندهد. برای مثال، یک تابع createProject در مسیر server/routes/projects.ts فقط باید انتقال داده (Transport) را مدیریت کند. این تابع باید احراز هویت را به یک تابع دسترسی (Access Function) و عملیات اصلی را به یک سرویس تفویض کند.

در یک پیاده‌سازی تمیز، Route مالک انتقال است، تابع دسترسی مالک احراز هویت است، سرویس مالک عملیات محصول است و Response Mapper مالک شکل عمومی پاسخ است. این جداسازی، سطح بررسی را برای عامل کوچک می‌کند. وقتی از عامل خواسته می‌شود ایجاد پروژه را تغییر دهد، نقطه شروع مشخصی دارد. این موضوع مربوط به یک معماری خاص نیست، بلکه یک قانون نام‌گذاری و مالکیت است: هر مرز باید یک دلیل برای تغییر و یک تست برای توصیف قراردادش داشته باشد.

API داده و احراز هویت

عامل‌ها هرگز نباید مالکیت را از روی نام جداول یا کامنت‌ها استنتاج کنند. محدودیت‌های احراز هویت باید نزدیک به عملیات داده قرار گیرند. به جای یک تابع کلی findProject استفاده از findWorkspaceProject به طور صریح به عامل می‌گوید که رابطه با Workspace بخشی از عملیات است.

مثال پیاده‌سازی:
export async function findWorkspaceProject(actorId: string, workspaceId: string, projectId: string) { return db.project.findFirst({ where: { id: projectId, workspaceId, members: { some: { actorId } } } }) }

تست مسیرهای رد (Denial Path) به همان اندازه حیاتی است. تستی که تایید کند پروژه‌ای خارج از Workspace کاربر مقدار null برمی‌گرداند، یک مثال عینی از مرز امنیتی برای عامل فراهم می‌کند. این کار مانع از آن می‌شود که عامل سعی کند قوانین را از روی فایل‌های سیاست‌گذاری دوردست بازسازی کند. از نام‌هایی استفاده کنید که خود حامل قانون باشند، به جای اینکه به عامل تکیه کنید تا آن را از یک فایل سیاست دوردست استخراج کند.

قوانین بادوام و ابزارها

حقایق سراسری پروژه باید در یک فایل دستورالعمل پروژه، مانند CLAUDE.md برای Claude یا .cursorrules برای Cursor قرار گیرند. این فایل‌ها باید موارد زیر را پوشش دهند:

  • کجا احراز هویت و دسترسی به داده‌ها اجرا می‌شود.
  • کدام دستورات یک Build تولید را تایید می‌کنند.
  • کدام دایرکتوری‌ها حاوی فایل‌های تولید شده هستند.
  • کدام رابط‌ها نیاز به یادداشت Migration دارند.
  • کدام فایل‌ها محافظت‌شده یا فقط مخصوص سرور هستند.
  • یک گزارش تکمیل (Completion Report) باید شامل چه مواردی باشد.

قوانینی که فقط برای یک دایرکتوری کاربرد دارند، باید نزدیک به همان دایرکتوری یا در یک قانون محدود به مسیر (Path-scoped) باشند. رویه‌هایی که مکرراً تغییر می‌کنند باید از دستورالعمل‌های اصلی لینک شوند تا فایل اصلی موجز باقی بماند. قصد و هدف را در ابزارهای مختلف ثابت نگه دارید: تصمیمات پروژه و نحوه تایید را توضیح دهید، نه توصیه‌های کلی برنامه‌نویسی که هر عاملی از قبل می‌داند. قانون باید پیش از شروع ویرایش قابل کشف باشد؛ اگر عامل مجبور باشد برای یافتن دستورالعمل محافظت از یک جدول پرداخت، کل مخزن را جست‌وجو کند، یعنی مخزن از قبل مسیر ناامن را ساده‌تر کرده است.

محافظت از مسیرهای پرریسک

برخی فایل‌ها نیاز به قوانین بررسی صریح دارند. راهنما پیشنهاد می‌کند Migrationها، سیاست‌های احراز هویت، وضعیت پرداخت (Billing State)، انواع پاسخ‌های عمومی، آرتیفکت‌های تولید شده و تنظیمات استقرار به عنوان «محافظت‌شده» علامت‌گذاری شوند. یک یادداشت محافظتی ساده می‌تواند عامل را هدایت کند:

  • فایل‌های تولید شده را به صورت دستی ویرایش نکنید.
  • هر Migration در Schema نیاز به یادداشت اثر بر داده‌ها دارد.
  • هر تغییر در احراز هویت نیاز به یک تست مثبت و یک تست منفی دارد.
  • هر تغییر در پاسخ عمومی نیاز به بررسی مصرف‌کننده (Consumer Check) دارد.
  • هر تغییر در تنظیمات استقرار نیاز به نتیجه Smoke-test دارد.
  • هرگز Secretها را کامیت نکنید یا آن‌ها را در لاگ‌ها و Fixtureها کپی نکنید.

در حالی که متن راهنمای عامل است، اجرا باید در CI، سیاست‌های Branch یا احراز هویت سرور باقی بماند. یک جمله نمی‌تواند درخواستی را که اپلیکیشن باید رد کند، مسدود کند. برای استفاده از ابزار، دامنه کاربر و Workspace باید تا حد امکان خارج از آرگومان‌های تحت کنترل مدل بماند. ورودی ابزار را اعتبارسنجی کنید، مالکیت منابع را بلافاصله پیش از اجرا بررسی کنید و برای اثرات جانبی حساس، تاییدیه مورد اعتماد بخواهید.

تست‌ها و سوابق تصمیمات

تست‌ها باید در کنار رفتاری باشند که از آن محافظت می‌کنند. تست‌های Route احراز هویت، مالکیت، اعتبارسنجی ورودی و رفتار پاسخ را تثبیت می‌کنند، در حالی که تست‌های سرویس، قوانین محصول را تثبیت می‌کنند. هیچ تستی نباید برای درک قرارداد خود، به کل پیاده‌سازی ماژول دیگر نیاز داشته باشد.

از Fixtureهای سانسورشده برای موارد تکراری مرزی استفاده کنید، مانند یک کاربر غیرمجاز، یک دسترسی منقضی شده، ورودی معیوب، یک رویداد تکراری یا Timeout ارائه‌دهنده (Provider). این کار مثال‌های عینی را بدون افشای داده‌های واقعی مشتری در اختیار عامل قرار می‌دهد.

نام تست‌ها باید بر اساس تصمیمات باشد، نه پیاده‌سازی. تستی با نام rejects_cross_workspace_project پس از یک بازنویسی (Refactor) همچنان مفید است، در حالی که تستی با نام uses_project_repository_method_2 سریعاً منسوخ می‌شود.

برخی انتخاب‌ها از روی کد مشخص نیستند. توصیه می‌شود سوابق تصمیمات (Decision Records) کوتاهی بنویسید که زمینه، انتخاب و موازنه (Trade-off) را توضیح دهد. برای مثال، ایزوله کردن رفتارهای خاص یک Provider پشت یک آداپتور (Adapter) باید ثبت شود:

  • تصمیم: نگه داشتن گزینه‌های خاص Provider پشت آداپتور.
  • زمینه: Providerها کنترل‌های متفاوتی برای پاسخ و ابزار دارند.
  • انتخاب: نرمال‌سازی رفتار محصول و حفظ جزئیات Provider پشت یک خروجی صریح (Escape Hatch).
  • موازنه: فراخوان‌ها باید برای استفاده از ویژگی‌های خاص Provider، صراحتاً درخواست دهند.

انتخاب، دلیل و پیامد را ثبت کنید و به کد متأثر لینک دهید. وقتی تصمیم تغییر می‌کند، رکورد جدیدی اضافه کنید و قبلی را بی‌صدا بازنویسی نکنید. این کار مانع از آن می‌شود که عامل یک استثنای توضیح‌نشده را به عنوان الگوی ترجیحی در نظر بگیرد.

تکمیل مبتنی بر شواهد

یک قرارداد ناقص است اگر تعریف نکند چگونه کار را به پایان برسانیم. عامل‌ها باید موظف به ارائه گزارش تکمیل شامل موارد زیر باشند:

  • تغییرات (Changed): لیست فایل‌ها و منطق خاص اضافه‌شده (مثلاً: «بررسی مالکیت Workspace اضافه شد»).
  • تایید شده (Verified): کدام تست‌های متمرکز و بررسی‌های Type پاس شدند (مثلاً: «تست‌های متمرکز سرویس: پاس شد»).
  • اجرا نشده (Not run): کدام بررسی‌ها رد شدند و چرا (مثلاً: «مجموعه کامل End-to-End؛ زیرا سرویس محلی Provider در دسترس نبود»).
  • ریسک (Risk): شکاف‌های باقی‌مانده، مانند نیاز به یک Fixture برای Timeout پیش از انتشار بعدی.

گزارش «اجرا نشده» مفیدترین شواهد برای یک بازبین انسانی است. این کار مانع از آن می‌شود که یک بررسی در دسترس نبودن، به اشتباه به عنوان ادعایی مبنی بر صحت کد تلقی شود. برای جریان‌های کاری AI، شناسه درخواست (Request ID)، نام ابزارها، تصمیمات سیاست‌گذاری، تعداد تلاش مجدد (Retry Count) و دسته‌های خطای ایمن را در برنامه تاییدیه بگنجانید.

حفظ قرارداد

مخازن زمانی دچار انحراف می‌شوند که استثناها تبدیل به الگو شوند. پس از هر ویژگی، تیم‌ها باید بپرسند: آیا عامل بعدی می‌تواند بدون توضیح خصوصی، Route، سرویس، قانون داده، تست، رکورد تصمیم و دستور مورد نیاز را پیدا کند؟ اگر نه، مرزها باید بهبود یابند.

افزودن قوانین در زمان ایجاد ابهام و حذف قوانینی که دیگر راهنمای تصمیمات نیستند، باعث می‌شود مسیر مشترک راحت‌تر از مسیر استثنائی کشف شود. این کار مخزن کد را از توده‌ای از فایل‌ها به یک سیستم خوانا برای عامل‌های AI تبدیل می‌کند. برای جلوگیری از انحراف پیکربندی در مقیاس بزرگ، می‌توان از رویکردهای کامپایلری در مدیریت تنظیمات استفاده کرد تا هماهنگی بین عامل‌ها حفظ شود. کیت‌های Full-stack شرکت OTF نقطه شروعی عملی با فایل‌های CLAUDE.md و .cursorrules و بیش از ۲۰ پرامپت تست‌شده AI ارائه می‌دهند، هرچند مسئولیت نهایی بازبینی و پذیرش همچنان بر عهده تیم انسانی است.

گام بعدی شما

  • فایل .cursorrules یا CLAUDE.md را به ریشه مخزن خود اضافه کرده و قوانین مالکیت پوشه‌ها را در آن ثبت کنید.
  • دستورات تست و Build را از حالت «دانش ضمنی» خارج کرده و در README به صورت لیست‌های اجرایی بنویسید.
  • برای هر تغییر حساس در احراز هویت، یک تست «مسیر رد» (Denial Path) بنویسید تا مرز امنیتی برای عامل ملموس شود.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

این رویکرد با تکیه بر تخصص در مهندسی نرم‌افزار، ریسک تخریب سیستم‌های تولیدی توسط AI را کاهش می‌دهد. تبدیل مستندات به حقایق اجرایی، اعتماد به اتوماسیون کدنویسی را از سطح «امیدواری» به سطح «سنجش‌پذیری» می‌برد.

تأثیر برای ایران

برای تیم‌های توسعه در ایران که با محدودیت منابع انسانی برای بازبینی دقیق کدها روبرو هستند، پیاده‌سازی این قراردادها می‌تواند نرخ خطای عامل‌های رایگان یا ارزان‌قیمت را به شدت کاهش دهد.

·نگاه ما
تحریریه دات‌هوش

تمرکز بر «قراردادهای کاری» نشان می‌دهد که گلوگاه فعلی عامل‌های کدنویس، قدرت استدلال مدل نیست، بلکه فقدان یک پروتکل ارتباطی استاندارد بین ساختار فایل‌ها و درک مدل است. در واقع، ما در حال گذار از دوران «پرامپت‌نویسی» به دوران «مهندسی محیط» هستیم؛ جایی که کیفیت خروجی مدل بیش از آنکه به دستور ما وابسته باشد، به خوانایی ساختاری مخزن کد بستگی دارد.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.