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