وقتی پاسخ‌گوی صوتی باید گفتگو را به کارشناس ارجاع دهد، یک جملهٔ «انتقال انجام شد» زمینهٔ کافی نمی‌سازد. لازم است بدانیم چه درخواستی مطرح بوده، کدام بخش تاریخچه همراه بسته است و دربارهٔ عمل قبلی چه چیزی هنوز نامعلوم مانده است. این درس یک بستهٔ کوچکِ کاملاً ساختگی و ماشین حالت محلی آن را آزمایش می‌کند؛ هیچ تماس، پیام یا دادهٔ مشتری به سامانه‌ای فرستاده نمی‌شود.

۱. تصمیم ارجاع با بستهٔ زمینه و رسید تحویل فرق دارد

جدایی تصمیم ارجاع از محتوای بستهٔ زمینه
تصویر مفهومی: جدایی تصمیم ارجاع از محتوای بستهٔ زمینه؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

مثال ما پروندهٔ فرضی Case7 با هدف «بررسی علت خطای ساختگی حسگر» است. علت ارجاع needs_expert انتخاب شده و وضعیت عمل قبلی unknown است. این متن، خلاصهٔ خودکار مدل زبانی یا گزارش تجربهٔ مشتری نیست؛ ورودی آزمایشیِ دست‌نویس است. حتی اگر مرحلهٔ تحویل محلی بعداً completed شود، وضعیت عمل قبلی بدون شاهد تازه همان unknown می‌ماند.

مستندات ارجاع Microsoft برای SDK v4 میان آغاز ارجاع و رویداد وضعیت تمایز می‌گذارد و امکان همراه‌کردن زمینه و رونوشت گفتگو را توضیح می‌دهد. از این تمایز برای صورت‌بندی مسئله استفاده می‌کنیم؛ قالب و ماشین حالتِ این درس، پیاده‌سازی آن SDK یا پروتکل انتقال تماس نیستند. تمام رویدادهای پذیرفته‌شدن و تکمیل را خود آزمون تولید می‌کند.

آستانهٔ ارجاع تماس به پرسش «چه وقت ارجاع بدهیم» می‌پردازد. اینجا آن تصمیم از قبل گرفته شده و مسئله «چه چیزی با ارجاع همراه باشد» است. مقصد، ظرفیت کارشناس، اعتبار هویت و دسترسی او در مدل حاضر بررسی نمی‌شوند؛ درست‌بودن قالب، مجوز انتقال اطلاعات را اثبات نمی‌کند.

۲. فیلدهای مجاز و وضعیت عمل را صریح نگه داریم

قرارداد صریح فیلدها و رد کلید ناشناخته
تصویر مفهومی: قرارداد صریح فیلدها و رد کلید ناشناخته؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

ورودی دقیقاً پنج فیلد case_id، reason، goal، action_state و history دارد. شناسه حداکثر شانزده نویسهٔ ASCII است و با حرف آغاز می‌شود. علت فقط یکی از نیاز به کارشناس، کمبود دانش یا درخواست کاربر است. وضعیت عمل یکی از none، in_progress، unknown و completed است. این برچسب، اظهار ورودی است و فایل برای واقعی‌بودن آن شاهدی جمع نمی‌کند.

goal رشته‌ای از یک تا نودوشش نقطهٔ کد است. هر نوبت تاریخچه دقیقاً شمارهٔ seq، نقش role و متن text دارد. نقش‌های ورودی از user آغاز می‌شوند و با assistant تناوب دارند؛ شماره‌ها صحیح، از صفر تا ۹۹۹۹ و اکیداً صعودی‌اند، اما لازم نیست پشت سر هم باشند. تاریخچهٔ ورودی حداکثر سی‌ودو نوبت و متن هر نوبت حداکثر صدوبیست نقطهٔ کد دارد.

راهنمای رسمی JSON Schema توضیح می‌دهد که تعریف properties به‌تنهایی حضور فیلدها یا ممنوعیت کلید اضافه را الزام نمی‌کند. کد ما با مقایسهٔ دقیق کلیدهای دیکشنری، قرارداد بستهٔ خود را اجرا می‌کند؛ موتور JSON Schema نصب یا اجرا نشده است. کلید ناشناخته، فیلد گم‌شده و نوع نادرست خطا می‌دهند؛ تبدیل خودکار یا دورریختن بی‌اعلان نداریم.

