agentleFS
vefmvaivefmvai/sysadmin/.claude/skills/refresh-vpn-knowledge/SKILL.md

refresh-vpn-knowledge

Skill1 starsChanged 3 months agoMITView on GitHub

Актуализация VPN-knowledge базы (`.claude/knowledge/networking/`) когда её содержимое старше TTL. База разделена на 3 слоя с разными TTL (ADR-0006): `_live/` (TTL 14 дней — фронт борьбы по странам), `_reference/` (TTL 60 дней — устройство протоколов/клиентов/панели/транспортов/fronting), `_meta/` (TTL 365 дней — реестр источников, глоссарий, конфликты). Сценарий: блокировки и TSPU-сигнатуры в РФ меняются ежедневно, выходят новые версии клиентов sing-box/Hiddify/Karing, появляются issues в 3X-UI — без актуализации агент работает с устаревшей картой и рекомендует уже сломанное. Процесс: проверка frontmatter → WebSearch по фиксированным sources_checked → Tavily research по выявленным изменениям → дифф старого и нового → Yellow Zone подтверждение → переписывание разделов + обновление last_researched. Триггеры: «обнови vpn knowledge», «refresh vpn knowledge», «актуализируй знания про обходы», «проверь свежесть vpn-базы», «давно не обновляли блокировки», + автотриггер из персоны §4.2 перед любой VPN-задачей если найден просроченный файл. НЕ для обновления самого мозга агента (это «обнови sysadmin» / git pull). НЕ для добавления новых VPN-протоколов с нуля (это исследовательская сессия отдельно).

The file

Files
SKILL.md
<role> Я отвечаю за свежесть VPN-knowledge базы — общедоменных знаний про VPN-протоколы, блокировки РФ, клиентов и панель 3X-UI, на которые опираются все VPN-скиллы. Реальность в этой области меняется ежемесячно: TSPU добавляет сигнатуры, выходят новые версии sing-box, появляются issues с iOS-клиентами, меняются reality-параметры. Без актуализации скиллы рекомендуют сломанное.

Работаю в Yellow Zone: правлю knowledge-файлы только с явным подтверждением оператора по каждому файлу. Не переписываю молча. Каждое изменение оператор видит как дифф «было / стало» и принимает или отклоняет. </role>

<context> Что предполагается: - VPN-knowledge живёт в `.claude/knowledge/networking/` в трёх слоях (ADR-0006): - `_live/` — frontline-{ru,cn,ir,by}.md + timeline.md (TTL 14 дней) - `_reference/` — vpn-protocols.md, transports.md, fronting-strategies.md, 3x-ui-panel.md, 3x-ui-api.md, client-apps.md (TTL 60 дней) - `_meta/` — sources-registry.md, glossary.md, conflicts.md (TTL 365 дней) - Каждый файл имеет frontmatter с полями `knowledge_domain: vpn`, `layer`, `last_researched`, `ttl_days`, `sources_checked` (см. helper `_lib/check-knowledge-freshness.sh`). - Tavily — 9 ключей с авто-ротацией через `~/.local/bin/tavily-search.sh` и `tavily-extract.sh` (curl напрямую к API, при quota_exceeded — следующий ключ). Конфиг ключей: `~/.config/tavily-keys.json`. WebSearch встроен как fallback. - Интернет на машине оператора работает (это локальный скилл, не серверный).

Что НЕ предполагается:

  • Что оператор сам мониторит ntc.party и GitHub-issues. Скилл делает это за него.
  • Что Tavily доступен — если упал, fallback на WebSearch+WebFetch.
  • Что все файлы устарели одновременно — скилл может актуализировать выборочно.</context>
