همه ما آنجا بودهایم: گذاشتی AI روی یک مسئله بتازد و برگشتی، یک آشغالدانی کامل و شلخته تحویل گرفتی. Ralph مخصوصاً به این حساس است، چون کاملاً Headless میچرخد — هیچ انسانی در حلقه نیست که مسیر را درست نگه دارد. اگر یک زیرکار آنطور که تصور کردی پیاده نشود، مدل Drift میکند و Drift میکند تا به یک AI Slop غیرقابلاستفاده برسی.
تقصیر کیست؟
بیشتر وقتها تقصیر خودمان است: یا بهقدر کافی دقیق توصیف نکردیم، یا آنقدر ابهام در جزئیات پیادهسازی گذاشتیم که مدل انتخاب اشتباه کرد. خبر خوب: خروجی مدل را راحت میشود دور ریخت و PRD را با درسهای حلقه اول اصلاح کرد. اما گاهی «از قبل» میدانی کجا ابهام هست — مثلاً جایی که مدل قرار است یک ساختار داده، اسکیمای دیتابیس یا Endpoint را تعریف کند. آنجا میخواهی «بهعمد» وارد شوی.
مکانیزم: پیشوند [human-in-the-loop]
Skill مربوط به Linear را کمی تغییر میدهیم: به مدل میگوییم وقتی یک Sub-issue شامل یک تصمیم معماری مهم است (مثل انتخاب مدل داده)، عنوانش را با `[human-in-the-loop]` شروع کند. Ralph CLI این رشته را تشخیص میدهد و بعد از انجام آن کار، بهجای `Done`، Issue را (و والدش را) به `In Review` میبرد.
برای اینکه از تمام شدن کار باخبر شوی، یک Hook کوچک هم اضافه میکنیم که فقط یک صدای کوتاه پخش میکند:
# ralph.toml
[hooks]
human_in_the_loop = "afplay ./sounds/ping.aiff"نمونه واقعی: مدل داده سفارشیسازی منو
PRD ای برای «افزودن Add-on و Modifier به آیتمهای منو» آماده است (مثلاً به همبرگر پنیر اضافه کن، سایز نوشیدنی را انتخاب کن، اثر قیمت را قبل از تأیید ببین). مهمترین Sub-issue، «تعریف مدل داده منو» است — پس Label `human-in-the-loop` دارد.
Ralph اجرا میشود، صدا پخش میشود، Issue در `In Review` است و مدل ساختار پیشنهادی را در Comment گذاشته. بازبینی میکنیم:
// پیشنهاد اولیه مدل (ناقص):
{
"customizations": [
{ "name": "Cheese", "price": 0.5 },
{ "name": "Veggie", "price": 0 }
]
}اینجا دقیقاً همان نقطه ابهامی است که از قبل حدس میزدیم. ما یک Comment میگذاریم: «options به یک فیلد id نیاز دارد؛ یک Unsigned Integer. غیر از این، پیشنهاد خوب است.» بعد Issue را به `To Do` برمیگردانیم و چون مطمئنیم بقیهاش خوب پیش میرود، Label `human-in-the-loop` را برمیداریم.
// بعد از بازخورد ما:
{
"customizations": [
{ "id": 1, "name": "Cheese", "price": 0.5 },
{ "id": 2, "name": "Veggie", "price": 0 }
]
}مدل بازخورد را برمیدارد: «per feedback, each option needs an id — I'll add it». حالا آن `id` بهعنوان Key در حلقه رندر options استفاده میشود.
چرا این الگو طلایی است؟
مدل را در Guardrail نگه داشتیم بیآنکه کل کار را خودمان بکنیم. تصمیم معماری کلیدی را قبل از ساخته شدن روی آن، تثبیت کردیم. این «برگرداندن آگاهانه خودت به حلقه» در کار روزمره با Ralph فوقالعاده مفید است — مرز بین اتوماسیون کامل و کنترل کامل.
به زبان ساده
حلقه Headless اگر مبهم باشد، آرامآرام کج میشود. جاهایی که از قبل میدانی تصمیم معماری است، عمداً خودت را برگردان: مدل کار را میکند، میایستد، تو Comment میگذاری.
مثال واقعی
مدل داده Add-on منو بدون id آمد. یک Comment: «هر option یک id عددی میخواهد.» Issue برگشت To Do، Label HITL برداشته شد. مدل id را اضافه کرد و همان را Key رندر کرد — قبل از اینکه کل فیچر روی مدل غلط ساخته شود.