۳. کوتاه‌سازی تاریخچه باید قابل مشاهده باشد

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

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

در نمونه شش نوبت با شماره‌های صفر تا پنج داریم. سه نوبت اول حذف و شماره‌های سه، چهار و پنج نگه داشته می‌شوند. متن شمارهٔ سه، پنجاه‌ودو حرف A دارد؛ چهل‌وهشت حرف می‌ماند و چهار نقطهٔ کدِ حذف‌شده گزارش می‌شود. نقش‌های خروجی assistant، user و assistant باقی می‌مانند؛ برای اینکه ابتدای قطعه ظاهراً user باشد، نقش یا ترتیب را تغییر نمی‌دهیم.

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

۴. کد کامل، مرجع مستقل و حالت‌های تحویل محلی

آزمون ترتیب نقش‌ها و حالت تحویل محلی
تصویر مفهومی: آزمون ترتیب نقش‌ها و حالت تحویل محلی؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

فایل handoff_context_contract.py با Python 3.14.5 و کتابخانهٔ استاندارد اجرا شده است. مرجع مستقل از برش فهرست و پیمایش نویسه‌ها استفاده می‌کند، نه deque یا تابع آماده‌سازی اصلی. سی‌وشش ترکیبِ تعداد نوبت و طول متن در یک گروه بررسی می‌شوند. مجموع هجده گروه نام‌دار است؛ تکرار اجرا یا زیرحالت‌ها، بررسی جدید شمرده نمی‌شوند.

"""Bounded synthetic handoff envelope and local declared-status transitions.

No call transfer, network delivery, agent acknowledgement, PII detection or action.
"""
from collections import deque
from copy import deepcopy
import json
import platform
import re

REQUEST_KEYS = {'case_id', 'reason', 'goal', 'action_state', 'history'}
TURN_KEYS = {'seq', 'role', 'text'}
REASONS = ('needs_expert', 'missing_knowledge', 'user_request')
ACTION_STATES = ('none', 'in_progress', 'unknown', 'completed')
KEEP_TURNS, KEEP_TEXT = 3, 48


def valid_text(value, maximum):
    return (type(value) is str and 1 <= len(value) <= maximum
            and all(ord(c) >= 32 and ord(c) != 127
                    and not 0xD800 <= ord(c) <= 0xDFFF for c in value))


def prepare_context(request):
    if type(request) is not dict or set(request) != REQUEST_KEYS:
        raise ValueError('request_fields')
    case_id = request['case_id']
    if type(case_id) is not str or re.fullmatch(r'[A-Za-z][A-Za-z0-9_-]{0,15}', case_id, re.ASCII) is None:
        raise ValueError('case_id')
    if type(request['reason']) is not str or request['reason'] not in REASONS:
        raise ValueError('reason')
    if type(request['action_state']) is not str or request['action_state'] not in ACTION_STATES:
        raise ValueError('action_state')
    if not valid_text(request['goal'], 96):
        raise ValueError('goal')
    history = request['history']
    if type(history) is not list or len(history) > 32:
        raise ValueError('history')
    tail = deque(maxlen=KEEP_TURNS)
    previous = -1
    for index, turn in enumerate(history):
        if type(turn) is not dict or set(turn) != TURN_KEYS:
            raise ValueError('turn_fields')
        seq = turn['seq']
        if type(seq) is not int or not 0 <= seq <= 9999 or seq <= previous:
            raise ValueError('seq')
        if type(turn['role']) is not str or turn['role'] != ('user' if index % 2 == 0 else 'assistant'):
            raise ValueError('role_order')
        text = turn['text']
        if not valid_text(text, 120):
            raise ValueError('turn_text')
        tail.append({'seq': seq, 'role': turn['role'], 'text': text[:KEEP_TEXT],
                     'omitted_codepoints': max(0, len(text) - KEEP_TEXT)})
        previous = seq
    kept = list(tail)
    omitted_turns = max(0, len(history) - KEEP_TURNS)
    return {'schema': 'handoff_context_v1', 'case_id': case_id,
            'reason': request['reason'], 'goal': request['goal'],
            'action_state': request['action_state'], 'history': kept,
            'source_turn_count': len(history), 'omitted_turns': omitted_turns,
            'shortened': omitted_turns > 0 or any(t['omitted_codepoints'] > 0 for t in kept)}


