Files
clinicpro/.claude/guidelines.md
T

13 KiB

راهنمای مشترک prompt-writer و run-prompt

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

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

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


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

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

  • پرامپت/درخواست را کامل بخوان، بعد کد واقعیِ مرتبط را بخوان. هرگز از حافظه دربارهٔ کد پروژه فرض نکن — فایل را باز کن.
  • مسئله را با کلمات خودت بازگو کن: «مشکل این است که 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 بدون مصرف اضافه نشده