صفحه ۹ از ۴۹، درس‌ها

درس 08. استفاده از فهرست ویژگی‌ها برای محدود کردن کارهای ایجنت

متنی ۱۰ دقیقه به‌روز شده در ۱۰ آبان ۱۴۰۵

در این صفحه
  1. ایجنت‌ها نمی‌دانند «اتمام کار» یعنی چه
  2. ماشین وضعیت ویژگی
  3. مفاهیم اصلی
  4. چرا فهرست‌های ویژگی‌ها باید جزو «عناصر بنیادین» باشند
  5. چگونه این کار را انجام دهیم
  6. موردی از دنیای واقعی
  7. نکات کلیدی
  8. منابع بیشتر
  9. تمرین‌ها

Code examples: code/ Practice project: Project 04. Runtime feedback and scope control

شما از یک ایجنت (agent) می‌خواهید یک وب‌سایت تجارت الکترونیک بسازد. پس از پایان کار، به شما می‌گوید «تمام شد». به کد نگاه می‌کنید — احراز هویت کاربر کار می‌کند، اما دکمهٔ تسویه حساب در سبد خرید هیچ کاری انجام نمی‌دهد، و فرایند پرداخت اصلاً متصل نشده است. مشکل از کجا آب خورد؟ شما هرگز به آن نگفتید «تمام شد» به‌چه معناست، بنابراین از استاندارد خودش استفاده کرد: «من کدهای زیادی نوشتم و کاملاً کامل به‌نظر می‌رسد.»

فهرست ویژگی‌ها (feature list) در نگاه بسیاری از افراد صرفاً یک یادداشت است — مواردی را بنویسید تا فراموش نکنید، و سپس آن‌ها را کنار بگذارید. اما در دنیای هارنس (harness)، فهرست ویژگی‌ها یک یادداشت برای انسان‌ها نیست. بلکه ساختار بنیادینی است که کل هارنس بر آن بنا شده است. زمان‌بند برای انتخاب وظایف به آن اتکا می‌کند، راستی‌آزما برای سنجش اتمام به آن تکیه دارد، و گزارشگر تحویل برای تولید خلاصه‌ها به آن وابسته است. بدون آن، این مؤلفه‌ها هیچ اجماع مشترکی برای اتکا ندارند.

هم Anthropic و هم OpenAI تأکید دارند: مصنوعات باید بیرونی‌سازی شوند. وضعیت ویژگی باید در یک فایل ماشین‌خوان در مخزن (repository) جای گیرد، نه در متن ساختارنیافتهٔ گفتگوها.

ایجنت‌ها نمی‌دانند «اتمام کار» یعنی چه#

نه Claude Code و نه Codex به‌طور خودکار نمی‌دانند منظور شما از «تمام شد» چیست. شما می‌گویید «یک قابلیت سبد خرید اضافه کن»، و برداشت مدل ممکن است این باشد که «یک مؤلفهٔ Cart و یک متد addToCart بنویس». اما منظور شما این بود که «کاربر بتواند محصولات را مرور کند، به سبد خرید بیفزاید، و تسویه حساب را به‌صورت سرتاسری (end-to-end) کامل کند».

این شکاف درک بدون یک فهرست ویژگی‌ها پایدار می‌ماند. ایجنت از استاندارد ضمنی خود استفاده می‌کند — که معمولاً این است: «کد خطای نحوی آشکاری ندارد». آنچه شما نیاز دارید راستی‌آزمایی (verification) رفتاری سرتاسری است. بدون یک فهرست، دو طرف هرگز بر سر معنای «تمام شد» به توافق نخواهند رسید.

به این یادداشت پیشرفت رایج نگاه کنید:

Did user auth, shopping cart mostly done, still need payments

آیا یک نشست جدید از ایجنت می‌تواند از این یادداشت به پرسش‌ها پاسخ دهد؟ «تقریباً انجام شد» یعنی چه؟ سبد خرید کدام آزمون‌ها را پاس کرده است؟ چه چیزی مانع پرداخت‌ها شده است؟ پاسخ به همهٔ این‌ها این است: «هیچ‌کس نمی‌داند».

نتیجه: نشست جدید مجبور است وضعیت پروژه را استنتاج کند، و ممکن است کارش به پیاده‌سازی دوبارهٔ قابلیت‌های تکمیل‌شده ختم شود. توصیهٔ Anthropic این است که پیشرفت و نتایج راستی‌آزمایی را در فایل‌های دارای نسخه ثبت کنید تا نشست بعدی بتواند وضعیت را بررسی کند.

ماشین وضعیت ویژگی#

flowchart LR
    Feature["One feature row"] --> Behavior["Behavior<br/>e.g.: POST /cart/items returns 201"]
    Feature --> Check["Verification command<br/>the exact check to run"]
    Feature --> State["State<br/>not_started / active / blocked / passing"]

    Behavior --> Complete["All three fields present<br/>the feature row is usable"]
    Check --> Complete
    State --> Complete