def serialize_packet(packet):
    # This function encodes prepared packets; it is not a general JSON validator.
    raw = json.dumps(packet, ensure_ascii=False, sort_keys=True, separators=(',', ':')).encode('utf-8')
    if len(raw) > 2048:
        raise ValueError('packet_bytes')
    return raw


class LocalHandoff:
    def __init__(self, request):
        self._packet = prepare_context(request)
        self._phase = 'prepared'

    def snapshot(self):
        return {'phase': self._phase, 'packet': deepcopy(self._packet)}

    def offer(self):
        if self._phase != 'prepared':
            raise ValueError('transition')
        self._phase = 'offered'  # Local intent only, no send or receipt.

    def apply_declared_status(self, event):
        if type(event) is not dict or set(event) != {'case_id', 'state'}:
            raise ValueError('event_fields')
        if type(event['case_id']) is not str or event['case_id'] != self._packet['case_id']:
            raise ValueError('case_mismatch')
        if type(event['state']) is not str or event['state'] not in ('accepted', 'failed', 'completed'):
            raise ValueError('event_state')
        allowed = {'offered': ('accepted', 'failed'), 'accepted': ('completed', 'failed')}
        if event['state'] not in allowed.get(self._phase, ()):
            raise ValueError('transition')
        self._phase = event['state']


def valid_fixture(count=6, length=12):
    return {'case_id': 'Case7', 'reason': 'needs_expert',
            'goal': 'بررسی علت خطای ساختگی حسگر', 'action_state': 'unknown',
            'history': [{'seq': i, 'role': 'user' if i % 2 == 0 else 'assistant',
                         'text': 'A' * length} for i in range(count)]}


def slice_oracle(request):
    """Independent valid-domain list slicing and enumeration; no deque/prepare call."""
    rows = []
    start = max(0, len(request['history']) - 3)
    for index, turn in enumerate(request['history']):
        if index >= start:
            characters = list(turn['text'])
            rows.append({'seq': turn['seq'], 'role': turn['role'],
                         'text': ''.join(characters[i] for i in range(min(48, len(characters)))),
                         'omitted_codepoints': len(characters) - min(48, len(characters))})
    return rows, start


def rejected(call, message):
    try:
        call()
    except ValueError as error:
        return str(error) == message
    return False


