| name | spec-analysis |
| description | Провести полный анализ соответствия спецификации OpenTelemetry. Парсит спецификацию с сайта, разбивает на секции с полным текстом, агенты верифицируют требования по коду и записывают результат в JSON, скрипт сборки детерминированно генерирует docs/spec-compliance.md.
|
Обзор
Скилл выполняет spec-first анализ соответствия реализации спецификации OpenTelemetry.
Результат - файл docs/spec-compliance.md с трассируемым чеклистом: каждое MUST/SHOULD требование привязано к конкретному файлу и строке в коде.
Принцип работы
scripts/extract_requirements.py - разбивает спецификацию на секции по заголовкам, сохраняет полный текст каждой секции в sections.json
scripts/generate_prompts.py - группирует секции в агентов (5-8 секций на агента), генерирует промпты с JSON-схемой вывода
- Оркестратор запускает general-purpose агентов, каждый записывает результат в
results/<agent>.json
scripts/assemble_report.py - детерминированно собирает docs/spec-compliance.md из JSON-результатов
Ключевое свойство: воспроизводимость
Повторный запуск скилла на том же коде должен давать те же статусы (found/partial/not_found/n_a).
Формулировки пояснений могут отличаться (генеративная природа агентов), но статусы - нет.
Это достигается за счёт:
- Строгого правила
1 keyword = 1 requirement: каждое вхождение MUST/SHOULD = отдельная запись
- Динамического
expected_keywords: regex считает ключевые слова в тексте секции (пропуская код-блоки)
- Валидации и ретрая: агенты с несовпавшим count перезапускаются (до 2 раз)
- Структурированного JSON-вывода от агентов (не свободный текст)
- Строгих критериев статуса в промптах (определённые условия для found/partial/not_found)
- Детерминированной сборки скриптом (JSON → markdown без потерь)
Никаких ad-hoc скриптов: всё необходимое входит в скилл. Оркестратор только запускает скрипты и агентов.
Классификация секций
Каждая секция классифицируется по двум осям:
Стабильность (определяется маркерами Status: в тексте спецификации):
- Stable - стабильное требование, обязательное к исполнению
- Development - нестабильное, может измениться в будущих версиях
Область применения (scope):
- universal - обязательно для любой реализации SDK
- conditional - обязательно только при реализации конкретной опциональной фичи
- deprecated - относится к устаревшей функциональности (Jaeger, OT Trace)
Ключевое правило: основной процент соответствия считается только по Stable + universal требованиям.
Известные условные секции:
| Подраздел спецификации | Фича | Почему условная |
|---|
| GetAll | GetAll Getter | Добавляется после stable релиза Getter |
| Resource detector name | Resource Detector Naming | Только для SDK с реализованными детекторами |
B3 Propagator и Prometheus Exporter ранее были условными, но теперь реализованы
(ОтелB3Пропагатор, ОтелПрометеусЧитательМетрик) и считаются как universal.
Шаг 1: Извлечение секций из спецификации
Запусти Python-скрипт для парсинга всех страниц спецификации OTel.
ВАЖНО: Скрипт загружает 12 страниц с opentelemetry.io. Убедись, что есть доступ в интернет.
При повторных запусках скрипт использует кеш из <output_dir>/*.txt. Удали кеш-файлы для обновления.
python3 .github/skills/spec-analysis/scripts/extract_requirements.py /tmp/otel-specs
Скрипт:
- Загружает 12 страниц спецификации
- Разбивает каждую страницу на секции по заголовкам (
##/###)
- Для каждой секции сохраняет полный текст, URL-якорь, стабильность, scope
- Считает количество MUST/SHOULD ключевых слов в каждой секции
- Сохраняет результат в
/tmp/otel-specs/sections.json
Ожидаемый результат: ~200-250 секций, в сумме содержащих ~800+ ключевых слов MUST/SHOULD.
Шаг 2: Генерация промптов для агентов
python3 .github/skills/spec-analysis/scripts/generate_prompts.py /tmp/otel-specs
Скрипт:
- Читает
sections.json
- Группирует секции по доменам (Context, Traces, Logs, Metrics, Export и т.д.)
- Разбивает крупные домены на группы по 5-8 секций
- Для каждого агента генерирует промпт с:
- Полным текстом секций
- Строгими критериями статуса (found/partial/not_found/n_a)
- JSON-схемой вывода
- Инструкцией записать результат в
results/<agent>.json
- Сохраняет
agents.json (конфигурация с launch_prompt) и prompts/<agent>.md (промпты)
Все критерии верификации, примеры false positive и правила n_a определены в scripts/generate_prompts.py (константа AGENT_INSTRUCTIONS).
Для изменения критериев - редактируй эту константу.
Ожидаемый результат: ~30-40 агентов.
Шаг 3: Запуск агентов верификации
ВАЖНО: Используй agent_type: "general-purpose" (Sonnet), НЕ explore (Haiku).
Haiku не обладает достаточной глубиной рассуждений для корректной верификации.
3.1. Прочитай список агентов
python3 -c "
import json
with open('/tmp/otel-specs/agents.json') as f:
agents = json.load(f)
for a in agents:
print(a['name'])
print(f'Всего: {len(agents)} агентов')
"
3.2. Запуск волнами по 10
Каждый агент в agents.json содержит поле launch_prompt - готовый к использованию промпт.
Агент по этому промпту сам прочитает свой файл инструкций и выполнит анализ.
Запускай агентов волнами по 10 штук (не больше) за один tool-calling ход:
Для каждого agent из agents.json:
task(
agent_type = "general-purpose",
mode = "background",
name = agent["name"],
prompt = agent["launch_prompt"]
)
Порядок волн:
- Запусти первые 10 агентов (одним tool-calling ходом)
- Подожди 60 секунд (
bash: sleep 60) - пауза для восстановления rate limit
- Запусти следующие 10 агентов
- Подожди 60 секунд
- Запусти оставшихся агентов
- Повторяй до запуска всех
Почему 10, а не 36? Sonnet-агенты потребляют значительный rate limit.
Запуск всех сразу приводит к массовым 429-ошибкам - агенты получают rate limit
на первом же запросе и завершаются без результата.
3.3. Обработка ошибок при запуске
- "Maximum concurrent agent limit reached": подожди завершения текущих агентов, затем запусти оставшихся
- 429 rate limit на первом ходе: агент завершится с
total_turns: 0 и без файла результата. Будет перезапущен на шаге 3.5
3.4. Проверка результатов
После завершения всех агентов проверь, что файлы записаны:
ls /tmp/otel-specs/results/*.json | wc -l
3.5: Валидация и повторный запуск
КРИТИЧЕСКИ ВАЖНО: Агенты обязаны вернуть данные по 100% секций и 100% ключевых слов.
Повторяй до тех пор, пока все не будут пройдены. Rate limit - не причина остановиться.
После завершения всех агентов обязательно выполни проверку:
python3 -c "
import json, os
with open('/tmp/otel-specs/agents.json') as f:
agents = json.load(f)
missing = []
mismatched = []
for agent in agents:
name = agent['name']
path = f\"/tmp/otel-specs/results/{name}.json\"
if not os.path.exists(path):
missing.append(name)
continue
with open(path) as f:
result = json.load(f)
for section in result['sections']:
expected = section['expected_keywords']
actual = len(section.get('requirements', []))
if actual != expected:
mismatched.append(f'{name}: {section[\"section_id\"]} expected={expected} actual={actual}')
if missing:
print(f'❌ Отсутствуют результаты ({len(missing)}):')
for m in missing:
print(f' {m}')
if mismatched:
print(f'⚠️ Несовпадения keywords ({len(mismatched)}):')
for m in mismatched:
print(f' {m}')
if not missing and not mismatched:
print(f'✅ Все {len(agents)} агентов вернули корректные результаты')
"
Rate limit (429) - отсутствующие результаты
Если агенты упали по rate limit (результат отсутствует, total_turns: 0 в read_agent):
- Подожди 120 секунд (
bash: sleep 120) перед перезапуском - rate limit должен восстановиться
- Перезапускай волнами по 5 (не 10!) - при повторе лимит ещё может быть частично исчерпан
- Пауза 120 секунд между волнами повторов
- Используй тот же
launch_prompt из agents.json
- Если вторая попытка тоже упала в 429 - увеличь паузу до 300 секунд и повтори
- До 3 попыток на каждого агента
Волна повтора:
sleep 120
→ запусти 5 агентов
→ дождись завершения
sleep 120
→ запусти следующие 5
→ ...
НЕ ОСТАНАВЛИВАЙСЯ при rate limit. Увеличивай паузу и продолжай.
Смена модели (например, на claude-sonnet-4) допустима как крайняя мера,
если основная модель заблокирована более 10 минут.
Несовпадения keywords
Если агент вернул неверное количество требований:
- Удали результат:
rm -f /tmp/otel-specs/results/<name>.json
- Перезапусти агента с дополнительным префиксом перед
launch_prompt:
⚠️ ПОВТОРНЫЙ ЗАПУСК: В предыдущей попытке количество требований не совпало.
Ошибки:
- Секция <section_id>: ожидалось <expected>, получено <actual>
Перечитай текст секции ВНИМАТЕЛЬНО и убедись, что нашёл РОВНО expected_keywords ключевых слов.
<оригинальный launch_prompt>
- До 3 попыток; если не удалось - зафиксируй расхождение и переходи к шагу 4
Шаг 4: Сборка итогового документа
python3 .github/skills/spec-analysis/scripts/assemble_report.py /tmp/otel-specs docs/spec-compliance.md
Скрипт:
- Загружает все
results/*.json
- Валидирует полноту (все секции покрыты, keywords ≈ найденным требованиям)
- Вычисляет статистику по доменам
- Детерминированно генерирует markdown с каждым требованием как отдельной строкой таблицы
- Загружает предыдущую версию
docs/spec-compliance.md из git (HEAD)
- Сравнивает построчно каждое требование: статус, расположение, пояснение
- Записывает отчёт расхождений в файл
<output_dir>/comparison-report.txt
- Записывает новый отчёт
docs/spec-compliance.md
Категории расхождений:
- 🔴 Понижение (found→partial, found→not_found) - возможная регрессия
- 🟢 Повышение (not_found→found, partial→found) - возможный прогресс
- 🔄 Боковое (partial↔not_found) - переоценка без явного улучшения
- ➕ Новые - требования, которых не было в предыдущем анализе
- ➖ Пропущенные - требования, исчезнувшие из нового анализа
Для каждого расхождения указываются возможные причины:
- Реальное изменение в коде
- Агент оценил строже/мягче при повторном анализе
- Ложное срабатывание
Структура выходного документа:
docs/spec-compliance.md
├── Сводка (Stable) - общий процент, MUST/SHOULD отдельно, таблица по разделам
├── Ключевые несоответствия (Stable)
│ ├── MUST/MUST NOT нарушения
│ └── SHOULD/SHOULD NOT несоответствия
├── Детальный анализ по разделам (Stable) - каждая секция = ####, каждое требование = строка таблицы
├── Требования Development-статуса - с полными таблицами
├── Условные требования (Conditional) - с полными таблицами для Stable+conditional
├── Ограничения платформы OneScript
└── Методология
Каждая секция спецификации = отдельный подзаголовок (####).
Каждое MUST/SHOULD = отдельная строка таблицы с полным текстом, статусом, расположением в коде и пояснением.
Шаг 4.5: Проверка полноты отчёта
Скрипт scripts/assemble_report.py автоматически проверяет полноту:
📊 Валидация полноты:
Keywords в спецификации: 824
Требований от агентов (JSON): 824
Требований в markdown: 824
✅ Все 824 требований присутствуют (JSON: 824, markdown: 824)
Если total не совпадает (❌ ОШИБКА в выводе):
- Посмотри какие секции не совпали (скрипт покажет)
- Перезапусти соответствующих агентов (Шаг 3.5)
- Повтори сборку (Шаг 4)
- Повторяй пока не будет 100% совпадение
Шаг 5: Проверка сравнения
Сравнение выполняется автоматически в шаге 4. Скрипт записывает подробный отчёт расхождений в файл:
docs/spec-comparison-report.md
ВАЖНО: Отчёт сохраняется в файл в репозитории (рядом с spec-compliance.md), а не выводится в терминал.
Это критически важно, потому что он может быть очень большим (сотни строк)
и вымывается из контекста при выводе в stdout. Всегда читай его из файла.
5.1. Прочитай отчёт сравнения
cat docs/spec-comparison-report.md
Если файл слишком большой, используй view tool для чтения по частям.
5.2. Анализ расхождений
Обрати внимание на:
- 🔴 Понижения - могут указывать на регрессию в коде. Проверь каждое.
- ➖ Пропущенные - агент мог пропустить требование из-за другой группировки
- ➕ Новые - агент нашёл требования, которые раньше не выделялись
Если изменений много (>10 понижений или >20 пропущенных требований), дополнительно проверь diff:
git --no-pager diff docs/spec-compliance.md | head -100
Шаг 6: Коммит
git add docs/spec-compliance.md docs/spec-comparison-report.md
git commit -m "docs: обновить анализ соответствия спецификации OpenTelemetry vX.Y.Z
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
Ограничения платформы OneScript
При анализе учитывай, что OneScript не поддерживает:
- Наносекундную точность времени (только миллисекунды)
- TLS/mTLS конфигурацию сертификатов
- X-Ray пропагатор (реализованы W3C TraceContext, W3C Baggage и B3)
- Число = System.Decimal (не IEEE 754): NaN, Infinity, отрицательный ноль невозможны
Версия спецификации
Текущая версия спецификации определяется автоматически из заголовка страницы при парсинге. Если версия изменилась, обнови бейдж в README.md:
[](docs/spec-compliance.md)