تیم میخواهد قابلیت تقویم را شروع کند. ایجنت میتواند بگوید endpoint رزرو کجاست، چه تستی اجرا میشود و آیا جدول token داریم. اما نمیتواند از روی کد کشف کند که پزشک حق دارد busy بودن رویداد شخصی را پنهان کند یا اینکه در قطع provider رزرو باید متوقف شود. اگر این دو نوع مجهول مخلوط شوند، ایجنت از روی حدس سیاست میسازد و تیم بعداً آن را «رفتار موجود» مینامد.
## اهداف یادگیری
پس از این درس میتوانی Fact قابل کشف را از Decision محصول/سیاست جدا کنی، reconnaissance کمخطر برای مخزن طراحی کنی، نتیجهٔ کشف را به شکل قابل تحویل بنویسی، و یک Decision ledger با مالک، ضربالاجل، پیامد و default بسازی.
## جای درس در چرخهٔ سرتاسری
این درس هنوز در Elicit است، اما به مرز Observe میرسد. Problem brief درس قبل پرسید چه چیزی ارزش دارد. اکنون ایجنت فقط شواهد فنی و رفتار فعلی را کشف میکند و انسان برای ارزش، policy و Trade-off پاسخ میدهد. این تمایز، Task Contract فصل قبل را عملی میکند: بخش Context و فرمانهای read-only برای facts است؛ شرط توقف `DECIDE` برای پاسخ انسانی است.
## دو نوع مجهول
**Fact** گزارهای دربارهٔ وضعیت قابل مشاهدهٔ مخزن، محیط یا رفتار موجود است. «Route ایجاد appointment کجاست؟»، «کدام tenantId در query فیلتر میشود؟»، «فرمان تست integration چیست؟»، «آیا migration برای calendar_token وجود دارد؟» fact هستند. ایجنت میتواند فایل، schema، تاریخچهٔ نزدیک، test و config را بخواند؛ خروجی باید مسیر، مشاهده و میزان اطمینان داشته باشد. Fact نیز میتواند ناقص یا منقضی باشد؛ مشاهدهٔ قدیمی را حقیقت ابدی فرض نکنید.
**Decision** گزارهای دربارهٔ آن چیزی است که سازمان انتخاب میکند. «کدام نقش مجاز به اتصال است؟»، «در outage رزرو دستی مجاز است؟»، «آیا عنوان رویداد شخصی به منشی نشان داده میشود؟»، «هزینهٔ provider تا چه سقفی پذیرفتنی است؟» از code قابل استخراج نیستند، حتی اگر code برای امروز یک پاسخ ضمنی داشته باشد. رفتار موجود ممکن است bug، بدهی یا policy تاریخگذشته باشد. ایجنت میتواند گزینه، پیامد و evidence ارائه کند؛ حق ندارد ارزش را به جای مالک تصمیم بگیرد.
قاعدهٔ فصل اول را دقیق نگه دارید: **واقعیتها کشف میشوند؛ تصمیمها elicited میشوند.** جمله به این معنی نیست که facts هرگز نیاز به گفتوگو ندارند یا decisionها هیچ شاهدی ندارند. یک تصمیم خوب از داده، قانون و گزینه تأثیر میگیرد؛ فرق در منبع authority است. برای Fact میپرسیم «از کجا نشان میدهی؟» برای Decision میپرسیم «چه کسی، تا چه زمانی، کدام trade-off را میپذیرد؟»
## reconnaissance: کشف کوچک، گزارش قابل بازتولید
Reconnaissance مجوز «هرچه خواستی بخوان» نیست. از Problem brief سؤالهای fact بساز و به هرکدام کمینهٔ مسیر بده. برای calendar sync ممکن است این قرارداد read-only باشد:
هدف: مسیر ایجاد/نمایش appointment و مرز tenant را پیدا کن.
مجاز: apps/api/src/modules/appointments، packages/db/schema، testهای مرتبط و package scripts.
ممنوع: ویرایش فایل، شبکه، خواندن Secret یا export داده.
خروجی: جدول Fact | شاهد مسیر/فرمان | اطمینان | سؤال باز.
توقف: اگر policy کسبوکار یا دسترسی token لازم شد، DECIDE.ایجنت ابتدا ساختار پوشه و scriptهای package را میبیند، سپس route و test نزدیک را باز میکند. خروجی خوب نمیگوید «احتمالاً tenancy رعایت شده»؛ میگوید «در `appointments.service.ts` query ایجاد رزرو `tenantId` را میگیرد؛ تست X جداسازی دو tenant را پوشش نمیدهد؛ برای اجرای `pnpm test appointments` نیاز به dependency نصبشده است.» شاهدِ مسیر یا فرمان، امکان بازبینی میدهد و «نمیدانم» را مفید میکند.
نمونهٔ خروجی reconnaissance
| Fact | شاهد | اطمینان | سؤال باز |
|---|---|---|---|
| create appointment از service مرکزی عبور میکند | مسیر route و تست integration | بالا | conflict در database یا service؟ |
| tenantId به query فعلی داده میشود | schema و query | متوسط | آیا همهٔ readها همین فیلتر را دارند؟ |
| token تقویم در schema دیده نشد | جستوجوی مسیرهای مجاز | متوسط | آیا provider secret در سرویس جداست؟ |
| تست timezone وجود دارد | نام test و فرمان package | بالا | مرجع timezone کاربر یا کلینیک چیست؟ |
این جدول «طراحی» نیست. بنابراین نباید از نبودِ token در مسیر محدود نتیجه بگیرد که token لازم نیست. شکاف discovery را با سؤال یا گسترش Scopeِ تأییدشده رفع میکنیم.
## Decision ledger: ابهام را مالکدار کن
Decision ledger حافظهٔ بیرونیِ کوتاه برای انتخابهایی است که اگر فراموش شوند، Agent و انسان دوباره بحث را از صفر آغاز میکنند. هر ردیف یک **تصمیم روشن**، **مالک authority**، **deadline**، **گزینه/تصمیم فعلی**، **پیامد** و **default** دارد. Default حکم دائمی یا حق حدس نیست؛ مسیر محافظهکارانهای است که فقط اگر تا deadline پاسخ نرسید اجرا میشود یا کار را متوقف میکند.
| تصمیم | مالک | deadline | پیامد | default |
|---|---|---|---|---|
| نمایش جزئیات رویداد؟ | مالک محصول + حریم خصوصی | پیش از Spec | دادهٔ حساس و UI | فقط busy/free |
| outage provider چه میکند؟ | مالک محصول + عملیات | پیش از Slice | رزرو، پشتیبانی و اعتماد کاربر | `DECIDE`: A) block؛ B) دستی/نامشخص؛ C) آخرین sync برچسبدار |
| token کجا میماند؟ | امنیت/معماری | پیش از اجرا | Secret و معماری | client ممنوع؛ کار BLOCKED |
| all-day چطور تفسیر میشود؟ | محصول + عملیات | پیش از مثال پذیرش | timezone و availability | هیچ بازهای خودکار آزاد نشود |
مالک لزوماً مدیر محصول نیست: امنیت مالک policy Secret، عملیات مالک رفتار outage و مهندس مالک امکان فنی را توضیح میدهد، اما هیچیک به تنهایی مالک ارزش تجاری نمیشود. deadline از «بعداً میپرسیم» جلوگیری میکند. پیامد نشان میدهد چرا ترتیب مهم است. اگر تصمیم فوراً مسیر طراحی را عوض میکند، قبل از نوشتن code باید پاسخ بگیرد.
ردیف outage عمداً تصمیمِ باز است. گزینهٔ A از ارائهٔ availability نامطمئن جلوگیری میکند اما ممکن است خدمت را متوقف کند. گزینهٔ B تداوم خدمت میدهد اما منشی باید وضعیت نامشخص و مسئولیت بررسی دستی را ببیند. گزینهٔ C اصطکاک را کم میکند، ولی به timestamp، حد کهنگی و خطر پیشنهاد نادرست وابسته است. تا مالک محصول و عملیات یکی را نپذیرفتهاند، هیچکدام Fact یا رفتار پذیرفتهشده نیست؛ default این ردیف `DECIDE/BLOCKED` است، نه «رزرو دستی مجاز است».
## مثال واقعی: Fact و Decision کنار هم
در booking-platform، ایجنت میبیند API فعلی هنگام conflict پاسخ `409` میدهد و testها timezone را با `UTC` میسازند. اینها facts با شاهداند. اما اینکه برای تقویم خارجی در حالت `UTC`، منطقهٔ کلینیک یا منطقهٔ پزشک authority باشد، decision است. اگر انسان نگوید، Agent نباید از test فعلی «سیاست timezone» استنتاج کند. در ledger ثبت میکند: «مالک عملیات/محصول، قبل از Acceptance examples؛ default: هیچ تبدیل زمان یا release انجام نشود.»
مثال ضعیف و علت شکست
«کد را بررسی کن و بهترین رفتار sync را پیاده کن.» خروجی ممکن است endpoint و schema را کشف کند و سپس خودسرانه تصمیم بگیرد eventهای all-day آزادند یا provider outage رزرو را block میکند. عبارت «بهترین» authority ندارد؛ حتی خروجی تست سبز هم policy را تأیید نمیکند.
مثال اصلاحشده
«فقط facts را با مسیر و فرمان شاهد کشف کن: جریان appointment، tenancy، تست timezone و محل secret. سپس Decision ledger پیشنهادی بساز؛ هر ردیف باید مالک، deadline، consequence و default داشته باشد. برای هر policy نامعلوم `DECIDE` کن؛ هیچ code یا migration تغییر نده.» Prompt روشن میکند ایجنت تحلیلگر است، نه تصمیمگیر.
## آزمایشگاه: دفتر تصمیم بساز
**ورودی:** Problem brief درس قبل و دسترسی read-only به مخزن نمونه. **گامها:** ۱) پنج پرسش fact و سه پرسش decision بنویس. ۲) برای factها مسیر و فرمانی که ممکن است شاهد شود تعیین کن. ۳) یک reconnaissance محدود اجرا یا روی کاغذ شبیهسازی کن. ۴) چهار ردیف ledger با مالک، deadline، consequence و default بساز. ۵) یک مورد را بهسبب نبود authority با `DECIDE` متوقف کن.
**خروجی مورد انتظار:** گزارشی که factها را با شاهد جدا میکند و ledger آن دربارهٔ نمایش busy، outage، token و timezone مسئول دارد.
**Recovery:** اگر عبارت «طبق کد» پاسخ یک policy شد، آن را از Fact به Decision منتقل کن و رفتار فعلی را فقط evidence بنام. اگر Scope کشف بزرگ شد، یک سؤال fact را حذف یا مسیرهای مجاز را باریک کن.
## خطاهای رایج و نشانهها
- تبدیل behavior موجود به policy مطلوب: «همین الان 409 است، پس محصول همین را میخواهد.»
- Fact بدون شاهد: مسیر، query یا فرمان قابل بازبینی نوشته نشده است.
- ledger بدون مالک: همه میتوانند نظر بدهند ولی هیچکس تصمیم نمیگیرد.
- default بدون deadline: فرض موقت بیصدا دائمی میشود.
- reconnaissance با Secret یا data واقعی: هدف discovery است، نه افزایش بیدلیل دسترسی.
## چکلیست Verification
- [ ] هر Fact شاهد مسیر، فرمان یا مشاهده دارد.
- [ ] هر Decision مالک authority و زمان پاسخ دارد.
- [ ] پیامد و default هر تصمیم روشن است.
- [ ] رفتار موجود را با انتخاب آینده اشتباه نگرفتهام.
- [ ] Scope read-only و مسیرهای مجاز reconnaissance ثبت شدهاند.
- [ ] مجهول policy با `DECIDE` متوقف میشود، نه با حدس.
## تمرین مستقل
برای «لغو رزرو تا ۲۴ ساعت قبل» پنج Fact، سه Decision و یک ledger سهردیفی بساز.
**Rubric پاسخ:** Facts باید شامل محل زمان رزرو، وضعیت فعلی، timezone و تستها با شاهد پیشنهادی باشند. Decisions باید مالک policy لغو، تکلیف استثنای عملیات و پیامد مالی داشته باشند. ledger خوب deadline و default محافظهکارانه دارد؛ پاسخ «کد را بخوان و خودت انتخاب کن» مردود است.
## جمعبندی
Reconnaissance، یقین ساختگی تولید نمیکند؛ شواهد محدود و سؤالهای باز میآورد. Decision ledger نیز جلسهٔ گفتوگو نیست؛ انتخاب، مالک و پیامد را پایدار میکند. در درس بعد، این سؤالها را بر حسب وابستگی و ریسک مرتب میکنیم تا تیم زودتر به گرههای واقعی برسد.
## منابع مستقیم
- [ISO/IEC/IEEE 29148:2018](https://www.iso.org/standard/72089.html) — استاندارد مهندسی نیاز؛ انتخابهای محصول را خودکار نمیکند.
- [IIBA — Conduct Elicitation](https://www.iiba.org/knowledgehub/business-analysis-body-of-knowledge-babok-guide/4-elicitation-and-collaboration/4.2-conduct-elicitation) — راهنمای حرفهای همکاری و استخراج نیاز.
- [Ron Jeffries — Card, Conversation, Confirmation](https://ronjeffries.com/xprog/articles/expcardconversationconfirmation/) — روش جامعهمحور برای گفتوگو و تأیید.
به زبان ساده
Fact چیزی است که از کد، schema یا تست با شاهد پیدا میشود؛ Decision انتخابی است که مالک محصول، امنیت یا عملیات باید تأیید کند. Agent میتواند گزینه و پیامد بدهد، اما policy را از رفتار فعلی حدس نمیزند.
مثال واقعی
در `booking-platform` فرضی، وجود فیلتر `tenantId` در query یک Fact قابلردیابی است؛ اینکه هنگام قطع provider رزرو متوقف شود یا دستی ادامه یابد، Decision دفتر تصمیم است.