def run_example():
    request = valid_fixture()
    request['history'][3]['text'] = 'A' * 52
    request['history'][4]['text'] = 'ب' * 12
    request['history'][5]['text'] = 'کارشناس لازم است'
    before = deepcopy(request)
    packet = prepare_context(request)
    raw = serialize_packet(packet)
    flow = LocalHandoff(request)
    initial = flow.snapshot()
    flow.offer()
    offered = flow.snapshot()
    wrong_case = rejected(lambda: flow.apply_declared_status({'case_id': 'Other', 'state': 'accepted'}), 'case_mismatch')
    wrong_case_unchanged = flow.snapshot() == offered
    flow.apply_declared_status({'case_id': 'Case7', 'state': 'accepted'})
    accepted = flow.snapshot()
    flow.apply_declared_status({'case_id': 'Case7', 'state': 'completed'})
    completed = flow.snapshot()
    failed = LocalHandoff(request)
    failed.offer()
    failed.apply_declared_status({'case_id': 'Case7', 'state': 'failed'})
    failed_snapshot = failed.snapshot()
    premature = LocalHandoff(request)
    premature_rejected = rejected(lambda: premature.apply_declared_status({'case_id': 'Case7', 'state': 'accepted'}), 'transition')
    premature.offer()
    completed_too_soon = rejected(lambda: premature.apply_declared_status({'case_id': 'Case7', 'state': 'completed'}), 'transition')
    missing = []
    for key in REQUEST_KEYS:
        r = valid_fixture()
        del r[key]
        missing.append(r)
    unknown_request = dict(request, phone='synthetic')
    unknown_turn = valid_fixture()
    unknown_turn['history'][0]['confidence'] = 0.9
    no_text = valid_fixture()
    del no_text['history'][0]['text']
    bad_roles = valid_fixture()
    bad_roles['history'][1]['role'] = 'user'
    bad_order = valid_fixture()
    bad_order['history'][2]['seq'] = 1
    bad_seq = valid_fixture()
    bad_seq['history'][0]['seq'] = True
    invalid_texts = ['', 'a' * 121, 'x\ny', '\ud800', 42]
    texts_rejected = []
    for text in invalid_texts:
        r = valid_fixture()
        r['history'][0]['text'] = text
        texts_rejected.append(rejected(lambda r=r: prepare_context(r), 'turn_text'))
    unicode_request = valid_fixture(1)
    unicode_request['history'][0]['text'] = 'x' * 47 + 'e\u0301'
    unicode_packet = prepare_context(unicode_request)
    explicit_text = valid_fixture(1)
    explicit_text['goal'] = 'شمارهٔ ساختگی 555123'
    explicit_text['history'][0]['text'] = 'نیم\u200cفاصله'
    explicit_packet = prepare_context(explicit_text)
    upper = valid_fixture(32, 120)
    upper['case_id'] = 'A' * 16
    upper['goal'] = chr(0x10000) * 96
    for index, turn in enumerate(upper['history']):
        turn['seq'] = 9900 + index
        turn['text'] = chr(0x10000) * 120
    upper_packet = prepare_context(upper)
    upper_bytes = len(serialize_packet(upper_packet))
    changed_snapshot = flow.snapshot()
    changed_snapshot['packet']['history'][0]['text'] = 'changed'
    request['history'][3]['text'] = 'changed'
    isolated = flow.snapshot() == completed
    request = deepcopy(before)
    oracle_cases, oracle_ok = 0, True
    for count in range(9):
        for length in (1, 48, 49, 120):
            sample = valid_fixture(count, length)
            observed = prepare_context(sample)
            expected_rows, expected_omitted = slice_oracle(sample)
            oracle_ok &= (observed['history'] == expected_rows and observed['omitted_turns'] == expected_omitted
                          and observed['source_turn_count'] == count
                          and observed['shortened'] == (count > 3 or (count > 0 and length > 48)))
            oracle_cases += 1
    checks = {
      'hand_tail_keeps_sequences_three_four_five': [t['seq'] for t in packet['history']] == [3, 4, 5] and packet['omitted_turns'] == 3 and packet['source_turn_count'] == 6,
      'hand_text_prefix_and_omitted_codepoints': packet['history'][0]['text'] == 'A' * 48 and packet['history'][0]['omitted_codepoints'] == 4 and packet['history'][1]['omitted_codepoints'] == 0 and packet['shortened'] is True,
      'recent_tail_keeps_original_roles_not_relabels': [t['role'] for t in packet['history']] == ['assistant', 'user', 'assistant'],
      'action_uncertainty_never_becomes_action_completion': all(s['packet']['action_state'] == 'unknown' for s in [initial, offered, accepted, completed]),
      'unknown_request_and_turn_fields_reject': rejected(lambda: prepare_context(unknown_request), 'request_fields') and rejected(lambda: prepare_context(unknown_turn), 'turn_fields'),
      'required_top_level_and_turn_fields_reject': all(rejected(lambda r=r: prepare_context(r), 'request_fields') for r in missing) and rejected(lambda: prepare_context(no_text), 'turn_fields'),
      'reason_and_action_state_enumerations_reject': rejected(lambda: prepare_context(dict(request, reason='other')), 'reason') and rejected(lambda: prepare_context(dict(request, action_state=True)), 'action_state'),
      'case_identifier_and_sequence_type_bounds': all(rejected(lambda value=value: prepare_context(dict(request, case_id=value)), 'case_id') for value in ['A' * 17, 'Case/7', True]) and rejected(lambda: prepare_context(bad_seq), 'seq'),
      'source_sequence_and_alternating_roles_enforced': rejected(lambda: prepare_context(bad_roles), 'role_order') and rejected(lambda: prepare_context(bad_order), 'seq'),
      'text_bound_control_surrogate_and_type_reject': all(texts_rejected) and rejected(lambda: prepare_context(dict(request, goal='g' * 97)), 'goal'),
      'source_history_count_and_list_type_bounds': len(prepare_context(valid_fixture(32))['history']) == 3 and rejected(lambda: prepare_context(valid_fixture(33)), 'history') and rejected(lambda: prepare_context(dict(request, history=())), 'history'),
      'codepoint_truncation_is_not_grapheme_or_privacy_filter': unicode_packet['history'][0]['text'] == 'x' * 47 + 'e' and unicode_packet['history'][0]['omitted_codepoints'] == 1 and explicit_packet['goal'] == explicit_text['goal'] and explicit_packet['history'][0]['text'] == 'نیم\u200cفاصله',
      'utf8_json_roundtrip_and_adversarial_size_fixture': json.loads(raw) == packet and len(raw) <= 2048 and upper_bytes <= 2048 and upper_packet['omitted_turns'] == 29,
      'prepared_packet_and_snapshots_are_isolated': request == before and isolated and prepare_context(request) == packet,
      'offered_is_only_local_intent_and_case_correlates': initial['phase'] == 'prepared' and offered['phase'] == 'offered' and wrong_case and wrong_case_unchanged,
      'legal_declared_success_and_failure_paths': accepted['phase'] == 'accepted' and completed['phase'] == 'completed' and failed_snapshot['phase'] == 'failed',
      'premature_terminal_duplicate_and_unknown_status_reject': premature_rejected and completed_too_soon and rejected(lambda: flow.offer(), 'transition') and rejected(lambda: flow.apply_declared_status({'case_id': 'Case7', 'state': 'accepted'}), 'transition') and rejected(lambda: failed.apply_declared_status({'case_id': 'Case7', 'state': 'accepted'}), 'transition') and rejected(lambda: premature.apply_declared_status({'case_id': 'Case7', 'state': 'sent'}), 'event_state') and rejected(lambda: premature.apply_declared_status({'case_id': 'Case7', 'state': 'accepted', 'extra': True}), 'event_fields') and flow.snapshot() == completed and failed.snapshot() == failed_snapshot,
      'independent_list_oracle_for_bounded_history': oracle_cases == 36 and bool(oracle_ok),
    }
    assert len(checks) == 18 and all(type(value) is bool and value for value in checks.values()), checks
    return {'python': platform.python_version(), 'dependencies': 'Python standard library only',
            'scope': 'Synthetic bounded context and declared local statuses only; no real identity, privacy guard, action or delivery acknowledgement',
            'results': {'prepared_packet': packet, 'serialized_bytes': len(raw),
                        'upper_bound_fixture_bytes': upper_bytes, 'byte_cap': 2048,
                        'declared_phase_timeline': [s['phase'] for s in [initial, offered, accepted, completed]],
                        'preserved_action_state': completed['packet']['action_state'],
                        'oracle_cases_inside_one_group': oracle_cases}, 'checks': checks}