<goals> После выполнения должно стать TRUE: - Все VPN-knowledge файлы с истёкшим TTL либо обновлены, либо явно подтверждены как актуальные (`last_researched` обновлён без правок содержимого). - Каждое изменение по содержимому подтверждено оператором отдельно (Yellow Zone). - Найденные новые источники (новые issues, новые клиенты) добавлены в `sources_checked` соответствующего файла. - Если выявлен критический сдвиг (например: «Reality с serverName=cloudflare начала фейлиться в РФ») — создаётся ADR в `$INFRA/decisions/`. </goals><parameters> - `LAYER` — какой слой актуализировать (default: `live` — потому что чаще всего нужен): - `live` — `_live/frontline-*.md` и `_live/timeline.md` (TTL 14 дней, чаще всего) - `reference` — `_reference/*.md` (TTL 60 дней, реже) - `meta` — `_meta/*.md` (TTL 365 дней, почти никогда) - `all` — все слои подряд - `DOMAIN` — какой knowledge-домен актуализировать (default: `vpn`). - `FILES` — конкретные файлы через запятую, для точечной актуализации (default: все просроченные в домене + слое). - `MODE` — `check` (только показать что устарело, не лезть в сеть) / `full` (полный цикл с WebSearch+Tavily) (default: `full`). - `TAVILY_BUDGET` — сколько Tavily-запросов максимум (default: 25 для LAYER=live, 30 для LAYER=reference, 0 для LAYER=meta — почти не нужен). - `AUTO_REFRESH_DATES` — если `true`, для файлов, где полный ресёрч (MODE=full) реально прогнан и НЕ нашёл изменений, обновить `last_researched` без правок текста (default: `false` — дата свежести проставляется только при реальной правке контента; иначе дата врёт, что знание перепроверено). </parameters>

Процедура

Шаг 0: Проверка свежести (Green Zone)

Снимок просроченного, снятый при загрузке скилла (домен vpn, ADR-0029):

!r=$(git rev-parse --show-toplevel 2>/dev/null); s="$r/.claude/skills/_lib/check-knowledge-freshness.sh"; if [ -n "$r" ] && [ -f "$s" ]; then echo "[снято $(date "+%Y-%m-%d %H:%M")]"; bash "$s" vpn --stale-only 2>&1 || true; else echo "НЕ СОБРАНО: helper не найден — прогоняю Шаг 0 скриптом ниже"; fi || true

Как этим пользоваться:

  • MODE=check — ответ уже в снимке выше, слой отбираю глазами по пути (_live/, _reference/, _meta/). Хода на замер не трачу, сразу докладываю оператору.
  • MODE=full или домен не vpn — снимок не подходит (нужен JSON для дальнейших шагов либо другой домен), прогоняю скрипт ниже.
  • Написано «НЕ СОБРАНО» — снимка нет, работаю только скриптом.

Снимок снят один раз, время съёмки указано в первой строке. Правил файлы знаний в этой же сессии — цифры устарели, перезамеряй скриптом.

Запускаю helper, чтобы понять — какие файлы просрочены.

SYSADMIN_ROOT=$(grep -oE '`/[^`]+sysadmin/?`' ~/.claude/agents/sysadmin.md 2>/dev/null \
    | head -1 | sed 's|`||g; s|/$||')
[ -z "$SYSADMIN_ROOT" ] && SYSADMIN_ROOT="$(pwd)"

# Список просроченных файлов в JSON-формате
STALE=$(bash "$SYSADMIN_ROOT/.claude/skills/_lib/check-knowledge-freshness.sh" \
    "${DOMAIN:-vpn}" --json --stale-only)

# Фильтр по LAYER (default: live — самый частый сценарий)
LAYER="${LAYER:-live}"
if [ "$LAYER" != "all" ]; then
    STALE=$(echo "$STALE" | jq --arg L "_${LAYER}/" '[.[] | select(.file | contains($L))]')
fi

STALE_COUNT=$(echo "$STALE" | jq 'length')

Если STALE_COUNT=0 — выводим оператору одну строку и выходим:

«Все VPN-knowledge файлы в слое _${LAYER}/ в актуальном TTL. Проверять нечего.»

Если есть просроченные — показываем список (с указанием слоя):

Просроченные VPN-knowledge (LAYER=live):
  ⚠️  _live/frontline-ru.md — last_researched 2026-05-01 (16 дней, TTL 14)
  ⚠️  _live/timeline.md     — last_researched 2026-04-30 (17 дней, TTL 14)

Если MODE=check — на этом останавливаемся. Иначе переходим к Шагу 1.

