# AGENTS.md

RU Direct генерирует списки российских подсетей и доменов для раздельного туннелирования в трёх уровнях и 25 форматах. Источник правды: `config/services/*.json`, `config/guard.json`, `config/exclude.txt` и код в `src/`. Всё в `dist/` и в ветке `release` собирается автоматически, руками не правится. Язык репозитория, комментариев и коммитов: русский.

## Карта репозитория

| Путь | Назначение |
| --- | --- |
| `src/main.ts` | Точка входа CLI: `update`, `generate`, `verify`, `check`, `tools` |
| `src/commands/` | Реализация команд, по файлу на команду |
| `src/services/build/` | Сборка уровней: зона страны, ASN сервисов, резолв, guard, лимиты |
| `src/services/formats/` | Генераторы форматов (`writers.ts`), geoip и geosite (`geodata.ts`), запись в `dist/` |
| `src/services/manifest/` | `manifest.json`, `SHA256SUMS`, `services.json`, заметки к релизу |
| `src/services/ripe/`, `dns/`, `zones/`, `guard/`, `tools/`, `cache/`, `config/`, `check/` | Клиенты внешних данных и проверки |
| `src/contracts/` | Константы: уровни, реестр форматов, источники, пути, HTTP, координаты репозитория |
| `src/helpers/cidr.ts` | Вся арифметика IPv4 и IPv6: парсинг, агрегация, вычитание, инверсия, индекс |
| `src/types/` | Типы с барелями `index.ts` по каталогам |
| `config/services/<категория>.json` | Сервисы: имя, уровень, домены, ASN с holder, ручные подсети с обоснованием, аудированные приложения |
| `config/guard.json` | Внешние списки anycast и CDN, статические подсети и запрещённые ASN |
| `config/exclude.txt` | Подсети, которые обязаны идти через VPN |
| `site/` | Статический сайт для GitHub Pages без сборки и зависимостей |
| `tests/unit/` | Vitest: CIDR, protobuf, генераторы, конфиг, сборка |
| `.github/workflows/` | `ci.yml` проверки, `update.yml` ежедневная сборка и публикация, `pages.yml` деплой сайта |

## Команды

```bash
npm ci
npm run lint                  # eslint, ноль предупреждений
npm test                      # tsc --noEmit и vitest
npm run verify -- --offline   # схема конфига без сети
npm run verify                # плюс проверка holder каждого ASN через RIPE
npm run tools                 # скачать sing-box и mihomo в .tools/
npm run update                # полная сборка в dist/, ходит в RIPE, DNS и списки guard
npm run generate              # сборка из cache/ без сети
npm run check -- <ip|домен>   # в какие уровни входит адрес
```

`update` с прогретым кэшем занимает около 15 секунд, с холодным до трёх минут. Без бинарников `.srs` и `.mrs` пропускаются с предупреждением, остальные файлы собираются.

## Как собираются списки

1. Зона страны: RIPE `country-resource-list` для RU, фолбэк ipdeny. Кэш сутки.
2. Guard: Cloudflare, AWS, Fastly, Google из официальных списков плюс `guard.json`. Кэш сутки, при сбое сети берётся устаревший кэш.
3. Каждый сервис: анонсируемые префиксы его ASN, отфильтрованные по стране (внутри зоны или `country: RU` в whois), домены резолвятся через системный DNS и DoH Google и Cloudflare. Адрес вне собственных ASN попадает точным `/32` или `/128`, и только если он российский.
4. Уровни: lite это сервисы с `tier: lite`, standard все сервисы, full плюс зона страны. Bogon вычищаются, guard и `exclude.txt` вычитаются, результат агрегируется. Лимит lite 500, standard 2000, превышение роняет сборку.
5. Форматы: текстовые генераторы в `writers.ts`, бинарные через sing-box и mihomo, `geoip.dat` и `geosite.dat` через свой protobuf-кодировщик.
6. Манифест: размеры, SHA-256, diff относительно `release`-ветки.

Семантика любого списка: адреса из него идут напрямую, мимо VPN.

## Правила правки конфигов

- Сервис добавляется в подходящую категорию `config/services`. Ключи в порядке `name`, `tier`, `notes`, `asns`, `cidrs`, `domains`, `apps`. Домены в нижнем регистре, отсортированы, без дублей.
- ASN только собственные сети сервиса. `holder` это подстрока реального holder из RIPE `as-overview`, проверка `npm run verify` обязана пройти. Хостинги, CDN и anti-DDoS запрещены в `guard.json`, операторов связи целиком не добавляем.
- Ручная подсеть всегда с `reason`. Один ASN может принадлежать только одному сервису.
- Домены брать из реального трафика или APK, не переписывать чужие списки. Тестовые, staging и зарубежные зеркала не добавлять.
- Изменение лимитов уровней, имён файлов, схемы манифеста и URL это публичный контракт, обсуждается заранее.

## Стиль кода

- TypeScript strict, ESM, алиас `@/` на `src/`. Импорты в файле выстроены лесенкой по длине строки.
- JSDoc на русском на каждой функции и методе, без точки в конце. Внутри функций комментарии только для неочевидного.
- Сервисы это классы с явными зависимостями в конструкторе, без DI-контейнера. Константы в `contracts`.
- Все `interface`, `type` и `enum` живут только в `src/types/<модуль>/<модуль>.types.ts` с барелем `index.ts`, даже если тип нужен одному файлу. Типы, ссылающиеся на классы сервисов, импортируют их через `import type`.
- Логи через `appLogger` в stderr, stdout только для результатов команд.
- Без эмодзи в коде, логах, документации и коммитах.

## Проверка перед завершением

```bash
npm run lint && npm test && npm run verify -- --offline
```

Если менялись `src/services`, `src/helpers` или `config/`, дополнительно `npm run update` и взгляд на числа уровней в логе. Тесты на новую логику CIDR и генераторов обязательны.

## Git

Агент не делает `git commit` и `git push`, а предлагает текст коммита. Формат conventional commits с русским описанием: `feat: …`, `fix: …`, `docs: …`, `chore: …`. Префикс `chore(lists):` зарезервирован за ботом в ветке `release`. Никаких `--force`, `--no-verify` и `reset --hard`.

## Спросить сначала

Изменение лимитов уровней, переименование файлов или уровней, правки `permissions` и секретов в workflows, удаление сервисов, добавление целых сетей операторов, хостингов или CDN, смена лицензии.

## Ссылки

`README.md` для людей, `llms.txt` для ИИ-поисковиков, `SECURITY.md`, шаблоны issue в `.github/ISSUE_TEMPLATE/`, документация Amnezia по split tunneling: https://docs.amnezia.org/ru/documentation/instructions/vpn-split-tunneling/
