تغییر ایجنتساخته وقتی آمادهٔ تحویل است که فقط «تست سبز» نباشد: دامنهٔ تغییر قابلفهم، شواهد لایهای، بازبین تازه و مسیر rollout/rollback داشته باشد. این درس PR کوچکِ قابلیت reschedule را از diff تا production دنبال میکند.
## اهداف یادگیری
پس از درس میتوانی PR را کوچک و توضیحپذیر کنی؛ diff و تست targeted/full را بخوانی؛ static/security و runtime/browser evidence جمع کنی؛ بازبین مستقل بخواهی؛ و DoD را به rollout تدریجی و rollback قابلاجرا وصل کنی.
## جایگاه در چرخه
درسهای TDD و fan-in تست میسازند؛ این درس در `Verify → Integrate → Learn` شواهد را مستقل و مرتب میکند. Verification نردبان است، نه یک checkbox: هر پله پلهٔ قبلی را تکمیل میکند و هیچ پلهای correctness همهٔ پلههای دیگر را ثابت نمیکند.
*شکل: شواهد از diff و تست محدود به شواهد runtime، review مستقل و rollout قابلبازگشت میرسد؛ پلهٔ بالاتر جایگزین پلهٔ پایین نیست.*
## DoD بهجای «کار تمام شد»
درخواست مبهم «reschedule را پیاده کن» PR بزرگ، review سطحی و merge پرریسک میسازد. نسخهٔ اصلاحشده یک outcome دارد: بیمار مالک appointment، slot آزاد را با زمان محلی معتبر میفرستد و پاسخ UTC و version میگیرد. author در توضیح PR مینویسد چه چیزی، چرا، چه چیزی عمداً خارج است، و چگونه بازگردانده میشود:
Scope: validation + protected write + audit؛ reminder/provider خارجی خارج است.
Risk: race و timezone؛ Evidence: A-04..A-08 و browser flow reschedule.
Rollback: flag=false؛ schema و audit را حذف نمیکنیم؛ owner و expiry ثبت شده.PR خوب کوچک است: تغییرات قرارداد، service و test فقط به همان رفتار مربوطاند. PR بد همزمان refactor، تغییر dependency و UI redesign دارد؛ حتی اگر تعداد خطهایش کم باشد، علت شکست را مبهم میکند. کوچکبودن هدف کاهش بار شناختی است، نه معیار کیفیت بهتنهایی.
## پلههای شواهد
۱. **Diff review:** فایلها، permission، migration، log و secret pattern را بخوان؛ هر خط باید به Spec یا test وصل شود. ۲. **Targeted tests:** ابتدا validation، race، replay و contract مرتبط را اجرا کن تا feedback سریع باشد. ۳. **Full tests:** unit/integration/E2E و consumer compatibility را با fixture تازه اجرا کن. ۴. **Static/security:** typecheck، lint، format، dependency audit، secret scan و policy scan؛ failure ناشناخته را سبز فرض نکن. ۵. **Runtime/browser evidence:** route واقعی، console/network، accessibility، tenant isolation و log redaction را در محیط ephemeral ثبت کن. ۶. **Fresh reviewer:** نویسنده خودش شاهد کافی نیست؛ بازبین بدون اتکا به روایت author diff، DoD و artifactها را بازسازی میکند. ۷. **Rollout:** flag خاموش پیشفرض، cohort کوچک، metric و stop rule؛ rollback یعنی خاموشکردن cohort و حفظ schema و audit، نه حذف کور دادهٔ نوشتهشده.
## مثال ضعیف و اصلاحشده
بد: «Vitest سبز است، پس merge کن.» این جمله نمیگوید کدام تست، آیا تست ضعیف شده، browser چه دید، یا migration برگشتپذیر است. خوب: PR به A-08 اشاره میکند، output و commit را پیوست میکند، `git diff --check` و scan را نشان میدهد، route flag را با false/true میآزماید، و بازبین تازه rollback runbook را روی fixture بررسی میکند.
## سناریوی booking-platform
یک PR race را حل کرده اما ۹۰۰ خط refactor هم دارد. author فقط full suite را پیوست کرده و rollout را «deploy عادی» نوشته است. درخواست تغییر باید PR را به contract/race و refactor جدا تقسیم کند، evidence targeted و full را با revision ثبت کند، browser flow و tenant A/B را نشان دهد، و برای flag cohort/owner/expiry و rollback اقدام مشخص بدهد. اگر refactor برای fix ضروری است، dependency آن را صریح و review را دو مرحلهای کنید.
## آزمایشگاه گامبهگام
**ورودی:** diff فرضی reschedule، Spec، test output و runbook. ۱) scope و non-goal را در PR description بنویس. ۲) diff را برای migration، secret، route و assertion بررسی کن. ۳) targeted سپس full command را اجرا و exit code، revision و environment را ذخیره کن. ۴) static/security را اجرا؛ failure مبهم را `BLOCKED` ثبت کن. ۵) browser evidence شامل URL، status، console، network، accessibility و tenant را اضافه کن. ۶) از همتیمی تازه بخواه بدون توضیح شفاهی DoD را ارزیابی کند. ۷) cohort و stop rule را بنویس.
برای اجرای امن، این فرمانها **نمونهٔ local/ephemeral** هستند و به repository آموزشی و database یکبارمصرف محدود میشوند؛ endpoint واقعی یا credential لازم نیست:
set -euo pipefail
git diff --check
pnpm exec vitest run apps/api/src/modules/appointments/reschedule.int.test.ts \
--testNamePattern='A-04|A-08'
pnpm exec eslint apps/api/src/modules/appointments
pnpm exec prettier --check apps/api/src/modules/appointments
TEST_DATABASE_URL='file:./.tmp/booking-verify.db' \
pnpm exec playwright test apps/web/tests/reschedule.spec.ts --project=chromium**Pseudo-command محلی (اجرا نشود):** `record-evidence --commit "$SHA" --commands ./commands.txt --out ./artifacts/run-01` فقط قرارداد ثبت artifact را نشان میدهد؛ مقدارهای secret یا URL خارجی در آن قرار نمیگیرند. خروجی قابلبررسی باید exit code صفر برای checkهای موفق، نام testهای A-04/A-08، summary مرورگر، diff stat، commit SHA، محیط `ephemeral` و فهرست limitationها باشد. اگر Playwright در مخزن وجود ندارد، آن را اجرا نکن؛ `BLOCKED: browser runner unavailable` ثبت کن.
خروجی مورد انتظار یک Evidence Pack با diff stat، command/output، محدودیت، review decision و rollback trigger است. **Recovery:** اگر targeted سبز و full قرمز شد، merge نکن؛ آخرین artifact را حفظ، تست failing را isolate و علت fixture/contract را اصلاح کن. اگر runtime به endpoint واقعی رفت، اجرا را متوقف، credential را revoke و incident owner را مطلع کن.
اگر formatter یا lint فقط بهخاطر baseline شکست خورد، خروجی قبل/بعد را در artifact جدا کن و دامنهٔ اصلاح را به فایلهای PR محدود نگه دار. اگر تست browser به سرویس خارجی وابسته بود، fake provider و fixture محلی بساز؛ timeout را بالا نبر تا failure پنهان شود. اگر reviewer با DoD مخالف بود، اختلاف را به decision record برگردان و rollout را تا تصمیم مالک متوقف کن.
## خطاهای رایج
- یکیگرفتن test green با evidence کافی.
- PR بزرگ با refactor و feature همزمان.
- اجرای فقط unit test و حذف browser/consumer evidence.
- review توسط همان نویسنده یا تایید «LGTM» بدون diff.
- rollbackی که schema یا audit را پاک میکند.
- تغییر threshold برای سبزشدن benchmark.
## Verification
- [ ] PR یک outcome، scope، non-goal و author explanation دارد.
- [ ] diff، targeted/full، static/security و runtime/browser evidence لینک شدهاند.
- [ ] assertion و test oracle بدون weaken شدن بازبینی شدهاند.
- [ ] بازبین تازه مستقل از author نتیجه داده است.
- [ ] flag، cohort، owner، stop rule و rollback tested هستند.
## تمرین و Rubric
برای PR بالا تصمیم بگیر merge، reject یا request changes. پاسخ کامل باید refactor را جدا یا توجیه کند، A-08 و full suite را با output بخواهد، browser و tenant evidence را مطالبه کند، fresh review و rollback flag را مشخص کند، و نبود هر شاهد را «ناشناخته» بنویسد نه «موفق».
## جمعبندی
DoD یک زنجیرهٔ قابلبازسازی است: diff، تست نزدیک، suite کامل، static/security، runtime/browser، بازبین مستقل و rollout قابلبازگشت. evidence ادعا را محدود میکند؛ نبود evidence شکست قطعی نیست، اما مجوز ادعای موفقیت هم نیست. هر artifact باید صاحب، زمان تولید و revision داشته باشد تا بازبینی بعدی قابلتکرار بماند. این metadata امکان مقایسهٔ منصفانه، پیگیری تصمیم، تشخیص شواهد قدیمی و بازسازی مسیر پذیرش را فراهم میکند.
## منابع مستقیم
- [NIST SSDF](https://csrc.nist.gov/pubs/sp/800/218/final) — practices توسعهٔ امن؛ چکلیست محصول خاص نیست.
- [NIST GenAI Profile](https://nvlpubs.nist.gov/nistpubs/ai/nist.ai.600-1.pdf) — ریسکهای GenAI؛ تضمین رفتار مدل نیست.
- [GitHub flow](https://docs.github.com/en/get-started/using-github/github-flow) — راهنمای رسمی PR و feedback؛ workflow پیشنهادی است و جایگزین DoD، review مستقل یا rollback نیست.
به زبان ساده
Definition of Done نردبانی از Diff، تست هدفمند، suite کامل، static/security، runtime/browser، review مستقل و rollout است. هر پله دامنهٔ خودش را دارد و جای پلهٔ دیگر را نمیگیرد.
مثال واقعی
در یک PR فرضی reschedule، A-08 و Diff check کافی نیستند؛ flag off/on، evidence مرورگر، log redaction و rollback runbook هم باید به claimهای مشخص وصل شوند.