Бесплатный интерактивный курс · aicoding.space

scout: радар экосистемы навыков

Практический курс по @dzhechkov/scout для того, кто поддерживает свой харнес AI-агента и устал вручную листать GitHub. Вместе с Леной ты запустишь радар по одиннадцати источникам, разберёшь формулу релевантности по частям, научишься читать отчёт, включишь глубокий анализ и выберешь путь интеграции для найденного навыка, а в конце поймёшь, почему ноль в отчёте — ещё не факт о мире.

Содержание курса

1. Зачем нужен scout

Что такое scout одной фразой — и почему это не «ещё один поиск по GitHub».

Ключевая мысль: разведка экосистемы навыков

Лена поддерживает харнес AI-агента для своей команды. Харнес — это вся обвязка вокруг модели: навыки, команды, хуки, память. И у неё была еженедельная боль: каждую пятницу она открывала GitHub, вбивала «claude skills», листала три страницы, потом шла на npm, потом в реестр MCP-серверов — и всё равно через неделю узнавала от коллеги о наборе навыков, который «все уже поставили».

scout — это разведка экосистемы навыков: одна команда, которая опрашивает одиннадцать источников, оценивает каждую находку по одной формуле и говорит, что с ней делать. Не «вот список ссылок», а «вот три репозитория, которые стоит интегрировать, восемь — понаблюдать, остальное — пропустить».

Что это меняет на практике:

  • вместо ручного обхода сайтов — dz scout, один вызов;
  • вместо «кажется, где-то видела» — память: scout помнит, что уже показывал, и отмечает по-настоящему новое;
  • вместо интуиции — число от 0 до 100 и рекомендация с понятной причиной.

Пакет живёт на npm: страница @dzhechkov/scout на npmjs.com, исходники — в публичном репозитории DZ Harness Hub на GitHub. Командой dz scout он доступен из @dzhechkov/harness-cli.

Компромисс: ты получаешь широкий охват и единую шкалу, но платишь тем, что оценка — эвристика. Она сортирует, а не решает: последнее слово всё равно за тобой.

💬 Не обязательно помнить команды. Внутри Claude Code или Codex достаточно сказать помощнику «посмотри, что нового появилось в экосистеме навыков» — и он сам выполнит dz scout. Команды в этом курсе нужны, чтобы ты понимал, что происходит под капотом.

2. Одиннадцать источников

Кто именно отвечает на запрос радара — от GitHub до arXiv — и почему их не пять.

Ключевая мысль: одиннадцать источников

Первое, что спросила Лена: «а почему одиннадцать? Мне хватило бы GitHub». Ответ — в истории пакета: он начинался с одного GitHub, и именно тогда Лена пропускала MCP-серверы, которые на GitHub помечены как угодно, только не темой mcp-server.

Сейчас scout опрашивает одиннадцать источников, и они делятся на четыре семьи:

  1. Код и пакеты — GitHub (репозитории по темам agent-skills, claude-code-skills, mcp-server; нужен токен) и реестр npm (пакеты с ключевыми словами mcp-server, claude-code, agent-skills; без авторизации).
  2. Реестры MCP-серверов — официальный реестр modelcontextprotocol.io, метареестр Glama.ai (по README — 29 900+ серверов) и маркетплейс Smithery.ai (7 300+ серверов).
  3. Пульс сообщества — Hacker News через поиск Algolia и OSSInsight Trending: сто репозиториев с самым быстрым ростом звёзд за неделю.
  4. Наука — Semantic Scholar (не чаще одного запроса в секунду) и arXiv (пауза три секунды между запросами): статьи про использование инструментов агентами.

Плюс два курируемых репозитория, которые сканируются целиком как инвентарь навыков: affaan-m/ECC и DreamLab-AI/agentbox (больше ста навыков, но без лицензии — поэтому scout по умолчанию ставит ему рекомендацию «наблюдать»).

Важная деталь механики: девять быстрых источников опрашиваются параллельно, а два академических — последовательно после них, потому что у них обязательные паузы между запросами. Результаты склеиваются и дедуплицируются по полному имени репозитория.

Компромисс: широкий охват стоит времени — академические источники с их паузами удлиняют прогон; зато ни один класс находок не остаётся слепым пятном.

3. Установка и первый запуск радара

