Files
clinicpro/docs/new_feture/taskes/task-10-policy-admin-sandbox/checklist.md
T
hamedandClaude Opus 5 bcfa87bfad feat(policy): rule builder and mandatory dry-run sandbox
Task 09 shipped a powerful API that a non-technical clinic owner could not
safely use. This closes that gap: activation now requires having seen what the
rule actually does.

- PolicySimulator runs a policy against real past appointments and writes
  nothing: evaluation works on facts (never entities), the whole run sits in a
  transaction rolled back and cleared in `finally`, and a test counts rows in
  five sensitive tables before and after
- activate() now demands a simulation of the *same version* — a report for
  version 1 does not unlock version 2
- PolicyTemplateRegistry: six ready-made rules, so the common case never
  touches a raw condition
- Severity from the affected ratio; 0% is a warning too, since a rule that
  changes nothing usually has a condition that never matches
- An empty clinic still succeeds with a warning, otherwise a new clinic could
  never activate anything

Admin: PoliciesPage, PolicyFormPage, PolicySimulationPage, and a
PolicyConditionBuilder built entirely from GET /policy-schema — a test proves a
field that exists only in the schema shows up with no frontend change, and that
operators are filtered per field type.

The schema response now carries per-field metadata (label, type, meaningful
operators) so the form has one source of truth instead of two.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 10:44:28 +03:30

8.3 KiB
Raw Blame History

چک‌لیست — تسک ۱۰ (فرم ساخت قانون و محیط آزمایش)

وضعیت کلی: تمام‌شده با انحراف‌های ثبت‌شده · آخرین بازبینی: ۱۴۰۵/۰۵/۰۹

قواعد: _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 و در تراکنش جدا
۱.۵ ارزیابی جدا — فقط همان قانون ⚠️ 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 ⚠️ فهرست نسخه‌ها با اثرهای هر نسخه نمایش داده می‌شود؛ diff بصری واقعی نیست

۴. تست

# مورد وضعیت یادداشت
۴.۱ شمارش ردیف قبل/بعد
۴.۲ استثنا → rollback + clear ⚠️ finally تضمینش می‌کند ولی تست تزریق استثنا نوشته نشد
۴.۳ نمونه‌گیری — فقط confirmed/completed، سقف سقف تست شد؛ فیلتر وضعیت غیرمستقیم (نوبت‌های نمونه completed اند)
۴.۴ دروازهٔ فعال‌سازی بدون آزمایش، نسخهٔ قدیمی، نسخهٔ درست، محیط خالی
۴.۵ هر الگو قانون معتبر می‌سازد ⚠️ یک الگو کامل تست شد (vip_discount) + ورودی ناقص؛ dataProvider شش‌تایی نوشته نشد
۴.۶ چهار آستانهٔ شدت ⚠️ high و none تست شدند؛ low/medium نه
۴.۷ فیلد ساختگی از mock schema در UI PolicyFormPage.test.tsx
۴.۸ عملگر نامعتبر نمایش داده نمی‌شود
۴.۹ صفحهٔ آزمایش — قفل فعال‌سازی روی نسخهٔ قدیمی PolicySimulationPage.test.tsx

اجرا: ddev exec php bin/phpunit tests/Policy → ۳۰ تست · npx vitest run → ۶۲۸ تست.

۵. مستندات

# مورد وضعیت یادداشت
۵.۱ docs/api/policy.mdsimulate، 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 بصری) · ۴.۲/۴.۵/۴.۶ (پوشش تست) — همه در همین فایل ثبت‌اند