Дешевая классификация публичного текста через Jev (OpenRouter) и advisory-оценка уровня исполнителя по явно разрешенному публичному описанию задачи. Для пакетного предфильтра и необязательной рекомендации cheap/standard/deep/clarify; не для разбора, гейта, автосмены исполнителя или текстов с ПД.
Installs into .claude/skills of the current project.
Are you the author of Jev Decide?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/dewil-jev-decide)
---
name: jev-decide
description: 'Дешевая классификация публичного текста через Jev (OpenRouter) и advisory-оценка уровня исполнителя по явно разрешенному публичному описанию задачи. Для пакетного предфильтра и необязательной рекомендации cheap/standard/deep/clarify; не для разбора, гейта, автосмены исполнителя или текстов с ПД.'
---
# Jev: классификация текста по вопросам
Jev (TypeSafe AI, модель `~typesafe/jev-latest` на OpenRouter) текст не пишет. На вход - текст и набор вопросов, на выход - ответ на каждый вопрос в заданной форме с вероятностями: `noul` (да/нет, тип так и называется), `choice` (вариант из списка с критериями), `score` (ступень шкалы). Доли цента на пачку, около полусекунды на текст, форма ответа фиксирована и не требует разбора свободного текста.
## Когда брать
Много однотипных публичных текстов (вакансии, объявления, заголовки задач, карточки товаров), и нужно отсеять явно лишнее до дорогого шага - разбора моделью или человеком.
## Когда НЕ брать
- **Текст с персональными данными или закрытый материал.** Сервис зарубежный. `pii-mask` здесь не выход: у Jev нет режима работы с метками, а замаскированный текст теряет признаки, по которым классифицируют. Материал, который нельзя вывозить из РФ, - `llm-ru`.
- **Нужен разбор, аргументация, ревью** - Jev отвечает только в заданной форме.
- **Гейт решения.** Результат - предфильтр, окончательное решение за тем, кто разбирает дальше.
## Порядок
1. **Текст публичный и без персональных данных** - проверка до всего остального. Есть ПД или закрытый материал - скилл не применяется (см. "Когда НЕ брать").
2. **Ключ** - `OPENROUTER_API_KEY` или `~/.config/openrouter/key` с правами 600: файл с правами шире скрипт не читает. В чат, артефакты и коммиты ключ не выводить (`secrets-handling.md`); в выводе скрипта он маскируется.
3. **Вопросы** - JSON-файл в проекте, `<проект>/scripts/jev/<тема>-questions.json`: объект `{имя: {type, instructions, criteria}}`. Вопросы пишутся под причины отсева, которые реально встречаются в этом потоке: предел качества задает набор вопросов. Замер, из которого пришел скилл (26 вакансий): правило по двум вопросам отсекло 10 из 16 отсеянных без потери подходящих, а остальные 6 отсеивались по причинам, которых в вопросах не было. Вопрос типа `choice` с размытыми вариантами дал уверенность 0,3-0,6 - на такой не опираться.
4. **Порог калибруется** на выборке с уже вынесенным вердиктом (прошедшие и отсеянные) и проверяется на следующих двух-трех пачках, прежде чем встраивать его в автоматику. Порог, подобранный на той же выборке, - замер: статистикой он станет на новых пачках. Ошибка "потеряли подходящее" дороже "пропустили лишнее": при сомнении порог мягче.
5. **Вызов:**
```bash
python3 scripts/jev-decide.py --questions <вопросы.json> --state-file <текст>
```
Текст можно подать на stdin. Вывод в stdout - ответ сервиса с маскировкой ключа, учетных данных прокси и строк вида `Bearer <токен>` в ключах и значениях JSON. Если маскировка меняет обязательное поле или ответ, скрипт возвращает код 3: по виду строки нельзя надежно отличить токен от обычного варианта вроде `Bearer rights`. Если ответ распознан как JSON, выводится JSON; иначе выводится сырой текст. Значение по типу лежит в `answers.<имя>.noul` (вероятность "да", 0-1), `answers.<имя>.score` (ожидаемая ступень шкалы, дробное), `answers.<имя>.choice` (вариант); у `choice` и `score` рядом `probabilities` и `confidence` (сверено на ответах модели `typesafe/jev-1.13-20260917` 25.09.2026). Промпт, разбирающий вывод, берет значения оттуда: свой разбор JSON в каждом промпте расходится.
**Прокси.** Порядок: `--proxy`, `JEV_PROXY`, `HTTPS_PROXY`/`https_proxy`. Источник печатается в stderr строкой `прокси: <источник>` (адрес не печатается) - по ней видно, что cron взял прокси. Cron не видит `HTTPS_PROXY` из профиля - в автоматике передавай `--proxy` или `JEV_PROXY` явно, иначе 403 от Cloudflare на каждом вызове.
6. **Код возврата проверяется всегда.** `0` - на каждый вопрос пригодный ответ по схеме, сохраненный после маскировки; `1` - сеть, HTTP, ключ, вход, ответ дольше 90 с; `3` - ответ пришел, но не на каждый вопрос (нет ответа, ответ не того типа, вариант не из критериев), формат не распознан или маскировка изменила обязательное поле либо ответ. На коде 3 ответ все равно печатается: JSON, если его удалось разобрать, или сырой текст при не-JSON ответе. Посмотреть его глазами, чтобы понять причину, но в отбор результат не брать. Частичный ответ, пропущенный в отбор, молча отсеет по отсутствующему признаку (`silent-failure.md`).
## Встраивание в автоматику - сначала теневой режим
Калибровка на выборке (шаг 4) дает порог, но не право отсеивать им в автоматике. Порядок перехода:
1. **Сначала только отметка.** Jev ставит вердикт рядом с решением основного конвейера (модель или человек) на каждом тексте, отсев по нему не делается.
2. **Главная метрика теневого режима** - сколько текстов, прошедших основной конвейер, Jev отсеял бы: потеря подходящего дороже пропуска лишнего. Вторая - доля совпадений.
3. **К отсеву по Jev** переходят после двух-трех прогонов подряд с нулем по главной метрике. Порог с калибровочной выборки на этих прогонах не подкручивается: подкрученный под проверку порог проверкой уже не является.
4. **Сбой Jev** (код 1 или 3) в автоматике - строка в отчете прогона и продолжение без него. Прогон из-за Jev не останавливается, и сбой не превращается в "Jev ничего не отсеял".
## Advisory: уровень исполнителя для одной задачи
Это отдельный необязательный режим внутри сессии. Jev сообщает только `cheap`, `standard`, `deep` или `clarify`; после этого локальная политика клиента может показать кандидата по точному mapping. Jev не выбирает вендора или конкретную модель и не запускает исполнителя. Обычная пакетная классификация выше сохраняет прежний порядок.
1. Используй только если пользователь явно разрешил отправить короткое описание задачи, которое он сам указал как публичное, не содержащее ПД и не закрытое. Не извлекай описание из файла задачи, памяти, кода, переписки или истории и не отправляй полученное из них резюме. Если допустимого описания нет, сеть не вызывай: локально запиши `unavailable — no explicitly approved public description`.
2. Передай только это описание через поддержанный stdin или `--state-file` вход существующего helper:
```bash
python3 scripts/jev-decide.py --questions scripts/jev-executor-questions.json
```
На stdin подается только явно разрешенное описание. Не передавай туда задачу целиком, память или другой контекст.
3. Всегда проверяй код выхода. Только `0` дает пригодный ответ. Для кодов `1` и `3` запиши рекомендацию как `unavailable` с кодом и безопасной краткой причиной; не разбирай и не сохраняй частичный/raw вывод. Продолжай текущим исполнителем. Ошибка никогда не означает `cheap`, пустой успешный результат или нулевую уверенность.
4. Рекомендация остается советом. Явный выбор пользователем provider/model/effort имеет приоритет. Локально отметь риск данных, ключей, доступа/прав или production/release; при таком риске `cheap` не поддерживает снижение уровня. При любом из этих рисков либо `clarify` нужен ручной разбор. Не выводи риск из ключевых слов и не используй confidence как порог допуска. Даже без отмеченного риска tier не разрешает автоматическое переключение или запуск исполнителя; для предложения кандидата применяй локальный mapping и ожидание подтверждения.
5. Немедленно добавь короткую запись в существующую Markdown-задачу, чтобы следующая сессия восстановила статус без повторного вызова. Сохрани дату, `mode: advisory`, статус/tier, модель Jev, SHA-256 вопроса, confidence, длительность, сообщенную стоимость или `unknown`, исходные provider/model/effort или `unknown`. Helper гарантирует пригодность tier только для кода `0`; если ответ не содержит модель, confidence или стоимость, укажи `unknown`, не угадывай и не считай такие поля обязательными. Длительность измерь локально. При skip/failure запиши `unavailable`, безопасную краткую причину и код при наличии, сохранив исходного исполнителя. Не включай описание на входе, сырой ответ, stderr, ключи или другие секреты. Если пользователь уже выбрал исполнителя, receipt фиксирует этот выбор и рекомендация его не меняет.
### Локальное предложение кандидата по tier
После пригодного ответа Jev с кодом `0` можно сопоставить `cheap`, `standard` или `deep` только с точной записью из раздела «Пул исполнителей» текущего клиентского `.AI/project.md`. Этот раздел является единственным источником approved pool и tier mapping для клиента. Прочитай provider, model, допустимые роли/инструменты, effort и availability отдельно; не выводи их из frontmatter skill, старого профиля, alias, кэша или памяти. Для конкретного проекта допустим собственный mapping.
Считай модель кандидатом лишь когда mapping однозначен, provider/model явно включены в пул, и нет известного исключения. Состояния `excluded` и `paused` запрещают предложение и запуск даже при оставшемся конфиге или профиле. `unknown`, настроенная модель, каталог или прежний успех не подтверждают текущую доступность, квоту, нужные права и совместимость инструментов: обозначай результат только как «кандидат, доступность не подтверждена», с `availability: unknown`. Статус `availability: confirmed` допустим только при свежем явном подтверждении для этого provider/model и этой роли; сохраняй его источник и время/дату. Известный свежий отказ auth/quota означает `proposed: none` для запуска до нового разрешенного подтверждения. Самостоятельно не делай ping, пробный вызов или запуск.
Явный текущий выбор пользователя provider/model/effort всегда главнее tier. Покажи tier как справочную оценку, сохрани выбранного исполнителя и не предлагай заменить его. Не переключай и не запускай исполнителя. Если раздел пула или точная строка mapping отсутствует, неполна, содержит конфликт либо двусмысленность, не восстанавливай решение по другим источникам: оставь текущего исполнителя, зафиксируй tier и безопасную причину, `proposed: none`. Не предлагай candidate при `clarify`, отмеченном риске данных/секретов, ключей, доступа/прав или production/release, а также при коде Jev `1`/`3`; сохрани текущего исполнителя и причину для ручного разбора. `cheap` и confidence не оправдывают понижение при риске или неопределенности.
Переноси effort только из явного выбора пользователя, применимой разрешенной роли или существующей настройки. Если источника нет или он не задает значение, пиши `unknown`; не придумывай CLI-флаги. Для альтернатив без точного tier mapping не назначай tier по имени. Для SDD-пары author/reviewer выбирай только разрешенных кандидатов с нужной совместимостью и подтвержденными правами; их фактические модели должны быть различны. Разные роли, профили, CLI-алиасы или имена не доказывают различие actual model. Если actual model, права или наличие допустимой distinct pair неизвестны, candidate для этой роли не утверждай.
Дополняй существующую Markdown-задачу durable receipt: Jev tier/status и причина; `proposed provider/model` либо `none`; effective effort либо `unknown`; ссылка/идентификатор секции и записи mapping; availability status, источник и дата либо `unknown`; `confirmation: pending`; исходный provider/model/effort либо `unknown`; и явная отметка, что executor не запускался и не менялся. При отказе записывай `proposed: none` и безопасную причину. Не включай input, сырой ответ, stderr или секреты. Следующая сессия читает receipt и не повторяет вызов; `pending` не является согласием или подтверждением доступности.
Вопросы находятся в поставляемом `scripts/jev-executor-questions.json`; это байтово точная копия frozen-вопроса пилота. SHA-256: `b6fc89cde27e47a909978ae763a25e0d41b9fee65296c5b235b5a25e880ae5a5`.
Ниже приведено ограниченное синтетическое свидетельство, не сертификация качества: пилот 02.10.2026 проверил 16 вымышленных публичных задач; 12 ответов совпали с заранее зафиксированной меткой, 4 разошлись. Среди ошибок были потенциально небезопасные понижения для ключей, доступа и production/release. Автоматический выбор и понижение уровня по этому результату не допускаются.
Этот раздел описывает только внутрисессионный advisory. Control prelaunch hook/consumer здесь не реализован и не считается установленным; его подключение требует отдельной единицы работы.
## Границы
- **Эндпоинт `api/alpha/decisions` помечен у OpenRouter как alpha.** Формат может смениться без предупреждения. Скрипт сверяет каждый ответ по опубликованной схеме (справочник API OpenRouter, раздел alphadecisions, сверено 25.09.2026): `answers` - объект с ключами-именами вопросов, у ответа поле `type` и значение по нему - `noul` (вероятность 0..1), `choice` (вариант из критериев), `score` (число). Сменится схема - сработает код 3. Синтетический пилот с ключом 02.10.2026 проверил 16 ответов по frozen question set, но это не сертификация качества на рабочих задачах и не доказательство безопасности маршрутизации.
- В автоматике по расписанию код 3 и код 1 пишутся в лог отдельной строкой: в итоговом "обработано N текстов" они теряются.