npm i -g, токен GitHub и первый dz scout — от пустого терминала до первого отчёта.

Ключевая мысль: первый запуск радара

Хватит вводных — Лена уже открыла терминал, открывай и ты. Первый запуск радара занимает три шага:

  1. Поставь командную оболочку харнеса: npm i -g @dzhechkov/harness-cli — команда dz scout приезжает вместе с ней, отдельно ставить @dzhechkov/scout не нужно.
  2. Положи токен GitHub в окружение: export GITHUB_TOKEN=.... Без него запросы к GitHub идут с лимитом 60 в час вместо 5 000 — и три источника, которые ходят в GitHub (сам GitHub, ECC и AgentBox), быстро в него упираются. Команда предупредит об отсутствующем токене одной строкой: dz scout: set GITHUB_TOKEN env var for higher rate limits.
  3. Запусти радар: dz scout.

Первая строка вывода — баннер Scanning ... sources, дальше — сводка по источникам вида Sources: github: 50, npm: 42, hackernews: 30, ..., строка памяти Memory: ... total tracked, ... new this scan и сам отчёт. Радар берёт до 50 лучших находок.

Полезные вариации первого запуска:

  • dz scout --since 2026-05-01 — только репозитории, обновлённые после даты (фильтр действует на GitHub-поиск и Hacker News);
  • dz scout --topics mcp-server,ai-agent — свои темы вместо шести тем по умолчанию (agent-skills, claude-code-skills, agentskills-io, mcp-server, ai-harness, claude-code-plugin); темы касаются только GitHub.

Грабли Лены — не повторяй: она запустила dz scout с давно отозванным токеном и получила отчёт, в строке Sources: которого имени github не было вовсе. Отчёт выглядел нормально — просто в нём не было главного. Почему это опасно и как scout теперь об этом предупреждает — в последней секции курса.

Компромисс: первый запуск прост — три команды, — но он ходит в сеть по одиннадцати адресам, и результат зависит от того, кто из них ответил. Полный прогон с академическими источниками занимает заметно больше времени, чем «мгновенно».

4. Радарный режим: шесть шагов

Что происходит между баннером «Scanning … sources» и таблицей отчёта — по порядку.

Ключевая мысль: шесть шагов радарного режима

Лена запустила радар и смотрит на бегущие строки. Между первой строкой и таблицей отчёта scout проходит шесть шагов радарного режима — и порядок здесь не случаен: каждый шаг готовит данные для следующего.

  1. Сканирует одиннадцать источников — быстрые параллельно, академические следом — и склеивает результаты без дублей.
  2. Определяет формат каждой находки: SKILL.md, plugin.json, каталог .claude/skills/, манифест MCP-сервера.
  3. Считает релевантность по одной формуле: формат 40 %, звёзды 30 %, свежесть 20 %, новизна 10 %.
  4. Сверяет со встроенным инвентарём — списком наших пакетов и известных навыков — и находит то, чего у нас нет.
  5. Выдаёт рекомендацию по каждой находке: интегрировать, наблюдать или пропустить.
  6. Показывает происхождение — какой именно источник нашёл каждую строку.

Зачем шаг 6, если отчёт уже готов? Лена поняла это на второй неделе: когда какая-то строка вызывает сомнение, первый вопрос — «откуда она?». Находка из OSSInsight Trending и находка из arXiv — это разные типы свидетельств, и читать их надо по-разному.

Обрати внимание на границу: шаги 1–3 работают с тем, что пришло из сети, шаги 4–6 — с тем, что scout знает о ТЕБЕ. Именно поэтому один и тот же репозиторий у разных команд получает разную новизну: инвентарь у всех свой.

Компромисс: такая конвейерная схема прозрачна и легко объяснима, но каждая эвристика в ней (формат по темам, новизна по совпадению имён) даёт ложные срабатывания — ниже мы разберём каждую и увидим, где именно.

5. Как scout узнаёт формат навыка

Шесть форматов, их веса и неожиданный факт: слово skill.md в описании тоже считается.

Ключевая мысль: детектор форматов навыков

Лена увидела в отчёте колонку Formats со значением agentskills-io и спросила: «а откуда scout это знает, он же не скачивал репозиторий?» Хороший вопрос — в радарном режиме scout действительно НЕ читает файлы. Детектор форматов навыков смотрит только на темы репозитория и текст его описания.

