تصمیم درباره‌ی اینکه ایجنت اجازه دارد دستوری را اجرا کند، در هارنس‌های امروز یک لایه‌ی جدا از مدل است و این لایه عدد دارد. در dscode نسخه‌ی 0.7.32 که ۲۵ سپتامبر بیرون آمد، بازبین خودکار یعنی هر درخواستِ حساس به یک مدلِ جداگانه و فقط‌خواندنی می‌رود و او تصمیم می‌گیرد. در این نوشته همین لایه را با یک دفترچه‌ی ساده اندازه می‌گیریم و سه عددی را به دست می‌آوریم که هر پیکربندی مجوزی به آن‌ها نیاز دارد: نرخ تأیید خودکار، زمان بازبینی، و اینکه کدام ابزارها واقعاً گلوگاه‌اند.

لایه‌ی مجوز کجاست و چرا عدد دارد

بگذارید اول یک سوءتفاهم را برداریم: لایه‌ی مجوز، بخشی از مدل نیست. یک قطعه‌ی کد بین ایجنت و ابزار است. ایجنت می‌گوید «می‌خواهم این دستور را اجرا کنم»، و این لایه پیش از رسیدن دستور به شل تصمیم می‌گیرد که بگذرد یا نگذرد. اگر مدل آرزوی خطرناکی داشته باشد، این لایه جلویش می‌ایستد.

همین معماری است که چهار عدد را ممکن می‌کند. چون هر تصمیم یک رکورد دارد، می‌توانید بشمارید چندتا مجاز شد و چندتا رد شد. می‌توانید ببینید هر تصمیم چقدر طول کشیده و کدام ابزار بیشتر درخواست داده است. بدون این لایه، هیچ‌کدام از این چهار عدد وجود ندارد.

این چهار عدد از هم جدا هستند و هرکدام یک سؤال متفاوت را جواب می‌دهند. نرخ تأیید می‌گوید لایه چقدر سخت‌گیر است. زمان بازبینی می‌گوید این سخت‌گیری برای کاربر چقدر طول می‌کشد. شمار ابزارهای درگیر می‌گوید گلوگاه کجاست. و نسبت رد شدن‌ها می‌گوید آیا لایه اصلاً کاری می‌کند یا فقط وقتم را می‌گیرد.

بیشتر تیم‌ها فقط اولی را نگاه می‌کنند و از همین‌جا اشتباه می‌کنند. نرخ بالای تأیید خودکار خوب به نظر می‌رسد، ولی تا وقتی ندانید زمان بازبینی چقدر است و کدام ابزارها اصلاً بازبینی می‌شوند، این عدد به شما چیزی نمی‌گوید.

در نوشته‌ی dscode دیدیم که تأیید خودکار یعنی چه: به‌جای یک جدول قواعد ثابت، دستورِ خودِ شما به یک مدلِ فقط‌خواندنی داده می‌شود تا بر اساس آن تصمیم بگیرد. آنجا درباره‌ی خودِ قابلیت حرف زدیم. اینجا درباره‌ی عددهایی که می‌دهد. دامنه و محدودیت‌های همین تصمیم‌ها در مستند تأیید خودکار نوشته شده است.

دفترچه‌ی لایه، به زبان ساده

بگذارید یک لایه‌ی مجوز را به کمترین شکلی که کار می‌کند بنویسیم. این همان کاری است که یک هارنس واقعی در خودش دارد، منتهی بدون اتصال به هیچ مدلی. هر تصمیم یک ردیف است و هر ردیف سه چیز دارد: کدام ابزار، مجاز شد یا نه، و بازبینی چقدر طول کشید.

نکته‌ای که این ساختار کوچک به شما یاد می‌دهد این است که لایه‌ی مجوز هیچ هوشی لازم ندارد. تصمیم‌گیری در مدل بازبین است، نه در این لایه. این لایه فقط کاری است که هر سیستم حسابداری هم می‌کند: ثبت، و بعد شمارش.

و همین‌جاست که عددهای خوب از دل کد درمی‌آیند. اگر لایه‌ی شما هر تصمیم را ثبت نکند، بعد از یک ماه نمی‌توانید بگویید بازبینی شما کار می‌کند یا فقط وقت شما را می‌گیرد. ثبت کردن، ارزان‌ترین بخش کاری است که اضافه می‌کنید و بیشترین اطلاعات را می‌دهد. سنجیدن اینکه قابلیت تازه چه چیزی را عوض کرده، روش خودش را دارد: راهنمای ارزیابی افزونه هر حالت را در نشست جدا اجرا می‌کند و دو بازو را با هم مقایسه می‌کند.

# ذخیره به نام perm_probe.py و اجرا؛ نیازی به نصب چیزی نیست:
$ python3 perm_probe.py

import json
from dataclasses import dataclass, field


@dataclass
class Decision:
    tool: str          # کدام ابزار درخواست داده
    allow: bool        # مجاز شد یا نه
    latency_ms: int = 0   # زمان بازبینی، صفر یعنی بدون بازبینی


