From ec6a4d7a859dd2110704346462324f94b2914f0d Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Mon, 27 Jul 2026 11:35:53 +0330 Subject: [PATCH] feat: add guidelines for prompt-writer and run-prompt skills --- .claude/guidelines.md | 118 ++++++++++++++++++++++++++ .claude/skills/prompt-writer/SKILL.md | 43 ++++++++-- .claude/skills/run-prompt/SKILL.md | 113 ++++++++++++------------ 3 files changed, 211 insertions(+), 63 deletions(-) create mode 100644 .claude/guidelines.md diff --git a/.claude/guidelines.md b/.claude/guidelines.md new file mode 100644 index 00000000..8e2072c8 --- /dev/null +++ b/.claude/guidelines.md @@ -0,0 +1,118 @@ +# راهنمای مشترک `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 بدون مصرف اضافه نشده diff --git a/.claude/skills/prompt-writer/SKILL.md b/.claude/skills/prompt-writer/SKILL.md index 38a31a29..fc816ce2 100644 --- a/.claude/skills/prompt-writer/SKILL.md +++ b/.claude/skills/prompt-writer/SKILL.md @@ -3,9 +3,11 @@ name: prompt-writer description: تولید فایل پرامپت .md برای یک قابلیت یا باگ‌فیکس در پروژه ClinicPro. استفاده کن وقتی کاربر می‌گوید «یک پرامپت بنویس»، «پرامپت بساز»، «write a prompt»، «برام پرامپت بنویس برای X». این skill پروژه را تحلیل می‌کند، سپس یک فایل .md کامل در .claude/prompt/ می‌سازد و دستور اجرا را نمایش می‌دهد. --- +> **قبل از شروع، فایل `.claude/guidelines.md` را بخوان و همهٔ بخش‌های آن را اعمال کن** (اگر روت جلسه workspace است: `clinicpro/.claude/guidelines.md`). آن فایل «چگونه کار کردن» (درک مسئله، معیار پذیرش، تست، مستندات، SOLID، رفتار تحلیل‌گر) را تعیین می‌کند؛ این skill فقط قواعد stack و مسیرها و قالب خروجی را دارد. در تناقض، guidelines برنده است. + ## نحوه دریافت ورودی -کاربر موضوع یا مشکل را توضیح می‌دهد. اگر توضیح کافی نبود، یک سوال کوتاه بپرس. +کاربر موضوع یا مشکل را توضیح می‌دهد. **ابهام = توقف**: اگر توضیح کافی نبود، همان اول یک سوال کوتاه بپرس و ادامه نده — نه وسط تحلیل. --- @@ -20,8 +22,13 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی - Backend: `src/` — Controllers، Services، Entities، Repositories - Frontend: `assets/admin/pages/`، `assets/admin/components/` - مستندات: `docs/api/` -3. **APIهای موجود را بررسی کن**: `ddev exec php bin/console debug:router | grep api` -4. **کد مرتبط را بخوان**: فقط فایل‌هایی که مستقیم به موضوع مربوطند +3. **APIهای موجود را بررسی کن**: `ddev exec php bin/console debug:router | grep api` — API جدید فقط وقتی هیچ اندپوینت موجودی، حتی با توسعه، کافی نباشد؛ دلیلش را در پرامپت بنویس +4. **کد مرتبط را بخوان**: فقط فایل‌هایی که مستقیم به موضوع مربوطند — کد واقعی، نه حافظه + +بعد از خواندن، **مسئله را با کلمات خودت بازگو کن** و به کاربر نشان بده: +«مشکل این است که X؛ رفتار درست Y است؛ محدودهٔ تغییر فایل‌های Z». اگر این سه جمله را نمی‌توانی بنویسی، هنوز مسئله را نفهمیده‌ای — سوال بپرس. + +**نقش تحلیل‌گر (guidelines §۶):** اگر راه‌حلی که کاربر خواسته اشتباه، ناقص یا پرریسک است، همین‌جا صریح و با دلیل بگو و منتظر تعیین تکلیف بمان — پرامپتِ یک راه‌حل غلط را ننویس. اگر چند راه‌حل جدی وجود دارد، کوتاه مقایسه کن (مزایا/معایب/ریسک) و دلیل انتخاب را در پرامپت ثبت کن. ### مرحله ۲ — نام‌گذاری فایل @@ -50,6 +57,14 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی <توضیح دقیق مشکل یا قابلیت مورد نیاز> +## معیار پذیرش + +<چه چیزی باید درست کار کند تا «تمام» حساب شود — قابل تست، نه کلی> + +- ✅ موفق: <رفتار درست در مسیر عادی — مثلاً «POST /api/v1/... با توکن ادمین → 200 و رکورد ذخیره می‌شود»> +- ❌ خطا: <رفتار درست در مسیر خطا — مثلاً «بدون permission → 403 با envelope خطا و کد از ErrorCodes»> +- ⚠️ مرزی: <حداقل یک حالت مرزی — لیست خالی، صفحه آخر pagination، تاریخ مرزی شمسی، …> + ## فایل‌های مرتبط | فایل | نقش | @@ -59,7 +74,7 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی ## وضعیت فعلی -<کد یا رفتار فعلی — فقط بخش مرتبط> +<کد یا رفتار فعلی — کپی از کد واقعی پروژه، نه بازنویسی از حافظه؛ فقط بخش مرتبط> ```php / tsx // کد فعلی مشکل‌دار یا ناقص @@ -75,6 +90,8 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی // نمونه کد یا pseudocode ``` +**نحوه تست:** <دقیقاً چطور این وظیفه تست می‌شود — دستور، curl با داده واقعی، سناریوی UI — تا run-prompt مجبور نباشد تست را اختراع کند> + ### ۲. <دومین وظیفه> ... @@ -83,7 +100,7 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی - <نکته معماری یا محدودیت مهم> - -- <الگوی پروژه که باید رعایت شود> +- <الگوی پروژه که باید رعایت شود؛ اگر راه‌حل از الگویی (Strategy، Factory، Event، …) استفاده می‌کند: نام الگو + دلیل انتخابش> ``` --- @@ -92,24 +109,29 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی **باید داشته باشد:** - مسیر دقیق فایل‌هایی که باید تغییر کنند -- وضعیت فعلی کد (کپی از کد واقعی، نه توصیف کلی) -- راه‌حل پیشنهادی با نمونه کد -- edge caseها -- الگوهای پروژه که باید رعایت شوند (BaseController، TanStack Query، Zod، ...) +- بخش «معیار پذیرش» با هر سه سناریو (موفق/خطا/مرزی) — **پرامپت بدون معیار پذیرش ناقص است** +- وضعیت فعلی کد (کپی از کد واقعی، نه توصیف کلی) — خود فایل پرامپت سند است +- راه‌حل پیشنهادی با نمونه کد؛ اگر الگو دارد، نام + دلیل +- «نحوه تست» برای هر وظیفه‌ای که منطق دارد +- edge caseها و الگوهای پروژه که باید رعایت شوند (BaseController، TanStack Query، Zod، ...) **نباید داشته باشد:** - توضیحات کلی و بدیهی - کدی که از پروژه واقعی کپی نشده - وظایف نامشخص مثل «بررسی کن» بدون مشخص کردن چه چیزی +- abstraction «برای آینده» — الگو فقط وقتی الان نیازش هست (guidelines §۵) **قوانین خاص پروژه که باید در پرامپت منعکس شود:** - Backend: همه controllerها از `BaseController` ارث می‌برند؛ پاسخ‌ها با `$this->success()` / `$this->paginated()` / `$this->error()` +- Controller نازک: منطق در Service، کوئری در Repository؛ وابستگی‌ها با constructor injection (نه `new`) +- خطاها با `AppException(ErrorCodes::ERR_XXX)` و پیام فارسی در `src/Shared/Constant/ErrorCodes.php` - Frontend paginated: items از `data?.data`، total از `data?.meta?.totalRecords` - Frontend single: از `data?.data` (ممکن است double-nested باشد) - Category API: triple-nested → `data?.data?.data ?? []` - تاریخ‌ها: Unix timestamp صحیح؛ نمایش با `formatDate()` شمسی - اگر Entity تغییر کرد: migration لازم است - مستندات: بعد از هر تغییر API، فایل مربوطه در `docs/api/` باید به‌روز شود +- اگر endpoint توسط سایت عمومی (`nobat724_front`) هم مصرف می‌شود، در پرامپت ذکر کن — تغییر قرارداد در build کلاینت خطا نمی‌دهد ### مرحله ۴ — خروجی نهایی @@ -135,7 +157,10 @@ description: تولید فایل پرامپت .md برای یک قابلیت ی - متد accept() فقط status تغییر می‌دهد، clinic->getDoctors()->add() صدا نمی‌زند - Clinic entity دارای ManyToMany $doctors است +→ بازگویی: مشکل — accept() رابطه clinic_doctors را نمی‌سازد؛ رفتار درست — پزشک بعد از accept در لیست پزشکان کلینیک باشد؛ محدوده — ClinicInvitationService.php + → فایل .claude/prompt/fix-invitation-accept.md ساخته شد + (شامل معیار پذیرش: ✅ accept → پزشک در لیست / ❌ دعوت منقضی → خطا / ⚠️ accept تکراری → بدون رکورد تکراری) توضیح: رفع باگ پذیرش دعوت — پزشک باید پس از accept به clinic_doctors اضافه شود. فایل پرامپت: .claude/prompt/fix-invitation-accept.md diff --git a/.claude/skills/run-prompt/SKILL.md b/.claude/skills/run-prompt/SKILL.md index 9720afef..6d6f1b45 100644 --- a/.claude/skills/run-prompt/SKILL.md +++ b/.claude/skills/run-prompt/SKILL.md @@ -3,6 +3,8 @@ name: run-prompt description: اجرای یک فایل پرامپت .md به صورت گام‌به‌گام و ایمن. هر قابلیت را جداگانه پیاده‌سازی، تست و مستند می‌کند. استفاده کن وقتی کاربر می‌گوید "اجرای پرامپت"، "پرامپت را اجرا کن"، "run prompt"، یا مسیر یک فایل .md می‌دهد. --- +> **قبل از شروع، فایل `.claude/guidelines.md` را بخوان و همهٔ بخش‌های آن را اعمال کن** (اگر روت جلسه workspace است: `clinicpro/.claude/guidelines.md`). آن فایل «چگونه کار کردن» (درک مسئله، todo، تعریف «تمام شد»، مستندات، SOLID، رفتار تحلیل‌گر، چک‌لیست پایانی §۷) را تعیین می‌کند؛ این skill فقط قواعد stack، دستورهای تست و مسیرها را دارد. در تناقض با متن پرامپت، guidelines برنده است — مگر کاربر صریحاً خلافش را بگوید. + ## نحوه دریافت ورودی اگر کاربر مسیر فایل داد → آن را بخوان. @@ -12,18 +14,20 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب ## قبل از شروع — تحلیل پرامپت و ساخت Todo -۱. فایل پرامپت را کامل بخوان -۲. مستندات موجود را بررسی کن: `docs/api/` -۳. کد مرتبط در `src/` و `assets/admin/` را مرور کن -۴. لیست قابلیت‌ها را از پرامپت استخراج کن -۵. **با `TodoWrite` یک todo کامل بساز** — یک آیتم به ازای هر قابلیت -۶. به کاربر نمایش بده: +۱. فایل پرامپت را **کامل** بخوان +۲. مستندات موجود را بررسی کن: `docs/api/` +۳. کد واقعیِ مرتبط در `src/` و `assets/admin/` را بخوان — هیچ فرضی از حافظه +۴. **نقد پرامپت (guidelines §۶):** اگر راه‌حل پرامپت اشتباه، ناقص یا پرریسک است، همین‌جا صریح و با دلیل بگو و منتظر تعیین تکلیف بمان. اجرای بی‌چون‌وچرای پرامپت غلط، خطای agent است. +۵. لیست قابلیت‌ها را استخراج کن؛ اگر پرامپت «معیار پذیرش» ندارد، خودت برای هر قابلیت بساز (موفق + خطا + مرزی) و به کاربر نشان بده +۶. **با `TodoWrite` todo کامل بساز** — یک آیتم قابل‌تست به ازای هر قابلیت +۷. به کاربر نمایش بده — تحلیل با **بازگویی مسئله و معیار پذیرش** تمام می‌شود، نه فقط لیست قابلیت‌ها: ``` -📋 قابلیت‌های شناسایی‌شده: - ۱. [نام قابلیت اول] - ۲. [نام قابلیت دوم] - ... +🧭 بازگویی مسئله: مشکل X است؛ رفتار درست Y؛ محدودهٔ تغییر فایل‌های Z. +📋 قابلیت‌ها + معیار پذیرش: + ۱. [نام] — ✅ [موفق] / ❌ [خطا] / ⚠️ [مرزی] + ۲. ... +⚠️ ایرادهای پرامپت (اگر هست): ... 🚀 شروع با قابلیت ۱ — آیا ادامه دهم؟ ``` @@ -32,48 +36,40 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب ## قوانین اجرا (اجباری — هیچ استثنایی ندارد) -### ۱. Todo — ستون فقرات اجرا +### ۱. Todo — ستون فقرات اجرا (guidelines §۲) **در ابتدای هر اجرا** یک todo کامل با `TodoWrite` بساز: - یک آیتم به ازای هر قابلیت با وضعیت `pending` +- هر آیتم **قابل تست** با خروجی مشخص («endpoint X با response Y کار می‌کند»)، نه فعل مبهم («بررسی سیستم نوبت») - آیتم‌های زیر-مجموعه اضافه کن اگر قابلیت چند بخش مستقل دارد **در طول اجرا:** -- هر قابلیت را که شروع می‌کنی → وضعیتش را `in_progress` کن -- هر قابلیت را که تست و تأیید شد → فوری `completed` کن -- هرگز دو آیتم را همزمان `in_progress` نگذار +- هر قابلیت را که شروع می‌کنی → `in_progress`؛ در هر لحظه فقط یک آیتم `in_progress` +- آیتم فقط وقتی `completed` می‌شود که هر سه انجام شده باشد: **پیاده‌سازی + تست سبز + مستندات به‌روز** - اگر خطا داری که قابلیت را block کرده → یک آیتم `in_progress` باقی بماند تا رفع شود - -**نمونه todo اولیه:** -``` -[ ] قابلیت ۱: Stats Bar backend endpoint -[ ] قابلیت ۲: Stats Bar frontend component -[ ] قابلیت ۳: PersianCalendar popup -[ ] قابلیت ۴: AppointmentStatusDropdown -[ ] قابلیت ۵: بازطراحی AppointmentsPage -``` +- کشف کار جدید وسط اجرا (باگ جانبی، وابستگی پنهان) → آیتم جدید به todo + اطلاع به کاربر؛ انجام بی‌صدا ممنوع ### ۲. یک قابلیت در هر مرحله - هرگز دو قابلیت را همزمان پیاده‌سازی نکن -- هرگز بدون تأیید موفقیت مرحله قبل به مرحله بعد نرو +- هرگز بدون تأیید موفقیت مرحله قبل به مرحله بعد نرو — خطا یعنی توقف کامل ### ۳. ترتیب اجرای هر قابلیت ``` -① تحلیل ② طراحی ③ پیاده‌سازی ④ تست ⑤ رفع خطا ⑥ مستندسازی ⑦ Todo + گزارش +① تحلیل ② طراحی ③ پیاده‌سازی ④ تست ⑤ رفع خطا ⑥ مستندسازی ⑦ چک‌لیست + Todo + گزارش ``` ### ۴. سازگاری با پروژه - همه تغییرات باید با Symfony 7 + React 19 سازگار باشند - از الگوهای موجود پروژه پیروی کن (BaseController، TanStack Query، Zod، ...) - اگر Entity تغییر کرد: `doctrine:migrations:diff` و `doctrine:migrations:migrate` اجرا کن -- اگر API تغییر کرد: همه بخش‌های وابسته (frontend types، api calls، ...) را اصلاح کن +- اگر قرارداد API تغییر کرد: همه کلاینت‌های وابسته را اصلاح کن — admin frontend (types، api calls) **و** اگر endpoint عمومی است، مصرف آن در `nobat724_front/services/` را دستی دنبال کن؛ این تغییرات در build خطا نمی‌دهند و در رانتایم می‌شکنند. نتیجه بررسی را گزارش بده. -### ۵. اصول کدنویسی -- SOLID و Clean Code -- هیچ کامنت غیرضروری اضافه نکن -- نام‌گذاری معنادار -- error handling فقط در boundaries واقعی (نه defensive programming اضافی) +### ۵. اصول کدنویسی (تفصیل در guidelines §۵) +- SOLID: Controller نازک، منطق در Service، کوئری در Repository؛ رفتار جدید با extension نه if روی نوع؛ وابستگی با constructor injection نه `new` +- سبک کد جدید = سبک فایل‌های مشابه موجود در پروژه +- هیچ کامنت بدیهی؛ نام‌گذاری معنادار؛ هیچ abstraction بدون مصرفِ الان +- error handling فقط در boundaries واقعی (Controller، فراخوانی API، I/O) --- @@ -83,9 +79,9 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب قبل از هر چیز: - فایل‌های مرتبط را بخوان -- endpoint های موجود را بررسی کن: `php bin/console debug:router | grep api` +- endpoint های موجود را بررسی کن: `php bin/console debug:router | grep api` — API جدید فقط وقتی هیچ موجودی، حتی با توسعه، کافی نباشد - Entity های مرتبط را شناسایی کن -- اگر سوال یا ابهامی هست → همین‌جا بپرس، نه وسط پیاده‌سازی +- **ابهام = توقف**: سوال را همین‌جا بپرس، نه وسط پیاده‌سازی ### مرحله ② — طراحی @@ -94,6 +90,8 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب - چه API endpoint هایی اضافه/تغییر می‌کنند - چه migration لازم است (اگر Entity تغییر کرد) +اگر بیش از یک راه‌حل جدی وجود دارد: مزایا، معایب، ریسک و حداقل یک گزینهٔ جایگزین را مقایسه کن و دلیل انتخاب را بنویس (guidelines §۶). قبل از ساختن چیز جدید: اول بگرد، بعد توسعه بده، در آخر بساز — و دلیلش را بنویس. + ### مرحله ③ — پیاده‌سازی - قابلیت را در todo روی `in_progress` بگذار @@ -103,7 +101,7 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب ### مرحله ④ — تست -بعد از هر قابلیت این چک‌لیست را اجرا کن: +Definition of Done: syntax/build سبز **و** پوشش سه سناریوی معیار پذیرش (موفق، خطا، مرزی). دستورهای زیر حداقل‌اند نه سقف — اگر قابلیت منطق دارد، همان منطق را واقعاً اجرا کن (curl به endpoint با داده و توکن واقعی، نه فقط `php -l`). اگر پرامپت «نحوه تست» داده، همان را اجرا کن. ```bash # PHP syntax @@ -121,6 +119,11 @@ ddev exec yarn dev # Route وجود دارد؟ ddev exec php bin/console debug:router | grep "new-route-name" + +# تست واقعی endpoint — سه سناریو: +# ✅ curl با توکن معتبر و داده واقعی → response مطابق معیار پذیرش +# ❌ بدون توکن / بدون permission / ورودی نامعتبر → status و error code درست +# ⚠️ حالت مرزی معیار پذیرش ``` اگر frontend تغییر کرد، TypeScript errors را بررسی کن: @@ -130,13 +133,13 @@ ddev exec npx tsc --noEmit --project tsconfig.json 2>&1 | head -30 ### مرحله ⑤ — رفع خطا -- اگر خطا بود → **همین‌جا** رفع کن، به مرحله بعد نرو +- اگر خطا بود → **همین‌جا** رفع کن، به مرحله بعد نرو؛ هیچ قابلیتی روی خرابهٔ قابلیت قبلی ساخته نمی‌شود - اگر خطا در فایل دیگری بود → آن را هم رفع کن - بعد از رفع خطا → دوباره تست را اجرا کن ### مرحله ⑥ — مستندسازی -بعد از موفقیت تست، مستندات را به‌روزرسانی کن: +سند در **همین جلسه** به‌روز می‌شود — «بعداً» یعنی هرگز. اگر سند موجود با رفتار فعلی فرق دارد، اول سند را اصلاح کن، بعد قابلیت جدید را اضافه کن. | تغییر | فایل مستندات | |-------|-------------| @@ -157,36 +160,37 @@ ddev exec npx tsc --noEmit --project tsconfig.json 2>&1 | head -30 الزامات مستندسازی: 1. endpoint جدید با method، path، permission 2. Request body با تمام فیلدها و نوع داده -3. Response format با مثال واقعی JSON +3. Response با **JSON واقعی از اجرای واقعی** (خروجی curl مرحله تست، نه دست‌ساز) 4. تمام status codes و error codes 5. اگر پارامتر query داشت → همه را مستند کن -### مرحله ⑦ — Todo + گزارش +### مرحله ⑦ — چک‌لیست + Todo + گزارش -بعد از موفقیت تست و مستندسازی: - -۱. **آیتم todo را `completed` کن** با `TodoWrite` -۲. گزارش کوتاه نمایش بده: +۱. **چک‌لیست پایان قابلیت — guidelines §۷** را کامل مرور کن؛ فقط اگر همهٔ آیتم‌ها تیک خورد، ادامه بده +۲. **آیتم todo را `completed` کن** با `TodoWrite` +۳. گزارش کوتاه نمایش بده: ``` ✅ قابلیت [شماره]: [نام] — تکمیل شد +معیار پذیرش: ✅ موفق / ❌ خطا / ⚠️ مرزی — هر سه تست شد (نتیجه واقعی، نه ادعا) فایل‌های تغییر یافته: • src/... • assets/admin/... • docs/api/... +مستندات: docs/api/... به‌روز شد | نیاز نداشت (دلیل) 📊 پیشرفت کلی: ✅ قابلیت ۱: [نام] — تکمیل - ✅ قابلیت ۲: [نام] — تکمیل - ⏳ قابلیت ۳: [نام] — در صف + ⏳ قابلیت ۲: [نام] — در صف ... - ───────────────────────────────── ▶ قابلیت بعدی: [شماره] — [نام] آیا ادامه دهم؟ ``` +در گزارش، بین **واقعیت** (خروجی تست واقعی)، **فرضیه** و **حدس** تفاوت بگذار و برچسبش را مشخص کن؛ اگر چیزی تست نشده، همان را بگو — قطعی جا نزن. + --- ## قوانین خاص این پروژه @@ -194,6 +198,7 @@ ddev exec npx tsc --noEmit --project tsconfig.json 2>&1 | head -30 ### Backend - همه controller ها از `BaseController` ارث می‌برند - پاسخ‌ها: `$this->success($data)` | `$this->paginated(...)` | `$this->error(...)` +- خطاها با `AppException(ErrorCodes::ERR_XXX)`؛ کدها و پیام فارسی در `src/Shared/Constant/ErrorCodes.php` - لیست‌های admin از DQL array hydration (`.getArrayResult()`) استفاده کنند - تاریخ‌ها Unix timestamp صحیح (نه DateTime object) - بعد از هر تغییر Entity: حتماً migration بساز و اجرا کن @@ -219,16 +224,16 @@ ddev exec npx tsc --noEmit --project tsconfig.json 2>&1 | head -30 ``` کاربر: /run-prompt .claude/prompt/appointments-redesign.md -→ فایل را می‌خوانم... -→ تحلیل می‌کنم... +→ guidelines.md خوانده شد +→ فایل پرامپت را می‌خوانم... +→ کد مرتبط را می‌خوانم و پرامپت را نقد می‌کنم... -📋 قابلیت‌های شناسایی‌شده: - ۱. Stats Bar — آمار امروز (backend + frontend) - ۲. تقویم شمسی Popup (PersianCalendar component) - ۳. بازطراحی Toolbar با date navigator - ۴. نمای جدولی با inline status change - ۵. نمای زمانبندی (Schedule View) - ۶. ثبت نوبت از slot خالی +🧭 بازگویی مسئله: صفحه نوبت‌ها آمار روز و تغییر وضعیت inline ندارد؛ رفتار درست، toolbar با آمار و تقویم شمسی است؛ محدوده AppointmentsPage + یک endpoint آمار. +📋 قابلیت‌ها + معیار پذیرش: + ۱. Stats Bar (backend + frontend) — ✅ آمار امروز درست / ❌ بدون توکن 401 / ⚠️ روز بدون نوبت → صفر + ۲. تقویم شمسی Popup — ✅/❌/⚠️ ... + ۳. بازطراحی Toolbar با date navigator — ... + ۴. نمای جدولی با inline status change — ... 🚀 شروع با قابلیت ۱ (Stats Bar) — آیا ادامه دهم؟ ```