Вот таблица из исходников (src/analyzer.ts), она же — самая весомая часть формулы оценки:

  • agentskills-io — вес 1.0: тема agentskills-io или agent-skills, либо слово skill.md в описании;
  • claude-plugin — 0.9: тема claude-code-plugin, либо plugin.json / .claude-plugin в описании;
  • claude-skills — 0.85: тема claude-code-skills или claude-code, либо .claude/skills в описании;
  • codex-skills — 0.7: тема codex или .agents/skills в описании;
  • mcp-server — 0.7: тема mcp-server или mcp, либо «mcp server» в описании;
  • generic-agent — 0.3: если ничего из списка не сработало, но есть тема ai-agent или слово «agent» в описании.

У репозитория может быть несколько форматов сразу; в формулу идёт лучший вес, умноженный на 40. То есть репозиторий с темой agent-skills получает сорок баллов из ста только за правильную тему — ещё до того, как посчитали звёзды.

А теперь неожиданность, которую Лена нашла сама: репозиторий с описанием «my todo app, skill.md coming soon» получит формат agentskills-io и все сорок баллов. Детектор честный, но наивный — он верит словам. Это и есть причина, почему рекомендация «интегрировать» — повод посмотреть, а не команда к действию.

Компромисс: детектор по темам и описанию — мгновенный и не ходит в сеть за каждым репозиторием; за это он платит ложными срабатываниями на словах в описании. Глубокий режим (--deep) исправляет именно это — он уже читает файлы.

6. Формула релевантности: 40 / 30 / 20 / 10

Из чего складывается число 0–100 и где проходят пороги «интегрировать / наблюдать / пропустить».

Ключевая мысль: формула релевантности

Прежде чем читать дальше, реши за Лену сам. Два репозитория: первый — тема agent-skills, 40 звёзд, коммит вчера; второй — тема mcp, 5 000 звёзд, последний коммит полтора года назад. Какой получит больше баллов? Запомни ответ — сейчас проверим.

Формула релевантности складывает четыре слагаемых, и сумма всегда в пределах 0–100:

  1. Формат — до 40. Лучший вес формата × 40 (прошлая секция).
  2. Звёзды — до 30. Не линейно, а по логарифму: min(1, log2(звёзды + 1) / 10) × 30. Насыщение наступает примерно на 1 023 звёздах — дальше рост звёзд ничего не добавляет. Сорок звёзд дают около 16 баллов, пять тысяч — все 30.
  3. Свежесть — до 20. Ступеньками по дням с последнего коммита: моложе 30 дней — 1.0; моложе 90 — 0.7; моложе года — 0.3; старше — 0.1. Умножается на 20.
  4. Новизна — до 10. Доля навыков-подсказок из тем репозитория, которых нет в нашем инвентаре, × 10.

Теперь пороги рекомендации:

  • интегрировать — оценка ≥ 70;
  • наблюдать — оценка от 40 до 69 и не меньше 50 звёзд;
  • пропустить — всё остальное.

Сверь свой прогноз. Первый репозиторий: 40 (формат) + ~16 (звёзды) + 20 (свежесть) + новизна — уже под 80, «интегрировать». Второй: 28 (mcp, 0.7 × 40) + 30 (звёзды) + 2 (старше года) — около 60, и при пяти тысячах звёзд это «наблюдать». Лена ставила на звёзды — и промахнулась: формат и свежесть вместе весят 60, звёзды — только 30.

Компромисс: логарифм по звёздам защищает от гигантов-ветеранов, а ступеньки свежести — от заброшенных проектов; но веса зашиты в код, и если для тебя звёзды важнее свежести, перенастроить их из командной строки нельзя.

7. Как читать отчёт разведки

Сводка по источникам, три таблицы по цветам и колонка «Novel skills» — что где искать.

Ключевая мысль: отчёт разведки

Лена получила свой первый отчёт и растерялась: две сотни строк, эмодзи, таблицы. Давай прочитаем отчёт разведки сверху вниз, как его печатает scout, — и ты увидишь, что смотреть нужно всего в четыре места.

