feat(graph): 3-color conflicts data (CONFLICT_TYPES + 2 new edges + reclassify 6)

CONFLICT_TYPES enum (RED/BLACK/GREEN с color/bg/emoji/label/rank), CONFLICT() helper расширен опциональным `type` (default RED). 6 существующих рёбер реклассифицированы: 2 🔴 (sk_rls↔ag_rls, hookify↔hk_pre_claude), 4 🟢 (psr_v1↔claude_md, upm↔fd, 21st↔fd, economy↔superpowers). 2 новых  ребра: mcp_pw↔sk_parallel (browser-in-use, квирк #2), ag_pest↔mcp_redis (Redis race в Pest --parallel, квирк 72). NODE_DETAILS conflicts items получили field `type` для всех 12 existing + 4 new items. Iter2 spec §4.1, §4.2, §4.4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-14 12:59:25 +03:00
parent 5d1a782155
commit 9d0298c6aa
+40 -28
View File
@@ -213,6 +213,11 @@ const NODES = [
// ════════════════════════════════════════════════════
// SECTION 2: EDGES
// ════════════════════════════════════════════════════
const CONFLICT_TYPES = {
RED: { color: '#ff5f57', bg: '#2d0000', emoji: '🔴', label: 'Не закрыт правилом', rank: 1 },
BLACK: { color: '#888888', bg: '#1a1a1a', emoji: '⚫', label: 'Возник на практике', rank: 2 },
GREEN: { color: '#859900', bg: '#0e1a00', emoji: '🟢', label: 'Закрыт правилом', rank: 3 },
};
const E = (from, to, label) => ({
from, to,
title: label,
@@ -220,15 +225,15 @@ const E = (from, to, label) => ({
arrows: { to: { enabled: true, scaleFactor: 0.6 } },
smooth: { type: 'continuous', roundness: 0.5 }
});
const CONFLICT = (from, to, label) => ({
const CONFLICT = (from, to, label, type = 'RED') => ({
from, to,
title: label,
label: '⚡',
label: CONFLICT_TYPES[type].emoji,
dashes: true,
width: 2,
color: { color: '#ff5f57', highlight: '#ff8880', hover: '#ff8880' },
color: { color: CONFLICT_TYPES[type].color, highlight: '#ff8880', hover: '#ff8880' },
arrows: { to: { enabled: true, scaleFactor: 0.7 }, from: { enabled: true, scaleFactor: 0.7 } },
font: { color: '#ff5f57', size: 14, align: 'middle', strokeWidth: 3, strokeColor: '#1e1e2e' },
font: { color: CONFLICT_TYPES[type].color, size: 14, align: 'middle', strokeWidth: 3, strokeColor: '#1e1e2e' },
smooth: { type: 'curvedCW', roundness: 0.35 }
});
@@ -326,14 +331,17 @@ const EDGES = [
E('mcp_boost', 'ag_rls', 'схема БД\nдля RLS-review'),
// ══════════════════════════════════════════════════
// КОНФЛИКТЫ (красные пунктирные рёбра)
// КОНФЛИКТЫ — 3-color classification (iter2 §4)
// 🔴 не закрыт правилом / ⚫ возник на практике / 🟢 закрыт правилом
// ══════════════════════════════════════════════════
CONFLICT('psr_v1', 'claude_md', '⚡ T2.2'),
CONFLICT('upm', 'fd_plugin', '⚡ R14.5'),
CONFLICT('mcp_21st', 'fd_plugin', '⚡ R14.5'),
CONFLICT('sk_rls', 'ag_rls', '⚡ перекрытие RLS'),
CONFLICT('hookify_plugin','hk_pre_claude', '⚡ может затенить'),
CONFLICT('hk_economy', 'superpowers', '⚡ §12 vs Economy'),
CONFLICT('sk_rls', 'ag_rls', 'RLS compliance: оба покрывают, нет регламента', 'RED'),
CONFLICT('hookify_plugin', 'hk_pre_claude', 'hookify может перезаписать существующий хук', 'RED'),
CONFLICT('mcp_pw', 'sk_parallel', 'Browser is already in use (квирк #2)', 'BLACK'),
CONFLICT('ag_pest', 'mcp_redis', 'Redis race в Pest --parallel subdir-only (квирк 72)', 'BLACK'),
CONFLICT('psr_v1', 'claude_md', 'Закрыто §5п.10 CLAUDE.md + хук CLAUDE.md-warn', 'GREEN'),
CONFLICT('upm', 'fd_plugin', 'PSR_v1 R14.5: не параллельно', 'GREEN'),
CONFLICT('mcp_21st', 'fd_plugin', 'PSR_v1 R14.5: не параллельно', 'GREEN'),
CONFLICT('hk_economy', 'superpowers', 'Pravila §12.4: §12 неотменяем', 'GREEN'),
];
// ════════════════════════════════════════════════════
@@ -390,7 +398,7 @@ const NODE_DETAILS = {
{ name: 'Pravila', cond: 'оба читаются при старте сессии' },
{ name: 'Tooling', cond: 'оба — оперативные карты уровня 2' }
],
[{ name: 'PSR_v1', desc: 'Правило §5 п.10 запрещает прямые правки, но PSR_v1 это явно не повторяет — есть риск Edit без скила' }]
[{ name: 'PSR_v1', desc: 'Правило §5 п.10 запрещает прямые правки, но PSR_v1 это явно не повторяет — есть риск Edit без скила', type: 'GREEN' }]
),
psr_v1: nd(
'Правила совместной работы плагинов — кто с кем работает, какая процедура обязательна.',
@@ -403,7 +411,7 @@ const NODE_DETAILS = {
{ name: '21st Magic MCP', cond: 'R14.4: включается только через процедуру' }
],
[{ name: 'CLAUDE.md', cond: 'обе — оперативные карты, правятся согласованно' }],
[{ name: 'CLAUDE.md', desc: 'CLAUDE.md §5 п.10 требует править только через скил claude-md-mgmt, а PSR_v1 это ограничение не повторяет — риск прямых Edit' }]
[{ name: 'CLAUDE.md', desc: 'CLAUDE.md §5 п.10 требует править только через скил claude-md-mgmt, а PSR_v1 это ограничение не повторяет — риск прямых Edit', type: 'GREEN' }]
),
tooling: nd(
'Реестр 35 инструментов — когда что использовать, команды установки, конфликты.',
@@ -428,7 +436,7 @@ const NODE_DETAILS = {
],
[{ name: 'Все 14 Superpowers-скилов', cond: 'содержит' }],
[{ name: 'Frontend Design', cond: 'пара — работают вместе при UI-задачах' }],
[{ name: 'economy-mode хук', desc: 'Режим экономии 100% теоретически может «сэкономить» запуск скила и нарушить обязательное правило §12 (§12 нельзя отменить)' }]
[{ name: 'economy-mode хук', desc: 'Режим экономии 100% теоретически может «сэкономить» запуск скила и нарушить обязательное правило §12 (§12 нельзя отменить)', type: 'GREEN' }]
),
fd_plugin: nd(
'Плагин знаний о UI — Vue, Vuetify, доступность, паттерны компонентов для Лидерры.',
@@ -438,8 +446,8 @@ const NODE_DETAILS = {
[],
[{ name: 'Superpowers', cond: 'пара — FD даёт UI-знания, Superpowers даёт процесс' }],
[
{ name: 'UI UX Pro Max', desc: 'Правило PSR_v1 R14.5: нельзя одновременно — оба включены в настройках, но должны чередоваться' },
{ name: '21st Magic MCP', desc: 'Правило PSR_v1 R14.5: нельзя одновременно с FD — оба потенциально доступны' }
{ name: 'UI UX Pro Max', desc: 'Правило PSR_v1 R14.5: нельзя одновременно — оба включены в настройках, но должны чередоваться', type: 'GREEN' },
{ name: '21st Magic MCP', desc: 'Правило PSR_v1 R14.5: нельзя одновременно с FD — оба потенциально доступны', type: 'GREEN' }
]
),
upm: nd(
@@ -449,7 +457,7 @@ const NODE_DETAILS = {
[{ name: 'PSR_v1', cond: 'R14.3: включается только через процедуру, не сам по себе' }],
[],
[],
[{ name: 'Frontend Design', desc: 'Правило PSR_v1 R14.5: нельзя одновременно — UPM как материал, FD как решатель; риск смешать роли' }]
[{ name: 'Frontend Design', desc: 'Правило PSR_v1 R14.5: нельзя одновременно — UPM как материал, FD как решатель; риск смешать роли', type: 'GREEN' }]
),
claude_md_mgmt: nd(
'Единственный разрешённый способ править CLAUDE.md — через скил claude-md-improver или revise-claude-md.',
@@ -467,8 +475,8 @@ const NODE_DETAILS = {
[{ name: 'hookify:conversation-analyzer агент', cond: 'запускает анализ разговоров' }],
[{ name: 'hookify:conversation-analyzer', cond: 'плагин и агент работают в паре' }],
[
{ name: 'PreToolUse:CLAUDE.md-warn', desc: 'hookify создаёт новые PreToolUse-хуки на лету — может перезаписать или конкурировать с этим хуком' },
{ name: 'economy-mode хук', desc: 'новые хуки от hookify могут конфликтовать с логикой парсера режима экономии' }
{ name: 'PreToolUse:CLAUDE.md-warn', desc: 'hookify создаёт новые PreToolUse-хуки на лету — может перезаписать или конкурировать с этим хуком', type: 'RED' },
{ name: 'economy-mode хук', desc: 'новые хуки от hookify могут конфликтовать с логикой парсера режима экономии', type: 'BLACK' }
]
),
@@ -527,7 +535,8 @@ const NODE_DETAILS = {
'Изоляция через worktree обязательна — никакого «работаю в одной директории на 3 ветках сразу». Иначе риск конфликта файлов и веток.',
[{ name: 'Superpowers', cond: 'содержит' }],
[],
[{ name: 'worktree скил', cond: 'parallel-work использует worktree для изоляции' }]
[{ name: 'worktree скил', cond: 'parallel-work использует worktree для изоляции' }],
[{ name: 'MCP: playwright', desc: 'Browser is already in use при одновременном запуске нескольких сессий через worktrees', type: 'BLACK' }]
),
sk_worktree: nd(
'Создаёт изолированную копию репозитория (worktree) для рискованной или параллельной работы.',
@@ -598,7 +607,7 @@ const NODE_DETAILS = {
[{ name: 'Tooling §3.2', cond: 'использует squawk (#15) и команды grep' }],
[],
[{ name: 'MCP: laravel-boost', cond: 'SQL запросы к schema.sql для проверки' }],
[{ name: 'rls-reviewer агент', desc: 'оба проверяют соответствие политик RLS — скил для ручной проверки таблицы, агент для разбора PR/diff; нет чёткой границы когда какой' }]
[{ name: 'rls-reviewer агент', desc: 'оба проверяют соответствие политик RLS — скил для ручной проверки таблицы, агент для разбора PR/diff; нет чёткой границы когда какой', type: 'RED' }]
),
sk_qitem: nd(
'Добавляет новый открытый вопрос в реестр Открытые_вопросы_v8_3.md с обновлением счётчиков §0 и версии.',
@@ -617,7 +626,7 @@ const NODE_DETAILS = {
[{ name: '.claude/settings.json', cond: 'описан как хук PreToolUse' }],
[],
[],
[{ name: 'hookify (плагин)', desc: 'hookify динамически создаёт новые хуки PreToolUse — может перезаписать или конкурировать с этим хуком' }]
[{ name: 'hookify (плагин)', desc: 'hookify динамически создаёт новые хуки PreToolUse — может перезаписать или конкурировать с этим хуком', type: 'RED' }]
),
hk_post_md: nd(
'После каждого Edit .md-файла запускает markdownlint --fix автоматически.',
@@ -656,7 +665,7 @@ const NODE_DETAILS = {
[{ name: '.claude/settings.json', cond: 'описан как хук UserPromptSubmit' }],
[],
[],
[{ name: 'Superpowers (§12)', desc: 'Экономия=100% теоретически может «сэкономить» вызов скила, нарушая обязательное правило (см. §12) — §12 неотменяем, экономия его не отменяет' }]
[{ name: 'Superpowers (§12)', desc: 'Экономия=100% теоретически может «сэкономить» вызов скила, нарушая обязательное правило (см. §12) — §12 неотменяем, экономия его не отменяет', type: 'GREEN' }]
),
// ── АГЕНТЫ ───────────────────────────────────────
@@ -666,7 +675,8 @@ const NODE_DETAILS = {
'READ-ONLY (только читает код, ничего не правит). Каждую гипотезу подтверждает реальным запуском, а не «похоже на квирк».',
[{ name: 'CLAUDE.md §6', cond: 'описывает когда вызывать' }],
[],
[{ name: 'MCP: redis', cond: 'читает Redis для дебага квирка 72 (supplier:session race)' }]
[{ name: 'MCP: redis', cond: 'читает Redis для дебага квирка 72 (supplier:session race)' }],
[{ name: 'MCP: redis', desc: 'Pest --parallel subdir-only race с Redis-кэшем (квирк 72)', type: 'BLACK' }]
),
ag_rls: nd(
'Проверяет миграции на соответствие RLS (защите строк по тенанту) — 7 пунктов чеклиста с реальными командами, только чтение.',
@@ -675,7 +685,7 @@ const NODE_DETAILS = {
[{ name: 'CLAUDE.md', cond: 'описывает в §6 и в директории агентов' }],
[],
[{ name: 'MCP: laravel-boost', cond: 'SQL запросы к db/schema.sql' }],
[{ name: 'rls-check скил', desc: 'оба покрывают соответствие RLS, чёткой границы нет: агент — для PR и диффов, скил — для ручной проверки таблицы' }]
[{ name: 'rls-check скил', desc: 'оба покрывают соответствие RLS, чёткой границы нет: агент — для PR и диффов, скил — для ручной проверки таблицы', type: 'RED' }]
),
ag_statusline: nd(
'Настраивает строку состояния Claude Code через правку файла настроек.',
@@ -757,7 +767,8 @@ const NODE_DETAILS = {
'Не для боевых пользователей. На сессию один общий браузер — при parallel-work возможны столкновения (см. квирк #2 в memory).',
[{ name: 'CLAUDE.md §3.1 #2', cond: 'активен с фазы 0' }],
[],
[{ name: 'SessionStart хук', cond: 'используется для визуальной проверки прототипов' }]
[{ name: 'SessionStart хук', cond: 'используется для визуальной проверки прототипов' }],
[{ name: 'parallel-work скил', desc: 'Один shared browser на сессию — конкуренция при параллельной работе через worktrees (memory квирк #2)', type: 'BLACK' }]
),
mcp_gh: nd(
'GitHub API — читает/создаёт PR, issues, коммиты, ветки в репозитории CoralMinister/lidpotok.',
@@ -797,7 +808,8 @@ const NODE_DETAILS = {
'**СТРОГО READ-ONLY** — никаких DEL/FLUSHDB/SET/LPUSH из Claude (только GET/KEYS/LIST). Источник Anthropic устарел — миграция post-MVP.',
[{ name: 'CLAUDE.md §3.3 #35', cond: 'off-phase debug-runtime; PSR_v1 R10.1 блок 3' }],
[],
[{ name: 'pest-parallel-debugger агент', cond: 'агент использует для квирка 72 (гонка в Redis)' }]
[{ name: 'pest-parallel-debugger агент', cond: 'агент использует для квирка 72 (гонка в Redis)' }],
[{ name: 'pest-parallel-debugger агент', desc: 'Redis race condition в Pest --parallel subdir-only runs (квирк 72)', type: 'BLACK' }]
),
mcp_21st: nd(
'Генератор стартовых шаблонов UI-компонентов через LLM. Активация только через процедуру R14.4.',
@@ -806,7 +818,7 @@ const NODE_DETAILS = {
[{ name: 'PSR_v1 R14.4', cond: 'строгая предпроверка: 9 условий перед активацией' }],
[],
[],
[{ name: 'Frontend Design', desc: 'PSR_v1 R14.5: нельзя параллельно — 21st как генератор материала, FD как решатель; риск смешать роли и нарушить R6 (фильтр стека)' }]
[{ name: 'Frontend Design', desc: 'PSR_v1 R14.5: нельзя параллельно — 21st как генератор материала, FD как решатель; риск смешать роли и нарушить R6 (фильтр стека)', type: 'GREEN' }]
),
// ── LEFTHOOK JOBS ─────────────────────────────────