Правила фильтрации команд
rtok run (а также rtok filter --stdin и переписывание Bash в PreToolUse, которое
вызывает rtok run) сокращает вывод команд по правилам для каждого семейства, прежде чем
его увидит модель. Сырой вывод всегда сначала архивируется, поэтому любой сокращённый
результат можно получить обратно через rtok expand <id> (без потерь по умолчанию, D4).
Правила никогда не вымарывают: строка с ошибкой, предупреждением или секретом проходит
без изменений.
Три уровня объединяются в таком порядке; для каждого семейства команд побеждает более поздний уровень:
- Встроенные —
rules/default.tomlв репозитории (grep, rg, sed, cat, make, curl, npm, pnpm, node, а также форматтеры cargo/git/test/tree в коде). - Пользовательский файл —
[plugins.cmd] rules(по умолчанию~/.rtok/rules.toml). - Дополнительные файлы (drop-ins) — каждый
*.tomlв[plugins.cmd] rules_dir(по умолчанию~/.rtok/rules.d/), объединяются в порядке имён файлов.
Отсутствующий файл или каталог не является ошибкой — этот уровень пропускается. Некорректный
файл пропускается во время работы (fail open), и о нём сообщает
rtok config validate, который называет каждый плохой файл.
Схема
Одна таблица TOML на семейство команд. Имя таблицы — первое слово команды
([grep], [pytest]); неизвестные семейства используют правило по умолчанию
(max_lines = 40, head = 10, tail = 10, дедупликация включена). Одно исключение: строка Bash,
которая связывает 2+ РАЗНЫЕ программы через &&, ; или перевод строки (T177), — это не вывод одного
семейства, поэтому она сопоставляется с [script]. Цепочка из одной и той же программы
(cargo build && cargo test или с ведущими cd/export) продолжает использовать собственный
форматтер/правило этой программы.
Тот же движок урезает результаты сторонних MCP-серверов за rtok mcp -- <server argv> (T59.4):
раздел [mcp] — это правило для текстового блока tools/call каждого обёрнутого сервера, а если его нет,
используется правило по умолчанию. Затрагиваются только текстовые блоки длиннее max_lines в результате без isError;
сырой блок сначала архивируется, а урезанный заканчивается тем же
трейлером [rtok <id> · N lines · expand: rtok expand <id>], что печатает rtok run. Экономия
записывается как измерение cmd / wrap с ref_id = <server>/<tool>:<id>.
| Поле | Тип | По умолчанию | Значение |
|---|---|---|---|
max_lines | целое ≥ 0 | 40 | предел строк вывода; остальное превращается в одну строку … N lines omitted (expand <id>) |
head | целое ≥ 0 | 10 | строки, всегда сохраняемые с начала |
tail | целое ≥ 0 | 10 | строки, всегда сохраняемые с конца |
drop | массив строк | [] | подстроки без учёта регистра, которые удаляются (| разделяет альтернативы) |
keep | массив строк | [] | подстроки, которые никогда не удаляются и никогда не обрезаются пределом; встроенные keep — error, warning, panic, fail, traceback |
dedupe | bool или "normalized" | true | true сворачивает соседние одинаковые строки в line (×N); "normalized" сравнивает строки, заменив метки времени, id, pid и длительности заполнителями, и сворачивает несоседние совпадения в line (×N, also lines k, l, …) |
group | "dir" | "diag" | выкл. | dir переписывает вывод «путь на строку» как dir/ (N files): a, b, c …; diag переписывает диагностики с кодами как E0308 ×N: first message (file:line, …); выполняется до обрезки head/tail (T64.1) |
json_items | целое ≥ 0 | 20 | массивы JSON сохраняют столько элементов; остальное — одна строка … +K more (T65.2) |
json_string | целое ≥ 0 | 200 | строки JSON длиннее этого обрезаются с указанием их длины в символах (T65.2) |
Любое другое поле, неверный тип или сломанный TOML считаются некорректными. При ненулевом коде выхода
всё это игнорируется: последние [plugins.cmd] fail_tail_lines строк (по умолчанию
80) печатаются дословно, потому что ошибка упавшей команды и есть полезные данные.
Разобранный пример
~/.rtok/rules.d/pytest.toml — сводит тихие прогоны pytest к указателю, но никогда
не теряет падение:
[pytest]
max_lines = 30
head = 5
tail = 15
drop = ["PASSED", "passed"]
keep = ["FAILED|failed|ERROR|error"]
dedupe = true
До (212 строк точек и прохождений) и после (12 строк):
tests/test_auth.py::test_login PASSED
tests/test_auth.py::test_refresh FAILED
… 200 lines omitted (expand abc123)
E assert False is True
Проверьте его, прежде чем на него полагаться:
rtok config validate # называет файлы rules.d/*.toml, которые не разбираются
validate проверяет файл, указанный в командной строке (или пользовательскую конфигурацию),
плюс единственный файл rules и каждый rules.d/*.toml, к которым он приводит.
Файл, о котором сообщено, пропускается во время работы, пока его не исправят; всё остальное продолжает
фильтровать.
Семейства (T50.1)
Измерено на golden-фикстурах в tests/cmd_golden/ (rtok filter --stdin, Rule против
Rule::default() на одном и том же теле; оценка токенов = байты/4).
| Семейство | Основные keep | до, Б | после, Б | оценка экономии |
|---|---|---|---|---|
gh | error, HTTP 4, gh: | 325 | 277 | 12 |
pip | ERROR, Could not | 389 | 341 | 12 |
uv | error, Failed | 292 | 244 | 12 |
python / python3 | Traceback, Error | 367 | 299 | 17 |
go | error, panic, cannot | 290 | 242 | 12 |
aws | An error occurred, AccessDenied | 349 | 301 | 12 |
mvn | BUILD FAILURE, [ERROR] | 419 | 395 | 6 |
gradle | BUILD FAILED, What went wrong | 357 | 302 | 13 |
dotnet | error CS, Build FAILED | 285 | 237 | 12 |
tsc | error TS, Found N error | 373 | 325 | 12 |
eslint | error, warning, problems | 298 | 250 | 12 |
brew | Error:, failed | 310 | 262 | 12 |
apt | ^E:, Unable to | 293 | 245 | 12 |
cmake | CMake Error, FAILED | 317 | 255 | 15 |
Форматтеры (T58.5)
Измерено на тех же golden-телах (formatters::compress, Measurement.kind = formatter
против Rule::default() на той же фикстуре; оценка токенов = байты/4). Каждый форматтер сохраняет одну
строку на объект и возвращает None для нераспознанного вывода, чтобы запасным вариантом оставался путь правил.
| Семейство | сохраняет | до, Б | после правила, Б | после форматтера, Б | оценка экономии относительно правила |
|---|---|---|---|---|---|
docker ps | одна строка на контейнер | 3147 | 1311 | 1190 | 30 |
kubectl get | одна строка на объект (NAME READY STATUS IP) | 4542 | 1770 | 1731 | 9 |
ps aux | одна строка на процесс | 2341 | 990 | 870 | 30 |
Группировка (T64.1)
Измерено на golden-фикстурах в tests/cmd_golden/ (formatters::compress со
встроенным правилом против того же правила с выключенным group; оценка токенов = байты/4). Для семейства
группировка включается, только если сгруппированное тело меньше. tree, git status, pytest и
python остаются как есть: псевдографика tree и форматтеры git/pytest не являются потоками «путь на строку»
или диагностик с кодами, а traceback python из T50.1 не уменьшается в виде NameError ×1.
| Семейство | group | без группировки, Б | с группировкой, Б | оценка экономии |
|---|---|---|---|---|
ls | dir | 248 | 49 | 49 |
find | dir | 539 | 83 | 114 |
rg (-l) | dir | 459 | 83 | 94 |
tsc | diag | 1619 | 107 | 378 |
eslint | diag | 749 | 48 | 175 |
cargo (check) | diag | 749 | 34 | 178 |
dotnet | diag | 849 | 71 | 194 |
JSON (T65.2)
Тело, которое serde_json разбирает как объект или массив, переписывается после группировки и
до обрезки head/tail: поля с null / пустой строкой / пустым контейнером удаляются, элементы массивов
сверх json_items показываются как … +K more, ключи объектов сохраняются, строки длиннее
json_string обрезаются с указанием их длины, по одной строке на ключ верхнего уровня. Тела, которые не разбираются,
не трогаются. Табличные форматтеры (kubectl get, docker ps) отступают, когда тело — JSON,
чтобы kubectl get -o json дошёл до этого прохода. toon остаётся вне пути хуков. Сырые байты остаются
в архиве; сокращённый результат по-прежнему несёт трейлер expand.
Измерено на tests/cmd_golden/{gh,aws,kubectl}_json.in (formatters::compress против
обрезки head/tail того же отформатированного тела; оценка токенов = байты/4).
| Источник | сырой, Б | обрезка по строкам, Б | компактный, Б | оценка экономии относительно сырого |
|---|---|---|---|---|
gh pr list --json | 10275 | 908 | 4530 | 1436 |
aws ec2 describe-instances | 19516 | 519 | 5890 | 3406 |
kubectl get pods -o json | 26271 | 353 | 8297 | 4493 |