Место 1 — строка источников. Sources: github: 50, npm: 42, hackernews: 30, mcp-registry: 20, .... Это сколько находок дал КАЖДЫЙ источник до дедупликации. Важная деталь из исходника команды (harness-cli/src/cli.ts): источник с нулём в эту строку не попадает вовсе — его имя просто исчезает. Первая проверка Лены теперь всегда здесь: пересчитать имена. Нет github — читать остальное рано (почему — в последней секции).

Место 2 — шапка. Total found: 216 | Scanned: 216 | New: 14 — сколько всего нашлось, сколько попало в отчёт после склейки дублей и сколько из них scout видит впервые (в первом прогоне здесь будет число всех находок).

Место 3 — три таблицы по цветам. Это те самые пороги из прошлой секции:

  • 🟢 Integrate — оценка ≥ 70. Сюда Лена смотрит первым делом, и обычно здесь три–пять строк;
  • 🟡 Monitor — 40–69 и не меньше 50 звёзд. Кандидаты на следующую неделю;
  • Skip — всё остальное. Пролистать, но не удалять: через --diff видно, кто отсюда вырос.

В каждой таблице пять колонок: репозиторий (ссылкой), звёзды, форматы, оценка и Novel skills — навыки, извлечённые из тем репозитория, которых нет в нашем инвентаре. Если в колонке прочерк — новизны по темам не найдено, и десять баллов новизны репозиторий не получил.

Место 4 — разделы --deep. «🔬 Deep Analysis» и «📊 Harness Gap Analysis» появляются только в глубоком режиме. Если их нет — ты запускал радар, а не аналитика.

Компромисс: отчёт — это markdown, его удобно читать в терминале и вставлять в заметки, но это не структурированные данные: для автоматической обработки бери программный API, а не парси текст.

8. Глубокий анализ и путь интеграции

Что делает --deep: скачивает SKILL.md, ищет ближайший наш навык и выбирает один из четырёх путей интеграции.

Ключевая мысль: путь интеграции

Радар сказал Лене «интегрировать» — и тут же встал следующий вопрос: интегрировать КАК? Скопировать целиком? Добавить кусок в наш похожий навык? Этот вопрос радар не решает: он не читал файлы. Его решает глубокий анализdz scout --deep.

Что он делает, шаг за шагом:

1. Берёт репозитории с оценкой ≥ 50 (заметь: ниже порога «интегрировать» — чтобы посмотреть и на кандидатов из «наблюдать»), только с GitHub и не больше десяти лучших.
2. Скачивает дерево репозитория, находит файлы SKILL.md — не больше пяти на репозиторий — и читает их frontmatter: имя и описание.
3. Ищет ближайший наш навык по совпадению ключевых слов описания: нужно как минимум два общих слова, иначе совпадения нет.
4. Выбирает путь интеграции — один из четырёх, строго по порядку проверок:
- skip — навык с таким именем уже есть в нашем инвентаре;
- merge — ближайший наш навык найден: добавить к нему уникальное, а не дублировать;
- canonicalize — ближайшего нет и у репозитория ≥ 100 звёзд: сильный сигнал, делать новый пак @dzhechkov/skills-*;
- new-preset — ближайшего нет, звёзд меньше ста: добавить в пресет или завести пак, когда сигнал подтвердится.
5. Пишет дельту — что найденный навык добавляет к нашему ближайшему.

Порядок проверок важен: Лена сначала решила, что canonicalize — это «лучшая» рекомендация. Нет: она означает «похожего у нас нет», а это не всегда хорошо — иногда нет, потому что и не нужно. Самый ценный путь на практике — merge: чужая идея усиливает уже работающий навык.

Сейчас твоя очередь принимать решения — в сценарии ниже ты и есть аналитик, а не scout.

Компромисс: глубокий режим читает реальные файлы и потому точнее радара, но каждый репозиторий — это несколько запросов к GitHub, а инвентарь описаний для сравнения — статичный снимок внутри пакета; чем дальше твой харнес ушёл от него, тем чаще «ближайший» будет промахиваться.

9. Анализ пробелов: чего не хватает твоему харнесу

Раздел Gap Analysis: тренды экосистемы, которых у тебя нет, и академические темы из arXiv.

Ключевая мысль: анализ пробелов

До сих пор scout отвечал на вопрос «что нового появилось?». Лена задала другой, куда более неудобный: «а чего у меня НЕТ, о чём я даже не думала?» На него отвечает анализ пробелов — раздел «📊 Harness Gap Analysis», который появляется в отчёте только в глубоком режиме.

