Files

14 KiB

راهنمای مشترک اسکیل‌های این پروژه

این فایل مرجع کیفیت همهٔ اسکیل‌های پروژه است. هر اسکیل باید در ابتدای بدنهٔ خود این خط را داشته باشد:

قبل از شروع، فایل .claude/guidelines.md را بخوان و همهٔ بخش‌های آن را اعمال کن.

قواعد stack و مسیر فایل‌ها در خود اسکیل‌ها می‌ماند؛ این فایل فقط چگونه کار کردن را تعیین می‌کند. اگر بین این فایل و متن پرامپت تناقضی بود، همین فایل برنده است — مگر اینکه کاربر صریحاً خلافش را بگوید.


۰. Grill — قبل از هر تغییر (اجباری)

قبل از نوشتن کد، ساختن فایل یا اجرای هر تغییر:

  1. ابزار Skill را با skill: "mattpocock-skills:grilling" صدا بزن.
  2. طبق آن اسکیل، سؤال‌ها را یکی‌یکی بپرس و بعد از هر سؤال منتظر جواب بمان.
  3. هر چیزی که با ابزار قابل کشف است را نپرس. خودت پیدا کن.
  4. اول graphify query "<سؤال>" بزن، بعد فایل بخوان.
  5. فقط تصمیم‌ها را از کاربر بپرس، نه واقعیت‌ها.
  6. برای هر سؤال، پاسخ پیشنهادی خودت را هم بنویس.
  7. تا وقتی کاربر «تأیید» نداده، هیچ فایلی را تغییر نده.

خروجی این مرحله یک درک مشترک است. بعد از تأیید، برو سراغ §۱.

استثنا: اگر کاربر گفت «بدون grill»، «مستقیم انجام بده» یا «سؤال نپرس»، این بخش را رد کن.


۱. درک مسئله — قبل از هر خط کد

هیچ چیز گران‌تر از پیاده‌سازیِ درستِ مسئلهٔ اشتباه نیست. به همین دلیل:

  • پرامپت/درخواست را کامل بخوان، بعد کد واقعیِ مرتبط را بخوان. هرگز از حافظه دربارهٔ کد پروژه فرض نکن — فایل را باز کن.
  • مسئله را با کلمات خودت بازگو کن: «مشکل این است که X؛ رفتار درست Y است؛ محدودهٔ تغییر فایل‌های Z». اگر این سه جمله را نمی‌توانی بنویسی، هنوز مسئله را نفهمیده‌ای.
  • برای هر قابلیت معیار پذیرش (acceptance criteria) تعریف کن: چه چیزی باید درست کار کند تا «تمام» حساب شود؟ شامل حالت موفق، حالت خطا، و حداقل یک حالت مرزی.
  • ابهام = توقف. سوال را همان اول بپرس، نه وسط پیاده‌سازی. حدس زدن وسط کار یعنی دوباره‌کاری.
  • در prompt-writer: قالب پرامپت باید بخش «معیار پذیرش» داشته باشد (بعد از «مشکل / هدف»). پرامپتی که معیار پذیرش ندارد ناقص است.
  • در run-prompt: مرحلهٔ «تحلیل» با بازگویی مسئله و معیار پذیرش به کاربر تمام می‌شود، نه فقط با لیست قابلیت‌ها.

۲. Todo — ستون فقرات اجرا

Todo فقط نمایش پیشرفت نیست؛ قرارداد بین تو و کاربر است که هیچ مرحله‌ای بی‌صدا رد نشود.

  • در ابتدای اجرا با TodoWrite لیست کامل بساز — یک آیتم به ازای هر قابلیت، همه pending.
  • هر آیتم باید قابل تست باشد: خروجی مشخص داشته باشد («endpoint X با response Y کار می‌کند»)، نه فعل مبهم («بررسی سیستم نوبت»).
  • در هر لحظه فقط یک آیتم in_progress.
  • آیتم فقط وقتی completed می‌شود که هر سهٔ این‌ها انجام شده باشد: پیاده‌سازی + تست سبز + مستندات به‌روز. کد بدون تست یا بدون سند، «تمام» نیست.
  • اگر وسط کار قابلیت جدیدی کشف شد (باگ جانبی، وابستگی پنهان)، به‌جای انجام بی‌صدا، آیتم جدید به todo اضافه کن و به کاربر بگو.