if __name__ == '__main__':
    print(json.dumps(run_example(), ensure_ascii=False, indent=2))

شیء محلی ابتدا prepared است. فراخوانی offer فقط آن را offered می‌کند؛ هیچ ارسال شبکه‌ای انجام نمی‌دهد. سپس رویداد ساختگیِ دارای شناسهٔ مطابق می‌تواند accepted یا failed اعلام کند. پس از accepted، completed یا failed مجاز است. completed زودرس، شناسهٔ دیگر، وضعیت ناشناخته و تکرار پس از حالت پایانی رد می‌شوند و حالت قبلی باقی می‌ماند. این جدول، سیاست آموزشی ماست.

{
  "python": "3.14.5",
  "dependencies": "Python standard library only",
  "scope": "Synthetic bounded context and declared local statuses only; no real identity, privacy guard, action or delivery acknowledgement",
  "results": {
    "prepared_packet": {
      "schema": "handoff_context_v1",
      "case_id": "Case7",
      "reason": "needs_expert",
      "goal": "بررسی علت خطای ساختگی حسگر",
      "action_state": "unknown",
      "history": [
        {
          "seq": 3,
          "role": "assistant",
          "text": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "omitted_codepoints": 4
        },
        {
          "seq": 4,
          "role": "user",
          "text": "بببببببببببب",
          "omitted_codepoints": 0
        },
        {
          "seq": 5,
          "role": "assistant",
          "text": "کارشناس لازم است",
          "omitted_codepoints": 0
        }
      ],
      "source_turn_count": 6,
      "omitted_turns": 3,
      "shortened": true
    },
    "serialized_bytes": 508,
    "upper_bound_fixture_bytes": 1343,
    "byte_cap": 2048,
    "declared_phase_timeline": [
      "prepared",
      "offered",
      "accepted",
      "completed"
    ],
    "preserved_action_state": "unknown",
    "oracle_cases_inside_one_group": 36
  },
  "checks": {
    "hand_tail_keeps_sequences_three_four_five": true,
    "hand_text_prefix_and_omitted_codepoints": true,
    "recent_tail_keeps_original_roles_not_relabels": true,
    "action_uncertainty_never_becomes_action_completion": true,
    "unknown_request_and_turn_fields_reject": true,
    "required_top_level_and_turn_fields_reject": true,
    "reason_and_action_state_enumerations_reject": true,
    "case_identifier_and_sequence_type_bounds": true,
    "source_sequence_and_alternating_roles_enforced": true,
    "text_bound_control_surrogate_and_type_reject": true,
    "source_history_count_and_list_type_bounds": true,
    "codepoint_truncation_is_not_grapheme_or_privacy_filter": true,
    "utf8_json_roundtrip_and_adversarial_size_fixture": true,
    "prepared_packet_and_snapshots_are_isolated": true,
    "offered_is_only_local_intent_and_case_correlates": true,
    "legal_declared_success_and_failure_paths": true,
    "premature_terminal_duplicate_and_unknown_status_reject": true,
    "independent_list_oracle_for_bounded_history": true
  }
}