Как он строится:

  1. У каждого репозитория, прошедшего глубокий анализ, берутся его темы — например ai-agents, mcp, deploy-automation. Каждая тема — это категория; scout считает, сколько репозиториев в неё попало.
  2. К категориям из кода добавляются академические темы: в описаниях статей arXiv, Semantic Scholar и историй Hacker News ищутся слова вроде «tool use», «multi-agent», «planning», «grounding», «alignment». Каждое попадание — плюс один к частоте темы.
  3. Для известных категорий scout подставляет короткое «What it is» — что это вообще такое, — чтобы Лене не пришлось гуглить runtime-governance.
  4. Рекомендация по каждой строке — например «Create @dzhechkov/skills-ai-agents» при большой частоте или «Monitor — academic research trend» для темы из статей.

Пример из README: ai-agents — 15 repos — Create @dzhechkov/skills-ai-agents; tool use — 5 papers — Monitor — academic research trend.

Вот тут начинается открытый вопрос, на который scout не ответит за тебя. Частота 15 репозиториев — это спрос экосистемы или мода недели? Пять статей про «tool use» — это пробел в твоём харнесе или тема, которая в нём не нужна вовсе? Лена завела правило: строка анализа пробелов — это гипотеза для бэклога, а не задача. Она записывает её и смотрит, повторится ли на следующей неделе. Повторилась дважды — тогда берётся.

Компромисс: анализ пробелов — единственное место, где scout говорит о том, чего ты не искал; но он считает частоту тем, а частота — это популярность, не ценность для твоей команды. Различить их можешь только ты.

10. Память: scout помнит, что уже видел

Каталог .dz/scout/, firstSeen/lastSeen, лимиты хранения и почему твои решения никогда не стираются.

Ключевая мысль: постоянная память сканирований

На второй неделе Лена заметила в шапке отчёта новое число: рядом с Scanned: 216 появилось «новых: 14». Откуда scout знает, что новых именно четырнадцать? Из постоянной памяти сканирований — каталога .dz/scout/ в проекте.

Три файла в нём:

  • scan-history.json — по записи на каждый виденный репозиторий: полное имя, firstSeen и lastSeen (даты первого и последнего появления), последняя оценка, рекомендация, источник и — если ты его записал — твоё решение userDecision;
  • last-report.json — последний отчёт целиком, для чтения без сети;
  • config.json — необязательные лимиты хранения.

Как память обновляется: после каждого прогона scout вливает результаты в историю. Знакомый репозиторий получает новые lastSeen и оценку; незнакомый заводится с firstSeen = сейчас и считается новым. Именно это число ты видишь в шапке.

Лимиты, чтобы история не разрасталась вечно (значения по умолчанию, меняются в config.json):

  • retentionDays: 90 — запись, которую не видели дольше 90 дней, удаляется;
  • maxEntries: 500 — при переполнении удаляются самые старые по lastSeen.

И одно правило, которое Лена оценила больше всего: запись с твоим решением не удаляется никогда — ни по возрасту, ни по переполнению. Если ты пометил репозиторий как «пропустить», scout не забудет этого через три месяца и не предложит его снова как новинку. Память здесь — не кэш, а твой журнал решений.

Остановись на секунду и подумай: сколько раз за последний месяц ты заново оценивал то, что уже оценивал? Именно этот повторный труд память убирает.

Компромисс: память живёт в каталоге проекта, а не в общем хранилище — на другой машине scout начнёт с чистого листа; зато она обычный JSON, и перенести её — значит скопировать три файла.

11. Флаги --diff и --report: что изменилось, без сети

Три раздела дифа — новые, исчезнувшие, изменившие оценку — и отчёт из кэша без единого запроса.

Ключевая мысль: флаги --diff и --report

В поезде без интернета Лена захотела перечитать пятничный отчёт — и обнаружила, что для этого не нужна сеть. Два флага работают поверх памяти из прошлой секции: флаги --diff и --report.

dz scout --report — показать последний сохранённый отчёт из .dz/scout/last-report.json. Ни одного сетевого запроса. Если отчёта ещё нет — scout так и скажет, а не покажет пустую таблицу.

