2026-05-11 00:46:51 +03:00
<!DOCTYPE html>
< html lang = "ru" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Карта работы — Hooks · Skills · Plugins< / title >
< link rel = "preconnect" href = "https://fonts.googleapis.com" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link href = "https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT,WONK@0,9..144,200..900,0..100,0..1;1,9..144,200..900,0..100,0..1&family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap" rel = "stylesheet" >
< script src = "https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js" defer > < / script >
< style >
/* ============================================================
COLOR SYSTEM — Vintage Engineering Manual
============================================================ */
: root {
--paper : #F2EBDC ;
--paper-shade : #E8DFC8 ;
--paper-deep : #D9CFB5 ;
--ink : #0E2235 ;
--ink-soft : #2B3D52 ;
--ink-fade : #5E6F82 ;
--blueprint : #1A6E8E ;
--blueprint-deep : #0F4D67 ;
--amber : #C48B26 ;
--amber-deep : #9A6A14 ;
--rust : #8B3A1B ;
--rust-deep : #6A2A12 ;
--sage : #5E7A4F ;
--sage-deep : #3E5333 ;
--grid : rgba ( 14 , 34 , 53 , 0.06 ) ;
--rule : rgba ( 14 , 34 , 53 , 0.15 ) ;
--shadow-paper : 0 1 px 0 rgba ( 0 , 0 , 0 , 0.04 ) , 0 4 px 24 px rgba ( 14 , 34 , 53 , 0.08 ) ;
}
/* ============================================================
RESET + BASE
============================================================ */
* , * :: before , * :: after { box-sizing : border-box ; margin : 0 ; padding : 0 ; }
html {
scroll-behavior : smooth ;
font-size : 16 px ;
}
body {
font-family : 'Plus Jakarta Sans' , system-ui , sans-serif ;
font-weight : 400 ;
font-size : 1 rem ;
line-height : 1.6 ;
color : var ( - - ink ) ;
background : var ( - - paper ) ;
background-image :
linear-gradient ( var ( - - grid ) 1 px , transparent 1 px ) ,
linear-gradient ( 90 deg , var ( - - grid ) 1 px , transparent 1 px ) ;
background-size : 32 px 32 px ;
background-attachment : fixed ;
min-height : 100 vh ;
text-rendering : optimizeLegibility ;
-webkit- font-smoothing : antialiased ;
}
/* Subtle paper grain overlay */
body :: before {
content : '' ;
position : fixed ;
inset : 0 ;
pointer-events : none ;
z-index : 1 ;
opacity : 0.4 ;
background-image : url ( "data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' /%3E%3CfeColorMatrix values='0 0 0 0 0.05 0 0 0 0 0.13 0 0 0 0 0.21 0 0 0 0.18 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E" ) ;
}
main { position : relative ; z-index : 2 ; }
/* ============================================================
TYPOGRAPHY
============================================================ */
. display {
font-family : 'Fraunces' , serif ;
font-variation-settings : 'opsz' 144 , 'SOFT' 50 , 'WONK' 1 ;
font-weight : 400 ;
letter-spacing : -0.02 em ;
line-height : 0.95 ;
}
. display-i {
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
font-weight : 300 ;
}
. mono {
font-family : 'JetBrains Mono' , ui-monospace , monospace ;
font-weight : 400 ;
}
. caps {
font-family : 'Plus Jakarta Sans' , sans-serif ;
font-weight : 600 ;
text-transform : uppercase ;
letter-spacing : 0.18 em ;
font-size : 0.72 rem ;
}
/* ============================================================
PAGE FRAME
============================================================ */
. frame {
max-width : 1240 px ;
margin : 0 auto ;
padding : 0 32 px ;
}
@ media ( max-width : 720px ) {
. frame { padding : 0 20 px ; }
}
/* ============================================================
HERO
============================================================ */
. hero {
padding : 96 px 0 64 px ;
position : relative ;
}
. hero-meta {
display : flex ;
align-items : baseline ;
gap : 24 px ;
margin-bottom : 48 px ;
color : var ( - - ink - fade ) ;
}
. hero-meta-divider {
flex : 1 ;
height : 1 px ;
background : var ( - - rule ) ;
position : relative ;
top : -4 px ;
}
. hero-title {
font-size : clamp ( 3 rem , 9 vw , 7 rem ) ;
margin-bottom : 32 px ;
}
. hero-title em {
font-style : italic ;
color : var ( - - blueprint ) ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
}
. hero-sub {
font-size : 1.25 rem ;
max-width : 720 px ;
color : var ( - - ink - soft ) ;
line-height : 1.55 ;
}
. hero-sub strong {
font-weight : 600 ;
color : var ( - - ink ) ;
background : linear-gradient ( transparent 60 % , rgba ( 196 , 139 , 38 , 0.35 ) 60 % ) ;
padding : 0 2 px ;
}
. hero-stamp {
position : absolute ;
top : 80 px ;
right : 32 px ;
display : flex ;
flex-direction : column ;
align-items : flex-end ;
text-align : right ;
color : var ( - - rust ) ;
border : 2 px solid var ( - - rust ) ;
padding : 14 px 18 px ;
transform : rotate ( 4 deg ) ;
background : rgba ( 242 , 235 , 220 , 0.6 ) ;
}
. hero-stamp . num { font-family : 'Fraunces' , serif ; font-size : 2 rem ; font-weight : 400 ; line-height : 1 ; }
. hero-stamp . lbl { font-size : 0.65 rem ; letter-spacing : 0.2 em ; text-transform : uppercase ; margin-top : 4 px ; }
@ media ( max-width : 720px ) {
. hero { padding : 60 px 0 40 px ; }
. hero-stamp { display : none ; }
}
/* ============================================================
SECTION
============================================================ */
. section {
padding : 64 px 0 ;
border-top : 1 px solid var ( - - rule ) ;
}
. section-num {
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 ;
font-weight : 300 ;
font-size : 4 rem ;
color : var ( - - blueprint ) ;
line-height : 1 ;
margin-bottom : 8 px ;
}
. section-title {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-variation-settings : 'opsz' 60 , 'SOFT' 30 ;
font-size : clamp ( 2 rem , 4 vw , 3 rem ) ;
line-height : 1.1 ;
margin-bottom : 12 px ;
letter-spacing : -0.01 em ;
}
. section-lede {
font-size : 1.15 rem ;
color : var ( - - ink - soft ) ;
max-width : 680 px ;
margin-bottom : 48 px ;
line-height : 1.55 ;
}
/* ============================================================
THE THREE CONCEPTS
============================================================ */
. triad {
display : grid ;
grid-template-columns : repeat ( 3 , 1 fr ) ;
gap : 0 ;
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper ) ;
}
@ media ( max-width : 900px ) {
. triad { grid-template-columns : 1 fr ; }
}
. triad-cell {
padding : 36 px 32 px 40 px ;
position : relative ;
background : var ( - - paper ) ;
transition : background 250 ms ;
}
. triad-cell : not ( : last-child ) {
border-right : 1 px solid var ( - - rule ) ;
}
@ media ( max-width : 900px ) {
. triad-cell : not ( : last-child ) {
border-right : none ;
border-bottom : 1 px solid var ( - - rule ) ;
}
}
. triad-cell : hover { background : var ( - - paper - shade ) ; }
. triad-tag {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.12 em ;
text-transform : uppercase ;
color : var ( - - blueprint ) ;
margin-bottom : 16 px ;
}
. triad-name {
font-family : 'Fraunces' , serif ;
font-weight : 400 ;
font-variation-settings : 'opsz' 100 , 'SOFT' 50 ;
font-size : 2.4 rem ;
line-height : 1 ;
margin-bottom : 8 px ;
color : var ( - - ink ) ;
}
. triad-name em {
font-style : italic ;
color : var ( - - rust ) ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
}
. triad-eq {
font-family : 'Fraunces' , serif ;
font-style : italic ;
color : var ( - - ink - fade ) ;
font-size : 1.05 rem ;
margin-bottom : 24 px ;
}
. triad-body {
font-size : 0.95 rem ;
line-height : 1.6 ;
color : var ( - - ink - soft ) ;
}
. triad-key {
margin-top : 24 px ;
padding-top : 16 px ;
border-top : 1 px dashed var ( - - rule ) ;
font-size : 0.85 rem ;
}
. triad-key b {
font-weight : 600 ;
color : var ( - - ink ) ;
}
. icon-shape {
width : 56 px ;
height : 56 px ;
margin-bottom : 24 px ;
display : flex ;
align-items : center ;
justify-content : center ;
}
/* ============================================================
TIMELINE
============================================================ */
. timeline {
margin-top : 32 px ;
position : relative ;
background : var ( - - paper - shade ) ;
border : 1 px solid var ( - - rule ) ;
padding : 48 px 32 px 40 px ;
border-radius : 2 px ;
overflow-x : auto ;
}
. timeline-rail {
position : relative ;
min-width : 1000 px ;
padding : 16 px 0 48 px ;
}
. timeline-line {
position : absolute ;
top : 50 % ;
left : 0 ;
right : 0 ;
height : 2 px ;
background : var ( - - ink ) ;
background-image : linear-gradient ( to right , var ( - - ink ) 0 , var ( - - ink ) 6 px , transparent 6 px , transparent 12 px ) ;
background-size : 12 px 2 px ;
z-index : 1 ;
}
. timeline-steps {
display : grid ;
grid-template-columns : repeat ( 5 , 1 fr ) ;
gap : 16 px ;
position : relative ;
z-index : 2 ;
}
. t-step {
display : flex ;
flex-direction : column ;
align-items : center ;
text-align : center ;
position : relative ;
}
. t-step-dot {
width : 18 px ;
height : 18 px ;
border-radius : 50 % ;
background : var ( - - paper ) ;
border : 2 px solid var ( - - ink ) ;
margin-bottom : 16 px ;
position : relative ;
}
. t-step-dot . user { background : var ( - - ink ) ; }
. t-step-dot . fire { background : var ( - - amber ) ; border-color : var ( - - amber - deep ) ; }
. t-step-dot . danger { background : var ( - - rust ) ; border-color : var ( - - rust - deep ) ; }
. t-step-dot . done { background : var ( - - sage ) ; border-color : var ( - - sage - deep ) ; }
. t-step-label {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.06 em ;
text-transform : uppercase ;
color : var ( - - blueprint ) ;
margin-bottom : 8 px ;
}
. t-step-title {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-variation-settings : 'opsz' 36 , 'SOFT' 30 ;
font-size : 1.05 rem ;
line-height : 1.15 ;
margin-bottom : 8 px ;
}
. t-step-desc {
font-size : 0.82 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.45 ;
max-width : 200 px ;
}
. t-step-script {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
color : var ( - - rust ) ;
margin-top : 8 px ;
padding : 4 px 8 px ;
background : rgba ( 139 , 58 , 27 , 0.08 ) ;
border-radius : 2 px ;
display : inline-block ;
}
/* Mid-turn micro-section (between UserPromptSubmit and Stop) */
. timeline-inner {
margin : 56 px 24 px 0 ;
padding : 24 px ;
border : 1 px dashed var ( - - blueprint ) ;
background : rgba ( 26 , 110 , 142 , 0.05 ) ;
position : relative ;
}
. timeline-inner-tag {
position : absolute ;
top : -10 px ;
left : 24 px ;
background : var ( - - paper - shade ) ;
padding : 0 12 px ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
text-transform : uppercase ;
letter-spacing : 0.1 em ;
color : var ( - - blueprint ) ;
}
. timeline-inner-grid {
display : grid ;
grid-template-columns : repeat ( 3 , 1 fr ) ;
gap : 20 px ;
}
@ media ( max-width : 900px ) {
. timeline-inner-grid { grid-template-columns : 1 fr ; }
}
. t-inner-step {
padding : 16 px ;
background : var ( - - paper ) ;
border-left : 3 px solid var ( - - blueprint ) ;
}
. t-inner-step . special {
border-left-color : var ( - - rust ) ;
}
. t-inner-title {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1 rem ;
margin-bottom : 4 px ;
line-height : 1.2 ;
}
. t-inner-trigger {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
color : var ( - - ink - fade ) ;
margin-bottom : 8 px ;
}
. t-inner-desc {
font-size : 0.85 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.5 ;
}
/* Parallel hooks (SessionStart, PostCompact) */
. timeline-parallel {
margin-top : 32 px ;
padding-top : 24 px ;
border-top : 1 px solid var ( - - rule ) ;
}
. timeline-parallel-title {
font-family : 'Plus Jakarta Sans' , sans-serif ;
font-weight : 600 ;
text-transform : uppercase ;
letter-spacing : 0.15 em ;
font-size : 0.75 rem ;
color : var ( - - ink - fade ) ;
margin-bottom : 16 px ;
}
. timeline-parallel-list {
display : grid ;
grid-template-columns : 1 fr 1 fr ;
gap : 24 px ;
}
@ media ( max-width : 720px ) {
. timeline-parallel-list { grid-template-columns : 1 fr ; }
}
. tp-item {
display : flex ;
gap : 16 px ;
}
. tp-item-when {
font-family : 'Fraunces' , serif ;
font-style : italic ;
color : var ( - - blueprint ) ;
font-weight : 400 ;
white-space : nowrap ;
min-width : 150 px ;
font-size : 0.95 rem ;
}
. tp-item-what {
font-size : 0.88 rem ;
color : var ( - - ink - soft ) ;
}
/* ============================================================
HOOK ROSTER — table-card hybrid
============================================================ */
. roster {
margin-top : 32 px ;
border : 1 px solid var ( - - rule ) ;
}
. roster-row {
display : grid ;
grid-template-columns : 180 px 220 px 1 fr 120 px ;
gap : 24 px ;
padding : 20 px 28 px ;
border-bottom : 1 px solid var ( - - rule ) ;
align-items : center ;
background : var ( - - paper ) ;
transition : background 200 ms ;
}
. roster-row : last-child { border-bottom : none ; }
. roster-row : hover { background : var ( - - paper - shade ) ; }
. roster-row . header {
background : var ( - - ink ) ;
color : var ( - - paper ) ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.12 em ;
text-transform : uppercase ;
}
. roster-row . header : hover { background : var ( - - ink ) ; }
@ media ( max-width : 900px ) {
. roster-row {
grid-template-columns : 1 fr ;
gap : 8 px ;
}
. roster-row . header { display : none ; }
}
. r-event {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.82 rem ;
font-weight : 500 ;
color : var ( - - blueprint - deep ) ;
}
. r-matcher {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.78 rem ;
color : var ( - - ink - soft ) ;
}
. r-script {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.8 rem ;
color : var ( - - rust ) ;
}
. r-desc {
font-size : 0.92 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.5 ;
}
. r-type {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
text-align : center ;
padding : 4 px 10 px ;
border : 1 px solid ;
width : max-content ;
letter-spacing : 0.05 em ;
text-transform : uppercase ;
}
. r-type . cmd { color : var ( - - sage - deep ) ; border-color : var ( - - sage ) ; background : rgba ( 94 , 122 , 79 , 0.1 ) ; }
. r-type . agent { color : var ( - - rust ) ; border-color : var ( - - rust ) ; background : rgba ( 139 , 58 , 27 , 0.1 ) ; }
/* ============================================================
PERMISSIONS BLOCK
============================================================ */
. perms {
margin-top : 32 px ;
display : grid ;
grid-template-columns : repeat ( 3 , 1 fr ) ;
gap : 20 px ;
}
@ media ( max-width : 900px ) {
. perms { grid-template-columns : 1 fr ; }
}
. perm-card {
padding : 28 px 24 px ;
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper ) ;
position : relative ;
}
. perm-card-num {
position : absolute ;
top : 16 px ;
right : 20 px ;
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
font-weight : 300 ;
font-size : 3.5 rem ;
line-height : 1 ;
}
. perm-card . allow { border-top : 4 px solid var ( - - sage ) ; }
. perm-card . allow . perm-card-num { color : var ( - - sage ) ; }
. perm-card . deny { border-top : 4 px solid var ( - - rust ) ; }
. perm-card . deny . perm-card-num { color : var ( - - rust ) ; }
. perm-card . ask { border-top : 4 px solid var ( - - amber ) ; }
. perm-card . ask . perm-card-num { color : var ( - - amber - deep ) ; }
. perm-card-label {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.72 rem ;
letter-spacing : 0.18 em ;
text-transform : uppercase ;
margin-bottom : 12 px ;
color : var ( - - ink - fade ) ;
}
. perm-card-title {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1.6 rem ;
margin-bottom : 12 px ;
line-height : 1.1 ;
}
. perm-card-body {
font-size : 0.88 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.5 ;
}
/* ============================================================
PLUGINS GRID
============================================================ */
. plugins {
margin-top : 32 px ;
display : grid ;
grid-template-columns : repeat ( 2 , 1 fr ) ;
gap : 24 px ;
}
@ media ( max-width : 900px ) {
. plugins { grid-template-columns : 1 fr ; }
}
. plugin-card {
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper ) ;
padding : 28 px 28 px 24 px ;
position : relative ;
}
. plugin-card-header {
display : flex ;
align-items : flex-start ;
justify-content : space-between ;
margin-bottom : 16 px ;
padding-bottom : 16 px ;
border-bottom : 1 px dashed var ( - - rule ) ;
}
. plugin-card-name {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-variation-settings : 'opsz' 60 , 'SOFT' 30 ;
font-size : 1.5 rem ;
line-height : 1.1 ;
}
. plugin-card-scope {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.08 em ;
text-transform : uppercase ;
padding : 4 px 8 px ;
background : var ( - - ink ) ;
color : var ( - - paper ) ;
}
. plugin-card-desc {
font-size : 0.92 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.55 ;
margin-bottom : 16 px ;
}
. plugin-skills-list {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.78 rem ;
color : var ( - - blueprint - deep ) ;
line-height : 1.7 ;
}
/* ============================================================
SKILLS BY PURPOSE
============================================================ */
. skills-purpose {
margin-top : 32 px ;
}
. sp-row {
display : grid ;
grid-template-columns : 280 px 1 fr ;
gap : 32 px ;
padding : 24 px 0 ;
border-bottom : 1 px solid var ( - - rule ) ;
}
. sp-row : last-child { border-bottom : none ; }
@ media ( max-width : 900px ) {
. sp-row { grid-template-columns : 1 fr ; gap : 12 px ; }
}
. sp-cat {
display : flex ;
flex-direction : column ;
gap : 6 px ;
}
. sp-cat-symbol {
font-family : 'Fraunces' , serif ;
font-variation-settings : 'opsz' 144 , 'WONK' 1 , 'SOFT' 100 ;
font-size : 3 rem ;
font-style : italic ;
font-weight : 300 ;
color : var ( - - rust ) ;
line-height : 1 ;
}
. sp-cat-name {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1.3 rem ;
line-height : 1.2 ;
}
. sp-cat-meta {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.75 rem ;
color : var ( - - ink - fade ) ;
}
. sp-skills {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.85 rem ;
line-height : 1.85 ;
color : var ( - - ink - soft ) ;
}
. sp-skill {
display : inline-block ;
padding : 2 px 8 px ;
margin : 2 px 4 px 2 px 0 ;
background : var ( - - paper - shade ) ;
border : 1 px solid var ( - - rule ) ;
color : var ( - - ink ) ;
font-size : 0.78 rem ;
white-space : nowrap ;
}
/* ============================================================
FILESYSTEM TREE
============================================================ */
. fs {
margin-top : 32 px ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.85 rem ;
line-height : 1.85 ;
background : var ( - - ink ) ;
color : var ( - - paper ) ;
padding : 36 px 32 px ;
border-radius : 2 px ;
overflow-x : auto ;
}
. fs-line {
display : flex ;
align-items : center ;
gap : 12 px ;
white-space : nowrap ;
}
. fs-path { color : var ( - - paper ) ; }
. fs-path b { color : var ( - - amber ) ; font-weight : 600 ; }
. fs-comment { color : var ( - - ink - fade ) ; font-style : italic ; }
. fs-comment :: before { content : '◆ ' ; color : var ( - - amber ) ; }
. fs-section-tag {
display : inline-block ;
padding : 2 px 8 px ;
margin-right : 8 px ;
background : rgba ( 196 , 139 , 38 , 0.2 ) ;
color : var ( - - amber ) ;
font-size : 0.7 rem ;
letter-spacing : 0.08 em ;
text-transform : uppercase ;
border : 1 px solid rgba ( 196 , 139 , 38 , 0.4 ) ;
}
/* ============================================================
MENTAL MODEL
============================================================ */
. mental {
margin-top : 32 px ;
border : 1 px solid var ( - - ink ) ;
padding : 48 px 40 px ;
background : var ( - - paper ) ;
position : relative ;
}
. mental-stage {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr ) ;
gap : 24 px ;
}
@ media ( max-width : 900px ) {
. mental-stage { grid-template-columns : 1 fr ; gap : 32 px ; }
}
. mental-actor {
position : relative ;
padding : 24 px 20 px ;
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper - shade ) ;
}
. mental-actor . you { border-left : 4 px solid var ( - - sage ) ; }
. mental-actor . runtime { border-left : 4 px solid var ( - - blueprint ) ; }
. mental-actor . claude { border-left : 4 px solid var ( - - amber ) ; }
. mental-actor . verifier { border-left : 4 px solid var ( - - rust ) ; }
. mental-tag {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.68 rem ;
letter-spacing : 0.16 em ;
text-transform : uppercase ;
color : var ( - - ink - fade ) ;
margin-bottom : 12 px ;
}
. mental-name {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1.2 rem ;
line-height : 1.1 ;
margin-bottom : 16 px ;
}
. mental-actor . you . mental-name { color : var ( - - sage - deep ) ; }
. mental-actor . runtime . mental-name { color : var ( - - blueprint - deep ) ; }
. mental-actor . claude . mental-name { color : var ( - - amber - deep ) ; }
. mental-actor . verifier . mental-name { color : var ( - - rust ) ; }
. mental-list {
list-style : none ;
font-size : 0.85 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.55 ;
}
. mental-list li {
position : relative ;
padding-left : 14 px ;
margin-bottom : 8 px ;
}
. mental-list li :: before {
content : '→' ;
position : absolute ;
left : 0 ;
color : var ( - - ink - fade ) ;
}
/* ============================================================
PRACTICAL ACTIONS
============================================================ */
. actions {
margin-top : 32 px ;
display : grid ;
grid-template-columns : repeat ( 2 , 1 fr ) ;
gap : 20 px ;
}
@ media ( max-width : 900px ) {
. actions { grid-template-columns : 1 fr ; }
}
. action {
padding : 24 px ;
background : var ( - - paper ) ;
border : 1 px solid var ( - - rule ) ;
position : relative ;
}
. action-num {
position : absolute ;
top : 12 px ;
right : 16 px ;
font-family : 'Fraunces' , serif ;
font-style : italic ;
color : var ( - - blueprint ) ;
font-size : 1.8 rem ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
font-weight : 300 ;
}
. action-want {
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-size : 1.05 rem ;
color : var ( - - ink - fade ) ;
margin-bottom : 6 px ;
}
. action-do {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1.25 rem ;
line-height : 1.2 ;
margin-bottom : 12 px ;
}
. action-cmd {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.82 rem ;
background : var ( - - ink ) ;
color : var ( - - amber ) ;
padding : 12 px 14 px ;
margin-top : 8 px ;
display : block ;
word-break : break-all ;
}
/* ============================================================
FOOTER
============================================================ */
. foot {
margin-top : 80 px ;
padding : 48 px 0 64 px ;
border-top : 2 px solid var ( - - ink ) ;
font-size : 0.85 rem ;
color : var ( - - ink - fade ) ;
display : flex ;
justify-content : space-between ;
flex-wrap : wrap ;
gap : 16 px ;
}
. foot . mono { color : var ( - - ink ) ; }
. foot-ornament {
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
font-size : 1.6 rem ;
font-weight : 300 ;
color : var ( - - rust ) ;
}
/* ============================================================
HIERARCHY SECTION
============================================================ */
. hier-section { margin-top : 32 px ; }
. hier-block {
margin-bottom : 48 px ;
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper ) ;
padding : 32 px 28 px ;
position : relative ;
}
. hier-block : last-child { margin-bottom : 0 ; }
. hier-block-tag {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.16 em ;
text-transform : uppercase ;
color : var ( - - rust ) ;
margin-bottom : 4 px ;
}
. hier-block-title {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-variation-settings : 'opsz' 48 , 'SOFT' 30 ;
font-size : 1.8 rem ;
line-height : 1.1 ;
margin-bottom : 8 px ;
}
. hier-block-lede {
font-size : 0.92 rem ;
color : var ( - - ink - soft ) ;
margin-bottom : 24 px ;
max-width : 640 px ;
line-height : 1.5 ;
}
/* 1. Containment ASCII tree */
. hier-tree {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.85 rem ;
line-height : 1.85 ;
background : var ( - - paper - shade ) ;
border-left : 4 px solid var ( - - blueprint ) ;
padding : 20 px 24 px ;
white-space : pre ;
overflow-x : auto ;
color : var ( - - ink ) ;
}
. hier-tree . root { color : var ( - - rust ) ; font-weight : 700 ; }
. hier-tree . leaf { color : var ( - - blueprint - deep ) ; }
. hier-tree . note { color : var ( - - ink - fade ) ; font-style : italic ; }
/* 2. Priority chain — numbered list */
. hier-priority {
list-style : none ;
counter-reset : prio ;
}
. hier-priority-row {
display : grid ;
grid-template-columns : 60 px 1 fr ;
align-items : start ;
gap : 16 px ;
padding : 14 px 0 ;
border-bottom : 1 px dashed var ( - - rule ) ;
}
. hier-priority-row : last-child { border-bottom : none ; }
. hier-priority-lvl {
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-variation-settings : 'opsz' 144 , 'SOFT' 100 , 'WONK' 1 ;
font-weight : 300 ;
font-size : 2.4 rem ;
line-height : 0.9 ;
color : var ( - - blueprint ) ;
}
. hier-priority-row . locked . hier-priority-lvl { color : var ( - - rust ) ; }
. hier-priority-content {
display : flex ;
flex-direction : column ;
gap : 4 px ;
}
. hier-priority-name {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1.1 rem ;
line-height : 1.15 ;
color : var ( - - ink ) ;
}
. hier-priority-name . badge {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.65 rem ;
letter-spacing : 0.1 em ;
text-transform : uppercase ;
padding : 2 px 6 px ;
background : var ( - - rust ) ;
color : var ( - - paper ) ;
margin-left : 8 px ;
vertical-align : middle ;
}
. hier-priority-note {
font-size : 0.85 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.45 ;
}
/* 3. Event timing — horizontal cards */
. hier-timing {
display : grid ;
grid-template-columns : repeat ( auto - fit , minmax ( 180 px , 1 fr ) ) ;
gap : 16 px ;
margin-top : 16 px ;
}
. hier-event {
padding : 16 px 14 px 14 px ;
background : var ( - - paper - shade ) ;
border-top : 3 px solid var ( - - sage ) ;
position : relative ;
}
. hier-event . once { border-top-color : var ( - - sage ) ; }
. hier-event . per-turn { border-top-color : var ( - - blueprint ) ; }
. hier-event . per-tool { border-top-color : var ( - - amber ) ; }
. hier-event . special { border-top-color : var ( - - rust ) ; }
. hier-event-num {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.1 em ;
color : var ( - - ink - fade ) ;
margin-bottom : 4 px ;
}
. hier-event-name {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.95 rem ;
font-weight : 500 ;
color : var ( - - ink ) ;
margin-bottom : 4 px ;
}
. hier-event-freq {
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-size : 0.82 rem ;
color : var ( - - ink - soft ) ;
margin-bottom : 8 px ;
}
. hier-event-script {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
color : var ( - - rust ) ;
}
/* ============================================================
SKILLS DETAIL (replaces sp-skills chip-only)
============================================================ */
. sp-skills-detail {
display : flex ;
flex-direction : column ;
gap : 0 ;
}
. sp-skill-row {
display : grid ;
grid-template-columns : 220 px 1 fr ;
gap : 20 px ;
padding : 12 px 0 ;
border-bottom : 1 px dashed var ( - - rule ) ;
align-items : baseline ;
}
. sp-skill-row : last-child { border-bottom : none ; }
@ media ( max-width : 720px ) {
. sp-skill-row { grid-template-columns : 1 fr ; gap : 4 px ; padding : 14 px 0 ; }
}
. sp-skill-key {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.82 rem ;
font-weight : 500 ;
color : var ( - - blueprint - deep ) ;
}
. sp-skill-what {
font-size : 0.9 rem ;
color : var ( - - ink - soft ) ;
line-height : 1.5 ;
}
. sp-skill-what em {
font-family : 'Fraunces' , serif ;
font-style : italic ;
color : var ( - - rust ) ;
font-weight : 500 ;
}
/* ============================================================
CONNECTIONS GRAPH (§X)
============================================================ */
. graph-controls {
margin-top : 32 px ;
display : flex ;
justify-content : space-between ;
align-items : center ;
gap : 16 px ;
flex-wrap : wrap ;
padding : 16 px 0 ;
border-top : 1 px solid var ( - - rule ) ;
border-bottom : 1 px solid var ( - - rule ) ;
}
. graph-filters {
display : flex ;
gap : 8 px ;
flex-wrap : wrap ;
}
. graph-filter {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.72 rem ;
letter-spacing : 0.08 em ;
text-transform : uppercase ;
padding : 6 px 12 px ;
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper ) ;
color : var ( - - ink ) ;
cursor : pointer ;
transition : background 200 ms , color 200 ms ;
}
. graph-filter . active {
background : var ( - - ink ) ;
color : var ( - - paper ) ;
border-color : var ( - - ink ) ;
}
. graph-filter : hover { background : var ( - - paper - shade ) ; }
. graph-filter . active : hover { background : var ( - - ink - soft ) ; }
. graph-reset {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.72 rem ;
letter-spacing : 0.08 em ;
text-transform : uppercase ;
padding : 6 px 14 px ;
border : 1 px solid var ( - - rust ) ;
background : var ( - - paper ) ;
color : var ( - - rust ) ;
cursor : pointer ;
}
. graph-reset : hover { background : var ( - - rust ) ; color : var ( - - paper ) ; }
. graph-container {
margin-top : 24 px ;
display : grid ;
grid-template-columns : 1 fr 280 px ;
gap : 24 px ;
align-items : start ;
}
. graph-svg-wrap {
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper - shade ) ;
background-image :
linear-gradient ( rgba ( 14 , 34 , 53 , 0.03 ) 1 px , transparent 1 px ) ,
linear-gradient ( 90 deg , rgba ( 14 , 34 , 53 , 0.03 ) 1 px , transparent 1 px ) ;
background-size : 24 px 24 px ;
overflow : hidden ;
min-height : 700 px ;
}
. graph-svg {
width : 100 % ;
height : 700 px ;
display : block ;
cursor : default ;
}
. graph-sidebar {
border : 1 px solid var ( - - rule ) ;
background : var ( - - paper ) ;
padding : 20 px 18 px ;
font-size : 0.88 rem ;
min-height : 200 px ;
position : relative ;
}
. graph-sidebar-empty {
color : var ( - - ink - fade ) ;
font-style : italic ;
font-family : 'Fraunces' , serif ;
}
. graph-sidebar-title {
font-family : 'Fraunces' , serif ;
font-weight : 500 ;
font-size : 1.15 rem ;
margin-bottom : 4 px ;
line-height : 1.15 ;
}
. graph-sidebar-badge {
display : inline-block ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.65 rem ;
letter-spacing : 0.1 em ;
text-transform : uppercase ;
padding : 2 px 8 px ;
background : var ( - - ink ) ;
color : var ( - - paper ) ;
margin-bottom : 12 px ;
}
. graph-sidebar-section {
margin-top : 16 px ;
padding-top : 12 px ;
border-top : 1 px dashed var ( - - rule ) ;
}
. graph-sidebar-section . governance {
border-top : 2 px solid var ( - - rust ) ;
padding-top : 14 px ;
}
. graph-sidebar-navlink {
margin-top : 10 px ;
padding : 5 px 10 px ;
border : 1 px solid var ( - - blueprint ) ;
background : var ( - - paper ) ;
color : var ( - - blueprint - deep ) ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
letter-spacing : 0.06 em ;
text-transform : uppercase ;
cursor : pointer ;
transition : background 200 ms , color 200 ms ;
}
. graph-sidebar-navlink : hover { background : var ( - - blueprint ) ; color : var ( - - paper ) ; }
. graph-sidebar-section-label {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.68 rem ;
letter-spacing : 0.12 em ;
text-transform : uppercase ;
color : var ( - - ink - fade ) ;
margin-bottom : 8 px ;
}
. graph-conn-list {
list-style : none ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.78 rem ;
line-height : 1.7 ;
color : var ( - - ink - soft ) ;
}
. graph-conn-list li b { color : var ( - - rust ) ; font-weight : 600 ; }
. graph-close {
position : absolute ;
top : 12 px ;
right : 14 px ;
border : none ;
background : transparent ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 1.2 rem ;
cursor : pointer ;
color : var ( - - ink - fade ) ;
}
. graph-close : hover { color : var ( - - rust ) ; }
. graph-legend {
margin-top : 24 px ;
padding : 20 px 24 px ;
background : var ( - - paper ) ;
border : 1 px solid var ( - - rule ) ;
display : grid ;
grid-template-columns : 1 fr 1 fr ;
gap : 24 px ;
}
. graph-legend-section h4 {
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.68 rem ;
letter-spacing : 0.14 em ;
text-transform : uppercase ;
color : var ( - - ink - fade ) ;
margin-bottom : 12 px ;
font-weight : 500 ;
}
. graph-legend-item {
display : flex ;
align-items : center ;
gap : 12 px ;
margin-bottom : 8 px ;
font-size : 0.82 rem ;
color : var ( - - ink - soft ) ;
}
. graph-legend-swatch {
width : 16 px ;
height : 16 px ;
border : 1.5 px solid var ( - - ink ) ;
flex-shrink : 0 ;
}
. graph-legend-line {
width : 28 px ;
height : 0 ;
border-top : 2 px solid var ( - - ink ) ;
flex-shrink : 0 ;
}
. graph-fallback {
padding : 48 px ;
text-align : center ;
color : var ( - - rust ) ;
font-family : 'Fraunces' , serif ;
font-style : italic ;
font-size : 1 rem ;
}
/* SVG node styles */
. gn-plugin { fill : var ( - - rust ) ; stroke : var ( - - ink ) ; stroke-width : 2 ; }
. gn-skill { fill : var ( - - blueprint ) ; stroke : var ( - - ink ) ; stroke-width : 1.5 ; }
. gn-script { fill : var ( - - amber ) ; stroke : var ( - - ink ) ; stroke-width : 1.5 ; }
. gn-event { fill : var ( - - sage ) ; stroke : var ( - - ink ) ; stroke-width : 2 ; }
. gn-state { fill : var ( - - rust ) ; stroke : var ( - - ink ) ; stroke-width : 2 ; }
. gn-perm { fill : var ( - - ink - fade ) ; stroke : var ( - - ink ) ; stroke-width : 1.5 ; }
. gn-rule { fill : var ( - - ink ) ; stroke : var ( - - rust ) ; stroke-width : 2 ; }
. gn-label {
font-family : 'Fraunces' , serif ;
font-size : 9 px ;
font-weight : 500 ;
fill : var ( - - ink ) ;
pointer-events : none ;
text-anchor : middle ;
}
. gn-node { cursor : pointer ; }
. gn-node : hover { filter : brightness ( 1.1 ) ; }
. dimmed { opacity : 0.15 ; }
. highlighted { opacity : 1 ; }
/* SVG link styles */
. gl { fill : none ; pointer-events : stroke ; }
. gl-contains { stroke : var ( - - blueprint ) ; stroke-width : 1.5 ; }
. gl-triggers { stroke : var ( - - sage ) ; stroke-width : 2 ; }
. gl-writes { stroke : var ( - - amber ) ; stroke-width : 2 ; }
. gl-reads { stroke : var ( - - amber ) ; stroke-width : 1.5 ; stroke-dasharray : 4 3 ; }
. gl-mandates { stroke : var ( - - rust ) ; stroke-width : 2.5 ; }
. gl-references { stroke : var ( - - ink - fade ) ; stroke-width : 1 ; stroke-dasharray : 2 3 ; }
. gl-blocks { stroke : var ( - - rust ) ; stroke-width : 1.5 ; stroke-dasharray : 5 3 ; }
. gl-denies { stroke : var ( - - rust ) ; stroke-width : 2 ; stroke-dasharray : 2 2 ; }
. gl-tooltip {
position : absolute ;
background : var ( - - ink ) ;
color : var ( - - paper ) ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.72 rem ;
padding : 4 px 8 px ;
pointer-events : none ;
z-index : 100 ;
border : 1 px solid var ( - - paper - shade ) ;
}
@ media ( max-width : 900px ) {
. graph-container { grid-template-columns : 1 fr ; }
. graph-svg-wrap { overflow-x : auto ; }
. graph-svg { min-width : 900 px ; }
. graph-sidebar {
position : fixed ;
bottom : 0 ; left : 0 ; right : 0 ;
border-top : 2 px solid var ( - - ink ) ;
border-left : none ; border-right : none ; border-bottom : none ;
z-index : 50 ;
max-height : 60 vh ;
overflow-y : auto ;
}
. graph-legend { grid-template-columns : 1 fr ; }
}
/* ============================================================
PAGE LOAD ANIMATION
============================================================ */
@ keyframes rise {
from { opacity : 0 ; transform : translateY ( 20 px ) ; }
to { opacity : 1 ; transform : translateY ( 0 ) ; }
}
. hero , . section { animation : rise 700 ms cubic-bezier ( 0.2 , 0.8 , 0.2 , 1 ) backwards ; }
. section : nth-of-type ( 1 ) { animation-delay : 100 ms ; }
. section : nth-of-type ( 2 ) { animation-delay : 200 ms ; }
. section : nth-of-type ( 3 ) { animation-delay : 300 ms ; }
. section : nth-of-type ( 4 ) { animation-delay : 400 ms ; }
. section : nth-of-type ( 5 ) { animation-delay : 500 ms ; }
. section : nth-of-type ( 6 ) { animation-delay : 600 ms ; }
. section : nth-of-type ( 7 ) { animation-delay : 700 ms ; }
. section : nth-of-type ( 8 ) { animation-delay : 800 ms ; }
@ media ( prefers-reduced-motion : reduce ) {
* , * :: before , * :: after {
animation : none !important ;
transition : none !important ;
}
html { scroll-behavior : auto ; }
}
/* Decorative SVG underline for hero title */
. hero-title-svg {
display : block ;
width : 140 px ;
margin : 16 px 0 0 ;
}
. hero-title-svg path {
fill : none ;
stroke : var ( - - rust ) ;
stroke-width : 2 ;
stroke-linecap : round ;
}
< / style >
< / head >
< body >
< main >
<!-- ============================================================
HERO
============================================================ -->
< header class = "hero" >
< div class = "frame" >
< div class = "hero-meta" >
< span class = "caps" > Carta · vol. i · 2026< / span >
< span class = "hero-meta-divider" > < / span >
2026-05-11 12:59:30 +03:00
< span class = "mono" > 11.05.2026< / span >
2026-05-11 00:46:51 +03:00
< / div >
< h1 class = "hero-title display" >
Карта работы< br >
< em > hooks< / em > · < em > skills< / em > · < em > plugins< / em >
< / h1 >
< svg class = "hero-title-svg" viewBox = "0 0 140 16" xmlns = "http://www.w3.org/2000/svg" >
< path d = "M2 10 Q 35 2, 70 8 T 138 6" / >
< / svg >
< p class = "hero-sub" >
2026-05-11 12:59:30 +03:00
Иллюстрированный справочник по внутреннему устройству Claude Code в проекте с установленным < span class = "mono" > claude-brain v1.0< / span > .
2026-05-11 00:46:51 +03:00
Что срабатывает в начале промпта, что — посреди вашей работы, и что — в конце.
2026-05-11 12:59:30 +03:00
< strong > Три типа сущностей, семь хуков, пять событий, четыре плагина, четыре MCP-сервера.< / strong >
2026-05-11 00:46:51 +03:00
< / p >
< div class = "hero-stamp" >
2026-05-11 12:59:30 +03:00
< span class = "num" > vIV< / span >
2026-05-11 00:46:51 +03:00
< span class = "lbl" > Edition · Carta< / span >
< / div >
< / div >
< / header >
<!-- ============================================================
I. THE THREE CONCEPTS
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > I< / div >
< h2 class = "section-title" > Три типа сущностей< / h2 >
< p class = "section-lede" >
Чтобы не путаться, важно понимать на каком слое живёт каждая вещь.
Один и тот же объект может быть одновременно частью плагина, скилом по природе и автоматизированным
хуком в действии — но < em > роль< / em > у каждого своя.
< / p >
< div class = "triad" >
< div class = "triad-cell" >
< div class = "triad-tag" > Слой 01 · Доставка< / div >
< div class = "icon-shape" >
< svg width = "56" height = "56" viewBox = "0 0 56 56" xmlns = "http://www.w3.org/2000/svg" >
< rect x = "8" y = "14" width = "40" height = "32" fill = "none" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "8" y1 = "22" x2 = "48" y2 = "22" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "28" y1 = "14" x2 = "28" y2 = "46" stroke = "#0E2235" stroke-width = "2" stroke-dasharray = "2 3" / >
< circle cx = "28" cy = "22" r = "3" fill = "#C48B26" / >
< / svg >
< / div >
< div class = "triad-name" > Плагин< / div >
< div class = "triad-eq" > = коробка / упаковка< / div >
< div class = "triad-body" >
Контейнер. Сам ничего не исполняет — только доставляет в систему скилы, slash-команды,
хуки, MCP-серверы и subagent'ы. Как rpm-пакет или npm-модуль: внутри что-то полезное, наружу — манифест.
< / div >
< div class = "triad-key" >
< b > Установка:< / b > через marketplace в < span class = "mono" > ~/.claude/settings.json< / span > .
< / div >
< / div >
< div class = "triad-cell" >
< div class = "triad-tag" > Слой 02 · Инструкция< / div >
< div class = "icon-shape" >
< svg width = "56" height = "56" viewBox = "0 0 56 56" xmlns = "http://www.w3.org/2000/svg" >
< path d = "M14 8 L42 8 L42 48 L14 48 Z" fill = "none" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "20" y1 = "16" x2 = "36" y2 = "16" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "20" y1 = "24" x2 = "36" y2 = "24" stroke = "#0E2235" stroke-width = "1.5" / >
< line x1 = "20" y1 = "30" x2 = "32" y2 = "30" stroke = "#0E2235" stroke-width = "1.5" / >
< line x1 = "20" y1 = "36" x2 = "36" y2 = "36" stroke = "#0E2235" stroke-width = "1.5" / >
< / svg >
< / div >
< div class = "triad-name" > Скил< em > ·< / em > < / div >
< div class = "triad-eq" > = инструкция в markdown< / div >
< div class = "triad-body" >
Текст, который я (Claude) читаю и которому следую. Например, «брейнсторм, потом план, потом TDD».
Я < strong > могу его проигнорировать< / strong > — это soft-правило: дисциплинированное самоприменение,
а не runtime gate.
< / div >
< div class = "triad-key" >
< b > Вызов:< / b > через < span class = "mono" > Skill< / span > -tool или slash < span class = "mono" > /имя< / span > .
< / div >
< / div >
< div class = "triad-cell" >
< div class = "triad-tag" > Слой 03 · Принуждение< / div >
< div class = "icon-shape" >
< svg width = "56" height = "56" viewBox = "0 0 56 56" xmlns = "http://www.w3.org/2000/svg" >
< circle cx = "28" cy = "28" r = "18" fill = "none" stroke = "#8B3A1B" stroke-width = "2" / >
< rect x = "22" y = "22" width = "12" height = "12" fill = "#8B3A1B" / >
< line x1 = "4" y1 = "28" x2 = "10" y2 = "28" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "46" y1 = "28" x2 = "52" y2 = "28" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "28" y1 = "4" x2 = "28" y2 = "10" stroke = "#0E2235" stroke-width = "2" / >
< line x1 = "28" y1 = "46" x2 = "28" y2 = "52" stroke = "#0E2235" stroke-width = "2" / >
< / svg >
< / div >
< div class = "triad-name" > Хук< / div >
< div class = "triad-eq" > = shell-скрипт runtime'а < / div >
< div class = "triad-body" >
Команда, которую запускает < strong > сам Claude Code< / strong > в момент события (UserPromptSubmit, Stop, etc).
Я < strong > не могу его обойти< / strong > и не вижу момент запуска. Это реальный gate.
< / div >
< div class = "triad-key" >
< b > Зарегистрирован:< / b > в < span class = "mono" > hooks< / span > блоке settings.json.
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
II. HIERARCHY & ORDER
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > II< / div >
< h2 class = "section-title" > Иерархия и порядок< / h2 >
< p class = "section-lede" >
Три разные «иерархии» накладываются друг на друга и часто путают.
< em > Контейнерная< / em > отвечает на «что внутри чего».
< em > Приоритетная< / em > — на «что важнее при конфликте».
< em > Временная< / em > — на «что срабатывает раньше».
< / p >
< div class = "hier-section" >
<!-- 1. CONTAINMENT -->
< div class = "hier-block" >
< div class = "hier-block-tag" > 1 · Контейнерная< / div >
< h3 class = "hier-block-title" > Что внутри чего лежит< / h3 >
< p class = "hier-block-lede" >
Плагин — упаковка. Содержит скилы, хуки, slash-команды, MCP-серверы, subagent'ы.
Сам плагин ничего не делает. Хуки регистрируются в settings.json и запускаются
самим Claude Code. Скилы — это .md-файлы, которые я читаю и которым следую.
< / p >
< div class = "hier-tree" > < span class = "root" > ПЛАГИН< / span > < span class = "note" > упаковка / контейнер< / span >
├─ < span class = "leaf" > Skills< / span > .md-инструкции для Claude
├─ < span class = "leaf" > Hooks< / span > Python/Bash скрипты + регистрация в settings.json
├─ < span class = "leaf" > Slash-commands< / span > /имя в промпте → запускает skill или агента
├─ < span class = "leaf" > MCP servers< / span > внешние tool-провайдеры
└─ < span class = "leaf" > Subagents< / span > специализированные агенты-исполнители
< span class = "root" > settings.json< / span > < span class = "note" > главный runtime конфиг< / span >
├─ < span class = "leaf" > enabledPlugins< / span > что включить
├─ < span class = "leaf" > permissions< / span > allow / deny / ask правила
├─ < span class = "leaf" > hooks< / span > event → matcher → handler
└─ < span class = "leaf" > env / mcp / ...< / span > остальное
< span class = "note" > ─── ПОТОКИ ВЛИЯНИЯ ───────────────────────────────────< / span >
Hook script ──> может запустить ЛЮБУЮ команду (Python, Bash, agent)
Skill markdown ──> я читаю и следую (но могу проигнорировать)
Plugin ──> ничего не делает сам — только доставляет содержимое< / div >
< / div >
<!-- 2. PRIORITY CHAIN -->
< div class = "hier-block" >
< div class = "hier-block-tag" > 2 · Приоритетная< / div >
< h3 class = "hier-block-title" > Что override'ит что при конфликте< / h3 >
< p class = "hier-block-lede" >
Когда правила противоречат — побеждает < em > верхний< / em > уровень.
Так договорились в CLAUDE.md §1. Уровень 0 — единственный неотменяемый
(даже « отступления» не отменяют его).
< / p >
< div class = "hier-priority" >
< div class = "hier-priority-row locked" >
< div class = "hier-priority-lvl" > 0< / div >
< div class = "hier-priority-content" >
< div class = "hier-priority-name" > Pravila §12 < span class = "badge" > hard rule< / span > < / div >
< div class = "hier-priority-note" > Superpowers hard rule — инвокировать skill ПЕРВЫМ для подходящих задач.
§9 «Отступления» к этому не применяется. Неотменяемо.< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 1< / div >
< div class = "hier-priority-content" >
2026-05-11 12:59:30 +03:00
< div class = "hier-priority-name" > Pravila_raboty_Claude.md< / div >
2026-05-11 00:46:51 +03:00
< div class = "hier-priority-note" > Продуктовые правила работы Claude, утверждены заказчиком (~13 секций).< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 2a< / div >
< div class = "hier-priority-content" >
< div class = "hier-priority-name" > CLAUDE.md< / div >
< div class = "hier-priority-note" > Общая оперативная карта проекта, ссылается на источники истины.< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 2b< / div >
< div class = "hier-priority-content" >
< div class = "hier-priority-name" > Tooling Прил. Н < / div >
< div class = "hier-priority-note" > Детальный реестр 33 инструментов. При конфликте с 2a — приоритет у CLAUDE.md как корневой карты.< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 3< / div >
< div class = "hier-priority-content" >
2026-05-11 12:59:30 +03:00
< div class = "hier-priority-name" > Plugin_stack_rules.md< / div >
2026-05-11 00:46:51 +03:00
< div class = "hier-priority-note" > Координирующий слой между плагинами (Superpowers + Frontend Design + UPM + 21st Magic), 16 правил.< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 4< / div >
< div class = "hier-priority-content" >
< div class = "hier-priority-name" > ~/.claude/settings.json< / div >
< div class = "hier-priority-note" > Runtime config: хуки, permissions, плагины. Исполняется средой Claude Code, не мной.< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 5< / div >
< div class = "hier-priority-content" >
< div class = "hier-priority-name" > memory/*.md< / div >
< div class = "hier-priority-note" > Кросс-сессионные факты о проекте, заказчике, окружении. Может быть stale — нужно verify.< / div >
< / div >
< / div >
< div class = "hier-priority-row" >
< div class = "hier-priority-lvl" > 6< / div >
< div class = "hier-priority-content" >
< div class = "hier-priority-name" > Прочие плагины< / div >
< div class = "hier-priority-note" > claude-md-management, ui-ux-pro-max, frontend-design, и т. д. — поведенческие подсказки.< / div >
< / div >
< / div >
< / div >
< / div >
<!-- 3. TIMING -->
< div class = "hier-block" >
< div class = "hier-block-tag" > 3 · Временная< / div >
< h3 class = "hier-block-title" > В каком порядке всё срабатывает< / h3 >
< p class = "hier-block-lede" >
События имеют фиксированный порядок в жизненном цикле сессии. Цвет верхней полосы
— это частота срабатывания: < em > один раз< / em > (зелёный), < em > на каждый submit< / em > (синий),
< em > на каждый tool call< / em > (янтарь), < em > нерегулярно< / em > (ржавый).
< / p >
< div class = "hier-timing" >
< div class = "hier-event once" >
< div class = "hier-event-num" > 1·once< / div >
< div class = "hier-event-name" > SessionStart< / div >
< div class = "hier-event-freq" > один раз на старте сессии< / div >
< div class = "hier-event-script" > economy-self-check.py< / div >
< / div >
< div class = "hier-event per-turn" >
< div class = "hier-event-num" > 2·per submit< / div >
< div class = "hier-event-name" > UserPromptSubmit< / div >
< div class = "hier-event-freq" > каждый раз когда вы отправляете промпт< / div >
< div class = "hier-event-script" > economy-mode.py< / div >
< / div >
< div class = "hier-event per-tool" >
< div class = "hier-event-num" > 3·per tool< / div >
< div class = "hier-event-name" > PreToolUse< / div >
< div class = "hier-event-freq" > перед каждым моим tool-вызовом< / div >
< div class = "hier-event-script" > skill-marker · skill-check · state-guard< / div >
< / div >
< div class = "hier-event special" >
< div class = "hier-event-num" > 4·per response< / div >
< div class = "hier-event-name" > Stop< / div >
< div class = "hier-event-freq" > конец моего ответа на вас< / div >
< div class = "hier-event-script" > Sonnet 4.6 verifier (agent-type)< / div >
< / div >
< div class = "hier-event special" >
< div class = "hier-event-num" > 5·irregular< / div >
< div class = "hier-event-name" > PostCompact< / div >
< div class = "hier-event-freq" > когда runtime сжимает старые сообщения< / div >
< div class = "hier-event-script" > economy-postcompact.py< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
III. TIMELINE OF A TURN
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > III< / div >
< h2 class = "section-title" > Хронология одного запроса< / h2 >
< p class = "section-lede" >
Что именно происходит за кулисами, пока вы пишете промпт и читаете ответ.
Пять чёрных дисков — главные события. Внутренний прямоугольник —
то, что повторяется на каждый мой tool-вызов.
< / p >
< div class = "timeline" >
< div class = "timeline-rail" >
< div class = "timeline-line" > < / div >
< div class = "timeline-steps" >
< div class = "t-step" >
< div class = "t-step-dot user" > < / div >
< div class = "t-step-label" > Шаг 1< / div >
< div class = "t-step-title" > Вы пишете промпт< / div >
< div class = "t-step-desc" > с опциональным «экономия N%» в самом конце< / div >
< / div >
< div class = "t-step" >
< div class = "t-step-dot fire" > < / div >
< div class = "t-step-label" > UserPromptSubmit< / div >
< div class = "t-step-title" > Парсер уровня< / div >
< div class = "t-step-desc" > парсит экономию, пишет state-файл, инжектит правила в мой контекст< / div >
< div class = "t-step-script" > economy-mode.py< / div >
< / div >
< div class = "t-step" >
< div class = "t-step-dot" > < / div >
< div class = "t-step-label" > Шаг 3< / div >
< div class = "t-step-title" > Я думаю и действую< / div >
< div class = "t-step-desc" > читаю, вызываю инструменты, привожу аргументы< / div >
< / div >
< div class = "t-step" >
< div class = "t-step-dot danger" > < / div >
< div class = "t-step-label" > Stop · agent< / div >
< div class = "t-step-title" > Верификатор< / div >
< div class = "t-step-desc" > Sonnet 4.6 читает ответ, ловит cherry-pick и блокирует< / div >
< div class = "t-step-script" > claude-sonnet-4-6< / div >
< / div >
< div class = "t-step" >
< div class = "t-step-dot done" > < / div >
< div class = "t-step-label" > Шаг 5< / div >
< div class = "t-step-title" > Вы видите ответ< / div >
< div class = "t-step-desc" > проверенный, или с пометкой о повторной попытке< / div >
< / div >
< / div >
< div class = "timeline-inner" >
< span class = "timeline-inner-tag" > Внутри шага 3 · PreToolUse< / span >
< div class = "timeline-inner-grid" >
< div class = "t-inner-step" >
< div class = "t-inner-title" > Маркер скила< / div >
< div class = "t-inner-trigger" > matcher: Skill< / div >
< div class = "t-inner-desc" > Каждый раз, когда я вызываю Skill — фиксирует «отметку» в темпе сессии.
Часть механизма «дисциплина».< / div >
< div class = "t-step-script" style = "margin-top:8px;" > skill-marker.py< / div >
< / div >
< div class = "t-inner-step" >
< div class = "t-inner-title" > Проверка дисциплины< / div >
< div class = "t-inner-trigger" > matcher: Edit|Write|MultiEdit< / div >
< div class = "t-inner-desc" > Если я делаю правки без вызова скила — напоминает о §12 правил Claude.
Не блокирует, только подсказывает.< / div >
< div class = "t-step-script" style = "margin-top:8px;" > skill-check.py< / div >
< / div >
< div class = "t-inner-step special" >
< div class = "t-inner-title" > Страж экономии< / div >
< div class = "t-inner-trigger" > matcher: Edit|Write|MultiEdit|Bash|Agent< / div >
< div class = "t-inner-desc" > Напоминает активный уровень при каждом действии. Ловит Bash-обходы (< span class = "mono" > sed -i< / span > , < span class = "mono" > echo > < / span > ).
Передаёт уровень subagent'у .< / div >
< div class = "t-step-script" style = "margin-top:8px;" > economy-state-guard.py< / div >
< / div >
< / div >
< / div >
< div class = "timeline-parallel" >
< div class = "timeline-parallel-title" > Происходит отдельно< / div >
< div class = "timeline-parallel-list" >
< div class = "tp-item" >
< span class = "tp-item-when" > На старте сессии< / span >
< span class = "tp-item-what" >
< strong > economy-self-check.py< / strong > проверяет, что все 5 hook-скриптов и Python на месте,
а settings.json валиден. При проблемах — видимое предупреждение в UI.
< / span >
< / div >
< div class = "tp-item" >
< span class = "tp-item-when" > После авто-сжатия< / span >
< span class = "tp-item-what" >
< strong > economy-postcompact.py< / strong > re-injects активный уровень обратно в контекст,
чтобы я не «забывал» правила после потери начала сессии.
< / span >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
III. HOOK ROSTER
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > IV< / div >
< h2 class = "section-title" > Реестр хуков — построчно< / h2 >
< p class = "section-lede" >
Семь активных хуков, четыре уникальных события, два типа исполнителей.
Шесть хуков — обычные shell-команды (Python-скрипты), один — agent-type с моделью Sonnet 4.6.
< / p >
< div class = "roster" >
< div class = "roster-row header" >
< div > Событие< / div >
< div > Matcher< / div >
< div > Что делает< / div >
< div > Тип< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > SessionStart< / div >
< div class = "r-matcher" > (any)< / div >
< div class = "r-desc" >
< strong > economy-self-check.py< / strong > · Проверяет инфраструктуру: hook-скрипты, Python в PATH, settings.json.
< / div >
< div class = "r-type cmd" > command< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > UserPromptSubmit< / div >
< div class = "r-matcher" > (any)< / div >
< div class = "r-desc" >
< strong > economy-mode.py< / strong > · Парсит «экономия N%» в конце промпта, пишет state, инжектит правила.
< / div >
< div class = "r-type cmd" > command< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > PreToolUse< / div >
< div class = "r-matcher" > Skill< / div >
< div class = "r-desc" >
< strong > skill-marker.py< / strong > · «Дисциплина»: ставит per-session отметку «скил был вызван».
< / div >
< div class = "r-type cmd" > command< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > PreToolUse< / div >
< div class = "r-matcher" > Edit|Write|MultiEdit< / div >
< div class = "r-desc" >
< strong > skill-check.py< / strong > · «Дисциплина»: если отметки нет — напоминание о §12 правил Claude.
< / div >
< div class = "r-type cmd" > command< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > PreToolUse< / div >
< div class = "r-matcher" > Edit|Write|MultiEdit|Bash|Agent< / div >
< div class = "r-desc" >
< strong > economy-state-guard.py< / strong > · Reminder активного уровня + Bash-bypass detection + subagent inheritance.
< / div >
< div class = "r-type cmd" > command< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > PostCompact< / div >
< div class = "r-matcher" > (any)< / div >
< div class = "r-desc" >
< strong > economy-postcompact.py< / strong > · После авто-сжатия истории re-injects правила активного уровня.
< / div >
< div class = "r-type cmd" > command< / div >
< / div >
< div class = "roster-row" >
< div class = "r-event" > Stop< / div >
< div class = "r-matcher" > (any)< / div >
< div class = "r-desc" >
< strong > Sonnet 4.6 verifier< / strong > · Inline agent в settings.json. Читает мой ответ + tool calls,
эмитит decision: «block» при нарушениях. Timeout 90 сек.
< / div >
< div class = "r-type agent" > agent< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
IV. PERMISSIONS BLOCK
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > V< / div >
< h2 class = "section-title" > Блок разрешений — Stage 0 ratchet< / h2 >
< p class = "section-lede" >
Декларативная защита от обхода. Эти правила в settings.json исполняются Claude Code < em > до< / em > того,
как я успею что-то сделать. После их установки даже я сам не могу нейтрализовать систему через Edit или Bash —
проверено на практике.
< / p >
< div class = "perms" >
< div class = "perm-card allow" >
< span class = "perm-card-num" > 1< / span >
< div class = "perm-card-label" > allow< / div >
< div class = "perm-card-title" > Разрешено< br > без вопросов< / div >
< div class = "perm-card-body" >
Одно правило: < span class = "mono" > Bash(git push origin main:*)< / span > — пуш в main без диалога.
Всё остальное идёт по обычным правилам Claude Code.
< / div >
< / div >
< div class = "perm-card deny" >
< span class = "perm-card-num" > 7< / span >
< div class = "perm-card-label" > deny< / div >
< div class = "perm-card-title" > Жёстко< br > заблокировано< / div >
< div class = "perm-card-body" >
Семь паттернов: < span class = "mono" > rm< / span > и < span class = "mono" > mv< / span > на hook-скрипты,
на settings.json, и на state-файлы экономии. Никаких prompts — просто отказ.
< / div >
< / div >
< div class = "perm-card ask" >
< span class = "perm-card-num" > 16< / span >
< div class = "perm-card-label" > ask< / div >
< div class = "perm-card-title" > Только< br > с вашим approve< / div >
< div class = "perm-card-body" >
Шестнадцать правил: каждый Edit и Write на settings.json или любой hook-скрипт триггерит
permission prompt. Вы видите, что я хочу сделать, и решаете.
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
V. PLUGINS
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > VI< / div >
< h2 class = "section-title" > Установленные плагины< / h2 >
< p class = "section-lede" >
Четыре плагина, доставленных через marketplace. Каждый включает в себя один или больше скилов.
Сами плагины ничего не делают — только привозят содержимое.
< / p >
< div class = "plugins" >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > superpowers< / div >
< div class = "plugin-card-scope" > obra/superpowers · v5.1.0< / div >
< / div >
< div class = "plugin-card-desc" >
Главный плагин дисциплины процесса работы. Содержит 14 скилов: brainstorm, plan, execute,
TDD, debug, code-review, verify, parallel agents, worktrees, finishing-branch, writing-skills…
Связан с §12 Pravila — half-вес проекта.
< / div >
< div class = "plugin-skills-list" >
14 skills · процесс работы
< / div >
< / div >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > claude-md-management< / div >
< div class = "plugin-card-scope" > anthropic · claude-plugins-official< / div >
< / div >
< div class = "plugin-card-desc" >
Единственный канал правок корневого CLAUDE.md. Не даёт ему расходиться с Pravila и Tooling.
2026-05-11 12:59:30 +03:00
Содержит claude-md-improver (skill — audit) и revise-claude-md (slash-command — capture learnings).
2026-05-11 00:46:51 +03:00
< / div >
< div class = "plugin-skills-list" >
2026-05-11 12:59:30 +03:00
1 skill + 1 slash-command · инфраструктура CLAUDE.md
2026-05-11 00:46:51 +03:00
< / div >
< / div >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > frontend-design< / div >
< div class = "plugin-card-scope" > anthropic · claude-plugins-official< / div >
< / div >
< div class = "plugin-card-desc" >
Помощник для построения отличающихся frontend-интерфейсов. Знает 50+ стилей,
принципы типографики, цвета, motion, layout. Используется для UI работы — например, для
этого документа.
< / div >
< div class = "plugin-skills-list" >
1 skill · UI/UX дизайн
< / div >
< / div >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > ui-ux-pro-max< / div >
< div class = "plugin-card-scope" > nextlevelbuilder · ui-ux-pro-max-skill< / div >
< / div >
< div class = "plugin-card-desc" >
2026-05-11 12:59:30 +03:00
Резерв-библиотека: 67 UI styles, 161 palette, 57 font pairings, 99 UX guidelines, 25 chart types
(across 15+ tech stacks). Off-phase tool — активируется только через R14 pipeline в Plugin Stack Rules.
2026-05-11 00:46:51 +03:00
< / div >
< div class = "plugin-skills-list" >
1 skill · резерв-библиотека UI/UX
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
VI. SKILLS BY PURPOSE
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > VII< / div >
< h2 class = "section-title" > Скилы по плагинам< / h2 >
< p class = "section-lede" >
2026-05-11 12:59:30 +03:00
Все 28 capabilities (27 skills + 1 slash-command) сгруппированы по родительскому плагину.
18 принадлежат одному из 4 установленных плагинов (17 skills + 1 command), 10 — « standalone / встроенные»
2026-05-11 00:46:51 +03:00
(не доставляются плагином, идут с Claude Code как часть базовой системы).
< / p >
< div class = "skills-purpose" >
< div class = "sp-row" >
< div class = "sp-cat" >
< div class = "sp-cat-symbol" > ⚡< / div >
< div class = "sp-cat-name" > superpowers< / div >
< div class = "sp-cat-meta" > 14 skills · obra/superpowers v5.1.0< / div >
< / div >
< div class = "sp-skills-detail" >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > brainstorming< / div >
< div class = "sp-skill-what" > < em > Идея → спек.< / em > Через диалог уточняет требования, предлагает 2-3 подхода с trade-off'ами. Не позволяет писать код до утверждения дизайна.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > writing-plans< / div >
< div class = "sp-skill-what" > < em > Спек → пошаговый план.< / em > Bite-sized задачи (2-5 мин каждая) с точными путями файлов, кодом, командами и TDD-структурой.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > executing-plans< / div >
< div class = "sp-skill-what" > < em > План → выполнение.< / em > Исполняет существующий план по шагам с checkpoint'ами для ревью между задачами.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > test-driven-development< / div >
< div class = "sp-skill-what" > < em > Iron law: тест ДО кода.< / em > Red (увидеть как тест падает), потом green (минимальная реализация), потом refactor. Никаких «тестов после».< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > systematic-debugging< / div >
< div class = "sp-skill-what" > < em > 4 фазы перед любым фиксом.< / em > Root cause → pattern → hypothesis → fix. Минимум 3 гипотезы. Запрет «быстрых патчей».< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > requesting-code-review< / div >
< div class = "sp-skill-what" > < em > Перед merge / PR.< / em > Двухстадийный review через subagent'ы: spec compliance + code quality.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > receiving-code-review< / div >
< div class = "sp-skill-what" > < em > Когда получил feedback ревью.< / em > Правила обработки замечаний без слепого согласия и без отвержения любой критики.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > verification-before-completion< / div >
< div class = "sp-skill-what" > < em > Перед claim «готово».< / em > Обязательно запустить verification команду, проверить exit code и output. Никаких «должно работать».< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > finishing-a-development-branch< / div >
< div class = "sp-skill-what" > < em > Когда работа на ветке закончена.< / em > Структурный выбор: merge / PR / cleanup с обоснованием каждого варианта.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > using-git-worktrees< / div >
< div class = "sp-skill-what" > < em > Изоляция feature-работы.< / em > Через `git worktree` — отдельный workspace вне current branch.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > subagent-driven-development< / div >
< div class = "sp-skill-what" > < em > Диспатч свежего subagent'а на каждую задачу плана.< / em > Изоляция контекста + 2-стадийный review между задачами.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > dispatching-parallel-agents< / div >
< div class = "sp-skill-what" > < em > 2+ независимых задачи без shared state.< / em > Параллельные subagent'ы вместо последовательного выполнения. Экономия времени.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > using-superpowers< / div >
< div class = "sp-skill-what" > < em > Базовый skill про другие skills.< / em > Объясняет как находить и инвокировать остальные. Обычно срабатывает в начале сессии.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > writing-skills< / div >
< div class = "sp-skill-what" > < em > Когда создаёшь новый skill.< / em > Правила его написания, валидации и deployment.< / div >
< / div >
< / div >
< / div >
< div class = "sp-row" >
< div class = "sp-cat" >
< div class = "sp-cat-symbol" > ¶< / div >
< div class = "sp-cat-name" > claude-md-management< / div >
2026-05-11 12:59:30 +03:00
< div class = "sp-cat-meta" > 1 skill + 1 command · anthropic · claude-plugins-official< / div >
2026-05-11 00:46:51 +03:00
< / div >
< div class = "sp-skills-detail" >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > claude-md-improver< / div >
< div class = "sp-skill-what" > < em > Audit + targeted updates CLAUDE.md.< / em > Единственный канал структурных правок: добавление/удаление секций, версии в шапке, правки правил.< / div >
< / div >
< div class = "sp-skill-row" >
2026-05-11 12:59:30 +03:00
< div class = "sp-skill-key" > revise-claude-md < span style = "color:var(--rust); font-style:italic;" > (command)< / span > < / div >
< div class = "sp-skill-what" > < em > Захват session-learnings.< / em > Новые квирки, команды, паттерны из текущей сессии → автоматически в CLAUDE.md. Доставляется как slash-command в < span class = "mono" > commands/< / span > , не skill.< / div >
2026-05-11 00:46:51 +03:00
< / div >
< / div >
< / div >
< div class = "sp-row" >
< div class = "sp-cat" >
< div class = "sp-cat-symbol" > ◊< / div >
< div class = "sp-cat-name" > frontend-design< / div >
< div class = "sp-cat-meta" > 1 skill · anthropic · claude-plugins-official< / div >
< / div >
< div class = "sp-skills-detail" >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > frontend-design< / div >
< div class = "sp-skill-what" > < em > Создание distinctive UI.< / em > Избегает generic AI-aesthetics. Distinctive fonts, bold direction, осознанные дизайн-выборы. Эта страница построена через него.< / div >
< / div >
< / div >
< / div >
< div class = "sp-row" >
< div class = "sp-cat" >
< div class = "sp-cat-symbol" > △< / div >
< div class = "sp-cat-name" > ui-ux-pro-max< / div >
< div class = "sp-cat-meta" > 1 skill · nextlevelbuilder · ui-ux-pro-max-skill< / div >
< / div >
< div class = "sp-skills-detail" >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > ui-ux-pro-max< / div >
2026-05-11 12:59:30 +03:00
< div class = "sp-skill-what" > < em > Резерв-библиотека UI/UX.< / em > 67 UI styles, 161 palette, 57 font pairings, 99 UX guidelines, 25 chart types (across 15+ tech stacks). Активируется через PSR R14 pipeline.< / div >
2026-05-11 00:46:51 +03:00
< / div >
< / div >
< / div >
< div class = "sp-row" >
< div class = "sp-cat" >
< div class = "sp-cat-symbol" > ⌖< / div >
< div class = "sp-cat-name" > Standalone / встроенные< / div >
< div class = "sp-cat-meta" > 10 skills · без плагина (часть базовой системы Claude Code)< / div >
< / div >
< div class = "sp-skills-detail" >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > update-config< / div >
< div class = "sp-skill-what" > < em > Правки settings.json.< / em > Хуки, permissions, env vars, MCP servers, plugins. Любая автоматизация behaviour'а — через этот skill.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > keybindings-help< / div >
< div class = "sp-skill-what" > < em > Клавиатурные сокращения.< / em > Настройка `~/.claude/keybindings.json` — chord-bindings, rebind keys.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > simplify< / div >
< div class = "sp-skill-what" > < em > Review недавнего кода.< / em > Reuse / quality / efficiency. Находит дубли, over-engineering, dead code — потом фиксит.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > fewer-permission-prompts< / div >
< div class = "sp-skill-what" > < em > Снижение шума permission prompts.< / em > Сканирует transcript'ы, добавляет allowlist в settings.json для частых read-only действий.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > init< / div >
< div class = "sp-skill-what" > < em > Новый проект → новый CLAUDE.md.< / em > Инициализация документации для нового codebase с анализом структуры.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > claude-api< / div >
< div class = "sp-skill-what" > < em > Claude API / Anthropic SDK apps.< / em > Build / debug / optimize. Также миграция между версиями моделей (4.5 → 4.6 → 4.7).< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > loop< / div >
< div class = "sp-skill-what" > < em > Запуск prompt'а на recurring interval.< / em > Например `/loop 5m /foo` — каждые 5 мин. Или self-paced если без интервала. Для polling, мониторинга.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > schedule< / div >
< div class = "sp-skill-what" > < em > Cron-расписания для агентов.< / em > Создание / управление scheduled remote routines. Также one-time scheduled запуски («сделай это завтра в 15:00»).< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > review< / div >
< div class = "sp-skill-what" > < em > Review текущего PR на GitHub.< / em > Чтение diff'а, замечания по логике, стилю, тестам. Подготовка к merge.< / div >
< / div >
< div class = "sp-skill-row" >
< div class = "sp-skill-key" > security-review< / div >
< div class = "sp-skill-what" > < em > Security audit pending changes.< / em > Полный security review текущей ветки: OWASP top 10, secrets, RLS, injection vectors.< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
VII. FILESYSTEM
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > VIII< / div >
< h2 class = "section-title" > Карта на диске< / h2 >
< p class = "section-lede" >
2026-05-11 12:59:30 +03:00
Где физически лежит каждый компонент. Три уровня: < em > user< / em > (общая инфраструктура Claude Code),
< em > brain (source)< / em > (репозиторий-источник, который правится осознанно), < em > project (consumer)< / em >
(любой проект, в который brain установлен через < span class = "mono" > install.sh< / span > ).
2026-05-11 00:46:51 +03:00
< / p >
< div class = "fs" >
< pre style = "margin:0;" >
< span class = "fs-section-tag" > user< / span > < span class = "fs-path" > C:\Users\Administrator\< b > .claude\< / b > < / span >
2026-05-11 12:59:30 +03:00
├── settings.json < span class = "fs-comment" > главный конфиг: permissions + hooks (собран из settings-fragment.json)< / span >
2026-05-11 00:46:51 +03:00
├── settings.json.backup-pre-economy-hardening
│
2026-05-11 12:59:30 +03:00
├── < span class = "fs-path" > < b > hooks/< / b > < / span > < span class = "fs-comment" > Python-скрипты хуков (синкаются из brain user-level-files/hooks/)< / span >
2026-05-11 00:46:51 +03:00
│ ├── skill-marker.py < span class = "fs-comment" > PreToolUse(Skill)< / span >
│ ├── skill-check.py < span class = "fs-comment" > PreToolUse(Edit|Write|MultiEdit)< / span >
│ ├── economy-mode.py (v3) < span class = "fs-comment" > UserPromptSubmit + state writer< / span >
│ ├── economy-mode-test.py < span class = "fs-comment" > 54 теста< / span >
│ ├── economy-self-check.py < span class = "fs-comment" > SessionStart< / span >
│ ├── economy-self-check-test.py < span class = "fs-comment" > 4 теста< / span >
│ ├── economy-state-guard.py < span class = "fs-comment" > PreToolUse + Bash detection< / span >
│ ├── economy-state-guard-test.py < span class = "fs-comment" > 6 тестов< / span >
│ ├── economy-verifier.py < span class = "fs-comment" > Stop wrapper< / span >
│ └── economy-postcompact.py < span class = "fs-comment" > PostCompact< / span >
│
2026-05-11 12:59:30 +03:00
├── < span class = "fs-path" > < b > plugins/cache/< / b > < / span > < span class = "fs-comment" > загруженные плагины (marketplace-источники в marketplaces.json)< / span >
│ ├── superpowers-dev/superpowers/5.1.0/ < span class = "fs-comment" > obra/superpowers< / span >
│ ├── claude-plugins-official/claude-md-management/1.0.0/
2026-05-11 00:46:51 +03:00
│ ├── claude-plugins-official/frontend-design/
2026-05-11 12:59:30 +03:00
│ └── ui-ux-pro-max-skill/ui-ux-pro-max/2.5.0/
2026-05-11 00:46:51 +03:00
│
2026-05-11 12:59:30 +03:00
└── < span class = "fs-path" > < b > projects/< cwd> /memory/< / b > < / span > < span class = "fs-comment" > долгосрочная память (per-project)< / span >
2026-05-11 00:46:51 +03:00
├── MEMORY.md (index)
2026-05-11 12:59:30 +03:00
└── ... per-project files
2026-05-11 00:46:51 +03:00
2026-05-11 12:59:30 +03:00
< span class = "fs-section-tag" > brain (source)< / span > < span class = "fs-path" > c:\моя\проекты\< b > claude-brain\< / b > < / span >
├── manifest.json < span class = "fs-comment" > SHA-256 hashes всех файлов brain v1.0< / span >
├── CLAUDE.md / README.md / CHANGELOG.md
2026-05-11 00:46:51 +03:00
│
2026-05-11 12:59:30 +03:00
├── < span class = "fs-path" > < b > project-files/< / b > < / span > < span class = "fs-comment" > копируется в consumer-проекты install.sh'ом< / span >
│ ├── CLAUDE.md.template
│ ├── .mcp.json.template < span class = "fs-comment" > playwright + github + semgrep< / span >
│ └── docs/
│ ├── Pravila_raboty_Claude.template.md
│ ├── Plugin_stack_rules.template.md
│ ├── Tooling.template.md
│ └── visualizations/hooks-skills-plugins-map.html < span class = "fs-comment" > вы тут< / span >
2026-05-11 00:46:51 +03:00
│
2026-05-11 12:59:30 +03:00
├── < span class = "fs-path" > < b > user-level-files/< / b > < / span > < span class = "fs-comment" > копируется в ~/.claude/ install.sh'ом< / span >
│ ├── hooks/ < span class = "fs-comment" > 7 рантайм + 3 test .py< / span >
│ ├── settings-fragment.json < span class = "fs-comment" > фрагмент для merge в settings.json< / span >
│ ├── marketplaces.json < span class = "fs-comment" > 3 marketplace-источника< / span >
│ ├── plugins-manifest.json < span class = "fs-comment" > 4 плагина + версии< / span >
│ └── mcp-user.template.json < span class = "fs-comment" > magic (21st.dev)< / span >
│
├── < span class = "fs-path" > < b > scripts/< / b > < / span > < span class = "fs-comment" > инструменты sync< / span >
│ ├── install.sh < span class = "fs-comment" > copy brain → consumer / ~/.claude< / span >
│ ├── verify.sh < span class = "fs-comment" > cross-check hashes vs manifest.json< / span >
│ └── extract.sh < span class = "fs-comment" > rescue: consumer → brain< / span >
│
└── docs/ < span class = "fs-comment" > документация brain'а самого< / span >
├── architecture.md
├── how-to-use-brain.md
├── secrets-and-tokens.md
└── sessions/2026-05-11-bootstrap-session.md
< span class = "fs-section-tag" > project (consumer)< / span > < span class = "fs-path" > < consumer-project> /< / span >
├── CLAUDE.md < span class = "fs-comment" > из template, substitutions заполнены при install< / span >
├── .mcp.json < span class = "fs-comment" > project-mode MCP (playwright/github/semgrep)< / span >
│
└── docs/
├── Pravila_raboty_Claude.md < span class = "fs-comment" > §12 hard rule (без версии в имени)< / span >
├── Plugin_stack_rules.md < span class = "fs-comment" > 16 правил координации< / span >
├── Tooling.md < span class = "fs-comment" > реестр инструментов проекта< / span >
├── CHANGELOG_claude_md.md
├── superpowers/{specs,plans}/ < span class = "fs-comment" > создаются по мере работы< / span >
└── visualizations/hooks-skills-plugins-map.html < span class = "fs-comment" > этот файл, installed copy< / span >
2026-05-11 00:46:51 +03:00
< / pre >
< / div >
< / div >
< / section >
<!-- ============================================================
VIII. MENTAL MODEL
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > IX< / div >
< h2 class = "section-title" > Кто за что отвечает< / h2 >
< p class = "section-lede" >
Четыре действующих лица — четыре роли. Каждый делает то, что больше никто не может,
и не лезет в чужой огород. Это про разделение обязанностей в системе.
< / p >
< div class = "mental" >
< div class = "mental-stage" >
< div class = "mental-actor you" >
< div class = "mental-tag" > Actor 01< / div >
< div class = "mental-name" > Вы (Дмитрий)< / div >
< ul class = "mental-list" >
< li > Пишете промпт, опционально ставите «экономия N%» в конце< / li >
< li > Approve'ите permission prompts на правки hook-файлов< / li >
< li > Можете выключить хуки через settings.json → disableAllHooks< / li >
< li > Вне Claude Code — единственный, кто может править settings/hooks без вопросов< / li >
< / ul >
< / div >
< div class = "mental-actor runtime" >
< div class = "mental-tag" > Actor 02< / div >
< div class = "mental-name" > Claude Code Runtime< / div >
< ul class = "mental-list" >
< li > Запускает хуки на нужных событиях, не спрашивая меня< / li >
< li > Применяет permissions (deny/ask) к моим действиям< / li >
< li > Передаёт мне injected additionalContext от хуков< / li >
< li > Auto-mode classifier ловит мои попытки обхода< / li >
< / ul >
< / div >
< div class = "mental-actor claude" >
< div class = "mental-tag" > Actor 03< / div >
< div class = "mental-name" > Я (Claude Opus 4.7)< / div >
< ul class = "mental-list" >
< li > Читаю injected правила и стараюсь им следовать< / li >
< li > Вызываю skills — добровольно или по §12 требованию< / li >
< li > Использую tools: Edit/Write/Bash/Read/Skill/etc.< / li >
< li > < em > Не могу< / em > обойти хуки или permissions — проверено< / li >
< / ul >
< / div >
< div class = "mental-actor verifier" >
< div class = "mental-tag" > Actor 04< / div >
< div class = "mental-name" > Sonnet 4.6 verifier< / div >
< ul class = "mental-list" >
< li > Читает мой финальный ответ + последние tool calls< / li >
< li > Сравнивает с активным уровнем экономии< / li >
< li > При cherry-pick или claim'е без evidence — < strong > блок< / strong > < / li >
< li > До 3 retry попыток за turn, потом — эскалация к вам< / li >
< / ul >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
X. CONNECTIONS GRAPH
============================================================ -->
< section class = "section" id = "graph-section" >
< div class = "frame" >
< div class = "section-num display-i" > X< / div >
< h2 class = "section-title" > Связи — интерактивная карта< / h2 >
< p class = "section-lede" >
50 узлов, 52 ребра, 8 типов связей. Кликни на любой узел —
подсветятся все его связи + откроется панель с деталями справа.
Тяни узлы мышкой для перестановки. Фильтры в верхней панели прячут
категории по одной.
< / p >
< div class = "graph-controls" >
< div class = "graph-filters" >
< button class = "graph-filter active" data-type = "plugin" > Плагины< / button >
< button class = "graph-filter active" data-type = "skill" > Скилы< / button >
< button class = "graph-filter active" data-type = "script" > Скрипты< / button >
< button class = "graph-filter active" data-type = "event" > События< / button >
< button class = "graph-filter active" data-type = "state" > Состояние< / button >
< button class = "graph-filter active" data-type = "perm" > Права< / button >
< button class = "graph-filter active" data-type = "rule" > Правила< / button >
< / div >
< button class = "graph-reset" > Сбросить расположение< / button >
< / div >
< div class = "graph-container" >
< div class = "graph-svg-wrap" >
< svg class = "graph-svg" viewBox = "0 0 1100 700" preserveAspectRatio = "xMidYMid meet" role = "img" aria-label = "Граф связей: 50 узлов, 52 ребра, 8 типов связей между плагинами, скилами, хуками и правилами" > < / svg >
< / div >
< aside class = "graph-sidebar" >
< div class = "graph-sidebar-empty" >
Кликни на узел чтобы увидеть его связи…
< / div >
< / aside >
< / div >
< div class = "graph-legend" >
< div class = "graph-legend-section" >
< h4 > Узлы (категории)< / h4 >
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--rust); border-radius:50%;" > < / span > Плагин (4)< / div >
2026-05-11 12:59:30 +03:00
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--blueprint); border-radius:50%;" > < / span > Скил/команда (28)< / div >
2026-05-11 00:46:51 +03:00
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--amber); border-radius:50%;" > < / span > Скрипт хука (7)< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--sage);" > < / span > Событие хука (5)< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--rust); transform:rotate(45deg);" > < / span > Файл состояния (1)< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--ink-fade);" > < / span > Права (3)< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-swatch" style = "background:var(--ink); border-color:var(--rust);" > < / span > Правило (2)< / div >
< / div >
< div class = "graph-legend-section" >
< h4 > Связи (типы)< / h4 >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--blueprint);" > < / span > содержит< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--sage); border-width:2px;" > < / span > запускает< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--amber); border-width:2px;" > < / span > пишет< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--amber); border-style:dashed;" > < / span > читает< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--rust); border-width:3px;" > < / span > обязывает< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--ink-fade); border-style:dotted;" > < / span > ссылается< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--rust); border-style:dashed;" > < / span > блокирует< / div >
< div class = "graph-legend-item" > < span class = "graph-legend-line" style = "border-color:var(--rust); border-style:dashed; border-width:2px;" > < / span > запрещает< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
2026-05-11 12:59:30 +03:00
XI. MCP SERVERS
2026-05-11 00:46:51 +03:00
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > XI< / div >
2026-05-11 12:59:30 +03:00
< h2 class = "section-title" > MCP-серверы — внешние tool-провайдеры< / h2 >
< p class = "section-lede" >
Четыре сервера Model Context Protocol. Один на user-уровне (магазин компонентов), три на project-уровне
(браузер, GitHub API, статанализ). MCP — это < em > не< / em > плагин и < em > не< / em > хук: это отдельный процесс,
который запускается рядом с Claude Code и предоставляет дополнительные tools через stdio или HTTP.
< / p >
< div class = "plugins" >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > magic< / div >
< div class = "plugin-card-scope" > user · stdio · npx< / div >
< / div >
< div class = "plugin-card-desc" >
UI-генерация компонентов от 21st.dev. Поиск, inspiration, refiner, logo search — для быстрых
визуальных набросков. Зарегистрирован в < span class = "mono" > ~/.claude/mcp.json< / span >
(template: < span class = "mono" > user-level-files/mcp-user.template.json< / span > ).
< / div >
< div class = "plugin-skills-list" >
< span class = "mono" > npx @21st-dev/magic@latest< / span > · API_KEY required
< / div >
< / div >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > playwright< / div >
< div class = "plugin-card-scope" > project · stdio · npx< / div >
< / div >
< div class = "plugin-card-desc" >
Headless-браузер. Открытие < span class = "mono" > web/*.html< / span > , screenshot, проверка интерактива,
навигация по DOM. Используется для визуальной верификации UI-работы.
< / div >
< div class = "plugin-skills-list" >
< span class = "mono" > npx @playwright/mcp@latest< / span >
< / div >
< / div >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > github< / div >
< div class = "plugin-card-scope" > project · HTTP · hosted< / div >
< / div >
< div class = "plugin-card-desc" >
Официальный hosted GitHub MCP. Issues, PRs, файлы, search, actions. Требует
< span class = "mono" > GITHUB_TOKEN< / span > (PAT, scopes: repo, read:org).
Заменил deprecated < span class = "mono" > @modelcontextprotocol/server-github< / span > 06.05.2026.
< / div >
< div class = "plugin-skills-list" >
< span class = "mono" > https://api.githubcopilot.com/mcp< / span >
< / div >
< / div >
< div class = "plugin-card" >
< div class = "plugin-card-header" >
< div class = "plugin-card-name" > semgrep< / div >
< div class = "plugin-card-scope" > project · stdio · npx< / div >
< / div >
< div class = "plugin-card-desc" >
SAST. Семантический поиск и анализ кода через Semgrep rules прямо в Claude Code.
Для security-review и поиска паттернов уязвимостей.
< / div >
< div class = "plugin-skills-list" >
< span class = "mono" > npx semgrep-mcp< / span >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
XII. ACTIONS
============================================================ -->
< section class = "section" >
< div class = "frame" >
< div class = "section-num display-i" > XII< / div >
2026-05-11 00:46:51 +03:00
< h2 class = "section-title" > Что вы можете сделать< / h2 >
< p class = "section-lede" >
Шесть практических действий. Каждое — одна команда или одно изменение в одном файле.
< / p >
< div class = "actions" >
< div class = "action" >
< span class = "action-num" > 1< / span >
< div class = "action-want" > Если вы хотите…< / div >
< div class = "action-do" > Активировать экономию для одной задачи< / div >
< div class = "r-desc" > Допишите в самый конец промпта одно из: < span class = "mono" > экономия 0%< / span > · < span class = "mono" > экономия 25%< / span > · < span class = "mono" > экономия 50%< / span > · < span class = "mono" > экономия 75%< / span > . 0% — максимум, 75% — мягко, без ключа — обычный режим.< / div >
< / div >
< div class = "action" >
< span class = "action-num" > 2< / span >
< div class = "action-want" > Если вы хотите…< / div >
< div class = "action-do" > Посмотреть, что сейчас включено< / div >
< code class = "action-cmd" > python -c "import json; s=json.load(open(r'C:\Users\Administrator\.claude\settings.json',encoding='utf-8')); print(list(s['hooks'].keys()))"< / code >
< / div >
< div class = "action" >
< span class = "action-num" > 3< / span >
< div class = "action-want" > Если вы хотите…< / div >
< div class = "action-do" > Вызвать скил вручную< / div >
< div class = "r-desc" > Напишите в промпте slash-команду: < span class = "mono" > /superpowers:brainstorming< / span > · < span class = "mono" > /claude-md-management:claude-md-improver< / span > · < span class = "mono" > /init< / span > · < span class = "mono" > /review< / span > · etc.< / div >
< / div >
< div class = "action" >
< span class = "action-num" > 4< / span >
< div class = "action-want" > Если вы хотите…< / div >
< div class = "action-do" > Выключить все хуки временно< / div >
< div class = "r-desc" > В < span class = "mono" > ~/.claude/settings.json< / span > на верхнем уровне добавьте < span class = "mono" > "disableAllHooks": true< / span > . Потребует ваш approve через ask-rule (так как Edit на settings.json). Уберёт всё включая дисциплину и верификатор.< / div >
< / div >
< div class = "action" >
< span class = "action-num" > 5< / span >
< div class = "action-want" > Если вы хотите…< / div >
< div class = "action-do" > Проверить, что хуки работают< / div >
< div class = "r-desc" > Откройте новую сессию Claude Code. SessionStart self-check сработает автоматически. Если что-то сломано — увидите < em > «Economy hook self-check FAILED»< / em > в начале сессии.< / div >
< / div >
< div class = "action" >
< span class = "action-num" > 6< / span >
< div class = "action-want" > Если вы хотите…< / div >
< div class = "action-do" > Откатить всё на до-economy состояние< / div >
< code class = "action-cmd" > copy "C:\Users\Administrator\.claude\settings.json.backup-pre-economy-hardening" "C:\Users\Administrator\.claude\settings.json"< / code >
< / div >
< / div >
< / div >
< / section >
<!-- ============================================================
FOOTER
============================================================ -->
< footer class = "foot" >
< div class = "frame" style = "display:flex; justify-content:space-between; flex-wrap:wrap; gap:32px; align-items:baseline;" >
< div >
< div class = "caps" style = "margin-bottom:6px;" > Document meta< / div >
< span class = "mono" > hooks-skills-plugins-map.html< / span > ·
2026-05-11 12:59:30 +03:00
< span class = "mono" > 2026-05-11< / span > ·
< span class = "mono" > brain v1.0 · 7 хуков / 4 плагина / 4 MCP / 28 capabilities< / span >
2026-05-11 00:46:51 +03:00
< / div >
< div class = "foot-ornament" > ~ fin ~< / div >
< div style = "text-align:right;" >
< div class = "caps" style = "margin-bottom:6px;" > Источник правды< / div >
< span class = "mono" > ~/.claude/settings.json< / span > < br >
< span style = "font-style:italic;" > прочитан напрямую, не из memory< / span >
< / div >
< / div >
< / footer >
< / main >
< script >
// ============================================================
// CONNECTIONS GRAPH DATA
// ============================================================
const GRAPH _NODES = [
// === Plugins (4) ===
{ id : 'plg:superpowers' , type : 'plugin' , label : 'superpowers' , desc : 'Главный плагин дисциплины процесса работы. 14 скилов.' } ,
{ id : 'plg:claude-md' , type : 'plugin' , label : 'claude-md-management' , desc : 'Единственный канал правок CLAUDE.md. 2 скила.' } ,
{ id : 'plg:fd' , type : 'plugin' , label : 'frontend-design' , desc : 'Создание distinctive frontend. Anthropic plugin.' } ,
{ id : 'plg:upm' , type : 'plugin' , label : 'ui-ux-pro-max' , desc : 'Резерв-библиотека UI/UX (50+ стилей, 161 палитра).' } ,
// === Skills (28) ===
// Superpowers (14)
{ id : 'skl:brainstorming' , type : 'skill' , label : 'brainstorming' , desc : 'Превращает идею в спек через диалог.' } ,
{ id : 'skl:writing-plans' , type : 'skill' , label : 'writing-plans' , desc : 'Из спека → пошаговый план.' } ,
{ id : 'skl:executing-plans' , type : 'skill' , label : 'executing-plans' , desc : 'Исполняет план по шагам.' } ,
{ id : 'skl:tdd' , type : 'skill' , label : 'test-driven-development' , desc : 'Тест ДО кода. Red-green-refactor.' } ,
{ id : 'skl:debug' , type : 'skill' , label : 'systematic-debugging' , desc : '4 фазы root cause. ≥3 гипотезы.' } ,
{ id : 'skl:req-review' , type : 'skill' , label : 'requesting-code-review' , desc : 'Перед merge — двухстадийный review.' } ,
{ id : 'skl:recv-review' , type : 'skill' , label : 'receiving-code-review' , desc : 'Обработка feedback ревью.' } ,
{ id : 'skl:verify' , type : 'skill' , label : 'verification-before-completion' , desc : 'Перед claim готово — verify.' } ,
{ id : 'skl:finishing' , type : 'skill' , label : 'finishing-a-development-branch' , desc : 'merge / PR / cleanup.' } ,
{ id : 'skl:worktrees' , type : 'skill' , label : 'using-git-worktrees' , desc : 'Изоляция feature-работы.' } ,
{ id : 'skl:subagent' , type : 'skill' , label : 'subagent-driven-development' , desc : 'Свежий subagent на каждую задачу.' } ,
{ id : 'skl:parallel' , type : 'skill' , label : 'dispatching-parallel-agents' , desc : "Параллельные subagent'ы." } ,
{ id : 'skl:using-sp' , type : 'skill' , label : 'using-superpowers' , desc : 'Базовый: как находить skills.' } ,
{ id : 'skl:writing-skills' , type : 'skill' , label : 'writing-skills' , desc : 'Создание новых skills.' } ,
// claude-md-management (2)
{ id : 'skl:md-improver' , type : 'skill' , label : 'claude-md-improver' , desc : 'Audit + targeted updates CLAUDE.md.' } ,
2026-05-11 12:59:30 +03:00
{ id : 'skl:md-revise' , type : 'skill' , label : 'revise-claude-md (command)' , desc : 'Захват session-learnings. Доставляется как slash-command (commands/), не skill.' } ,
2026-05-11 00:46:51 +03:00
// frontend-design (1)
{ id : 'skl:fd-skill' , type : 'skill' , label : 'frontend-design' , desc : 'Distinctive UI без AI-aesthetics.' } ,
// ui-ux-pro-max (1)
{ id : 'skl:upm-skill' , type : 'skill' , label : 'ui-ux-pro-max' , desc : 'Резерв-библиотека стилей.' } ,
// Standalone (10)
{ id : 'skl:update-config' , type : 'skill' , label : 'update-config' , desc : 'Правки settings.json.' } ,
{ id : 'skl:keybindings' , type : 'skill' , label : 'keybindings-help' , desc : 'Клавиатурные сокращения.' } ,
{ id : 'skl:simplify' , type : 'skill' , label : 'simplify' , desc : 'Review кода на reuse/quality.' } ,
{ id : 'skl:fewer-prompts' , type : 'skill' , label : 'fewer-permission-prompts' , desc : 'Снижение шума prompts.' } ,
{ id : 'skl:init' , type : 'skill' , label : 'init' , desc : 'Новый CLAUDE.md для нового проекта.' } ,
{ id : 'skl:claude-api' , type : 'skill' , label : 'claude-api' , desc : 'Claude API / SDK apps.' } ,
{ id : 'skl:loop' , type : 'skill' , label : 'loop' , desc : 'Recurring prompt на интервале.' } ,
{ id : 'skl:schedule' , type : 'skill' , label : 'schedule' , desc : 'Cron-расписания для агентов.' } ,
{ id : 'skl:review' , type : 'skill' , label : 'review' , desc : 'Review текущего PR.' } ,
{ id : 'skl:sec-review' , type : 'skill' , label : 'security-review' , desc : 'Security audit pending changes.' } ,
// === Hook scripts (7) ===
{ id : 'scr:skill-marker' , type : 'script' , label : 'skill-marker.py' , desc : 'Отметка о вызове Skill.' } ,
{ id : 'scr:skill-check' , type : 'script' , label : 'skill-check.py' , desc : 'Reminder §12 если skill не вызван.' } ,
{ id : 'scr:economy-mode' , type : 'script' , label : 'economy-mode.py' , desc : 'Парсит экономию N%, пишет state.' } ,
{ id : 'scr:economy-self-check' , type : 'script' , label : 'economy-self-check.py' , desc : 'SessionStart runtime guard.' } ,
{ id : 'scr:economy-state-guard' , type : 'script' , label : 'economy-state-guard.py' , desc : 'PreToolUse reminder + Bash bypass.' } ,
{ id : 'scr:economy-verifier' , type : 'script' , label : 'economy-verifier.py (Sonnet 4.6)' , desc : 'Stop verifier — блокирует cherry-pick.' } ,
{ id : 'scr:economy-postcompact' , type : 'script' , label : 'economy-postcompact.py' , desc : 'Re-inject правил после компакции.' } ,
// === Hook events (5) ===
{ id : 'evt:session-start' , type : 'event' , label : 'SessionStart' , desc : 'Один раз на старте сессии.' } ,
{ id : 'evt:user-prompt-submit' , type : 'event' , label : 'UserPromptSubmit' , desc : 'Каждый submit от пользователя.' } ,
{ id : 'evt:pre-tool-use' , type : 'event' , label : 'PreToolUse' , desc : 'Перед каждым tool call.' } ,
{ id : 'evt:post-compact' , type : 'event' , label : 'PostCompact' , desc : 'После авто-компакции.' } ,
{ id : 'evt:stop' , type : 'event' , label : 'Stop' , desc : 'Конец моего ответа.' } ,
// === State file (1) ===
{ id : 'st:economy-state' , type : 'state' , label : 'claude-economy-state.json' , desc : '$TEMP/claude-economy-<session_id>.json — shared state.' } ,
// === Permissions (3) ===
{ id : 'prm:allow' , type : 'perm' , label : 'permissions.allow (1)' , desc : 'Разрешено без вопросов: Bash(git push origin main:*).' } ,
{ id : 'prm:deny' , type : 'perm' , label : 'permissions.deny (7)' , desc : 'Жёстко заблокировано: rm/mv hook/settings/state.' } ,
{ id : 'prm:ask' , type : 'perm' , label : 'permissions.ask (16)' , desc : 'С approve пользователя: Edit/Write hook files и settings.json.' } ,
// === Rules (2) ===
{ id : 'rul:pravila-12' , type : 'rule' , label : 'Pravila §12' , desc : 'Hard rule: Superpowers skill ПЕРВЫМ.' } ,
{ id : 'rul:claude-md' , type : 'rule' , label : 'CLAUDE.md' , desc : 'Главная карта проекта.' }
] ;
console . log ( 'GRAPH_NODES:' , GRAPH _NODES . length , '(expected 50)' ) ;
const GRAPH _LINKS = [
// === contains (18) — plugin → skill ===
// superpowers (14)
{ source : 'plg:superpowers' , target : 'skl:brainstorming' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:writing-plans' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:executing-plans' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:tdd' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:debug' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:req-review' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:recv-review' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:verify' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:finishing' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:worktrees' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:subagent' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:parallel' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:using-sp' , type : 'contains' } ,
{ source : 'plg:superpowers' , target : 'skl:writing-skills' , type : 'contains' } ,
// claude-md (2)
{ source : 'plg:claude-md' , target : 'skl:md-improver' , type : 'contains' } ,
{ source : 'plg:claude-md' , target : 'skl:md-revise' , type : 'contains' } ,
// fd (1)
{ source : 'plg:fd' , target : 'skl:fd-skill' , type : 'contains' } ,
// upm (1)
{ source : 'plg:upm' , target : 'skl:upm-skill' , type : 'contains' } ,
// === triggers (7) — event → script ===
{ source : 'evt:session-start' , target : 'scr:economy-self-check' , type : 'triggers' } ,
{ source : 'evt:user-prompt-submit' , target : 'scr:economy-mode' , type : 'triggers' } ,
{ source : 'evt:pre-tool-use' , target : 'scr:skill-marker' , type : 'triggers' } ,
{ source : 'evt:pre-tool-use' , target : 'scr:skill-check' , type : 'triggers' } ,
{ source : 'evt:pre-tool-use' , target : 'scr:economy-state-guard' , type : 'triggers' } ,
{ source : 'evt:post-compact' , target : 'scr:economy-postcompact' , type : 'triggers' } ,
{ source : 'evt:stop' , target : 'scr:economy-verifier' , type : 'triggers' } ,
// === writes (1) — script → state ===
{ source : 'scr:economy-mode' , target : 'st:economy-state' , type : 'writes' } ,
// === reads (3) — script → state ===
{ source : 'scr:economy-state-guard' , target : 'st:economy-state' , type : 'reads' } ,
{ source : 'scr:economy-verifier' , target : 'st:economy-state' , type : 'reads' } ,
{ source : 'scr:economy-postcompact' , target : 'st:economy-state' , type : 'reads' } ,
// === mandates (14) — Pravila §12 → 14 superpowers skills ===
{ source : 'rul:pravila-12' , target : 'skl:brainstorming' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:writing-plans' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:executing-plans' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:tdd' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:debug' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:req-review' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:recv-review' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:verify' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:finishing' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:worktrees' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:subagent' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:parallel' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:using-sp' , type : 'mandates' } ,
{ source : 'rul:pravila-12' , target : 'skl:writing-skills' , type : 'mandates' } ,
// === references (1) — CLAUDE.md → Pravila §12 ===
{ source : 'rul:claude-md' , target : 'rul:pravila-12' , type : 'references' } ,
// === blocks (7) — permissions.ask → hook scripts ===
{ source : 'prm:ask' , target : 'scr:skill-marker' , type : 'blocks' } ,
{ source : 'prm:ask' , target : 'scr:skill-check' , type : 'blocks' } ,
{ source : 'prm:ask' , target : 'scr:economy-mode' , type : 'blocks' } ,
{ source : 'prm:ask' , target : 'scr:economy-self-check' , type : 'blocks' } ,
{ source : 'prm:ask' , target : 'scr:economy-state-guard' , type : 'blocks' } ,
{ source : 'prm:ask' , target : 'scr:economy-verifier' , type : 'blocks' } ,
{ source : 'prm:ask' , target : 'scr:economy-postcompact' , type : 'blocks' } ,
// === denies (1) — permissions.deny → state file ===
{ source : 'prm:deny' , target : 'st:economy-state' , type : 'denies' }
] ;
console . log ( 'GRAPH_LINKS:' , GRAPH _LINKS . length , '(expected 52)' ) ;
// ============================================================
// RUSSIAN LABEL MAPPINGS + CLASSIFICATION
// ============================================================
const EDGE _TYPE _RU = {
contains : 'содержит' ,
triggers : 'запускает' ,
writes : 'пишет' ,
reads : 'читает' ,
mandates : 'обязывает' ,
references : 'ссылается' ,
blocks : 'блокирует' ,
denies : 'запрещает'
} ;
const NODE _TYPE _RU = {
plugin : 'Плагин' ,
skill : 'Скил' ,
script : 'Скрипт' ,
event : 'Событие' ,
state : 'Состояние' ,
perm : 'Права' ,
rule : 'Правило'
} ;
const EDGE _DESC = {
contains : 'Плагин упаковывает скил и доставляет его в систему как часть marketplace-пакета.' ,
triggers : 'Hook event запускает скрипт автоматически в момент события (SessionStart, PreToolUse, Stop, etc.).' ,
writes : 'Скрипт записывает данные в общий state-файл $TEMP/claude-economy-<session_id>.json для других хуков той же сессии.' ,
reads : 'Скрипт читает данные из state-файла, чтобы знать активный уровень экономии и применять правила.' ,
mandates : 'Pravila §12 hard rule обязывает использовать этот skill для подходящих задач — §9 «Отступления» НЕ применяется.' ,
references : 'Документ ссылается на другой как часть приоритетной цепочки правил (CLAUDE.md §1). При конфликте — приоритет у верхнего уровня.' ,
blocks : 'permissions.ask требует явный approve пользователя перед Edit/Write этого файла. Защита от tampering.' ,
denies : 'permissions.deny полностью запрещает Bash-операции (rm/mv/cp) над защищёнными файлами — обхода нет.'
} ;
const GOVERNANCE _TYPES = [ 'contains' , 'mandates' , 'triggers' , 'blocks' , 'denies' ] ;
// ============================================================
// D3 SIMULATION + RENDER + INTERACTIVITY
// ============================================================
window . addEventListener ( 'DOMContentLoaded' , ( ) => {
if ( typeof d3 === 'undefined' ) {
document . querySelector ( '.graph-svg-wrap' ) . innerHTML =
'<div class="graph-fallback">⚠ D3.js не загружен (нужен интернет для CDN). Остальная страница работает offline.</div>' ;
return ;
}
const W = 1100 , H = 700 ;
const svg = d3 . select ( '.graph-svg' ) ;
// Y-position по типу для clustering
const Y _BY _TYPE = {
'rule' : 80 , 'plugin' : 200 , 'skill' : 340 ,
'event' : 540 , 'script' : 460 , 'state' : 380 , 'perm' : 600
} ;
const LINK _DISTANCE = {
'contains' : 60 , 'triggers' : 50 , 'writes' : 40 , 'reads' : 40 ,
'mandates' : 100 , 'references' : 80 , 'blocks' : 70 , 'denies' : 50
} ;
const NODE _SIZE = {
'plugin' : 22 , 'skill' : 10 , 'script' : 14 , 'event' : 14 ,
'state' : 16 , 'perm' : 16 , 'rule' : 18
} ;
// Force simulation
const sim = d3 . forceSimulation ( GRAPH _NODES )
. force ( 'link' , d3 . forceLink ( GRAPH _LINKS ) . id ( d => d . id )
. distance ( d => LINK _DISTANCE [ d . type ] || 50 )
. strength ( 0.5 ) )
. force ( 'charge' , d3 . forceManyBody ( ) . strength ( - 280 ) )
. force ( 'center' , d3 . forceCenter ( W / 2 , H / 2 ) )
. force ( 'y' , d3 . forceY ( d => Y _BY _TYPE [ d . type ] || H / 2 ) . strength ( 0.18 ) )
. force ( 'collide' , d3 . forceCollide ( ) . radius ( d => ( NODE _SIZE [ d . type ] || 10 ) + 6 ) ) ;
// Render links
const linkSel = svg . append ( 'g' ) . attr ( 'class' , 'links' )
. selectAll ( 'line' )
. data ( GRAPH _LINKS )
. join ( 'line' )
. attr ( 'class' , d => ` gl gl- ${ d . type } ` ) ;
// Render nodes как <g>
const nodeSel = svg . append ( 'g' ) . attr ( 'class' , 'nodes' )
. selectAll ( 'g.gn-node' )
. data ( GRAPH _NODES )
. join ( 'g' )
. attr ( 'class' , d => ` gn-node gn-node- ${ d . type } ` ) ;
// Shape по type
nodeSel . each ( function ( d ) {
const g = d3 . select ( this ) ;
const size = NODE _SIZE [ d . type ] ;
if ( d . type === 'plugin' || d . type === 'skill' || d . type === 'script' ) {
g . append ( 'circle' ) . attr ( 'r' , size ) . attr ( 'class' , ` gn- ${ d . type } ` ) ;
} else if ( d . type === 'event' ) {
g . append ( 'rect' ) . attr ( 'x' , - size ) . attr ( 'y' , - size )
. attr ( 'width' , size * 2 ) . attr ( 'height' , size * 2 ) . attr ( 'class' , 'gn-event' ) ;
} else if ( d . type === 'state' ) {
g . append ( 'polygon' )
. attr ( 'points' , ` 0,- ${ size } ${ size } ,0 0, ${ size } - ${ size } ,0 ` )
. attr ( 'class' , 'gn-state' ) ;
} else if ( d . type === 'perm' ) {
const s = size ;
g . append ( 'polygon' )
. attr ( 'points' , ` - ${ s } ,- ${ s / 2 } 0,- ${ s } ${ s } ,- ${ s / 2 } ${ s } , ${ s / 2 } 0, ${ s } - ${ s } , ${ s / 2 } ` )
. attr ( 'class' , 'gn-perm' ) ;
} else if ( d . type === 'rule' ) {
g . append ( 'rect' ) . attr ( 'x' , - size ) . attr ( 'y' , - size )
. attr ( 'width' , size * 2 ) . attr ( 'height' , size * 2 ) . attr ( 'class' , 'gn-rule' ) ;
}
} ) ;
// Labels
nodeSel . append ( 'text' )
. attr ( 'class' , 'gn-label' )
. attr ( 'dy' , d => ( NODE _SIZE [ d . type ] || 10 ) + 14 )
. text ( d => d . label ) ;
// ============================================================
// INTERACTIVITY: click + highlight + sidebar
// ============================================================
const sidebar = document . querySelector ( '.graph-sidebar' ) ;
let activeId = null ;
function showSidebar ( node ) {
const incoming = GRAPH _LINKS . filter ( l =>
( typeof l . target === 'object' ? l . target . id : l . target ) === node . id ) ;
const outgoing = GRAPH _LINKS . filter ( l =>
( typeof l . source === 'object' ? l . source . id : l . source ) === node . id ) ;
const governedBy = incoming . filter ( l => GOVERNANCE _TYPES . includes ( l . type ) ) ;
const governing = outgoing . filter ( l => GOVERNANCE _TYPES . includes ( l . type ) ) ;
const infoFlow = [ ... incoming , ... outgoing ] . filter ( l => ! GOVERNANCE _TYPES . includes ( l . type ) ) ;
const fmtIncoming = list => list . map ( l => {
const srcId = typeof l . source === 'object' ? l . source . id : l . source ;
const src = GRAPH _NODES . find ( n => n . id === srcId ) ;
return ` <li> ${ src ? src . label : srcId } <b> ${ EDGE _TYPE _RU [ l . type ] ? ? l . type } </b></li> ` ;
} ) . join ( '' ) ;
const fmtOutgoing = list => list . map ( l => {
const tgtId = typeof l . target === 'object' ? l . target . id : l . target ;
const tgt = GRAPH _NODES . find ( n => n . id === tgtId ) ;
return ` <li><b> ${ EDGE _TYPE _RU [ l . type ] ? ? l . type } </b> → ${ tgt ? tgt . label : tgtId } </li> ` ;
} ) . join ( '' ) ;
const fmtInfoFlow = list => list . map ( l => {
const sId = typeof l . source === 'object' ? l . source . id : l . source ;
const tId = typeof l . target === 'object' ? l . target . id : l . target ;
const isIncoming = tId === node . id ;
if ( isIncoming ) {
const src = GRAPH _NODES . find ( n => n . id === sId ) ;
return ` <li> ${ src ? src . label : sId } <b> ${ EDGE _TYPE _RU [ l . type ] ? ? l . type } </b></li> ` ;
} else {
const tgt = GRAPH _NODES . find ( n => n . id === tId ) ;
return ` <li><b> ${ EDGE _TYPE _RU [ l . type ] ? ? l . type } </b> → ${ tgt ? tgt . label : tId } </li> ` ;
}
} ) . join ( '' ) ;
const typeLabel = NODE _TYPE _RU [ node . type ] ? ? node . type ;
sidebar . innerHTML = `
<button class="graph-close" aria-label="Close">× </button>
<div class="graph-sidebar-title"> ${ node . label } </div>
<div class="graph-sidebar-badge"> ${ typeLabel } </div>
<div class="graph-sidebar-section">
<div class="graph-sidebar-section-label">За что отвечает</div>
<div style="font-size:0.85rem; color: var(--ink-soft); line-height: 1.5;"> ${ node . desc } </div>
</div>
${ governedBy . length ? `
<div class="graph-sidebar-section governance">
<div class="graph-sidebar-section-label">Кто руководит ( ${ governedBy . length } )</div>
<ul class="graph-conn-list"> ${ fmtIncoming ( governedBy ) } </ul>
</div> ` : '' }
${ governing . length ? `
<div class="graph-sidebar-section governance">
<div class="graph-sidebar-section-label">Кем руководит ( ${ governing . length } )</div>
<ul class="graph-conn-list"> ${ fmtOutgoing ( governing ) } </ul>
</div> ` : '' }
${ infoFlow . length ? `
<div class="graph-sidebar-section">
<div class="graph-sidebar-section-label">Связи — info flow ( ${ infoFlow . length } )</div>
<ul class="graph-conn-list"> ${ fmtInfoFlow ( infoFlow ) } </ul>
</div> ` : '' }
` ;
sidebar . querySelector ( '.graph-close' ) . addEventListener ( 'click' , clearHighlight ) ;
}
function highlightNode ( node ) {
activeId = node . id ;
const relatedIds = new Set ( [ node . id ] ) ;
GRAPH _LINKS . forEach ( l => {
const sId = typeof l . source === 'object' ? l . source . id : l . source ;
const tId = typeof l . target === 'object' ? l . target . id : l . target ;
if ( sId === node . id ) relatedIds . add ( tId ) ;
if ( tId === node . id ) relatedIds . add ( sId ) ;
} ) ;
nodeSel . classed ( 'dimmed' , d => ! relatedIds . has ( d . id ) ) ;
linkSel . classed ( 'dimmed' , l => {
const sId = typeof l . source === 'object' ? l . source . id : l . source ;
const tId = typeof l . target === 'object' ? l . target . id : l . target ;
return sId !== node . id && tId !== node . id ;
} ) ;
showSidebar ( node ) ;
}
function clearHighlight ( ) {
activeId = null ;
nodeSel . classed ( 'dimmed' , false ) ;
linkSel . classed ( 'dimmed' , false ) ;
sidebar . innerHTML = '<div class="graph-sidebar-empty">Кликни на узел или связь чтобы увидеть детали…</div>' ;
}
function showEdgeSidebar ( edge ) {
const sId = typeof edge . source === 'object' ? edge . source . id : edge . source ;
const tId = typeof edge . target === 'object' ? edge . target . id : edge . target ;
const src = GRAPH _NODES . find ( n => n . id === sId ) ;
const tgt = GRAPH _NODES . find ( n => n . id === tId ) ;
const ruLabel = EDGE _TYPE _RU [ edge . type ] ? ? edge . type ;
const desc = EDGE _DESC [ edge . type ] ? ? '' ;
const srcType = NODE _TYPE _RU [ src ? . type ] ? ? '' ;
const tgtType = NODE _TYPE _RU [ tgt ? . type ] ? ? '' ;
sidebar . innerHTML = `
<button class="graph-close" aria-label="Close">× </button>
<div class="graph-sidebar-title"> ${ ruLabel } </div>
<div class="graph-sidebar-badge">Связь</div>
<div class="graph-sidebar-section">
<div class="graph-sidebar-section-label">Что это значит</div>
<div style="font-size:0.85rem; color: var(--ink-soft); line-height: 1.5;"> ${ desc } </div>
</div>
<div class="graph-sidebar-section">
<div class="graph-sidebar-section-label">Источник — ${ srcType } </div>
<div style="font-family: 'Fraunces', serif; font-weight: 500; font-size: 1rem;"> ${ src ? . label ? ? sId } </div>
<div style="font-size:0.82rem; color: var(--ink-soft); line-height: 1.45; margin-top: 4px;"> ${ src ? . desc ? ? '' } </div>
<button class="graph-sidebar-navlink" data-nav-to=" ${ sId } ">Перейти к узлу →</button>
</div>
<div class="graph-sidebar-section">
<div class="graph-sidebar-section-label">Цель — ${ tgtType } </div>
<div style="font-family: 'Fraunces', serif; font-weight: 500; font-size: 1rem;"> ${ tgt ? . label ? ? tId } </div>
<div style="font-size:0.82rem; color: var(--ink-soft); line-height: 1.45; margin-top: 4px;"> ${ tgt ? . desc ? ? '' } </div>
<button class="graph-sidebar-navlink" data-nav-to=" ${ tId } ">Перейти к узлу →</button>
</div>
` ;
sidebar . querySelector ( '.graph-close' ) . addEventListener ( 'click' , clearHighlight ) ;
sidebar . querySelectorAll ( '.graph-sidebar-navlink' ) . forEach ( btn => {
btn . addEventListener ( 'click' , ( ) => {
const targetId = btn . dataset . navTo ;
const targetNode = GRAPH _NODES . find ( n => n . id === targetId ) ;
if ( targetNode ) highlightNode ( targetNode ) ;
} ) ;
} ) ;
}
function highlightEdge ( edge ) {
const sId = typeof edge . source === 'object' ? edge . source . id : edge . source ;
const tId = typeof edge . target === 'object' ? edge . target . id : edge . target ;
activeId = ` edge: ${ sId } -> ${ tId } ` ;
nodeSel . classed ( 'dimmed' , d => d . id !== sId && d . id !== tId ) ;
linkSel . classed ( 'dimmed' , l => l !== edge ) ;
showEdgeSidebar ( edge ) ;
}
nodeSel . on ( 'click' , ( event , d ) => {
if ( event . defaultPrevented ) return ; // was a drag, not a click
event . stopPropagation ( ) ;
if ( activeId === d . id ) clearHighlight ( ) ;
else highlightNode ( d ) ;
} ) ;
svg . on ( 'click' , clearHighlight ) ;
// ============================================================
// INTERACTIVITY: hover edge → tooltip
// ============================================================
const tooltip = d3 . select ( document . body )
. append ( 'div' ) . attr ( 'class' , 'gl-tooltip' ) . style ( 'display' , 'none' ) ;
linkSel . on ( 'mouseover' , function ( event , l ) {
const sId = typeof l . source === 'object' ? l . source . id : l . source ;
const tId = typeof l . target === 'object' ? l . target . id : l . target ;
const src = GRAPH _NODES . find ( n => n . id === sId ) ;
const tgt = GRAPH _NODES . find ( n => n . id === tId ) ;
tooltip . html ( ` <b> ${ EDGE _TYPE _RU [ l . type ] ? ? l . type } </b>: ${ src ? . label ? ? sId } → ${ tgt ? . label ? ? tId } ` )
. style ( 'display' , 'block' )
. style ( 'left' , ( event . pageX + 12 ) + 'px' )
. style ( 'top' , ( event . pageY - 8 ) + 'px' ) ;
d3 . select ( this ) . style ( 'stroke-width' , '4' ) ;
} ) ;
linkSel . on ( 'mousemove' , function ( event ) {
tooltip . style ( 'left' , ( event . pageX + 12 ) + 'px' ) . style ( 'top' , ( event . pageY - 8 ) + 'px' ) ;
} ) ;
linkSel . on ( 'mouseout' , function ( ) {
tooltip . style ( 'display' , 'none' ) ;
d3 . select ( this ) . style ( 'stroke-width' , null ) ;
} ) ;
linkSel . on ( 'click' , function ( event , l ) {
event . stopPropagation ( ) ;
tooltip . style ( 'display' , 'none' ) ;
highlightEdge ( l ) ;
} ) ;
// ============================================================
// INTERACTIVITY: drag
// ============================================================
function dragstart ( event , d ) {
if ( ! event . active ) sim . alphaTarget ( 0.3 ) . restart ( ) ;
d . fx = d . x ;
d . fy = d . y ;
}
function dragmove ( event , d ) {
d . fx = event . x ;
d . fy = event . y ;
}
function dragend ( event , d ) {
if ( ! event . active ) sim . alphaTarget ( 0 ) ;
d . fx = null ;
d . fy = null ;
}
nodeSel . call ( d3 . drag ( )
. on ( 'start' , dragstart )
. on ( 'drag' , dragmove )
. on ( 'end' , dragend ) ) ;
// ============================================================
// INTERACTIVITY: filter chips + reset
// ============================================================
const filters = document . querySelectorAll ( '.graph-filter' ) ;
const hiddenTypes = new Set ( ) ;
function applyFilters ( ) {
// If currently-selected node's type is being hidden — clear selection
if ( activeId && ! activeId . startsWith ( 'edge:' ) ) {
const activeNode = GRAPH _NODES . find ( n => n . id === activeId ) ;
if ( activeNode && hiddenTypes . has ( activeNode . type ) ) clearHighlight ( ) ;
}
// If currently-selected edge has hidden source/target type — clear
if ( activeId && activeId . startsWith ( 'edge:' ) ) {
const match = activeId . match ( /^edge:(.+)->(.+)$/ ) ;
if ( match ) {
const sN = GRAPH _NODES . find ( n => n . id === match [ 1 ] ) ;
const tN = GRAPH _NODES . find ( n => n . id === match [ 2 ] ) ;
if ( ( sN && hiddenTypes . has ( sN . type ) ) || ( tN && hiddenTypes . has ( tN . type ) ) ) clearHighlight ( ) ;
}
}
nodeSel . style ( 'display' , d => hiddenTypes . has ( d . type ) ? 'none' : null ) ;
linkSel . style ( 'display' , l => {
const sT = ( typeof l . source === 'object' ? l . source . type : GRAPH _NODES . find ( n => n . id === l . source ) . type ) ;
const tT = ( typeof l . target === 'object' ? l . target . type : GRAPH _NODES . find ( n => n . id === l . target ) . type ) ;
return ( hiddenTypes . has ( sT ) || hiddenTypes . has ( tT ) ) ? 'none' : null ;
} ) ;
}
filters . forEach ( btn => {
btn . addEventListener ( 'click' , ( ) => {
const type = btn . dataset . type ;
if ( hiddenTypes . has ( type ) ) {
hiddenTypes . delete ( type ) ;
btn . classList . add ( 'active' ) ;
} else {
hiddenTypes . add ( type ) ;
btn . classList . remove ( 'active' ) ;
}
applyFilters ( ) ;
} ) ;
} ) ;
document . querySelector ( '.graph-reset' ) . addEventListener ( 'click' , ( ) => {
hiddenTypes . clear ( ) ;
filters . forEach ( b => b . classList . add ( 'active' ) ) ;
applyFilters ( ) ;
clearHighlight ( ) ;
GRAPH _NODES . forEach ( n => { n . fx = null ; n . fy = null ; } ) ;
sim . alpha ( 0.7 ) . restart ( ) ;
} ) ;
// Tick — обновление позиций
sim . on ( 'tick' , ( ) => {
linkSel
. attr ( 'x1' , d => d . source . x ) . attr ( 'y1' , d => d . source . y )
. attr ( 'x2' , d => d . target . x ) . attr ( 'y2' , d => d . target . y ) ;
nodeSel . attr ( 'transform' , d => ` translate( ${ d . x } , ${ d . y } ) ` ) ;
} ) ;
} ) ;
< / script >
< / body >
< / html >