Правила фильтрации команд

From docs/ru/cmd-rules.md at cc732c3 View on GitHub

rtok run (а также rtok filter --stdin и переписывание Bash в PreToolUse, которое вызывает rtok run) сокращает вывод команд по правилам для каждого семейства, прежде чем его увидит модель. Сырой вывод всегда сначала архивируется, поэтому любой сокращённый результат можно получить обратно через rtok expand <id> (без потерь по умолчанию, D4). Правила никогда не вымарывают: строка с ошибкой, предупреждением или секретом проходит без изменений.

Три уровня объединяются в таком порядке; для каждого семейства команд побеждает более поздний уровень:

  1. Встроенные — rules/default.toml в репозитории (grep, rg, sed, cat, make, curl, npm, pnpm, node, а также форматтеры cargo/git/test/tree в коде).
  2. Пользовательский файл — [plugins.cmd] rules (по умолчанию ~/.rtok/rules.toml).
  3. Дополнительные файлы (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целое ≥ 040предел строк вывода; остальное превращается в одну строку … N lines omitted (expand <id>)
headцелое ≥ 010строки, всегда сохраняемые с начала
tailцелое ≥ 010строки, всегда сохраняемые с конца
dropмассив строк[]подстроки без учёта регистра, которые удаляются (| разделяет альтернативы)
keepмассив строк[]подстроки, которые никогда не удаляются и никогда не обрезаются пределом; встроенные keep — error, warning, panic, fail, traceback
dedupebool или "normalized"truetrue сворачивает соседние одинаковые строки в 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целое ≥ 020массивы JSON сохраняют столько элементов; остальное — одна строка … +K more (T65.2)
json_stringцелое ≥ 0200строки 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до, Бпосле, Боценка экономии
gherror, HTTP 4, gh:32527712
pipERROR, Could not38934112
uverror, Failed29224412
python / python3Traceback, Error36729917
goerror, panic, cannot29024212
awsAn error occurred, AccessDenied34930112
mvnBUILD FAILURE, [ERROR]4193956
gradleBUILD FAILED, What went wrong35730213
dotneterror CS, Build FAILED28523712
tscerror TS, Found N error37332512
eslinterror, warning, problems29825012
brewError:, failed31026212
apt^E:, Unable to29324512
cmakeCMake Error, FAILED31725515

Форматтеры (T58.5)

Измерено на тех же golden-телах (formatters::compress, Measurement.kind = formatter против Rule::default() на той же фикстуре; оценка токенов = байты/4). Каждый форматтер сохраняет одну строку на объект и возвращает None для нераспознанного вывода, чтобы запасным вариантом оставался путь правил.

Семействосохраняетдо, Бпосле правила, Бпосле форматтера, Боценка экономии относительно правила
docker psодна строка на контейнер31471311119030
kubectl getодна строка на объект (NAME READY STATUS IP)4542177017319
ps auxодна строка на процесс234199087030

Группировка (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без группировки, Бс группировкой, Боценка экономии
lsdir2484949
finddir53983114
rg (-l)dir4598394
tscdiag1619107378
eslintdiag74948175
cargo (check)diag74934178
dotnetdiag84971194

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 --json1027590845301436
aws ec2 describe-instances1951651958903406
kubectl get pods -o json2627135382974493