flowchart LR
    List["feature_list.json / features.md"] --> Scheduler["Pick the next not_started item"]
    Scheduler --> Agent["Agent works on that one item"]
    Agent --> Verifier["Run that item's verification command"]
    Verifier -->|pass| Passing["Mark it passing<br/>and attach evidence"]
    Verifier -->|fail| Active["Keep it active"]
    Verifier -->|dependency issue| Blocked["Mark it blocked"]
    Passing --> Handoff["Update handoff note<br/>and current progress"]
    Active --> Agent

مفاهیم اصلی#

  • فهرست‌های ویژگی‌ها از عناصر بنیادین هارنس هستند: نه «ابزارهای اختیاری برنامه‌ریزی»، بلکه ساختارهای داده‌ای بنیادین که تمام مؤلفه‌های دیگر هارنس به آن‌ها وابسته‌اند. زمان‌بند، راستی‌آزما، و گزارشگر تحویل همگی برای کارکرد خود نیاز به خواندن فهرست ویژگی‌ها دارند.
  • ساختار سه‌گانه: هر قلم ویژگی شامل سه عنصر است: (شرح رفتار، دستور راستی‌آزمایی، وضعیت کنونی). رفتار به ایجنت می‌گوید چه کند، راستی‌آزمایی به آن می‌گوید چه چیزی اتمام کار محسوب می‌شود، و وضعیت به آن می‌گوید کار در چه مرحله‌ای است. فقدان هر عنصر قلم را ناقص می‌کند.
  • مدل ماشین وضعیت: هر قلم ویژگی دارای چهار وضعیت است — not_started، active، blocked، و passing. انتقال‌های وضعیت توسط هارنس کنترل می‌شوند، نه اینکه ایجنت آزادانه آن‌ها را تغییر دهد.
  • دروازه‌بانی وضعیت قبولی: تنها راهی که یک ویژگی از active به passing می‌رود، اجرای موفقیت‌آمیز دستور راستی‌آزمایی است. این انتقال برگشت‌ناپذیر است — وقتی به passing رسید، نمی‌تواند بازگردد.
  • یگانه منبع حقیقت: تمام اطلاعات دربارهٔ «چه کاری باید انجام شود» باید از یک فهرست ویژگی‌ها مشتق شود. هیچ تناقضی نباید میان فهرست ویژگی‌ها و تاریخچهٔ گفتگو وجود داشته باشد.
  • پس‌فشار (Back-Pressure): تعداد ویژگی‌هایی که هنوز پاس نشده‌اند، همان فشاری است که هارنس بر ایجنت وارد می‌کند. پس‌فشار صفر = پروژه کامل است.

چرا فهرست‌های ویژگی‌ها باید جزو «عناصر بنیادین» باشند#

اسناد برای خواندن انسان‌ها هستند؛ عناصر بنیادین برای اجرای سیستم‌ها هستند. اسناد را می‌توان نادیده گرفت؛ اما عناصر بنیادین را نمی‌توان دور زد.

آن را مانند محدودیت‌های تریگر در پایگاه داده در برابر بررسی‌های لایهٔ برنامه در نظر بگیرید: اولی توسط موتور پایگاه داده اعمال می‌شود — هیچ کوئری SQL نمی‌تواند آن را دور بزند. دومی به درستی کد برنامه بستگی دارد و ممکن است تصادفاً دور زده شود. فهرست‌های ویژگی‌ها به‌عنوان عناصر بنیادین هارنس همان نقش محدودیت‌های سطح پایگاه داده را ایفا می‌کنند — ایجنت نمی‌تواند آن‌ها را دور بزند.

به‌طور مشخص، فهرست ویژگی‌ها به چهار مؤلفهٔ هارنس خدمت می‌کند:

  1. زمان‌بند: وضعیت‌ها را می‌خواند، ویژگی بعدی با وضعیت not_started را انتخاب می‌کند.
  2. راستی‌آزما: دستورات راستی‌آزمایی را اجرا می‌کند، و تصمیم می‌گیرد آیا اجازهٔ انتقال وضعیت را بدهد یا خیر.
  3. گزارشگر تحویل: خلاصه‌های تحویل نشست را به‌طور خودکار از روی فهرست ویژگی‌ها تولید می‌کند.
  4. ردیاب پیشرفت: توزیع وضعیت‌ها را محاسبه می‌کند، و معیارهای سلامت پروژه را ارائه می‌دهد.

چگونه این کار را انجام دهیم#

1. تعریف یک قالب کمینه برای فهرست ویژگی‌ها#

نیازی به یک سیستم پیچیده ندارید — یک فایل ساختاریافتهٔ Markdown یا JSON کفایت می‌کند. نکتهٔ کلیدی این است که هر ورودی باید ساختار سه‌گانه را داشته باشد:

{
  "id": "F03",
  "behavior": "POST /cart/items with {product_id, quantity} returns 201",
  "verification": "curl -X POST http://localhost:3000/api/cart/items -H 'Content-Type: application/json' -d '{\"product_id\":1,\"quantity\":2}' | jq .status == 201",
  "state": "passing",
  "evidence": "commit abc123, test output log"
}

2. واگذاری کنترل انتقال وضعیت به هارنس#