۳. تست — تعریف «تمام شد»

  • Definition of Done برای هر قابلیت: syntax/lint/build سبز و پوشش سه سناریوی معیار پذیرش (موفق، خطا، مرزی). این همان قاعدهٔ پروژه است: هیچ تسکی بدون تست تمام نیست.
  • خطا یعنی توقف کامل. هیچ قابلیتی روی خرابهٔ قابلیت قبلی ساخته نمی‌شود.
  • دستورهای تست هر پروژه در خود اسکیل run-prompt آمده؛ آن‌ها حداقل‌اند نه سقف. اگر قابلیت منطق دارد (نه فقط UI)، تست واقعی همان منطق را اجرا کن — مثلاً صدا زدن endpoint با داده واقعی، نه فقط php -l.
  • تغییر cross-repo تست خودکار ندارد. تغییر قرارداد API در build کلاینت‌ها خطا نمی‌دهد و در رانتایم می‌شکند؛ پس بعد از هر تغییر قرارداد، مصرف واقعی را در هر کلاینت متأثر دستی دنبال کن و نتیجه را گزارش بده.
  • در prompt-writer: در بخش «وظایف» یا «نکات مهم» هر پرامپت بنویس این قابلیت چطور تست می‌شود — تا run-prompt مجبور نباشد خودش تست را اختراع کند.

۴. مستندسازی — بخشی از کار، نه بعد از کار

  • سند در همان جلسه‌ای به‌روز می‌شود که کد تغییر کرده. «بعداً می‌نویسم» یعنی هرگز.
  • مپینگ src/*docs/api/*.md در اسکیل run-prompt است؛ الزام محتوایی: endpoint با method/path/permission، بدنهٔ request با نوع همهٔ فیلدها، response با JSON واقعی (خروجی اجرای واقعی، نه دست‌ساز)، همهٔ status/error codeها.
  • سند باید با کد هم‌خوان باشد: اگر سند موجود با رفتار فعلی فرق دارد، اول سند را اصلاح کن، بعد قابلیت جدید را اضافه کن.
  • خود فایل پرامپت هم سند است: در prompt-writer بخش «وضعیت فعلی» باید کپی از کد واقعی باشد؛ کد بازنویسی‌شده از حافظه ممنوع.
  • کامنت بدیهی ننویس؛ مستندات کوتاه و دقیق فقط روی چیزهای عمومی (public API، قرارداد، تصمیم معماری).

۵. کدنویسی — SOLID و الگوها در بستر این پروژه

الگو ابزار حل مسئله است، نه مدال. اول مسئله، بعد الگو.

SOLID — یعنی در این پروژه:

  • S (تک‌مسئولیتی): Controller نازک — فقط دریافت request، صدا زدن Service، برگرداندن response با $this->success()/paginated()/error(). منطق دامنه در Service؛ کوئری در Repository. در فرانت: کامپوننتی که هم fetch می‌کند، هم state پیچیده دارد، هم render سنگین — بشکن.
  • O (باز/بسته): رفتار جدید = کلاس/استراتژی جدید، نه if/switch جدید روی نوع. نمونه‌های واقعی این workspace: درگاه پرداخت، ارسال‌کنندهٔ SMS، نوع نوبت — برای این‌ها interface + پیاده‌سازی جدا، نه شاخه‌شاخه کردن یک Service.
  • L (جایگزینی): پیاده‌سازی جدیدِ یک interface باید همان قرارداد را کامل رعایت کند — همان شکل response، همان exceptionها. کلاسی که «تقریباً» قرارداد را رعایت می‌کند، cross-repo bug تولید می‌کند.
  • I (تفکیک interface): interfaceهای کوچک و متمرکز. اگر پیاده‌سازی‌ای مجبور است متدی را خالی بگذارد، interface بزرگ است.
  • D (وارونگی وابستگی): Service به interface وابسته باشد، نه کلاس concrete؛ تزریق با DI خود Symfony (constructor injection + autowiring). new کردن سرویس داخل سرویس ممنوع.

الگوهای پذیرفته‌شدهٔ این workspace:

الگو کجا چرا
Repository همهٔ دسترسی داده (Doctrine و لایهٔ repo در tauri) جداسازی کوئری از منطق
Service Layer منطق دامنه در src/*/Service Controller نازک، منطق قابل تست
Strategy پرداخت، SMS، هر جای «چند روش برای یک کار» افزودن روش جدید بدون دست زدن به موجود
Factory ساخت objectهای پیچیده/وابسته به نوع تمرکز منطق ساخت
Event/Observer Symfony EventDispatcher برای اثرات جانبی (نوتیف، لاگ) جدا کردن اثر جانبی از جریان اصلی
Adapter کلاینت‌های API (api.ts، services/response.js) یک نقطهٔ تماس با backend

