feat(registry): токенизация needs/produces — группа skills B (этап 2b, роутер-реестр)

Phase 2b группа B: 39 контрактов (plugin-dev, claude-md-management, adr-kit,
ui-ux-pro-max, frontend-design + одиночные self-authored/standalone скилы)
переведены на токены словаря. Словарь +61, всего 167 токенов, v0.5.0.

Кросс-мост графа: frontend-design produces ui-design -> design-handoff (group A).
skill-creator/writing-skills сходятся на authored-skill.

Тест: замок-тест группы B + кросс-мост ui-design. Регрессия 4371 passed, exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-19 10:23:08 +03:00
parent ef92b5e39e
commit 88fc55b4a5
41 changed files with 949 additions and 185 deletions
+367 -1
View File
@@ -1,5 +1,5 @@
{
"version": "0.4.0",
"version": "0.5.0",
"tokens": [
{
"token": "running-portal",
@@ -636,6 +636,372 @@
"category": "given",
"label": "исходные brand-материалы",
"description": "Docs/transcripts/recordings. Вход brand-voice:guideline-generation."
},
{
"token": "plugin-agent",
"category": "produced",
"label": "субагент плагина",
"description": "frontmatter+when-to-use+промпт. Выход plugin-dev:agent-development."
},
{
"token": "plugin-command",
"category": "produced",
"label": "слэш-команда плагина",
"description": "YAML+аргументы+bash. Выход plugin-dev:command-development."
},
{
"token": "plugin-hook",
"category": "produced",
"label": "хук плагина",
"description": "событие+matcher+скрипт. Выход plugin-dev:hook-development."
},
{
"token": "plugin-mcp-config",
"category": "produced",
"label": "MCP-конфиг плагина",
"description": ".mcp.json сервер. Выход plugin-dev:mcp-integration."
},
{
"token": "plugin-scaffold",
"category": "produced",
"label": "структура плагина",
"description": "plugin.json+раскладка. Выход plugin-dev:plugin-structure."
},
{
"token": "plugin-settings-file",
"category": "produced",
"label": "настройки плагина",
"description": ".local.md YAML+состояние. Выход plugin-dev:plugin-settings."
},
{
"token": "plugin-skill",
"category": "produced",
"label": "навык плагина",
"description": "SKILL.md+прогрессивное раскрытие. Выход plugin-dev:skill-development."
},
{
"token": "claude-md-quality-report",
"category": "produced",
"label": "quality-report CLAUDE.md",
"description": "rubric+targeted-правки. Выход claude-md-management:claude-md-improver."
},
{
"token": "claude-md-updated",
"category": "produced",
"label": "CLAUDE.md дополнен",
"description": "session-learnings внесены. Выход claude-md-management:revise-claude-md."
},
{
"token": "adr-record",
"category": "produced",
"label": "ADR-файл + гейт",
"description": "ADR в docs/adr/ + enforcement. Выход adr-kit:adr."
},
{
"token": "adr-compliance-verdict",
"category": "produced",
"label": "вердикт соответствия ADR",
"description": "Соответствие staged diff + пути разрешения. Выход adr-kit:judge."
},
{
"token": "banner-design-material",
"category": "produced",
"label": "материал баннера",
"description": "Дизайн баннера (→Vue+Vuetify; код — FD). Выход ui-ux-pro-max:banner-design."
},
{
"token": "ui-brand-system-material",
"category": "produced",
"label": "материал бренд-системы",
"description": "Палитра/типографика (→стек). Выход ui-ux-pro-max:brand."
},
{
"token": "ui-design-material",
"category": "produced",
"label": "материал UI-дизайна",
"description": "UI-дизайн 50+ стилей (→Vue+Vuetify; код — FD). Выход ui-ux-pro-max:design."
},
{
"token": "ui-design-system-material",
"category": "produced",
"label": "материал дизайн-системы",
"description": "Токены/компоненты (под Vue+Vuetify). Выход ui-ux-pro-max:design-system."
},
{
"token": "slides-material",
"category": "produced",
"label": "материал презентации",
"description": "Стратегические слайды. Выход ui-ux-pro-max:slides."
},
{
"token": "ui-styling-material",
"category": "produced",
"label": "материал стилизации UI",
"description": "Стилизация (shadcn/Tailwind→ОБЯЗАТЕЛЬНО Vue+Vuetify). Выход ui-ux-pro-max:ui-styling."
},
{
"token": "ui-ux-decision-material",
"category": "produced",
"label": "материал UI/UX-решения",
"description": "50+ стилей/161 палитра/57 шрифтов/25 чартов (→стек). Выход ui-ux-pro-max:ui-ux-pro-max."
},
{
"token": "architecture-pattern-guidance",
"category": "produced",
"label": "справка по архпаттернам",
"description": "Описание паттернов+критерии (Clean/Hexagonal/DDD/CQRS). Выход architecture-patterns."
},
{
"token": "ccpm-prd-epics",
"category": "produced",
"label": "PRD/эпики/issues",
"description": "PRD→эпик→issue в .claude/. Выход ccpm."
},
{
"token": "ml-result",
"category": "produced",
"label": "ML-результат",
"description": "Модель/метрики/визуализация. Выход data-scientist."
},
{
"token": "discovery-brief",
"category": "produced",
"label": "discovery-brief",
"description": "FEATURE-бриф или SYSTEM-снимок. Выход discovery-interview."
},
{
"token": "knowledge-graph-answer",
"category": "produced",
"label": "ответ knowledge-graph",
"description": "Узлы/рёбра/source_location портала. Выход graphifyy."
},
{
"token": "generated-hook",
"category": "produced",
"label": "сгенерированный хук",
"description": "Claude Code хук (PreToolUse/.../Stop). Выход hookify."
},
{
"token": "backend-conventions",
"category": "produced",
"label": "backend-конвенции",
"description": "Слоистость/RLS/bcmath/идемпотентность. Выход laravel-backend-patterns."
},
{
"token": "ru-marketing-output",
"category": "produced",
"label": "РФ-маркетинг",
"description": "Каналы/конверсия/152-ФЗ согласия. Выход marketing-ru."
},
{
"token": "marketing-frameworks",
"category": "produced",
"label": "маркетинг-фреймворки",
"description": "40 фреймворков как материал (AIDA/PAS/CRO). Выход marketingskills."
},
{
"token": "normative-sync-result",
"category": "produced",
"label": "синхрон нормативки",
"description": "Pravila/PSR/Tooling/CLAUDE.md (versions/cross-refs/§9). Выход normative-sync."
},
{
"token": "deploy-verdict",
"category": "produced",
"label": "вердикт деплоя",
"description": "GO/NO-GO + 8 SSH pre-flight. Выход prod-deploy-validator."
},
{
"token": "as-is-process-reconstruction",
"category": "produced",
"label": "реконструкция as-is",
"description": "As-is процесс + узкие места из кода. Выход process-analysis."
},
{
"token": "bpmn-model",
"category": "produced",
"label": "BPMN-модель",
"description": "BPMN 2.0 (swimlane/события/шлюзы). Выход process-modeling."
},
{
"token": "billing-money-audit",
"category": "produced",
"label": "аудит денег биллинга",
"description": "Money-инварианты биллинга. Выход billing-audit."
},
{
"token": "ru-tax-context",
"category": "produced",
"label": "РСБУ/налоговый контекст",
"description": "Расчёты/проводки ДТ-КТ/выгрузки. Выход ru-tax-accounting."
},
{
"token": "security-inline-warning",
"category": "produced",
"label": "inline security-предупреждение",
"description": "Предупреждение+блок правки (sys.exit 2). Выход security-guidance."
},
{
"token": "security-audit-report",
"category": "produced",
"label": "глубокий security-аудит",
"description": "diff-review/supply-chain/variant/static. Выход trail-of-bits."
},
{
"token": "cc-automation-recommendations",
"category": "produced",
"label": "рекомендации автоматизаций CC",
"description": "hooks/permissions/settings. Выход claude-code-setup."
},
{
"token": "prompt-eval-result",
"category": "produced",
"label": "результат eval промпта",
"description": "Ассерты/judge/red-team. Выход promptfoo."
},
{
"token": "plugin-authoring-intent",
"category": "given",
"label": "намерение создать компонент плагина",
"description": "Создать агента/команду/хук/MCP/скил/структуру плагина. Вход plugin-dev:*."
},
{
"token": "claude-md-edit-intent",
"category": "given",
"label": "намерение проверить/улучшить CLAUDE.md",
"description": "Audit или точечные правки. Вход claude-md-management:claude-md-improver."
},
{
"token": "session-learnings",
"category": "given",
"label": "learnings сессии",
"description": "Захватить quirks/команды/паттерны в CLAUDE.md. Вход revise-claude-md."
},
{
"token": "adr-decision-intent",
"category": "given",
"label": "намерение принять ADR",
"description": "Принять/записать архитектурное решение. Вход adr-kit:adr."
},
{
"token": "staged-diff",
"category": "given",
"label": "staged diff",
"description": "Staged diff для сверки против ADR. Вход adr-kit:judge."
},
{
"token": "architecture-question",
"category": "given",
"label": "вопрос выбора архпаттерна",
"description": "Вопрос выбора архитектурного паттерна. Вход architecture-patterns."
},
{
"token": "feature-mgmt-idea",
"category": "given",
"label": "идея фичи для управления",
"description": "PRD→эпик→issue→код. Вход ccpm."
},
{
"token": "ml-task",
"category": "given",
"label": "датасет + ML-задача",
"description": "Классификация/регрессия/анализ. Вход data-scientist."
},
{
"token": "pre-design-task",
"category": "given",
"label": "задача до проектирования",
"description": "Фича (интервью) или ориентация в системе. Вход discovery-interview."
},
{
"token": "codebase-question",
"category": "given",
"label": "структурный вопрос по проекту",
"description": "Cross-layer вопрос (docs+code). Вход graphifyy."
},
{
"token": "hookify-behavior",
"category": "given",
"label": "/hookify + поведение",
"description": "Поведение для предотвращения хуком. Вход hookify."
},
{
"token": "backend-task",
"category": "given",
"label": "backend-задача Лидерры",
"description": "controller/service/job/RLS/деньги. Вход laravel-backend-patterns."
},
{
"token": "ru-marketing-task",
"category": "given",
"label": "РФ-маркетинг-задача",
"description": "Директ/ВК/Telegram/лендинг/152-ФЗ. Вход marketing-ru."
},
{
"token": "marketing-framework-need",
"category": "given",
"label": "нужен маркетинг-фреймворк",
"description": "Задача, требующая фреймворка (AIDA/PAS/CRO). Вход marketingskills."
},
{
"token": "completed-integration",
"category": "given",
"label": "завершённая интеграция/ADR",
"description": "Интеграция/ADR/brain-артефакт для синка нормативки. Вход normative-sync."
},
{
"token": "prod-deploy-intent",
"category": "given",
"label": "намерение выката на бой",
"description": "Выкат на боевой liderra.ru. Вход prod-deploy-validator."
},
{
"token": "as-is-discovery-task",
"category": "given",
"label": "as-is discovery из кода",
"description": "As-is процесс для discovery из кода Laravel. Вход process-analysis."
},
{
"token": "to-be-process",
"category": "given",
"label": "to-be бизнес-процесс",
"description": "To-be процесс для моделирования. Вход process-modeling."
},
{
"token": "billing-code",
"category": "given",
"label": "код биллинга",
"description": "Код/диф биллинга для аудита денег. Вход billing-audit."
},
{
"token": "ru-tax-question",
"category": "given",
"label": "вопрос РСБУ/НК РФ",
"description": "НДС/УСН/налоговая база/проводки. Вход ru-tax-accounting."
},
{
"token": "file-edit-risky",
"category": "given",
"label": "правка с уязвимым паттерном",
"description": "Правка файла с потенциально уязвимым паттерном. Вход security-guidance."
},
{
"token": "security-audit-target",
"category": "given",
"label": "diff/код для security-аудита",
"description": "Diff/код для глубокого аудита. Вход trail-of-bits."
},
{
"token": "cc-usage-patterns",
"category": "given",
"label": "паттерны использования CC",
"description": "Паттерны Claude Code для рекомендаций. Вход claude-code-setup."
},
{
"token": "prompt-eval-task",
"category": "given",
"label": "промпт + тест-кейсы",
"description": "LLM-промпт + кейсы для eval. Вход promptfoo."
}
]
}
@@ -2,10 +2,10 @@
"skill": "adr-kit:adr",
"kind": "external",
"needs": [
"намерение принять/записать архитектурное решение"
"adr-decision-intent"
],
"produces": [
"ADR-файл в docs/adr/ + enforcement-гейт"
"adr-record"
],
"constraints": [
"содержательный навык плагина adr-kit",
@@ -2,10 +2,10 @@
"skill": "adr-kit:judge",
"kind": "external",
"needs": [
"staged diff для сверки против принятых ADR"
"staged-diff"
],
"produces": [
"вердикт соответствия + пути разрешения нарушения"
"adr-compliance-verdict"
],
"constraints": [
"содержательный навык плагина adr-kit",
@@ -1,12 +1,29 @@
{
"skill": "architecture-patterns",
"kind": "external",
"needs": ["вопрос выбора архитектурного паттерна"],
"produces": ["описание паттернов + критерии выбора (Clean/Hexagonal/DDD/CQRS/...)"],
"constraints": ["справочник паттернов (knowledge)", "НЕ фиксация решения (adr-kit)"],
"needs": [
"architecture-question"
],
"produces": [
"architecture-pattern-guidance"
],
"constraints": [
"справочник паттернов (knowledge)",
"НЕ фиксация решения (adr-kit)"
],
"preview-form": "none",
"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,11 +1,24 @@
{
"skill": "billing-audit",
"kind": "own",
"needs": ["код/диф биллинга для аудита денежной корректности"],
"produces": ["отчёт о money-инвариантах биллинга"],
"constraints": ["self-authored; аудит кода биллинга (bcmath/идемпотентность/tier/charge_source)", "ADR-012: НЕ налоги (ru-tax), НЕ процесс (process-*), НЕ security (D3)"],
"needs": [
"billing-code"
],
"produces": [
"billing-money-audit"
],
"constraints": [
"self-authored; аудит кода биллинга (bcmath/идемпотентность/tier/charge_source)",
"ADR-012: НЕ налоги (ru-tax), НЕ процесс (process-*), НЕ security (D3)"
],
"preview-form": "outline",
"defaults": ["проверять потерю копеек, двойное списание, tier-резолюцию, дрейф reconcile"],
"key-decisions": ["какие денежные инварианты в scope"],
"acceptance-criteria": ["каждый денежный путь проверен на потерю копеек и двойное списание"]
"defaults": [
"проверять потерю копеек, двойное списание, tier-резолюцию, дрейф reconcile"
],
"key-decisions": [
"какие денежные инварианты в scope"
],
"acceptance-criteria": [
"каждый денежный путь проверен на потерю копеек и двойное списание"
]
}
+25 -7
View File
@@ -1,12 +1,30 @@
{
"skill": "ccpm",
"kind": "external",
"needs": ["идея фичи для управления (PRD→эпик→issue→код)"],
"produces": ["PRD/эпики/issues в .claude/prds/ + .claude/epics/"],
"constraints": ["вендоренный скил, 14 bash-скриптов без хуков", "GitHub-issues через GitHub MCP", "НЕ продуктовые церемонии (product-management)"],
"needs": [
"feature-mgmt-idea"
],
"produces": [
"ccpm-prd-epics"
],
"constraints": [
"вендоренный скил, 14 bash-скриптов без хуков",
"GitHub-issues через GitHub MCP",
"НЕ продуктовые церемонии (product-management)"
],
"preview-form": "outline",
"defaults": ["PRD → эпик → issues → код"],
"key-decisions": ["декомпозиция эпика на issues"],
"acceptance-criteria": ["фича прослежена PRD→issue→код"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"PRD → эпик issues → код"
],
"key-decisions": [
"декомпозиция эпика на issues"
],
"acceptance-criteria": [
"фича прослежена PRD→issue→код"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,12 +1,28 @@
{
"skill": "claude-code-setup",
"kind": "external",
"needs": ["паттерны использования Claude Code для рекомендаций"],
"produces": ["рекомендации автоматизаций (hooks/permissions/settings)"],
"constraints": ["READ-ONLY рекомендатель, не меняет конфиг"],
"needs": [
"cc-usage-patterns"
],
"produces": [
"cc-automation-recommendations"
],
"constraints": [
"READ-ONLY рекомендатель, не меняет конфиг"
],
"preview-form": "outline",
"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,30 @@
{
"skill": "claude-md-management:claude-md-improver",
"kind": "external",
"needs": ["намерение проверить/улучшить CLAUDE.md (audit или точечные правки структуры/правил §5)"],
"produces": ["quality-report по CLAUDE.md (rubric) + targeted-правки файла"],
"constraints": ["один из двух входов плагина claude-md-management", "правка CLAUDE.md — только через этот канал (§5 п.10)", "внутри flow — синхрон Pravila+Tooling (п.7)"],
"needs": [
"claude-md-edit-intent"
],
"produces": [
"claude-md-quality-report"
],
"constraints": [
"один из двух входов плагина claude-md-management",
"правка CLAUDE.md — только через этот канал (§5 п.10)",
"внутри flow — синхрон Pravila+Tooling (п.7)"
],
"preview-form": "none",
"defaults": ["claude-md-improver — для структурных изменений, добавления/удаления секций, правок правил §5 и версии в шапке"],
"key-decisions": ["audit целиком vs точечная правка конкретной секции"],
"acceptance-criteria": ["quality-report выдан ДО правок; правки targeted; нормативка синхронна"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"claude-md-improver — для структурных изменений, добавления/удаления секций, правок правил §5 и версии в шапке"
],
"key-decisions": [
"audit целиком vs точечная правка конкретной секции"
],
"acceptance-criteria": [
"quality-report выдан ДО правок; правки targeted; нормативка синхронна"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,12 +1,30 @@
{
"skill": "claude-md-management:revise-claude-md",
"kind": "external",
"needs": ["намерение захватить learnings текущей сессии в CLAUDE.md"],
"produces": ["CLAUDE.md дополнен session-learnings (новые quirks/команды/паттерны)"],
"constraints": ["один из двух входов плагина claude-md-management", "правка CLAUDE.md — только через этот канал (§5 п.10)", "внутри flow — синхрон Pravila+Tooling (п.7)"],
"needs": [
"session-learnings"
],
"produces": [
"claude-md-updated"
],
"constraints": [
"один из двух входов плагина claude-md-management",
"правка CLAUDE.md — только через этот канал (§5 п.10)",
"внутри flow — синхрон Pravila+Tooling (п.7)"
],
"preview-form": "none",
"defaults": ["revise-claude-md — для захвата learnings из текущей сессии"],
"key-decisions": ["что из сессии достойно CLAUDE.md, а что — memory"],
"acceptance-criteria": ["learnings внесены через плагин; нормативка синхронна"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"revise-claude-md — для захвата learnings из текущей сессии"
],
"key-decisions": [
"что из сессии достойно CLAUDE.md, а что — memory"
],
"acceptance-criteria": [
"learnings внесены через плагин; нормативка синхронна"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,12 +1,29 @@
{
"skill": "data-scientist",
"kind": "external",
"needs": ["датасет + ML-задача (классификация/регрессия/анализ)"],
"produces": ["ML-результат: модель, метрики, визуализация"],
"constraints": ["вендоренный скил; классический ML-воркфлоу", "требует датасета, не доменной БД портала"],
"needs": [
"ml-task"
],
"produces": [
"ml-result"
],
"constraints": [
"вендоренный скил; классический ML-воркфлоу",
"требует датасета, не доменной БД портала"
],
"preview-form": "sample",
"defaults": ["загрузка → feature engineering → обучение → оценка"],
"key-decisions": ["алгоритм и метрики под задачу"],
"acceptance-criteria": ["модель оценена метриками, результат воспроизводим"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"загрузка → feature engineering → обучение → оценка"
],
"key-decisions": [
"алгоритм и метрики под задачу"
],
"acceptance-criteria": [
"модель оценена метриками, результат воспроизводим"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,11 +1,24 @@
{
"skill": "discovery-interview",
"kind": "own",
"needs": ["задача до проектирования: фича (интервью заказчика) или ориентация в системе"],
"produces": ["discovery-brief (FEATURE) или snapshot мета-слоя (SYSTEM)"],
"constraints": ["self-authored; FEATURE=JTBD-интервью человека, SYSTEM=ориентация по мета-слою", "ADR-009 граница с process-analysis (#53): человек vs код"],
"needs": [
"pre-design-task"
],
"produces": [
"discovery-brief"
],
"constraints": [
"self-authored; FEATURE=JTBD-интервью человека, SYSTEM=ориентация по мета-слою",
"ADR-009 граница с process-analysis (#53): человек vs код"
],
"preview-form": "outline",
"defaults": ["FEATURE → discovery-brief в brainstorming; SYSTEM → snapshot в docs/discovery/"],
"key-decisions": ["режим FEATURE или SYSTEM"],
"acceptance-criteria": ["проблема/контекст вскрыты до проектирования"]
"defaults": [
"FEATURE → discovery-brief в brainstorming; SYSTEM → snapshot в docs/discovery/"
],
"key-decisions": [
"режим FEATURE или SYSTEM"
],
"acceptance-criteria": [
"проблема/контекст вскрыты до проектирования"
]
}
@@ -1,12 +1,30 @@
{
"skill": "frontend-design",
"kind": "external",
"needs": ["UI-задача: компонент / паттерн / состояние / a11y-принцип"],
"produces": ["доменное решение UI/UX (компоненты, паттерны, a11y-принципы)"],
"constraints": ["доменная база UI для Vue+Vuetify; обязательный стек-фильтр R6.0", "paired со #19", "технический a11y — за Pa11y, не здесь"],
"needs": [
"ui-task"
],
"produces": [
"ui-design"
],
"constraints": [
"доменная база UI для Vue+Vuetify; обязательный стек-фильтр R6.0",
"paired со #19",
"технический a11y — за Pa11y, не здесь"
],
"preview-form": "mockup",
"defaults": ["срезать React/Tailwind/shadcn → Vue 3 + Vuetify 3; палитра Forest из Brandbook"],
"key-decisions": ["компонент/паттерн под задачу в рамках стека"],
"acceptance-criteria": ["решение в стеке Vue+Vuetify, бренд Forest соблюдён"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"срезать React/Tailwind/shadcn → Vue 3 + Vuetify 3; палитра Forest из Brandbook"
],
"key-decisions": [
"компонент/паттерн под задачу в рамках стека"
],
"acceptance-criteria": [
"решение в стеке Vue+Vuetify, бренд Forest соблюдён"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,12 +1,30 @@
{
"skill": "graphifyy",
"kind": "external",
"needs": ["структурный/cross-layer вопрос по проекту (docs+code)"],
"produces": ["ответ из knowledge-graph портала (узлы/рёбра/source_location)"],
"constraints": ["user-level CLI; backend GEMINI/GOOGLE key ИЛИ Claude subagent", "ADR-017: KG1 НЕ context7 #60 (внутренний vs внешний), KG2 НЕ Boost #10 (static vs runtime), KG3 НЕ openapi #47, KG4 НЕ Sentry #34, KG5 НЕ adr-kit/mermaid (auto vs manual)", "артефакты graphify-out*/ gitignored; только manual --update"],
"needs": [
"codebase-question"
],
"produces": [
"knowledge-graph-answer"
],
"constraints": [
"user-level CLI; backend GEMINI/GOOGLE key ИЛИ Claude subagent",
"ADR-017: KG1 НЕ context7 #60 (внутренний vs внешний), KG2 НЕ Boost #10 (static vs runtime), KG3 НЕ openapi #47, KG4 НЕ Sentry #34, KG5 НЕ adr-kit/mermaid (auto vs manual)",
"артефакты graphify-out*/ gitignored; только manual --update"
],
"preview-form": "none",
"defaults": ["query/explain/path read-only; перед открытым codebase-вопросом сначала graphify"],
"key-decisions": ["структурный вопрос vs известный путь (Read/Grep)"],
"acceptance-criteria": ["структурный вопрос отвечен с source_location-цитатами"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"query/explain/path read-only; перед открытым codebase-вопросом сначала graphify"
],
"key-decisions": [
"структурный вопрос vs известный путь (Read/Grep)"
],
"acceptance-criteria": [
"структурный вопрос отвечен с source_location-цитатами"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
+24 -7
View File
@@ -1,12 +1,29 @@
{
"skill": "hookify",
"kind": "external",
"needs": ["явный /hookify + поведение для предотвращения"],
"produces": ["сгенерированный Claude Code хук (PreToolUse/PostToolUse/Stop/...)"],
"constraints": ["только по явному /hookify", "HK1 pre-check коллизий с существующими хуками (ADR-010)"],
"needs": [
"hookify-behavior"
],
"produces": [
"generated-hook"
],
"constraints": [
"только по явному /hookify",
"HK1 pre-check коллизий с существующими хуками (ADR-010)"
],
"preview-form": "outline",
"defaults": ["HK1 pre-check до генерации"],
"key-decisions": ["тип события хука и условие"],
"acceptance-criteria": ["хук генерируется без коллизий с существующей архитектурой"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"HK1 pre-check до генерации"
],
"key-decisions": [
"тип события хука и условие"
],
"acceptance-criteria": [
"хук генерируется без коллизий с существующей архитектурой"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,11 +1,24 @@
{
"skill": "laravel-backend-patterns",
"kind": "own",
"needs": ["backend-задача Лидерры (controller/service/job/RLS/деньги)"],
"produces": ["проектные backend-конвенции (слоистость, RLS-aware, bcmath, идемпотентность, partition-aware)"],
"constraints": ["self-authored справочник проектных конвенций", "ADR-013: BT5 НЕ architecture-patterns #38 (проектные vs generic), BT6 НЕ billing-audit #62"],
"needs": [
"backend-task"
],
"produces": [
"backend-conventions"
],
"constraints": [
"self-authored справочник проектных конвенций",
"ADR-013: BT5 НЕ architecture-patterns #38 (проектные vs generic), BT6 НЕ billing-audit #62"
],
"preview-form": "outline",
"defaults": ["controller→service→job; RLS-aware; деньги через bcmath/LedgerService"],
"key-decisions": ["паттерн под слой задачи"],
"acceptance-criteria": ["backend-код следует конвенциям Лидерры"]
"defaults": [
"controller→service→job; RLS-aware; деньги через bcmath/LedgerService"
],
"key-decisions": [
"паттерн под слой задачи"
],
"acceptance-criteria": [
"backend-код следует конвенциям Лидерры"
]
}
@@ -1,11 +1,24 @@
{
"skill": "marketing-ru",
"kind": "own",
"needs": ["маркетинговая задача для РФ-рынка (Директ/ВК/Telegram/лендинг/152-ФЗ)"],
"produces": ["РФ-маркетинг: каналы, конверсия лендинга, 152-ФЗ согласия"],
"constraints": ["self-authored; РФ-специфика (ADR-015 MKT9, 152-ФЗ cross-ref #71)", "НЕ generic marketing #74"],
"needs": [
"ru-marketing-task"
],
"produces": [
"ru-marketing-output"
],
"constraints": [
"self-authored; РФ-специфика (ADR-015 MKT9, 152-ФЗ cross-ref #71)",
"НЕ generic marketing #74"
],
"preview-form": "outline",
"defaults": ["РФ-каналы: Яндекс.Директ/ВК/Telegram; согласия по 152-ФЗ"],
"key-decisions": ["канал и РФ-ограничения"],
"acceptance-criteria": ["маркетинг учитывает РФ-каналы и 152-ФЗ"]
"defaults": [
"РФ-каналы: Яндекс.Директ/ВК/Telegram; согласия по 152-ФЗ"
],
"key-decisions": [
"канал и РФ-ограничения"
],
"acceptance-criteria": [
"маркетинг учитывает РФ-каналы и 152-ФЗ"
]
}
@@ -1,12 +1,29 @@
{
"skill": "marketingskills",
"kind": "external",
"needs": ["маркетинговая задача, требующая фреймворка (AIDA/PAS/CRO/...)"],
"produces": ["маркетинговые фреймворки как материал (40 шт)"],
"constraints": ["материал/резерв-библиотека, не решатель (ADR-015 MKT3)", "решатель — marketing #74"],
"needs": [
"marketing-framework-need"
],
"produces": [
"marketing-frameworks"
],
"constraints": [
"материал/резерв-библиотека, не решатель (ADR-015 MKT3)",
"решатель — marketing #74"
],
"preview-form": "none",
"defaults": ["материал отбирается, решение за marketing #74"],
"key-decisions": ["какой фреймворк под задачу"],
"acceptance-criteria": ["фреймворк отобран как материал для решателя"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"материал отбирается, решение за marketing #74"
],
"key-decisions": [
"какой фреймворк под задачу"
],
"acceptance-criteria": [
"фреймворк отобран как материал для решателя"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,11 +1,24 @@
{
"skill": "normative-sync",
"kind": "own",
"needs": ["завершённая интеграция/ADR/brain-артефакт для синка нормативки"],
"produces": ["синхронизированные Pravila/PSR_v1/Tooling/CLAUDE.md (version bumps, §0 cross-refs, footer, §9)"],
"constraints": ["project-агент; звать после закрытия крупной off-phase интеграции/ADR (Pravila §2.4)", "парный с #85; не в Tooling-каноне счётчиков"],
"needs": [
"completed-integration"
],
"produces": [
"normative-sync-result"
],
"constraints": [
"project-агент; звать после закрытия крупной off-phase интеграции/ADR (Pravila §2.4)",
"парный с #85; не в Tooling-каноне счётчиков"
],
"preview-form": "outline",
"defaults": ["синк 4 нормативных файлов с version bumps"],
"key-decisions": ["какие version bumps/cross-refs нужны"],
"acceptance-criteria": ["4 нормативных документа синхронны, cross-refs сходятся"]
"defaults": [
"синк 4 нормативных файлов с version bumps"
],
"key-decisions": [
"какие version bumps/cross-refs нужны"
],
"acceptance-criteria": [
"4 нормативных документа синхронны, cross-refs сходятся"
]
}
@@ -2,10 +2,10 @@
"skill": "plugin-dev:agent-development",
"kind": "external",
"needs": [
"намерение создать субагента плагина"
"plugin-authoring-intent"
],
"produces": [
"субагент: frontmatter + when-to-use + системный промпт"
"plugin-agent"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -2,10 +2,10 @@
"skill": "plugin-dev:command-development",
"kind": "external",
"needs": [
"намерение создать слэш-команду плагина"
"plugin-authoring-intent"
],
"produces": [
"слэш-команда: YAML-frontmatter + аргументы + bash"
"plugin-command"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -2,10 +2,10 @@
"skill": "plugin-dev:hook-development",
"kind": "external",
"needs": [
"намерение создать хук плагина (PreToolUse/PostToolUse/...)"
"plugin-authoring-intent"
],
"produces": [
"хук: событие + matcher + скрипт ${CLAUDE_PLUGIN_ROOT}"
"plugin-hook"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -2,10 +2,10 @@
"skill": "plugin-dev:mcp-integration",
"kind": "external",
"needs": [
"намерение подключить MCP-сервер в плагин"
"plugin-authoring-intent"
],
"produces": [
".mcp.json: stdio/SSE/HTTP-сервер в плагине"
"plugin-mcp-config"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -2,10 +2,10 @@
"skill": "plugin-dev:plugin-settings",
"kind": "external",
"needs": [
"намерение сделать поведение плагина настраиваемым"
"plugin-authoring-intent"
],
"produces": [
".local.md настройки плагина (YAML-frontmatter + состояние)"
"plugin-settings-file"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -2,10 +2,10 @@
"skill": "plugin-dev:plugin-structure",
"kind": "external",
"needs": [
"намерение создать или организовать плагин"
"plugin-authoring-intent"
],
"produces": [
"структура плагина: plugin.json + раскладка компонентов"
"plugin-scaffold"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -2,10 +2,10 @@
"skill": "plugin-dev:skill-development",
"kind": "external",
"needs": [
"намерение создать навык внутри плагина"
"plugin-authoring-intent"
],
"produces": [
"навык плагина: SKILL.md + прогрессивное раскрытие"
"plugin-skill"
],
"constraints": [
"под-навык зонтика plugin-dev (разработка Claude-плагинов)",
@@ -1,11 +1,25 @@
{
"skill": "process-analysis",
"kind": "own",
"needs": ["as-is процесс для discovery из кода Laravel"],
"produces": ["реконструкция as-is процесса + узкие места"],
"constraints": ["self-authored project skill; discovery из app-кода (routes/controllers/jobs)", "ADR-009 граница с discovery-interview (#55): код vs человек", "НЕ моделирование to-be (process-modeling)"],
"needs": [
"as-is-discovery-task"
],
"produces": [
"as-is-process-reconstruction"
],
"constraints": [
"self-authored project skill; discovery из app-кода (routes/controllers/jobs)",
"ADR-009 граница с discovery-interview (#55): код vs человек",
"НЕ моделирование to-be (process-modeling)"
],
"preview-form": "outline",
"defaults": ["discovery из маршрутов/контроллеров/джобов/очередей"],
"key-decisions": ["scope процесса для реконструкции"],
"acceptance-criteria": ["as-is процесс восстановлен, узкие места выявлены"]
"defaults": [
"discovery из маршрутов/контроллеров/джобов/очередей"
],
"key-decisions": [
"scope процесса для реконструкции"
],
"acceptance-criteria": [
"as-is процесс восстановлен, узкие места выявлены"
]
}
@@ -1,11 +1,25 @@
{
"skill": "process-modeling",
"kind": "own",
"needs": ["to-be бизнес-процесс для моделирования"],
"produces": ["BPMN 2.0 модель (swimlane/события/шлюзы) в docs/process/"],
"constraints": ["self-authored project skill; нотация BPMN", "НЕ as-is анализ из кода (process-analysis)", "рендер диаграмм — через свой вывод/mermaid"],
"needs": [
"to-be-process"
],
"produces": [
"bpmn-model"
],
"constraints": [
"self-authored project skill; нотация BPMN",
"НЕ as-is анализ из кода (process-analysis)",
"рендер диаграмм — через свой вывод/mermaid"
],
"preview-form": "diagram",
"defaults": ["BPMN 2.0; результаты в docs/process/"],
"key-decisions": ["границы и дорожки процесса"],
"acceptance-criteria": ["to-be модель покрывает поток управления и роли"]
"defaults": [
"BPMN 2.0; результаты в docs/process/"
],
"key-decisions": [
"границы и дорожки процесса"
],
"acceptance-criteria": [
"to-be модель покрывает поток управления и роли"
]
}
@@ -1,11 +1,24 @@
{
"skill": "prod-deploy-validator",
"kind": "own",
"needs": ["намерение выката на боевой liderra.ru"],
"produces": ["вердикт GO/NO-GO + результаты 8 SSH pre-flight проверок"],
"constraints": ["project-агент; READ-ONLY по дизайну; звать перед любым выкатом (Pravila §2.4)", "парный с #84; не в Tooling-каноне"],
"needs": [
"prod-deploy-intent"
],
"produces": [
"deploy-verdict"
],
"constraints": [
"project-агент; READ-ONLY по дизайну; звать перед любым выкатом (Pravila §2.4)",
"парный с #84; не в Tooling-каноне"
],
"preview-form": "outline",
"defaults": ["8 READ-ONLY SSH-проверок: конфиг/сервисы/БД/очереди"],
"key-decisions": ["go/no-go по результатам проверок"],
"acceptance-criteria": ["вердикт GO/NO-GO обоснован pre-flight проверками"]
"defaults": [
"8 READ-ONLY SSH-проверок: конфиг/сервисы/БД/очереди"
],
"key-decisions": [
"go/no-go по результатам проверок"
],
"acceptance-criteria": [
"вердикт GO/NO-GO обоснован pre-flight проверками"
]
}
@@ -1,12 +1,29 @@
{
"skill": "promptfoo",
"kind": "external",
"needs": ["LLM-промпт + тест-кейсы для eval"],
"produces": ["результат eval/регрессии промпта (ассерты/judge/red-team)"],
"constraints": ["только вручную/CI, никогда в хук (платные вызовы)", "НЕ SAST (Semgrep)"],
"needs": [
"prompt-eval-task"
],
"produces": [
"prompt-eval-result"
],
"constraints": [
"только вручную/CI, никогда в хук (платные вызовы)",
"НЕ SAST (Semgrep)"
],
"preview-form": "none",
"defaults": ["запуск вручную или в CI"],
"key-decisions": ["метрики/ассерты eval"],
"acceptance-criteria": ["промпт прошёл регрессию/eval по критериям"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"запуск вручную или в CI"
],
"key-decisions": [
"метрики/ассерты eval"
],
"acceptance-criteria": [
"промпт прошёл регрессию/eval по критериям"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,11 +1,24 @@
{
"skill": "ru-tax-accounting",
"kind": "own",
"needs": ["вопрос по РСБУ/НК РФ (НДС/УСН/налоговая база/проводки)"],
"produces": ["РСБУ/налоговый контекст: расчёты, проводки ДТ/КТ, выгрузки бухгалтеру"],
"constraints": ["self-authored; закрывает РФ-gap finance-plugin (#61)", "ADR-012: НЕ billing-audit #62 (код), НЕ D1/D2 (право)"],
"needs": [
"ru-tax-question"
],
"produces": [
"ru-tax-context"
],
"constraints": [
"self-authored; закрывает РФ-gap finance-plugin (#61)",
"ADR-012: НЕ billing-audit #62 (код), НЕ D1/D2 (право)"
],
"preview-form": "outline",
"defaults": ["НДС/УСН по НК РФ; проводки по РСБУ"],
"key-decisions": ["налоговый режим и база"],
"acceptance-criteria": ["налоговый расчёт/проводка корректны по НК РФ/РСБУ"]
"defaults": [
"НДС/УСН по НК РФ; проводки по РСБУ"
],
"key-decisions": [
"налоговый режим и база"
],
"acceptance-criteria": [
"налоговый расчёт/проводка корректны по НК РФ/РСБУ"
]
}
@@ -1,12 +1,29 @@
{
"skill": "security-guidance",
"kind": "external",
"needs": ["правка файла с потенциально уязвимым паттерном"],
"produces": ["inline-предупреждение + блок правки (sys.exit 2)"],
"constraints": ["блокирующий PreToolUse-хук, speed-bump per файл+правило", "НЕ глубокий аудит (Trail of Bits)"],
"needs": [
"file-edit-risky"
],
"produces": [
"security-inline-warning"
],
"constraints": [
"блокирующий PreToolUse-хук, speed-bump per файл+правило",
"НЕ глубокий аудит (Trail of Bits)"
],
"preview-form": "none",
"defaults": ["одноразовый блок, retry проходит"],
"key-decisions": ["реальная уязвимость vs false-positive"],
"acceptance-criteria": ["уязвимый паттерн замечен до коммита"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"одноразовый блок, retry проходит"
],
"key-decisions": [
"реальная уязвимость vs false-positive"
],
"acceptance-criteria": [
"уязвимый паттерн замечен до коммита"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,12 +1,30 @@
{
"skill": "skill-creator",
"kind": "external",
"needs": ["намерение создать standalone Claude-скил"],
"produces": ["scaffold SKILL.md + evals.json + references/"],
"constraints": ["конструктор скилов с eval-набором", "НЕ плагины (plugin-dev)", "НЕ хуки (hookify)"],
"needs": [
"skill-authoring-intent"
],
"produces": [
"authored-skill"
],
"constraints": [
"конструктор скилов с eval-набором",
"НЕ плагины (plugin-dev)",
"НЕ хуки (hookify)"
],
"preview-form": "outline",
"defaults": ["скил с eval-набором для проверки точности"],
"key-decisions": ["scope и триггеры скила"],
"acceptance-criteria": ["скил оформлен, eval проходит"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"скил с eval-набором для проверки точности"
],
"key-decisions": [
"scope и триггеры скила"
],
"acceptance-criteria": [
"скил оформлен, eval проходит"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -1,12 +1,30 @@
{
"skill": "trail-of-bits",
"kind": "external",
"needs": ["diff/код для глубокого security-аудита"],
"produces": ["глубокий аудит-отчёт (diff-review / supply-chain / variant / static)"],
"constraints": ["on-demand глубокий аудит (8 скилов)", "НЕ inline-блок (Security Guidance)", "НЕ быстрый SAST (Semgrep)"],
"needs": [
"security-audit-target"
],
"produces": [
"security-audit-report"
],
"constraints": [
"on-demand глубокий аудит (8 скилов)",
"НЕ inline-блок (Security Guidance)",
"НЕ быстрый SAST (Semgrep)"
],
"preview-form": "outline",
"defaults": ["on-demand кампания, не в хуке"],
"key-decisions": ["какой аудит-скил под задачу"],
"acceptance-criteria": ["аудит покрыл diff/supply-chain/варианты"],
"source": { "version": "n/a", "hash": "0000000000000000000000000000000000000000000000000000000000000000", "path": "" }
"defaults": [
"on-demand кампания, не в хуке"
],
"key-decisions": [
"какой аудит-скил под задачу"
],
"acceptance-criteria": [
"аудит покрыл diff/supply-chain/варианты"
],
"source": {
"version": "n/a",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"path": ""
}
}
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:banner-design",
"kind": "external",
"needs": [
"задача дизайна баннера"
"ui-task"
],
"produces": [
"дизайн баннера (стек → Vue+Vuetify; код — Frontend Design)"
"banner-design-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:brand",
"kind": "external",
"needs": [
"задача бренд-системы UI"
"ui-task"
],
"produces": [
"бренд-система: палитра, типографика (приводится к нашему стеку)"
"ui-brand-system-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:design-system",
"kind": "external",
"needs": [
"задача дизайн-системы (токены/компоненты)"
"ui-task"
],
"produces": [
"токены и компоненты дизайн-системы (под Vue+Vuetify)"
"ui-design-system-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:design",
"kind": "external",
"needs": [
"унифицированная UI-дизайн-задача"
"ui-task"
],
"produces": [
"UI-дизайн (50+ стилей; стек → Vue+Vuetify; код — Frontend Design)"
"ui-design-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:slides",
"kind": "external",
"needs": [
"задача стратегической презентации"
"ui-task"
],
"produces": [
"стратегические слайды/презентация"
"slides-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:ui-styling",
"kind": "external",
"needs": [
"задача стилизации UI"
"ui-task"
],
"produces": [
"стилизация UI (источник shadcn/Tailwind → ОБЯЗАТЕЛЬНО приводится к Vue+Vuetify)"
"ui-styling-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
@@ -2,10 +2,10 @@
"skill": "ui-ux-pro-max:ui-ux-pro-max",
"kind": "external",
"needs": [
"широкая UI/UX-задача (выбор стиля/палитры/чарта)"
"ui-task"
],
"produces": [
"UI/UX-решение: 50+ стилей, 161 палитра, 57 пар шрифтов, 25 типов чартов (стек → Vue+Vuetify)"
"ui-ux-decision-material"
],
"constraints": [
"UI-навык пула ui-ux-pro-max",
+35
View File
@@ -0,0 +1,35 @@
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 load = (f) => JSON.parse(readFileSync(join(cdir, f), 'utf8'));
const PREFIXES = ['plugin-dev__', 'claude-md-management__', 'adr-kit__', 'ui-ux-pro-max__'];
const FILES = readdirSync(cdir).filter((f) => f.endsWith('.contract.json') && PREFIXES.some((p) => f.startsWith(p)));
FILES.push('frontend-design.contract.json');
const entries = FILES.map((f) => ({ contract: load(f), currentContent: '' }));
describe('Phase 2b группа skills — замок словаря + кросс-мост ui-design', () => {
const { tokens } = loadVocabulary({ path: vocabPath });
it('структурные skills-контракты группы B проходят замок словаря', () => {
const { contracts, errors } = buildRegistry(entries, { vocabTokens: tokens });
expect(errors).toEqual([]);
expect(contracts.length).toBe(FILES.length);
});
it('кросс-мост frontend-design -> design-handoff через ui-design', () => {
const fd = load('frontend-design.contract.json');
const dh = load('design-plugin__design-handoff.contract.json');
const { contracts } = buildRegistry([{ contract: fd }, { contract: dh }], { vocabTokens: tokens });
const { edges } = buildDependencyGraph(contracts);
expect(edges.some((e) => e.from === 'frontend-design' && e.to === 'design-plugin:design-handoff')).toBe(true);
});
});