Handbooks
Концепции

Достоверность анализа

Два уровня анализа производят внешне одинаковый результат. Это ловушка, поэтому каждый адаптер объявляет, что он способен выдать, а руководство это раскрывает.

Проблема

Handbooks анализирует 18 языков двумя движками:

  • Полный уровень (full) — написанный вручную адаптер для каждого языка, с разрешением вызовов по типам, унаследованными членами, отслеживанием состояния по атрибутам и диапазонами операторов.
  • Универсальный уровень (generic) — один движок на основе конфигурации с декларативной спецификацией для каждого языка. Инвентаризация файлов и функций точна; отношения вызовов — по мере возможностей.

Оба производят одно и то же промежуточное представление. Ничто ниже по потоку не может различить их, глядя на узлы и рёбра.

В этом и ловушка. Читатель — и особенно агент — принял бы ребро вызова универсального уровня за факт питоновского качества и рассуждал бы на его основе соответственно.

Решение: объявить, записать, раскрыть

1. Каждый адаптер объявляет, что он способен выдать

interface AdapterCapabilities {
  tier: 'full' | 'generic';
  callTypes: readonly CallType[]; // which edge kinds it can actually produce
  selfAttrs: boolean; // can it track self/this attribute reads and writes?
  statementSpans: boolean; // can it report statement spans (resync precision)?
}

Это поле обязательное, а не опциональное. Адаптеры может регистрировать кто угодно, и самодельный адаптер, не объявивший ничего, просто не попадает в метаданные графа — вместо того чтобы получить выдуманное за него заявление о достоверности.

2. Phase 1 записывает это для каждого языка

phase1/graph.json (excerpt)
{
  "metadata": {
    "language": "multi",
    "languages": {
      "typescript": { "tier": "full", "selfAttrs": true, "statementSpans": true, "callTypes": ["..."] },
      "kotlin": { "tier": "generic", "selfAttrs": false, "statementSpans": false, "callTypes": ["..."] }
    }
  }
}

Для каждого языка, а не для графа в целом — многоязычный запуск смешивает уровни, и единственная метка language: "multi" полностью скрыла бы это.

3. Руководство говорит об этом там, где формируется доверие

Когда присутствует хоть один язык универсального уровня, обзор получает одну строку сразу под системной прозой:

Достоверность анализа — отношения вызовов для Kotlin, Scala получены универсальным (управляемым конфигурацией) анализатором: они построены по мере возможностей и могут быть неполными. Инвентаризация файлов и структура этих языков точны.

И нигде вообще, когда все языки полного уровня, — так обычный случай остаётся свободным от шума. То же раскрытие появляется в HTML-сайте, индексе-локаторе для агентов и llms-full.txt.

Какой уровень у моего языка?

Полный уровень: Python, TypeScript (и JavaScript), Go, Rust, Java, C#, C/C++, Ruby, PHP, Swift, Dart, Solidity, Shell.

Универсальный уровень: Kotlin, Scala, Zig, Objective-C, OCaml.

Расширения и оговорки — в Поддержке языков.

Чего на самом деле стоит «по мере возможностей»

Полный уровеньУниверсальный уровень
Инвентаризация файловточноточно
Инвентаризация функций и методовточноточно
Диапазоны строк и сигнатурыточноточно
Прямые вызовы по имениточнов основном
self.method() / this.method()разрешаетсячасто
self.attr.method() через известный типразрешаетсянет
param.method() через аннотацию типаразрешаетсянет
Унаследованные членыразрешаетсянет
Отслеживание состояния по атрибутамданет
Диапазоны операторов (точность resync)данет

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

Две честные оговорки

Swift. Встроенная грамматика аварийно завершает процесс на V8 ≥ 13 — измерено: фатально 5 раз из 5 на Node 24, нормально на Node 21, и уникально для этой одной грамматики из девятнадцати. На таком рантайме адаптер отказывается на этапе discovery и называет средство (node --liftoff-only), вместо того чтобы уронить весь ваш запуск.

Shell. Скрипт, содержащий оператор case, пропускается, потому что эта грамматика бросает исключение — её внешний сканер импортирует символ, который зафиксированный WASM-линкер не предоставляет. Поскольку case вездесущ, это большинство нетривиальных скриптов (измерено на nvm: все 6 файлов, все 122 функции), так что считайте покрытие shell частичным. Журнал сканирования называет причину, а каждый пропущенный скрипт отдельно попадает в phase1/scan-coverage.json с reason: "unparsable" — этот пробел можно перечислить, а не угадывать.

Оба случая сообщаются через логгер во время сканирования. Запустите с -v, чтобы их увидеть.

Перевод языка на уровень выше

Язык универсального уровня — это декларативная спецификация, а не парсер — см. Добавление языка. Повышение до полного уровня означает реализацию LanguageAdapter напрямую и объявление честных возможностей. Контракт адаптера намеренно мал.

На этой странице