ایجنت نمی‌تواند مستقیماً وضعیت یک ویژگی را به passing تغییر دهد. تنها می‌تواند درخواست راستی‌آزمایی ارسال کند. هارنس دستور راستی‌آزمایی را اجرا کرده و تصمیم می‌گیرد که آیا اجازهٔ انتقال داده شود یا خیر. این همان «دروازه‌بانی وضعیت قبولی» است.

3. نوشتن قواعد در CLAUDE.md#

## Feature List Rules
- Feature list file: /docs/features.md
- Only one feature active at a time
- Verification command must pass before marking as passing
- Don't modify feature list states yourself — the verification script updates them automatically

4. کالیبره کردن دانه‌بندی#

دامنهٔ (scope) هر قلم ویژگی باید به‌گونه‌ای تعیین شود که «در یک نشست قابل‌تکمیل باشد». اگر بیش از حد گسترده باشد تمام نمی‌شود؛ اگر بیش از حد خرد باشد بار مدیریتی افزایش می‌یابد. «کاربر بتواند کالاها را به سبد خرید اضافه کند» دانه‌بندی خوبی است. «پیاده‌سازی سبد خرید» بیش از حد گسترده است. «ایجاد فیلد name در مدل Cart» بیش از حد خرد است.

موردی از دنیای واقعی#

یک پلتفرم تجارت الکترونیک با 10 ویژگی. مقایسهٔ دو رویکرد ردیابی:

حالت یادداشت: ایجنت از یادداشت‌های ساختارنیافته برای ردیابی پیشرفت استفاده می‌کند. پس از 3 نشست، یادداشت‌ها تبدیل می‌شوند به «احراز هویت کاربر و فهرست محصولات انجام شد، سبد خرید تقریباً تمام است اما باگ دارد، پرداخت‌ها آغاز نشده است». یک نشست جدید به 20 دقیقه زمان برای استنتاج وضعیت نیاز دارد، و در نهایت قابلیت‌های تکمیل‌شده را از نو پیاده‌سازی می‌کند.

حالت ساختاریافته: هر ویژگی دارای وضعیت و دستور راستی‌آزمایی شفاف است. یک نشست جدید فهرست ویژگی‌ها را می‌خواند و ظرف 3 دقیقه متوجه می‌شود: موارد F01 تا F05 در وضعیت passing هستند، F06 در وضعیت active (در حال انجام) است، و F07 تا F10 در وضعیت not_started قرار دارند. مستقیماً کار را از F06 پی می‌گیرد، با صفر درصد بازکاری.

یک فهرست ساختاریافته، وضعیت و دستور راستی‌آزمایی هر ویژگی را در یک جا گرد می‌آورد تا نشست جدید بداند چه کارهایی انجام شده است.

نکات کلیدی#

  • فهرست‌های ویژگی‌ها ساختار بنیادین هارنس هستند، نه یادداشتی برای انسان‌ها. زمان‌بند، راستی‌آزما، و گزارشگر تحویل همگی به آن‌ها وابسته‌اند.
  • هر قلم ویژگی باید ساختار سه‌گانه را داشته باشد: شرح رفتار + دستور راستی‌آزمایی + وضعیت کنونی. فقدان یک عنصر آن را ناقص می‌کند.
  • انتقال‌های وضعیت توسط هارنس کنترل می‌شوند — ایجنت نمی‌تواند خودش وضعیت‌ها را تغییر دهد. قبولی در راستی‌آزمایی تنها مسیر ارتقا است.
  • فهرست ویژگی‌ها یگانه منبع حقیقت پروژه است — تمام اطلاعات «چه باید کرد» از آن مشتق می‌شود.
  • دانه‌بندی را روی «قابل‌تکمیل در یک نشست» کالیبره کنید. اگر بیش از حد گسترده باشد تمام نمی‌شود؛ اگر بیش از حد ریز باشد قابل‌مدیریت نیست.

منابع بیشتر#

تمرین‌ها#

  1. طراحی فهرست ویژگی‌ها: یک اسکیما برای JSON فهرست ویژگی‌های کمینه تعریف کنید. شامل: شناسه، شرح رفتار، دستور راستی‌آزمایی، وضعیت کنونی، ارجاع شواهد. از آن برای توصیف یک پروژهٔ واقعی با 5 ویژگی استفاده کنید.

  2. مقایسهٔ سخت‌گیری در راستی‌آزمایی: 3 ویژگی انتخاب کنید و هم راستی‌آزمایی «آسان‌گیرانه» (مثلاً «کد خطای نحوی ندارد») و هم «سخت‌گیرانه» (مثلاً «آزمون سرتاسری پاس می‌شود») طراحی کنید. نرخ مثبت کاذب را در هر دو رویکرد مقایسه نمایید.

  3. بازبینی اصل یگانه منبع حقیقت: یک پروژهٔ موجود با ایجنت را بررسی کرده و اطلاعات دامنه‌ای را که با فهرست ویژگی‌ها در تناقض است بیابید (نیازمندی‌های ضمنی در گفتگوها، کامنت‌های TODO در کد، و غیره). طرحی برای یکپارچه‌سازی تمام اطلاعات در فهرست ویژگی‌ها طراحی کنید.