@dataclass
class Ledger:
    rows: list = field(default_factory=list)

    def summary(self):
        total = len(self.rows)
        auto = sum(1 for r in self.rows if r.allow)
        lat = [r.latency_ms for r in self.rows if r.latency_ms]
        return {
            "total": total,
            "auto_approved": auto,
            "denied": total - auto,
            "auto_rate": round(auto / total, 3) if total else 0,
            "review_p50_ms": sorted(lat)[len(lat) // 2] if lat else 0,
            "review_p95_ms": sorted(lat)[int(len(lat) * 0.95)] if lat else 0,
        }

این بیست‌ودو ردیف، یک بعدازظهر واقعی کار ایجنت را بازسازی می‌کنند: نه خواندن، نه نوشتن، نه دستور شل. بیست ردیف مجاز شدند و دو ردیف نه.

# بیست‌ودو درخواست واقعی از یک بعدازظهر کار ایجنت
TASKS = [
    ("read_file", True, 0), ("read_file", True, 0), ("grep", True, 0),
    ("read_file", True, 0), ("list_dir", True, 0), ("read_file", True, 0),
    ("write_file", True, 120), ("write_file", True, 118), ("read_file", True, 0),
    ("bash", True, 340), ("bash", True, 352), ("read_file", True, 0),
    ("write_file", True, 125), ("grep", True, 0), ("read_file", True, 0),
    ("bash", False, 361), ("read_file", True, 0), ("write_file", True, 130),
    ("bash", True, 348), ("read_file", True, 0), ("list_dir", True, 0),
    ("bash", False, 355),
]

سه عددی که هر پیکربندی به آن‌ها نیاز دارد

خروجی واقعی همان اسکریپت روی همین ماشین است.

$ python3 perm_probe.py

=== سه آستانه‌ای که یک لایه‌ی مجوز لازم دارد ===
نرخ تأیید خودکار: 90.9%
میانه‌ی زمان بازبینی: 340 میلی‌ثانیه
صدک ۹۵ زمان بازبینی: 361 میلی‌ثانیه

bash         5 درخواست     3 تأیید   60%
grep         2 درخواست     2 تأیید   100%
list_dir     2 درخواست     2 تأیید   100%
read_file    9 درخواست     9 تأیید   100%
write_file   4 درخواست     4 تأیید   100%

نخستین عدد، نرخ تأیید خودکار. نود و نه درصد یعنی از هر صد درخواست، نود و نه بی‌سروصدا گذشتند. این عدد را نباید زیاد کرد. اگر به صد درصد برسد، لایه‌ی شما عملاً وجود ندارد و فقط کاغذ است.

دومین عدد، زمان بازبینی. میانه‌ی سیصد و چهل میلی‌ثانیه و صدک نود و پنج، سیصد و شصت و یک. این یعنی هر تصمیمی که به بازبین برسد، کمتر از نیم‌ثانیه معطلی به کاربر تحمیل می‌کند. این عدد دقیقاً تعیین می‌کند بازبینی را روی کدام ابزارها بگذارید.

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

توجه کنید که این ستون، برخلاف دو تای قبل، تفسیر نمی‌خواهد. سه ابزار با نرخ صد درصد یعنی در این کار، هرگز دلیلی برای نگه‌داشتن آن‌ها نبوده. یک ابزار با نرخ شصت درصد یعنی بازبینی آن‌جا دارد کاری می‌کند. همین یک ردیف، جای بازبینی را برای شما تعیین می‌کند.

این را به آن اضافه کنید که هزینه‌ی هر ابزار یکسان نیست. نوشتن فایل چهار بار در این کار اتفاق افتاده، ولی اگر یک هارنس، اجرای دستور را بیست بار در یک ساعت بفرستد، همان بازبینی می‌تواند چند ثانیه از وقت شما را در هر ساعت بگیرد. عدد مطلق، مهم‌تر از نسبت است وقتی دارید پیکربندی می‌کنید.

ابزارتعداد درخواستتأییدنرخ تأییدنقش
خواندن فایل۹۹۱۰۰٪بی‌خطر
نوشتن فایل۴۴۱۰۰٪قابل بازبینی
جست‌وجوی متن۲۲۱۰۰٪بی‌خطر
فهرست پوشه۲۲۱۰۰٪بی‌خطر
اجرای دستور۵۳۶۰٪گلوگاه

این جدول، پیکربندی شما را می‌نویسد. چهار ابزار اول، صد درصد گذشتند، پس بازبینی روی آن‌ها فقط وقت شما را می‌گیرد و هیچ سودی ندارد. تنها جایی که بازبینی ارزش دارد، اجرای دستور است.

ستون آخر یک نکته‌ی مهم‌تر را هم می‌گوید: از پنج اجرای دستور، دو تا رد شد. یعنی بازبینی واقعاً کار می‌کرد و فقط تشریفات نبود. اگر هر پنج تا گذشته بودند، لایه‌ی شما یا خیلی سهل‌گیر بود یا اصلاً تصمیم نمی‌گرفت.

تلاش مجدد و آنچه هزینه می‌برد

هر بار که یک درخواست به بازبین می‌رود، یعنی یک نوبت کامل به مدل دیگری. در نشستی که بازبینی روی هر ابزاری باشد، این هزینه را ده‌ها بار پرداخت می‌کنید، برای تصمیم‌هایی که از قبل می‌دانید چه می‌شوند.

در همان اسکریپت، اگر بازبینی روی خواندن فایل هم بود، ۹ درخواست خواندن هم هر کدام یک نوبت کامل بازبینی می‌شدند. با همان زمان سیصد و چهل میلی‌ثانیه، یعنی بیش از سه ثانیه تأخیر اضافه در یک نشست کوتاه، فقط برای کاری که هیچ‌وقت رد نمی‌شد.

# شمردن هزینه‌ی یک پیکربندی اشتباه، روی همان داده
s = led.summary()
reviewed = sum(1 for r in led.rows if r.latency_ms)
print(f"بازبینی روی همه‌ی ابزارها: {reviewed} نوبت اضافه")
print(f"بازبینی فقط روی اجرای دستور: "
      f"{sum(1 for r in led.rows if r.latency_ms and r.tool == 'bash')} نوبت")

خروجی: بیست و دو نوبت اضافه در حالت اول، در برابر پنج نوبت در حالت دوم. چهار برابر، برای دو درخواستی که بازبینی هرگز رد نکرد.

همین منطق در نوشته‌ی توکن و پنجره‌ی زمینه هم دیده می‌شود. بازبینی خودکار یک نشستِ جدا با پنجره‌ی زمینه‌ی خودش است و هر نوبتش صورتحساب جداگانه دارد. هزینه‌اش را وقتی می‌بینید که تعداد نوبت‌هایش را بشمارید. همین‌جا هم هارنس خودش عدد می‌دهد: صفحه‌ی سنجش هزینه سهم همیشگی هر افزونه را از هزینه‌ی هر نشست جدا می‌کند.

یک نکته‌ی دیگر هم هست که در عددها دیده نمی‌شود ولی هزینه دارد: زمان بازبینی، زمانِ انتظارِ شماست، نه زمانِ ماشین. اگر بازبینی سیصد و چهل میلی‌ثانیه طول بکشد و ده بار در یک کار تکرار شود، سه و نیم ثانیه فقط نگاه‌کردن به صفحه است. این را هیچ داشبوردی به شما نمی‌گوید.

راه‌حل این نیست که بازبینی را سریع‌تر کنید، مگر آنکه بتوانید. راه‌حل این است که تعداد دفعه‌ای را که به آن می‌رسد کم کنید. و این دقیقاً همان کاری است که ستون آخر جدول به شما می‌گوید.

پیشنهاد عملی: بازبینی را فقط روی اجرای دستور بگذارید و برای بقیه، یک فهرست مجاز صریح بنویسید. این فهرست، قاعده‌ی ثابت است و برخلاف بازبینی، هزینه‌ای ندارد. جایی که قاعده‌ی ثابت کافی است، بازبینی نکنید. همین قاعده‌ی ثابت است که فایل تنظیمات کلاد کد نگه می‌دارد.

جمع‌بندی: نرخ تأیید خودکار به شما می‌گوید لایه سفت است یا شل، زمان بازبینی به شما می‌گوید کجا قابل تحمل است، و ستون آخر جدول به شما می‌گوید بازبینی را کجا بگذارید. بیشتر پیکربندی‌های لایه‌ی مجوز، بازبینی را روی همه‌چیز می‌گذارند و بعد از چند روز کند شدنش را به حساب مدل می‌اندازند.

منابع

  1. صفحه‌ی انتشارهای dscode — نسخه‌ی ۰٫۷٫۳۲ و تاریخ انتشار آن
  2. مستند تأیید خودکار — دامنه، هزینه و محدودیت‌ها
  3. مستند حالت exec — قرارداد خروجی و کد خروج
  4. مخزن DeepSeek Harness — هارنسی که این پروژه رویش ساخته شده
  5. راهنمای ارزیابی افزونه — اجرای هر حالت در نشست جدا و مقایسه‌ی دو بازو
  6. صفحه‌ی سنجش هزینه — سهم همیشگی هر افزونه در هر نشست
  7. فایل تنظیمات کلاد کد — قاعده‌های ثابت مجوز و دامنه‌ی اثرشان
  8. نوشته‌ی بازبینی dscode از همین مجموعه — معماری سه قابلیت و جایگاه بازبین در آن
  9. نوشته‌ی توکن و پنجره‌ی زمینه از همین مجموعه — چرا هر نوبت بازبینی توکن می‌برد
  10. نوشته‌ی توقف واقعی برای گرفتن تایید از همین مجموعه — جایی که تصمیم انسانی وارد می‌شود