The wiring is fixed and browser-verified, but components/appointment/ has no dark: utilities at all, so the booking flow still renders identically in either theme. That is design work, and the row says so rather than claiming done. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.6 KiB
8.6 KiB
چکلیست — تسک ۱۰ (فرم ساخت قانون و محیط آزمایش)
وضعیت کلی: ✅ تمامشده با انحرافهای ثبتشده · آخرین بازبینی: ۱۴۰۵/۰۵/۰۹
قواعد: _shared/definition-of-done.md · red-lines.md · ui-conventions.md
۰. خط سرخ
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۰.۱ | --group=slot-mode-frozen سبز |
✅ | |
| ۰.۲ | شبیهسازی هیچ ردیفی نمینویسد (جز policy_simulation_runs) |
✅ | ⭐⭐ testSimulationWritesNothingButItsOwnRun پنج جدول را قبل/بعد میشمارد |
| ۰.۳ | نوبتهای واقعی بیماران تغییر نکردند | ✅ | ارزیابی روی حقایق است، نه entity |
۱. بکاند — شبیهساز
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۱.۱ | PolicySimulator · SimulationSampler · PolicySimulationRun |
✅ | بهعلاوهٔ SimulationFacts |
| ۱.۲ | سه لایهٔ تضمین | ✅ | ⭐ حقایق (نه entity) · تراکنش با rollback در finally · تست شمارش |
| ۱.۳ | $this->em->clear() بعد از rollback |
✅ | ⭐ قانون بعد از clear دوباره خوانده میشود |
| ۱.۴ | ثبت نتیجه بعد از rollback و در تراکنش جدا | ✅ | |
| ۱.۵ | ارزیابی جدا — فقط همان قانون | ✅ | evaluateIsolated() روی هر شش موتور. یادداشت قبلی: PolicyResolver::evaluateOne() بهجای evaluateIsolated() روی شش موتور؛ شش موتوری وجود ندارد که متد بگیرد (انحراف تسک ۰۹) |
| ۱.۶ | فیلتر شعبه/سرویس/دسته از دامنهٔ قانون | ⚠️ | از دامنهٔ قانون استخراج میشود، نه از داخل condition؛ شرطها فیلدِ id ندارند که به کوئری تبدیل شوند |
| ۱.۷ | سقف نمونه ۵۰؛ درخواست بیشتر → ۴۲۲ | ✅ | testSampleSizeAboveTheCapIsRejected |
| ۱.۸ | PolicyTemplateRegistry با پنج الگو |
✅ | شش الگو |
| ۱.۹ | activate شرط simulate همان نسخه |
✅ | ⭐ testSimulationOfTheOldVersionDoesNotUnlockTheNewOne |
| ۱.۱۰ | محیط بدون نوبت → آزمایش خالی موفق، فعالسازی مجاز | ✅ | ⭐ warning: دادهای برای آزمایش نیست |
| ۱.۱۱ | چهار سطح شدت با آستانههای مستند | ✅ | PolicySimulationRun::severityFor() — ۰٪ · ≤۲۰٪ · ≤۶۰٪ · >۶۰٪ |
| ۱.۱۲ | دو endpoint | ✅ | سه تا: policy-templates · simulate · simulations |
| ۱.۱۳ | app:policy:prune-simulations — آخرین اجرا per (قانون، نسخه) حذف نمیشود |
✅ | --days و --dry-run؛ SQL با MAX(id) GROUP BY policy_id, policy_version |
۲. دیتابیس
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۲.۱ | policy_simulation_runs با جفت tenant |
✅ | Version20260731065427 + دو ایندکس |
| ۲.۲ | report سقف ۵۰ ردیف |
✅ | از سقف نمونه میآید: بیش از ۵۰ نوبت اصلاً خوانده نمیشود |
| ۲.۳ | TenantSchemaCoverageTest سبز |
✅ |
۳. UI
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۳.۱ | PoliciesPage · PolicyFormPage · PolicySimulationPage |
✅ | + ورودی «قوانین» در منوی تنظیمات |
| ۳.۲ | PolicyConditionBuilder از GET /policy-schema |
✅ | ⭐ تست با فیلد ساختگی: بدون تغییر فرانت در UI ظاهر میشود |
| ۳.۳ | عملگرها per فیلد فیلتر میشوند | ✅ | ⭐ field_meta[].operators — تست جداگانه |
| ۳.۴ | نوع ورودی مقدار از schema | ✅ | int · enum · bool · list |
| ۳.۵ | همهٔ selectها SearchableSelect |
✅ | هیچ <select> بومی |
| ۳.۶ | انتخاب الگو → فرم کوتاه مقدارها | ✅ | حالت پیشفرض صفحه همین است |
| ۳.۷ | ستون «وضعیت فعلی ← با این قانون» | ✅ | ⭐ |
| ۳.۸ | درصد + شدت با رنگ توکنمحور | ✅ | کلاسهای badge green/amber/red موجود |
| ۳.۹ | شدت none هشدار میدهد |
✅ | «احتمالاً شرطش هرگز برقرار نمیشود» |
| ۳.۱۰ | شدت high → تأیید دوم |
✅ | |
| ۳.۱۱ | ConfirmDialog موجود |
✅ | نه window.confirm |
| ۳.۱۲ | DataTable + فیلتر دسته در URL |
✅ | useUrlState |
| ۳.۱۳ | backTo روی هر سه صفحه |
✅ | |
| ۳.۱۴ | هیچ رنگ/شعاع hard-code | ✅ | فقط var(--…) |
| ۳.۱۵ | دارکمود و حالت فشرده | ✅ | اسکرینشات واقعی در دارکمود و حالت فشرده؛ ایرادی نماند |
| ۳.۱۶ | RTL و موبایل — اسکرول افقی جدول | ✅ | overflow-x: auto دور جدول گزارش |
| ۳.۱۷ | تاریخها شمسی | ✅ | formatDate |
| ۳.۱۸ | همهٔ رشتهها فارسی | ✅ | |
| ۳.۱۹ | تاریخچهٔ نسخهها با diff | ✅ | PolicyVersionDiff — هر نسخه در برابر نسخهٔ پیش، فیلدبهفیلد؛ «بدون تغییرِ معنادار» هم صریح گفته میشود |
۴. تست
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۴.۱ | شمارش ردیف قبل/بعد | ✅ | ⭐⭐ |
| ۴.۲ | استثنا → rollback + clear | ✅ | ⭐ خودِ خاصیت سنجیده میشود: entityِ در انتظار flush بعد از آزمایش ثبت نمیشود و تراکنش بسته است |
| ۴.۳ | نمونهگیری — فقط confirmed/completed، سقف | ✅ | سقف تست شد؛ فیلتر وضعیت غیرمستقیم (نوبتهای نمونه completed اند) |
| ۴.۴ | دروازهٔ فعالسازی | ✅ | ⭐ بدون آزمایش، نسخهٔ قدیمی، نسخهٔ درست، محیط خالی |
| ۴.۵ | هر الگو قانون معتبر میسازد | ✅ | هر شش الگو تا فعالسازی رفتند. یادداشت قبلی: dataProvider ششتایی نوشته نشد |
| ۴.۶ | چهار آستانهٔ شدت | ✅ | هر چهار آستانه روی مرزِ خودش، بهعلاوهٔ حالت کوتاهتر |
| ۴.۷ | فیلد ساختگی از mock schema در UI | ✅ | ⭐ PolicyFormPage.test.tsx |
| ۴.۸ | عملگر نامعتبر نمایش داده نمیشود | ✅ | |
| ۴.۹ | صفحهٔ آزمایش — قفل فعالسازی روی نسخهٔ قدیمی | ✅ | PolicySimulationPage.test.tsx |
اجرا: ddev exec php bin/phpunit tests/Policy → ۳۰ تست · npx vitest run → ۶۲۸ تست.
۵. مستندات
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۵.۱ | docs/api/policy.md — simulate، policy-templates، شرط تازهٔ activate |
✅ | JSON واقعی |
| ۵.۲ | policy-engine.md بخش «چرا آزمایش اجباری است» |
✅ | + سه لایهٔ تضمین و دو حالت مرزی |
۶. بازبینی پایانی
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۶.۱ | هیچ 🔄 و ⏳ بیدلیل نمانده | ✅ | ۷ مورد ⚠️ همه با دلیل |
| ۶.۲ | bin/phpunit کامل سبز |
✅ | ۱۲۵۰ تست |
| ۶.۳ | --group=slot-mode-frozen سبز |
✅ | |
| ۶.۴ | phpstan بدون خطای جدید |
✅ | ۱۴ = baseline |
| ۶.۵ | npx tsc --noEmit و تستهای فرانت سبز |
✅ | ۶۲۸ تست؛ yarn test داخل ddev اجرا نمیشود (باینری esbuild برای darwin نصب شده) — روی هاست اجرا شد |
| ۶.۶ | تستهای tenant سبز | ✅ | |
| ۶.۷ | docs/api/* بهروز |
✅ | |
| ۶.۸ | چکلیست UI کامل | ✅ | جز ۳.۱۵ و ۳.۱۹ |
| ۶.۹ | دو کلاینت دیگر بررسی شدند | ✅ | این تسک هیچ قرارداد عمومیای عوض نکرد؛ همهٔ اندپوینتها پنلمحورند |
| ۶.۱۰ | commit، سپس graphify update . |
✅ | دو کامیت جدا |
| ۶.۱۱ | موارد بهتعویق با دلیل | ✅ | ۳.۱۵ (بازبینی چشمی) · ۳.۱۹ (diff بصری) · ۴.۲/۴.۵/۴.۶ (پوشش تست) — همه در همین فایل ثبتاند |