Шаг 1: Брифинг (Yellow Zone — переход к web-исследованию)

«Я собираюсь актуализировать <N> VPN-knowledge файлов. Это значит:

  1. Пройду WebSearch'ем по их sources_checked (короткие запросы, бесплатно).
  2. Для файлов, где WebSearch выявил изменения — сделаю глубокий Tavily research (бюджет до $TAVILY_BUDGET запросов из 1000/мес).
  3. Покажу тебе дифф для каждого файла — что предлагаю изменить.
  4. По твоему «да» правлю файл, обновляю last_researched.
  5. Если выявлен критический сдвиг (Reality сломался, клиент удалён из App Store) — предложу создать ADR в $INFRA/decisions/.

Web-исследование может занять 3-10 минут. Tavily расходует общий лимит на месяц, поэтому я экономлю — иду в Tavily только за подтверждением WebSearch-находок.

Подтверди старт: «да» / «давай» / «делай».»

Без подтверждения — не запускаю web-запросы. Без --mode=check, оператор может сначала посмотреть что устарело, потом решить запускать актуализацию.

Шаг 2: WebSearch-обход (Green Zone — read-only веб)

Для каждого просроченного файла:

  1. Извлекаю sources_checked из frontmatter:
    FILE=".claude/knowledge/networking/_reference/vpn-protocols.md"  # пример (любой слой)
    SOURCES=$(awk '/^---$/{c++; next} c==1 && /^  - /{sub("^  - ", ""); print}' "$FILE" | head -10)
  2. Для каждого URL — WebSearch с запросом контекста файла. Готовые формулы запросов по каждому файлу и карта источников по трём слоям — references/search-strategies.md. Сочинять запросы заново не надо: беру оттуда и подставляю <last_researched>.
  3. Собираю результаты в один JSON-документ:
    {
      "file": "vpn-protocols.md",
      "findings": [
        {"source": "ntc.party/c/blocking", "summary": "Новая статья о фейлах Reality 2026-06", "url": "..."},
        {"source": "XTLS/Xray-core releases", "summary": "Релиз v1.9 с fix'ом X25519 fingerprint", "url": "..."}
      ]
    }
  4. Если по файлу findings пуст — этот файл актуален, переходим к Шагу 5 (обновление только last_researched).

Шаг 3: Tavily search/research (по бюджету)

Только для файлов, где WebSearch нашёл изменения, делаю глубокий поиск.

Приоритет инструментов (для экономии quota):

  1. ~/.local/bin/tavily-search.sh "query" advanced 8 (curl-обёртка с ротацией 9 ключей) — обычные поиски, default
  2. ~/.local/bin/tavily-extract.sh "https://url" — извлечение конкретной страницы (тот же ротатор)
  3. mcp__tavily__tavily_search (basic depth) — если curl недоступен
  4. mcp__tavily__tavily_research (pro depth) — только для глубоких синтезов; имеет отдельный жёсткий лимит, не использовать на простых проверках актуальности
  5. WebSearch + WebFetch — fallback при полном исчерпании Tavily

Бюджет жёсткий: не более $TAVILY_BUDGET запросов за весь прогон скилла. По умолчанию для LAYER=live — 25, для LAYER=reference — 30, для LAYER=meta — 0. При исчерпании — fallback на WebSearch.

Пример Tavily-запроса для _live/frontline-ru.md:
"Russia VPN blocking status May 2026 latest TSPU signatures
new blocks since 2026-05-01 mobile operators differences"

Шаг 4: Дифф и подтверждение (Yellow Zone)

Для каждого файла, где найдены изменения, формирую дифф-предложение. Скелет:

=== <файл> ===
<раздел>

БЫЛО (на <дата last_researched>):   > <дословная цитата старого текста>
ПРЕДЛАГАЮ (на <сегодня>):           > <новый текст> (источник: <URL>)

Изменения в sources_checked: + <URL>

Применить? (да / нет / показать ещё контекст)

Цитата «БЫЛО» — дословная, не пересказ: без неё оператор не заметит, что новая формулировка тише старой. Развёрнутый образец — references/output-formats.md.

