Кеш промптів

From docs/uk/prompt-cache.md at cc732c3 View on GitHub

Чи ламає rtok кеш промптів?

Ні — це виміряно, а не обіцяно. rtok stats на цій машині (2026-09-18) показує hit=97.5% — 5 620 803 600 токенів читання з кешу проти 145 402 240 токенів створення кешу і 667 038 некешованих вхідних токенів за 910 сесій, — а розділ Cache у rtok report на ту саму дату не має жодного рядка про скидання кешу в усьому журналі обліку: нуль зафіксованих скидань кешу промптів. Причина структурна, для кожного інтерфейсу нижче: побайтово стабільне вставлення, переписування поза робочим краєм розмови і хуки, які торкаються кожного результату один раз. Відтворіть обидва числа:

rtok stats 2>/dev/null | head -4
rtok report 2>/dev/null | sed -n '/[Cc]ache/,+6p'

Хуки — фільтрування один раз, далі байтами володіє хост

cmd і read працюють на PreToolUse, до виклику: вивід скорочується один раз, і хост зберігає цей текст у своєму транскрипті. Кожен наступний хід повторює власні збережені байти хоста — rtok уже не бере участі, тож ніщо з того, чого він торкався, між ходами не змінюється. Та сама логіка, що й в аргументі rtk щодо кешу, плюс архів: усе, що вирізано, можна отримати, а байти, що лишаються, незмінні протягом усієї сесії.

inject — побайтово стабільний на кожному ході

Вставлення SessionStart обчислюється заново на кожному ході, тож воно лишається в кешованому префіксі, лише якщо байти ніколи не зсуваються. І вони не зсуваються: два запуски з незміненим станом дають ідентичний вивід, що закріплено тестом three_500_budget_800_drops_one_and_is_byte_stable (src/plugins/inject/mod.rs), а session_start_has_nudges_once_and_stable покриває шлях підказок (nudge). Будь-що в inject, що залежить від часу чи лічильників, — це баг за власним інваріантом плагіна, а не компроміс.

archive / proxy — переписування лише поза keep_turns, побайтово ідентичні вказівники

Фільтр archive на боці проксі переписує результат інструмента у вказівник на архів, лише коли хід старший за archive.keep_turns; system, tools і найновіші ходи ніколи не змінюються, тож робочий край — частина, яку провайдер ще записує в кеш, — лишається недоторканим. Два тести в src/plugins/archive/mod.rs закріплюють стабільність: six_turn_fixtures_archive_only_turns_1_and_2_on_every_wire (із шести ходів переписуються лише 1–2, для кожного формату протоколу) і live_blobs_shrink_stably_outside_the_working_edge (вказівник переписаного блоку побайтово ідентичний, коли його переписують знову).

Виміряно на цій машині, 2026-09-18 — mise exec -- cargo run --quiet -- stats 2>/dev/null | head -4:

sessions 910  lines 433211  malformed 0
usage input=667038 cache_create=145402240 cache_read=5620803600 output=27472613  hit=97.5%  median_context=63829
api                         input cache_create cache_read output    hit
codex                    12370533            0  243051392 671350  95.2%

і mise exec -- cargo run --quiet -- report 2>/dev/null | sed -n '/[Cc]ache/,+6p':

## Cache

Prompt-cache busts by cause, from the proxy's `usage` rows (whole ledger).

No rows in window.

Це весь журнал обліку, зібраний проксі: попри те, що archive переписує старіші результати інструментів у трафіку, жодного скидання кешу ніколи не зафіксовано, а частка влучань становить 97.5% (95.2% для api codex, яке повідомляє 0 токенів створення кешу).

По смугах — частка влучань і replay-тест

Коли проксі обслужив трафік поза смугою agent (bulk, internal, …), rtok stats додає поруч з api таблицю lane з тими самими лічильниками та часткою влучань у кеш промпту для кожної смуги (lanes у --json). Сховище лише з ходами агента такої таблиці не друкує. Стабільність смуги agent закріплена тестом tests/proxy_cache_replay.rs: він програє одну зростаючу розмову через проксі з усіма ввімкненими переписуваннями й перевіряє, що tools, system і кожне повідомлення до живого краю попереднього ходу доходять до upstream побайтно однаковими.

guard — відмови не додають байтів

Відмова guard — це рішення PreToolUse, а не вміст: вона блокує повторний виклик із фіксованою однорядковою причиною duplicate; rtok expand <id> і не додає байтів результату інструмента до жодного ходу. За результат, у якому вона відмовляє, уже заплатили один раз, і його можна отримати за цим id, тож модель ніколи не платить за другу копію, — а транскрипт, який вона повторює, лишається незмінним, що й потрібно для кешу.

Збереження без втрат не коштує кешу

Усе описане вище скорочує байти; ніщо їх не втрачає. Кожні скорочені дані архівуються до вирізання, а expand <id> відновлює оригінал (--lines, --grep). Вказівник у транскрипті побайтово стабільний, тож можливість отримати дані ніколи не переписує префікс: кеш зберігає свої влучання, а ви — повний текст.

Sticky-маршрутизація проти Batch / Flex

Влучання в кеш промптів провайдера потребують стабільного байтового префікса і, для upstream із кількома pod, прив'язки до того самого бекенду, що тримає кеш (I-84 / sticky-маршрутизація). Це ортогонально до Batch (асинхронний pass-through; жодного спільного живого KV сесії з інтерактивним агентом) і Flex (service_tier на тому самому синхронному протоколі — правила кешу діють і далі, знижка дається рівнем). rtok не перетворюватиме синхронний хід агента на завдання Batch лише заради економії; робіть це тільки з явним клієнтом Batch. Подробиці: batch-flex.md.

# Запланований прапорець sticky у [proxy.routing] (сьогодні не завантажується) — закріплює upstream для прив'язки кешу.
# Flex — це [proxy.flex]; спостереження за Batch — [proxy.batch]. Жоден із них не переписує кешовані
# байти system/tools/живого краю так, як це зробило б необережне стиснення.
[proxy.routing]
sticky = true