نمونهٔ آماده‌شده در قالب JSON فشردهٔ UTF-8، ۵۰۸ بایت است. سقف قراردادی خروجی ۲۰۴۸ بایت انتخاب شده و یک نمونه با طول‌های بیشینه و نقاط کد چهاربایتی، ۱۳۴۳ بایت دارد. این‌ها اندازهٔ بسته‌های آزمایش‌اند؛ سقف سرویس، توکن مدل یا اندازهٔ کل حافظه نیستند. کپی مستقلِ snapshot و مقایسهٔ ورودی نیز تغییر ناخواستهٔ تاریخچه یا بسته را بررسی می‌کنند.

۵. محدودیت متن و چهار پرسش پاسخ‌دار

مرز نمونهٔ آفلاین و انتقال واقعی به کارشناس
تصویر مفهومی: مرز نمونهٔ آفلاین و انتقال واقعی به کارشناس؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

رشتهٔ پایتون دنبالهٔ نقاط کد Unicode است. برش در چهل‌وهشتمین نقطهٔ کد ممکن است نویسهٔ ترکیبی را جدا کند؛ برای مثال e بماند و علامت ترکیبی بعدش حذف شود. حفظ واژه، خوشهٔ نوشتاری یا معنای جمله تضمین نشده است. کنترل‌های ASCII و surrogate رد می‌شوند، اما متن همچنان نیازمند بررسی مناسب کاربرد واقعی است.

پرسش اول: آیا completed در ماشین تحویل یعنی عمل قبلی انجام شده؟ پاسخ: خیر؛ مرحلهٔ تحویل و action_state جدا هستند. در تمام مراحل نمونه، وضعیت عمل unknown می‌ماند. completed نیز فقط رویداد اعلام‌شدهٔ ساختگی است و تأیید واقعی کارشناس نداریم.

پرسش دوم: چرا قطعهٔ کوتاه می‌تواند با assistant شروع شود؟ پاسخ: چون سه نوبت آخرِ تاریخچهٔ معتبر را نگه می‌داریم. نقش و شمارهٔ اصلی حفظ می‌شوند؛ تبدیل نقش برای زیباترشدن خروجی، شاهد گفتگو را تغییر می‌دهد.

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

پرسش چهارم: آیا offered اجازه می‌دهد به کاربر بگوییم کارشناس وصل شده؟ پاسخ: خیر؛ فقط قصد محلی ثبت شده است. ماشین حالت ورودی IVR نیز قرارداد جدا دارد. منابع در ۲۴ مهر ۱۴۰۵ خوانده شدند؛ صفحهٔ Microsoft به‌روزرسانی ۹ اکتبر ۲۰۲۴ دارد. این تمرین آفلاین، بدون خبر تازه یا ادعای انتقال موفق واقعی است.

منابع و مطالعهٔ بیشتر

بررسی منابع: ۲۴ مهر ۱۴۰۵. تحلیل‌ها و پیشنهادهای اجرایی، جمع‌بندی نویسنده‌اند.