بازگشت به کتابخانهکتابخانه6.1چرخهٔ Red–Green–Refactor و قرارداد همکاری انسان و Agent
مهندسی نرم‌افزار ایجنت‌محورAGENTIC SOFTWARE ENGINEERING — از Grilling و Context Engineering تا TDD، Ralph، Subagent، امنیت و تحویل قابل‌اعتماد
v1.0.0
01واقعیت مهندسی ایجنت‌محور
02Grilling و زبان مشترک
03Context Engineering
04Spec-Driven Development و برنامهٔ اجرایی
05Vertical Slices و تحویل تدریجی
06TDD با ایجنت‌ها
07گردش‌کار روزانه، Debug و UI Prototyping
08ساخت هارنس — Rules، Skills، Hooks و MCP
09Ralph و اجرای طولانی‌مدت
10Subagent، Worktree و ارکستراسیون موازی
11Verification، Security و مقیاس تیمی
12پروژهٔ نهایی سناریومحور
LESSON 6.1فصل ۶ — TDD با ایجنت‌ها

چرخهٔ Red–Green–Refactor و قرارداد همکاری انسان و Agent

  • ~۴۸ دقیقه
  • ۵ پرسش
  • متن را انتخاب کن تا هایلایت شود

در TDD، تست فقط یک فایل کمکی نیست؛ قرارداد مشاهده‌پذیر رفتار است. ایجنت می‌تواند نوشتن کد و اجرای فرمان را سریع کند، اما انسان باید رفتار مجاز، Oracle و مرز اختیار را تأیید کند. این درس چرخهٔ Red–Green–Refactor را با یک policy مستقل برای reschedule در `booking-platform` اجرا می‌کند.

## اهداف یادگیری

پس از درس می‌توانی چرخه را با یک رفتار کوچک اجرا کنی، Red را پیش از پیاده‌سازی ببینی، Green را با کمترین کد بسازی، Refactor را زیر تست سبز انجام دهی و برای ایجنت Task Contract شامل Scope، ممنوعیت، فرمان و Evidence بنویسی.

## جایگاه در چرخهٔ سرتاسری

فصل ۵ رفتار reschedule را به Sliceهای کوچک رساند. اکنون در مرحلهٔ `Test` هستیم و پیش از `Implement`، مثال پذیرفته‌شده را به تست executable تبدیل می‌کنیم. قرارداد فصل ۵ حفظ می‌شود: appointment باید `CONFIRMED` باشد، deadline دقیقاً ۲۴ ساعت است، زمان در timezone کلینیک تفسیر و در UTC ذخیره می‌شود، و درخواست بسته باید `409 RESCHEDULE_WINDOW_CLOSED` با body قراردادی بدهد، بدون mutation یا audit تازه.

چرخهٔ Red–Green–Refactor برای reschedule

*شکل: چرخهٔ TDD از رفتار reschedule تأییدشده تا Red، Green کمینه، Refactor و Verification کامل؛ اگر شاهد کافی نیست، چرخه به تست برمی‌گردد.*

## مفهوم عمیق

**Red** یعنی تستی که رفتار جدید را مطالبه می‌کند و به دلیل نبود آن رفتار شکست می‌خورد. **Green** یعنی کمترین پیاده‌سازی که همان Oracle را سبز می‌کند. **Refactor** تغییر ساختار بدون تغییر رفتار مشاهده‌شده است. این سه واژه دستور «همیشه اول تست» نیستند؛ قرارداد بازخورد کوتاه و قابل‌تکرارند.

برای ایجنت، انسان باید پنج چیز را قبل از اجرا مشخص کند: رفتار، فایل‌های مجاز، چیزهای ممنوع، فرمان‌های Verification و نشانهٔ پایان. ایجنت می‌تواند factهای مخزن را بخواند و patch پیشنهاد کند، اما نباید policy reschedule را از خود اختراع کند. یک چرخه فقط یک رفتار باریک دارد؛ مثلاً «برای appointment تأییدشده، در پنجرهٔ بسته reschedule رد شود»، نه هم‌زمان reminder، refund و calendar sync.

مثال بد

«قانون reschedule را پیاده کن و همهٔ تست‌ها را سبز کن.»

این درخواست چند policy حل‌نشده دارد: appointment باید confirmed باشد، مرز دقیق زمان، timezone، status/body پاسخ و اثر audit. معیار پایان نیز «سبز بودن» است و ایجنت می‌تواند assertion را حذف یا تست را mock کند.

مثال اصلاح‌شده: Vitest

import { describe, expect, it } from "vitest";
import { rescheduleDecision } from "./reschedule-policy";

