2026-05-13 17:05:59 +03:00
<!DOCTYPE html>
< html lang = "ru" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Система автоматизации Лидерры< / title >
< script src = "https://unpkg.com/vis-network@9.1.9/standalone/umd/vis-network.min.js" > < / script >
< style >
* { box-sizing : border-box ; margin : 0 ; padding : 0 ; }
body { background : #0d0d1a ; color : #fdf6e3 ; font-family : 'Segoe UI' , system-ui , sans-serif ; height : 100 vh ; display : flex ; flex-direction : column ; overflow : hidden ; }
/* ── Toolbar ── */
# toolbar { background : #073642 ; border-bottom : 1 px solid #586e75 ; padding : 8 px 12 px ; display : flex ; align-items : center ; gap : 10 px ; flex-shrink : 0 ; }
# toolbar h1 { font-size : 14 px ; color : #93a1a1 ; white-space : nowrap ; margin-right : 6 px ; }
# search { background : #002b36 ; border : 1 px solid #586e75 ; color : #fdf6e3 ; border-radius : 5 px ; padding : 5 px 10 px ; font-size : 13 px ; width : 220 px ; outline : none ; }
# search : focus { border-color : #268bd2 ; }
# search :: placeholder { color : #586e75 ; }
. btn { background : #073642 ; border : 1 px solid #586e75 ; color : #93a1a1 ; border-radius : 5 px ; padding : 5 px 12 px ; font-size : 12 px ; cursor : pointer ; transition : all 0.15 s ; }
. btn : hover { background : #0d4a5a ; color : #fdf6e3 ; border-color : #839496 ; }
# btn-clear { margin-left : auto ; }
/* ── Main area ── */
# main { flex : 1 ; display : flex ; overflow : hidden ; }
/* ── Graph canvas ── */
# network { flex : 1 ; background : #1e1e2e ; }
2026-05-14 09:09:01 +03:00
# network canvas { background : #1e1e2e ; }
2026-05-13 17:05:59 +03:00
/* ── Legend panel ── */
2026-05-14 12:17:08 +03:00
# legend-panel { width : 300 px ; min-width : 300 px ; background : #002b36 ; border-left : 1 px solid #586e75 ; overflow-y : auto ; padding : 16 px ; display : none ; flex-direction : column ; gap : 14 px ; position : relative ; }
# legend-handle {
position : absolute ; left : 0 ; top : 0 ;
width : 6 px ; height : 100 % ;
cursor : col-resize ;
background : transparent ;
transition : background 0.15 s ;
z-index : 10 ;
}
# legend-handle : hover , # legend-handle . dragging { background : #0d4a5a ; }
2026-05-13 17:05:59 +03:00
# legend-panel . visible { display : flex ; }
# legend-close { align-self : flex-end ; background : none ; border : none ; color : #586e75 ; font-size : 18 px ; cursor : pointer ; line-height : 1 ; padding : 0 ; }
# legend-close : hover { color : #fdf6e3 ; }
# legend-title { font-size : 15 px ; font-weight : 600 ; color : #fdf6e3 ; overflow-wrap : break-word ; }
2026-05-14 13:14:20 +03:00
# legend-edge-title { font-size : 15 px ; font-weight : 600 ; color : #fdf6e3 ; overflow-wrap : break-word ; line-height : 1.4 ; }
2026-05-13 17:05:59 +03:00
# legend-category { font-size : 11 px ; text-transform : uppercase ; letter-spacing : 0.08 em ; }
. legend-section { background : #073642 ; border-radius : 6 px ; padding : 10 px 12 px ; }
. legend-section h4 { font-size : 11 px ; text-transform : uppercase ; letter-spacing : 0.06 em ; color : #839496 ; margin-bottom : 6 px ; }
. legend-section p { font-size : 13 px ; color : #eee8d5 ; line-height : 1.5 ; }
. legend-section ul { list-style : none ; display : flex ; flex-direction : column ; gap : 4 px ; }
. legend-section li { font-size : 12 px ; color : #eee8d5 ; line-height : 1.4 ; }
. legend-section li span . cond { color : #839496 ; font-style : italic ; }
2026-05-14 13:16:56 +03:00
. conflict-item { border-radius : 4 px ; padding : 6 px 8 px ; margin-top : 4 px ; }
. conflict-item . cname { font-weight : 600 ; font-size : 12 px ; }
. conflict-item . cdesc { color : #eee8d5 ; font-size : 11 px ; margin-top : 2 px ; line-height : 1.4 ; }
2026-05-13 17:05:59 +03:00
# legend-no-conflicts { font-size : 12 px ; color : #586e75 ; }
/* ── Category legend footer ── */
# cat-legend { background : #073642 ; border-top : 1 px solid #586e75 ; padding : 7 px 14 px ; display : flex ; flex-wrap : wrap ; gap : 12 px ; flex-shrink : 0 ; }
. cat-item { display : flex ; align-items : center ; gap : 5 px ; font-size : 11 px ; color : #839496 ; }
. cat-dot { width : 10 px ; height : 10 px ; border-radius : 50 % ; flex-shrink : 0 ; }
2026-05-15 06:04:27 +03:00
/* .cat-item interactive states (Task 1) — separate from layout rule above to keep concerns split */
2026-05-15 06:00:14 +03:00
. cat-item {
cursor : pointer ;
padding : 2 px 6 px ;
border-radius : 4 px ;
transition : background 0.12 s , box-shadow 0.12 s ;
user-select : none ;
}
. cat-item : hover { background : rgba ( 255 , 255 , 255 , 0.05 ) ; }
. cat-item . active {
background : rgba ( 253 , 246 , 227 , 0.12 ) ;
box-shadow : inset 0 0 0 1 px rgba ( 253 , 246 , 227 , 0.4 ) ;
color : #fdf6e3 ;
}
2026-05-16 09:41:04 +03:00
/* ── Паспорт узла (iter6) ── */
# passport-section p { font-size : 12 px ; color : #eee8d5 ; line-height : 1.6 ; }
# passport-section p . pp-k { color : #839496 ; }
2026-05-16 09:54:44 +03:00
/* ── Кнопки режимов в футере (iter6) ── */
. cat-ctl-sep { width : 1 px ; align-self : stretch ; background : #586e75 ; margin : 0 4 px ; }
. cat-ctl {
background : #002b36 ; border : 1 px solid #586e75 ; color : #93a1a1 ;
border-radius : 4 px ; padding : 2 px 8 px ; font-size : 11 px ; cursor : pointer ;
transition : background 0.12 s , box-shadow 0.12 s ; user-select : none ;
}
. cat-ctl : hover { background : #0d4a5a ; color : #fdf6e3 ; }
. cat-ctl . active {
background : rgba ( 253 , 246 , 227 , 0.12 ) ;
box-shadow : inset 0 0 0 1 px rgba ( 253 , 246 , 227 , 0.4 ) ;
color : #fdf6e3 ;
}
2026-05-16 15:03:48 +03:00
/* ── Панель «Разделы» (функциональная квалификация) ── */
# legend-sections-content { display : flex ; flex-direction : column ; gap : 10 px ; }
# legend-sections-title { font-size : 15 px ; font-weight : 600 ; color : #fdf6e3 ; }
. sect-bucket-h { font-size : 11 px ; text-transform : uppercase ; letter-spacing : 0.06 em ; color : #b58900 ; font-weight : 600 ; margin : 8 px 0 2 px ; }
. sect-row { background : #073642 ; border-radius : 6 px ; padding : 7 px 10 px ; }
. sect-row . sect-empty { opacity : 0.5 ; }
. sect-name { font-size : 12 px ; color : #eee8d5 ; font-weight : 600 ; }
. sect-name . sect-id { color : #839496 ; font-weight : 400 ; }
. sect-cnt { font-size : 11 px ; color : #839496 ; }
. sect-empty-mark { font-size : 11 px ; color : #586e75 ; font-style : italic ; margin-top : 3 px ; }
. sect-chips { display : flex ; flex-wrap : wrap ; gap : 4 px ; margin-top : 5 px ; }
. sect-chip { font-size : 10 px ; color : #93a1a1 ; background : #002b36 ; border : 1 px solid #586e75 ; border-radius : 3 px ; padding : 1 px 5 px ; cursor : pointer ; }
. sect-chip : hover { background : #0d4a5a ; color : #fdf6e3 ; }
2026-05-16 22:31:26 +03:00
/* ── Панель «Хотелки» (отложенный backlog развития мозга) ── */
# legend-wishlist-content { display : flex ; flex-direction : column ; gap : 10 px ; }
# legend-wishlist-title { font-size : 15 px ; font-weight : 600 ; color : #fdf6e3 ; }
. wish-row { background : #073642 ; border-radius : 6 px ; padding : 8 px 10 px ; border-left : 3 px solid #586e75 ; }
. wish-row . wish-next { border-left-color : #859900 ; }
. wish-row . wish-blocked { border-left-color : #b58900 ; }
. wish-row . wish-idea { border-left-color : #586e75 ; }
. wish-head { font-size : 12 px ; color : #eee8d5 ; font-weight : 600 ; }
. wish-head . wish-id { color : #839496 ; font-weight : 400 ; }
. wish-status { font-size : 11 px ; margin-top : 3 px ; }
. wish-note { font-size : 11 px ; color : #93a1a1 ; margin-top : 4 px ; line-height : 1.5 ; }
. wish-sect { font-size : 10 px ; color : #586e75 ; margin-top : 4 px ; }
. wish-legend { font-size : 10 px ; color : #586e75 ; display : flex ; flex-wrap : wrap ; gap : 8 px ; margin-top : 6 px ; }
2026-05-13 17:05:59 +03:00
< / style >
< / head >
< body >
< div id = "toolbar" >
< h1 > 🗺 Лидерра — карта автоматизации< / h1 >
< input id = "search" type = "text" placeholder = "Поиск узла…" autocomplete = "off" >
< button class = "btn" id = "btn-freeze" > ❄ Зафиксировать< / button >
< button class = "btn" id = "btn-unfreeze" > ▶ Расшевелить< / button >
< button class = "btn" id = "btn-reset" > ⊙ Сбросить вид< / button >
< button class = "btn" id = "btn-clear" > ✕ Снять выделение< / button >
< / div >
< div id = "main" >
< div id = "network" > < / div >
< div id = "legend-panel" >
2026-05-14 12:17:08 +03:00
< div id = "legend-handle" title = "Перетащи, чтобы изменить ширину" > < / div >
2026-05-13 17:05:59 +03:00
< button id = "legend-close" > × < / button >
2026-05-14 13:14:20 +03:00
< div id = "legend-node-content" >
< div id = "legend-title" > —< / div >
< div id = "legend-category" > < / div >
2026-05-16 09:41:04 +03:00
< div class = "legend-section" id = "passport-section" >
< h4 > 📇 Паспорт узла< / h4 >
< p > < span class = "pp-k" > Внедрён:< / span > < span id = "ld-since" > —< / span > < / p >
< p > < span class = "pp-k" > Последнее изменение:< / span > < span id = "ld-changed" > —< / span > < / p >
2026-05-16 15:03:48 +03:00
< p > < span class = "pp-k" > Раздел:< / span > < span id = "ld-section" > —< / span > < / p >
2026-05-16 09:41:04 +03:00
< p > < span class = "pp-k" > Использований за 7 дней:< / span > < span id = "ld-uses" > —< / span > < / p >
< p id = "ld-dup-row" style = "display:none;" > < span class = "pp-k" > Дубль:< / span > < span id = "ld-dup" > —< / span > < / p >
< / div >
2026-05-14 13:14:20 +03:00
< div class = "legend-section" > < h4 > Что делает< / h4 > < p id = "ld-desc" > —< / p > < / div >
< div class = "legend-section" > < h4 > Когда используется< / h4 > < p id = "ld-when" > —< / p > < / div >
< div class = "legend-section" > < h4 > Ограничения< / h4 > < p id = "ld-limits" > —< / p > < / div >
< div class = "legend-section" > < h4 > Кому подчиняется< / h4 > < ul id = "ld-reports" > < / ul > < / div >
< div class = "legend-section" > < h4 > Кто подчиняется ему< / h4 > < ul id = "ld-manages" > < / ul > < / div >
< div class = "legend-section" > < h4 > С кем работает одновременно< / h4 > < ul id = "ld-together" > < / ul > < / div >
< div class = "legend-section" id = "conflicts-section" >
< h4 > ⚡ Конфликты< / h4 >
< div id = "ld-conflicts" > < / div >
< / div >
< / div >
< div id = "legend-edge-content" style = "display:none;" >
< div id = "legend-edge-title" > —< / div >
< div class = "legend-section" > < h4 > Источник запроса< / h4 > < p id = "le-from" > —< / p > < / div >
< div class = "legend-section" > < h4 > Конечный получатель< / h4 > < p id = "le-to" > —< / p > < / div >
< div class = "legend-section" > < h4 > Тип связи< / h4 > < p id = "le-type" > —< / p > < / div >
< div class = "legend-section" > < h4 > Когда срабатывает< / h4 > < p id = "le-when" > —< / p > < / div >
< div class = "legend-section" > < h4 > Что передаёт< / h4 > < p id = "le-transfers" > —< / p > < / div >
< div class = "legend-section" > < h4 > Обязательность< / h4 > < p id = "le-mandatory" > —< / p > < / div >
< div class = "legend-section" > < h4 > Регламент< / h4 > < p id = "le-rule" > —< / p > < / div >
2026-05-13 17:05:59 +03:00
< / div >
2026-05-16 15:03:48 +03:00
< div id = "legend-sections-content" style = "display:none;" >
< div id = "legend-sections-title" > 📂 Разделы деятельности Лидерры< / div >
< div class = "legend-section" >
< p > Узлы карты распределены по функциональным разделам. Пустые разделы — будущие домены «мозга», под которые в карте dev-автоматики ещё нет узлов (playbook не наполнен).< / p >
< / div >
< div id = "sect-list" > < / div >
< / div >
2026-05-16 22:31:26 +03:00
< div id = "legend-wishlist-content" style = "display:none;" >
< div id = "legend-wishlist-title" > 💡 Хотелки — отложенный backlog< / div >
< div class = "legend-section" >
< p > Отложенные «хотелки» развития мозга и портала — то, что решили сделать позже, чтобы не забыть. Источник правды — массив WISHLIST в этом HTML-файле; новая хотелка = новый объект.< / p >
< div class = "wish-legend" > < span > ▶ к работе< / span > < span > ⏸ ждёт зависимости< / span > < span > 💭 идея< / span > < / div >
< / div >
< div id = "wish-list" > < / div >
< / div >
2026-05-13 17:05:59 +03:00
< / div >
< / div >
2026-05-15 06:12:43 +03:00
<!-- data - filter - key атрибуты потребляются SECTION 8 (interactive highlighting) -->
2026-05-13 17:05:59 +03:00
< div id = "cat-legend" >
2026-05-15 06:07:16 +03:00
< div class = "cat-item" data-filter-key = "group:rules" > < div class = "cat-dot" style = "background:#268bd2" > < / div > Правила< / div >
< div class = "cat-item" data-filter-key = "group:plugins" > < div class = "cat-dot" style = "background:#859900" > < / div > Плагины< / div >
< div class = "cat-item" data-filter-key = "group:skills_sp" > < div class = "cat-dot" style = "background:#6c71c4" > < / div > Скилы Superpowers< / div >
< div class = "cat-item" data-filter-key = "group:skills_proj" > < div class = "cat-dot" style = "background:#d33682" > < / div > Скилы проекта< / div >
< div class = "cat-item" data-filter-key = "group:hooks" > < div class = "cat-dot" style = "background:#2aa198" > < / div > Хуки< / div >
< div class = "cat-item" data-filter-key = "group:agents" > < div class = "cat-dot" style = "background:#b58900" > < / div > Агенты< / div >
< div class = "cat-item" data-filter-key = "group:mcp" > < div class = "cat-dot" style = "background:#cb4b16" > < / div > MCP-серверы< / div >
< div class = "cat-item" data-filter-key = "group:lefthook" > < div class = "cat-dot" style = "background:#dc322f" > < / div > Lefthook jobs< / div >
< div class = "cat-item" data-filter-key = "group:memory" > < div class = "cat-dot" style = "background:#586e75" > < / div > Memory files< / div >
2026-05-15 15:34:39 +03:00
< div class = "cat-item" data-filter-key = "group:ruflo" > < div class = "cat-dot" style = "background:#ff8800" > < / div > 🌊 ruflo (оркестратор)< / div >
2026-05-15 06:07:16 +03:00
< div class = "cat-item" data-filter-key = "conflict:RED" > < div class = "cat-dot" style = "background:#ff5f57; border:1px dashed #ff5f57" > < / div > 🔴 Не закрыт правилом< / div >
< div class = "cat-item" data-filter-key = "conflict:BLACK" > < div class = "cat-dot" style = "background:#888888; border:1px dashed #888888" > < / div > ⚫ Возник на практике< / div >
< div class = "cat-item" data-filter-key = "conflict:GREEN" > < div class = "cat-dot" style = "background:#859900; border:1px dashed #859900" > < / div > 🟢 Закрыт правилом< / div >
2026-05-16 09:54:44 +03:00
< span class = "cat-ctl-sep" > < / span >
< button class = "cat-ctl" id = "cat-ctl-heat" title = "Подсветить узлы по числу вызовов за 7 дней" > 🔥 По использованию< / button >
< button class = "cat-ctl" id = "cat-ctl-dup" title = "Подсветить явные пары дублей (D1–D5, D7)" > ⧉ Дубли< / button >
2026-05-16 15:03:48 +03:00
< button class = "cat-ctl" id = "cat-ctl-sect" title = "Показать функциональные разделы и распределение узлов по ним" > 📂 Разделы< / button >
2026-05-16 22:31:26 +03:00
< button class = "cat-ctl" id = "cat-ctl-wish" title = "Показать отложенные хотелки — backlog развития мозга и портала" > 💡 Хотелки< / button >
2026-05-13 17:05:59 +03:00
< / div >
< script >
// ════════════════════════════════════════════════════
// SECTION 1: NODES
// ════════════════════════════════════════════════════
2026-05-14 09:22:45 +03:00
// Радиально-секторная компоновка.
// Сектора (по 90°): N=workflow (0– 90), E=UI (90– 180), S=infra (180– 270), W=data/RLS (270– 360).
const RADII = [ 0 , 220 , 400 , 600 , 800 , 1000 , 1180 ] ;
function pos ( ring , angleDeg ) {
const r = RADII [ ring ] ;
const a = angleDeg * Math . PI / 180 ;
return { x : Math . round ( r * Math . cos ( a ) ) , y : Math . round ( r * Math . sin ( a ) ) } ;
}
2026-05-13 17:05:59 +03:00
const NODES = [
2026-05-14 09:22:45 +03:00
// ── ПРАВИЛА (4) ── центр + первое кольцо ───────
2026-05-16 13:44:14 +03:00
{ id : 'pravila' , label : 'Pravila v1.16' , group : 'rules' , size : 38 , ring : 0 , ... pos ( 0 , 0 ) } ,
{ id : 'claude_md' , label : 'CLAUDE.md v2.2' , group : 'rules' , size : 34 , ring : 1 , ... pos ( 1 , 30 ) } ,
{ id : 'psr_v1' , label : 'PSR_v1 v3.2' , group : 'rules' , size : 32 , ring : 1 , ... pos ( 1 , 150 ) } ,
{ id : 'tooling' , label : 'Tooling v2.2' , group : 'rules' , size : 30 , ring : 1 , ... pos ( 1 , 270 ) } ,
2026-05-14 09:22:45 +03:00
2026-05-17 04:46:32 +03:00
// ── ПЛАГИНЫ (11) ── второе кольцо ──────────────
2026-05-14 09:22:45 +03:00
{ id : 'superpowers' , label : 'Superpowers v5.1' , group : 'plugins' , size : 30 , ring : 2 , ... pos ( 2 , 45 ) } ,
{ id : 'fd_plugin' , label : 'Frontend Design' , group : 'plugins' , size : 26 , ring : 2 , ... pos ( 2 , 135 ) } ,
{ id : 'upm' , label : 'UI UX Pro Max' , group : 'plugins' , size : 22 , ring : 2 , ... pos ( 2 , 165 ) } ,
{ id : 'claude_md_mgmt' , label : 'claude-md-mgmt' , group : 'plugins' , size : 22 , ring : 2 , ... pos ( 2 , 225 ) } ,
{ id : 'hookify_plugin' , label : 'hookify (плагин)' , group : 'plugins' , size : 22 , ring : 2 , ... pos ( 2 , 200 ) } ,
2026-05-16 15:39:47 +03:00
{ id : 'skill_creator' , label : 'skill-creator' , group : 'plugins' , size : 20 , ring : 2 , ... pos ( 2 , 70 ) } ,
{ id : 'claude_setup' , label : 'claude-code-setup' , group : 'plugins' , size : 22 , ring : 2 , ... pos ( 2 , 90 ) } ,
{ id : 'plugin_dev' , label : 'plugin-dev' , group : 'plugins' , size : 22 , ring : 2 , ... pos ( 2 , 290 ) } ,
{ id : 'context7' , label : 'context7 (docs MCP)' , group : 'plugins' , size : 20 , ring : 2 , ... pos ( 2 , 315 ) } ,
2026-05-17 04:46:32 +03:00
// A6 architecture-tooling (17.05.2026) — 2 плагина раздела «Архитектура систем»
{ id : 'adr_kit' , label : 'adr-kit' , group : 'plugins' , size : 22 , ring : 2 , ... pos ( 2 , 240 ) } ,
{ id : 'arch_patterns' , label : 'architecture-patterns' , group : 'plugins' , size : 20 , ring : 2 , ... pos ( 2 , 250 ) } ,
2026-05-14 09:22:45 +03:00
// ── СКИЛЫ SUPERPOWERS (14) — N sector (0– 90) ────
{ id : 'sk_brainstorm' , label : 'brainstorming' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 5 ) } ,
{ id : 'sk_wplans' , label : 'writing-plans' , group : 'skills_sp' , size : 20 , ring : 3 , ... pos ( 3 , 11 ) } ,
{ id : 'sk_eplans' , label : 'executing-plans' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 17 ) } ,
{ id : 'sk_subagent' , label : 'subagent-driven' , group : 'skills_sp' , size : 20 , ring : 3 , ... pos ( 3 , 23 ) } ,
{ id : 'sk_tdd' , label : 'TDD' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 29 ) } ,
{ id : 'sk_verify' , label : 'verification-before-completion' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 36 ) } ,
{ id : 'sk_debug' , label : 'systematic-debugging' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 43 ) } ,
{ id : 'sk_parallel' , label : 'parallel-work' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 50 ) } ,
{ id : 'sk_worktree' , label : 'worktree' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 57 ) } ,
{ id : 'sk_pr' , label : 'finishing-pr' , group : 'skills_sp' , size : 18 , ring : 3 , ... pos ( 3 , 64 ) } ,
{ id : 'sk_coderev' , label : 'code-review' , group : 'skills_sp' , size : 16 , ring : 3 , ... pos ( 3 , 71 ) } ,
{ id : 'sk_spreview' , label : 'spec-review' , group : 'skills_sp' , size : 16 , ring : 3 , ... pos ( 3 , 78 ) } ,
{ id : 'sk_wskills' , label : 'writing-skills' , group : 'skills_sp' , size : 16 , ring : 3 , ... pos ( 3 , 85 ) } ,
{ id : 'sk_elements' , label : 'elements-of-style' , group : 'skills_sp' , size : 16 , ring : 3 , ... pos ( 3 , 92 ) } ,
2026-05-17 04:46:32 +03:00
// ── СКИЛЫ ПРОЕКТА (4) — W sector (RLS/arch) ────
2026-05-14 09:22:45 +03:00
{ id : 'sk_rls' , label : 'rls-check' , group : 'skills_proj' , size : 20 , ring : 3 , ... pos ( 3 , 305 ) } ,
{ id : 'sk_qitem' , label : 'q-item-add' , group : 'skills_proj' , size : 20 , ring : 3 , ... pos ( 3 , 220 ) } ,
2026-05-16 15:39:47 +03:00
{ id : 'sk_regression' , label : 'regression' , group : 'skills_proj' , size : 20 , ring : 3 , ... pos ( 3 , 260 ) } ,
2026-05-17 04:46:32 +03:00
// A6 architecture-tooling (17.05.2026) — вендоренный скил диаграмм
{ id : 'mermaid_skill' , label : 'mermaid (skill)' , group : 'skills_proj' , size : 18 , ring : 3 , ... pos ( 3 , 280 ) } ,
2026-05-14 09:22:45 +03:00
2026-05-16 15:39:47 +03:00
// ── ХУКИ (12) — S+infra + E (economy/skill) ───
2026-05-14 09:22:45 +03:00
{ id : 'hk_session' , label : 'SessionStart:\ncontext-inject' , group : 'hooks' , size : 24 , ring : 4 , ... pos ( 4 , 100 ) } ,
{ id : 'hk_economy' , label : 'UserPromptSubmit:\neconomy-mode' , group : 'hooks' , size : 22 , ring : 4 , ... pos ( 4 , 95 ) } ,
{ id : 'hk_pre_claude' , label : 'PreToolUse:\nCLAUDE.md-warn' , group : 'hooks' , size : 22 , ring : 4 , ... pos ( 4 , 215 ) } ,
{ id : 'hk_post_md' , label : 'PostToolUse:\nmarkdownlint' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 195 ) } ,
{ id : 'hk_post_schema' , label : 'PostToolUse:\nschema-changelog' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 300 ) } ,
2026-05-16 15:39:47 +03:00
{ id : 'hk_self_check' , label : 'SessionStart:\neconomy-self-check' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 105 ) } ,
{ id : 'hk_skill_marker' , label : 'PreToolUse:\nskill-marker' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 115 ) } ,
{ id : 'hk_skill_check' , label : 'PreToolUse:\nskill-check' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 125 ) } ,
{ id : 'hk_state_guard' , label : 'PreToolUse:\neconomy-state-guard' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 135 ) } ,
{ id : 'hk_postcompact' , label : 'PostCompact:\neconomy-postcompact' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 145 ) } ,
{ id : 'hk_verifier' , label : 'Stop:\neconomy-verifier (агент)' , group : 'hooks' , size : 22 , ring : 4 , ... pos ( 4 , 155 ) } ,
{ id : 'hk_ruflo_queen' , label : 'UserPromptSubmit:\nruflo-queen-hook' , group : 'hooks' , size : 20 , ring : 4 , ... pos ( 4 , 165 ) } ,
2026-05-14 09:22:45 +03:00
// ── АГЕНТЫ (11) — N (workflow) + W (RLS) ──────
{ id : 'ag_explore' , label : 'Explore' , group : 'agents' , size : 20 , ring : 4 , ... pos ( 4 , 10 ) } ,
{ id : 'ag_general' , label : 'general-purpose' , group : 'agents' , size : 20 , ring : 4 , ... pos ( 4 , 25 ) } ,
{ id : 'ag_plan' , label : 'Plan' , group : 'agents' , size : 20 , ring : 4 , ... pos ( 4 , 40 ) } ,
{ id : 'ag_pest' , label : 'pest-parallel-debugger' , group : 'agents' , size : 24 , ring : 4 , ... pos ( 4 , 55 ) } ,
{ id : 'ag_guide' , label : 'claude-code-guide' , group : 'agents' , size : 18 , ring : 4 , ... pos ( 4 , 70 ) } ,
{ id : 'ag_statusline' , label : 'statusline-setup' , group : 'agents' , size : 18 , ring : 4 , ... pos ( 4 , 85 ) } ,
{ id : 'ag_hookify' , label : 'hookify:\nconversation-analyzer' , group : 'agents' , size : 18 , ring : 4 , ... pos ( 4 , 230 ) } ,
{ id : 'ag_pcreator' , label : 'plugin-dev:\nagent-creator' , group : 'agents' , size : 16 , ring : 4 , ... pos ( 4 , 245 ) } ,
{ id : 'ag_pvalid' , label : 'plugin-dev:\nplugin-validator' , group : 'agents' , size : 16 , ring : 4 , ... pos ( 4 , 260 ) } ,
{ id : 'ag_skreview' , label : 'plugin-dev:\nskill-reviewer' , group : 'agents' , size : 16 , ring : 4 , ... pos ( 4 , 275 ) } ,
{ id : 'ag_rls' , label : 'rls-reviewer' , group : 'agents' , size : 22 , ring : 4 , ... pos ( 4 , 315 ) } ,
// ── MCP-СЕРВЕРЫ (7) — E (UI) + W (data) ───────
{ id : 'mcp_21st' , label : 'MCP: 21st.dev Magic' , group : 'mcp' , size : 20 , ring : 5 , ... pos ( 5 , 130 ) } ,
{ id : 'mcp_pw' , label : 'MCP: playwright' , group : 'mcp' , size : 22 , ring : 5 , ... pos ( 5 , 110 ) } ,
{ id : 'mcp_gh' , label : 'MCP: github' , group : 'mcp' , size : 22 , ring : 5 , ... pos ( 5 , 75 ) } ,
{ id : 'mcp_boost' , label : 'MCP: laravel-boost' , group : 'mcp' , size : 24 , ring : 5 , ... pos ( 5 , 290 ) } ,
{ id : 'mcp_redis' , label : 'MCP: redis' , group : 'mcp' , size : 22 , ring : 5 , ... pos ( 5 , 310 ) } ,
{ id : 'mcp_sentry' , label : 'MCP: sentry' , group : 'mcp' , size : 22 , ring : 5 , ... pos ( 5 , 330 ) } ,
{ id : 'mcp_semgrep' , label : 'MCP: semgrep' , group : 'mcp' , size : 20 , ring : 5 , ... pos ( 5 , 350 ) } ,
// ── LEFTHOOK JOBS (10) — S+W (infra/data) ─────
{ id : 'lh_mdlint' , label : 'lefthook:\nmarkdownlint' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 185 ) } ,
{ id : 'lh_cspell' , label : 'lefthook:\ncspell' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 200 ) } ,
{ id : 'lh_stylelint' , label : 'lefthook:\nstylelint' , group : 'lefthook' , size : 16 , ring : 5 , ... pos ( 5 , 215 ) } ,
{ id : 'lh_eslint' , label : 'lefthook:\neslint-vue' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 230 ) } ,
{ id : 'lh_lychee' , label : 'lefthook:\nlychee-links' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 245 ) } ,
{ id : 'lh_gitleaks' , label : 'lefthook:\ngitleaks' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 260 ) } ,
{ id : 'lh_gitleaks2' , label : 'lefthook:\ngitleaks pre-push' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 275 ) } ,
{ id : 'lh_pint' , label : 'lefthook:\npint' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 25 ) } ,
{ id : 'lh_larastan' , label : 'lefthook:\nlarastan' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 50 ) } ,
{ id : 'lh_squawk' , label : 'lefthook:\nsquawk' , group : 'lefthook' , size : 18 , ring : 5 , ... pos ( 5 , 320 ) } ,
2026-05-16 15:39:47 +03:00
// ── MEMORY FILES (23) — внешнее кольцо ──────────
2026-05-14 09:22:45 +03:00
{ id : 'mem_user' , label : 'memory:\nuser_profile' , group : 'memory' , size : 16 , ring : 6 , ... pos ( 6 , 0 ) } ,
{ id : 'mem_comm' , label : 'memory:\nfeedback_comm' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 24 ) } ,
{ id : 'mem_env' , label : 'memory:\nfeedback_env' , group : 'memory' , size : 16 , ring : 6 , ... pos ( 6 , 48 ) } ,
{ id : 'mem_sp' , label : 'memory:\nfeedback_superpowers' , group : 'memory' , size : 16 , ring : 6 , ... pos ( 6 , 72 ) } ,
{ id : 'mem_plugins' , label : 'memory:\nfeedback_plugins' , group : 'memory' , size : 16 , ring : 6 , ... pos ( 6 , 96 ) } ,
{ id : 'mem_handoff' , label : 'memory:\nreference_handoff' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 120 ) } ,
{ id : 'mem_redesign' , label : 'memory:\nportal_redesign' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 144 ) } ,
{ id : 'mem_devindices' , label : 'memory:\ndev_indices' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 168 ) } ,
{ id : 'mem_phase1' , label : 'memory:\nphase1_strategy' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 192 ) } ,
{ id : 'mem_state' , label : 'memory:\nproject_state' , group : 'memory' , size : 16 , ring : 6 , ... pos ( 6 , 216 ) } ,
{ id : 'mem_brain' , label : 'memory:\nclaude_brain' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 240 ) } ,
{ id : 'mem_supplier' , label : 'memory:\nsupplier_integration' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 264 ) } ,
{ id : 'mem_audit' , label : 'memory:\naudit_2026-05-13' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 288 ) } ,
{ id : 'mem_archive' , label : 'memory:\nreference_archive' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 312 ) } ,
{ id : 'mem_github' , label : 'memory:\nreference_github' , group : 'memory' , size : 14 , ring : 6 , ... pos ( 6 , 336 ) } ,
2026-05-16 15:39:47 +03:00
{ id : 'mem_audit_b' , label : 'memory:\naudit_B_status' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 12 ) } ,
{ id : 'mem_audit_c' , label : 'memory:\naudit_C_pending' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 36 ) } ,
{ id : 'mem_suppliercrm' , label : 'memory:\nsupplier_crm' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 60 ) } ,
{ id : 'mem_audit12' , label : 'memory:\nfull_audit_05-12' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 84 ) } ,
{ id : 'mem_audit14' , label : 'memory:\nfull_audit_05-14' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 108 ) } ,
{ id : 'mem_sprint1' , label : 'memory:\nsprint1_p0_closure' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 132 ) } ,
{ id : 'mem_sprint2' , label : 'memory:\nsprint2_p1_progress' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 156 ) } ,
{ id : 'mem_sprint3' , label : 'memory:\nsprint3_progress' , group : 'memory' , size : 12 , ring : 6 , ... pos ( 6 , 180 ) } ,
2026-05-15 15:34:39 +03:00
2026-05-16 06:48:46 +03:00
// ── RUFLO ОРКЕСТРАТОР (9) — фактический реколлаж iter5 — кластер вне радиального layout (верх-лево) ──
{ id : 'ruflo_queen' , label : 'ruflo Queen\n(hive-mind)' , group : 'ruflo' , size : 44 , x : - 1340 , y : - 700 } ,
{ id : 'ruflo_plugins' , label : 'плагины ruflo\n0 из 20 · скилов 0' , group : 'ruflo' , size : 20 , x : - 1340 , y : - 880 } ,
{ id : 'ruflo_workers' , label : '10 воркеров\nhive-mind (idle)' , group : 'ruflo' , size : 26 , x : - 1160 , y : - 800 } ,
{ id : 'ruflo_agents_catalog' , label : 'каталог агентов ruflo\n(100 определений)' , group : 'ruflo' , size : 24 , x : - 1530 , y : - 830 } ,
{ id : 'ruflo_commands' , label : 'slash-команды\nruflo (88)' , group : 'ruflo' , size : 22 , x : - 1140 , y : - 630 } ,
{ id : 'ruflo_daemon' , label : 'демон ruflo\n(воркеры падают)' , group : 'ruflo' , size : 24 , x : - 1560 , y : - 650 } ,
{ id : 'ruflo_memory' , label : 'память ruflo\n(~0 записей)' , group : 'ruflo' , size : 24 , x : - 1380 , y : - 500 } ,
{ id : 'ruflo_mcp' , label : 'ruflo MCP\n(~210 инструментов)' , group : 'ruflo' , size : 26 , x : - 1190 , y : - 460 } ,
{ id : 'ruflo_recall_hook' , label : 'хук recall\n(UserPromptSubmit)' , group : 'ruflo' , size : 22 , x : - 1570 , y : - 470 } ,
2026-05-15 15:34:39 +03:00
// ── MEMORY +1 (артефакт ruflo big-bang) ──
2026-05-16 06:48:46 +03:00
{ id : 'mem_ruflo' , label : 'memory:\nproject_ruflo_integration' , group : 'memory' , size : 14 , x : - 1740 , y : - 620 } ,
2026-05-13 17:05:59 +03:00
] ;
// ════════════════════════════════════════════════════
// SECTION 2: EDGES
// ════════════════════════════════════════════════════
2026-05-14 12:59:25 +03:00
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 } ,
} ;
2026-05-13 17:05:59 +03:00
const E = ( from , to , label ) => ( {
2026-05-14 09:09:42 +03:00
from , to ,
title : label ,
2026-05-13 17:05:59 +03:00
color : { color : '#586e75' , highlight : '#93a1a1' , hover : '#93a1a1' } ,
arrows : { to : { enabled : true , scaleFactor : 0.6 } } ,
2026-05-14 09:09:42 +03:00
smooth : { type : 'continuous' , roundness : 0.5 }
2026-05-13 17:05:59 +03:00
} ) ;
2026-05-14 12:59:25 +03:00
const CONFLICT = ( from , to , label , type = 'RED' ) => ( {
2026-05-14 09:09:42 +03:00
from , to ,
title : label ,
2026-05-14 12:59:25 +03:00
label : CONFLICT _TYPES [ type ] . emoji ,
2026-05-13 17:05:59 +03:00
dashes : true ,
width : 2 ,
2026-05-14 12:59:25 +03:00
color : { color : CONFLICT _TYPES [ type ] . color , highlight : '#ff8880' , hover : '#ff8880' } ,
2026-05-13 17:05:59 +03:00
arrows : { to : { enabled : true , scaleFactor : 0.7 } , from : { enabled : true , scaleFactor : 0.7 } } ,
2026-05-14 12:59:25 +03:00
font : { color : CONFLICT _TYPES [ type ] . color , size : 14 , align : 'middle' , strokeWidth : 3 , strokeColor : '#1e1e2e' } ,
2026-05-13 17:05:59 +03:00
smooth : { type : 'curvedCW' , roundness : 0.35 }
} ) ;
const EDGES = [
// ── ПРАВИЛА — иерархия ──────────────────────────
E ( 'pravila' , 'claude_md' , 'подчиняет\n(уровень 1→2a)' ) ,
E ( 'pravila' , 'psr_v1' , 'подчиняет\n(уровень 1→3)' ) ,
E ( 'claude_md' , 'tooling' , 'ссылается\nна реестр' ) ,
E ( 'pravila' , 'superpowers' , '§12: обязывает\nинвокировать 1-м' ) ,
// ── PSR_v1 координирует плагины ─────────────────
E ( 'psr_v1' , 'superpowers' , 'R5: координирует\nпарный стек' ) ,
E ( 'psr_v1' , 'fd_plugin' , 'R5: координирует\nпарный стек' ) ,
E ( 'psr_v1' , 'upm' , 'R14.3: активирует\nтолько через pipeline' ) ,
E ( 'psr_v1' , 'mcp_21st' , 'R14.4: активирует\nтолько через pipeline' ) ,
E ( 'psr_v1' , 'claude_md_mgmt' , 'R10.1 блок 1:\nинфраструктурный' ) ,
// ── CLAUDE.md ────────────────────────────────────
E ( 'claude_md' , 'mcp_boost' , 'описывает §3.2' ) ,
E ( 'claude_md' , 'mcp_sentry' , 'описывает §4.8' ) ,
E ( 'claude_md' , 'mcp_redis' , 'описывает §4.9' ) ,
E ( 'claude_md' , 'claude_md_mgmt' , '§5п.10:\nединственный канал' ) ,
E ( 'claude_md' , 'ag_pest' , 'описывает\nкогда вызывать' ) ,
E ( 'claude_md' , 'ag_rls' , 'описывает\nкогда вызывать' ) ,
// ── ХУКИ ────────────────────────────────────────
E ( 'hk_pre_claude' , 'claude_md' , 'проверяет\nпри Edit/Write' ) ,
E ( 'hk_post_md' , 'lh_mdlint' , 'дублирует задачу\n(локально)' ) ,
E ( 'hk_post_schema' , 'claude_md' , 'напоминает про\nCHANGELOG_schema' ) ,
E ( 'hk_session' , 'mem_user' , 'читает\nпри старте' ) ,
E ( 'hk_session' , 'mem_env' , 'читает\nпри старте' ) ,
E ( 'hk_session' , 'mem_sp' , 'читает\nпри старте' ) ,
E ( 'hk_session' , 'mem_plugins' , 'читает\nпри старте' ) ,
E ( 'hk_session' , 'mem_state' , 'читает\nпри старте' ) ,
E ( 'hk_economy' , 'superpowers' , 'парсит уровень\nэкономии' ) ,
// ── SUPERPOWERS содержит скилы ──────────────────
E ( 'superpowers' , 'sk_brainstorm' , 'содержит' ) ,
E ( 'superpowers' , 'sk_tdd' , 'содержит' ) ,
E ( 'superpowers' , 'sk_debug' , 'содержит' ) ,
E ( 'superpowers' , 'sk_wplans' , 'содержит' ) ,
E ( 'superpowers' , 'sk_eplans' , 'содержит' ) ,
E ( 'superpowers' , 'sk_verify' , 'содержит' ) ,
E ( 'superpowers' , 'sk_parallel' , 'содержит' ) ,
E ( 'superpowers' , 'sk_worktree' , 'содержит' ) ,
E ( 'superpowers' , 'sk_pr' , 'содержит' ) ,
E ( 'superpowers' , 'sk_subagent' , 'содержит' ) ,
E ( 'superpowers' , 'sk_wskills' , 'содержит' ) ,
E ( 'superpowers' , 'sk_spreview' , 'содержит' ) ,
E ( 'superpowers' , 'sk_coderev' , 'содержит' ) ,
E ( 'superpowers' , 'sk_elements' , 'содержит' ) ,
// ── СКИЛЫ вызывают друг друга ───────────────────
E ( 'sk_brainstorm' , 'sk_wplans' , 'вызывает\nпосле дизайна' ) ,
E ( 'sk_wplans' , 'sk_eplans' , 'вызывает\nдля выполнения' ) ,
E ( 'sk_wplans' , 'sk_subagent' , 'альтернатива\nexecuting-plans' ) ,
E ( 'sk_subagent' , 'ag_explore' , 'запускает\nдля поиска' ) ,
E ( 'sk_subagent' , 'ag_general' , 'запускает\nдля задач' ) ,
E ( 'sk_subagent' , 'ag_plan' , 'запускает\nдля архитектуры' ) ,
E ( 'sk_parallel' , 'sk_worktree' , 'использует\nдля изоляции' ) ,
// ── СКИЛЫ ПРОЕКТА ───────────────────────────────
E ( 'sk_rls' , 'tooling' , 'использует\nsquawk + grep §3.2' ) ,
E ( 'sk_rls' , 'mcp_boost' , 'SQL запросы\nк схеме' ) ,
E ( 'sk_qitem' , 'claude_md_mgmt' , 'делегирует\nправку CLAUDE.md' ) ,
// ── CLAUDE-MD-MGMT ──────────────────────────────
E ( 'claude_md_mgmt' , 'claude_md' , 'единственный\nканал правок' ) ,
// ── HOOKIFY ─────────────────────────────────────
E ( 'ag_hookify' , 'hookify_plugin' , 'передаёт\nанализ' ) ,
E ( 'hookify_plugin' , 'hk_pre_claude' , 'может создавать\nновые хуки' ) ,
E ( 'hookify_plugin' , 'hk_economy' , 'может создавать\nновые хуки' ) ,
// ── АГЕНТЫ используют MCP ───────────────────────
E ( 'ag_pest' , 'mcp_redis' , 'читает\nочереди/кэш' ) ,
E ( 'ag_rls' , 'mcp_boost' , 'SQL запросы\nк БД' ) ,
E ( 'ag_guide' , 'mcp_gh' , 'ищет\nв репозитории' ) ,
// ── LEFTHOOK вызывается git ──────────────────────
E ( 'lh_gitleaks' , 'mem_plugins' , 'блокирует коммит\nпри ПДн в staged' ) ,
E ( 'lh_larastan' , 'mcp_boost' , 'Boost даёт\nконтекст типов' ) ,
E ( 'lh_squawk' , 'tooling' , 'соответствует\n§3.2 #15' ) ,
E ( 'lh_gitleaks2' , 'lh_gitleaks' , 'строже:\nвся история' ) ,
E ( 'lh_lychee' , 'claude_md' , 'проверяет\nссылки в .md' ) ,
// ── MEMORY читается Claude ──────────────────────
2026-05-16 15:39:47 +03:00
E ( 'mem_env' , 'ag_pest' , 'квирки 73/77\nиспользует агент' ) ,
2026-05-13 17:05:59 +03:00
E ( 'mem_plugins' , 'psr_v1' , 'отражает\nтекущие версии' ) ,
E ( 'mem_archive' , 'claude_md' , 'синхронизирует\nверсии доков' ) ,
// ── MCP ─────────────────────────────────────────
E ( 'mcp_pw' , 'hk_session' , 'используется\nдля a11y smoke' ) ,
E ( 'mcp_gh' , 'sk_pr' , 'PR, issues\nпри finishing-pr' ) ,
E ( 'mcp_boost' , 'ag_rls' , 'схема БД\nдля RLS-review' ) ,
2026-05-16 15:39:47 +03:00
// ── АУДИТ-АКТУАЛИЗАЦИЯ 16.05.2026 — связи новых узлов ──
E ( 'psr_v1' , 'skill_creator' , 'R10.1:\nвнешний инструмент' ) ,
E ( 'psr_v1' , 'claude_setup' , 'R10.1:\nвнешний инструмент' ) ,
E ( 'psr_v1' , 'plugin_dev' , 'R10.1:\nвнешний инструмент' ) ,
E ( 'psr_v1' , 'context7' , 'R10.1:\nвнешний инструмент' ) ,
E ( 'plugin_dev' , 'ag_pcreator' , 'содержит\nагента' ) ,
E ( 'plugin_dev' , 'ag_pvalid' , 'содержит\nагента' ) ,
E ( 'plugin_dev' , 'ag_skreview' , 'содержит\nагента' ) ,
E ( 'skill_creator' , 'sk_wskills' , 'обе создают\nскилы' ) ,
E ( 'hk_self_check' , 'hk_economy' , 'система\nэкономии' ) ,
E ( 'hk_skill_marker' , 'hk_skill_check' , 'пара\nmarker/check' ) ,
E ( 'hk_skill_check' , 'superpowers' , 'энфорсит §12:\nскил перед кодом' ) ,
E ( 'hk_state_guard' , 'hk_economy' , 'система\nэкономии' ) ,
E ( 'hk_postcompact' , 'hk_economy' , 'переинжект\nрежима после компакта' ) ,
E ( 'hk_verifier' , 'sk_verify' , 'энфорсит\nпроверку готовности' ) ,
E ( 'hk_ruflo_queen' , 'ruflo_queen' , '§14: маршрут\nqueen-задач' ) ,
E ( 'sk_regression' , 'ag_pest' , 'передаёт разбор\nпадений Pest --parallel' ) ,
2026-05-17 04:46:32 +03:00
// ── A6 ARCHITECTURE-TOOLING 17.05.2026 — связи новых узлов ──
E ( 'psr_v1' , 'adr_kit' , 'R10.1 блок 1:\narchitecture-tooling' ) ,
E ( 'psr_v1' , 'arch_patterns' , 'R10.1 блок 1:\narchitecture-tooling' ) ,
E ( 'tooling' , 'mermaid_skill' , '§4.12: реестр\n(вендоренный скил)' ) ,
2026-05-13 17:05:59 +03:00
// ══════════════════════════════════════════════════
2026-05-14 12:59:25 +03:00
// КОНФЛИКТЫ — 3-color classification (iter2 §4)
// 🔴 не закрыт правилом / ⚫ возник на практике / 🟢 закрыт правилом
2026-05-13 17:05:59 +03:00
// ══════════════════════════════════════════════════
2026-05-16 08:48:30 +03:00
CONFLICT ( 'sk_rls' , 'ag_rls' , 'RLS: граница задана — скил по таблице, агент по diff/PR (spec 2026-05-16)' , 'GREEN' ) ,
2026-05-14 12:59:25 +03:00
CONFLICT ( 'hookify_plugin' , 'hk_pre_claude' , 'hookify может перезаписать существующий хук' , 'RED' ) ,
CONFLICT ( 'mcp_pw' , 'sk_parallel' , 'Browser is already in use (квирк #2)' , 'BLACK' ) ,
2026-05-16 15:39:47 +03:00
CONFLICT ( 'ag_pest' , 'mcp_redis' , 'Квирк 72 устранён 16.05.2026 (commit 0fa1a73 — array-стор в тестах): гонки в Redis при Pest --parallel больше нет' , 'GREEN' ) ,
2026-05-14 12:59:25 +03:00
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' ) ,
2026-05-16 13:44:14 +03:00
CONFLICT ( 'hk_economy' , 'superpowers' , '§12 — hard-rule уровня 0; economy-режим §12 не отменяет (Pravila §12.4)' , 'GREEN' ) ,
2026-05-15 15:34:39 +03:00
// ══════════════════════════════════════════════════
2026-05-16 06:48:46 +03:00
// RUFLO ОРКЕСТРАТОР — фактический реколлаж (iter5, 2026-05-15)
2026-05-15 15:34:39 +03:00
// ══════════════════════════════════════════════════
2026-05-16 06:48:46 +03:00
// Queen → артефакты установки ruflo init (рой idle, артефакты не задействованы)
E ( 'ruflo_queen' , 'ruflo_workers' , 'координирует\n(0 задач)' ) ,
E ( 'ruflo_queen' , 'ruflo_agents_catalog' , 'ruflo init высыпал\n(не задействовано)' ) ,
E ( 'ruflo_queen' , 'ruflo_commands' , 'ruflo init высыпал\n(не задействовано)' ) ,
E ( 'ruflo_queen' , 'ruflo_plugins' , 'плагинов ruflo:\n0 установлено' ) ,
// MCP-сервер ruflo — связывает половины кластера + читает/пишет память
E ( 'ruflo_mcp' , 'ruflo_queen' , 'инструменты\nуправления роем' ) ,
E ( 'ruflo_mcp' , 'ruflo_memory' , 'читает/пишет\nпамять' ) ,
// память ruflo — recall-хук и воркер consolidate демона
E ( 'ruflo_recall_hook' , 'ruflo_memory' , 'запускает\nruflo memory search' ) ,
E ( 'ruflo_daemon' , 'ruflo_memory' , 'воркер consolidate\nобращается к памяти' ) ,
2026-05-16 13:44:14 +03:00
// 4 узла-правила → Queen (реколлаж 16.05.2026: ruflo — advisory-подсистема; Pravila §14 — queen-триггер)
E ( 'pravila' , 'ruflo_queen' , '§14:\nqueen-триггер' ) ,
E ( 'claude_md' , 'ruflo_queen' , '§3.5: описывает\n(advisory-подсистема)' ) ,
E ( 'psr_v1' , 'ruflo_queen' , '§14:\ncross-ref' ) ,
E ( 'tooling' , 'ruflo_queen' , '§4.10: реестр\n(advisory-подсистема)' ) ,
2026-05-15 15:34:39 +03:00
// memory → ruflo
2026-05-16 06:48:46 +03:00
E ( 'mem_ruflo' , 'ruflo_queen' , 'документирует\nинтеграцию' ) ,
2026-05-15 15:34:39 +03:00
2026-05-16 06:48:46 +03:00
// 3 конфликта ruflo (3-color, iter2 §4)
2026-05-16 13:44:14 +03:00
CONFLICT ( 'ruflo_queen' , 'pravila' , 'Закрыто реколлажем 16.05.2026: нормативка приведена к рантайму — ruflo переописан в advisory/automation-подсистему, декларация уровня −1 убрана' , 'GREEN' ) ,
2026-05-16 06:48:46 +03:00
CONFLICT ( 'ruflo_memory' , 'mem_state' , 'Два хранилища памяти не синхронизированы; память ruflo почти пуста (0 записей)' , 'BLACK' ) ,
2026-05-16 15:39:47 +03:00
CONFLICT ( 'ruflo_daemon' , 'ag_pest' , 'Worker-jitter демона ruflo усиливает Pest-квирки 73/77 (квирк 72 устранён 16.05 — его jitter больше не усиливает)' , 'BLACK' ) ,
2026-05-13 17:05:59 +03:00
] ;
// ════════════════════════════════════════════════════
// SECTION 3: NODE DETAILS
// ════════════════════════════════════════════════════
const CATEGORY _LABELS = {
rules : 'Правило' , plugins : 'Плагин' , skills _sp : 'Скил Superpowers' ,
skills _proj : 'Скил проекта' , hooks : 'Хук .claude' , agents : 'Агент' ,
2026-05-15 15:34:39 +03:00
mcp : 'MCP-сервер' , lefthook : 'Lefthook job' , memory : 'Memory-файл' ,
ruflo : 'ruflo (оркестратор)'
2026-05-13 17:05:59 +03:00
} ;
2026-05-14 09:10:57 +03:00
function nd ( desc , when , limits , reportsTo , manages , together , conflicts ) {
// Backward-compat: old 5-arg signature was nd(desc, reportsTo, manages, together, conflicts).
// If 2nd arg is an array, treat as old-style call and shift args.
if ( Array . isArray ( when ) ) {
return {
desc ,
when : '' ,
limits : '' ,
reportsTo : when ,
manages : limits ,
together : reportsTo ,
conflicts : ( manages || [ ] ) ,
} ;
}
return { desc , when : when || '' , limits : limits || '' , reportsTo , manages , together , conflicts : conflicts || [ ] } ;
2026-05-13 17:05:59 +03:00
}
const NODE _DETAILS = {
// ── ПРАВИЛА ──────────────────────────────────────
pravila : nd (
2026-05-14 12:29:21 +03:00
'Главный свод правил работы Клода — кто чем командует, что запрещено, какие обязательные действия.' ,
'Действует всегда — Клод читает его при старте каждой сессии.' ,
2026-05-16 13:44:14 +03:00
'§12 Superpowers — hard-rule уровня 0 цепочки приоритетов: скил инвокируется первым, §9 «Отступления» не применяется, economy-режим §12 не отменяет. Расходимость с другими документами — нарушение §7.' ,
[ ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 12:29:21 +03:00
{ name : 'CLAUDE.md' , cond : 'подчинён, уровень 2a в цепочке приоритетов' } ,
{ name : 'PSR_v1' , cond : 'подчинён, уровень 3 в цепочке приоритетов' } ,
2026-05-14 17:15:39 +03:00
{ name : 'плагин Superpowers' , cond : '§12 обязывает запускать скил первым' } ,
2026-05-13 17:05:59 +03:00
{ name : 'Все компоненты' , cond : 'через цепочку приоритетов §1' }
] ,
2026-05-15 15:56:36 +03:00
[ { name : 'CLAUDE.md' , cond : 'оба читаются при старте сессии' } ] ,
2026-05-16 13:44:14 +03:00
[ { name : 'ruflo Queen' , desc : 'iter4– iter5: нормативка декларировала ruflo Queen-led routing уровнем − 1 (overlord) — расходилось с рантаймом (рой idle, 0 задач). Реколлаж 16.05.2026 (Pravila v1.16 / CLAUDE.md v2.2 / PSR_v1 v3.2 / Tooling v2.2) привёл нормативку к факту: ruflo переописан в advisory/automation-подсистему, уровень −1 убран. Конфликт «декларация ≠ рантайм» закрыт.' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
claude _md : nd (
2026-05-16 13:44:14 +03:00
'Оперативная карта проекта — технологии, команды, фазы, 7-уровневая цепочка приоритетов (§1, уровни 0–6) и §3.5 — ruflo как advisory/automation-подсистема, ссылки на документы.' ,
2026-05-14 12:29:21 +03:00
'Читается при старте каждой сессии; обновляется при новом инструменте или новой фазе.' ,
'Править можно только через скил `/claude-md-management:claude-md-improver` или `:revise-claude-md` (правило §5 п.10). Прямые Edit/Write блокируются хуком предупреждения.' ,
[ { name : 'Pravila' , cond : 'всегда подчинён (уровень 2a)' } ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-16 13:44:14 +03:00
{ name : 'Tooling v2.2' , cond : 'ссылается как на реестр инструментов' } ,
2026-05-14 17:15:39 +03:00
{ name : 'плагин claude-md-management' , cond : 'правило §5 п.10 — единственный канал правок' }
2026-05-13 17:05:59 +03:00
] ,
[
2026-05-14 12:29:21 +03:00
{ name : 'Pravila' , cond : 'оба читаются при старте сессии' } ,
{ name : 'Tooling' , cond : 'оба — оперативные карты уровня 2' }
2026-05-13 17:05:59 +03:00
] ,
2026-05-14 12:59:25 +03:00
[ { name : 'PSR_v1' , desc : 'Правило §5 п.10 запрещает прямые правки, но PSR_v1 это явно не повторяет — есть риск Edit без скила' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
psr _v1 : nd (
2026-05-16 13:44:14 +03:00
'Правила совместной работы плагинов — кто с кем работает, какая процедура обязательна. R0 — головной фильтр выбора плагинов (с реколлажа 16.05.2026 снова на вершине стека, не sub-policy под ruflo).' ,
2026-05-14 17:15:39 +03:00
'При выборе UI-инструмента (плагин Frontend Design против плагина UI UX Pro Max против MCP-сервера 21st Magic), при координации парных плагинов, при включении дополнительного MCP (внешнего сервиса-инструмента Claude) вне основных фаз.' ,
'Обязательное правило R14.5: плагины UI UX Pro Max, 21st Magic, Frontend Design — нельзя использовать одновременно. Обязательное правило R6.0 (фильтр стека) и R6.1 (палитра Forest) — нужно соблюдать при UI-выводе плагинов.' ,
2026-05-14 12:29:21 +03:00
[ { name : 'Pravila' , cond : 'подчинён, уровень 3 в цепочке' } ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 17:15:39 +03:00
{ name : 'плагин Superpowers + плагин Frontend Design' , cond : 'координирует как пару плагинов' } ,
{ name : 'плагин UI UX Pro Max' , cond : 'R14.3: включается только через процедуру' } ,
{ name : 'MCP-сервер 21st Magic' , cond : 'R14.4: включается только через процедуру' }
2026-05-13 17:05:59 +03:00
] ,
2026-05-14 12:29:21 +03:00
[ { name : 'CLAUDE.md' , cond : 'обе — оперативные карты, правятся согласованно' } ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'CLAUDE.md' , desc : 'CLAUDE.md §5 п.10 требует править только через скил claude-md-management, а PSR_v1 это ограничение не повторяет — риск прямых Edit' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
tooling : nd (
2026-05-16 13:44:14 +03:00
'Реестр 55 позиций — 35 формализованных инструментов + 20 ruflo-плагинов; §4.10 — ruflo как advisory/automation-подсистема. Когда что использовать, команды установки, конфликты.' ,
2026-05-14 17:15:39 +03:00
'При выборе инструмента для фазы (нулевая документация / первая backend / вторая frontend / третья перед запуском в боевую среду), при добавлении нового инструмента, при обновлении версий.' ,
2026-05-14 12:29:21 +03:00
'При прямом конфликте с CLAUDE.md побеждает CLAUDE.md (оперативная карта уровня 2a). Любая правка требует синхронизации с CLAUDE.md §3.' ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 12:29:21 +03:00
{ name : 'Pravila' , cond : 'уровень 2b — оперативная карта рядом с CLAUDE.md' } ,
{ name : 'CLAUDE.md' , cond : 'при прямом конфликте побеждает CLAUDE.md' }
2026-05-13 17:05:59 +03:00
] ,
[ ] ,
2026-05-14 12:29:21 +03:00
[ { name : 'CLAUDE.md' , cond : 'обе — оперативные карты, правятся синхронно' } ]
2026-05-13 17:05:59 +03:00
) ,
// ── ПЛАГИНЫ ──────────────────────────────────────
superpowers : nd (
2026-05-14 12:29:21 +03:00
'Плагин поведения Клода — 14 скилов для тестов, отладки, планирования, параллельной работы.' ,
2026-05-14 17:15:39 +03:00
'При творческих, отладочных, тестовых и многошаговых задачах: скил brainstorming (продумать варианты) / скил TDD (разработка через тесты — failing test first) / скил systematic-debugging / скил verification-before-completion (обязательная проверка готовности) / скил writing-plans / скил parallel-work / скил worktree / скил finishing-PR (запрос на слияние кода) / скил subagent-driven-development / скил writing-skills (карта типов в §12.2 Pravila).' ,
2026-05-16 13:44:14 +03:00
'§12 Superpowers — hard-rule уровня 0 цепочки приоритетов: скил инвокируется первым. Единственная отмена — явная просьба заказчика «не используй superpowers сейчас» на текущее действие; §9 «Отступления» к §12 не применяется; economy-режим §12 не отменяет.' ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 12:29:21 +03:00
{ name : 'Pravila §12' , cond : 'обязательное правило: скил запускается первым' } ,
2026-05-14 17:15:39 +03:00
{ name : 'PSR_v1' , cond : 'координирует как пару с плагином Frontend Design' }
2026-05-13 17:05:59 +03:00
] ,
2026-05-14 17:15:39 +03:00
[ { name : 'Все 14 скилов Superpowers' , cond : 'содержит' } ] ,
[ { name : 'плагин Frontend Design' , cond : 'пара — работают вместе при UI-задачах' } ] ,
2026-05-16 13:44:14 +03:00
[ { name : 'хук economy-mode' , desc : 'Режим экономии 100% теоретически может «сэкономить» запуск скила — §12 (hard-rule уровня 0) economy-режим не отменяет.' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
fd _plugin : nd (
2026-05-14 17:15:39 +03:00
'Плагин знаний о UI — Vue, Vuetify, доступность (accessibility), паттерны компонентов для Лидерры.' ,
'При UI/UX задачах — компоненты, экраны, паттерны взаимодействия; в паре с плагином Superpowers (даёт процесс).' ,
2026-05-14 12:29:21 +03:00
'Фильтр стека R6.0: срезать React/Tailwind/shadcn/JSX в Vue 3 + Vuetify 3. Обязательное правило палитры Forest R6.1 для цветов, шрифтов и иконок.' ,
[ { name : 'PSR_v1' , cond : 'R5: подчинён как часть пары плагинов' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'пара — Frontend Design даёт UI-знания, Superpowers даёт процесс' } ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 17:15:39 +03:00
{ name : 'плагин UI UX Pro Max' , desc : 'Правило PSR_v1 R14.5: нельзя одновременно — оба включены в настройках, но должны чередоваться' , type : 'GREEN' } ,
{ name : 'MCP-сервер 21st Magic' , desc : 'Правило PSR_v1 R14.5: нельзя одновременно с Frontend Design — оба потенциально доступны' , type : 'GREEN' }
2026-05-13 17:05:59 +03:00
]
) ,
upm : nd (
2026-05-14 12:29:21 +03:00
'Резервная библиотека UI — 50+ стилей, 161 палитра, 99 правил-подсказок UX. Только по процедуре.' ,
2026-05-14 17:15:39 +03:00
'Только по процедуре PSR_v1 R14.3: запасной вариант к плагину Frontend Design ИЛИ «третий вариант» в архитектурном решении.' ,
'R14.5: нельзя одновременно с плагином Frontend Design / MCP-сервером 21st Magic. Фильтр стека R6.0 и обязательное правило палитры Forest R6.1 — обязательны. Проверка доступности Pa11y (автопроверка accessibility — доступности) перед выкаткой.' ,
2026-05-14 12:29:21 +03:00
[ { name : 'PSR_v1' , cond : 'R14.3: включается только через процедуру, не сам по себе' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Frontend Design' , desc : 'Правило PSR_v1 R14.5: нельзя одновременно — UI UX Pro Max как материал, Frontend Design как решатель; риск смешать роли' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
claude _md _mgmt : nd (
2026-05-14 12:29:21 +03:00
'Единственный разрешённый способ править CLAUDE.md — через скил claude-md-improver или revise-claude-md.' ,
'При любой правке CLAUDE.md (новая фаза, новый инструмент, смена версии, новые особенности — всё через скил).' ,
'Правило PSR_v1 R10.1 блок 1 (инфраструктурная категория). Внутри процедуры продолжают действовать §4 правил Клода (синхронизация Pravila + Tooling).' ,
2026-05-13 17:05:59 +03:00
[ { name : 'PSR_v1' , cond : 'R10.1 Блок 1: инфраструктурная категория' } ] ,
2026-05-14 12:29:21 +03:00
[ { name : 'CLAUDE.md' , cond : 'правило §5 п.10: единственный канал правок' } ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил q-item-add' , cond : 'скил делегирует правки CLAUDE.md через этот плагин' } ]
2026-05-13 17:05:59 +03:00
) ,
hookify _plugin : nd (
2026-05-14 12:29:21 +03:00
'Плагин создания хуков — анализирует разговоры и предлагает новые автоматизации в виде хуков.' ,
'При запросе «давай повесим хук на это поведение» или после серии повторяющихся ошибок — анализ через агента conversation-analyzer.' ,
'Правило PSR_v1 R10.1. Новые хуки могут конфликтовать с существующими (см. конфликты ниже) — обязательная проверка файла настроек до создания.' ,
2026-05-13 17:05:59 +03:00
[ { name : 'PSR_v1' , cond : 'R10.1: формализован' } ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'агент hookify:conversation-analyzer' , cond : 'запускает анализ разговоров' } ] ,
[ { name : 'агент hookify:conversation-analyzer' , cond : 'плагин и агент работают в паре' } ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 17:15:39 +03:00
{ name : 'хук pre-claude-warn' , desc : 'плагин hookify создаёт новые хуки PreToolUse на лету — может перезаписать или конкурировать с этим хуком' , type : 'RED' }
2026-05-13 17:05:59 +03:00
]
) ,
2026-05-17 04:46:32 +03:00
// ── A6 ARCHITECTURE-TOOLING (17.05.2026) ─────────
adr _kit : nd (
'Плагин ADR (Architecture Decision Records) — фиксация закрытых архитектурных решений в docs/adr/ (формат Nygard, 7 секций) + декларативный энфорсер adr-judge.' ,
'При фиксации архитектурного решения — стек, паттерн, граница слоёв; ADR-NNN в docs/adr/. Открытые вопросы — не сюда, они в реестре Открытые_вопросы.' ,
'Правило PSR_v1 R10.1 блок 1 (architecture-tooling, off-phase). adr-judge врезан в lefthook pre-commit job 9 — декларативный regex без --llm, 0 вызовов Claude API. init/install-hooks НЕ запускаются (конфликт-аудит AK1/AK2). Не UI → вне фильтров R6.0/R6.1/R14. Tooling §4.11, CLAUDE.md §3.3 #36.' ,
[ { name : 'PSR_v1' , cond : 'R10.1 блок 1: architecture-tooling' } , { name : 'Tooling' , cond : '§4.11 #36 — реестр' } ] ,
[ { name : 'lefthook job 9 (adr-judge)' , cond : 'врезан как pre-commit проверка Enforcement-блоков' } ] ,
[ { name : 'docs/adr/' , cond : 'хранилище ADR — ADR-000/001/002' } ]
) ,
arch _patterns : nd (
'Скил-плагин — справочник архитектурных паттернов (Clean / Hexagonal / layered architecture, Domain-Driven Design). Knowledge-only, не решатель.' ,
'При архитектурном вопросе «какой паттерн подходит» — playbook паттернов; код не генерирует, файлы не правит.' ,
'Правило PSR_v1 R10.1 блок 1 (architecture-tooling, off-phase). Knowledge-only — без хуков и машинерии. Не UI → вне фильтров R6.0/R6.1/R14. Tooling §4.13, CLAUDE.md §3.3 #38.' ,
[ { name : 'PSR_v1' , cond : 'R10.1 блок 1: architecture-tooling' } , { name : 'Tooling' , cond : '§4.13 #38 — реестр' } ] ,
[ ] ,
[ ]
) ,
mermaid _skill : nd (
'Вендоренный standalone-скил (.claude/skills/mermaid/) — генерирует исходник Mermaid-диаграмм (23 типа, включая C4/architecture). Рендера mmdc/Chromium не требует.' ,
'При построении C4/архитектурной диаграммы — результат в docs/architecture/ (Mermaid рендерится на GitHub нативно).' ,
'Вендорен — не плагин, не marketplace, не подсистема (конфликт-аудит CC1: иммунен к потере апстрима). lefthook markdownlint+cspell исключают .claude/skills/mermaid/** (MK1). Tooling §4.12, CLAUDE.md §3.3 #37.' ,
[ { name : 'Tooling' , cond : '§4.12 #37 — реестр' } ] ,
[ ] ,
[ { name : 'docs/architecture/' , cond : 'C4-диаграммы → c4-context.md' } ]
) ,
2026-05-13 17:05:59 +03:00
// ── СКИЛЫ SUPERPOWERS ────────────────────────────
sk _brainstorm : nd (
'Продумывает задачу вместе с заказчиком, формулирует варианты A/B/C и согласует дизайн до написания кода.' ,
2026-05-14 12:42:32 +03:00
'При творческой задаче — новая фича, непростой рефакторинг, дизайн-решение; ДО любого кода или плана.' ,
2026-05-14 17:15:39 +03:00
'Обязательно явное «Approved» от заказчика до перехода к скилу writing-plans. Запрет: нельзя запускать скилы реализации до утверждения дизайна.' ,
[ { name : 'плагин Superpowers' , cond : 'содержит' } , { name : 'Pravila §12' , cond : 'обязательное правило (см. §12) для творческих задач' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил writing-plans' , cond : 'вызывается сразу после brainstorming для создания плана' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _tdd : nd (
2026-05-14 17:15:39 +03:00
'Ведёт разработку через написание падающего теста до кода: сначала RED (тест провален), потом GREEN (тест проходит). TDD (разработка через тесты — failing test first).' ,
2026-05-14 12:42:32 +03:00
'При любом новом боевом коде — backend (Pest) и frontend (Vitest).' ,
'Падающий тест пишется ДО реализации; формулировка «код должен работать» без проверенного теста — нарушение правила §12.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } , { name : 'Pravila §12' , cond : 'обязательное правило (см. §12) для любого нового кода' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил executing-plans' , cond : 'TDD встроен в каждый шаг плана выполнения' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _debug : nd (
2026-05-14 12:42:32 +03:00
'Системная отладка: минимум 3 гипотезы, опровержение каждой реальной проверкой до того, как править код — никаких «должно работать».' ,
'При неожиданном поведении, падении теста, ошибке во время работы, неожиданном выводе.' ,
'Минимум 3 гипотезы. Опровержение через реальные команды и тесты, а не «логика подсказывает». Никаких «попробую исправить» без подтверждённой причины.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } , { name : 'Pravila §12' , cond : 'обязательное правило (см. §12) при неожиданном поведении' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер redis' , cond : 'используется для отладки очередей Redis' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _wplans : nd (
'Создаёт детальный план реализации с полным кодом, командами и шагами по 2-5 минут.' ,
2026-05-14 17:15:39 +03:00
'После скила brainstorming (творческая задача) или сразу для многошаговой (≥3 шагов) технической задачи.' ,
2026-05-14 12:42:32 +03:00
'Никаких заглушек (TBD, TODO, «add validation»). Каждый шаг — реальный код или команда. Покрытие спецификации обязательно.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } , { name : 'Pravila §12' , cond : 'обязательное правило (см. §12) для многошаговых задач (≥3 шагов)' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил executing-plans или скил subagent-driven' , cond : 'план передаётся в один из них для выполнения' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _eplans : nd (
'Выполняет готовый план шаг за шагом, отмечает чекбоксы, делает коммиты после каждого шага.' ,
2026-05-14 17:15:39 +03:00
'После скила writing-plans (если выбрано выполнение в текущей сессии); альтернатива — скил subagent-driven-development в той же сессии.' ,
2026-05-14 12:42:32 +03:00
'Каждый шаг отмечается галочкой, коммиты не объединяются — атомарно по одному за шаг (Pravila §4.2).' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил writing-plans' , cond : 'получает план от writing-plans' } , { name : 'скил subagent-driven-development' , cond : 'альтернатива — зависит от выбора пользователя' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _verify : nd (
2026-05-14 12:42:32 +03:00
'Обязательная проверка перед заявлением «готово»: запускает тесты, видит реальный вывод, никаких предположений.' ,
'Перед любым заявлением «готово»/«passed»/«closed»/«merged» — обязательно (правило §12 + экономия 0% как жёсткое требование).' ,
'Реальный запуск, не «должно пройти». Вывод тестов виден полностью. Выборочные результаты запрещены («tests pass» = ровно столько, сколько действительно прошло).' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } , { name : 'Pravila §12' , cond : 'обязательное правило (см. §12) перед любым заявлением «готово»' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер laravel-boost' , cond : 'запросы к БД для проверки данных' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _parallel : nd (
2026-05-14 12:42:32 +03:00
'Разбивает независимые задачи на параллельные потоки с изоляцией через git worktrees (отдельные рабочие копии репозитория).' ,
'При нескольких независимых рабочих фронтах одновременно (CTO-задача + Plan-задача + audit-fix).' ,
'Изоляция через worktree обязательна — никакого «работаю в одной директории на 3 ветках сразу». Иначе риск конфликта файлов и веток.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил worktree' , cond : 'parallel-work использует worktree для изоляции' } ] ,
[ { name : 'MCP-сервер playwright' , desc : 'Браузер уже занят (Browser is already in use) при одновременном запуске нескольких сессий через worktree' , type : 'BLACK' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _worktree : nd (
2026-05-14 12:42:32 +03:00
'Создаёт изолированную копию репозитория (worktree) для рискованной или параллельной работы.' ,
'При параллельной работе нескольких задач или при рискованной работе (рефакторинг с возможным откатом, ветка экспериментов).' ,
'Очистка через ExitWorktree обязательна. Не оставлять забытые worktree — захламляют файловую систему.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил parallel-work' , cond : 'worktree — инструмент для parallel-work' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _pr : nd (
2026-05-14 17:15:39 +03:00
'Чеклист финальной готовности PR (запроса на слияние кода): тесты, документация, чистота кода, проверки перед push.' ,
2026-05-14 12:42:32 +03:00
'Перед `gh pr create` или `git push` в общую ветку — обязательная проверка готовности.' ,
2026-05-14 17:15:39 +03:00
'Проверки перед push (job gitleaks в lefthook по всей истории + job lychee) — не обходить через `--no-verify`. Pravila §4.2.' ,
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер github' , cond : 'создаёт PR (запрос на слияние кода) через GitHub' } , { name : 'lefthook (job-набор перед push)' , cond : 'запускает job gitleaks + job lychee' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _subagent : nd (
'Запускает суб-агентов для крупных задач — каждый в отдельном контексте без накопленного шума.' ,
2026-05-14 12:42:32 +03:00
'При выполнении плана в той же сессии ИЛИ при делегировании поиска/анализа большого объёма.' ,
'Суб-агент в режиме экономии 0%: запрашивать полный сырой вывод, а не сводку — решения принимать самому.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 17:15:39 +03:00
{ name : 'агент Explore' , cond : 'запускает для поиска по кодовой базе' } ,
{ name : 'агент general-purpose' , cond : 'запускает для сложных задач' } ,
{ name : 'агент Plan' , cond : 'запускает для архитектурного планирования' }
2026-05-13 17:05:59 +03:00
] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил writing-plans' , cond : 'subagent-driven — основной способ выполнения планов' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _wskills : nd (
2026-05-14 12:42:32 +03:00
'Создаёт новые скилы по стандартному шаблону: файл SKILL.md, заголовочный блок (frontmatter), описание процесса.' ,
'При формализации повторяющегося процесса в переиспользуемый скил (после 2-3 примеров одинаковой работы).' ,
'Шаблон SKILL.md, заголовочный блок (name, description, when_to_use, allowed-tools), описание процесса с DOT-диаграммой.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'агент plugin-dev:skill-reviewer' , cond : 'агент проверяет созданный скил' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _spreview : nd (
2026-05-14 12:42:32 +03:00
'Проверяет документ-спецификацию на полноту, противоречия, заглушки и объём работ.' ,
2026-05-14 17:15:39 +03:00
'После скила writing-plans на отдельном этапе ДО реализации — для крупных планов с несколькими задачами.' ,
'Самопроверка прямо в скиле brainstorming достаточна для небольшой спецификации; для крупных — отдельный запуск этого скила.' ,
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил brainstorming' , cond : 'spec-review вызывается в конце brainstorming после записи спека' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _coderev : nd (
2026-05-14 12:42:32 +03:00
'Систематический разбор кода — безопасность, тесты, архитектура, соответствие правилам.' ,
2026-05-14 17:15:39 +03:00
'Перед слиянием PR (запроса на слияние кода); после крупной серии коммитов; при подготовке к релизу; при подозрении на регрессию (возврат к старому багу).' ,
'Без выборочности: разбор всех изменений, а не только подозрительных. SAST (статический анализ кода на уязвимости, через MCP-сервер semgrep) включается обязательно.' ,
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер semgrep' , cond : 'SAST-проверка при ревью кода' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _elements : nd (
'Улучшает написание текстов и документации — ясность, лаконичность, без воды.' ,
2026-05-14 17:15:39 +03:00
'При написании спецификации/плана/CHANGELOG/описания PR (запроса на слияние кода) — для общения с командой.' ,
2026-05-14 12:42:32 +03:00
'Без воды. Без «легко», «просто», «всего лишь». Каждое утверждение измеримо.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин Superpowers' , cond : 'содержит' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
// ── СКИЛЫ ПРОЕКТА ────────────────────────────────
sk _rls : nd (
2026-05-14 17:15:39 +03:00
'7-шаговый чеклист RLS (защита строк по тенанту) для новой таблицы: tenant_id, ENABLE RLS (включение защиты строк), политики, права для 5 ролей, CHANGELOG, проверка через squawk, дымовой тест (быстрая проверка функциональности).' ,
'При создании новой таблицы в db/schema.sql ИЛИ при правках существующих политик RLS (защиты строк по тенанту).' ,
'Права для 5 ролей обязательны (crm_app_user / crm_app_admin / crm_supplier_worker BYPASSRLS (право обходить защиту строк — для системных задач) / crm_readonly / crm_migrator). Запись в CHANGELOG_schema.md обязательна.' ,
2026-05-13 17:05:59 +03:00
[ { name : 'Tooling §3.2' , cond : 'использует squawk (#15) и команды grep' } ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер laravel-boost' , cond : 'SQL запросы к schema.sql для проверки' } ] ,
2026-05-16 08:48:30 +03:00
[ { name : 'агент rls-reviewer' , desc : 'граница задана регламентом (spec 2026-05-16): скил — ручная проверка одной названной таблицы + живой дымовой тест; агент — разбор diff/ветки/PR. См. секцию «Граница с агентом rls-reviewer» в SKILL.md.' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
sk _qitem : nd (
'Добавляет новый открытый вопрос в реестр Открытые_вопросы_v8_3.md с обновлением счётчиков §0 и версии.' ,
2026-05-14 12:42:32 +03:00
'При появлении нового открытого вопроса (Биз-/CTO-/Ю-/Диз-/DO-/OPEN-) — формальная запись в реестр.' ,
'Категория (Биз-/CTO-/...) обязательна. Связанные документы (CLAUDE.md/Pravila/PSR_v1/Tooling) — синхронизируются.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин claude-md-management' , cond : 'скил делегирует правку CLAUDE.md через плагин (правило §5п.10 в нормативке)' } ]
2026-05-13 17:05:59 +03:00
) ,
// ── ХУКИ ─────────────────────────────────────────
hk _pre _claude : nd (
'Блокирует прямое редактирование CLAUDE.md — срабатывает на Edit/Write по этому файлу.' ,
2026-05-14 17:15:39 +03:00
'PreToolUse (перед каждым вызовом инструмента) — перед каждым Edit/Write, фильтр путей нацелен на CLAUDE.md.' ,
'Обход запрещён. Единственный способ редактировать — плагин claude-md-management (правило §5п.10 в нормативке).' ,
2026-05-14 12:42:32 +03:00
[ { name : '.claude/settings.json' , cond : 'описан как хук PreToolUse' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин hookify' , desc : 'плагин hookify динамически создаёт новые хуки PreToolUse — может перезаписать или конкурировать с этим хуком' , type : 'RED' } ]
2026-05-13 17:05:59 +03:00
) ,
hk _post _md : nd (
2026-05-14 12:42:32 +03:00
'После каждого Edit .md-файла запускает markdownlint --fix автоматически.' ,
2026-05-14 17:15:39 +03:00
'PostToolUse (после каждого вызова инструмента) — после Edit/Write на *.md (кроме корневого CLAUDE.md, чтобы не зациклить).' ,
2026-05-14 12:42:32 +03:00
'Не правит CLAUDE.md (исключён из фильтра путей). При неисправимой ошибке (например, битая ссылка) — предупреждение, не блокировка.' ,
[ { name : '.claude/settings.json' , cond : 'описан как хук PostToolUse' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'job markdownlint в lefthook' , cond : 'дублируют задачу: хук — в сессии, lefthook — при коммите' } ]
2026-05-13 17:05:59 +03:00
) ,
hk _post _schema : nd (
'После правки db/schema.sql напоминает обновить db/CHANGELOG_schema.md.' ,
2026-05-14 17:15:39 +03:00
'PostToolUse (после каждого вызова инструмента) — после Edit/Write на `db/schema.sql`.' ,
2026-05-14 12:42:32 +03:00
'Напоминание, не блокировка. Дисциплина ведения CHANGELOG_schema — на разработчике (§4.2 Pravila).' ,
[ { name : '.claude/settings.json' , cond : 'описан как хук PostToolUse' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'job squawk в lefthook' , cond : 'оба реагируют на изменения SQL' } ]
2026-05-13 17:05:59 +03:00
) ,
hk _session : nd (
2026-05-14 12:42:32 +03:00
'При старте каждой сессии подгружает CLAUDE.md, Pravila и ключевые memory-файлы в контекст.' ,
2026-05-14 17:15:39 +03:00
'SessionStart (при старте сессии) — единожды при инициализации сессии Claude Code.' ,
2026-05-14 12:42:32 +03:00
'Список memory-файлов фиксированный — для расширения править настройку хука. Не читает 80+ квирков целиком — выборочно по релевантности.' ,
[ { name : '.claude/settings.json' , cond : 'описан как хук SessionStart' } ] ,
2026-05-13 17:05:59 +03:00
[
2026-05-14 17:15:39 +03:00
{ name : 'память user_profile' , cond : 'читает' } ,
{ name : 'память feedback_environment' , cond : 'читает' } ,
{ name : 'память project_state' , cond : 'читает' } ,
{ name : 'память feedback_superpowers_hard_rule' , cond : 'читает' } ,
{ name : 'память feedback_plugin_paired_stack' , cond : 'читает' }
2026-05-13 17:05:59 +03:00
] ,
[ ]
) ,
hk _economy : nd (
2026-05-14 12:42:32 +03:00
'Перед каждым промптом разбирает «экономия X%» и выставляет режим строгости (0% = максимальное качество, 100% = по умолчанию).' ,
2026-05-14 17:15:39 +03:00
'UserPromptSubmit (перед отправкой промпта пользователя) — ищет шаблон /экономия\\s*(\\d+)%/.' ,
2026-05-16 13:44:14 +03:00
'§12 Superpowers — hard-rule уровня 0, economy-режим §12 НЕ отменяет ни на каком уровне. Действует только на текущую задачу — следующий промпт разбирается заново.' ,
2026-05-14 12:42:32 +03:00
[ { name : '.claude/settings.json' , cond : 'описан как хук UserPromptSubmit' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-16 13:44:14 +03:00
[ { name : 'плагин Superpowers (§12)' , desc : 'Экономия=100% теоретически может «сэкономить» вызов скила — §12 (hard-rule уровня 0) economy-режим не отменяет ни на каком уровне (Pravila §12.4).' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
// ── АГЕНТЫ ───────────────────────────────────────
ag _pest : nd (
2026-05-16 15:39:47 +03:00
'Разбирает падения тестов Pest --parallel: отличает настоящую ошибку от известных квирков (73/77 и др.; квирк 72 устранён 16.05.2026 — commit 0fa1a73).' ,
2026-05-14 17:15:39 +03:00
'При падении Pest --parallel ИЛИ при дымовом тесте (быстрой проверке функциональности) только из подкаталога (как в аудите Phase 3 SyncSupplierProjectsJobTest).' ,
'READ-ONLY (только чтение — только читает код, ничего не правит). Каждую гипотезу подтверждает реальным запуском, а не «похоже на квирк».' ,
2026-05-13 17:05:59 +03:00
[ { name : 'CLAUDE.md §6' , cond : 'описывает когда вызывать' } ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер redis' , cond : 'читает Redis для отладки квирка 72 (гонка supplier:session)' } ] ,
2026-05-16 06:48:46 +03:00
[
2026-05-16 15:39:47 +03:00
{ name : 'MCP-сервер redis' , desc : 'Квирк 72 (гонка с кэшем Redis при Pest --parallel из подкаталога) устранён 16.05.2026 — commit 0fa1a73, array-стор в тестах. Конфликт закрыт.' , type : 'GREEN' } ,
{ name : 'демон ruflo' , desc : 'Worker-jitter фонового демона ruflo (PM2) усиливает частоту Pest-квирков 73/77. Квирк 72 устранён 16.05 — его jitter больше не усиливает. На baseline-регрессии — `pm2 stop ruflo-daemon` (квирк #93, переоценён).' , type : 'BLACK' }
2026-05-16 06:48:46 +03:00
]
2026-05-13 17:05:59 +03:00
) ,
ag _rls : nd (
2026-05-14 12:47:10 +03:00
'Проверяет миграции на соответствие RLS (защите строк по тенанту) — 7 пунктов чеклиста с реальными командами, только чтение.' ,
2026-05-14 17:15:39 +03:00
'При создании/правке миграции в db/migrations/ ИЛИ при правке db/schema.sql ИЛИ при ревью PR (запроса на слияние кода) с изменениями БД.' ,
'READ-ONLY (только чтение — только Read/Grep/Glob/Bash) — код не пишет. Не замена скилу rls-check — у них разные сценарии.' ,
2026-05-14 12:47:10 +03:00
[ { name : 'CLAUDE.md' , cond : 'описывает в §6 и в директории агентов' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер laravel-boost' , cond : 'SQL запросы к db/schema.sql' } ] ,
2026-05-16 08:48:30 +03:00
[ { name : 'скил rls-check' , desc : 'граница задана регламентом (spec 2026-05-16): агент — разбор diff/ветки/PR со статическим 7-пунктовым чеклистом; скил — ручная проверка одной названной таблицы + живой дымовой тест. См. секцию «Граница со скилом /rls-check» в rls-reviewer.md.' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
ag _statusline : nd (
2026-05-14 12:47:10 +03:00
'Настраивает строку состояния Claude Code через правку файла настроек.' ,
2026-05-14 17:15:39 +03:00
'При запросе пользователя «настрой строку состояния» — редкая разовая задача.' ,
2026-05-14 12:47:10 +03:00
'Правит только секцию statusline в settings.json, другие части файла не трогает.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
ag _guide : nd (
2026-05-14 17:15:39 +03:00
'Отвечает на вопросы про API Claude Code, SDK, MCP-серверы (внешние сервисы-инструменты Claude), хуки, slash-команды.' ,
2026-05-14 09:17:37 +03:00
'При вопросе про возможности Claude Code/SDK/API — «Can Claude...», «How do I...», «Does Claude...».' ,
2026-05-14 17:15:39 +03:00
'READ-ONLY (только чтение): ищет в документации, код не правит. Не для отладки кода — только вопросы о платформе.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'MCP-сервер github' , cond : 'при необходимости ищет примеры в репозитории' } ]
2026-05-13 17:05:59 +03:00
) ,
ag _explore : nd (
2026-05-14 12:47:10 +03:00
'Быстрый поиск файлов по шаблону имени или по символу — только чтение, без анализа.' ,
'При точечном поиске — найти файл по имени или сделать grep по символу/ключевому слову.' ,
'Не для свободного исследования. Не для ревью/аудита (читает отрывки, теряет контекст за пределами окна чтения).' ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил subagent-driven-development' , cond : 'запускается для задач поиска' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
ag _general : nd (
2026-05-14 12:47:10 +03:00
'Универсальный агент для сложных многошаговых исследований — с полным набором инструментов.' ,
2026-05-14 17:15:39 +03:00
'При сложных многошаговых задачах исследования или написания кода, когда агента Explore не хватает (нужен анализ, не только поиск).' ,
2026-05-14 12:47:10 +03:00
'Полный набор инструментов — может писать код. Дороже Explore по токенам.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил subagent-driven-development' , cond : 'запускается для основных задач' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
ag _plan : nd (
2026-05-14 12:47:10 +03:00
'Архитектор: разрабатывает планы реализации, находит критичные файлы, разбирает компромиссы.' ,
2026-05-14 17:15:39 +03:00
'При архитектурном планировании задачи из нескольких компонентов (не для мелкого рефакторинга).' ,
'READ-ONLY (только чтение — без Edit/Write/NotebookEdit). Возвращает план, сам его не реализует.' ,
[ { name : 'скил subagent-driven-development' , cond : 'запускается для архитектурных задач' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил writing-plans' , cond : 'агент Plan и скил writing-plans решают похожую задачу в разных контекстах' } ]
2026-05-13 17:05:59 +03:00
) ,
ag _hookify : nd (
2026-05-14 12:47:10 +03:00
'Разбирает транскрипты диалогов и ищет поведение, которое стоит предотвратить хуком.' ,
2026-05-14 09:17:37 +03:00
'При триггере /hookify без аргументов ИЛИ при запросе «look back at this conversation, what mistakes to prevent».' ,
2026-05-14 17:15:39 +03:00
'READ-ONLY (только чтение — только Read+Grep). Рекомендует хуки, сам их не создаёт — передаёт в плагин hookify.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'плагин hookify' , cond : 'агент передаёт рекомендации в плагин' } ]
2026-05-13 17:05:59 +03:00
) ,
ag _pcreator : nd (
2026-05-14 12:47:10 +03:00
'Создаёт настройку новых агентов по описанию от пользователя.' ,
2026-05-14 09:17:37 +03:00
'При запросе «create an agent that...» — генерация agent.md по описанию функциональности.' ,
2026-05-14 17:15:39 +03:00
'Только инструменты Write/Read. Созданного агента сам не проверяет — передаёт в агент plugin-validator.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'агент plugin-dev:plugin-validator' , cond : 'валидатор проверяет созданного агента' } ]
2026-05-13 17:05:59 +03:00
) ,
ag _pvalid : nd (
2026-05-14 12:47:10 +03:00
'Проверяет структуру плагина на корректность — plugin.json, инструменты, манифест.' ,
'После создания/правки plugin.json или компонентов плагина — превентивная проверка.' ,
2026-05-14 17:15:39 +03:00
'READ-ONLY (только чтение — Read/Grep/Glob/Bash). Сам не правит — выдаёт список нарушений.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'агент plugin-dev:agent-creator' , cond : 'валидатор и создатель работают в паре' } ]
2026-05-13 17:05:59 +03:00
) ,
ag _skreview : nd (
2026-05-14 12:47:10 +03:00
'Оценивает качество написанного скила — описание, ход работы, примеры, лучшие практики.' ,
2026-05-14 17:15:39 +03:00
'После создания/правки скила через скил writing-skills — превентивное ревью.' ,
'READ-ONLY (только чтение — Read/Grep/Glob). Не правит — выдаёт рекомендации.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил writing-skills' , cond : 'skill-reviewer проверяет то, что создал writing-skills' } ]
2026-05-13 17:05:59 +03:00
) ,
// ── MCP-СЕРВЕРЫ ──────────────────────────────────
mcp _pw : nd (
2026-05-14 12:47:10 +03:00
'Управляет браузером — снимает скриншоты, кликает, заполняет формы для smoke- и a11y-тестов.' ,
2026-05-14 09:18:45 +03:00
'При визуальной проверке прототипов (фаза 0), при a11y smoke (axe-core), при UI integration smoke.' ,
2026-05-14 12:47:10 +03:00
'Не для боевых пользователей. На сессию один общий браузер — при parallel-work возможны столкновения (см. квирк #2 в memory).' ,
2026-05-13 17:05:59 +03:00
[ { name : 'CLAUDE.md §3.1 #2' , cond : 'активен с фазы 0' } ] ,
[ ] ,
2026-05-14 12:59:25 +03:00
[ { name : 'SessionStart хук' , cond : 'используется для визуальной проверки прототипов' } ] ,
[ { name : 'parallel-work скил' , desc : 'Один shared browser на сессию — конкуренция при параллельной работе через worktrees (memory квирк #2)' , type : 'BLACK' } ]
2026-05-13 17:05:59 +03:00
) ,
mcp _gh : nd (
2026-05-14 12:47:10 +03:00
'GitHub API — читает/создаёт PR, issues, коммиты, ветки в репозитории CoralMinister/lidpotok.' ,
'При работе с PR/issues, при поиске в репозитории, при создании PR через скил finishing-pr.' ,
'Не делать push в main без явного одобрения. Pravila §4: атомарные коммиты, не объединять их через MCP.' ,
2026-05-13 17:05:59 +03:00
[ { name : 'CLAUDE.md §3.1 #3' , cond : 'активен с фазы 0' } ] ,
[ ] ,
[ { name : 'finishing-pr скил' , cond : 'создаёт PR через этот MCP' } ]
) ,
mcp _boost : nd (
2026-05-14 12:47:10 +03:00
'Laravel Boost — SQL-запросы к dev-БД, схема таблиц, журналы ошибок, поиск по документации Laravel.' ,
2026-05-14 17:15:39 +03:00
'С первой фазы (старт backend) и далее — при SQL-запросах, поиске в документации Laravel, работе с моделями Eloquent.' ,
2026-05-14 12:47:10 +03:00
'**READ-ONLY к prod** — `.env.production` не должен попадать в локальный конфиг. Не использовать правила-подсказки Inertia/Livewire/Tailwind/Filament.' ,
[ { name : 'CLAUDE.md §3.2 #10' , cond : 'активен с фазы 1, доступ к prod только на чтение' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ { name : 'ag_rls агент' , cond : 'rls-reviewer использует Boost для SQL' } , { name : 'sk_rls скил' , cond : 'rls-check использует Boost' } ]
) ,
mcp _semgrep : nd (
2026-05-14 12:47:10 +03:00
'SAST (статический анализ кода на уязвимости) — ищет уязвимости, XSS (внедрение JS), SQLi (внедрение SQL), нарушения правил по шаблонам.' ,
2026-05-14 17:15:39 +03:00
'На третьей фазе проекта (перед запуском в боевую среду) — при просмотре кода через скил code-review и при автозапуске проверок CI (continuous integration) перед выпуском новой версии.' ,
2026-05-14 12:47:10 +03:00
'Настройка в .semgrep.yml. Ложные срабатывания документируются прямо в коде.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'CLAUDE.md §3.4 #25' , cond : 'третья фаза — перед запуском в боевую среду' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 17:15:39 +03:00
[ { name : 'скил code-review' , cond : 'MCP-сервер semgrep используется при разборе кода' } ]
2026-05-13 17:05:59 +03:00
) ,
mcp _sentry : nd (
2026-05-14 12:47:10 +03:00
'Читает ошибки из self-hosted Sentry в Yandex Cloud — события, стектрейсы, метрики. READ-ONLY (только чтение).' ,
'При расследовании ошибок боевой среды во время работы (после развёртывания Б-1).' ,
'**READ-ONLY** (org:read/project:read/event:read). Ждёт развёртывания инстанса Sentry по Б-1 (зависит от регистрации ООО).' ,
2026-05-14 17:15:39 +03:00
[ { name : 'CLAUDE.md §3.3 #34' , cond : 'вне основных фаз (для отладки во время работы); ждёт развёртывания Sentry по Б-1' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
mcp _redis : nd (
2026-05-14 12:47:10 +03:00
'Читает Redis/Memurai — ключи, очереди, кэш для отладки гонок (race conditions). СТРОГО READ-ONLY.' ,
2026-05-16 15:39:47 +03:00
'При отладке очередей Redis (Pest --parallel квирки 73/77), при анализе инвалидации кэша.' ,
2026-05-14 12:47:10 +03:00
'**СТРОГО READ-ONLY** — никаких DEL/FLUSHDB/SET/LPUSH из Claude (только GET/KEYS/LIST). Источник Anthropic устарел — миграция post-MVP.' ,
2026-05-14 17:15:39 +03:00
[ { name : 'CLAUDE.md §3.3 #35' , cond : 'вне основных фаз (для отладки во время работы); PSR_v1 R10.1 блок 3' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 12:59:25 +03:00
[ { name : 'pest-parallel-debugger агент' , cond : 'агент использует для квирка 72 (гонка в Redis)' } ] ,
2026-05-16 15:39:47 +03:00
[ { name : 'агент pest-parallel-debugger' , desc : 'Квирк 72 (гонка с кэшем Redis при Pest --parallel из подкаталога) устранён 16.05.2026 — commit 0fa1a73. Конфликт закрыт.' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
mcp _21st : nd (
2026-05-14 12:47:10 +03:00
'Генератор стартовых шаблонов UI-компонентов через LLM. Активация только через процедуру R14.4.' ,
'Только через процедуру PSR_v1 R14.4: предпроверка из 9 условий (брендовый App*? есть аналог в Vuetify? есть уже существующий компонент?).' ,
'R14.5: не запускать параллельно с FD/UPM. Обязательны: JSX→Vue, Tailwind→utility, shadcn→Vuetify. Pa11y a11y на готовом виде.' ,
[ { name : 'PSR_v1 R14.4' , cond : 'строгая предпроверка: 9 условий перед активацией' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 12:59:25 +03:00
[ { name : 'Frontend Design' , desc : 'PSR_v1 R14.5: нельзя параллельно — 21st как генератор материала, FD как решатель; риск смешать роли и нарушить R6 (фильтр стека)' , type : 'GREEN' } ]
2026-05-13 17:05:59 +03:00
) ,
// ── LEFTHOOK JOBS ─────────────────────────────────
lh _gitleaks : nd (
2026-05-14 12:53:35 +03:00
'Ищет ПДн (персональные данные), токены и API-ключи в файлах, готовых к коммиту. Если находит — коммит блокируется.' ,
'Перед каждым коммитом — проверяет только те файлы, что добавлены через `git add`.' ,
'Обход через `--no-verify` запрещён (правило §4.2 Pravila). Находка = блокирующая ошибка, не предупреждение. Известные ложные срабатывания — в файл `.gitleaksignore`.' ,
[ { name : 'lefthook.yml' , cond : 'задача №1 в наборе перед коммитом, без параллельного запуска' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'lefthook:gitleaks pre-push' , cond : 'версия для push сканирует всю историю' } ]
2026-05-13 17:05:59 +03:00
) ,
lh _mdlint : nd (
2026-05-14 12:53:35 +03:00
'Проверяет и авто-исправляет стиль файлов Markdown перед коммитом.' ,
'Перед каждым коммитом, когда в нём есть файлы `.md`.' ,
'Настройки в `.markdownlint-cli2.cjs`. Авто-исправление включено (исправленные файлы авто-сохраняются обратно в коммит).' ,
[ { name : 'lefthook.yml' , cond : 'задача №2 в наборе перед коммитом' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'PostToolUse:markdownlint-fix хук' , cond : 'делают одно и то же — хук сразу после правки, lefthook при коммите' } ]
2026-05-13 17:05:59 +03:00
) ,
lh _cspell : nd (
2026-05-14 12:53:35 +03:00
'Проверяет орфографию в `.md` файлах по словарю `cspell-words.txt`.' ,
'Перед каждым коммитом, когда в нём есть файлы `.md`.' ,
'Словарь: `cspell-words.txt`. Кириллица — в нижнем регистре. Не обходить через `--no-verify` — добавлять валидные слова в словарь.' ,
[ { name : 'lefthook.yml' , cond : 'задача №3 в наборе перед коммитом' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
lh _stylelint : nd (
2026-05-14 12:53:35 +03:00
'Линтует CSS в HTML-прототипах (`web/v8/*.html`).' ,
'Перед каждым коммитом, когда в нём есть файлы `.html`/`.css`.' ,
'Настройки Stylelint в `.stylelintrc`. Устаревшие свойства (например `word-break: break-word`) блокируют коммит.' ,
[ { name : 'lefthook.yml' , cond : 'задача №4 в наборе перед коммитом' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
lh _pint : nd (
2026-05-14 12:53:35 +03:00
'Авто-форматирует код PHP по PSR-стандарту (стиль кода PHP). Исправленные файлы авто-сохраняются обратно в коммит.' ,
'Перед каждым коммитом — на каждый файл `.php` в директории `app/`.' ,
'Авто-исправление включено. Настройки в `app/pint.json`.' ,
[ { name : 'lefthook.yml' , cond : 'задача №5 в наборе перед коммитом, корень `app/`' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
lh _larastan : nd (
2026-05-14 12:53:35 +03:00
'Статический анализ PHP (Larastan, уровень L9) — находит ошибки типов выше базового уровня.' ,
'Перед каждым коммитом, когда в нём есть файлы `.php` в `app/`.' ,
'Базовый уровень `phpstan-baseline.neon` зафиксирован — новые ошибки блокируют коммит. Не повышать базовый уровень без обоснования.' ,
[ { name : 'lefthook.yml' , cond : 'задача №6 в наборе перед коммитом, корень `app/`' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'MCP: laravel-boost' , cond : 'Boost даёт контекст типов через IDE-подсказки' } ]
2026-05-13 17:05:59 +03:00
) ,
lh _squawk : nd (
2026-05-14 12:53:35 +03:00
'Линтер SQL-миграций — проверяет безопасные шаблоны (без блокировки таблиц, параллельный CREATE INDEX и т.п.).' ,
'Перед каждым коммитом, когда в нём есть файлы миграций (`database/migrations/*.php` или `db/*.sql`).' ,
'Настройки в `squawk.toml`. Небезопасные миграции (`ALTER TABLE ADD COLUMN NOT NULL DEFAULT`) запрещены без явной метки `-- squawk-ignore`.' ,
[ { name : 'lefthook.yml' , cond : 'задача №7 в наборе перед коммитом, фильтр путей `*.sql`' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'Tooling #15 squawk' , cond : 'соответствует записи §3.2 в Tooling' } ]
2026-05-13 17:05:59 +03:00
) ,
lh _eslint : nd (
2026-05-14 12:53:35 +03:00
'Линтует файлы Vue/TypeScript в `app/resources/js/`.' ,
'Перед каждым коммитом, когда в нём есть файлы `.vue`/`.ts`/`.tsx` в `app/`.' ,
'Flat-config ESLint 10 + plugin-vue 10. Обход через `--no-verify` запрещён. Ошибки блокируют коммит, предупреждения допустимы.' ,
[ { name : 'lefthook.yml' , cond : 'задача №8 в наборе перед коммитом, корень `app/`' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ]
) ,
lh _gitleaks2 : nd (
2026-05-14 12:53:35 +03:00
'Полный скан всей истории коммитов на секреты — строже задачи перед коммитом.' ,
'pre-push (перед `git push` на удалённый репозиторий) — сканирует историю новых коммитов целиком.' ,
'Обход через `--no-verify` запрещён (правило §4.2 Pravila). На больших push (200+ коммитов) занимает 30+ секунд.' ,
[ { name : 'lefthook.yml' , cond : 'задача в наборе перед push' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'lefthook:gitleaks' , cond : 'версия для push строже: проверяет всю историю, а не только staged' } ]
2026-05-13 17:05:59 +03:00
) ,
lh _lychee : nd (
2026-05-14 12:53:35 +03:00
'Проверяет все ссылки в `.md` файлах на битые (`docs/**/*.md`, `db/**/*.md`, корневые `*.md`).' ,
'pre-push (перед `git push`) — проверяет ссылки во всех `.md` файлах репозитория.' ,
'Внешние ссылки проверяются с таймаутом 10 секунд; при отсутствии интернета — ошибка. Настройки в `lychee.toml`. Обход через `--no-verify` запрещён.' ,
[ { name : 'lefthook.yml' , cond : 'задача в наборе перед push' } ] ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ { name : 'CLAUDE.md' , cond : 'проверяет ссылки в CLAUDE.md в том числе' } ]
) ,
// ── MEMORY FILES ─────────────────────────────────
mem _user : nd (
'Профиль заказчика: Дмитрий, Windows Server 2022, VSCode, русский язык, путь к проекту.' ,
2026-05-14 12:53:35 +03:00
'Читается при старте каждой сессии через хук SessionStart — для языка и предпочтений.' ,
2026-05-14 09:20:54 +03:00
'Не содержит секретов. При смене заказчика — переписать полностью.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ { name : 'SessionStart хук' , cond : 'читается при старте каждой сессии' } ]
) ,
mem _comm : nd (
2026-05-14 12:53:35 +03:00
'Стиль общения: короткие команды («а», «б», «делай»), варианты A/B/C, явная фиксация переоткрытий.' ,
'Читается при работе с заказчиком — чтобы соответствовать его стилю общения.' ,
'Это не код, а правила коммуникации. Корректировки — только через явный отзыв заказчика.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'memory:user_profile' , cond : 'дополняет профиль заказчика' } ]
2026-05-13 17:05:59 +03:00
) ,
mem _env : nd (
2026-05-14 12:53:35 +03:00
'80+ квирков (особенностей) окружения: специфика Windows Server, баги инструментов, обходные пути.' ,
'При неожиданном поведении — сначала проверить memory:env на известный квирк.' ,
'Не дублировать — добавлять только новые квирки. Счётчик квирков актуализируется в `project_state.md`.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[
2026-05-16 15:39:47 +03:00
{ name : 'pest-parallel-debugger агент' , cond : 'квирки 73/77 используются агентом' } ,
2026-05-13 17:05:59 +03:00
{ name : 'SessionStart хук' , cond : 'читается при старте' }
]
) ,
mem _sp : nd (
2026-05-16 13:44:14 +03:00
'Правило §12 (hard-rule уровня 0) + архитектура хука economy из 6 компонентов — дисциплина вызова скилов.' ,
2026-05-14 12:53:35 +03:00
'При работе со скилами — для соответствия обязательному правилу §12 Pravila.' ,
'Описывает архитектуру хука economy (6 компонентов) — менять только при изменении самого хука.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'economy-mode хук' , cond : 'memory описывает архитектуру хука' } ]
2026-05-13 17:05:59 +03:00
) ,
mem _plugins : nd (
2026-05-14 12:53:35 +03:00
'Правила парного стека плагинов, MCP-серверы для отладки, уровневая структура PSR_v1.' ,
'При работе с плагинами FD/UPM/21st/Sentry/Redis MCP — для уровневого разделения по PSR_v1.' ,
2026-05-14 09:20:54 +03:00
'Синхронизируется с PSR_v1 — изменения в memory только если изменился сам PSR_v1.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ { name : 'PSR_v1' , cond : 'memory отражает актуальные версии PSR_v1' } ]
) ,
mem _state : nd (
2026-05-14 12:53:35 +03:00
'Текущее состояние проекта: ветка, тесты (Pest/Vitest), последние коммиты, активные задачи.' ,
2026-05-14 09:20:54 +03:00
'Читается при старте сессии — для быстрого контекста; обновляется после крупных вех.' ,
2026-05-14 12:53:35 +03:00
'Может устаревать — перечитать при сомнении. Не доверять данным старше 2-3 дней без проверки.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-16 06:48:46 +03:00
[ { name : 'SessionStart хук' , cond : 'читается при старте для быстрого контекста' } ] ,
[ { name : 'память ruflo' , desc : 'Два хранилища памяти не синхронизированы: проектные `memory/*.md` (16 файлов) и база ruflo `.swarm/memory.db`. Фактически память ruflo почти пуста — MCP-сервер репортит 0 записей (+2 тестовых призрака от alpha-бага HNSW #1122). Recall-хук срабатывает на каждый промпт, но извлекать ему почти нечего.' , type : 'BLACK' } ]
2026-05-13 17:05:59 +03:00
) ,
mem _phase1 : nd (
2026-05-14 12:53:35 +03:00
'Стратегия фазы 1: нативный стек Windows без Docker, расширение pg_partman заменено Artisan-задачей в cron.' ,
'При работе с инфраструктурой фазы 1 (PG/Redis/PHP-CLI нативно на Windows).' ,
'Стратегия зафиксирована до закрытия блокера Б-1 (Managed PG в Yandex Cloud) или 6 месяцев — пересмотр указан в файле.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
mem _archive : nd (
'Карта источников истины: версии всех 13+ ключевых документов проекта.' ,
2026-05-14 09:20:54 +03:00
'При вопросах «какая версия документа X» или «где источник истины для Y».' ,
2026-05-14 12:53:35 +03:00
'Синхронизируется с §0 CLAUDE.md. Изменения в memory — только если изменился §0 CLAUDE.md.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
2026-05-14 12:53:35 +03:00
[ { name : 'CLAUDE.md' , cond : 'memory синхронизирует версии с §0 CLAUDE.md' } ]
2026-05-13 17:05:59 +03:00
) ,
mem _github : nd (
2026-05-14 12:53:35 +03:00
'Репозиторий GitHub CoralMinister/lidpotok: HEAD, хуки, правила push.' ,
'При работе с GitHub — push, PR, операции с ветками.' ,
'Не делать `push --force` на main (предупреждение в Pravila). Хуки перед push обязательны.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ { name : 'MCP: github' , cond : 'MCP и memory дополняют друг друга для работы с GitHub' } ]
) ,
mem _handoff : nd (
2026-05-14 12:53:35 +03:00
'Дизайн-передача от Платона: что из `liderra_v8_handoff/` используем, что нет.' ,
'При UI/дизайн-задачах — для разделения «брендбук используем» vs «состав фич — по ТЗ v8.5».' ,
'Передача — только дизайн/токены/компоненты. Функционал и состав экранов — НЕ из передачи (берём из ТЗ).' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
mem _audit : nd (
2026-05-14 12:53:35 +03:00
'Полный аудит портала 13.05.2026: 38 находок, вердикт жёлтый, 10 отложенных вопросов закрыты.' ,
'При вопросах про аудит или его последствия (Q.DEFER, распределение P0/P1/P2).' ,
'Это снимок состояния — не редактировать при последующих аудитах, создавать новые memory-файлы.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
mem _supplier : nd (
2026-05-14 12:53:35 +03:00
'Прогресс интеграции с поставщиком лидов (планы 1-5): задачи, коммиты, блокеры.' ,
'При работе с интеграцией поставщика (планы 1-5) — для текущего состояния и блокеров.' ,
'Блокеры (Б-1, доступы) — внешние, не разрешаются силами Claude. Только отслеживание.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
mem _brain : nd (
2026-05-14 12:53:35 +03:00
'Claude Brain v1.0 — отдельный репозиторий «мозга», тег `brain-v1.0`, скрипт `install.sh`.' ,
'При работе с репозиторием brain или скриптом `install.sh` для синхронизации потребителей.' ,
'Push на репозиторий brain в GitHub заблокирован (вопрос 8.2). Не пытаться push без разрешения.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
mem _redesign : nd (
2026-05-14 12:53:35 +03:00
'Редизайн Quiet Luxury: 20 коммитов, базовый CSS + composables + переписанный AppSidebar.' ,
'При работе с редизайном портала (frontend, AppSidebar, базовый CSS).' ,
'Бэклог итерации I2 — в §15 спека, 10 пунктов отложены. Не реализовывать пункты I2 без явного запроса.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
mem _devindices : nd (
2026-05-14 12:53:35 +03:00
'Dev Element Indices — временная фича обратной связи для разработки; к удалению в продакшене.' ,
'При работе с dev-фидбеком (например «1030 измени цвет») — для соответствия номер → элемент.' ,
'**ВРЕМЕННАЯ** — заказчик прямо сказал «уберём в конечном релизе». Не вкладываться в долгосрочную инфраструктуру.' ,
2026-05-13 17:05:59 +03:00
[ ] ,
[ ] ,
[ ]
) ,
2026-05-15 15:34:39 +03:00
2026-05-16 06:48:46 +03:00
// ── RUFLO ОРКЕСТРАТОР (фактический реколлаж iter5) ──
2026-05-15 15:34:39 +03:00
ruflo _queen : nd (
2026-05-16 13:44:14 +03:00
'Queen оркестратора ruflo v3.7.0-alpha.38 — стратегическая «королева» роя hive-mind (топология hierarchical-mesh, консенсус byzantine). С реколлажа 16.05.2026 (CLAUDE.md §3.5, Tooling §4.10) — advisory/automation-подсистема, не entry-point: рой работает параллельно, Клод — напрямую.' ,
'Запускается только по триггеру queen/королева в промпте (Pravila §14 — hard-rule маршрутизации). Без триггера рой простаивает — Клод работает напрямую.' ,
'Фактическая инспекция рантайма 15.05.2026: Queen активна (term 1, нагрузка 0), но за всё время — 0 задач, 0 раундов консенсуса, 0 общей памяти. Реколлаж 16.05.2026 привёл нормативку к этому факту — ruflo переописан в advisory/automation-подсистему, декларация уровня −1 убрана. Alpha-версия, LLM API-ключей нет.' ,
[
{ name : 'Pravila §14' , cond : 'queen-триггер — hard-rule маршрутизации задачи через Queen' } ,
{ name : 'CLAUDE.md §3.5 / Tooling §4.10' , cond : 'нормативно описан как advisory/automation-подсистема' }
] ,
2026-05-15 15:34:39 +03:00
[
2026-05-16 06:48:46 +03:00
{ name : '10 воркеров hive-mind' , cond : 'координирует рой — все 10 простаивают' } ,
{ name : 'каталог агентов ruflo' , cond : 'ruflo init высыпал в .claude/agents/ — не задействовано' } ,
{ name : 'slash-команды ruflo' , cond : 'ruflo init высыпал в .claude/commands/ — не задействовано' } ,
{ name : 'плагины ruflo' , cond : 'установлено 0 из ~20 в реестре' }
] ,
[
{ name : 'memory:project_ruflo_integration' , cond : 'memory-файл документирует интеграцию' } ,
{ name : 'ruflo MCP' , cond : 'MCP-сервер экспонирует инструменты управления роем' }
2026-05-15 15:34:39 +03:00
] ,
2026-05-16 13:44:14 +03:00
[ { name : 'Pravila' , desc : 'iter4– iter5: нормативка декларировала ruflo Queen-led routing уровнем − 1 (overlord над всей иерархией) — расходилось с рантаймом (рой idle, 0 задач, 0 раундов консенсуса). Реколлаж 16.05.2026 (Pravila v1.16 / CLAUDE.md v2.2 / PSR_v1 v3.2 / Tooling v2.2) привёл нормативку к факту: ruflo переописан в advisory/automation-подсистему, уровень −1 убран. Конфликт «декларация ≠ рантайм» закрыт.' , type : 'GREEN' } ]
2026-05-15 15:34:39 +03:00
) ,
2026-05-16 06:48:46 +03:00
ruflo _workers : nd (
'Рабочие агенты роя hive-mind ruflo — 10 штук. Все одного типа (generic worker), без специализации. На карте до iter5 рисовались 9 «ролей» (Архитектор/Кодер/…) — таких ролей в рантайме не существует.' ,
'По задумке — Queen раздаёт воркерам подзадачи. Фактически — ни разу.' ,
'Инспекция рантайма 15.05.2026: 10 воркеров, все в статусе «простаивает» (idle), у каждого 0 выполненных задач. LLM API-ключей нет → реальная агентская работа невозможна. Последний рой запущен с тестовой задачей «ответь словом READY и ничего не меняй».' ,
[ { name : 'ruflo Queen' , cond : 'подчинены — Queen-led иерархия hive-mind' } ] ,
2026-05-15 15:34:39 +03:00
[ ] ,
[ ]
) ,
2026-05-16 06:48:46 +03:00
ruflo _daemon : nd (
'Фоновый демон ruflo под управлением PM2 (процесс `ruflo-daemon`). По расписанию запускает 5 воркеров: map (каждые 15 мин), audit (10 мин), optimize (15 мин), consolidate (30 мин), testgaps (20 мин). Переживает перезагрузку через планировщик задач Windows.' ,
'Работает постоянно в фоне.' ,
2026-05-16 15:39:47 +03:00
'Инспекция рантайма 15.05.2026: воркеры audit / optimize / testgaps пытаются запустить `claude` и КАЖДЫЙ РАЗ падают с ошибкой «файл не найден» (spawn claude ENOENT) — результат пустой (за сутки: audit 29 запусков, optimize 19, testgaps 14 — все пустые). Журнал демона при этом помечает их «успешными» — расхождение метрики и факта. Локально работают только воркеры map и consolidate (без вызова `claude`). Worker-jitter усиливает частоту Pest-квирков 73/77 (квирк 72 устранён 16.05) — на baseline-регрессии нужно `pm2 stop ruflo-daemon`.' ,
2026-05-15 15:34:39 +03:00
[ ] ,
[ ] ,
2026-05-16 06:48:46 +03:00
[ { name : 'память ruflo' , cond : 'воркер consolidate обращается к хранилищу' } ] ,
2026-05-16 15:39:47 +03:00
[ { name : 'агент pest-parallel-debugger' , desc : 'Worker-jitter фонового демона ruflo (PM2) усиливает частоту Pest-квирков 73/77. Квирк 72 устранён 16.05 (commit 0fa1a73) — его jitter больше не усиливает. На baseline-регрессии — `pm2 stop ruflo-daemon` (квирк #93, переоценён).' , type : 'BLACK' } ]
2026-05-15 15:34:39 +03:00
) ,
2026-05-16 06:48:46 +03:00
ruflo _mcp : nd (
'MCP-сервер ruflo (внешний сервис-инструмент Клода) — отдельный процесс `ruflo mcp start`, режим stdio, 7-й сервер в `.mcp.json`. Экспонирует ~210 инструментов (агенты / память / рой / хуки / нейросеть и др.).' ,
'Инструменты доступны Клоду постоянно. Это единственная по-настоящему рабочая точка интеграции ruflo — через неё и собрана фактическая инспекция 15.05.2026.' ,
'Клод НЕ обязан вызывать ruflo-инструменты — отсюда статус ruflo как параллельной подсистемы, а не overlord. Память, опрашиваемая через MCP, почти пуста (0 записей). Alpha-версия.' ,
2026-05-15 15:34:39 +03:00
[ ] ,
2026-05-16 06:48:46 +03:00
[ ] ,
[
{ name : 'ruflo Queen' , cond : 'экспонирует инструменты управления роем' } ,
{ name : 'память ruflo' , cond : 'читает/пишет через инструменты memory_*' }
]
2026-05-15 15:34:39 +03:00
) ,
ruflo _memory : nd (
2026-05-16 06:48:46 +03:00
'Хранилище памяти ruflo — файл базы `.swarm/memory.db` (SQLite через sql.js) + векторный индекс HNSW с реальными embeddings Xenova/all-MiniLM-L6-v2 (384 измерения).' ,
'Должно накапливать факты между сессиями; recall-хук и MCP-инструменты обращаются к нему.' ,
'Инспекция рантайма 15.05.2026: MCP-сервер репортит 0 записей. В базе — 2 тестовых «призрака» (h7-fixed-verify, hook-e2e) от alpha-бага HNSW #1122 (`memory delete` убирает строку, но не вектор). Проектные `memory/*.md` (16 файлов) в неё не проиндексированы. Наполняется только вручную через `ruflo memory store`.' ,
[ ] ,
2026-05-15 15:34:39 +03:00
[ ] ,
2026-05-16 06:48:46 +03:00
[
{ name : 'ruflo MCP' , cond : 'MCP читает/пишет через инструменты memory_*' } ,
{ name : 'хук recall' , cond : 'recall-хук запускает поиск по памяти' } ,
{ name : 'демон ruflo' , cond : 'воркер consolidate обращается к памяти' }
] ,
[ { name : 'memory:project_state' , desc : 'Два хранилища памяти не синхронизированы: проектные `memory/*.md` (16 файлов) и база ruflo `.swarm/memory.db`. Фактически память ruflo почти пуста — MCP-сервер репортит 0 записей (+2 тестовых призрака от alpha-бага HNSW #1122). Recall-хук срабатывает на каждый промпт, но извлекать ему почти нечего.' , type : 'BLACK' } ]
2026-05-15 15:34:39 +03:00
) ,
2026-05-16 06:48:46 +03:00
ruflo _recall _hook : nd (
'Хук типа UserPromptSubmit, зарегистрирован в `.claude/settings.json` — скрипт `tools/ruflo-recall-hook.mjs`. На каждый промпт пользователя запускает `ruflo memory search` и подмешивает топ-3 найденных записи в контекст. Единственный хук ruflo, реально вшитый в сессию Claude Code.' ,
'Перед каждым промптом пользователя.' ,
'Срабатывает «мягко» (fail-open): при ошибке/таймауте — пустой инжект, промпт не блокируется. Хук работает (виден в системных напоминаниях этой сессии), но память ruflo почти пуста — извлекать почти нечего (recall возвращает 2 тестовых призрака). У самого ruflo есть 26-27 внутренних хуков, но в `.claude/settings.json` вшит только этот один.' ,
2026-05-15 15:34:39 +03:00
[ ] ,
[ ] ,
2026-05-16 06:48:46 +03:00
[ { name : 'память ruflo' , cond : 'запускает поиск по памяти ruflo' } ]
2026-05-15 15:34:39 +03:00
) ,
2026-05-16 06:48:46 +03:00
ruflo _agents _catalog : nd (
'Каталог определений агентов, который `ruflo init` высыпал в `.claude/agents/` — 100 файлов в 23 категориях (core, consensus, sparc, github, v3, flow-nexus, optimization, sublinear, templates и др.). Из них 98 — от ruflo, 2 — проектные (rls-reviewer, pest-parallel-debugger).' ,
'Определения видны Claude Code как доступные типы суб-агентов.' ,
'Статичные файлы-заготовки. «ruflo использует каталог» — нет: воркеры роя безымянные generic, у демона свой набор воркеров. Каталог просто лежит.' ,
[ { name : 'ruflo Queen' , cond : 'высыпан установкой ruflo init' } ] ,
[ ] ,
[ ]
) ,
ruflo _commands : nd (
'Slash-команды, которые `ruflo init` высыпал в `.claude/commands/` — 88 файлов (категории sparc, github, hooks, analysis, automation, optimization, monitoring).' ,
'Доступны как slash-команды Claude Code.' ,
'Статичные файлы. Это ближайший аналог «скилов» у ruflo — но НЕ Claude Code скилы; в `.claude/skills/` ruflo не положил ничего (там только 2 проектных скила). Команды лежат, в работе проекта не задействуются.' ,
[ { name : 'ruflo Queen' , cond : 'высыпаны установкой ruflo init' } ] ,
[ ] ,
[ ]
) ,
ruflo _plugins : nd (
'Плагины ruflo. В IPFS-реестре оркестратора заявлено ~20 плагинов. Установлено — 0.' ,
'Никогда — ни один плагин не подключён.' ,
'Фактически: папки `.claude-flow/plugins/` не существует, ни один плагин не установлен. `ruflo plugins list` зависает на IPFS-discovery (реестр недоступен — Pinata/Cloudflare не отвечают). Отдельно: Claude Code скилов ruflo не привнёс — в `.claude/skills/` только 2 проектных (rls-check, q-item-add). Прямой ответ на вопрос «какие плагины и скилы использует ruflo»: ноль и ноль.' ,
[ { name : 'ruflo Queen' , cond : 'часть установки ruflo' } ] ,
2026-05-15 15:34:39 +03:00
[ ] ,
[ ]
) ,
mem _ruflo : nd (
2026-05-16 06:48:46 +03:00
'Memory-файл `project_ruflo_integration` — история ruflo big-bang (установка, нормативная инверсия, активация рантайма) и alpha-баги.' ,
2026-05-15 15:34:39 +03:00
'При работе с ruflo — для контекста интеграции и известных alpha-багов.' ,
2026-05-16 06:48:46 +03:00
'Снимок на 15.05.2026. iter5 карты опирается на фактическую инспекцию рантайма, а не только на этот файл.' ,
2026-05-15 15:34:39 +03:00
[ ] ,
[ ] ,
[ { name : 'ruflo Queen' , cond : 'документирует ruflo-интеграцию' } ]
) ,
2026-05-16 15:39:47 +03:00
// ── АУДИТ-АКТУАЛИЗАЦИЯ 16.05.2026 ────────────────
skill _creator : nd (
'Плагин Anthropic для создания новых скилов — eval-driven подход: датасеты сценариев, train/test split, бенчмарк-цикл.' ,
'При формализации повторяющегося процесса в скил с проверяемым выводом (генерация кода, преобразование файлов).' ,
'Включён в настройках (~/.claude/settings.json). Для discipline-скилов (TDD-типа) предпочтительнее скил writing-skills плагина Superpowers — у них разные философии.' ,
[ { name : 'PSR_v1' , cond : 'R10.1: внешний плагин-инструмент' } ] ,
[ ] ,
[ { name : 'скил writing-skills' , cond : 'обе создают скилы — skill-creator eval-driven, writing-skills через TDD' } ]
) ,
claude _setup : nd (
'Плагин Anthropic — рекомендатель автоматизаций (claude-automation-recommender): анализирует репозиторий и советует, какие MCP-серверы, скилы, хуки, суб-агентов добавить.' ,
'При настройке/ревизии автоматизации проекта — «чего не хватает в тулчейне».' ,
'Включён в настройках (~/.claude/settings.json). Рекомендации — совещательные, решение за заказчиком.' ,
[ { name : 'PSR_v1' , cond : 'R10.1: внешний плагин-инструмент' } ] ,
[ ] ,
[ ]
) ,
plugin _dev : nd (
'Плагин Anthropic для разработки плагинов Claude Code — 7 скилов (структура плагина, разработка скилов / агентов / хуков / команд, интеграция MCP, настройки).' ,
'При создании или правке плагина и его компонентов.' ,
'Включён в настройках. Содержит 3 агента, уже представленные на карте (agent-creator / plugin-validator / skill-reviewer).' ,
[ { name : 'PSR_v1' , cond : 'R10.1: внешний плагин-инструмент' } ] ,
[
{ name : 'агент plugin-dev:agent-creator' , cond : 'входит в плагин' } ,
{ name : 'агент plugin-dev:plugin-validator' , cond : 'входит в плагин' } ,
{ name : 'агент plugin-dev:skill-reviewer' , cond : 'входит в плагин' }
] ,
[ ]
) ,
context7 : nd (
'Плагин Anthropic — актуальная документация библиотек / фреймворков / API через MCP-инструменты query-docs и resolve-library-id.' ,
'При вопросах по библиотеке / фреймворку / SDK / CLI — синтаксис API, конфигурация, миграция версий. Предпочтительнее веб-поиска для документации библиотек.' ,
'Включён в настройках. Не для рефакторинга / отладки бизнес-логики / ревью — только документация.' ,
[ { name : 'PSR_v1' , cond : 'R10.1: внешний плагин-инструмент' } ] ,
[ ] ,
[ ]
) ,
hk _self _check : nd (
'Хук SessionStart — economy-self-check.py: при старте сессии восстанавливает уровень экономии из файла состояния и проверяет согласованность.' ,
'SessionStart — единожды при инициализации сессии.' ,
'Часть архитектуры economy-хука из 6 компонентов (memory feedback_superpowers_hard_rule). §12 economy-режим не отменяет.' ,
[ { name : '~/.claude/settings.json' , cond : 'хук SessionStart (user-level)' } ] ,
[ ] ,
[ { name : 'хук economy-mode' , cond : 'оба — часть системы экономии' } ]
) ,
hk _skill _marker : nd (
'Хук PreToolUse на вызов Skill — skill-marker.py: фиксирует факт инвокации скила в состоянии сессии (пара со skill-check).' ,
'PreToolUse, matcher Skill — перед каждым вызовом скила.' ,
'Часть пары skill-marker / skill-check — runtime-энфорсмент §12 (скил инвокируется первым).' ,
[ { name : '~/.claude/settings.json' , cond : 'хук PreToolUse (user-level)' } ] ,
[ ] ,
[ { name : 'хук skill-check' , cond : 'пара: marker фиксирует вызов скила, check проверяет' } ]
) ,
hk _skill _check : nd (
'Хук PreToolUse на Edit/Write/MultiEdit — skill-check.py: проверяет, был ли инвокирован подходящий скил перед правкой кода (§12 дисциплина).' ,
'PreToolUse, matcher Edit|Write|MultiEdit.' ,
'Пара со skill-marker. Энфорсит §12 — нельзя править код, минуя обязательный скил.' ,
[ { name : '~/.claude/settings.json' , cond : 'хук PreToolUse (user-level)' } ] ,
[ ] ,
[ { name : 'хук skill-marker' , cond : 'пара skill-marker / skill-check' } ]
) ,
hk _state _guard : nd (
'Хук PreToolUse на Edit/Write/MultiEdit/Bash/Agent — economy-state-guard.py: ловит обходы режима экономии (в т.ч. Bash-обход Edit и наследование суб-агентами).' ,
'PreToolUse, matcher Edit|Write|MultiEdit|Bash|Agent.' ,
'Часть системы экономии из 6 компонентов. Закрывает bypass-пути (Bash вместо Edit, суб-агенты).' ,
[ { name : '~/.claude/settings.json' , cond : 'хук PreToolUse (user-level)' } ] ,
[ ] ,
[ { name : 'хук economy-mode' , cond : 'оба — система экономии' } ]
) ,
hk _postcompact : nd (
'Хук PostCompact — economy-postcompact.py: после компактификации сессии переинжектит состояние режима экономии в контекст.' ,
'PostCompact — после сжатия истории сессии.' ,
'Часть системы экономии из 6 компонентов — гарантирует, что режим переживает компакт.' ,
[ { name : '~/.claude/settings.json' , cond : 'хук PostCompact (user-level)' } ] ,
[ ] ,
[ ]
) ,
hk _verifier : nd (
'Хук Stop — агент-верификатор (модель Sonnet 4.6): после ответа проверяет соответствие режиму экономии — заявления «готово» без тестов, правки без тестов, выборочные результаты.' ,
'Stop — после каждого ответа Claude (кроме тривиальных Q&A-ходов).' ,
'Решение decision:block при нарушении. На уровне экономии 5 — short-circuit {compliant:true}. Стоит денег (вызовы Sonnet).' ,
[ { name : '~/.claude/settings.json' , cond : 'хук Stop типа agent (user-level)' } ] ,
[ ] ,
[ { name : 'скил verification-before-completion' , cond : 'верификатор энфорсит то, что требует скил' } ]
) ,
hk _ruflo _queen : nd (
'Хук UserPromptSubmit — ruflo-queen-hook.mjs: при триггер-словах queen/королева в промпте инжектит жёсткую директиву маршрутизации задачи через ruflo Queen (Pravila §14).' ,
'UserPromptSubmit — перед каждым промптом; срабатывает на queen / королева.' ,
'Энфорсит §14 Pravila (hard-rule). Перед платным спавном роя — превью. Зарегистрирован в project .claude/settings.json.' ,
[
{ name : '.claude/settings.json' , cond : 'хук UserPromptSubmit (project-level)' } ,
{ name : 'Pravila §14' , cond : 'энфорсит queen-триггер' }
] ,
[ ] ,
[ { name : 'ruflo Queen' , cond : 'хук маршрутизирует queen-задачи на Queen' } ]
) ,
sk _regression : nd (
'Проектный скил /regression — единый прогон регрессии: Pest --parallel + Vitest + сборка, парсинг результатов (JSON-first для pest --parallel, см. квирк 94).' ,
'Перед коммитом/пушем или при запросе полной регрессии — единая сводка по тестам.' ,
'Реализация — .claude/skills/regression/ (SKILL.md + run.mjs + run.test.mjs). parsePest: JSON.parse строки {"tool":"pest"}, regex — fallback.' ,
[ ] ,
[ ] ,
[ { name : 'агент pest-parallel-debugger' , cond : 'при падениях Pest --parallel передаёт разбор агенту' } ]
) ,
mem _audit _b : nd (
'Memory-файл audit_B_status — статус и находки аудитов D и B (закрыты, 6 коммитов, 34/34 RLS после хотфикса).' ,
'При вопросах про аудиты D / B — историческая запись, аудит не запускать повторно.' ,
'Снимок-история. Не редактировать — новые аудиты в новые файлы.' ,
[ ] , [ ] , [ ]
) ,
mem _audit _c : nd (
'Memory-файл audit_C_pending — аудит C, полностью реализован 07.05 (4 коммита).' ,
'При вопросах про аудит C — историческая запись, не запускать повторно.' ,
'Снимок-история. Детали — реестр §13.10, CHANGELOG §Y.' ,
[ ] , [ ] , [ ]
) ,
mem _suppliercrm : nd (
'Memory-файл supplier_crm — бизнес-модель поставщика лидов crm.bp-gr.ru: B1/B2/B3 = платформы-источники, проекты = каналы, сделки = лиды, 14 статусов.' ,
'При работе с интеграцией поставщика — для доменной модели.' ,
'Доменное описание, синхронизировано со схемой Лидерры.' ,
[ ] , [ ] , [ ]
) ,
mem _audit12 : nd (
'Memory-файл full_audit_2026-05-12 — аудит портала 12.05 + post-audit + закрытия Q.DEFER.003/004.' ,
'При вопросах про аудит 12.05 и его последствия.' ,
'Снимок-история. Содержит уроки про axe-core race-condition и mis-attribution квирка 72.' ,
[ ] , [ ] , [ ]
) ,
mem _audit14 : nd (
'Memory-файл full_audit_2026-05-14 — аудит портала #3 (14 фаз, 26 находок, вердикт зелёный).' ,
'При вопросах про аудит #3 от 14.05.' ,
'Снимок-история. Не редактировать при последующих аудитах.' ,
[ ] , [ ] , [ ]
) ,
mem _sprint1 : nd (
'Memory-файл sprint1_p0_closure — закрытие 5 P0 UI-находок аудита (DealsView, Kanban DnD, BulkActionsBar, Admin-экраны).' ,
'При вопросах про Sprint 1 / P0-фиксы портала.' ,
'Снимок-история спринта. 10 атомарных коммитов.' ,
[ ] , [ ] , [ ]
) ,
mem _sprint2 : nd (
'Memory-файл sprint2_p1_progress — Sprint 2 P1 wave 1: планы A (Auth) / B (Settings) / C (Billing) — закрыты и запушены.' ,
'При вопросах про Sprint 2 / P1-фиксы.' ,
'Снимок-история. Содержит коррекцию: SyncSupplierProjectsJobTest — реальный баг времени, не квирк 72.' ,
[ ] , [ ] , [ ]
) ,
mem _sprint3 : nd (
'Memory-файл sprint3_progress — Sprint 3 (P1 wave 2): под-планы 3A-3F, 3A-3D закрыты и запушены, 3E-3F в ожидании.' ,
'При вопросах про Sprint 3 / P1 wave 2.' ,
'Снимок-история, обновляется по ходу спринта.' ,
[ ] , [ ] , [ ]
) ,
2026-05-13 17:05:59 +03:00
} ;
2026-05-14 13:11:12 +03:00
// ════════════════════════════════════════════════════
// SECTION 3.5: EDGE DETAILS (iter2 §5)
// ════════════════════════════════════════════════════
const edgeKey = ( from , to ) => from + '->' + to ;
const EDGE _DETAILS = {
// ── ПРАВИЛА — иерархия ──────────────────────────
'pravila->claude_md' : { type : 'подчиняет' , when : 'всегда — CLAUDE.md уровень ниже Pravila' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §1 (уровень 1→2a)' } ,
'pravila->psr_v1' : { type : 'подчиняет' , when : 'всегда — PSR_v1 уровень 3 ниже Pravila' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §1 (уровень 1→3)' } ,
'claude_md->tooling' : { type : 'документирует' , when : 'при правке реестра инструментов' , transfers : 'документация' , mandatory : 'обязательно' , rule : 'CLAUDE.md §0, §3 (ссылка на Прил. Н)' } ,
2026-05-16 13:44:14 +03:00
'pravila->superpowers' : { type : 'подчиняет' , when : 'задача попадает под карту §12.2 (14 типов)' , transfers : 'контроль' , mandatory : 'hard-block' , rule : 'Pravila §12 (hard-rule уровня 0; скил первым, §9 не применяется)' } ,
2026-05-14 13:11:12 +03:00
// ── PSR_v1 координирует плагины ─────────────────
'psr_v1->superpowers' : { type : 'координирует' , when : 'paired-stack: процесс/решатель' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'PSR_v1 R5 (paired stack ядро)' } ,
'psr_v1->fd_plugin' : { type : 'координирует' , when : 'paired-stack: процесс/решатель' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'PSR_v1 R5 (paired stack ядро)' } ,
2026-05-14 17:15:39 +03:00
'psr_v1->upm' : { type : 'координирует' , when : 'вне основных фаз — активация через процедуру R14.3' , transfers : 'контроль' , mandatory : 'опционально' , rule : 'PSR_v1 R10.1, R11.5, R14.3' } ,
'psr_v1->mcp_21st' : { type : 'координирует' , when : 'вне основных фаз — активация через процедуру R14.4' , transfers : 'контроль' , mandatory : 'опционально' , rule : 'PSR_v1 R10.1, R14.4' } ,
2026-05-14 13:11:12 +03:00
'psr_v1->claude_md_mgmt' : { type : 'координирует' , when : 'инфраструктурный плагин для CLAUDE.md edits' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'PSR_v1 R10.1 блок 1' } ,
// ── CLAUDE.md — документирует ──────────────────
'claude_md->mcp_boost' : { type : 'документирует' , when : 'фаза 1+ Laravel SQL/Eloquent/docs' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'CLAUDE.md §3.2 #10' } ,
2026-05-14 17:15:39 +03:00
'claude_md->mcp_sentry' : { type : 'документирует' , when : 'вне основных фаз — для отладки во время работы, ждёт Б-1' , transfers : 'документация' , mandatory : 'опционально' , rule : 'CLAUDE.md §3.3 #34' } ,
'claude_md->mcp_redis' : { type : 'документирует' , when : 'вне основных фаз — Memurai только на чтение' , transfers : 'документация' , mandatory : 'опционально' , rule : 'CLAUDE.md §3.3 #35' } ,
2026-05-14 13:11:12 +03:00
'claude_md->claude_md_mgmt' : { type : 'документирует' , when : 'единственный канал правок CLAUDE.md' , transfers : 'документация' , mandatory : 'hard-block' , rule : 'CLAUDE.md §5 п.10' } ,
'claude_md->ag_pest' : { type : 'документирует' , when : 'агент для Pest TDD задач' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'CLAUDE.md §3 (агенты)' } ,
'claude_md->ag_rls' : { type : 'документирует' , when : 'агент для RLS-аудита и smoke-тестов' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'CLAUDE.md §3 (агенты)' } ,
// ── HOOKS — триггеры ────────────────────────────
'hk_pre_claude->claude_md' : { type : 'триггерит' , when : 'PreToolUse Edit/Write CLAUDE.md' , transfers : 'проверка' , mandatory : 'hard-block' , rule : 'settings.json hooks (claude-md-management канал)' } ,
'hk_post_md->lh_mdlint' : { type : 'триггерит' , when : 'PostToolUse Edit *.md → markdownlint --fix' , transfers : 'триггер' , mandatory : 'обязательно' , rule : 'settings.json hooks + lefthook' } ,
'hk_post_schema->claude_md' : { type : 'триггерит' , when : 'PostToolUse Edit db/schema.sql → напоминание sync' , transfers : 'триггер' , mandatory : 'обязательно' , rule : 'settings.json hooks (§4.2 правил Claude)' } ,
'hk_session->mem_user' : { type : 'триггерит' , when : 'SessionStart инжектит memory-блок' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'settings.json hooks (memory inject)' } ,
'hk_session->mem_env' : { type : 'триггерит' , when : 'SessionStart инжектит memory-блок' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'settings.json hooks (memory inject)' } ,
'hk_session->mem_sp' : { type : 'триггерит' , when : 'SessionStart инжектит memory-блок' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'settings.json hooks (memory inject)' } ,
'hk_session->mem_plugins' : { type : 'триггерит' , when : 'SessionStart инжектит memory-блок' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'settings.json hooks (memory inject)' } ,
'hk_session->mem_state' : { type : 'триггерит' , when : 'SessionStart инжектит memory-блок' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'settings.json hooks (memory inject)' } ,
// ── SUPERPOWERS — содержит skills ───────────────
'superpowers->sk_brainstorm' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_tdd' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_debug' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_wplans' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_eplans' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_verify' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_parallel' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_worktree' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_pr' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_subagent' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_wskills' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_spreview' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_coderev' : { type : 'содержит' , when : 'plugin содержит skill' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12.2 (карта 14 типов)' } ,
'superpowers->sk_elements' : { type : 'содержит' , when : 'plugin содержит skill (using-superpowers)' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12 (старт сессии)' } ,
// ── SKILLS — последовательности ─────────────────
'sk_brainstorm->sk_wplans' : { type : 'запускает' , when : 'после brainstorming → writing-plans' , transfers : 'триггер' , mandatory : 'рекомендуется' , rule : 'PSR_v1 R5 (paired-stack flow)' } ,
'sk_wplans->sk_eplans' : { type : 'запускает' , when : 'plan готов → executing-plans' , transfers : 'триггер' , mandatory : 'рекомендуется' , rule : 'Superpowers process chain' } ,
'sk_wplans->sk_subagent' : { type : 'альтернатива' , when : 'если в текущей сессии — subagent-driven-development вместо executing' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'Superpowers process chain (in-session alt)' } ,
'sk_subagent->ag_explore' : { type : 'запускает' , when : 'параллельный поиск/исследование' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'subagent-driven-development (Task agent)' } ,
'sk_subagent->ag_general' : { type : 'запускает' , when : 'general-purpose subagent для независимых задач' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'subagent-driven-development (Task agent)' } ,
'sk_subagent->ag_plan' : { type : 'запускает' , when : 'агент планирования больших задач' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'subagent-driven-development (Task agent)' } ,
'sk_parallel->sk_worktree' : { type : 'запускает' , when : 'parallel agents требует изоляцию worktree' , transfers : 'триггер' , mandatory : 'рекомендуется' , rule : 'PSR_v1 R5 (dispatching-parallel-agents)' } ,
'sk_rls->tooling' : { type : 'читает' , when : 'RLS-аудит сверяется с реестром инструментов' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'Tooling Прил. Н (squawk/Boost)' } ,
'sk_rls->mcp_boost' : { type : 'запускает' , when : 'RLS-смоук читает БД через Boost MCP' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'CLAUDE.md §3.2 #10 (Boost)' } ,
'sk_qitem->claude_md_mgmt' : { type : 'запускает' , when : 'правки реестра открытых вопросов → бамп CLAUDE.md' , transfers : 'триггер' , mandatory : 'обязательно' , rule : 'CLAUDE.md §5 п.10 (единственный канал)' } ,
'claude_md_mgmt->claude_md' : { type : 'запускает' , when : 'skills claude-md-improver / revise-claude-md правят файл' , transfers : 'контроль' , mandatory : 'hard-block' , rule : 'CLAUDE.md §5 п.10' } ,
// ── HOOKIFY — генерирует hooks ──────────────────
'ag_hookify->hookify_plugin' : { type : 'запускает' , when : 'агент hookify создаёт правила через plugin' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'hookify plugin docs' } ,
'hookify_plugin->hk_economy' : { type : 'содержит' , when : 'hookify сгенерировал economy hook' , transfers : 'контроль' , mandatory : 'обязательно' , rule : 'Pravila §12 economy hook architecture' } ,
// ── АГЕНТЫ → MCP/инструменты ────────────────────
'ag_rls->mcp_boost' : { type : 'запускает' , when : 'RLS-аудит через Boost MCP' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'CLAUDE.md §3.2 #10' } ,
'ag_guide->mcp_gh' : { type : 'запускает' , when : 'агент гайдов работает с GitHub issues/PR' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'CLAUDE.md §3.1 #3 (GitHub MCP)' } ,
// ── LEFTHOOK jobs ───────────────────────────────
'lh_gitleaks->mem_plugins' : { type : 'документирует' , when : 'gitleaks-job описан в memory о плагинах' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'Tooling Прил. Н §8 (lefthook.yml)' } ,
'lh_larastan->mcp_boost' : { type : 'запускает' , when : 'Larastan job использует Boost для контекста' , transfers : 'проверка' , mandatory : 'обязательно' , rule : 'lefthook.yml job + Boost' } ,
'lh_squawk->tooling' : { type : 'читает' , when : 'squawk-конфиг описан в реестре инструментов' , transfers : 'документация' , mandatory : 'обязательно' , rule : 'Tooling Прил. Н #15' } ,
'lh_gitleaks2->lh_gitleaks' : { type : 'альтернатива' , when : 'второй gitleaks-job (pre-push) вариант pre-commit' , transfers : 'проверка' , mandatory : 'опционально' , rule : 'lefthook.yml (дубль pre-push)' } ,
'lh_lychee->claude_md' : { type : 'читает' , when : 'lychee валидирует ссылки в CLAUDE.md и docs' , transfers : 'проверка' , mandatory : 'обязательно' , rule : 'CLAUDE.md §4 + lefthook' } ,
// ── MEMORY → плагины/правила ────────────────────
'mem_env->ag_pest' : { type : 'документирует' , when : 'memory о квирках окружения нужен для Pest agent' , transfers : 'данные' , mandatory : 'рекомендуется' , rule : 'memory/feedback_environment.md' } ,
'mem_plugins->psr_v1' : { type : 'документирует' , when : 'memory о парном стеке отражает PSR_v1' , transfers : 'данные' , mandatory : 'рекомендуется' , rule : 'memory/feedback_plugin_paired_stack.md' } ,
'mem_archive->claude_md' : { type : 'документирует' , when : 'memory об архиве содержит refs на CLAUDE.md' , transfers : 'данные' , mandatory : 'рекомендуется' , rule : 'memory/reference_archive.md' } ,
// ── MCP → агенты/skills ─────────────────────────
'mcp_pw->hk_session' : { type : 'триггерит' , when : 'Playwright MCP вызывается из SessionStart hook' , transfers : 'триггер' , mandatory : 'опционально' , rule : 'settings.json hooks + Playwright' } ,
'mcp_gh->sk_pr' : { type : 'запускает' , when : 'finishing-a-development-branch использует gh-команды' , transfers : 'триггер' , mandatory : 'обязательно' , rule : 'Superpowers finishing-a-development-branch' } ,
'mcp_boost->ag_rls' : { type : 'запускает' , when : 'Boost MCP отдаёт данные RLS-агенту' , transfers : 'данные' , mandatory : 'обязательно' , rule : 'CLAUDE.md §3.2 #10' } ,
// ── КОНФЛИКТЫ (8 рёбер; 3 из них имеют ту же пару from/to, что и обычные — здесь объединены под одним ключом) ─
2026-05-16 08:48:30 +03:00
'sk_rls->ag_rls' : { type : 'конфликт' , when : 'граница задана: скил — по таблице, агент — по diff/ветке/PR' , transfers : 'coverage' , mandatory : 'опционально' , rule : 'секции «Граница…» в SKILL.md + rls-reviewer.md (spec 2026-05-16)' } ,
2026-05-14 13:11:12 +03:00
'hookify_plugin->hk_pre_claude' : { type : 'конфликт' , when : 'hookify plugin генерирует hook — двойное owner-ship vs settings.json' , transfers : 'coverage' , mandatory : 'опционально' , rule : 'нет регламента (plugin vs settings.json)' } ,
'mcp_pw->sk_parallel' : { type : 'конфликт' , when : 'Playwright и parallel-agents оба требуют изоляцию' , transfers : 'coverage' , mandatory : 'опционально' , rule : 'нет регламента (изоляция worktree vs MCP)' } ,
'ag_pest->mcp_redis' : { type : 'конфликт' , when : 'Pest --parallel race на Redis cache (quirk 72/77)' , transfers : 'coverage' , mandatory : 'опционально' , rule : 'CLAUDE.md §3.3 #35 (Redis MCP) — race остаётся вне регламента' } ,
'psr_v1->claude_md' : { type : 'конфликт' , when : 'PSR_v1 уровень 3 vs CLAUDE.md 2a — приоритет CLAUDE.md' , transfers : 'контроль' , mandatory : 'hard-block' , rule : 'CLAUDE.md §1 (priority chain)' } ,
'upm->fd_plugin' : { type : 'конфликт' , when : 'UPM и FD оба претендуют на UI-решения' , transfers : 'coverage' , mandatory : 'hard-block' , rule : 'PSR_v1 R14.5 (не параллельно)' } ,
'mcp_21st->fd_plugin' : { type : 'конфликт' , when : '21st Magic и FD оба генераторы UI' , transfers : 'coverage' , mandatory : 'hard-block' , rule : 'PSR_v1 R14.5 (не параллельно)' } ,
2026-05-16 13:44:14 +03:00
'hk_economy->superpowers' : { type : 'конфликт' , when : 'economy-режим теоретически может «сэкономить» вызов скила — §12 (hard-rule уровня 0) economy не отменяет' , transfers : 'контроль' , mandatory : 'hard-block' , rule : 'Pravila §12.4 (только явный «не используй»)' } ,
2026-05-15 15:34:39 +03:00
2026-05-16 13:44:14 +03:00
// ── RUFLO ОРКЕСТРАТОР — реколлаж (iter5 2026-05-15 + нормативный sync 2026-05-16) ──
'ruflo_queen->ruflo_workers' : { type : 'подчиняет' , when : 'hive-mind активен, но рой ни разу не получал задач' , transfers : 'контроль' , mandatory : 'опционально (рой idle)' , rule : 'Tooling §4.10 (ruflo как advisory-подсистема)' } ,
2026-05-16 06:48:46 +03:00
'ruflo_queen->ruflo_agents_catalog' : { type : 'артефакт' , when : '`ruflo init` высыпал каталог в .claude/agents/' , transfers : 'ничего (файлы лежат)' , mandatory : 'не задействовано' , rule : 'артефакт установки ruflo' } ,
'ruflo_queen->ruflo_commands' : { type : 'артефакт' , when : '`ruflo init` высыпал команды в .claude/commands/' , transfers : 'ничего (файлы лежат)' , mandatory : 'не задействовано' , rule : 'артефакт установки ruflo' } ,
'ruflo_queen->ruflo_plugins' : { type : 'артефакт' , when : 'плагины ruflo — 0 установлено из ~20 в реестре' , transfers : 'ничего' , mandatory : 'не задействовано' , rule : 'артефакт установки ruflo' } ,
'ruflo_mcp->ruflo_memory' : { type : 'читает' , when : 'MCP-инструменты memory_* обращаются к хранилищу' , transfers : 'данные' , mandatory : 'опционально' , rule : 'Tooling §4.10' } ,
'ruflo_recall_hook->ruflo_memory' : { type : 'читает' , when : 'recall-хук на каждый промпт запускает `ruflo memory search`' , transfers : 'данные' , mandatory : '«мягко» (fail-open)' , rule : '.claude/settings.json (UserPromptSubmit)' } ,
'ruflo_daemon->ruflo_memory' : { type : 'читает' , when : 'воркер consolidate демона обращается к памяти' , transfers : 'данные' , mandatory : 'опционально' , rule : '.claude-flow daemon' } ,
'ruflo_mcp->ruflo_queen' : { type : 'экспонирует' , when : 'MCP-сервер отдаёт инструменты hive-mind_*/agent_*/swarm_*' , transfers : 'инструменты' , mandatory : 'опционально' , rule : 'Tooling §4.10' } ,
2026-05-16 13:44:14 +03:00
'ruflo_queen->pravila' : { type : 'конфликт' , when : 'реколлаж 16.05.2026 привёл нормативку к рантайму — конфликт «декларация ≠ рантайм» закрыт' , transfers : 'coverage' , mandatory : 'закрыто' , rule : 'Закрыто реколлажем: Pravila v1.16 / CLAUDE.md v2.2 / PSR_v1 v3.2 / Tooling v2.2' } ,
'pravila->ruflo_queen' : { type : 'триггерит' , when : 'триггер-слова queen/королева в промпте — задача маршрутизируется через ruflo Queen' , transfers : 'триггер' , mandatory : 'hard-rule' , rule : 'Pravila §14 (queen/королева → hive-mind spawn)' } ,
'claude_md->ruflo_queen' : { type : 'документирует' , when : 'CLAUDE.md §3.5 описывает ruflo как advisory/automation-подсистему' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'CLAUDE.md §3.5' } ,
'psr_v1->ruflo_queen' : { type : 'документирует' , when : 'PSR_v1 §14 — cross-ref на queen-триггер Pravila §14' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'PSR_v1 §14' } ,
'tooling->ruflo_queen' : { type : 'документирует' , when : 'Tooling §4.10 — реестр ruflo как advisory/automation-подсистемы' , transfers : 'документация' , mandatory : 'рекомендуется' , rule : 'Tooling §4.10' } ,
2026-05-16 06:48:46 +03:00
'mem_ruflo->ruflo_queen' : { type : 'документирует' , when : 'memory-файл хранит историю ruflo-интеграции' , transfers : 'данные' , mandatory : 'рекомендуется' , rule : 'memory/project_ruflo_integration.md' } ,
'ruflo_memory->mem_state' : { type : 'конфликт' , when : 'два хранилища памяти не синхронизированы; память ruflo почти пуста' , transfers : 'coverage' , mandatory : 'опционально' , rule : 'нет регламента синхронизации (alpha-баг HNSW #1122)' } ,
'ruflo_daemon->ag_pest' : { type : 'конфликт' , when : 'daemon worker-jitter усиливает частоту Pest-квирка 72' , transfers : 'coverage' , mandatory : 'опционально' , rule : 'memory feedback_environment квирк #93' } ,
2026-05-14 13:11:12 +03:00
} ;
2026-05-16 09:30:49 +03:00
// ════════════════════════════════════════════════════
// SECTION 3.6: NODE META (iter6 — даты, использование, дубли)
// ════════════════════════════════════════════════════
// Данные — фактический снимок: даты из git/changelog/mtime, счётчик uses —
// из разбора транскриптов сессий Claude Code за окно META_WINDOW.
// Методика и воспроизводимость — план iter6, Приложение А.
const META _SNAPSHOT = '16.05.2026' ; // дата генерации значений
const META _WINDOW = '09– 16.05.2026' ; // окно подсчёта использования (7 дней)
// uses: number — измеримый узел (0 = реально простаивал); null — измерить нельзя
// (узел-правило / плагин-обёртка / автономный демон / пассивное хранилище) → «нет данных».
// usesSrc: 'скил' | 'агент' | 'MCP' | 'хук' | 'memory-чтение' | 'коммиты' | 'инспекция' | '—'
const NODE _META = {
// ── ПРАВИЛА (4) — узлы-правила, напрямую не вызываются ──
2026-05-16 13:44:14 +03:00
pravila : { since : '06.05.2026' , changed : '16.05.2026' , uses : null , usesSrc : '—' } ,
claude _md : { since : '06.05.2026' , changed : '16.05.2026' , uses : null , usesSrc : '—' } ,
psr _v1 : { since : '09.05.2026' , changed : '16.05.2026' , uses : null , usesSrc : '—' } ,
tooling : { since : '06.05.2026' , changed : '16.05.2026' , uses : null , usesSrc : '—' } ,
2026-05-16 09:30:49 +03:00
// ── ПЛАГИНЫ (5) ──
superpowers : { since : '09.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
fd _plugin : { since : '10.05.2026' , changed : '—' , uses : 1 , usesSrc : 'скил' } ,
upm : { since : '10.05.2026' , changed : '—' , uses : 0 , usesSrc : 'скил' } ,
claude _md _mgmt : { since : '10.05.2026' , changed : '—' , uses : 15 , usesSrc : 'скил' } ,
hookify _plugin : { since : '—' , changed : '—' , uses : null , usesSrc : '—' } ,
// ── СКИЛЫ SUPERPOWERS (14) — связка подключена 09.05.2026 ──
sk _brainstorm : { since : '09.05.2026' , changed : '—' , uses : 44 , usesSrc : 'скил' } ,
sk _wplans : { since : '09.05.2026' , changed : '—' , uses : 54 , usesSrc : 'скил' } ,
sk _eplans : { since : '09.05.2026' , changed : '—' , uses : 11 , usesSrc : 'скил' } ,
sk _subagent : { since : '09.05.2026' , changed : '—' , uses : 33 , usesSrc : 'скил' } ,
sk _tdd : { since : '09.05.2026' , changed : '—' , uses : 2 , usesSrc : 'скил' } ,
sk _verify : { since : '09.05.2026' , changed : '—' , uses : 25 , usesSrc : 'скил' } ,
sk _debug : { since : '09.05.2026' , changed : '—' , uses : 10 , usesSrc : 'скил' } ,
sk _parallel : { since : '09.05.2026' , changed : '—' , uses : 3 , usesSrc : 'скил' } ,
sk _worktree : { since : '09.05.2026' , changed : '—' , uses : 3 , usesSrc : 'скил' } ,
sk _pr : { since : '09.05.2026' , changed : '—' , uses : 10 , usesSrc : 'скил' } ,
sk _coderev : { since : '09.05.2026' , changed : '—' , uses : 1 , usesSrc : 'скил' } ,
sk _spreview : { since : '09.05.2026' , changed : '—' , uses : 0 , usesSrc : 'скил' } ,
sk _wskills : { since : '09.05.2026' , changed : '—' , uses : 0 , usesSrc : 'скил' } ,
sk _elements : { since : '09.05.2026' , changed : '—' , uses : 0 , usesSrc : 'скил' } ,
// ── СКИЛЫ ПРОЕКТА (2) — файлы добавлены в репозиторий 13.05.2026 ──
sk _rls : { since : '13.05.2026' , changed : '—' , uses : 0 , usesSrc : 'скил' } ,
sk _qitem : { since : '13.05.2026' , changed : '—' , uses : 1 , usesSrc : 'скил' } ,
// ── ХУКИ (5) ──
hk _session : { since : '—' , changed : '—' , uses : 67 , usesSrc : 'хук' } ,
hk _economy : { since : '10.05.2026' , changed : '—' , uses : 276 , usesSrc : 'хук' } ,
hk _pre _claude : { since : '13.05.2026' , changed : '—' , uses : 249 , usesSrc : 'хук' } ,
hk _post _md : { since : '06.05.2026' , changed : '—' , uses : 1334 , usesSrc : 'хук' } ,
hk _post _schema : { since : '13.05.2026' , changed : '—' , uses : 22 , usesSrc : 'хук' } ,
// ── АГЕНТЫ (11) ──
ag _explore : { since : 'встроено в Claude Code' , changed : '—' , uses : 26 , usesSrc : 'агент' } ,
ag _general : { since : 'встроено в Claude Code' , changed : '—' , uses : 512 , usesSrc : 'агент' } ,
ag _plan : { since : 'встроено в Claude Code' , changed : '—' , uses : 0 , usesSrc : 'агент' } ,
ag _pest : { since : '13.05.2026' , changed : '—' , uses : 2 , usesSrc : 'агент' } ,
ag _guide : { since : 'встроено в Claude Code' , changed : '—' , uses : 4 , usesSrc : 'агент' } ,
ag _statusline : { since : 'встроено в Claude Code' , changed : '—' , uses : 0 , usesSrc : 'агент' } ,
ag _hookify : { since : '—' , changed : '—' , uses : 0 , usesSrc : 'агент' } ,
ag _pcreator : { since : '—' , changed : '—' , uses : 0 , usesSrc : 'агент' } ,
ag _pvalid : { since : '—' , changed : '—' , uses : 0 , usesSrc : 'агент' } ,
ag _skreview : { since : '—' , changed : '—' , uses : 0 , usesSrc : 'агент' } ,
ag _rls : { since : '13.05.2026' , changed : '—' , uses : 2 , usesSrc : 'агент' } ,
// ── MCP-СЕРВЕРЫ (7) ──
mcp _21st : { since : '10.05.2026' , changed : '—' , uses : 0 , usesSrc : 'MCP' } ,
mcp _pw : { since : '06.05.2026' , changed : '—' , uses : 706 , usesSrc : 'MCP' } ,
mcp _gh : { since : '06.05.2026' , changed : '—' , uses : 0 , usesSrc : 'MCP' } ,
mcp _boost : { since : '08.05.2026' , changed : '—' , uses : 73 , usesSrc : 'MCP' } ,
mcp _redis : { since : '13.05.2026' , changed : '—' , uses : 0 , usesSrc : 'MCP' } ,
mcp _sentry : { since : '13.05.2026' , changed : '—' , uses : 0 , usesSrc : 'MCP' } ,
mcp _semgrep : { since : '10.05.2026' , changed : '—' , uses : 0 , usesSrc : 'MCP' } ,
// ── LEFTHOOK JOBS (10) — uses ≈ число коммитов в окне, фильтр по типу файла ──
lh _mdlint : { since : '06.05.2026' , changed : '—' , uses : 232 , usesSrc : 'коммиты' } ,
lh _cspell : { since : '06.05.2026' , changed : '—' , uses : 232 , usesSrc : 'коммиты' } ,
lh _stylelint : { since : '06.05.2026' , changed : '—' , uses : 43 , usesSrc : 'коммиты' } ,
lh _eslint : { since : '08.05.2026' , changed : '—' , uses : 120 , usesSrc : 'коммиты' } ,
lh _lychee : { since : '06.05.2026' , changed : '—' , uses : 56 , usesSrc : 'коммиты' } ,
lh _gitleaks : { since : '06.05.2026' , changed : '—' , uses : 514 , usesSrc : 'коммиты' } ,
lh _gitleaks2 : { since : '06.05.2026' , changed : '—' , uses : 56 , usesSrc : 'коммиты' } ,
lh _pint : { since : '08.05.2026' , changed : '—' , uses : 134 , usesSrc : 'коммиты' } ,
lh _larastan : { since : '08.05.2026' , changed : '—' , uses : 134 , usesSrc : 'коммиты' } ,
lh _squawk : { since : '08.05.2026' , changed : '—' , uses : 19 , usesSrc : 'коммиты' } ,
// ── MEMORY FILES (15) — uses = вызовы Read; changed = mtime файла ──
mem _user : { since : '07.05.2026' , changed : '08.05.2026' , uses : 0 , usesSrc : 'memory-чтение' } ,
mem _comm : { since : '07.05.2026' , changed : '08.05.2026' , uses : 0 , usesSrc : 'memory-чтение' } ,
mem _env : { since : '07.05.2026' , changed : '15.05.2026' , uses : 41 , usesSrc : 'memory-чтение' } ,
mem _sp : { since : '09.05.2026' , changed : '10.05.2026' , uses : 1 , usesSrc : 'memory-чтение' } ,
mem _plugins : { since : '09.05.2026' , changed : '13.05.2026' , uses : 9 , usesSrc : 'memory-чтение' } ,
mem _handoff : { since : '08.05.2026' , changed : '—' , uses : 0 , usesSrc : 'memory-чтение' } ,
mem _redesign : { since : '12.05.2026' , changed : '—' , uses : 0 , usesSrc : 'memory-чтение' } ,
mem _devindices : { since : '12.05.2026' , changed : '—' , uses : 1 , usesSrc : 'memory-чтение' } ,
mem _phase1 : { since : '08.05.2026' , changed : '—' , uses : 1 , usesSrc : 'memory-чтение' } ,
mem _state : { since : '07.05.2026' , changed : '15.05.2026' , uses : 73 , usesSrc : 'memory-чтение' } ,
mem _brain : { since : '11.05.2026' , changed : '—' , uses : 1 , usesSrc : 'memory-чтение' } ,
mem _supplier : { since : '10.05.2026' , changed : '12.05.2026' , uses : 13 , usesSrc : 'memory-чтение' } ,
mem _audit : { since : '13.05.2026' , changed : '—' , uses : 3 , usesSrc : 'memory-чтение' } ,
mem _archive : { since : '07.05.2026' , changed : '15.05.2026' , uses : 21 , usesSrc : 'memory-чтение' } ,
mem _github : { since : '07.05.2026' , changed : '15.05.2026' , uses : 33 , usesSrc : 'memory-чтение' } ,
// ── RUFLO ОРКЕСТРАТОР (9) — все внедрены big-bang'ом 15.05.2026 ──
2026-05-16 13:44:14 +03:00
ruflo _queen : { since : '15.05.2026' , changed : '16.05.2026' , uses : 0 , usesSrc : 'инспекция' } ,
2026-05-16 09:30:49 +03:00
ruflo _plugins : { since : '15.05.2026' , changed : '—' , uses : 0 , usesSrc : 'инспекция' } ,
ruflo _workers : { since : '15.05.2026' , changed : '—' , uses : 0 , usesSrc : 'инспекция' } ,
ruflo _agents _catalog : { since : '15.05.2026' , changed : '—' , uses : 0 , usesSrc : 'инспекция' ,
dupNote : '100 определений агентов дублируют реестр агентов; каталог буквально содержит 2 проектных агента' } ,
ruflo _commands : { since : '15.05.2026' , changed : '—' , uses : 0 , usesSrc : 'инспекция' ,
dupNote : '88 slash-команд дублируют роль скилов — именованные вызываемые процедуры; команды инертны' } ,
ruflo _daemon : { since : '15.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
ruflo _memory : { since : '15.05.2026' , changed : '—' , uses : null , usesSrc : '—' ,
dupNote : 'дублирует роль 16 memory-файлов проекта — постоянная память между сессиями; уже ⚫-конфликт с project_state' } ,
ruflo _mcp : { since : '15.05.2026' , changed : '—' , uses : 36 , usesSrc : 'MCP' } ,
ruflo _recall _hook : { since : '15.05.2026' , changed : '—' , uses : 220 , usesSrc : 'хук' } ,
// ── MEMORY +1 (артефакт ruflo big-bang) ──
mem _ruflo : { since : '15.05.2026' , changed : '16.05.2026' , uses : 18 , usesSrc : 'memory-чтение' } ,
2026-05-16 15:39:47 +03:00
// ── АУДИТ-АКТУАЛИЗАЦИЯ 16.05.2026 — узлы добавлены по полному аудиту карты ──
// uses новых узлов по транскриптам не измерялись (null = нет данных).
skill _creator : { since : '11.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
claude _setup : { since : '11.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
plugin _dev : { since : '—' , changed : '—' , uses : null , usesSrc : '—' } ,
context7 : { since : '—' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _self _check : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _skill _marker : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _skill _check : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _state _guard : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _postcompact : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _verifier : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
hk _ruflo _queen : { since : '15.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
sk _regression : { since : '15.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _audit _b : { since : '08.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _audit _c : { since : '07.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _suppliercrm : { since : '10.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _audit12 : { since : '12.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _audit14 : { since : '14.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _sprint1 : { since : '15.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _sprint2 : { since : '15.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mem _sprint3 : { since : '16.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
2026-05-17 04:46:32 +03:00
// ── A6 ARCHITECTURE-TOOLING 17.05.2026 ──
adr _kit : { since : '17.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
arch _patterns : { since : '17.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
mermaid _skill : { since : '17.05.2026' , changed : '—' , uses : null , usesSrc : '—' } ,
2026-05-16 09:30:49 +03:00
} ;
// Явные парные дубли (Фича 3) — попадают в кнопку «⧉ Дубли».
const DUPLICATE _GROUPS = [
{ id : 'D1' , pct : 90 , members : [ 'hk_post_md' , 'lh_mdlint' ] ,
reason : 'оба запускают markdownlint --fix на .md — разница только в триггере (после правки в сессии против при коммите)' } ,
{ id : 'D2' , pct : 85 , members : [ 'lh_gitleaks' , 'lh_gitleaks2' ] ,
reason : 'оба — скан секретов gitleaks; pre-commit проверяет staged-файлы, pre-push — всю историю (надмножество)' } ,
{ id : 'D3' , pct : 85 , members : [ 'sk_rls' , 'ag_rls' ] ,
reason : 'оба — 7-пунктовая проверка RLS-соответствия; уже отмечено 🔴-конфликтом «нет регламента кто когда»' } ,
{ id : 'D4' , pct : 80 , members : [ 'sk_eplans' , 'sk_subagent' ] ,
reason : 'оба исполняют план writing-plans пошагово; разница — параллельная сессия против суб-агентов в текущей' } ,
{ id : 'D5' , pct : 80 , members : [ 'sk_wplans' , 'ag_plan' ] ,
reason : 'оба производят план задачи; скил writing-plans — inline с полным кодом, агент Plan — архитектурный набросок READ-ONLY' } ,
{ id : 'D7' , pct : 80 , members : [ 'ruflo_recall_hook' , 'hk_session' ] ,
reason : 'оба инжектят память в контекст Клода; recall-хук — на каждый промпт из базы ruflo, SessionStart — при старте из .md-файлов' } ,
] ;
// Производный индекс: nodeId -> { partner, pct, reason } — для рендера легенды и подсветки.
const DUP _BY _NODE = new Map ( ) ;
DUPLICATE _GROUPS . forEach ( g => g . members . forEach ( m => {
const partner = g . members . find ( x => x !== m ) ;
DUP _BY _NODE . set ( m , { partner , pct : g . pct , reason : g . reason } ) ;
} ) ) ;
const DUP _NODE _SET = new Set ( DUP _BY _NODE . keys ( ) ) ; // 12 узлов-членов парных дублей
2026-05-16 15:03:48 +03:00
// ════════════════════════════════════════════════════
// SECTION 3.5: ФУНКЦИОНАЛЬНЫЕ РАЗДЕЛЫ (функциональная квалификация)
// ════════════════════════════════════════════════════
// Разделы деятельности Лидерры. Каждый узел карты отнесён к одному разделу
// (NODE_SECTION). Часть разделов пока пустая — это бизнес-домены, под которые
// в карте dev-автоматики ещё нет узлов. Основа будущего «мозга»: 1 раздел =
// 1 playbook «как и что делать».
const SECTION _BUCKETS = [
{ id : 'A' , label : 'Технические и продуктовые' } ,
{ id : 'B' , label : 'Коммуникации' } ,
{ id : 'C' , label : 'Бизнес и операции' } ,
{ id : 'D' , label : 'Право и комплаенс' } ,
{ id : 'E' , label : 'Мета и управление' } ,
] ;
const SECTIONS = [
{ id : 'A1' , bucket : 'A' , label : 'Программирование — backend' } ,
{ id : 'A2' , bucket : 'A' , label : 'Программирование — frontend' } ,
{ id : 'A3' , bucket : 'A' , label : 'Программирование — интеграции (API, вебхуки)' } ,
{ id : 'A4' , bucket : 'A' , label : 'Дизайн (UI/UX, графика, бренд)' } ,
{ id : 'A5' , bucket : 'A' , label : 'Тестирование, QA и отладка' } ,
{ id : 'A6' , bucket : 'A' , label : 'Архитектура систем' } ,
{ id : 'A7' , bucket : 'A' , label : 'DevOps, инфраструктура, деплой' } ,
{ id : 'A8' , bucket : 'A' , label : 'Информационная безопасность' } ,
{ id : 'A9' , bucket : 'A' , label : 'Работа с данными (БД, миграции, RLS)' } ,
{ id : 'A10' , bucket : 'A' , label : 'Аналитика и отчётность (BI)' } ,
{ id : 'A11' , bucket : 'A' , label : 'ML / AI-разработка' } ,
{ id : 'B1' , bucket : 'B' , label : 'Голосовое общение по телефону' } ,
{ id : 'B2' , bucket : 'B' , label : 'Мессенджеры' } ,
{ id : 'B3' , bucket : 'B' , label : 'Электронная почта' } ,
{ id : 'B4' , bucket : 'B' , label : 'SMS-рассылки' } ,
{ id : 'B5' , bucket : 'B' , label : 'Видеосвязь' } ,
{ id : 'B6' , bucket : 'B' , label : 'Чат на сайте / онлайн-консультант' } ,
{ id : 'B7' , bucket : 'B' , label : 'Социальные сети' } ,
{ id : 'B8' , bucket : 'B' , label : 'Push / in-app уведомления' } ,
{ id : 'C1' , bucket : 'C' , label : 'Маркетинг и лидогенерация' } ,
{ id : 'C2' , bucket : 'C' , label : 'Продажи' } ,
{ id : 'C3' , bucket : 'C' , label : 'Квалификация и обработка лидов' } ,
{ id : 'C4' , bucket : 'C' , label : 'Работа с поставщиками лидов' } ,
{ id : 'C5' , bucket : 'C' , label : 'Клиентский успех, поддержка, удержание' } ,
{ id : 'C6' , bucket : 'C' , label : 'Финансы — биллинг и тарификация' } ,
{ id : 'C7' , bucket : 'C' , label : 'Финансы — бухгалтерия и налоги' } ,
{ id : 'C8' , bucket : 'C' , label : 'HR и управление персоналом' } ,
{ id : 'C9' , bucket : 'C' , label : 'Управление проектами' } ,
{ id : 'C10' , bucket : 'C' , label : 'Бизнес-процессы (общее)' } ,
{ id : 'D1' , bucket : 'D' , label : 'Юриспруденция и договорная работа' } ,
{ id : 'D2' , bucket : 'D' , label : 'Защита ПДн (152-ФЗ, РКН)' } ,
{ id : 'D3' , bucket : 'D' , label : 'Аудит и управление рисками' } ,
{ id : 'E1' , bucket : 'E' , label : 'Мета — правила и нормативка' } ,
{ id : 'E2' , bucket : 'E' , label : 'Мета — оркестрация и автоматизация (Claude-воркфлоу)' } ,
{ id : 'E3' , bucket : 'E' , label : 'Документация' } ,
{ id : 'E4' , bucket : 'E' , label : 'Управление знаниями и память' } ,
{ id : 'E5' , bucket : 'E' , label : 'Стратегия и принятие решений' } ,
{ id : 'E6' , bucket : 'E' , label : 'Обучение и онбординг' } ,
{ id : 'E7' , bucket : 'E' , label : 'Исследования' } ,
2026-05-16 15:08:29 +03:00
{ id : 'E8' , bucket : 'E' , label : 'Самообучение Claude' } ,
2026-05-16 15:03:48 +03:00
] ;
2026-05-17 04:46:32 +03:00
// Узел -> раздел. Покрывает все 106 узлов карты.
2026-05-16 15:03:48 +03:00
const NODE _SECTION = {
// правила (4)
pravila : 'E1' , claude _md : 'E1' , psr _v1 : 'E1' , tooling : 'E1' ,
// плагины (5)
superpowers : 'E2' , fd _plugin : 'A4' , upm : 'A4' , claude _md _mgmt : 'E1' , hookify _plugin : 'E2' ,
// скилы superpowers (14)
sk _brainstorm : 'E5' , sk _wplans : 'E2' , sk _eplans : 'E2' , sk _subagent : 'E2' ,
sk _tdd : 'A5' , sk _verify : 'A5' , sk _debug : 'A5' , sk _parallel : 'E2' ,
sk _worktree : 'E2' , sk _pr : 'E2' , sk _coderev : 'A5' , sk _spreview : 'A5' ,
sk _wskills : 'E2' , sk _elements : 'E3' ,
// скилы проекта (2)
sk _rls : 'A9' , sk _qitem : 'E3' ,
// хуки (5)
hk _session : 'E4' , hk _economy : 'E2' , hk _pre _claude : 'E1' , hk _post _md : 'E3' , hk _post _schema : 'A9' ,
// агенты (11)
ag _explore : 'E2' , ag _general : 'E2' , ag _plan : 'E2' , ag _pest : 'A5' , ag _guide : 'E6' ,
ag _statusline : 'E2' , ag _hookify : 'E2' , ag _pcreator : 'E2' , ag _pvalid : 'E2' ,
ag _skreview : 'E2' , ag _rls : 'A9' ,
// MCP-серверы (7)
mcp _21st : 'A4' , mcp _pw : 'A5' , mcp _gh : 'A7' , mcp _boost : 'A1' ,
mcp _redis : 'A7' , mcp _sentry : 'A7' , mcp _semgrep : 'A8' ,
// lefthook jobs (10)
lh _mdlint : 'E3' , lh _cspell : 'E3' , lh _stylelint : 'A2' , lh _eslint : 'A2' ,
lh _lychee : 'E3' , lh _gitleaks : 'A8' , lh _gitleaks2 : 'A8' , lh _pint : 'A1' ,
lh _larastan : 'A1' , lh _squawk : 'A9' ,
// memory files (16)
mem _user : 'E4' , mem _comm : 'E4' , mem _env : 'E4' , mem _sp : 'E4' , mem _plugins : 'E4' ,
mem _handoff : 'E4' , mem _redesign : 'E4' , mem _devindices : 'E4' , mem _phase1 : 'E4' ,
mem _state : 'E4' , mem _brain : 'E4' , mem _supplier : 'E4' , mem _audit : 'E4' ,
mem _archive : 'E4' , mem _github : 'E4' , mem _ruflo : 'E4' ,
// ruflo (9)
ruflo _queen : 'E2' , ruflo _plugins : 'E2' , ruflo _workers : 'E2' , ruflo _agents _catalog : 'E2' ,
ruflo _commands : 'E2' , ruflo _daemon : 'E2' , ruflo _memory : 'E4' , ruflo _mcp : 'E2' ,
ruflo _recall _hook : 'E4' ,
2026-05-16 15:39:47 +03:00
// АУДИТ-АКТУАЛИЗАЦИЯ 16.05.2026 — новые узлы
skill _creator : 'E8' , claude _setup : 'E8' , plugin _dev : 'E2' , context7 : 'E7' ,
hk _self _check : 'E2' , hk _skill _marker : 'E2' , hk _skill _check : 'E2' , hk _state _guard : 'E2' ,
hk _postcompact : 'E2' , hk _verifier : 'E2' , hk _ruflo _queen : 'E2' ,
sk _regression : 'A5' ,
mem _audit _b : 'E4' , mem _audit _c : 'E4' , mem _suppliercrm : 'E4' , mem _audit12 : 'E4' ,
mem _audit14 : 'E4' , mem _sprint1 : 'E4' , mem _sprint2 : 'E4' , mem _sprint3 : 'E4' ,
2026-05-17 04:46:32 +03:00
// A6 architecture-tooling 17.05.2026 — раздел «Архитектура систем» наполнен
adr _kit : 'A6' , arch _patterns : 'A6' , mermaid _skill : 'A6' ,
2026-05-16 15:03:48 +03:00
} ;
// Производные индексы для рендера панели и Паспорта.
const SECTION _BY _ID = new Map ( SECTIONS . map ( s => [ s . id , s ] ) ) ;
const SECTION _NODES = new Map ( SECTIONS . map ( s => [ s . id , [ ] ] ) ) ;
NODES . forEach ( n => {
const sid = NODE _SECTION [ n . id ] ;
if ( sid && SECTION _NODES . has ( sid ) ) SECTION _NODES . get ( sid ) . push ( n . id ) ;
} ) ;
2026-05-16 22:31:26 +03:00
// ════════════════════════════════════════════════════
// SECTION 3.5: WISHLIST — отложенный backlog (todo-лист хотелок)
// ════════════════════════════════════════════════════
// Редактируемый список отложенных «хотелок» развития мозга/портала.
// Добавить хотелку = добавить объект. status: 'next' | 'blocked' | 'idea'.
const WISH _STATUS = {
next : { emoji : '▶' , label : 'к работе' , color : '#859900' } ,
blocked : { emoji : '⏸' , label : 'ждёт зависимости' , color : '#b58900' } ,
idea : { emoji : '💭' , label : 'идея' , color : '#586e75' } ,
} ;
const WISHLIST = [
{ id : 'W1' , status : 'next' , section : 'E8' ,
title : 'K7-spike — починка embeddings ruflo' ,
note : 'Tensor.location / onnxruntime version sync. Гейт жизнеспособности моста claude-mem→ReasoningBank. ~1-2 ч, systematic-debugging, ≥3 гипотезы.' } ,
{ id : 'W2' , status : 'blocked' , section : 'E8' ,
title : 'Мост claude-mem → ReasoningBank' ,
note : 'Замкнутый self-learning loop: захват (claude-mem) → адаптер+LLM-трансформ → сток (ruflo memory) → recall. Gated на W1.' } ,
{ id : 'W3' , status : 'blocked' , section : 'E8' ,
title : 'claude-mem #1 — установка плагином' ,
note : 'Слой авто-захвата моста. Ставить как плагин (не npx — риск перезаписи settings.json). Роль решается после W1.' } ,
{ id : 'W4' , status : 'blocked' , section : 'E8' ,
title : 'Двухуровневый ремонтник моста' ,
note : 'Tier 1 — auto-heal операционки (рестарт демона, re-run h7-patch, retry). Tier 2 — circuit-breaker на семантику (halt, не чинить). Часть W2.' } ,
] ;
2026-05-13 17:05:59 +03:00
// ════════════════════════════════════════════════════
// SECTION 4: VIS INIT
// ════════════════════════════════════════════════════
const GROUPS = {
rules : { color : { background : '#073642' , border : '#268bd2' , highlight : { border : '#93a1a1' , background : '#0d4a5a' } } , font : { color : '#fdf6e3' , size : 13 , bold : true } } ,
plugins : { color : { background : '#001a00' , border : '#859900' , highlight : { border : '#b8cc00' , background : '#002600' } } , font : { color : '#fdf6e3' , size : 12 } } ,
skills _sp : { color : { background : '#1a0033' , border : '#6c71c4' , highlight : { border : '#9b9fea' , background : '#250047' } } , font : { color : '#fdf6e3' , size : 11 } } ,
skills _proj : { color : { background : '#2d0020' , border : '#d33682' , highlight : { border : '#e869a8' , background : '#3d0028' } } , font : { color : '#fdf6e3' , size : 12 } } ,
hooks : { color : { background : '#002233' , border : '#2aa198' , highlight : { border : '#4dd7ce' , background : '#003344' } } , font : { color : '#fdf6e3' , size : 11 } } ,
agents : { color : { background : '#1a1200' , border : '#b58900' , highlight : { border : '#e0ad00' , background : '#261a00' } } , font : { color : '#fdf6e3' , size : 11 } } ,
mcp : { color : { background : '#2d1200' , border : '#cb4b16' , highlight : { border : '#ff6b30' , background : '#3d1900' } } , font : { color : '#fdf6e3' , size : 11 } } ,
lefthook : { color : { background : '#2d0000' , border : '#dc322f' , highlight : { border : '#ff5f5c' , background : '#3d0000' } } , font : { color : '#fdf6e3' , size : 10 } } ,
memory : { color : { background : '#112233' , border : '#586e75' , highlight : { border : '#839496' , background : '#1a2f40' } } , font : { color : '#eee8d5' , size : 10 } } ,
2026-05-15 15:34:39 +03:00
ruflo : { color : { background : '#332100' , border : '#ff8800' , highlight : { border : '#ffaa33' , background : '#4d3300' } } , font : { color : '#fdf6e3' , size : 12 , bold : true } } ,
2026-05-13 17:05:59 +03:00
} ;
const nodesDS = new vis . DataSet ( NODES ) ;
const edgesDS = new vis . DataSet ( EDGES ) ;
const network = new vis . Network (
document . getElementById ( 'network' ) ,
{ nodes : nodesDS , edges : edgesDS } ,
{
groups : GROUPS ,
nodes : {
shape : 'dot' ,
borderWidth : 2 ,
borderWidthSelected : 3 ,
font : { multi : 'html' } ,
} ,
edges : {
2026-05-14 09:23:46 +03:00
smooth : { type : 'continuous' , roundness : 0.5 } ,
2026-05-13 17:05:59 +03:00
selectionWidth : 2 ,
} ,
physics : {
2026-05-14 09:23:46 +03:00
enabled : false ,
2026-05-13 17:05:59 +03:00
} ,
interaction : {
hover : true ,
tooltipDelay : 400 ,
multiselect : false ,
} ,
}
) ;
2026-05-14 09:23:46 +03:00
network . once ( 'afterDrawing' , ( ) => {
network . fit ( { animation : { duration : 600 , easingFunction : 'easeInOutQuad' } } ) ;
2026-05-13 17:05:59 +03:00
} ) ;
// ════════════════════════════════════════════════════
// SECTION 5: LEGEND PANEL
// ════════════════════════════════════════════════════
function renderLegendItem ( item ) {
return ` <li> ${ item . name } ${ item . cond ? ` <span class="cond">— ${ item . cond } </span> ` : '' } </li> ` ;
}
2026-05-14 13:14:20 +03:00
function showNodeLegend ( nodeId ) {
document . getElementById ( 'legend-node-content' ) . style . display = '' ;
document . getElementById ( 'legend-edge-content' ) . style . display = 'none' ;
2026-05-16 15:03:48 +03:00
document . getElementById ( 'legend-sections-content' ) . style . display = 'none' ;
2026-05-16 22:31:26 +03:00
document . getElementById ( 'legend-wishlist-content' ) . style . display = 'none' ;
2026-05-13 17:05:59 +03:00
const node = NODES . find ( n => n . id === nodeId ) ;
const details = NODE _DETAILS [ nodeId ] ;
const panel = document . getElementById ( 'legend-panel' ) ;
if ( ! node || ! details ) { panel . classList . remove ( 'visible' ) ; return ; }
document . getElementById ( 'legend-title' ) . textContent = node . label . replace ( /\n/g , ' ' ) ;
const catLabel = CATEGORY _LABELS [ node . group ] || node . group ;
const catColor = GROUPS [ node . group ] && GROUPS [ node . group ] . color ? GROUPS [ node . group ] . color . border : '#839496' ;
document . getElementById ( 'legend-category' ) . innerHTML =
` <span style="color: ${ catColor } ; font-weight:600;">● ${ catLabel } </span> ` ;
2026-05-16 09:41:04 +03:00
// ── Паспорт узла (iter6) ──
const meta = NODE _META [ nodeId ] || { since : '—' , changed : '—' , uses : null , usesSrc : '—' } ;
document . getElementById ( 'ld-since' ) . textContent = meta . since || '—' ;
document . getElementById ( 'ld-changed' ) . textContent = meta . changed || '—' ;
2026-05-16 15:03:48 +03:00
const _sec = NODE _SECTION [ nodeId ] ? SECTION _BY _ID . get ( NODE _SECTION [ nodeId ] ) : null ;
document . getElementById ( 'ld-section' ) . textContent = _sec ? ` ${ _sec . id } · ${ _sec . label } ` : '—' ;
2026-05-16 09:41:04 +03:00
const usesEl = document . getElementById ( 'ld-uses' ) ;
if ( meta . uses === null || meta . uses === undefined ) {
usesEl . textContent = 'нет данных (узел не вызывается напрямую)' ;
usesEl . style . color = '#586e75' ;
} else {
usesEl . innerHTML = ` <b> ${ meta . uses } </b> <span style="color:#839496;">( ${ meta . usesSrc } ) · срез ${ META _WINDOW } </span> ` ;
usesEl . style . color = '' ;
}
// строка «Дубль» — парный дубль (DUPLICATE_GROUPS) либо ролевая заметка ruflo (dupNote)
const dupRow = document . getElementById ( 'ld-dup-row' ) ;
const dupEl = document . getElementById ( 'ld-dup' ) ;
const pair = DUP _BY _NODE . get ( nodeId ) ;
if ( pair ) {
const partnerNode = NODES . find ( n => n . id === pair . partner ) ;
const partnerLabel = partnerNode ? partnerNode . label . replace ( /\n/g , ' ' ) : pair . partner ;
dupEl . innerHTML = ` ⧉ <b> ${ partnerLabel } </b> (~ ${ pair . pct } %) — ${ pair . reason } ` ;
dupRow . style . display = '' ;
} else if ( meta . dupNote ) {
dupEl . innerHTML = ` ⧉ ${ meta . dupNote } ` ;
dupRow . style . display = '' ;
} else {
dupRow . style . display = 'none' ;
}
2026-05-13 17:05:59 +03:00
document . getElementById ( 'ld-desc' ) . textContent = details . desc ;
2026-05-14 09:10:57 +03:00
document . getElementById ( 'ld-when' ) . textContent = details . when || '—' ;
document . getElementById ( 'ld-limits' ) . textContent = details . limits || 'без особых ограничений' ;
2026-05-13 17:05:59 +03:00
const ldReports = document . getElementById ( 'ld-reports' ) ;
ldReports . innerHTML = details . reportsTo . length
? details . reportsTo . map ( renderLegendItem ) . join ( '' )
: '<li style="color:#586e75; font-style:italic;">Не подчиняется никому</li>' ;
const ldManages = document . getElementById ( 'ld-manages' ) ;
ldManages . innerHTML = details . manages . length
? details . manages . map ( renderLegendItem ) . join ( '' )
: '<li style="color:#586e75; font-style:italic;">Никто не подчиняется</li>' ;
const ldTogether = document . getElementById ( 'ld-together' ) ;
ldTogether . innerHTML = details . together . length
? details . together . map ( renderLegendItem ) . join ( '' )
: '<li style="color:#586e75; font-style:italic;">Нет особых одновременных связей</li>' ;
const ldConflicts = document . getElementById ( 'ld-conflicts' ) ;
if ( details . conflicts && details . conflicts . length ) {
2026-05-14 13:16:56 +03:00
const sorted = [ ... details . conflicts ] . sort ( ( a , b ) =>
( CONFLICT _TYPES [ a . type ] ? CONFLICT _TYPES [ a . type ] . rank : 999 ) -
( CONFLICT _TYPES [ b . type ] ? CONFLICT _TYPES [ b . type ] . rank : 999 )
) ;
ldConflicts . innerHTML = sorted . map ( c => {
const t = CONFLICT _TYPES [ c . type ] || CONFLICT _TYPES . RED ;
return ` <div class="conflict-item" style="background: ${ t . bg } "> ` +
` <div class="cname" style="color: ${ t . color } "> ${ t . emoji } ${ c . name } </div> ` +
` <div class="cdesc"> ${ c . desc } </div> ` +
` </div> ` ;
} ) . join ( '' ) ;
2026-05-13 17:05:59 +03:00
} else {
ldConflicts . innerHTML = '<div id="legend-no-conflicts" style="font-size:12px;color:#586e75;">Конфликтов не выявлено</div>' ;
}
document . getElementById ( 'conflicts-section' ) . style . display = '' ;
panel . classList . add ( 'visible' ) ;
}
2026-05-14 13:14:20 +03:00
function showEdgeLegend ( edgeId ) {
const edge = edgesDS . get ( edgeId ) ;
if ( ! edge ) return ;
const panel = document . getElementById ( 'legend-panel' ) ;
document . getElementById ( 'legend-node-content' ) . style . display = 'none' ;
document . getElementById ( 'legend-edge-content' ) . style . display = '' ;
2026-05-16 15:03:48 +03:00
document . getElementById ( 'legend-sections-content' ) . style . display = 'none' ;
2026-05-16 22:31:26 +03:00
document . getElementById ( 'legend-wishlist-content' ) . style . display = 'none' ;
2026-05-14 13:14:20 +03:00
const fromNode = NODES . find ( n => n . id === edge . from ) ;
const toNode = NODES . find ( n => n . id === edge . to ) ;
if ( ! fromNode || ! toNode ) return ;
const fromCat = CATEGORY _LABELS [ fromNode . group ] || fromNode . group ;
const toCat = CATEGORY _LABELS [ toNode . group ] || toNode . group ;
const fromColor = ( GROUPS [ fromNode . group ] && GROUPS [ fromNode . group ] . color ) ? GROUPS [ fromNode . group ] . color . border : '#839496' ;
const toColor = ( GROUPS [ toNode . group ] && GROUPS [ toNode . group ] . color ) ? GROUPS [ toNode . group ] . color . border : '#839496' ;
const edgeColor = ( edge . color && edge . color . color ) ? edge . color . color : '#586e75' ;
document . getElementById ( 'legend-edge-title' ) . innerHTML =
'<span style="color:' + fromColor + '">' + fromNode . label . replace ( /\n/g , ' ' ) + '</span>' +
' <span style="color:' + edgeColor + '">→</span> ' +
'<span style="color:' + toColor + '">' + toNode . label . replace ( /\n/g , ' ' ) + '</span>' ;
document . getElementById ( 'le-from' ) . innerHTML =
fromNode . label . replace ( /\n/g , ' ' ) +
' <span style="color:' + fromColor + ';font-size:11px;text-transform:uppercase;">(' + fromCat + ')</span>' ;
document . getElementById ( 'le-to' ) . innerHTML =
toNode . label . replace ( /\n/g , ' ' ) +
' <span style="color:' + toColor + ';font-size:11px;text-transform:uppercase;">(' + toCat + ')</span>' ;
const details = EDGE _DETAILS [ edgeKey ( edge . from , edge . to ) ] ;
if ( details ) {
document . getElementById ( 'le-type' ) . textContent = details . type ;
document . getElementById ( 'le-when' ) . textContent = details . when ;
document . getElementById ( 'le-transfers' ) . textContent = details . transfers ;
document . getElementById ( 'le-mandatory' ) . textContent = details . mandatory ;
document . getElementById ( 'le-rule' ) . textContent = details . rule ;
} else {
[ 'le-type' , 'le-when' , 'le-transfers' , 'le-mandatory' ] . forEach ( id =>
document . getElementById ( id ) . textContent = '—' ) ;
document . getElementById ( 'le-rule' ) . textContent = 'Регламент не задокументирован' ;
}
panel . classList . add ( 'visible' ) ;
}
2026-05-16 15:03:48 +03:00
// ── Панель «Разделы» — функциональная квалификация (3-й режим легенды) ──
function showSectionsLegend ( ) {
document . getElementById ( 'legend-node-content' ) . style . display = 'none' ;
document . getElementById ( 'legend-edge-content' ) . style . display = 'none' ;
2026-05-16 22:31:26 +03:00
document . getElementById ( 'legend-wishlist-content' ) . style . display = 'none' ;
2026-05-16 15:03:48 +03:00
document . getElementById ( 'legend-sections-content' ) . style . display = '' ;
let html = '' ;
for ( const bucket of SECTION _BUCKETS ) {
html += ` <div class="sect-bucket-h"> ${ bucket . id } . ${ bucket . label } </div> ` ;
for ( const sec of SECTIONS . filter ( s => s . bucket === bucket . id ) ) {
const nodeIds = SECTION _NODES . get ( sec . id ) || [ ] ;
const empty = nodeIds . length === 0 ;
html += ` <div class="sect-row ${ empty ? ' sect-empty' : '' } "> ` ;
html += ` <div><span class="sect-name"><span class="sect-id"> ${ sec . id } </span> ${ sec . label } </span> <span class="sect-cnt">· ${ nodeIds . length } </span></div> ` ;
if ( empty ) {
html += ` <div class="sect-empty-mark">— пусто (playbook ещё не наполнен) —</div> ` ;
} else {
html += '<div class="sect-chips">' + nodeIds . map ( id => {
const node = NODES . find ( n => n . id === id ) ;
const lbl = node ? node . label . replace ( /\n/g , ' ' ) : id ;
return ` <span class="sect-chip" data-node=" ${ id } "> ${ lbl } </span> ` ;
} ) . join ( '' ) + '</div>' ;
}
html += '</div>' ;
}
}
document . getElementById ( 'sect-list' ) . innerHTML = html ;
document . getElementById ( 'legend-panel' ) . classList . add ( 'visible' ) ;
}
2026-05-16 22:31:26 +03:00
// ── Панель «Хотелки» — отложенный backlog (режим легенды) ──
function showWishlistLegend ( ) {
document . getElementById ( 'legend-node-content' ) . style . display = 'none' ;
document . getElementById ( 'legend-edge-content' ) . style . display = 'none' ;
document . getElementById ( 'legend-sections-content' ) . style . display = 'none' ;
document . getElementById ( 'legend-wishlist-content' ) . style . display = '' ;
let html = '' ;
for ( const w of WISHLIST ) {
const st = WISH _STATUS [ w . status ] || WISH _STATUS . idea ;
html += ` <div class="wish-row wish- ${ w . status } "> ` ;
html += ` <div class="wish-head"><span class="wish-id"> ${ w . id } </span> ${ w . title } </div> ` ;
html += ` <div class="wish-status" style="color: ${ st . color } "> ${ st . emoji } ${ st . label } </div> ` ;
html += ` <div class="wish-note"> ${ w . note } </div> ` ;
if ( w . section ) {
const sec = SECTION _BY _ID . get ( w . section ) ;
html += ` <div class="wish-sect">Раздел: ${ w . section } ${ sec ? ' · ' + sec . label : '' } </div> ` ;
}
html += '</div>' ;
}
document . getElementById ( 'wish-list' ) . innerHTML = html ;
document . getElementById ( 'legend-panel' ) . classList . add ( 'visible' ) ;
}
2026-05-13 17:05:59 +03:00
network . on ( 'click' , params => {
if ( params . nodes . length === 1 ) {
2026-05-15 06:24:06 +03:00
const id = params . nodes [ 0 ] ;
2026-05-16 09:54:44 +03:00
// iter6 — в режиме heat/dup клик открывает паспорт, но не трогает подсветку режима
if ( HIGHLIGHT . state . viewMode === null ) {
HIGHLIGHT . setSelectedNode ( id ) ;
HIGHLIGHT . applyHighlight ( ) ;
}
2026-05-15 06:24:06 +03:00
// Right panel still shows details of the clicked node (last-clicked, even after toggle-off)
showNodeLegend ( id ) ;
2026-05-14 13:14:20 +03:00
} else if ( params . edges . length === 1 ) {
showEdgeLegend ( params . edges [ 0 ] ) ;
2026-05-13 17:05:59 +03:00
} else if ( params . nodes . length === 0 && params . edges . length === 0 ) {
2026-05-16 09:54:44 +03:00
if ( HIGHLIGHT . state . viewMode === null ) {
HIGHLIGHT . setSelectedNode ( null ) ;
HIGHLIGHT . applyHighlight ( ) ;
}
2026-05-13 17:05:59 +03:00
document . getElementById ( 'legend-panel' ) . classList . remove ( 'visible' ) ;
}
} ) ;
document . getElementById ( 'legend-close' ) . addEventListener ( 'click' , ( ) => {
document . getElementById ( 'legend-panel' ) . classList . remove ( 'visible' ) ;
} ) ;
// ════════════════════════════════════════════════════
// SECTION 6: TOOLBAR
// ════════════════════════════════════════════════════
let highlightedNode = null ;
document . getElementById ( 'search' ) . addEventListener ( 'input' , function ( ) {
2026-05-15 06:30:55 +03:00
// Search is a separate mode — last-wins over highlight state
HIGHLIGHT . clearAll ( ) ;
HIGHLIGHT . updateLegendVisuals ( ) ;
2026-05-13 17:05:59 +03:00
const q = this . value . trim ( ) . toLowerCase ( ) ;
if ( ! q ) {
nodesDS . update ( NODES . map ( n => ( { id : n . id , borderWidth : 2 , opacity : 1.0 } ) ) ) ;
highlightedNode = null ;
return ;
}
const matches = NODES . filter ( n => n . label . toLowerCase ( ) . includes ( q ) ) ;
const updates = NODES . map ( n => {
const match = matches . some ( m => m . id === n . id ) ;
return {
id : n . id ,
borderWidth : match ? 5 : 1 ,
opacity : match ? 1.0 : 0.25 ,
} ;
} ) ;
nodesDS . update ( updates ) ;
if ( matches . length === 1 ) {
network . focus ( matches [ 0 ] . id , { scale : 1.4 , animation : { duration : 500 , easingFunction : 'easeInOutQuad' } } ) ;
2026-05-14 13:14:20 +03:00
showNodeLegend ( matches [ 0 ] . id ) ;
2026-05-13 17:05:59 +03:00
highlightedNode = matches [ 0 ] . id ;
}
} ) ;
document . getElementById ( 'btn-freeze' ) . addEventListener ( 'click' , ( ) => {
network . setOptions ( { physics : { enabled : false } } ) ;
} ) ;
document . getElementById ( 'btn-unfreeze' ) . addEventListener ( 'click' , ( ) => {
2026-05-14 09:23:46 +03:00
network . setOptions ( {
physics : {
enabled : true ,
solver : 'forceAtlas2Based' ,
forceAtlas2Based : {
gravitationalConstant : - 50 ,
centralGravity : 0.0 ,
springLength : 100 ,
springConstant : 0.02 ,
damping : 0.6 ,
avoidOverlap : 0.4 ,
} ,
} ,
} ) ;
2026-05-13 17:05:59 +03:00
} ) ;
document . getElementById ( 'btn-reset' ) . addEventListener ( 'click' , ( ) => {
2026-05-14 09:23:46 +03:00
// (a) Restore radial positions
nodesDS . update ( NODES . map ( n => ( { id : n . id , x : n . x , y : n . y } ) ) ) ;
// (b) Refit camera
2026-05-13 17:05:59 +03:00
network . fit ( { animation : { duration : 600 , easingFunction : 'easeInOutQuad' } } ) ;
} ) ;
document . getElementById ( 'btn-clear' ) . addEventListener ( 'click' , ( ) => {
document . getElementById ( 'search' ) . value = '' ;
2026-05-15 06:30:55 +03:00
HIGHLIGHT . clearAll ( ) ;
HIGHLIGHT . updateLegendVisuals ( ) ;
HIGHLIGHT . applyHighlight ( ) ;
nodesDS . update ( NODES . map ( n => ( { id : n . id , borderWidth : 2 } ) ) ) ; // reset borderWidth used by search-highlight
2026-05-13 17:05:59 +03:00
document . getElementById ( 'legend-panel' ) . classList . remove ( 'visible' ) ;
highlightedNode = null ;
} ) ;
2026-05-14 12:17:08 +03:00
// ════════════════════════════════════════════════════
// SECTION 7: RESIZE HANDLE + LOCALSTORAGE
// ════════════════════════════════════════════════════
const LEGEND _STORAGE _KEY = 'liderra-map-legend-width' ;
const LEGEND _MIN _W = 300 , LEGEND _MAX _W = 900 ;
2026-05-14 12:22:52 +03:00
let redrawScheduled = false ;
2026-05-14 12:17:08 +03:00
function applyLegendWidth ( w ) {
const clamped = Math . max ( LEGEND _MIN _W , Math . min ( LEGEND _MAX _W , w ) ) ;
const panel = document . getElementById ( 'legend-panel' ) ;
panel . style . width = clamped + 'px' ;
panel . style . minWidth = clamped + 'px' ;
2026-05-14 12:22:52 +03:00
if ( typeof network !== 'undefined' && network && ! redrawScheduled ) {
redrawScheduled = true ;
requestAnimationFrame ( ( ) => {
redrawScheduled = false ;
network . redraw ( ) ;
} ) ;
}
2026-05-14 12:17:08 +03:00
}
function restoreLegendWidth ( ) {
2026-05-14 12:22:52 +03:00
let saved = 300 ;
try {
saved = parseInt ( localStorage . getItem ( LEGEND _STORAGE _KEY ) || '300' , 10 ) ;
} catch ( e ) { /* private mode or quota — keep default */ }
2026-05-14 12:17:08 +03:00
applyLegendWidth ( saved ) ;
}
( function setupResizeHandle ( ) {
const handle = document . getElementById ( 'legend-handle' ) ;
if ( ! handle ) return ;
let dragging = false ;
handle . addEventListener ( 'mousedown' , e => {
dragging = true ;
handle . classList . add ( 'dragging' ) ;
document . body . style . userSelect = 'none' ;
e . preventDefault ( ) ;
} ) ;
document . addEventListener ( 'mousemove' , e => {
if ( ! dragging ) return ;
const w = window . innerWidth - e . clientX ;
applyLegendWidth ( w ) ;
} ) ;
document . addEventListener ( 'mouseup' , ( ) => {
if ( ! dragging ) return ;
dragging = false ;
handle . classList . remove ( 'dragging' ) ;
document . body . style . userSelect = '' ;
const w = parseInt ( document . getElementById ( 'legend-panel' ) . style . width , 10 ) ;
2026-05-14 12:22:52 +03:00
try { localStorage . setItem ( LEGEND _STORAGE _KEY , String ( w ) ) ; } catch ( e ) { /* private mode or quota */ }
2026-05-14 12:17:08 +03:00
} ) ;
} ) ( ) ;
2026-05-15 06:12:43 +03:00
// ════════════════════════════════════════════════════
// SECTION 8: HIGHLIGHTING (legend filter + node focus)
// ════════════════════════════════════════════════════
const HIGHLIGHT = ( function setupHighlight ( ) {
const FILTER _GROUP _PREFIX = 'group:' ;
const FILTER _CONFLICT _PREFIX = 'conflict:' ;
const OPACITY _FOCUS = 1.0 ;
const OPACITY _FILTER = 0.55 ;
const OPACITY _DIM = 0.15 ;
const CONFLICT _EDGE _MIN _OPACITY = 0.85 ;
const state = {
selectedNode : null ,
legendFilter : new Set ( ) ,
2026-05-16 09:54:44 +03:00
viewMode : null , // null | 'heat' | 'dup' — взаимоисключающие режимы (iter6)
2026-05-15 06:12:43 +03:00
} ;
2026-05-16 09:54:44 +03:00
// ── Теплокарта использования (iter6) — 4 яруса по NODE_META[id].uses ──
function heatOpacity ( nodeId ) {
const m = NODE _META [ nodeId ] ;
const u = m ? m . uses : null ;
if ( u === null || u === undefined ) return 0.5 ; // нет данных — нейтрально
if ( u >= 21 ) return 1.0 ; // часто
if ( u >= 6 ) return 0.65 ; // иногда
if ( u >= 1 ) return 0.35 ; // редко
return 0.12 ; // простаивает (uses === 0)
}
// Узлы верхнего яруса теплокарты получают акцентную рамку.
function heatBorderWidth ( nodeId ) {
if ( state . viewMode !== 'heat' ) return 2 ;
const m = NODE _META [ nodeId ] ;
const u = m ? m . uses : null ;
return ( typeof u === 'number' && u >= 21 ) ? 4 : 2 ;
}
// Переключатель режима — toggle; включение режима гасит пофильтровую подсветку.
function setViewMode ( mode ) {
state . viewMode = ( state . viewMode === mode ) ? null : mode ;
if ( state . viewMode !== null ) {
state . legendFilter . clear ( ) ;
state . selectedNode = null ;
}
}
2026-05-15 06:12:43 +03:00
// ── Pre-computed indices ──────────────────────────
const NODES _BY _ID = new Map ( ) ;
const NEIGHBOURS = new Map ( ) ;
const CONFLICT _ENDPOINTS = { RED : new Set ( ) , BLACK : new Set ( ) , GREEN : new Set ( ) } ;
const CONFLICT _EDGE _TYPE = new Map ( ) ;
NODES . forEach ( n => {
NODES _BY _ID . set ( n . id , n ) ;
if ( ! NEIGHBOURS . has ( n . id ) ) NEIGHBOURS . set ( n . id , new Set ( ) ) ;
} ) ;
edgesDS . get ( ) . forEach ( edge => {
// Both directions — Q5; conflict edges count as connections — Q6
if ( NEIGHBOURS . has ( edge . from ) ) NEIGHBOURS . get ( edge . from ) . add ( edge . to ) ;
if ( NEIGHBOURS . has ( edge . to ) ) NEIGHBOURS . get ( edge . to ) . add ( edge . from ) ;
if ( edge . dashes && edge . color && edge . color . color ) {
for ( const t of [ 'RED' , 'BLACK' , 'GREEN' ] ) {
if ( CONFLICT _TYPES [ t ] . color === edge . color . color ) {
CONFLICT _ENDPOINTS [ t ] . add ( edge . from ) ;
CONFLICT _ENDPOINTS [ t ] . add ( edge . to ) ;
CONFLICT _EDGE _TYPE . set ( edge . id , t ) ;
break ;
}
}
}
} ) ;
// ── Opacity computations ──────────────────────────
function computeNodeOpacity ( nodeId ) {
2026-05-16 09:54:44 +03:00
// Row 0: view-mode (iter6) — глобальная картина, поверх focus/filter
if ( state . viewMode === 'heat' ) return heatOpacity ( nodeId ) ;
if ( state . viewMode === 'dup' ) return DUP _NODE _SET . has ( nodeId ) ? OPACITY _FOCUS : OPACITY _DIM ;
2026-05-15 06:12:43 +03:00
// Row 1: focus
if ( state . selectedNode !== null ) {
if ( state . selectedNode === nodeId ) return OPACITY _FOCUS ;
const neigh = NEIGHBOURS . get ( state . selectedNode ) ;
if ( neigh && neigh . has ( nodeId ) ) return OPACITY _FOCUS ;
}
// Row 2: idle
if ( state . legendFilter . size === 0 && state . selectedNode === null ) return OPACITY _FOCUS ;
// Row 3: in filter?
const node = NODES _BY _ID . get ( nodeId ) ;
let inFilter = false ;
if ( node && state . legendFilter . has ( FILTER _GROUP _PREFIX + node . group ) ) inFilter = true ;
if ( ! inFilter ) {
for ( const t of [ 'RED' , 'BLACK' , 'GREEN' ] ) {
if ( state . legendFilter . has ( FILTER _CONFLICT _PREFIX + t ) && CONFLICT _ENDPOINTS [ t ] . has ( nodeId ) ) {
inFilter = true ;
break ;
}
}
}
if ( inFilter ) return state . selectedNode ? OPACITY _FILTER : OPACITY _FOCUS ;
// Row 4: everything else
return OPACITY _DIM ;
}
function computeEdgeOpacity ( edge ) {
const fromO = computeNodeOpacity ( edge . from ) ;
const toO = computeNodeOpacity ( edge . to ) ;
const baseline = Math . min ( fromO , toO ) ;
// Conflict edge directly selected via 🔴/⚫/🟢 in filter — boost to ≥0.85
const ctype = CONFLICT _EDGE _TYPE . get ( edge . id ) ;
if ( ctype && state . legendFilter . has ( FILTER _CONFLICT _PREFIX + ctype ) ) {
return Math . max ( CONFLICT _EDGE _MIN _OPACITY , baseline ) ;
}
return baseline ;
}
function applyHighlight ( ) {
const nodeUpdates = NODES . map ( n => ( {
id : n . id ,
opacity : computeNodeOpacity ( n . id ) ,
2026-05-16 09:54:44 +03:00
borderWidth : heatBorderWidth ( n . id ) , // 4 для верхнего яруса теплокарты, иначе 2 (iter6)
2026-05-15 06:12:43 +03:00
} ) ) ;
const edgeUpdates = edgesDS . get ( ) . map ( e => ( {
id : e . id ,
color : Object . assign ( { } , e . color || { } , { opacity : computeEdgeOpacity ( e ) } ) ,
} ) ) ;
nodesDS . update ( nodeUpdates ) ;
edgesDS . update ( edgeUpdates ) ;
}
// ── State manipulators ────────────────────────────
function toggleFilter ( key ) {
if ( state . legendFilter . has ( key ) ) state . legendFilter . delete ( key ) ;
else state . legendFilter . add ( key ) ;
}
function setSelectedNode ( id ) {
if ( state . selectedNode === id ) state . selectedNode = null ; // toggle on repeat
else state . selectedNode = id ;
}
function clearAll ( ) {
state . selectedNode = null ;
state . legendFilter . clear ( ) ;
2026-05-16 09:54:44 +03:00
state . viewMode = null ;
2026-05-15 06:12:43 +03:00
}
function updateLegendVisuals ( ) {
document . querySelectorAll ( '#cat-legend .cat-item' ) . forEach ( item => {
const key = item . dataset . filterKey ;
if ( ! key ) return ;
if ( state . legendFilter . has ( key ) ) item . classList . add ( 'active' ) ;
else item . classList . remove ( 'active' ) ;
} ) ;
2026-05-16 09:54:44 +03:00
const heatBtn = document . getElementById ( 'cat-ctl-heat' ) ;
const dupBtn = document . getElementById ( 'cat-ctl-dup' ) ;
if ( heatBtn ) heatBtn . classList . toggle ( 'active' , state . viewMode === 'heat' ) ;
if ( dupBtn ) dupBtn . classList . toggle ( 'active' , state . viewMode === 'dup' ) ;
2026-05-15 06:12:43 +03:00
}
2026-05-15 06:20:22 +03:00
// ── Legend click delegation ───────────────────────
document . getElementById ( 'cat-legend' ) . addEventListener ( 'click' , e => {
2026-05-16 09:54:44 +03:00
// iter6 — клик по кнопке режима heat/dup
const ctl = e . target . closest ( '.cat-ctl' ) ;
if ( ctl ) {
2026-05-16 15:03:48 +03:00
if ( ctl . id === 'cat-ctl-sect' ) { showSectionsLegend ( ) ; return ; }
2026-05-16 22:31:26 +03:00
if ( ctl . id === 'cat-ctl-wish' ) { showWishlistLegend ( ) ; return ; }
2026-05-16 09:54:44 +03:00
setViewMode ( ctl . id === 'cat-ctl-heat' ? 'heat' : 'dup' ) ;
applyHighlight ( ) ;
updateLegendVisuals ( ) ;
return ;
}
2026-05-15 06:20:22 +03:00
const item = e . target . closest ( '.cat-item' ) ;
if ( ! item || ! item . dataset . filterKey ) return ;
toggleFilter ( item . dataset . filterKey ) ;
applyHighlight ( ) ;
updateLegendVisuals ( ) ;
} ) ;
2026-05-15 06:12:43 +03:00
// Expose API (closes over state)
return {
applyHighlight ,
toggleFilter ,
setSelectedNode ,
clearAll ,
updateLegendVisuals ,
state , // exposed for debug only
} ;
} ) ( ) ;
2026-05-16 15:03:48 +03:00
// Клик по чипу узла в панели «Разделы» — открыть паспорт узла + сфокусировать граф.
document . getElementById ( 'sect-list' ) . addEventListener ( 'click' , e => {
const chip = e . target . closest ( '.sect-chip' ) ;
if ( ! chip ) return ;
const id = chip . dataset . node ;
if ( HIGHLIGHT . state . viewMode === null ) {
HIGHLIGHT . setSelectedNode ( id ) ;
HIGHLIGHT . applyHighlight ( ) ;
}
network . focus ( id , { scale : 1.2 , animation : { duration : 500 , easingFunction : 'easeInOutQuad' } } ) ;
showNodeLegend ( id ) ;
} ) ;
2026-05-14 12:17:08 +03:00
window . addEventListener ( 'DOMContentLoaded' , restoreLegendWidth ) ;
2026-05-13 17:05:59 +03:00
< / script >
< / body >
< / html >