dz scout --diff — сравнить текущий скан с историей и показать раздел «🔄 Changes Since Last Scan» из трёх частей:

  • 🆕 New — репозитории, которых не было в истории (до двадцати строк со ссылкой, оценкой и рекомендацией);
  • Gone — были в истории, а в этом скане не появились (до десяти);
  • 📈 Score Changed — оценка изменилась на 5 баллов и больше, со стрелкой вверх или вниз.

Небольшая тонкость из исходника команды: начиная со второго прогона раздел изменений печатается и без флага — команда показывает его всякий раз, когда память не пуста; --diff лишь гарантирует его. Так что не удивляйся, если увидел его, не прося.

Порог в пять баллов — сознательный: свежесть считается ступеньками по дням, и без порога каждую неделю «менялись» бы десятки строк только потому, что репозиторий стал на день старше.

А теперь сюрприз, который поймал Лену. Раздел Gone не означает «репозиторий удалили». Он означает «в ЭТОМ скане его не нашли» — а не нашли его, возможно, потому что источник, который его давал, в этот раз не ответил. Дюжина строк в Gone сразу — это сигнал проверить строку Sources:, а не хоронить проекты. Об этом — последняя секция.

Если ничего не изменилось, scout честно печатает «No changes since last scan» — пустой раздел он не рисует.

Компромисс: --diff превращает еженедельный прогон из «прочитай двести строк» в «прочитай пятнадцать», но он сравнивает с историей, а история подчиняется лимитам хранения — репозиторий, стёртый по возрасту, всплывёт как «новый».

12. Программный API: scout внутри твоего кода

scanAllSources, generateReport, deepAnalyze и ScoutMemory — те же шаги радара, но из TypeScript.

Ключевая мысль: программный API

Лене надоело копировать отчёт в заметки руками, и она захотела складывать находки прямо в бэклог команды. Для этого есть программный API — пакет @dzhechkov/scout экспортирует те же шаги, что проходит dz scout, по одной функции на шаг.

Минимальный сценарий — три вызова:

import { scanAllSources, generateReport, deepAnalyze } from '@dzhechkov/scout';

