feat(registry): токенизация needs/produces — группа tools/MCP, ЭТАП 2b ЗАВЕРШЁН (роутер-реестр)
Phase 2b группа C (финал): 51 атомарный инструмент (MCP-серверы + линтеры/ тулинг) переведены на токены словаря. Словарь +98, всего 265 токенов, v0.6.0. ИТОГ ЭТАПА 2b: ВСЕ 153 контракта needs/produces на токенах словаря. - замок словаря проходит на полном наборе (0 unknown) — готовность к 2d; - граф ожил: A8-цепочка, superpowers, knowledge-work, кросс-плагинные мосты (write-spec->writing-plans, frontend-design->design-handoff). Тест: финальный замок-тест всего реестра (153 контракта + рёбра графа). Регрессия 4373 passed, exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.0",
|
||||
"tokens": [
|
||||
{
|
||||
"token": "running-portal",
|
||||
@@ -1002,6 +1002,594 @@
|
||||
"category": "given",
|
||||
"label": "промпт + тест-кейсы",
|
||||
"description": "LLM-промпт + кейсы для eval. Вход promptfoo."
|
||||
},
|
||||
{
|
||||
"token": "ui-template-draft",
|
||||
"category": "produced",
|
||||
"label": "стартовый UI-шаблон",
|
||||
"description": "LLM-сгенерированный UI-шаблон. Выход 21st-magic."
|
||||
},
|
||||
{
|
||||
"token": "db-or-docs-result",
|
||||
"category": "produced",
|
||||
"label": "результат SQL/Eloquent или docs",
|
||||
"description": "Результат запроса к dev-БД или релевантная докуменация Laravel. Выход boost."
|
||||
},
|
||||
{
|
||||
"token": "library-docs",
|
||||
"category": "produced",
|
||||
"label": "документация библиотеки",
|
||||
"description": "Актуальная документация библиотеки/SDK. Выход context7."
|
||||
},
|
||||
{
|
||||
"token": "ru-seo-data",
|
||||
"category": "produced",
|
||||
"label": "SEO-данные РФ",
|
||||
"description": "SERP/бэклинки/конкурентный анализ РФ. Выход dataforseo-mcp."
|
||||
},
|
||||
{
|
||||
"token": "semantic-web-results",
|
||||
"category": "produced",
|
||||
"label": "семантический веб-поиск",
|
||||
"description": "Результаты по смыслу + страница по URL. Выход exa-mcp."
|
||||
},
|
||||
{
|
||||
"token": "figma-tokens",
|
||||
"category": "produced",
|
||||
"label": "дизайн-токены Figma",
|
||||
"description": "Извлечённые токены/компоненты/стили. Выход figma-mcp."
|
||||
},
|
||||
{
|
||||
"token": "web-page-content",
|
||||
"category": "produced",
|
||||
"label": "содержимое страниц",
|
||||
"description": "Scrape/crawl/map/extract + web-research. Выход firecrawl-mcp."
|
||||
},
|
||||
{
|
||||
"token": "github-op-result",
|
||||
"category": "produced",
|
||||
"label": "результат GitHub-операции",
|
||||
"description": "Чтение/запись issue/PR/комментария. Выход github-mcp."
|
||||
},
|
||||
{
|
||||
"token": "notebook-result",
|
||||
"category": "produced",
|
||||
"label": "результат ноутбука",
|
||||
"description": "Результат исполнения ячеек. Выход jupyter-mcp."
|
||||
},
|
||||
{
|
||||
"token": "n8n-automation",
|
||||
"category": "produced",
|
||||
"label": "автоматизация n8n",
|
||||
"description": "Автоматизация процесса через n8n. Выход n8n-mcp."
|
||||
},
|
||||
{
|
||||
"token": "api-resources",
|
||||
"category": "produced",
|
||||
"label": "API-ресурсы (чтение)",
|
||||
"description": "Эндпоинты/схемы/параметры как MCP-ресурсы. Выход openapi-mcp."
|
||||
},
|
||||
{
|
||||
"token": "web-answer-cited",
|
||||
"category": "produced",
|
||||
"label": "web-ответ с цитатами",
|
||||
"description": "Ранжированный ответ sonar (search/ask/research/reason). Выход perplexity-mcp."
|
||||
},
|
||||
{
|
||||
"token": "browser-interaction-result",
|
||||
"category": "produced",
|
||||
"label": "результат браузера",
|
||||
"description": "Скриншот/взаимодействие/console+network. Выход playwright-mcp."
|
||||
},
|
||||
{
|
||||
"token": "sql-result",
|
||||
"category": "produced",
|
||||
"label": "результат SQL",
|
||||
"description": "Результат исторического SQL к dev-БД. Выход postgres-mcp."
|
||||
},
|
||||
{
|
||||
"token": "scheduled-social-posts",
|
||||
"category": "produced",
|
||||
"label": "запланированные публикации",
|
||||
"description": "Публикации в 30+ соцсетях (VK/Telegram). Выход postiz."
|
||||
},
|
||||
{
|
||||
"token": "redis-state",
|
||||
"category": "produced",
|
||||
"label": "состояние Redis",
|
||||
"description": "Ключи/очереди/TTL/паттерны (чтение). Выход redis-mcp."
|
||||
},
|
||||
{
|
||||
"token": "sentry-events",
|
||||
"category": "produced",
|
||||
"label": "события Sentry",
|
||||
"description": "События/ошибки/трассировки (чтение). Выход sentry-mcp."
|
||||
},
|
||||
{
|
||||
"token": "telegram-result",
|
||||
"category": "produced",
|
||||
"label": "результат Telegram",
|
||||
"description": "Публикация/редактирование/аналитика канала. Выход telegram-mcp."
|
||||
},
|
||||
{
|
||||
"token": "email-blast-sent",
|
||||
"category": "produced",
|
||||
"label": "email-рассылка отправлена",
|
||||
"description": "Отправка маркетинговой рассылки. Выход unisender-go-mcp."
|
||||
},
|
||||
{
|
||||
"token": "svg-icon",
|
||||
"category": "produced",
|
||||
"label": "SVG-иконка",
|
||||
"description": "Иконка из не-Lucide коллекции (Material/Tabler/Phosphor). Выход universal-icons-mcp."
|
||||
},
|
||||
{
|
||||
"token": "metrika-data",
|
||||
"category": "produced",
|
||||
"label": "данные Яндекс.Метрики",
|
||||
"description": "Визиты/источники/гео/поведение. Выход yandex-metrika-mcp."
|
||||
},
|
||||
{
|
||||
"token": "wordstat-frequency",
|
||||
"category": "produced",
|
||||
"label": "частотность Wordstat",
|
||||
"description": "Частотность РФ-запросов: сезонность/связанные. Выход yandex-wordstat-mcp."
|
||||
},
|
||||
{
|
||||
"token": "spelling-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт орфографии",
|
||||
"description": "Отчёт о неизвестных словах. Выход cspell."
|
||||
},
|
||||
{
|
||||
"token": "cve-dependency-pr",
|
||||
"category": "produced",
|
||||
"label": "auto-PR на CVE зависимости",
|
||||
"description": "Auto-PR при CVE в зависимости. Выход dependabot."
|
||||
},
|
||||
{
|
||||
"token": "layer-violation-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт нарушений слоёв",
|
||||
"description": "Нарушения границ слоёв. Выход deptrac."
|
||||
},
|
||||
{
|
||||
"token": "linted-js-vue",
|
||||
"category": "produced",
|
||||
"label": "пролинченный JS/Vue",
|
||||
"description": "Исправленный/проверенный JS/Vue (ESLint+Prettier). Выход eslint-prettier."
|
||||
},
|
||||
{
|
||||
"token": "secret-leak-findings",
|
||||
"category": "produced",
|
||||
"label": "находки утечек секретов",
|
||||
"description": "Ключи/токены/пароли/DSN. Выход gitleaks."
|
||||
},
|
||||
{
|
||||
"token": "stories-catalog",
|
||||
"category": "produced",
|
||||
"label": "каталог stories",
|
||||
"description": "Визуальный каталог stories/variants. Выход histoire."
|
||||
},
|
||||
{
|
||||
"token": "ide-stubs",
|
||||
"category": "produced",
|
||||
"label": "IDE-заглушки",
|
||||
"description": "@mixin IdeHelper* для autocomplete. Выход ide-helper."
|
||||
},
|
||||
{
|
||||
"token": "php-type-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт типов PHP",
|
||||
"description": "Ошибки типов/сигнатур/undefined. Выход larastan."
|
||||
},
|
||||
{
|
||||
"token": "broken-link-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт битых ссылок",
|
||||
"description": "Битые URL и якоря. Выход lychee."
|
||||
},
|
||||
{
|
||||
"token": "markdown-style-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт стиля Markdown",
|
||||
"description": "Нарушения стиля Markdown. Выход markdownlint."
|
||||
},
|
||||
{
|
||||
"token": "mermaid-diagram",
|
||||
"category": "produced",
|
||||
"label": "диаграмма Mermaid",
|
||||
"description": "Диаграмма в нотации Mermaid/C4. Выход mermaid."
|
||||
},
|
||||
{
|
||||
"token": "runtime-trace",
|
||||
"category": "produced",
|
||||
"label": "runtime-трейс",
|
||||
"description": "Коррелированный request/job/query трейс. Выход nightowl."
|
||||
},
|
||||
{
|
||||
"token": "a11y-violations-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт a11y (рантайм)",
|
||||
"description": "Нарушения WCAG 2.1 AA на странице. Выход pa11y."
|
||||
},
|
||||
{
|
||||
"token": "php-test-result",
|
||||
"category": "produced",
|
||||
"label": "результат Pest",
|
||||
"description": "Pass/fail/assertions PHP-тестов. Выход pest."
|
||||
},
|
||||
{
|
||||
"token": "masked-dump",
|
||||
"category": "produced",
|
||||
"label": "маскированный дамп",
|
||||
"description": "Дамп с маской ПДн (телефоны/имена/email). Выход pg-anonymizer."
|
||||
},
|
||||
{
|
||||
"token": "db-audit-log",
|
||||
"category": "produced",
|
||||
"label": "аудит-журнал БД",
|
||||
"description": "Журнал DDL/DML/DCL операций. Выход pg-audit."
|
||||
},
|
||||
{
|
||||
"token": "formatted-sql",
|
||||
"category": "produced",
|
||||
"label": "отформатированный SQL",
|
||||
"description": "Отступы/регистр/выравнивание. Выход pg-formatter."
|
||||
},
|
||||
{
|
||||
"token": "auto-partitions",
|
||||
"category": "produced",
|
||||
"label": "авто-партиции",
|
||||
"description": "Создание/удаление partition по расписанию. Выход pg-partman."
|
||||
},
|
||||
{
|
||||
"token": "php-quality-metrics",
|
||||
"category": "produced",
|
||||
"label": "метрики качества PHP",
|
||||
"description": "Сложность/архитектура/code style. Выход php-insights."
|
||||
},
|
||||
{
|
||||
"token": "formatted-php",
|
||||
"category": "produced",
|
||||
"label": "отформатированный PHP",
|
||||
"description": "PSR-12 + Laravel style. Выход pint."
|
||||
},
|
||||
{
|
||||
"token": "refactored-php",
|
||||
"category": "produced",
|
||||
"label": "рефакторенный PHP",
|
||||
"description": "Upgrade/dead-code/modernization. Выход rector."
|
||||
},
|
||||
{
|
||||
"token": "composer-cve-block",
|
||||
"category": "produced",
|
||||
"label": "блок CVE-пакета",
|
||||
"description": "Блок установки пакета с известным CVE. Выход roave-security."
|
||||
},
|
||||
{
|
||||
"token": "sast-report",
|
||||
"category": "produced",
|
||||
"label": "SAST-отчёт",
|
||||
"description": "Уязвимости кода (инъекции/XSS/конфиг). Выход semgrep."
|
||||
},
|
||||
{
|
||||
"token": "migration-danger-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт опасной миграции",
|
||||
"description": "Блокировки/без CONCURRENTLY/ненадёжный DEFAULT. Выход squawk."
|
||||
},
|
||||
{
|
||||
"token": "css-style-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт стиля CSS",
|
||||
"description": "Нарушения стиля CSS. Выход stylelint."
|
||||
},
|
||||
{
|
||||
"token": "image-cve-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт CVE образа",
|
||||
"description": "CVE в OS-пакетах и зависимостях образа. Выход trivy."
|
||||
},
|
||||
{
|
||||
"token": "vitest-result",
|
||||
"category": "produced",
|
||||
"label": "результат Vitest",
|
||||
"description": "Pass/fail unit/component. Выход vitest."
|
||||
},
|
||||
{
|
||||
"token": "editor-type-diagnostics",
|
||||
"category": "produced",
|
||||
"label": "диагностика в редакторе",
|
||||
"description": "IntelliSense/go-to-def/hover/типы. Выход volar."
|
||||
},
|
||||
{
|
||||
"token": "vue-type-report",
|
||||
"category": "produced",
|
||||
"label": "отчёт типов Vue",
|
||||
"description": "Несоответствия типов в шаблонах/script. Выход vue-tsc."
|
||||
},
|
||||
{
|
||||
"token": "ui-template-intent",
|
||||
"category": "given",
|
||||
"label": "намерение UI-шаблона",
|
||||
"description": "Компонент/лейаут/форма. Вход 21st-magic."
|
||||
},
|
||||
{
|
||||
"token": "db-or-docs-query",
|
||||
"category": "given",
|
||||
"label": "запрос к БД или docs",
|
||||
"description": "SQL/Eloquent к dev-БД или вопрос по docs Laravel. Вход boost."
|
||||
},
|
||||
{
|
||||
"token": "library-api-question",
|
||||
"category": "given",
|
||||
"label": "вопрос по API библиотеки",
|
||||
"description": "Вопрос по API/доке библиотеки/SDK. Вход context7."
|
||||
},
|
||||
{
|
||||
"token": "ru-seo-question",
|
||||
"category": "given",
|
||||
"label": "SEO-вопрос РФ",
|
||||
"description": "SERP/ключевые/бэклинки РФ. Вход dataforseo-mcp."
|
||||
},
|
||||
{
|
||||
"token": "semantic-search-need",
|
||||
"category": "given",
|
||||
"label": "нужен семантический поиск",
|
||||
"description": "Найти источники по смыслу. Вход exa-mcp."
|
||||
},
|
||||
{
|
||||
"token": "figma-file",
|
||||
"category": "given",
|
||||
"label": "Figma-файл",
|
||||
"description": "Файл с дизайн-токенами/компонентами. Вход figma-mcp."
|
||||
},
|
||||
{
|
||||
"token": "web-read-need",
|
||||
"category": "given",
|
||||
"label": "нужно прочитать страницу/сайт",
|
||||
"description": "Прочитать/обойти/извлечь со страниц. Вход firecrawl-mcp."
|
||||
},
|
||||
{
|
||||
"token": "repo-ref",
|
||||
"category": "given",
|
||||
"label": "ссылка на repo/issue/PR",
|
||||
"description": "Ссылка на repo/issue/PR. Вход github-mcp."
|
||||
},
|
||||
{
|
||||
"token": "github-operation-intent",
|
||||
"category": "given",
|
||||
"label": "намерение GitHub-операции",
|
||||
"description": "Операция чтения/записи. Вход github-mcp."
|
||||
},
|
||||
{
|
||||
"token": "jupyter-notebook",
|
||||
"category": "given",
|
||||
"label": "Jupyter-ноутбук",
|
||||
"description": "Ноутбук для исполнения. Вход jupyter-mcp."
|
||||
},
|
||||
{
|
||||
"token": "n8n-workflow",
|
||||
"category": "given",
|
||||
"label": "workflow n8n",
|
||||
"description": "Workflow для движка n8n. Вход n8n-mcp."
|
||||
},
|
||||
{
|
||||
"token": "openapi-spec",
|
||||
"category": "given",
|
||||
"label": "OpenAPI-спецификация",
|
||||
"description": "OpenAPI/REST-спека интеграции. Вход openapi-mcp."
|
||||
},
|
||||
{
|
||||
"token": "web-research-question",
|
||||
"category": "given",
|
||||
"label": "вопрос веб-разведки",
|
||||
"description": "Актуальные практики/нормы/конкуренты с источниками. Вход perplexity-mcp."
|
||||
},
|
||||
{
|
||||
"token": "browser-target",
|
||||
"category": "given",
|
||||
"label": "URL/HTML для браузера",
|
||||
"description": "URL или HTML-файл для управления. Вход playwright-mcp."
|
||||
},
|
||||
{
|
||||
"token": "browser-action-intent",
|
||||
"category": "given",
|
||||
"label": "намерение действия браузера",
|
||||
"description": "Скриншот/взаимодействие/сетевой трейс. Вход playwright-mcp."
|
||||
},
|
||||
{
|
||||
"token": "historical-sql-query",
|
||||
"category": "given",
|
||||
"label": "исторический SQL-запрос",
|
||||
"description": "Исторический SQL к dev-БД. Вход postgres-mcp."
|
||||
},
|
||||
{
|
||||
"token": "social-content-plan",
|
||||
"category": "given",
|
||||
"label": "план публикаций",
|
||||
"description": "Контент-календарь/план соцсетей. Вход postiz."
|
||||
},
|
||||
{
|
||||
"token": "redis-state-question",
|
||||
"category": "given",
|
||||
"label": "вопрос о состоянии Redis",
|
||||
"description": "Ключи/очереди/TTL. Вход redis-mcp."
|
||||
},
|
||||
{
|
||||
"token": "prod-runtime-error",
|
||||
"category": "given",
|
||||
"label": "production runtime ошибка",
|
||||
"description": "Ошибка для диагностики. Вход sentry-mcp."
|
||||
},
|
||||
{
|
||||
"token": "telegram-action",
|
||||
"category": "given",
|
||||
"label": "действие в Telegram",
|
||||
"description": "Пост/действие в канале. Вход telegram-mcp."
|
||||
},
|
||||
{
|
||||
"token": "email-blast-task",
|
||||
"category": "given",
|
||||
"label": "массовая email-рассылка",
|
||||
"description": "Рассылка через Unisender Go. Вход unisender-go-mcp."
|
||||
},
|
||||
{
|
||||
"token": "svg-icon-need",
|
||||
"category": "given",
|
||||
"label": "нужна SVG-иконка",
|
||||
"description": "Иконка не-Lucide коллекции. Вход universal-icons-mcp."
|
||||
},
|
||||
{
|
||||
"token": "web-analytics-question",
|
||||
"category": "given",
|
||||
"label": "вопрос веб-аналитики",
|
||||
"description": "Аналитика лендинга. Вход yandex-metrika-mcp."
|
||||
},
|
||||
{
|
||||
"token": "keyword-topic",
|
||||
"category": "given",
|
||||
"label": "тема для ключевых слов",
|
||||
"description": "Тема для подбора ключевых. Вход yandex-wordstat-mcp."
|
||||
},
|
||||
{
|
||||
"token": "markdown-files",
|
||||
"category": "given",
|
||||
"label": "Markdown-файлы",
|
||||
"description": "Markdown для проверки. Вход cspell/lychee/markdownlint."
|
||||
},
|
||||
{
|
||||
"token": "project-dictionary",
|
||||
"category": "given",
|
||||
"label": "словарь проекта",
|
||||
"description": "Пользовательский словарь орфографии. Вход cspell."
|
||||
},
|
||||
{
|
||||
"token": "project-dependencies",
|
||||
"category": "given",
|
||||
"label": "зависимости проекта",
|
||||
"description": "Composer/npm зависимости. Вход dependabot."
|
||||
},
|
||||
{
|
||||
"token": "php-layers",
|
||||
"category": "given",
|
||||
"label": "PHP-слои",
|
||||
"description": "Слои для проверки направления зависимостей. Вход deptrac."
|
||||
},
|
||||
{
|
||||
"token": "js-vue-source",
|
||||
"category": "given",
|
||||
"label": "JS/Vue-код",
|
||||
"description": "JS/Vue для линта/тестов. Вход eslint-prettier/vitest."
|
||||
},
|
||||
{
|
||||
"token": "git-diff-or-history",
|
||||
"category": "given",
|
||||
"label": "git diff/история",
|
||||
"description": "Diff или история репозитория. Вход gitleaks."
|
||||
},
|
||||
{
|
||||
"token": "vue-component",
|
||||
"category": "given",
|
||||
"label": "Vue-компонент",
|
||||
"description": "Vue-компонент(ы) для каталога/проверки типов. Вход histoire/vue-tsc."
|
||||
},
|
||||
{
|
||||
"token": "laravel-project",
|
||||
"category": "given",
|
||||
"label": "Laravel-проект",
|
||||
"description": "Facades/модели/хелперы. Вход ide-helper."
|
||||
},
|
||||
{
|
||||
"token": "php-source",
|
||||
"category": "given",
|
||||
"label": "PHP-код",
|
||||
"description": "PHP-код для анализа/форматирования/рефакторинга. Вход larastan/pint/php-insights/rector."
|
||||
},
|
||||
{
|
||||
"token": "diagram-requirement",
|
||||
"category": "given",
|
||||
"label": "требование к диаграмме",
|
||||
"description": "C4/flow/sequence. Вход mermaid."
|
||||
},
|
||||
{
|
||||
"token": "trace-correlation-need",
|
||||
"category": "given",
|
||||
"label": "нужна корреляция трасс",
|
||||
"description": "Сквозная request/job/query корреляция. Вход nightowl."
|
||||
},
|
||||
{
|
||||
"token": "rendered-page",
|
||||
"category": "given",
|
||||
"label": "отрендеренная страница",
|
||||
"description": "Страница/URL для a11y. Вход pa11y."
|
||||
},
|
||||
{
|
||||
"token": "php-tests",
|
||||
"category": "given",
|
||||
"label": "PHP-тесты",
|
||||
"description": "Unit/feature/RLS тесты. Вход pest."
|
||||
},
|
||||
{
|
||||
"token": "db-dump-with-pii",
|
||||
"category": "given",
|
||||
"label": "дамп с ПДн",
|
||||
"description": "Дамп БД с персональными данными. Вход pg-anonymizer."
|
||||
},
|
||||
{
|
||||
"token": "db-operations",
|
||||
"category": "given",
|
||||
"label": "операции БД",
|
||||
"description": "DDL/DML/DCL операции. Вход pg-audit."
|
||||
},
|
||||
{
|
||||
"token": "sql-file",
|
||||
"category": "given",
|
||||
"label": "SQL-файл",
|
||||
"description": "SQL для форматирования. Вход pg-formatter."
|
||||
},
|
||||
{
|
||||
"token": "partition-schedule",
|
||||
"category": "given",
|
||||
"label": "расписание партиций",
|
||||
"description": "Расписание партиционирования таблиц. Вход pg-partman."
|
||||
},
|
||||
{
|
||||
"token": "composer-install",
|
||||
"category": "given",
|
||||
"label": "composer install/update",
|
||||
"description": "Установка/обновление пакетов. Вход roave-security."
|
||||
},
|
||||
{
|
||||
"token": "code-for-sast",
|
||||
"category": "given",
|
||||
"label": "код для SAST",
|
||||
"description": "PHP/JS/Vue для SAST. Вход semgrep."
|
||||
},
|
||||
{
|
||||
"token": "sql-migration",
|
||||
"category": "given",
|
||||
"label": "SQL-миграция",
|
||||
"description": "Миграция PostgreSQL. Вход squawk."
|
||||
},
|
||||
{
|
||||
"token": "css-source",
|
||||
"category": "given",
|
||||
"label": "CSS-код",
|
||||
"description": "CSS в .vue SFC или .css. Вход stylelint."
|
||||
},
|
||||
{
|
||||
"token": "docker-image",
|
||||
"category": "given",
|
||||
"label": "Docker-образ",
|
||||
"description": "Образ для скана. Вход trivy."
|
||||
},
|
||||
{
|
||||
"token": "open-vue-file",
|
||||
"category": "given",
|
||||
"label": "открытый .vue в VSCode",
|
||||
"description": "Открытый .vue для IntelliSense. Вход volar."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "21st-magic",
|
||||
"kind": "external",
|
||||
"needs": ["намерение UI-шаблона (компонент / лейаут / форма)"],
|
||||
"produces": ["стартовый UI-шаблон (LLM-сгенерированный)"],
|
||||
"constraints": ["генератор шаблонов через PSR_v1 R14.4 pipeline", "Pa11y проверка обязательна после генерации", "стек-фильтр R6.0"],
|
||||
"needs": [
|
||||
"ui-template-intent"
|
||||
],
|
||||
"produces": [
|
||||
"ui-template-draft"
|
||||
],
|
||||
"constraints": [
|
||||
"генератор шаблонов через PSR_v1 R14.4 pipeline",
|
||||
"Pa11y проверка обязательна после генерации",
|
||||
"стек-фильтр R6.0"
|
||||
],
|
||||
"preview-form": "mockup",
|
||||
"defaults": ["после генерации — обязательный Pa11y"],
|
||||
"key-decisions": ["какой шаблон; адаптация под Vue+Vuetify"],
|
||||
"acceptance-criteria": ["шаблон в стеке Vue+Vuetify, Pa11y 0 нарушений"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"после генерации — обязательный Pa11y"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какой шаблон; адаптация под Vue+Vuetify"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"шаблон в стеке Vue+Vuetify, Pa11y 0 нарушений"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "boost",
|
||||
"kind": "external",
|
||||
"needs": ["SQL/Eloquent-запрос к dev-БД или вопрос по docs Laravel/пакета"],
|
||||
"produces": ["результат SQL/Eloquent или релевантная документация Laravel"],
|
||||
"constraints": ["MCP к dev-БД через Roster auto-detect", "НЕ подключать к production DB", "заменил PostgreSQL MCP (#1)"],
|
||||
"needs": [
|
||||
"db-or-docs-query"
|
||||
],
|
||||
"produces": [
|
||||
"db-or-docs-result"
|
||||
],
|
||||
"constraints": [
|
||||
"MCP к dev-БД через Roster auto-detect",
|
||||
"НЕ подключать к production DB",
|
||||
"заменил PostgreSQL MCP (#1)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["read-first; serverить только установленные пакеты (Roster)"],
|
||||
"key-decisions": ["источник: только dev-БД, не прод"],
|
||||
"acceptance-criteria": ["запрос/доки отданы из правильного (dev) источника"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-first; serverить только установленные пакеты (Roster)"
|
||||
],
|
||||
"key-decisions": [
|
||||
"источник: только dev-БД, не прод"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"запрос/доки отданы из правильного (dev) источника"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "context7",
|
||||
"kind": "external",
|
||||
"needs": ["вопрос по API/доке конкретной библиотеки/SDK"],
|
||||
"produces": ["актуальная документация библиотеки/SDK"],
|
||||
"constraints": ["первый выбор для доков известной библиотеки", "WebFetch — fallback на URL; WebSearch — без знания библиотеки"],
|
||||
"needs": [
|
||||
"library-api-question"
|
||||
],
|
||||
"produces": [
|
||||
"library-docs"
|
||||
],
|
||||
"constraints": [
|
||||
"первый выбор для доков известной библиотеки",
|
||||
"WebFetch — fallback на URL; WebSearch — без знания библиотеки"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["resolve-library-id → query-docs"],
|
||||
"key-decisions": ["какая библиотека/тема"],
|
||||
"acceptance-criteria": ["актуальная дока по API получена"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"resolve-library-id → query-docs"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какая библиотека/тема"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"актуальная дока по API получена"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
{
|
||||
"skill": "cspell",
|
||||
"kind": "external",
|
||||
"needs": ["Markdown-текст для проверки орфографии", "пользовательский словарь проекта"],
|
||||
"produces": ["отчёт о неизвестных словах"],
|
||||
"constraints": ["ru/en орфография .md с пользовательским словарём", "НЕ стиль (markdownlint)", "НЕ грамматика"],
|
||||
"needs": [
|
||||
"markdown-files",
|
||||
"project-dictionary"
|
||||
],
|
||||
"produces": [
|
||||
"spelling-report"
|
||||
],
|
||||
"constraints": [
|
||||
"ru/en орфография .md с пользовательским словарём",
|
||||
"НЕ стиль (markdownlint)",
|
||||
"НЕ грамматика"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["учитывать cspell-words.txt"],
|
||||
"key-decisions": ["новый валидный термин → в словарь, а не подавлять находку"],
|
||||
"acceptance-criteria": ["0 неизвестных слов вне словаря"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"учитывать cspell-words.txt"
|
||||
],
|
||||
"key-decisions": [
|
||||
"новый валидный термин → в словарь, а не подавлять находку"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 неизвестных слов вне словаря"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "dataforseo-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["SEO-вопрос по РФ (SERP/ключевые/бэклинки)"],
|
||||
"produces": ["SEO-данные РФ: SERP-позиции, бэклинки, конкурентный анализ"],
|
||||
"constraints": ["DEFERRED — платный, pending Б-1", "комплементарен Wordstat #79"],
|
||||
"needs": [
|
||||
"ru-seo-question"
|
||||
],
|
||||
"produces": [
|
||||
"ru-seo-data"
|
||||
],
|
||||
"constraints": [
|
||||
"DEFERRED — платный, pending Б-1",
|
||||
"комплементарен Wordstat #79"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["при платном аккаунте"],
|
||||
"key-decisions": ["какие SEO-данные нужны"],
|
||||
"acceptance-criteria": ["SEO-данные РФ получены (при доступе)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"при платном аккаунте"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие SEO-данные нужны"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"SEO-данные РФ получены (при доступе)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "dependabot",
|
||||
"kind": "external",
|
||||
"needs": ["Composer/npm-зависимости"],
|
||||
"produces": ["auto-PR при обнаружении CVE в зависимости"],
|
||||
"constraints": ["авто-PR через .github/dependabot.yml", "НЕ блок install (Roave)"],
|
||||
"needs": [
|
||||
"project-dependencies"
|
||||
],
|
||||
"produces": [
|
||||
"cve-dependency-pr"
|
||||
],
|
||||
"constraints": [
|
||||
"авто-PR через .github/dependabot.yml",
|
||||
"НЕ блок install (Roave)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["настройка через .github/dependabot.yml"],
|
||||
"key-decisions": ["принять/отклонить предложенное обновление"],
|
||||
"acceptance-criteria": ["CVE-зависимости имеют открытый update-PR"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"настройка через .github/dependabot.yml"
|
||||
],
|
||||
"key-decisions": [
|
||||
"принять/отклонить предложенное обновление"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"CVE-зависимости имеют открытый update-PR"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "deptrac",
|
||||
"kind": "external",
|
||||
"needs": ["PHP-слои для проверки направления зависимостей"],
|
||||
"produces": ["отчёт о нарушениях границ слоёв"],
|
||||
"constraints": ["граф слоёв по app/deptrac.yaml; lefthook job 10", "НЕ типовой анализ (Larastan)", "НЕ декларативный ADR (adr-judge)"],
|
||||
"needs": [
|
||||
"php-layers"
|
||||
],
|
||||
"produces": [
|
||||
"layer-violation-report"
|
||||
],
|
||||
"constraints": [
|
||||
"граф слоёв по app/deptrac.yaml; lefthook job 10",
|
||||
"НЕ типовой анализ (Larastan)",
|
||||
"НЕ декларативный ADR (adr-judge)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["конфиг 13 слоёв, консервативный ruleset"],
|
||||
"key-decisions": ["допустимые направления зависимостей"],
|
||||
"acceptance-criteria": ["0 нарушений границ слоёв"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"конфиг 13 слоёв, консервативный ruleset"
|
||||
],
|
||||
"key-decisions": [
|
||||
"допустимые направления зависимостей"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 нарушений границ слоёв"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "eslint-prettier",
|
||||
"kind": "external",
|
||||
"needs": ["JS/Vue-код для линта+форматирования"],
|
||||
"produces": ["исправленный/проверенный JS/Vue по ESLint+Prettier"],
|
||||
"constraints": ["связка lint+format JS/Vue", "НЕ CSS (Stylelint)", "НЕ типы (vue-tsc)"],
|
||||
"needs": [
|
||||
"js-vue-source"
|
||||
],
|
||||
"produces": [
|
||||
"linted-js-vue"
|
||||
],
|
||||
"constraints": [
|
||||
"связка lint+format JS/Vue",
|
||||
"НЕ CSS (Stylelint)",
|
||||
"НЕ типы (vue-tsc)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["flat-config + plugin-vue; config-prettier разводит конфликты"],
|
||||
"key-decisions": ["scope: staged-файлы vs весь js/vue"],
|
||||
"acceptance-criteria": ["0 ESLint-ошибок, формат единообразен"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"flat-config + plugin-vue; config-prettier разводит конфликты"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope: staged-файлы vs весь js/vue"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 ESLint-ошибок, формат единообразен"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "exa-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["нужно найти источники по смыслу, которые keyword-поиск пропускает"],
|
||||
"produces": ["семантически близкие результаты веб-поиска (web_search_exa) + страница по URL (web_fetch_exa)"],
|
||||
"constraints": ["READ-ONLY MCP, живой веб", "платный API, ключ EXA_API_KEY только в env", "обнаружение источников, НЕ ранжированный ответ (perplexity #87) и НЕ глубокое чтение (firecrawl #89)"],
|
||||
"needs": [
|
||||
"semantic-search-need"
|
||||
],
|
||||
"produces": [
|
||||
"semantic-web-results"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY MCP, живой веб",
|
||||
"платный API, ключ EXA_API_KEY только в env",
|
||||
"обнаружение источников, НЕ ранжированный ответ (perplexity #87) и НЕ глубокое чтение (firecrawl #89)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["семантическое обнаружение источников по смыслу"],
|
||||
"key-decisions": ["web_search_exa vs web_fetch_exa; глубина выдачи"],
|
||||
"acceptance-criteria": ["найдены концептуально релевантные источники по смыслу запроса"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"семантическое обнаружение источников по смыслу"
|
||||
],
|
||||
"key-decisions": [
|
||||
"web_search_exa vs web_fetch_exa; глубина выдачи"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"найдены концептуально релевантные источники по смыслу запроса"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "figma-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["Figma-файл с дизайн-токенами/компонентами"],
|
||||
"produces": ["извлечённые дизайн-токены/компоненты/стили"],
|
||||
"constraints": ["DEFERRED — нет Figma-аккаунта; источник — статический handoff Платона", "extract-only, code-gen за Frontend Design (#30)"],
|
||||
"needs": [
|
||||
"figma-file"
|
||||
],
|
||||
"produces": [
|
||||
"figma-tokens"
|
||||
],
|
||||
"constraints": [
|
||||
"DEFERRED — нет Figma-аккаунта; источник — статический handoff Платона",
|
||||
"extract-only, code-gen за Frontend Design (#30)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["на поддерживаемом источнике: extract-only"],
|
||||
"key-decisions": ["какие токены извлекать"],
|
||||
"acceptance-criteria": ["токены извлечены из Figma-источника (когда доступен)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"на поддерживаемом источнике: extract-only"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие токены извлекать"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"токены извлечены из Figma-источника (когда доступен)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "firecrawl-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["нужно прочитать страницу целиком / обойти сайт / извлечь структурированное со страниц"],
|
||||
"produces": ["содержимое страниц и обхода (scrape/batch_scrape/map/search/crawl/extract) + автономный web-research (firecrawl_agent)"],
|
||||
"constraints": ["READ-ONLY (read-тяжёлый) MCP, живой веб", "платный API, ключ FIRECRAWL_API_KEY только в env", "глубокое чтение/обход, НЕ ранжированный ответ (perplexity #87) и НЕ наш REST-спек (openapi #47)"],
|
||||
"needs": [
|
||||
"web-read-need"
|
||||
],
|
||||
"produces": [
|
||||
"web-page-content"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY (read-тяжёлый) MCP, живой веб",
|
||||
"платный API, ключ FIRECRAWL_API_KEY только в env",
|
||||
"глубокое чтение/обход, НЕ ранжированный ответ (perplexity #87) и НЕ наш REST-спек (openapi #47)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["scrape одной страницы целиком в markdown"],
|
||||
"key-decisions": ["scrape vs crawl vs extract vs agent; глубина обхода"],
|
||||
"acceptance-criteria": ["получено полное/структурированное содержимое целевой страницы или обхода"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"scrape одной страницы целиком в markdown"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scrape vs crawl vs extract vs agent; глубина обхода"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"получено полное/структурированное содержимое целевой страницы или обхода"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "github-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["ссылка на repo/issue/PR", "намерение операции"],
|
||||
"produces": ["результат чтения или записи issue/PR/комментария"],
|
||||
"constraints": ["внешний MCP — операции через GitHub API", "НЕ локальный git-флоу (это git/PowerShell)"],
|
||||
"needs": [
|
||||
"repo-ref",
|
||||
"github-operation-intent"
|
||||
],
|
||||
"produces": [
|
||||
"github-op-result"
|
||||
],
|
||||
"constraints": [
|
||||
"внешний MCP — операции через GitHub API",
|
||||
"НЕ локальный git-флоу (это git/PowerShell)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["read-first перед мутацией"],
|
||||
"key-decisions": ["scope операции: чтение или запись"],
|
||||
"acceptance-criteria": ["операция отражена в GitHub и подтверждена ответом API"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-first перед мутацией"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope операции: чтение или запись"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"операция отражена в GitHub и подтверждена ответом API"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "gitleaks",
|
||||
"kind": "external",
|
||||
"needs": ["git diff или история репозитория"],
|
||||
"produces": ["находки утечек секретов (ключи/токены/пароли/DSN)"],
|
||||
"constraints": ["сканирует секреты в diff/истории через lefthook pre-commit/pre-push", "НЕ SAST-уязвимости кода (Semgrep)"],
|
||||
"needs": [
|
||||
"git-diff-or-history"
|
||||
],
|
||||
"produces": [
|
||||
"secret-leak-findings"
|
||||
],
|
||||
"constraints": [
|
||||
"сканирует секреты в diff/истории через lefthook pre-commit/pre-push",
|
||||
"НЕ SAST-уязвимости кода (Semgrep)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["protect --staged на pre-commit; полная история на pre-push"],
|
||||
"key-decisions": ["реальный секрет vs тестовая фикстура (false-positive)"],
|
||||
"acceptance-criteria": ["0 утечек секретов в diff/истории"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"protect --staged на pre-commit; полная история на pre-push"
|
||||
],
|
||||
"key-decisions": [
|
||||
"реальный секрет vs тестовая фикстура (false-positive)"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 утечек секретов в diff/истории"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "histoire",
|
||||
"kind": "external",
|
||||
"needs": ["Vue-компонент для каталога stories"],
|
||||
"produces": ["визуальный каталог stories/variants"],
|
||||
"constraints": ["каталог компонентов (не Storybook)", "Vuetify через setupFile"],
|
||||
"needs": [
|
||||
"vue-component"
|
||||
],
|
||||
"produces": [
|
||||
"stories-catalog"
|
||||
],
|
||||
"constraints": [
|
||||
"каталог компонентов (не Storybook)",
|
||||
"Vuetify через setupFile"
|
||||
],
|
||||
"preview-form": "sample",
|
||||
"defaults": ["npm run story"],
|
||||
"key-decisions": ["какие компоненты/variants в каталоге"],
|
||||
"acceptance-criteria": ["stories собираются и рендерятся"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"npm run story"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие компоненты/variants в каталоге"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"stories собираются и рендерятся"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "ide-helper",
|
||||
"kind": "external",
|
||||
"needs": ["Laravel-проект (facades/модели/хелперы)"],
|
||||
"produces": ["IDE-заглушки (@mixin IdeHelper*) для autocomplete/type-inference"],
|
||||
"constraints": ["генерация stubs для IDE", "НЕ влияет на рантайм"],
|
||||
"needs": [
|
||||
"laravel-project"
|
||||
],
|
||||
"produces": [
|
||||
"ide-stubs"
|
||||
],
|
||||
"constraints": [
|
||||
"генерация stubs для IDE",
|
||||
"НЕ влияет на рантайм"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["ide-helper:generate + models -W -M -N"],
|
||||
"key-decisions": ["когда перегенерировать (после изменения моделей)"],
|
||||
"acceptance-criteria": ["autocomplete/type-inference покрывают facades+модели"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"ide-helper:generate + models -W -M -N"
|
||||
],
|
||||
"key-decisions": [
|
||||
"когда перегенерировать (после изменения моделей)"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"autocomplete/type-inference покрывают facades+модели"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
{
|
||||
"skill": "jupyter-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["Jupyter-ноутбук для исполнения"],
|
||||
"produces": ["результат исполнения ячеек ноутбука"],
|
||||
"constraints": ["DEFERRED — нет Python ML-окружения на native-Windows"],
|
||||
"needs": [
|
||||
"jupyter-notebook"
|
||||
],
|
||||
"produces": [
|
||||
"notebook-result"
|
||||
],
|
||||
"constraints": [
|
||||
"DEFERRED — нет Python ML-окружения на native-Windows"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["на поддерживаемой среде с Python ML"],
|
||||
"key-decisions": ["какие ячейки исполнять"],
|
||||
"acceptance-criteria": ["ноутбук исполнен, результаты получены (на поддерживаемой среде)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"на поддерживаемой среде с Python ML"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие ячейки исполнять"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"ноутбук исполнен, результаты получены (на поддерживаемой среде)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "larastan",
|
||||
"kind": "external",
|
||||
"needs": ["PHP-код для статанализа типов"],
|
||||
"produces": ["отчёт об ошибках типов/сигнатур/undefined-переменных"],
|
||||
"constraints": ["типовой анализ PHPStan+Laravel", "НЕ стиль (Pint)", "НЕ граф слоёв (deptrac)"],
|
||||
"needs": [
|
||||
"php-source"
|
||||
],
|
||||
"produces": [
|
||||
"php-type-report"
|
||||
],
|
||||
"constraints": [
|
||||
"типовой анализ PHPStan+Laravel",
|
||||
"НЕ стиль (Pint)",
|
||||
"НЕ граф слоёв (deptrac)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["уровень + baseline проекта"],
|
||||
"key-decisions": ["новая ошибка vs baseline-долг"],
|
||||
"acceptance-criteria": ["0 новых ошибок типов сверх baseline"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"уровень + baseline проекта"
|
||||
],
|
||||
"key-decisions": [
|
||||
"новая ошибка vs baseline-долг"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 новых ошибок типов сверх baseline"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "lychee",
|
||||
"kind": "external",
|
||||
"needs": ["Markdown-файлы со ссылками"],
|
||||
"produces": ["отчёт о битых URL и якорях"],
|
||||
"constraints": ["внутренние + внешние ссылки и якоря .md", "НЕ стиль/орфография"],
|
||||
"needs": [
|
||||
"markdown-files"
|
||||
],
|
||||
"produces": [
|
||||
"broken-link-report"
|
||||
],
|
||||
"constraints": [
|
||||
"внутренние + внешние ссылки и якоря .md",
|
||||
"НЕ стиль/орфография"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["проверять и внутренние якоря, и внешние URL"],
|
||||
"key-decisions": ["внешний временно недоступный vs реально битый — различать"],
|
||||
"acceptance-criteria": ["0 битых ссылок/якорей"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"проверять и внутренние якоря, и внешние URL"
|
||||
],
|
||||
"key-decisions": [
|
||||
"внешний временно недоступный vs реально битый — различать"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 битых ссылок/якорей"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "markdownlint",
|
||||
"kind": "external",
|
||||
"needs": ["Markdown-файлы для линта"],
|
||||
"produces": ["отчёт о нарушениях стиля Markdown"],
|
||||
"constraints": ["внешний CLI — стиль .md (заголовки/таблицы/пробелы/переносы)", "НЕ орфография (cspell)", "НЕ ссылки (lychee)"],
|
||||
"needs": [
|
||||
"markdown-files"
|
||||
],
|
||||
"produces": [
|
||||
"markdown-style-report"
|
||||
],
|
||||
"constraints": [
|
||||
"внешний CLI — стиль .md (заголовки/таблицы/пробелы/переносы)",
|
||||
"НЕ орфография (cspell)",
|
||||
"НЕ ссылки (lychee)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["авто-fix где возможно (--fix), кроме корневого CLAUDE.md"],
|
||||
"key-decisions": ["scope: какие .md в проверке"],
|
||||
"acceptance-criteria": ["0 нарушений стиля по правилам markdownlint"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"авто-fix где возможно (--fix), кроме корневого CLAUDE.md"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope: какие .md в проверке"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 нарушений стиля по правилам markdownlint"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "mermaid",
|
||||
"kind": "external",
|
||||
"needs": ["требование к диаграмме (C4 / flow / sequence / ...)"],
|
||||
"produces": ["диаграмма в нотации Mermaid/C4"],
|
||||
"constraints": ["вендоренный скил; диаграммы в docs/architecture/", "НЕ фиксация решения (adr-kit)"],
|
||||
"needs": [
|
||||
"diagram-requirement"
|
||||
],
|
||||
"produces": [
|
||||
"mermaid-diagram"
|
||||
],
|
||||
"constraints": [
|
||||
"вендоренный скил; диаграммы в docs/architecture/",
|
||||
"НЕ фиксация решения (adr-kit)"
|
||||
],
|
||||
"preview-form": "diagram",
|
||||
"defaults": ["C4: context/container/component"],
|
||||
"key-decisions": ["тип и уровень диаграммы"],
|
||||
"acceptance-criteria": ["диаграмма рендерится и отражает систему"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"C4: context/container/component"
|
||||
],
|
||||
"key-decisions": [
|
||||
"тип и уровень диаграммы"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"диаграмма рендерится и отражает систему"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "n8n-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["workflow для движка n8n"],
|
||||
"produces": ["автоматизация процесса через n8n"],
|
||||
"constraints": ["DEFERRED — n8n не в стеке; движок процессов = очередь Laravel", "принятие n8n — отдельное архитектурное решение"],
|
||||
"needs": [
|
||||
"n8n-workflow"
|
||||
],
|
||||
"produces": [
|
||||
"n8n-automation"
|
||||
],
|
||||
"constraints": [
|
||||
"DEFERRED — n8n не в стеке; движок процессов = очередь Laravel",
|
||||
"принятие n8n — отдельное архитектурное решение"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["на среде с n8n"],
|
||||
"key-decisions": ["принятие n8n как движка — отдельный ADR"],
|
||||
"acceptance-criteria": ["workflow исполняется в n8n (когда принят)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"на среде с n8n"
|
||||
],
|
||||
"key-decisions": [
|
||||
"принятие n8n как движка — отдельный ADR"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"workflow исполняется в n8n (когда принят)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "nightowl",
|
||||
"kind": "external",
|
||||
"needs": ["сквозная корреляция request/job/query трассировок"],
|
||||
"produces": ["коррелированный runtime-трейс (self-hosted)"],
|
||||
"constraints": ["DEFERRED — нет pcntl/posix на native-Windows; pending Б-1/Linux", "ADR-013 BT7 НЕ Sentry #34 (трейс vs ошибки), BT8 НЕ Pail/Boost"],
|
||||
"needs": [
|
||||
"trace-correlation-need"
|
||||
],
|
||||
"produces": [
|
||||
"runtime-trace"
|
||||
],
|
||||
"constraints": [
|
||||
"DEFERRED — нет pcntl/posix на native-Windows; pending Б-1/Linux",
|
||||
"ADR-013 BT7 НЕ Sentry #34 (трейс vs ошибки), BT8 НЕ Pail/Boost"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["на Linux-среде с pcntl/posix"],
|
||||
"key-decisions": ["scope корреляции трассировок"],
|
||||
"acceptance-criteria": ["request/job/query скоррелированы в трейс (на поддерживаемой среде)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"на Linux-среде с pcntl/posix"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope корреляции трассировок"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"request/job/query скоррелированы в трейс (на поддерживаемой среде)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "openapi-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["OpenAPI/REST-спецификация интеграции"],
|
||||
"produces": ["эндпоинты/схемы/параметры как MCP-ресурсы (чтение)"],
|
||||
"constraints": ["READ-ONLY интроспекция спеки", "НЕ генерация кода"],
|
||||
"needs": [
|
||||
"openapi-spec"
|
||||
],
|
||||
"produces": [
|
||||
"api-resources"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY интроспекция спеки",
|
||||
"НЕ генерация кода"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["read-only через .mcp.json"],
|
||||
"key-decisions": ["какой эндпоинт/схему смотреть"],
|
||||
"acceptance-criteria": ["структура API понята из спеки"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-only через .mcp.json"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какой эндпоинт/схему смотреть"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"структура API понята из спеки"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "pa11y",
|
||||
"kind": "external",
|
||||
"needs": ["отрендеренная веб-страница / URL"],
|
||||
"produces": ["отчёт о нарушениях доступности WCAG 2.1 AA"],
|
||||
"constraints": ["единственный технический SoT a11y в проекте", "НЕ через Lighthouse", "НЕ визуальный смок (Playwright)"],
|
||||
"needs": [
|
||||
"rendered-page"
|
||||
],
|
||||
"produces": [
|
||||
"a11y-violations-report"
|
||||
],
|
||||
"constraints": [
|
||||
"единственный технический SoT a11y в проекте",
|
||||
"НЕ через Lighthouse",
|
||||
"НЕ визуальный смок (Playwright)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["проверять контраст / alt / роли / фокус-порядок по WCAG 2.1 AA"],
|
||||
"key-decisions": ["какие страницы/URL в a11y-прогоне"],
|
||||
"acceptance-criteria": ["0 нарушений WCAG 2.1 AA на проверяемых страницах"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"проверять контраст / alt / роли / фокус-порядок по WCAG 2.1 AA"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие страницы/URL в a11y-прогоне"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 нарушений WCAG 2.1 AA на проверяемых страницах"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "perplexity-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["вопрос веб-разведки: актуальные практики/нормы/конкуренты — нужен ответ-с-источниками"],
|
||||
"produces": ["ранжированный web-ответ с цитатами (sonar): search/ask/research/reason"],
|
||||
"constraints": ["READ-ONLY MCP, живой веб", "платный API (sonar-*), ключ PERPLEXITY_API_KEY только в env — без авто-расхода без нужды", "НЕ SDK-доки (context7 #60); НЕ внутренний граф проекта (graphify #86)"],
|
||||
"needs": [
|
||||
"web-research-question"
|
||||
],
|
||||
"produces": [
|
||||
"web-answer-cited"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY MCP, живой веб",
|
||||
"платный API (sonar-*), ключ PERPLEXITY_API_KEY только в env — без авто-расхода без нужды",
|
||||
"НЕ SDK-доки (context7 #60); НЕ внутренний граф проекта (graphify #86)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["ранжированный ответ-с-источниками, не сырой список ссылок"],
|
||||
"key-decisions": ["search vs ask vs research vs reason; глубина (reasoning_effort)"],
|
||||
"acceptance-criteria": ["получен ответ с цитируемыми источниками по запросу веб-разведки"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"ранжированный ответ-с-источниками, не сырой список ссылок"
|
||||
],
|
||||
"key-decisions": [
|
||||
"search vs ask vs research vs reason; глубина (reasoning_effort)"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"получен ответ с цитируемыми источниками по запросу веб-разведки"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "pest",
|
||||
"kind": "external",
|
||||
"needs": ["PHP-тесты (unit/feature/RLS)"],
|
||||
"produces": ["результат прогона тестов (pass/fail/assertions)"],
|
||||
"constraints": ["Pest 4: unit/feature/RLS/parallel/browser/stress/mutation", "НЕ Vue-тесты (Vitest)"],
|
||||
"needs": [
|
||||
"php-tests"
|
||||
],
|
||||
"produces": [
|
||||
"php-test-result"
|
||||
],
|
||||
"constraints": [
|
||||
"Pest 4: unit/feature/RLS/parallel/browser/stress/mutation",
|
||||
"НЕ Vue-тесты (Vitest)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["composer test; --parallel в CI"],
|
||||
"key-decisions": ["scope: какие тесты, parallel vs serial"],
|
||||
"acceptance-criteria": ["все тесты зелёные, без регрессий"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"composer test; --parallel в CI"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope: какие тесты, parallel vs serial"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"все тесты зелёные, без регрессий"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "pg-anonymizer",
|
||||
"kind": "external",
|
||||
"needs": ["дамп БД с персональными данными"],
|
||||
"produces": ["маскированный дамп (телефоны/имена/email)"],
|
||||
"constraints": ["загрузка по требованию LOAD 'anon' (не db-wide preload)", "на проде liderra.ru"],
|
||||
"needs": [
|
||||
"db-dump-with-pii"
|
||||
],
|
||||
"produces": [
|
||||
"masked-dump"
|
||||
],
|
||||
"constraints": [
|
||||
"загрузка по требованию LOAD 'anon' (не db-wide preload)",
|
||||
"на проде liderra.ru"
|
||||
],
|
||||
"preview-form": "sample",
|
||||
"defaults": ["маски по требованию для выгрузок"],
|
||||
"key-decisions": ["какие поля маскировать"],
|
||||
"acceptance-criteria": ["ПДн в выгрузке замаскированы"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"маски по требованию для выгрузок"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие поля маскировать"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"ПДн в выгрузке замаскированы"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "pg-audit",
|
||||
"kind": "external",
|
||||
"needs": ["DDL/DML/DCL операции БД"],
|
||||
"produces": ["аудит-журнал операций на уровне БД"],
|
||||
"constraints": ["pgaudit.log=ddl,role,write; log_parameter=off (ПДн не логируются)", "на проде liderra.ru; закрывает 152-ФЗ"],
|
||||
"needs": [
|
||||
"db-operations"
|
||||
],
|
||||
"produces": [
|
||||
"db-audit-log"
|
||||
],
|
||||
"constraints": [
|
||||
"pgaudit.log=ddl,role,write; log_parameter=off (ПДн не логируются)",
|
||||
"на проде liderra.ru; закрывает 152-ФЗ"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["журнал в /var/log/postgresql"],
|
||||
"key-decisions": ["scope логируемых операций"],
|
||||
"acceptance-criteria": ["аудит-журнал БД ведётся, ПДн не в логах"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"журнал в /var/log/postgresql"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope логируемых операций"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"аудит-журнал БД ведётся, ПДн не в логах"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "pg-formatter",
|
||||
"kind": "external",
|
||||
"needs": ["SQL-файл для форматирования"],
|
||||
"produces": ["отформатированный SQL (отступы/регистр/выравнивание)"],
|
||||
"constraints": ["форматирование SQL по хуку на db/schema.sql", "НЕ линт опасных паттернов (squawk)"],
|
||||
"needs": [
|
||||
"sql-file"
|
||||
],
|
||||
"produces": [
|
||||
"formatted-sql"
|
||||
],
|
||||
"constraints": [
|
||||
"форматирование SQL по хуку на db/schema.sql",
|
||||
"НЕ линт опасных паттернов (squawk)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["стандарт pgFormatter"],
|
||||
"key-decisions": ["scope: какой SQL форматировать"],
|
||||
"acceptance-criteria": ["SQL приведён к стандарту pgFormatter"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"стандарт pgFormatter"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope: какой SQL форматировать"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"SQL приведён к стандарту pgFormatter"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "pg-partman",
|
||||
"kind": "external",
|
||||
"needs": ["расписание партиционирования таблиц"],
|
||||
"produces": ["авто-создание/удаление partition-таблиц по расписанию"],
|
||||
"constraints": ["dormant — недоступно на native-Windows PG", "заменён Artisan partitions:create-months"],
|
||||
"needs": [
|
||||
"partition-schedule"
|
||||
],
|
||||
"produces": [
|
||||
"auto-partitions"
|
||||
],
|
||||
"constraints": [
|
||||
"dormant — недоступно на native-Windows PG",
|
||||
"заменён Artisan partitions:create-months"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["на поддерживаемой среде — по расписанию; на dev заменён ручным cron'ом"],
|
||||
"key-decisions": ["окно/гранулярность партиций"],
|
||||
"acceptance-criteria": ["партиции созданы/удалены по расписанию (на поддерживаемой среде)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"на поддерживаемой среде — по расписанию; на dev заменён ручным cron'ом"
|
||||
],
|
||||
"key-decisions": [
|
||||
"окно/гранулярность партиций"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"партиции созданы/удалены по расписанию (на поддерживаемой среде)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "php-insights",
|
||||
"kind": "external",
|
||||
"needs": ["PHP-код для метрик качества"],
|
||||
"produces": ["метрики: сложность, архитектура, code style score"],
|
||||
"constraints": ["on-demand/CI, не блокирует; пороги 78/79/73", "ADR-013 BT4 НЕ Pint/Larastan; уникум — оси complexity+architecture"],
|
||||
"needs": [
|
||||
"php-source"
|
||||
],
|
||||
"produces": [
|
||||
"php-quality-metrics"
|
||||
],
|
||||
"constraints": [
|
||||
"on-demand/CI, не блокирует; пороги 78/79/73",
|
||||
"ADR-013 BT4 НЕ Pint/Larastan; уникум — оси complexity+architecture"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["composer insights; baseline-пороги"],
|
||||
"key-decisions": ["какие оси/пороги важны"],
|
||||
"acceptance-criteria": ["метрики не ниже baseline-порогов"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"composer insights; baseline-пороги"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие оси/пороги важны"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"метрики не ниже baseline-порогов"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "pint",
|
||||
"kind": "external",
|
||||
"needs": ["PHP-код для форматирования"],
|
||||
"produces": ["отформатированный PHP по PSR-12 + Laravel style"],
|
||||
"constraints": ["только форматирование стиля", "НЕ статанализ типов (Larastan)"],
|
||||
"needs": [
|
||||
"php-source"
|
||||
],
|
||||
"produces": [
|
||||
"formatted-php"
|
||||
],
|
||||
"constraints": [
|
||||
"только форматирование стиля",
|
||||
"НЕ статанализ типов (Larastan)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["применять Laravel preset"],
|
||||
"key-decisions": ["scope: staged-файлы vs весь php"],
|
||||
"acceptance-criteria": ["0 расхождений со стилем Pint"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"применять Laravel preset"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope: staged-файлы vs весь php"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 расхождений со стилем Pint"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
{
|
||||
"skill": "playwright-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["URL или HTML-файл для управления", "намерение: скриншот / взаимодействие / сетевой трейс"],
|
||||
"produces": ["скриншот / результат взаимодействия / снимок console+network"],
|
||||
"constraints": ["внешний MCP — управляет headless-браузером", "НЕ a11y-проверка (это Pa11y)", "НЕ замена unit/e2e-тестам"],
|
||||
"needs": [
|
||||
"browser-target",
|
||||
"browser-action-intent"
|
||||
],
|
||||
"produces": [
|
||||
"browser-interaction-result"
|
||||
],
|
||||
"constraints": [
|
||||
"внешний MCP — управляет headless-браузером",
|
||||
"НЕ a11y-проверка (это Pa11y)",
|
||||
"НЕ замена unit/e2e-тестам"
|
||||
],
|
||||
"preview-form": "sample",
|
||||
"defaults": ["read-first: снять снимок/состояние страницы до действия"],
|
||||
"key-decisions": ["что проверяем: визуал, взаимодействие или сетевой трейс"],
|
||||
"acceptance-criteria": ["ожидаемое состояние страницы подтверждено снимком/снапшотом"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-first: снять снимок/состояние страницы до действия"
|
||||
],
|
||||
"key-decisions": [
|
||||
"что проверяем: визуал, взаимодействие или сетевой трейс"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"ожидаемое состояние страницы подтверждено снимком/снапшотом"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
{
|
||||
"skill": "postgres-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["исторический SQL-запрос к dev-БД"],
|
||||
"produces": ["результат SQL (исторически)"],
|
||||
"constraints": ["historic — заменён Laravel Boost (#10); не используется"],
|
||||
"needs": [
|
||||
"historical-sql-query"
|
||||
],
|
||||
"produces": [
|
||||
"sql-result"
|
||||
],
|
||||
"constraints": [
|
||||
"historic — заменён Laravel Boost (#10); не используется"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["заменён Boost #10"],
|
||||
"key-decisions": ["использовать Boost #10 вместо этого узла"],
|
||||
"acceptance-criteria": ["SQL-запросы идут через Boost #10, не через этот узел"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"заменён Boost #10"
|
||||
],
|
||||
"key-decisions": [
|
||||
"использовать Boost #10 вместо этого узла"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"SQL-запросы идут через Boost #10, не через этот узел"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "postiz",
|
||||
"kind": "external",
|
||||
"needs": ["контент-календарь / план публикаций в соцсети"],
|
||||
"produces": ["запланированные публикации в 30+ соцсетях (VK/Telegram)"],
|
||||
"constraints": ["self-host AGPL-3.0 без дистрибуции (ADR-015 MKT7)", "покрывает VK-постинг"],
|
||||
"needs": [
|
||||
"social-content-plan"
|
||||
],
|
||||
"produces": [
|
||||
"scheduled-social-posts"
|
||||
],
|
||||
"constraints": [
|
||||
"self-host AGPL-3.0 без дистрибуции (ADR-015 MKT7)",
|
||||
"покрывает VK-постинг"
|
||||
],
|
||||
"preview-form": "outline",
|
||||
"defaults": ["контент-календарь, self-host"],
|
||||
"key-decisions": ["каналы и расписание публикаций"],
|
||||
"acceptance-criteria": ["публикации запланированы по календарю"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"контент-календарь, self-host"
|
||||
],
|
||||
"key-decisions": [
|
||||
"каналы и расписание публикаций"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"публикации запланированы по календарю"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "rector",
|
||||
"kind": "external",
|
||||
"needs": ["PHP-код для авто-рефакторинга/version-upgrade"],
|
||||
"produces": ["трансформированный PHP (upgrade/dead-code/modernization)"],
|
||||
"constraints": ["вручную/CI, не блокирует коммит", "ADR-013: BT1 НЕ Pint (трансформация vs формат), BT2 комплементарен Larastan, BT3 НЕ deptrac"],
|
||||
"needs": [
|
||||
"php-source"
|
||||
],
|
||||
"produces": [
|
||||
"refactored-php"
|
||||
],
|
||||
"constraints": [
|
||||
"вручную/CI, не блокирует коммит",
|
||||
"ADR-013: BT1 НЕ Pint (трансформация vs формат), BT2 комплементарен Larastan, BT3 НЕ deptrac"
|
||||
],
|
||||
"preview-form": "dry-run",
|
||||
"defaults": ["dry-run baseline; conservative ruleset"],
|
||||
"key-decisions": ["какие правила трансформации"],
|
||||
"acceptance-criteria": ["код трансформирован, тесты зелёные"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"dry-run baseline; conservative ruleset"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие правила трансформации"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"код трансформирован, тесты зелёные"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "redis-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["вопрос о состоянии Redis/Memurai (ключи/очереди/TTL)"],
|
||||
"produces": ["состояние Redis (чтение): ключи, очереди, TTL, паттерны"],
|
||||
"constraints": ["READ-ONLY MCP к Redis/Memurai", "НЕ prod-ошибки (Sentry MCP)"],
|
||||
"needs": [
|
||||
"redis-state-question"
|
||||
],
|
||||
"produces": [
|
||||
"redis-state"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY MCP к Redis/Memurai",
|
||||
"НЕ prod-ошибки (Sentry MCP)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["read-only инспекция кэша/очередей"],
|
||||
"key-decisions": ["что инспектировать: кэш, очередь, race"],
|
||||
"acceptance-criteria": ["состояние кэша/очереди/race локализовано"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-only инспекция кэша/очередей"
|
||||
],
|
||||
"key-decisions": [
|
||||
"что инспектировать: кэш, очередь, race"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"состояние кэша/очереди/race локализовано"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "roave-security",
|
||||
"kind": "external",
|
||||
"needs": ["composer install/update"],
|
||||
"produces": ["блок установки пакета с известным CVE"],
|
||||
"constraints": ["conflict-список CVE на install/update", "НЕ SAST кода (Semgrep)"],
|
||||
"needs": [
|
||||
"composer-install"
|
||||
],
|
||||
"produces": [
|
||||
"composer-cve-block"
|
||||
],
|
||||
"constraints": [
|
||||
"conflict-список CVE на install/update",
|
||||
"НЕ SAST кода (Semgrep)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["срабатывает автоматически на composer"],
|
||||
"key-decisions": ["нет ручного выбора — автоматический conflict-гейт"],
|
||||
"acceptance-criteria": ["установка с известным CVE заблокирована"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"срабатывает автоматически на composer"
|
||||
],
|
||||
"key-decisions": [
|
||||
"нет ручного выбора — автоматический conflict-гейт"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"установка с известным CVE заблокирована"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "semgrep",
|
||||
"kind": "external",
|
||||
"needs": ["PHP/JS/Vue-код для SAST"],
|
||||
"produces": ["отчёт об уязвимостях кода (инъекции, небезопасная конфигурация, XSS)"],
|
||||
"constraints": ["SAST бинарь + MCP", "НЕ секреты в diff (gitleaks)", "НЕ глубокий on-demand аудит (Trail of Bits)"],
|
||||
"needs": [
|
||||
"code-for-sast"
|
||||
],
|
||||
"produces": [
|
||||
"sast-report"
|
||||
],
|
||||
"constraints": [
|
||||
"SAST бинарь + MCP",
|
||||
"НЕ секреты в diff (gitleaks)",
|
||||
"НЕ глубокий on-demand аудит (Trail of Bits)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["npm run sast"],
|
||||
"key-decisions": ["scope скана; реальная уязвимость vs false-positive"],
|
||||
"acceptance-criteria": ["0 уязвимостей высокого риска"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"npm run sast"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope скана; реальная уязвимость vs false-positive"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 уязвимостей высокого риска"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "sentry-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["production runtime ошибка для диагностики"],
|
||||
"produces": ["события/ошибки/трассировки из Sentry (чтение)"],
|
||||
"constraints": ["READ-ONLY MCP к self-hosted Sentry", "pending активации Б-1", "НЕ Redis-состояние (Redis MCP)"],
|
||||
"needs": [
|
||||
"prod-runtime-error"
|
||||
],
|
||||
"produces": [
|
||||
"sentry-events"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY MCP к self-hosted Sentry",
|
||||
"pending активации Б-1",
|
||||
"НЕ Redis-состояние (Redis MCP)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["read-only диагностика"],
|
||||
"key-decisions": ["какое событие/трассировку смотреть"],
|
||||
"acceptance-criteria": ["причина prod-ошибки локализована по событию Sentry"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-only диагностика"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какое событие/трассировку смотреть"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"причина prod-ошибки локализована по событию Sentry"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "squawk",
|
||||
"kind": "external",
|
||||
"needs": ["SQL-миграция PostgreSQL"],
|
||||
"produces": ["отчёт об опасных паттернах миграции (блокировки, без CONCURRENTLY, ненадёжный DEFAULT)"],
|
||||
"constraints": ["линт миграций в pre-commit для database/migrations", "НЕ форматирование (pgFormatter)"],
|
||||
"needs": [
|
||||
"sql-migration"
|
||||
],
|
||||
"produces": [
|
||||
"migration-danger-report"
|
||||
],
|
||||
"constraints": [
|
||||
"линт миграций в pre-commit для database/migrations",
|
||||
"НЕ форматирование (pgFormatter)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["прогон на staged миграциях"],
|
||||
"key-decisions": ["блокирующая операция vs допустимая"],
|
||||
"acceptance-criteria": ["0 опасных паттернов в миграции"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"прогон на staged миграциях"
|
||||
],
|
||||
"key-decisions": [
|
||||
"блокирующая операция vs допустимая"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 опасных паттернов в миграции"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
{
|
||||
"skill": "stylelint",
|
||||
"kind": "external",
|
||||
"needs": ["CSS-код в .vue SFC или .css-файлах"],
|
||||
"produces": ["отчёт о нарушениях стиля CSS"],
|
||||
"constraints": ["CSS в .vue SFC + css-файлы", "НЕ JS/TS (ESLint)", "НЕ a11y (Pa11y)"],
|
||||
"needs": [
|
||||
"css-source"
|
||||
],
|
||||
"produces": [
|
||||
"css-style-report"
|
||||
],
|
||||
"constraints": [
|
||||
"CSS в .vue SFC + css-файлы",
|
||||
"НЕ JS/TS (ESLint)",
|
||||
"НЕ a11y (Pa11y)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["порядок свойств + именование по конфигу проекта"],
|
||||
"key-decisions": ["scope: staged-файлы vs весь css"],
|
||||
"acceptance-criteria": ["0 нарушений стиля CSS"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"порядок свойств + именование по конфигу проекта"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope: staged-файлы vs весь css"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 нарушений стиля CSS"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "telegram-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["пост/действие в Telegram-канале"],
|
||||
"produces": ["публикация/редактирование/аналитика Telegram-канала"],
|
||||
"constraints": ["выделенный аккаунт через SESSION_STRING (только .env)", "ADR-015 MKT8"],
|
||||
"needs": [
|
||||
"telegram-action"
|
||||
],
|
||||
"produces": [
|
||||
"telegram-result"
|
||||
],
|
||||
"constraints": [
|
||||
"выделенный аккаунт через SESSION_STRING (только .env)",
|
||||
"ADR-015 MKT8"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["выделенный аккаунт, SESSION_STRING в .env"],
|
||||
"key-decisions": ["канал и контент поста"],
|
||||
"acceptance-criteria": ["пост опубликован / аналитика получена"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"выделенный аккаунт, SESSION_STRING в .env"
|
||||
],
|
||||
"key-decisions": [
|
||||
"канал и контент поста"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"пост опубликован / аналитика получена"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "trivy",
|
||||
"kind": "external",
|
||||
"needs": ["Docker-образ для скана"],
|
||||
"produces": ["отчёт о CVE в OS-пакетах и зависимостях образа"],
|
||||
"constraints": ["скан Docker-образов в CI перед push в registry", "НЕ скан кода (Semgrep)"],
|
||||
"needs": [
|
||||
"docker-image"
|
||||
],
|
||||
"produces": [
|
||||
"image-cve-report"
|
||||
],
|
||||
"constraints": [
|
||||
"скан Docker-образов в CI перед push в registry",
|
||||
"НЕ скан кода (Semgrep)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["trivy image перед push в Yandex Container Registry"],
|
||||
"key-decisions": ["порог severity для блока"],
|
||||
"acceptance-criteria": ["0 критичных CVE в образе"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"trivy image перед push в Yandex Container Registry"
|
||||
],
|
||||
"key-decisions": [
|
||||
"порог severity для блока"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 критичных CVE в образе"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "unisender-go-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["массовая email-рассылка через Unisender Go"],
|
||||
"produces": ["отправка маркетинговой email-рассылки"],
|
||||
"constraints": ["DEFERRED — нет upstream MCP, нужна своя обёртка", "ADR-015 MKT5: маркетинговые рассылки НЕ транзакционный email; 152-ФЗ согласия cross-ref #77/#71"],
|
||||
"needs": [
|
||||
"email-blast-task"
|
||||
],
|
||||
"produces": [
|
||||
"email-blast-sent"
|
||||
],
|
||||
"constraints": [
|
||||
"DEFERRED — нет upstream MCP, нужна своя обёртка",
|
||||
"ADR-015 MKT5: маркетинговые рассылки НЕ транзакционный email; 152-ФЗ согласия cross-ref #77/#71"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["при наличии обёртки"],
|
||||
"key-decisions": ["сегмент и согласия рассылки"],
|
||||
"acceptance-criteria": ["рассылка отправлена с соблюдением 152-ФЗ согласий (при наличии обёртки)"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"при наличии обёртки"
|
||||
],
|
||||
"key-decisions": [
|
||||
"сегмент и согласия рассылки"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"рассылка отправлена с соблюдением 152-ФЗ согласий (при наличии обёртки)"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "universal-icons-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["потребность в SVG-иконке (не-Lucide коллекция)"],
|
||||
"produces": ["SVG-иконка из коллекции (Material/Tabler/Phosphor/...)"],
|
||||
"constraints": ["только не-Lucide коллекции (ADR-006: Lucide → lucide-vue-next)", "raw-SVG, не компонент"],
|
||||
"needs": [
|
||||
"svg-icon-need"
|
||||
],
|
||||
"produces": [
|
||||
"svg-icon"
|
||||
],
|
||||
"constraints": [
|
||||
"только не-Lucide коллекции (ADR-006: Lucide → lucide-vue-next)",
|
||||
"raw-SVG, не компонент"
|
||||
],
|
||||
"preview-form": "sample",
|
||||
"defaults": ["для Lucide использовать lucide-vue-next, не этот MCP"],
|
||||
"key-decisions": ["коллекция и конкретная иконка"],
|
||||
"acceptance-criteria": ["иконка вставлена из не-Lucide коллекции корректно"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"для Lucide использовать lucide-vue-next, не этот MCP"
|
||||
],
|
||||
"key-decisions": [
|
||||
"коллекция и конкретная иконка"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"иконка вставлена из не-Lucide коллекции корректно"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "vitest",
|
||||
"kind": "external",
|
||||
"needs": ["Vue-компоненты/модули для unit/component-тестов"],
|
||||
"produces": ["результат прогона Vitest (pass/fail)"],
|
||||
"constraints": ["тесты Vue (jsdom, @vue/test-utils, Pinia)", "НЕ PHP-тесты (Pest)"],
|
||||
"needs": [
|
||||
"js-vue-source"
|
||||
],
|
||||
"produces": [
|
||||
"vitest-result"
|
||||
],
|
||||
"constraints": [
|
||||
"тесты Vue (jsdom, @vue/test-utils, Pinia)",
|
||||
"НЕ PHP-тесты (Pest)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["npm run test:vue"],
|
||||
"key-decisions": ["scope тестов"],
|
||||
"acceptance-criteria": ["все Vue-тесты зелёные"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"npm run test:vue"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope тестов"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"все Vue-тесты зелёные"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "volar",
|
||||
"kind": "external",
|
||||
"needs": ["открытый .vue-файл в VSCode"],
|
||||
"produces": ["IntelliSense / go-to-definition / hover / диагностика типов в редакторе"],
|
||||
"constraints": ["VSCode-расширение (редактор-only)", "НЕ CI type-check (vue-tsc)"],
|
||||
"needs": [
|
||||
"open-vue-file"
|
||||
],
|
||||
"produces": [
|
||||
"editor-type-diagnostics"
|
||||
],
|
||||
"constraints": [
|
||||
"VSCode-расширение (редактор-only)",
|
||||
"НЕ CI type-check (vue-tsc)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["работает в редакторе автоматически"],
|
||||
"key-decisions": ["нет ручного выбора — редакторная служба"],
|
||||
"acceptance-criteria": ["навигация/диагностика по .vue работают в редакторе"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"работает в редакторе автоматически"
|
||||
],
|
||||
"key-decisions": [
|
||||
"нет ручного выбора — редакторная служба"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"навигация/диагностика по .vue работают в редакторе"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "vue-tsc",
|
||||
"kind": "external",
|
||||
"needs": [".vue-компоненты для проверки типов"],
|
||||
"produces": ["отчёт о несоответствиях типов в шаблонах/script"],
|
||||
"constraints": ["полный type-check только в CI", "НЕ редакторная служба (Volar)"],
|
||||
"needs": [
|
||||
"vue-component"
|
||||
],
|
||||
"produces": [
|
||||
"vue-type-report"
|
||||
],
|
||||
"constraints": [
|
||||
"полный type-check только в CI",
|
||||
"НЕ редакторная служба (Volar)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["прогон в CI"],
|
||||
"key-decisions": ["scope проверки типов"],
|
||||
"acceptance-criteria": ["0 ошибок типов vue-tsc"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"прогон в CI"
|
||||
],
|
||||
"key-decisions": [
|
||||
"scope проверки типов"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"0 ошибок типов vue-tsc"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "yandex-metrika-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["вопрос веб-аналитики лендинга"],
|
||||
"produces": ["данные Яндекс.Метрики (визиты/источники/гео/демография/поведение)"],
|
||||
"constraints": ["READ-ONLY MCP; активен при живом лендинге (Б-1)", "НЕ подбор ключевых слов (Wordstat #79)"],
|
||||
"needs": [
|
||||
"web-analytics-question"
|
||||
],
|
||||
"produces": [
|
||||
"metrika-data"
|
||||
],
|
||||
"constraints": [
|
||||
"READ-ONLY MCP; активен при живом лендинге (Б-1)",
|
||||
"НЕ подбор ключевых слов (Wordstat #79)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["read-only чтение метрик"],
|
||||
"key-decisions": ["какие метрики смотреть"],
|
||||
"acceptance-criteria": ["аналитика лендинга получена из Метрики"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"read-only чтение метрик"
|
||||
],
|
||||
"key-decisions": [
|
||||
"какие метрики смотреть"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"аналитика лендинга получена из Метрики"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
{
|
||||
"skill": "yandex-wordstat-mcp",
|
||||
"kind": "external",
|
||||
"needs": ["тема для подбора ключевых слов"],
|
||||
"produces": ["частотность запросов РФ (Wordstat): сезонность, связанные фразы"],
|
||||
"constraints": ["только Wordstat (5 read-only tools); Direct-мутации отключены (ADR-015)", "НЕ веб-аналитика (Метрика #78)"],
|
||||
"needs": [
|
||||
"keyword-topic"
|
||||
],
|
||||
"produces": [
|
||||
"wordstat-frequency"
|
||||
],
|
||||
"constraints": [
|
||||
"только Wordstat (5 read-only tools); Direct-мутации отключены (ADR-015)",
|
||||
"НЕ веб-аналитика (Метрика #78)"
|
||||
],
|
||||
"preview-form": "none",
|
||||
"defaults": ["только Wordstat-модуль"],
|
||||
"key-decisions": ["набор ключевых фраз"],
|
||||
"acceptance-criteria": ["ключевые слова подобраны с частотностью РФ"],
|
||||
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
|
||||
"defaults": [
|
||||
"только Wordstat-модуль"
|
||||
],
|
||||
"key-decisions": [
|
||||
"набор ключевых фраз"
|
||||
],
|
||||
"acceptance-criteria": [
|
||||
"ключевые слова подобраны с частотностью РФ"
|
||||
],
|
||||
"source": {
|
||||
"version": "n/a",
|
||||
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { readFileSync, readdirSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { buildRegistry } from './skill-contract-registry.mjs';
|
||||
import { loadVocabulary } from './capability-vocabulary.mjs';
|
||||
import { buildDependencyGraph } from './coverage-machine.mjs';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const cdir = join(here, '..', 'docs', 'registry', 'contracts');
|
||||
const vocabPath = join(here, '..', 'docs', 'registry', 'capability-vocabulary.json');
|
||||
|
||||
const FILES = readdirSync(cdir).filter((f) => f.endsWith('.contract.json'));
|
||||
const entries = FILES.map((f) => ({ contract: JSON.parse(readFileSync(join(cdir, f), 'utf8')), currentContent: '' }));
|
||||
|
||||
describe('Phase 2b ИТОГ — весь реестр проходит замок словаря (готовность к 2d)', () => {
|
||||
const { tokens } = loadVocabulary({ path: vocabPath });
|
||||
|
||||
it('ВСЕ контракты needs/produces — только токены словаря (0 unknown)', () => {
|
||||
const { contracts, errors } = buildRegistry(entries, { vocabTokens: tokens });
|
||||
expect(errors).toEqual([]);
|
||||
expect(contracts.length).toBe(FILES.length);
|
||||
expect(FILES.length).toBe(153);
|
||||
});
|
||||
|
||||
it('граф непуст: рёбра рабочих цепочек существуют на полном наборе', () => {
|
||||
const { contracts } = buildRegistry(entries, { vocabTokens: tokens });
|
||||
const { edges } = buildDependencyGraph(contracts);
|
||||
expect(edges.length).toBeGreaterThan(0);
|
||||
const has = (from, to) => edges.some((e) => e.from === from && e.to === to);
|
||||
// A8-цепочка (нужды security-go-live кормятся пятью проверками)
|
||||
expect(has('owasp-zap', 'security-go-live')).toBe(true);
|
||||
expect(has('nuclei', 'security-go-live')).toBe(true);
|
||||
// superpowers
|
||||
expect(has('superpowers:writing-plans', 'superpowers:executing-plans')).toBe(true);
|
||||
// кросс-плагинный мост
|
||||
expect(has('frontend-design', 'design-plugin:design-handoff')).toBe(true);
|
||||
expect(has('product-management:write-spec', 'superpowers:writing-plans')).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user