describe("reschedule window", () => {
  it("rejects reschedule at exactly 24 hours before start", () => {
    const result = rescheduleDecision({
      now: new Date("2026-09-10T10:00:00Z"),
      startsAt: new Date("2026-09-11T10:00:00Z"),
      status: "CONFIRMED",
    });
    expect(result).toEqual({
      allowed: false,
      status: 409,
      body: { code: "RESCHEDULE_WINDOW_CLOSED" },
    });
  });
});

در این مثال «دقیقاً ۲۴ ساعت»، `CONFIRMED` بودن appointment و همان status/body فصل ۵ صریح است. این policy مستقلِ reschedule است و cancellation تازه‌ای به Canon اضافه نمی‌کند. تست policy pure است و به‌تنهایی نبود mutation و audit را ثابت نمی‌کند؛ در Slice integration باید آن Oracleهای persistent نیز اضافه شوند.

## قرارداد همکاری انسان و Agent

Goal: تصمیم reschedule برای appointment CONFIRMED را در مرز 24 ساعت مشخص کن.
Context: packages/contracts و apps/api/src/modules/appointments را بخوان؛
         contractهای فصل ۵ و timezone کلینیک authority هستند.
Allowed: فقط فایل policy و تست همان policy.
Forbidden: تغییر deadline، حذف assertion، mock کردن clock در تست integration،
           migration، شبکه و ارسال notification.
Input: مثال acceptance A-04 برای `RESCHEDULE_WINDOW_CLOSED`.
Done: اول خروجی Red، سپس patch کمینه، خروجی Green و Diff خلاصه‌شده.
Recovery: اگر status یا timezone نامعلوم بود DECIDE بده و کد نزن.

ایجنت باید هر مرحله را گزارش کند. انسان در Red می‌پرسد «چرا شکست خورد؟»، در Green «آیا بیش از حد پیاده‌سازی شده؟» و در Refactor «آیا Oracle یا contract تغییر نکرده است؟». این تقسیم کار، همکاری را به کنترل کیفیت قابل‌ممیزی تبدیل می‌کند.

## سناریوی booking-platform

در Slice S2 از فصل ۵، eligibility پیش از protected write رخ می‌دهد. policy مستقل reschedule در این درس فقط مرز زمانی را به چرخه وصل می‌کند و cancellation یا reminder تازه‌ای به Canon اضافه نمی‌کند. اگر `now` و `startsAt` در دو timezone متفاوت باشند، ورودی باید ابتدا به Instant معتبر تبدیل شود. policy نباید `tenantId` یا `actorId` را از body بپذیرد؛ آن‌ها از credential می‌آیند. تصمیم unresolved دربارهٔ مرز inclusive/exclusive باید owner و deadline داشته باشد، نه حدس ایجنت.

## آزمایشگاه گام‌به‌گام

**ورودی:** acceptance example A-04، appointment `CONFIRMED`، baseline reschedule policy، Node و Vitest محلی.

۱. فایل موجود policy و فرمان تست را کشف کن:

pnpm exec vitest run packages/contracts/src/reschedule-policy.test.ts

**خروجی مورد انتظار:** baseline سبز یا فهرست شکست‌های موجود که قبل از تغییر ثبت شده است.

۲. تست reschedule در مرز ۲۴ ساعت را بدون implementation اضافه کن. اجرا باید شکست معنادار بدهد:

FAIL expected allowed:false, received allowed:true

این Red معتبر است چون assertion مربوط به رفتار جدید است، نه syntax یا import شکسته.

۳. کمترین implementation را اضافه کن و همان تست را اجرا کن. **خروجی:** `1 passed`.

۴. Refactor کوچک انجام بده؛ مثلاً نام `remainingMs` را به `remainingMilliseconds` تغییر بده و تست را دوباره اجرا کن.

**Recovery:** اگر baseline پیشاپیش fail است، به Red ساختگی دست نزن؛ commit یا log baseline را نگه دار، dependency را repair کن و چرخه را از یک محیط پاک تکرار کن. اگر ایجنت تست را تغییر داد، diff تست را revert و contract را دوباره تأیید کن.

## خطاهای رایج و نشانه‌ها

  • نوشتن implementation پیش از test؛ اولین اجرا هرگز Red واقعی ندارد.
  • یک چرخهٔ بزرگ برای policy، repository و notification؛ علت شکست نامعلوم می‌شود.
  • استفاده از `Date.now()` مستقیم؛ تست مرزی ناپایدار است.
  • سبز کردن با تغییر expected؛ diff تست از diff production بزرگ‌تر یا بی‌دلیل تغییر کرده است.
  • مخلوط کردن unit policy با database؛ شکست شبکه یا fixture به Red نسبت داده می‌شود.

