# راهنمای مشترک `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 بدون مصرف اضافه نشده