مرز over-engineering:

  • الگو فقط وقتی که الان دو پیاده‌سازی یا یک نیاز مشخص برای تعویض وجود دارد. برای «شاید در آینده» abstraction نساز.
  • error handling فقط در boundaryهای واقعی (Controller، فراخوانی API، I/O) — نه try/catch دفاعی دور هر متد.
  • قبل از ساختن هر چیز جدید: اول بگرد (endpoint، کامپوننت، سرویس موجود)، بعد توسعه بده، در آخر بساز — و دلیلش را بنویس.
  • در prompt-writer: اگر راه‌حل پیشنهادی الگویی را به کار می‌برد، در بخش «نکات مهم» نام الگو و دلیل انتخابش را بنویس تا run-prompt همان مسیر را برود.

۶. رفتار تحلیل‌گر — نقش agent در هر دو اسکیل

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

  • اگر تصمیم کاربر یا راه‌حل خواسته‌شده در پرامپت اشتباه، ناقص یا پرریسک است، قبل از پیاده‌سازی صریح و با دلیل بگو و منتظر تعیین تکلیف بمان. اجرای بی‌چون‌وچرای یک پرامپت غلط، خطای agent است نه کاربر.
  • تأیید بدون تحلیل ممنوع — «ایدهٔ خوبی است» و «کاملاً درست است» بدون استدلال ننویس. هر نتیجه‌گیری بر پایهٔ منطق، شواهد، کد واقعی پروژه یا مستندات رسمی باشد.
  • بین واقعیت (کد/سند موجود)، فرضیه، نظر و حدس تفاوت بگذار و در گزارش‌ها برچسبش را مشخص کن. اگر داده کافی نیست، همین را بگو؛ حدس را قطعی جا نزن.
  • برای هر پیشنهاد طراحی: مزایا، معایب، ریسک‌ها و حداقل یک گزینهٔ جایگزین. اگر چند راه‌حل وجود دارد، مقایسه کن و دلیل انتخاب را بنویس. (جای طبیعی این کار مرحلهٔ «طراحی» در run-prompt و بخش «وظایف» در prompt-writer است.)
  • در تصمیم‌های مهم و موضوعات پیچیده، اول قدم‌به‌قدم تحلیل کن و ساختار/طرح پیشنهادی را قبل از خروجی نهایی ارائه بده و تأیید بگیر — نه اینکه مستقیم سراغ کد یا متن نهایی بروی.
  • مرجع ادعاهای فنی: مستندات رسمی فریم‌ورک‌ها و کد خود پروژه، نه حافظه.

و در تعامل:

  • سبک کد جدید = سبک فایل‌های مشابه موجود در همان پروژه؛ کد واقعی پروژه، نمونهٔ سبک است.
  • وقتی کاربر بازخورد می‌دهد، همان خروجی موجود را اصلاح کن؛ بازتولید از صفر فقط اگر خودش بخواهد.

۷. چک‌لیست پایان هر قابلیت (برای run-prompt)

قبل از completed کردن آیتم todo، همهٔ این‌ها باید تیک بخورد:

  • مسئله و معیار پذیرش در ابتدای کار بازگو و تأیید شده بود
  • اگر راه‌حل پرامپت ایراد یا ریسک داشت، قبل از اجرا اعلام و تعیین تکلیف شده بود
  • Controller نازک است؛ منطق در Service/Repository است
  • رفتار جدید با extension اضافه شده، نه با if روی نوع
  • وابستگی‌ها تزریق شده‌اند، نه new شده
  • تست‌ها سبزند: موفق + خطا + مرزی
  • اگر قرارداد API تغییر کرده: کلاینت‌های متأثر دستی بررسی و گزارش شده‌اند
  • docs/api/ (یا سند مرتبط) در همین جلسه به‌روز شده و با رفتار واقعی هم‌خوان است
  • هیچ کامنت بدیهی و هیچ abstraction بدون مصرف اضافه نشده