Оператор:

  • «да» — применяю Edit к файлу, добавляю URL в sources_checked, обновляю last_researched.
  • «нет» — пропускаю этот файл; last_researched НЕ трогаю (оператор отверг найденные изменения — файл не перепроверен, освежать дату было бы самообманом).
  • «показать ещё контекст» — вывожу полные WebSearch+Tavily findings по этому файлу.

Шаг 5: Обновление last_researched

last_researched — это дата ПОСЛЕДНЕЙ РЕАЛЬНОЙ ПРОВЕРКИ, не «дата запуска скилла». Обновляю её только в двух случаях:

  1. Файл реально правился (оператор сказал «да» изменениям из ресёрча).
  2. Полный ресёрч (MODE=full) прогнан, изменений не нашёл, И оператор явно запустил скилл с AUTO_REFRESH_DATES=true — осознанное «подтверждаю, перепроверено, всё актуально».

В остальных случаях (MODE=check; оператор сказал «нет»; ресёрч не прогонялся) дата остаётся старой — пусть честно показывает возраст знания.

TODAY=$(date -u +%Y-%m-%d)
# Через sed заменяю строку last_researched:
sed -i.bak -E "s/^last_researched:.*/last_researched: $TODAY/" "$FILE"
rm -f "${FILE}.bak"

Шаг 6: Если найден критический сдвиг — действия по слою

Поведение зависит от слоя:

  • _live/ — ADR обычно НЕ нужен (фронт меняется быстро, ADR создаст шум). Просто добавить запись в _live/timeline.md и обновить соответствующий _live/frontline-*.md. timeline.md — append-only, не правим старое.
  • _reference/ — да, ADR если breaking change архитектурного уровня (примеры: «Reality официально сломан в РФ», «sing-box-vt удалён из App Store», «новый эталонный клиент вытесняет sing-box»). Шаблон — decisions/0000-template.md в публичном репо или $INFRA/decisions/ приватной infra/.
  • _meta/ — обновление через сам файл (conflicts.md для расхождений, sources-registry.md для новых источников), без ADR.

Шаг 7: Краткий отчёт

Отчёт содержит пять блоков:

  1. Файлы, обновлённые с изменениями — имя, какой раздел правился, сколько источников добавлено.
  2. Файлы, обновлённые без изменений (только дата) — отдельным списком, не вперемешку с первым: там дата проставлена под ответственность оператора, а не потому, что знание переписано.
  3. Расход Tavily — потрачено / бюджет.
  4. Расход WebSearch — число запросов (бесплатно).
  5. ADR, если был критический сдвиг, — путь к созданному документу.

Финальная строка — новая last_researched и когда сработает следующая проверка. Готовый образец отчёта — references/output-formats.md.

Анти-паттерны

  • Не правь knowledge молча. Каждое изменение текста — Yellow Zone, подтверждение.
  • Не жги Tavily-лимит. Сначала WebSearch (бесплатно), потом Tavily только за подтверждением. Бюджет $TAVILY_BUDGET — жёсткий, не превышай.
  • Не обновляй last_researched без проверки. Если оператор сказал «всё ок, не лезь» по конкретному файлу — это явное решение, а не пропуск. Запоминай его.
  • Не считай отсутствие изменений в WebSearch гарантией актуальности. Если файл старше 90 дней и в Tavily-бюджете осталось — сделай хотя бы один Tavily-запрос, чтобы убедиться что не пропустил.
  • Не правь несколько файлов одним коммитом без разделения. Если каждый файл актуализирован отдельно — это отдельные логические изменения, делай отдельные коммиты с описанием что именно изменилось.

Bundled resources

ФайлЧто это и когда открывать
references/search-strategies.mdКарта источников по трём слоям + готовые формулы запросов под каждый knowledge-файл (WebSearch-набор, Tavily-формулировка, «что искать в первую очередь»). Открывать на Шаге 2, до первого запроса в сеть
references/output-formats.mdОбразцы вывода: развёрнутое дифф-предложение (Шаг 4) и финальный отчёт (Шаг 7) с пояснением, почему они устроены именно так
evals/triggers.mdpositive/negative фразы для проверки, что скилл подхватывается по адресу

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.