const { results, totalBySource, statusBySource } = await scanAllSources({ token: process.env.GITHUB_TOKEN });
const report = generateReport({ repos: results, totalFound: results.length, newSinceLastScan: 0, scannedAt: new Date().toISOString(), topics: [] });
const deep = await deepAnalyze(results, { token: process.env.GITHUB_TOKEN });
```

Что здесь что:

  1. scanAllSources — радар целиком: одиннадцать источников, дедупликация, сортировка по оценке. Возвращает results (профили с тегом источника), totalBySource (строка Sources: в виде объекта) и statusBySource — здоровье каждого источника, о нём в последней секции.
  2. generateReport — превращает результаты в объект отчёта с полями summary (сколько интегрировать / наблюдать / пропустить) и markdown — тот самый текст, который печатает команда.
  3. deepAnalyze — глубокий анализ; принимает minScore (по умолчанию 50) и возвращает разборы по репозиториям, список пробелов и markdown.

Отдельные источники тоже экспортируются — scanNpm, scanHN, scanMcpRegistry, scanGlama и остальные — если тебе нужен один канал, а не радар. А класс ScoutMemory даёт то, чего нет в командной строке: метод recordDecision(fullName, 'integrate' | 'monitor' | 'skip') записывает твоё решение в память — ту самую запись, которая никогда не удаляется.

Лена написала двадцать строк: скан → report.summary.integrate → по каждой строке «интегрировать» создать карточку в бэклоге → recordDecision, чтобы не создать её дважды. Пятничный вечер стал пятиминутным.

Компромисс: программный API даёт структуру вместо markdown и доступ к решениям, но это ESM-пакет для Node 20+, и его сигнатуры — часть версии: обновляя пакет, перечитывай README, а не полагайся на память.

13. Ноль — это не находка: здоровье источника

История одного отозванного токена: почему «github: 0» молчал, и как scout теперь отличает пустой ответ от отсутствия ответа.

Ключевая мысль: здоровье источника

Помнишь грабли Лены из третьей секции — отчёт без GitHub, который выглядел нормально? Эта секция про то, почему так вышло, и почему сегодня так уже не выйдет. Она опирается не на README, а на комментарий в исходнике src/sources/index.ts, где записан измеренный случай.

Что было измерено (2026-08-22). С отозванным GITHUB_TOKEN сканер GitHub упал с ошибкой 401 Bad credentials. Но одиннадцать источников опрашиваются через Promise.allSettled — конструкцию, которая по определению не роняет весь прогон из-за одного отказа. Отказ был проглочен, и в строке Sources: напечаталось github: 0. Главный источник разведки молчал, и это было неотличимо от «на GitHub ничего нового нет». Хуже того: команда предупреждала только об ОТСУТСТВИИ токена — плохой токен был тише, чем никакого.

Что изменилось. У каждого источника появилось здоровье источника — поле SourceHealth со значениями ok или failed, плюс первая строка причины отказа. Правило одно: ноль со статусом ok — это измеренный ноль, факт о мире; ноль со статусом failed — это отсутствие измерения, и печататься одинаково они не должны. В программном API это statusBySource, который возвращает scanAllSources.

Честная оговорка про командную строку. На момент написания курса сама команда dz scout (harness-cli/src/cli.ts) этот статус НЕ печатает: она берёт из scanAllSources только результаты и счётчики и убирает из строки Sources: источники с нулём. Поэтому в терминале отказ выглядит как отсутствие имени источника в строке — а причину отказа увидишь только из своего кода через statusBySource. Знать это важнее, чем верить README.

Общий урок, который Лена унесла из этой истории дальше scout: пустой результат и отсутствующий результат — разные вещи, и инструмент обязан их различать. Если твой отчёт, тест или мониторинг выводит «всё чисто» из тишины, он сломается молча на первом же новом способе отказа.

Поэтому у Лены теперь ритуал: в терминале — пересчитать имена в строке Sources:; в своём скрипте — прочитать statusBySource до того, как трогать результаты. Ноль у GitHub при статусе ok — редкость, но бывает; ноль при failed — чинить токен, а не читать отчёт.

Компромисс: статус здоровья добавляет в вывод ещё одну строку, которую надо читать; зато он убирает целый класс тихих ошибок — «отчёт выглядит нормально, а главного в нём нет».

Частые вопросы

Нужно ли ставить @dzhechkov/scout отдельно?

Нет. Команда dz scout приезжает вместе с @dzhechkov/harness-cli (npm i -g @dzhechkov/harness-cli). Отдельно пакет нужен только для программного API в своём коде.

Что будет без GITHUB_TOKEN?

GitHub, ECC и AgentBox ходят в GitHub без авторизации с лимитом 60 запросов в час вместо 5 000 — команда предупредит об отсутствующем токене. С отозванным (а не отсутствующим) токеном GitHub отвечает 401: в программном API это статус failed с причиной, а в терминале имя github просто исчезает из строки Sources.

Почему репозиторий с тысячами звёзд попал в «наблюдать», а не в «интегрировать»?

Звёзды весят максимум 30 баллов и насыщаются около 1 023. Формат (до 40) и свежесть (до 20) весят вместе больше; старый репозиторий с форматом mcp получает около 60 — это «наблюдать».

Чем отличаются dz scout и dz scout --deep?

Радар (dz scout) смотрит на темы и описания и не скачивает файлы. Глубокий режим (--deep) для репозиториев с оценкой от 50 скачивает SKILL.md, ищет ближайший наш навык, выбирает путь интеграции и строит анализ пробелов.

Что значит canonicalize в разделе Deep Analysis?

Ближайшего нашего навыка не нашлось и у репозитория не меньше 100 звёзд: сильный сигнал завести новый пак @dzhechkov/skills-*. Это не «лучшая» рекомендация, а «похожего у нас нет» — иногда потому, что и не нужно.

Где хранится память scout и можно ли её перенести?

В каталоге проекта .dz/scout/: scan-history.json, last-report.json и config.json. Это обычный JSON — перенос на другую машину равен копированию трёх файлов.

Почему в разделе Gone после --diff сразу много репозиториев?

Gone означает «не найден в этом скане», а не «удалён». Массовое исчезновение почти всегда значит, что источник не ответил — пересчитай имена в строке Sources (нулевые источники из неё исчезают), а в своём коде прочитай statusBySource.

Можно ли поменять веса формулы 40 / 30 / 20 / 10?

Из командной строки — нет, веса зашиты в src/analyzer.ts. Порог глубокого анализа (по умолчанию 50) задаётся параметром minScore в программном API deepAnalyze.