## چک‌لیست Verification

  • [ ] acceptance example و مرز ۲۴ ساعت صریح است.
  • [ ] Red قبل از implementation با علت رفتاری ثبت شده است.
  • [ ] Green کمینه است و contract فصل ۵ را تغییر نمی‌دهد.
  • [ ] Refactor فقط ساختار را تغییر داده و تست‌ها دوباره اجرا شده‌اند.
  • [ ] فرمان، نسخهٔ محیط و خروجی در Evidence ثبت شده‌اند.

## تمرین مستقل

برای «reschedule در ۲۴ ساعت و یک دقیقه مانده مجاز است» تست و قرارداد Agent بنویس.

**Rubric پاسخ:** باید Instantهای ثابت، status `CONFIRMED`، assertion روی `allowed:true` و body/status موفق فصل ۵، یک فرمان قابل‌تکرار، ممنوعیت تغییر deadline و Recovery برای timezone نامعلوم را داشته باشد.

## مرز ادعا و مقایسهٔ ابزار

Vitest در این درس runner و assertion فراهم می‌کند؛ سبز شدن آن دربارهٔ صحت timezone، امنیت endpoint یا نبود race ادعا نمی‌سازد. Cursor، Claude Code، Copilot و Codex ممکن است فرمان و سطح اختیار متفاوتی داشته باشند، اما قرارداد همکاری مستقل از نام ابزار است: Context محدود، مسیرهای مجاز، منع credential واقعی و خروجی قابل‌بررسی. هرچه ابزار اجرای خودکار بیشتری دارد، allowlist و توقف انسانی مهم‌تر می‌شود. قابلیت محصول را با روش TDD یکی ندان؛ مستند رسمی ابزار capability را توضیح می‌دهد، نه کیفیت این مخزن را تضمین کند.

در Evidence، تاریخ، نسخهٔ runner، commit و environment را بنویس. نتیجهٔ موفق روی laptop یا database mock را به staging تعمیم نده. اگر clock، timezone database یا locale فرق دارد، آن را limitation ثبت کن. این سطح‌بندی ادعا مانع می‌شود «تست داریم» به‌اشتباه «رفتار production ثابت است» ترجمه شود.

## جمع‌بندی

TDD با ایجنت یعنی بازخورد را سریع‌تر و مرز اختیار را روشن‌تر کنیم، نه اینکه Oracle را واگذار کنیم. Red مشاهده‌شده، Green کمینه و Refactor زیر تست سبز سه شاهد جدا هستند.

## منابع مستقیم

  • [Martin Fowler — Test-Driven Development](https://martinfowler.com/bliki/TestDrivenDevelopment.html) — توضیح چرخه و محدودیت تعمیم آن به تیم‌ها.
  • [Kent Beck — Test-Driven Development: By Example](https://www.oreilly.com/library/view/test-driven-development/0321146530/) — منبع اولیهٔ روش.
  • [Vitest — Guide](https://vitest.dev/guide/) — مستند رسمی فرمان و assertion؛ نسخهٔ پروژه باید ثبت شود.
  • [Anthropic — Claude Code best practices](https://www.anthropic.com/engineering/claude-code-best-practices) — گزارش میدانی فروشنده، نه تضمین کیفیت Agent.

به زبان ساده

در TDD، Red شکست رفتاری پیش از implementation است، Green کمینه‌ترین کد لازم و Refactor تغییر ساختار زیر همان Oracle است. Agent می‌تواند اجرای چرخه را سریع کند، اما deadline و policy را تعیین نمی‌کند.

مثال واقعی

تست مستقل دوره برای reschedule در دقیقاً ۲۴ ساعت مانده، `409 RESCHEDULE_WINDOW_CLOSED` و عدم تغییر state را می‌خواهد؛ این مثال آموزشی به implementation خاصی وابسته نیست.

دانش‌سنجی

آزمون درس

۵ Q
01
Red معتبر در TDD چیست؟
02
کدام مورد باید در قرارداد Agent بیاید؟
03
در پنجرهٔ بستهٔ reschedule چه contractی حفظ می‌شود؟
04
چرا policy unit به‌تنهایی کافی نیست؟
05
Recovery مناسب برای policy نامعلوم چیست؟

سناریوی تشریحی

برای پنجرهٔ بستهٔ reschedule در appointment `CONFIRMED`، قرارداد Agent و چرخهٔ Red–Green–Refactor را ارائه کن.