Last active
November 24, 2025 17:52
-
-
Save pahaz/dd091bf0f55c1323cc5f82714baa42a3 to your computer and use it in GitHub Desktop.
Чеклист CTO vs проблемы организации
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="ru"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <title>Граф связей: чек-лист CTO ↔ боли</title> | |
| <style> | |
| body { | |
| margin: 0; | |
| font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| } | |
| #graph { | |
| flex: 1; | |
| min-height: 0; /* чтобы flex-контейнер нормально сжимался по высоте */ | |
| } | |
| #graph svg { | |
| width: 100%; | |
| height: auto; /* сохраняем пропорции, подстраиваем ширину под окно */ | |
| display: block; /* убирает лишние отступы снизу */ | |
| } | |
| .legend { | |
| padding: 8px 12px; | |
| font-size: 14px; | |
| border-bottom: 1px solid #ddd; | |
| background: #fafafa; | |
| display: flex; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| } | |
| .legend span { | |
| display: inline-flex; | |
| align-items: center; | |
| margin-right: 16px; | |
| } | |
| .legend .dot { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| margin-right: 6px; | |
| display: inline-block; | |
| } | |
| .legend .view-toggle { | |
| margin-left: auto; | |
| font-size: 13px; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 4px; | |
| } | |
| .legend button { | |
| padding: 3px 8px; | |
| font-size: 12px; | |
| border-radius: 4px; | |
| border: 1px solid #ccc; | |
| background: #fff; | |
| cursor: pointer; | |
| } | |
| .legend button.active { | |
| font-weight: 600; | |
| border-color: #333; | |
| background: #e0e0e0; | |
| } | |
| .node text { | |
| pointer-events: none; | |
| font-size: 11px; | |
| } | |
| .node circle { | |
| stroke: #fff; | |
| stroke-width: 1.5px; | |
| } | |
| .node.checklist circle { | |
| fill: #1f77b4; | |
| } | |
| .node.pain circle { | |
| fill: #ff7f0e; | |
| } | |
| .node.selected circle { | |
| stroke: #000; | |
| stroke-width: 3px; | |
| } | |
| .link { | |
| stroke: #aaa; | |
| opacity: 0.6; | |
| transition: opacity 0.15s, stroke 0.15s; | |
| } | |
| /* подсветка связей в двудольном режиме */ | |
| .link.highlight { | |
| stroke: #000; | |
| opacity: 1; | |
| } | |
| .link.dimmed { | |
| opacity: 0.1; | |
| } | |
| /* текст комментариев по связям в двудольном режиме */ | |
| .note-text { | |
| fill: #555; | |
| font-size: 8px; | |
| opacity: 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="legend"> | |
| <span><span class="dot" style="background:#1f77b4"></span>Пункты чек-листа CTO</span> | |
| <span><span class="dot" style="background:#ff7f0e"></span>Боли (1–36)</span> | |
| <span style="margin-left:24px;opacity:.7;"> | |
| Силовой: клик по узлу — фокус и кольца. Двудольный: клик подсвечивает связи узла. | |
| </span> | |
| <span class="view-toggle"> | |
| Вид: | |
| <button id="mode-force" class="active">Силовой</button> | |
| <button id="mode-bipartite">Двудольный</button> | |
| </span> | |
| </div> | |
| <div id="graph"> | |
| <svg | |
| width="1400" height="1100" | |
| viewBox="0 0 1400 1100" | |
| preserveAspectRatio="xMidYMid meet" | |
| ></svg> | |
| </div> | |
| <script src="https://d3js.org/d3.v7.min.js"></script> | |
| <script> | |
| // Пункты чек-листа CTO | |
| const checklistItems = [ | |
| { id: 'c1', label: 'Синхронизируем видение рынка и стратегии' }, | |
| { id: 'c2', label: 'Встраиваем технологическое видение в стратегию компании' }, | |
| { id: 'c3', label: 'Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям' }, | |
| { id: 'c4', label: 'Синхронизируем roadmap, цели и задачи' }, | |
| { id: 'c5', label: 'Приоритизируем продуктовый и технический бэклог' }, | |
| { id: 'c6', label: 'Договариваемся про бюджеты' }, | |
| { id: 'c7', label: 'Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»' }, | |
| { id: 'c8', label: 'Строим стратегию найма' }, | |
| { id: 'c9', label: 'Балансируем «скорость найма / стоимость поиска / риски культурных расхождений»' }, | |
| { id: 'c10', label: 'Проверяем, соответствует ли «рабочая среда» ожиданиям' }, | |
| { id: 'c11', label: 'Выделяем и декомпозируем ключевые эпики и инициативы' }, | |
| { id: 'c12', label: 'Согласовываем общие OKR / KPI / дашборды / ключевые метрики' }, | |
| { id: 'c13', label: 'Доносим, что реализуемо, где фантазии и как управляем рисками' }, | |
| { id: 'c14', label: 'Определяем структуру команд' }, | |
| { id: 'c15', label: 'Формируем культуру, ценности и архитектурные принципы' }, | |
| { id: 'c16', label: 'Определяем клиентские пути' }, | |
| { id: 'c17', label: 'Определяем ценность для клиентов и как будем её доставлять' }, | |
| { id: 'c18', label: 'Выравниваем ценности, ожидания и доступные инструменты' }, | |
| { id: 'c19', label: 'Стандартизируем инженерные практики и подходы' }, | |
| { id: 'c20', label: 'Отслеживаем сигналы от тех, кто ежедневно создаёт ценность' }, | |
| { id: 'c21', label: 'Собираем обратную связь, поддерживаем и анализируем мотивацию' }, | |
| { id: 'c22', label: 'Разрабатываем грейды, систему оценки и ценностей' }, | |
| { id: 'c23', label: 'Публичные выступления, технический бренд, репутация компании' }, | |
| { id: 'c24', label: 'Выстраиваем канал получения обратной связи с «передовой» от клиентов' }, | |
| { id: 'c25', label: 'Определяем общую культуру и ценности' }, | |
| { id: 'c26', label: 'Формируем внешнее позиционирование технологий' }, | |
| { id: 'c27', label: 'Поддерживаем сложные сделки и коммитменты' }, | |
| { id: 'c28', label: 'Работа с ключевыми партнёрами' }, | |
| { id: 'c29', label: 'Прохождение внешних аудитов' } | |
| ]; | |
| // Боли 1–36 | |
| const pains = [ | |
| { | |
| id: 'p1', | |
| label: '1. Работа без фокуса', | |
| notes: [ | |
| 'Компания гоняется за всеми хотелками и трендами.', | |
| 'Нет единого плана и отказа от лишнего.' | |
| ] | |
| }, | |
| { | |
| id: 'p2', | |
| label: '2. Установка на переработки', | |
| notes: [ | |
| 'Переработки считаются нормой и «героизмом».', | |
| 'Скорость выжимают из людей, а не из организации.' | |
| ] | |
| }, | |
| { | |
| id: 'p3', | |
| label: '3. Избыток встреч', | |
| notes: [ | |
| 'Календарь забит совещаниями вместо работы.', | |
| 'Встречи плохо готовятся и мало что решают.' | |
| ] | |
| }, | |
| { | |
| id: 'p4', | |
| label: '4. Чрезмерная бюрократия', | |
| notes: [ | |
| 'Любое изменение тонет в согласованиях.', | |
| 'Решения откладывают, ответственность размыта.' | |
| ] | |
| }, | |
| { | |
| id: 'p5', | |
| label: '5. Совместительство и размытие зон ответственности', | |
| notes: [ | |
| 'На людей вешают несколько конфликтующих ролей.', | |
| 'Никто не отвечает за результат целиком, все быстрее выгорают.' | |
| ] | |
| }, | |
| { | |
| id: 'p6', | |
| label: '6. Медленное принятие решений и бессмысленная работа', | |
| notes: [ | |
| 'Фичи делаются, но релизы и эффект откладываются на месяцы.', | |
| 'У людей исчезает ощущение смысла и влияния.' | |
| ] | |
| }, | |
| { | |
| id: 'p7', | |
| label: '7. Сбой в Work-life и невозможность отключиться', | |
| notes: [ | |
| 'Работа растягивается на вечера, выходные, другие часовые пояса.', | |
| 'Дежурства и ожидание звонка не дают восстановиться.' | |
| ] | |
| }, | |
| { | |
| id: 'p8', | |
| label: '8. Отсутствие чётких и адекватных требований', | |
| notes: [ | |
| 'Руководство не формулирует понятных целей и критериев.', | |
| 'Команды постоянно угадывают, «что имели в виду наверху».' | |
| ] | |
| }, | |
| { | |
| id: 'p9', | |
| label: '9. Изолированность команд и дефицит коммуникаций', | |
| notes: [ | |
| 'Люди работают в «коробочках» без нормального общения.', | |
| 'Продукт и команда фрагментируются, падает вовлечённость.' | |
| ] | |
| }, | |
| { | |
| id: 'p10', | |
| label: '10. Отсутствие контроля над жизнью', | |
| notes: [ | |
| 'Сотрудники почти ни на что не влияют.', | |
| 'Решения принимаются «над головой», рождая беспомощность.' | |
| ] | |
| }, | |
| { | |
| id: 'p11', | |
| label: '11. Непрозрачность карьерного трека', | |
| notes: [ | |
| 'Неясно, как расти и сколько это займет.', | |
| 'Карьера ощущается как туман с высоким стрессом.' | |
| ] | |
| }, | |
| { | |
| id: 'p12', | |
| label: '12. Выстроена система обмана', | |
| notes: [ | |
| 'Обещают рост и компенсации, но постоянно переносят.', | |
| 'Доверие ломается, мотивация держится на манипуляциях.' | |
| ] | |
| }, | |
| { | |
| id: 'p13', | |
| label: '13. Метрики превыше смысла', | |
| notes: [ | |
| 'Процессы подстраивают под KPI, а не под ценность.', | |
| 'Люди играют в цифры вместо улучшения системы.' | |
| ] | |
| }, | |
| { | |
| id: 'p14', | |
| label: '14. Хайп превыше смысла', | |
| notes: [ | |
| 'Технологии и фичи выбирают по моде, а не по пользе.', | |
| 'Ресурсы уходят на «хайп-проекты» вместо ключевых задач.' | |
| ] | |
| }, | |
| { | |
| id: 'p15', | |
| label: '15. Обязательный возврат в офис', | |
| notes: [ | |
| 'Насильный отказ от гибрида и удалёнки.', | |
| 'Теряется гибкость, растёт недовольство и отток.' | |
| ] | |
| }, | |
| { | |
| id: 'p16', | |
| label: '16. Слишком много или совсем без документации', | |
| notes: [ | |
| 'Пишут толстые документы ради процесса.', | |
| 'Или обходятся без описаний, всё держится в головах.' | |
| ] | |
| }, | |
| { | |
| id: 'p17', | |
| label: '17. Отсутствие системности информации', | |
| notes: [ | |
| 'Документы разрознены, противоречат и быстро стареют.', | |
| 'Непонятно, где искать ответы и как в это всё въехать.' | |
| ] | |
| }, | |
| { | |
| id: 'p18', | |
| label: '18. Негативный новостной фон', | |
| notes: [ | |
| 'Постоянные новости про сокращения, кризисы, угрозы.', | |
| 'Люди перестают верить в будущее компании.' | |
| ] | |
| }, | |
| { | |
| id: 'p19', | |
| label: '19. Отсутствие или несоблюдение стратегии', | |
| notes: [ | |
| 'Стратегия либо отсутствует, либо живет только в презентации.', | |
| 'Руководство почти не тратит время на стратегическую работу.' | |
| ] | |
| }, | |
| { | |
| id: 'p20', | |
| label: '20. Отсутствие приоритетов', | |
| notes: [ | |
| 'Сразу много «самых важных» задач.', | |
| 'Командам приходится самим решать, что делать и чем жертвовать.' | |
| ] | |
| }, | |
| { | |
| id: 'p21', | |
| label: '21. Дискредитация стратегии', | |
| notes: [ | |
| 'Формально делают «свои мини-стратегии», не связанные с общей.', | |
| 'Стратегия превращается в формальность, которой никто не верит.' | |
| ] | |
| }, | |
| { | |
| id: 'p22', | |
| label: '22. Постоянные отвлечения', | |
| notes: [ | |
| 'Почта, мессенджеры, «на минуточку» рвут фокус весь день.', | |
| 'Много времени уходит на переключения вместо глубокой работы.' | |
| ] | |
| }, | |
| { | |
| id: 'p23', | |
| label: '23. Организационный долг', | |
| notes: [ | |
| 'Временные костыли в ролях и процессах становятся постоянными.', | |
| 'Любое изменение упирается в старые «временные решения».' | |
| ] | |
| }, | |
| { | |
| id: 'p24', | |
| label: '24. Технический долг', | |
| notes: [ | |
| 'Качество, тесты и рефакторинг системно откладывают.', | |
| 'Система становится хрупкой, дорогой и тормозит развитие.' | |
| ] | |
| }, | |
| { | |
| id: 'p25', | |
| label: '25. Хаос в процессах', | |
| notes: [ | |
| 'Нет единых правил, кто и как что делает.', | |
| 'Всё держится на ручном управлении и личных договорённостях.' | |
| ] | |
| }, | |
| { | |
| id: 'p26', | |
| label: '26. Борьба с конфликтами', | |
| notes: [ | |
| 'Конфликты стараются гасить, а не разбирать причины.', | |
| 'Потеря сигналов о проблемах и общая апатия.' | |
| ] | |
| }, | |
| { | |
| id: 'p27', | |
| label: '27. Фасилитация проблем', | |
| notes: [ | |
| 'Фасилитация используется как постоянное «обезболивающее».', | |
| 'Корневые организационные баги не лечатся.' | |
| ] | |
| }, | |
| { | |
| id: 'p28', | |
| label: '28. Агенты изменений не видят всей картины', | |
| notes: [ | |
| 'Тем, кто тянет изменения, не дают контекста и полномочий.', | |
| 'Инициативы остаются локальными и разрозненными.' | |
| ] | |
| }, | |
| { | |
| id: 'p29', | |
| label: '29. Простои и панические релизы', | |
| notes: [ | |
| 'Частые аварии, инциденты и «пожарные» выкаты.', | |
| 'Команда живёт в постоянном режиме тушения огня.' | |
| ] | |
| }, | |
| { | |
| id: 'p30', | |
| label: '30. Отсутствие резервов', | |
| notes: [ | |
| 'Люди и мощности загружены под 100%.', | |
| 'Малейший сбой рушит план и перегружает всех.' | |
| ] | |
| }, | |
| { | |
| id: 'p31', | |
| label: '31. Митинги по утрам, работа — вечером', | |
| notes: [ | |
| 'Самое продуктивное время занято совещаниями и перепиской.', | |
| 'Настоящая работа уезжает на вечер и ночь.' | |
| ] | |
| }, | |
| { | |
| id: 'p32', | |
| label: '32. Отсутствие онбординга (особенно для тимлидов)', | |
| notes: [ | |
| 'Новичков и новых менеджеров плохо вводят в роль.', | |
| 'Высокий стресс, ошибки и ранние увольнения.' | |
| ] | |
| }, | |
| { | |
| id: 'p33', | |
| label: '33. Раздавать задачи сверху', | |
| notes: [ | |
| 'Руководитель сам раздаёт задачи как считает нужным.', | |
| 'Не учитываются сильные стороны и интересы людей.' | |
| ] | |
| }, | |
| { | |
| id: 'p34', | |
| label: '34. Использовать метрики, ревью и прочие практики для критики', | |
| notes: [ | |
| 'Метрики и оценка превращаются в инструмент давления.', | |
| 'Ревью бьёт по самооценке вместо развития.' | |
| ] | |
| }, | |
| { | |
| id: 'p35', | |
| label: '35. Неправильный выбор стека технологий и подходов', | |
| notes: [ | |
| 'Технологии выбирают по привычке, цене или хайпу.', | |
| 'Стек удорожает проект и повышает риск провала.' | |
| ] | |
| }, | |
| { | |
| id: 'p36', | |
| label: '36. Массовые сокращения', | |
| notes: [ | |
| 'Увольнения используют как главный способ «оптимизации».', | |
| 'Долгосрочно рушат результаты и выталкивают лучших людей.' | |
| ] | |
| } | |
| ]; | |
| // Рёбра: какая боль лечится какими пунктами чек-листа + weight (1..3) | |
| const links = [ | |
| // p1 «1. Работа без фокуса» ← c1 «Синхронизируем видение рынка и стратегии» — главный стратегический рычаг фокуса | |
| { source: 'c1', target: 'p1', weight: 3, notes: 'Привязывает работу к общему контексту рынка.' }, | |
| // p1 «1. Работа без фокуса» ← c2 «Встраиваем технологическое видение в стратегию компании» — соединяет тех и стратегию | |
| { source: 'c2', target: 'p1', weight: 2, notes: 'Соединяет технологические решения со стратегией.' }, | |
| // p1 «1. Работа без фокуса» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — экономический фильтр | |
| { source: 'c3', target: 'p1', weight: 2, notes: 'Фильтрует инициативы через экономический смысл.' }, | |
| // p1 «1. Работа без фокуса» ← c4 «Синхронизируем roadmap, цели и задачи» — фокус закрепляется в планах | |
| { source: 'c4', target: 'p1', weight: 2, notes: 'Фиксирует фокус в планах и целях.' }, | |
| // p1 «1. Работа без фокуса» ← c5 «Приоритизируем продуктовый и технический бэклог» — локальное отсечение лишнего | |
| { source: 'c5', target: 'p1', weight: 1, notes: 'Отбрасывает лишние задачи в бэклоге.' }, | |
| // p1 «1. Работа без фокуса» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — подкрепляет фокус измеримыми целями | |
| { source: 'c12', target: 'p1', weight: 2, notes: 'Связывает фокус с измеримыми результатами, а не с хотелками.' }, | |
| // p1 «1. Работа без фокуса» ← c13 «Доносим, что реализуемо, где фантазии и как управляем рисками» — отрезвление хотелок | |
| { source: 'c13', target: 'p1', weight: 1, notes: 'Управление рисками и реалистичностью отсекает расфокус на «фантазии».' }, | |
| // p2 «2. Установка на переработки» ← c6 «Договариваемся про бюджеты» — главный рычаг: ресурсы вместо переработок | |
| { source: 'c6', target: 'p2', weight: 3, notes: 'Закладывает ресурсы без опоры на переработки.' }, | |
| // p2 «2. Установка на переработки» ← c7 «Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»» — баланс скорости и качества | |
| { source: 'c7', target: 'p2', weight: 2, notes: 'Ограничивает скорость за счёт качества, а не людей.' }, | |
| // p2 «2. Установка на переработки» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — учитывает цену выгорания | |
| { source: 'c3', target: 'p2', weight: 2, notes: 'Учитывает цену выгорания и текучки.' }, | |
| // p2 «2. Установка на переработки» ← c8 «Строим стратегию найма» — найм вместо вечного аврала | |
| { source: 'c8', target: 'p2', weight: 2, notes: 'Планирует найм вместо вечного аврала.' }, | |
| // p2 «2. Установка на переработки» ← c9 «Балансируем «скорость найма / стоимость поиска / риски культурных расхождений»» — сглаживает качели найма | |
| { source: 'c9', target: 'p2', weight: 2, notes: 'Не допускает «хиринг во что бы то ни стало».' }, | |
| // p2 «2. Установка на переработки» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — нормализует ожидания по режиму | |
| { source: 'c10', target: 'p2', weight: 1, notes: 'Фиксирует разумные ожидания по режиму работы.' }, | |
| // p2 «2. Установка на переработки» ← c15 «Формируем культуру, ценности и архитектурные принципы» — закрепляем норму устойчивой, а не героической работы. | |
| { source: 'c15', target: 'p2', weight: 1, notes: 'Культура устойчивой скорости, а не героизма.' }, | |
| // p2 «2. Установка на переработки» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — видим и лечим выгорание. | |
| { source: 'c21', target: 'p2', weight: 1, notes: 'Отслеживаем выгорание и корректируем практики.' }, | |
| // p2 «2. Установка на переработки» ← c19 «Стандартизируем инженерные практики и подходы» — автоматизация рутины | |
| { source: 'c19', target: 'p2', weight: 1, notes: 'Автоматизация снижает объем ручного труда и овертаймов.' }, | |
| // p3 «3. Избыток встреч» ← c4 «Синхронизируем roadmap, цели и задачи» — главный рычаг: заменяет статус-митинги планом | |
| { source: 'c4', target: 'p3', weight: 3, notes: 'Снимает нужду в статус-митингах через общий план.' }, | |
| // p3 «3. Избыток встреч» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — ясные задачи вместо созвонов «что делать?» | |
| { source: 'c11', target: 'p3', weight: 2, notes: 'Делает задачи ясными и декомпозированными.' }, | |
| // p3 «3. Избыток встреч» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — статус считывается из дашборда | |
| { source: 'c12', target: 'p3', weight: 2, notes: 'Переносит статус в дашборды, а не в созвоны.' }, | |
| // p3 «3. Избыток встреч» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — формат и объём митингов подстраивают под людей | |
| { source: 'c10', target: 'p3', weight: 1, notes: 'Подстраивает формат встреч под комфорт работы.' }, | |
| // p3 «3. Избыток встреч» ← c19 «Стандартизируем инженерные практики и подходы» — можно ввести правила по встречам и синкам. | |
| { source: 'c19', target: 'p3', weight: 1, notes: 'Стандарты включают правила про встречи и синки.' }, | |
| // p4 «4. Чрезмерная бюрократия» ← c14 «Определяем структуру команд» — понятные зоны ответственности вместо согласований по кругу. | |
| { source: 'c14', target: 'p4', weight: 3, notes: 'Ясная структура команд проясняет, кто решает и за что отвечает.' }, | |
| // p4 «4. Чрезмерная бюрократия» ← c19 «Стандартизируем инженерные практики и подходы» — стандарты вместо ручного контроля | |
| { source: 'c19', target: 'p4', weight: 2, notes: 'Задаёт простые стандарты вместо ручной бюрократии.' }, | |
| // p4 «4. Чрезмерная бюрократия» ← c4 «Синхронизируем roadmap, цели и задачи» — меньше формальных согласований ради галочки. | |
| { source: 'c4', target: 'p4', weight: 1, notes: 'Прозрачные цели уменьшают количество согласований ради галочки.' }, | |
| // p4 «4. Чрезмерная бюрократия» ← c13 «Доносим, что реализуемо, где фантазии и как управляем рисками» — главный фильтр того, что надо согласовывать | |
| { source: 'c13', target: 'p4', weight: 1, notes: 'Определяет, какие решения действительно требуют согласований.' }, | |
| // p4 «4. Чрезмерная бюрократия» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — понятные owner-ы решений | |
| { source: 'c11', target: 'p4', weight: 1, notes: 'Назначает владельцев инициатив и решений.' }, | |
| // p5 «5. Совместительство и размытие зон ответственности» ← c14 «Определяем структуру команд» — главный рычаг: ясная оргструктура | |
| { source: 'c14', target: 'p5', weight: 3, notes: 'Разводит роли и ответственность по командам.' }, | |
| // p5 «5. Совместительство и размытие зон ответственности» ← c15 «Формируем культуру, ценности и архитектурные принципы» — культура one owner | |
| { source: 'c15', target: 'p5', weight: 2, notes: 'Фиксирует принцип «one owner» в культуре.' }, | |
| // p5 «5. Совместительство и размытие зон ответственности» ← c4 «Синхронизируем roadmap, цели и задачи» — цели закреплены за конкретными командами | |
| { source: 'c4', target: 'p5', weight: 2, notes: 'Привязывает цели к конкретным владельцам.' }, | |
| // p5 «5. Совместительство и размытие зон ответственности» ← c8 «Строим стратегию найма» — найм закрывает системные дыры вместо совместительства | |
| { source: 'c8', target: 'p5', weight: 1, notes: 'Добирает людей вместо загрузки одних и тех же.' }, | |
| // p5 «5. Совместительство и размытие зон ответственности» ← c9 «Балансируем «скорость найма / стоимость поиска / риски культурных расхождений»» — не форсим совместительство ради скорости. | |
| { source: 'c9', target: 'p5', weight: 1, notes: 'Балансируем скорость найма и культурные риски, снижая совместительство.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — главный рычаг: короткие циклы | |
| { source: 'c11', target: 'p6', weight: 3, notes: 'Рубит большие проекты на управляемые шаги.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c4 «Синхронизируем roadmap, цели и задачи» — ускоряет согласование решений. | |
| { source: 'c4', target: 'p6', weight: 2, notes: 'Синхронизация roadmap ускоряет решения по фичам и релизам.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — видны цели и результаты | |
| { source: 'c12', target: 'p6', weight: 2, notes: 'Фокусирует команды на измеримых результатах.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c16 «Определяем клиентские пути» — задачи привязаны к конкретным сценариям | |
| { source: 'c16', target: 'p6', weight: 2, notes: 'Привязывает задачи к понятным пользовательским сценариям.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c13 «Доносим, что реализуемо, где фантазии и как управляем рисками» — убирает бессмысленные ожидания и подвешенные фичи. | |
| { source: 'c13', target: 'p6', weight: 2, notes: 'Описываем, что реально и как управляем рисками.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c14 «Определяем структуру команд» — автономность ускоряет | |
| { source: 'c14', target: 'p6', weight: 2, notes: 'Автономность ускоряет принятие решений.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c5 «Приоритизируем продуктовый и технический бэклог» — в первую очередь доезжает ценность | |
| { source: 'c5', target: 'p6', weight: 2, notes: 'Выстраивает очередь задач по ценности.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c24 «Выстраиваем канал получения обратной связи с «передовой» от клиентов» — быстрая проверка эффекта | |
| { source: 'c24', target: 'p6', weight: 1, notes: 'Быстро замыкает цикл от клиента до команды.' }, | |
| // p6 «6. Медленное принятие решений и бессмысленная работа» ← c27 «Поддерживаем сложные сделки и коммитменты» — делаем обязательства реалистичными и управляемыми. | |
| { source: 'c27', target: 'p6', weight: 1, notes: 'Поддержка сложных коммитов делает их реалистичнее.' }, | |
| // p7 «7. Сбой в Work-life и невозможность отключиться» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — главный рычаг WL-баланса | |
| { source: 'c10', target: 'p7', weight: 3, notes: 'Формализует границы рабочей среды и времени.' }, | |
| // p7 «7. Сбой в Work-life и невозможность отключиться» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — вовремя замечаем перегруз и меняем процессы. | |
| { source: 'c21', target: 'p7', weight: 2, notes: 'Отслеживаем выгорание и своевременно поддерживаем людей.' }, | |
| // p7 «7. Сбой в Work-life и невозможность отключиться» ← c7 «Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»» — не всё всегда «быстро» | |
| { source: 'c7', target: 'p7', weight: 2, notes: 'Убирает режим «всегда срочно» через договорённости.' }, | |
| // p7 «7. Сбой в Work-life и невозможность отключиться» ← c6 «Договариваемся про бюджеты» — ресурсы на поддержку вместо ночных дежурств всех подряд | |
| { source: 'c6', target: 'p7', weight: 2, notes: 'Закладывает бюджет на поддержку и SRE, а не людей по ночам.' }, | |
| // p7 «7. Сбой в Work-life и невозможность отключиться» ← c14 «Определяем структуру команд» — нормальные on-call, ротации и зоны ответственности | |
| { source: 'c14', target: 'p7', weight: 1, notes: 'Разводит on-call и зоны ответственности.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c1 «Синхронизируем видение рынка и стратегии» — главный источник смысла требований | |
| { source: 'c1', target: 'p8', weight: 3, notes: 'Задаёт рамку, для чего вообще делаем продукт.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c16 «Определяем клиентские пути» — требования от customer journey | |
| { source: 'c16', target: 'p8', weight: 3, notes: 'Формализует сценарии, под которые пишем требования.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c2 «Встраиваем технологическое видение в стратегию компании» — отсекает лишние тех-хотелки | |
| { source: 'c2', target: 'p8', weight: 2, notes: 'Отсекает «невписывающиеся» тех-хотелки.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c24 «Выстраиваем канал получения обратной связи с «передовой» от клиентов» — получаем реальные запросы, а не догадки. | |
| { source: 'c24', target: 'p8', weight: 2, notes: 'Канал с «передовой» уточняет реальные ожидания клиентов.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c4 «Синхронизируем roadmap, цели и задачи» — согласованные цели и сроки | |
| { source: 'c4', target: 'p8', weight: 2, notes: 'Согласовывает цели и сроки фич между сторонами.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c17 «Определяем ценность для клиентов и как будем её доставлять» — требования = ценность | |
| { source: 'c17', target: 'p8', weight: 2, notes: 'Фокусирует требования на клиентской ценности.' }, | |
| // p8 «8. Отсутствие чётких и адекватных требований» ← c18 «Выравниваем ценности, ожидания и доступные инструменты» — продажи и маркетинг не обещают лишнего | |
| { source: 'c18', target: 'p8', weight: 1, notes: 'Синхронизирует продажи и маркетинг с реальными возможностями.' }, | |
| // p9 «9. Изолированность команд и дефицит коммуникаций» ← c14 «Определяем структуру команд» — главный рычаг: как команды стыкуются | |
| { source: 'c14', target: 'p9', weight: 3, notes: 'Описывает, как команды стыкуются друг с другом.' }, | |
| // p9 «9. Изолированность команд и дефицит коммуникаций» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — цель объединяет | |
| { source: 'c12', target: 'p9', weight: 3, notes: 'Общие цели заставляют выходить из изоляции ради результата.' }, | |
| // p9 «9. Изолированность команд и дефицит коммуникаций» ← c15 «Формируем культуру, ценности и архитектурные принципы» — ценности про открытость | |
| { source: 'c15', target: 'p9', weight: 2, notes: 'Поощряет открытость и горизонтальные связи.' }, | |
| // p9 «9. Изолированность команд и дефицит коммуникаций» ← c19 «Стандартизируем инженерные практики и подходы» — общие ритуалы и процессы | |
| { source: 'c19', target: 'p9', weight: 2, notes: 'Задаёт общие инженерные ритуалы и форматы общения.' }, | |
| // p9 «9. Изолированность команд и дефицит коммуникаций» ← c4 «Синхронизируем roadmap, цели и задачи» — объединяем команды вокруг общих целей и релизов. | |
| { source: 'c4', target: 'p9', weight: 2, notes: 'Общий roadmap связывает команды вокруг общих целей.' }, | |
| // p9 «9. Изолированность команд и дефицит коммуникаций» ← c20 «Отслеживаем сигналы от тех, кто ежедневно создаёт ценность» — сигналы о стыках и разрывах | |
| { source: 'c20', target: 'p9', weight: 1, notes: 'Подсвечивает проблемы взаимодействия «с земли».' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — главный канал влияния сотрудников | |
| { source: 'c21', target: 'p10', weight: 3, notes: 'Создаёт канал, где люди могут влиять на решения.' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c25 «Определяем общую культуру и ценности» — закрепляем уважение к автономии как норму. | |
| { source: 'c25', target: 'p10', weight: 2, notes: 'Культура уважает личные границы и автономию.' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c20 «Отслеживаем сигналы от тех, кто ежедневно создаёт ценность» — поднимает сигналы о перегрузе и бессмысленной работе | |
| { source: 'c20', target: 'p10', weight: 2, notes: 'Поднимает сигналы о перегрузе и бессмысленной работе.' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — влияет на режим и формат работы | |
| { source: 'c10', target: 'p10', weight: 2, notes: 'Настраивает режим работы под ожидания команды.' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c4 «Синхронизируем roadmap, цели и задачи» — показывает связь работы с целями | |
| { source: 'c4', target: 'p10', weight: 2, notes: 'Объясняет, как вклад команды связан с целями.' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — прозрачная связь вклада и роста | |
| { source: 'c22', target: 'p10', weight: 1, notes: 'Прозрачно связывает вклад с ростом и оценкой.' }, | |
| // p10 «10. Отсутствие контроля над жизнью» ← c18 «Выравниваем ценности, ожидания и доступные инструменты» — честно проговариваем, что возможно и на каких условиях. | |
| { source: 'c18', target: 'p10', weight: 1, notes: 'Выравниваем ожидания и доступные инструменты.' }, | |
| // p11 «11. Непрозрачность карьерного трека» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — главный источник понятного трека | |
| { source: 'c22', target: 'p11', weight: 3, notes: 'Фиксирует уровни, критерии и ожидания по ролям.' }, | |
| // p11 «11. Непрозрачность карьерного трека» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — явные планы развития | |
| { source: 'c21', target: 'p11', weight: 2, notes: 'Выявляет карьерные ожидания и формирует планы роста.' }, | |
| // p11 «11. Непрозрачность карьерного трека» ← c14 «Определяем структуру команд» — роли и уровни встроены в структуру | |
| { source: 'c14', target: 'p11', weight: 1, notes: 'Привязывает роли и уровни к структуре команд.' }, | |
| // p11 «11. Непрозрачность карьерного трека» ← c25 «Определяем общую культуру и ценности» — поддерживающая культура снижает тревожность вокруг роста. | |
| { source: 'c25', target: 'p11', weight: 1, notes: 'Культура поддерживает развитие, а не только «героизм».' }, | |
| // p11 «11. Непрозрачность карьерного трека» ← c8 «Строим стратегию найма» — внутренний рост vs внешний найм | |
| { source: 'c8', target: 'p11', weight: 1, notes: 'Растим внутри или нанимаем.' }, | |
| // p12 «12. Выстроена система обмана» ← c25 «Определяем общую культуру и ценности» — главный рычаг честности | |
| { source: 'c25', target: 'p12', weight: 3, notes: 'Закрепляет честность и прозрачность как норму.' }, | |
| // p12 «12. Выстроена система обмана» ← c18 «Выравниваем ценности, ожидания и доступные инструменты» — перестаём обещать то, что не собираемся делать. | |
| { source: 'c18', target: 'p12', weight: 2, notes: 'Выравниваем ожидания вместо ложных обещаний.' }, | |
| // p12 «12. Выстроена система обмана» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — убирает произвол в повышениях | |
| { source: 'c22', target: 'p12', weight: 2, notes: 'Убирает произвол в повышениях и оценках.' }, | |
| // p12 «12. Выстроена система обмана» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — сверка обещаний и реальности | |
| { source: 'c21', target: 'p12', weight: 1, notes: 'Регулярно сверяет реальность с обещаниями.' }, | |
| // p13 «13. Метрики превыше смысла» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — главный рычаг: метрики как навигация | |
| { source: 'c12', target: 'p13', weight: 3, notes: 'Делает метрики инструментом навигации, а не кнута.' }, | |
| // p13 «13. Метрики превыше смысла» ← c25 «Определяем общую культуру и ценности» — смысл работы важнее цифр | |
| { source: 'c25', target: 'p13', weight: 2, notes: 'Ставит смысл работы выше цифр в отчёте.' }, | |
| // p13 «13. Метрики превыше смысла» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — метрики привязаны к экономике | |
| { source: 'c3', target: 'p13', weight: 2, notes: 'Связывает метрики с реальной экономикой продукта.' }, | |
| // p13 «13. Метрики превыше смысла» ← c17 «Определяем ценность для клиентов и как будем её доставлять» — возвращаем метрикам связь с реальной пользой. | |
| { source: 'c17', target: 'p13', weight: 2, notes: 'Фокус на ценности для клиента возвращает смысл метрикам.' }, | |
| // p13 «13. Метрики превыше смысла» ← c14 «Определяем структуру команд» — продуктовая ориентация | |
| { source: 'c14', target: 'p13', weight: 1, notes: 'Команды отвечают за ценность.' }, | |
| // p13 «13. Метрики превыше смысла» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — живые сигналы важнее графика | |
| { source: 'c21', target: 'p13', weight: 1, notes: 'Даёт живую обратную связь поверх цифр.' }, | |
| // p14 «14. Хайп превыше смысла» ← c1 «Синхронизируем видение рынка и стратегии» — главный фильтр хайпа через рынок/стратегию | |
| { source: 'c1', target: 'p14', weight: 3, notes: 'Фильтрует хайп-фичи через контекст рынка.' }, | |
| // p14 «14. Хайп превыше смысла» ← c2 «Встраиваем технологическое видение в стратегию компании» — технологические решения под стратегию | |
| { source: 'c2', target: 'p14', weight: 3, notes: 'Оценивает стеки через призму стратегии.' }, | |
| // p14 «14. Хайп превыше смысла» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — экономика хайп-проектов | |
| { source: 'c3', target: 'p14', weight: 2, notes: 'Считает, окупится ли хайповая инициатива.' }, | |
| // p14 «14. Хайп превыше смысла» ← c17 «Определяем ценность для клиентов и как будем её доставлять» — хайп сверяется с ценностью | |
| { source: 'c17', target: 'p14', weight: 2, notes: 'Проверяет, есть ли от хайпа ценность клиенту.' }, | |
| // p14 «14. Хайп превыше смысла» ← c5 «Приоритизируем продуктовый и технический бэклог» — хайп не попадает в топ бэклога без обоснования | |
| { source: 'c5', target: 'p14', weight: 1, notes: 'Не пускает хайп в топ бэклога без обоснований.' }, | |
| // p14 «14. Хайп превыше смысла» ← c26 «Формируем внешнее позиционирование технологий» — вынуждает объяснять, зачем именно эти технологии бизнесу. | |
| { source: 'c26', target: 'p14', weight: 2, notes: 'Внешнее позиционирование требует осмысленных решений.' }, | |
| // p15 «15. Обязательный возврат в офис» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — главный рычаг формата работы | |
| { source: 'c10', target: 'p15', weight: 3, notes: 'Собирает сигналы про формат работы и гибкость.' }, | |
| // p15 «15. Обязательный возврат в офис» ← c18 «Выравниваем ценности, ожидания и доступные инструменты» — честно обсуждаем гибрид/удалёнку/офис. | |
| { source: 'c18', target: 'p15', weight: 2, notes: 'Выравниваем ожидания по поводу гибрида/офиса/удалёнки.' }, | |
| // p15 «15. Обязательный возврат в офис» ← c25 «Определяем общую культуру и ценности» — ценность доверия и автономии | |
| { source: 'c25', target: 'p15', weight: 2, notes: 'Формулирует ценность доверия и автономии.' }, | |
| // p15 «15. Обязательный возврат в офис» ← c8 «Строим стратегию найма» — стратегия найма учитывает гибрид/удалёнку | |
| { source: 'c8', target: 'p15', weight: 1, notes: 'Закладывает гибрид и удалёнку в стратегию найма.' }, | |
| // p16 «16. Слишком много или совсем без документации» ← c19 «Стандартизируем инженерные практики и подходы» — главный рычаг: что и как документируем | |
| { source: 'c19', target: 'p16', weight: 3, notes: 'Определяет, что и как документируем.' }, | |
| // p16 «16. Слишком много или совсем без документации» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — дока вокруг эпиков | |
| { source: 'c11', target: 'p16', weight: 2, notes: 'Привязывает документы к эпикам, а не к «всему подряд».' }, | |
| // p16 «16. Слишком много или совсем без документации» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — комфортный объём и формат документации | |
| { source: 'c10', target: 'p16', weight: 1, notes: 'Учитывает, сколько документации людям комфортно.' }, | |
| // p16 «16. Слишком много или совсем без документации» ← c16 «Определяем клиентские пути» — документация обслуживает конкретный сценарий, а не сама себя. | |
| { source: 'c16', target: 'p16', weight: 1, notes: 'Клиентские пути задают минимально нужный уровень описаний.' }, | |
| // p16 «16. Слишком много или совсем без документации» ← c17 «Определяем ценность для клиентов и как будем её доставлять» — оставляем только ту документацию, которая помогает доставлять ценность. | |
| { source: 'c17', target: 'p16', weight: 1, notes: 'Фокус на ценности отсеивает бессмысленную документацию.' }, | |
| // p16 «16. Слишком много или совсем без документации» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — требование к команде | |
| { source: 'c22', target: 'p16', weight: 1, notes: 'Навык документирования можем включить в грейды.' }, | |
| // p17 «17. Отсутствие системности информации» ← c19 «Стандартизируем инженерные практики и подходы» — главный набор правил знания-шеринга | |
| { source: 'c19', target: 'p17', weight: 3, notes: 'Вводит единые правила знания-шеринга.' }, | |
| // p17 «17. Отсутствие системности информации» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — структурируем информацию вокруг эпиков и инициатив. | |
| { source: 'c11', target: 'p17', weight: 2, notes: 'Декомпозиция инициатив структурирует информацию по эпикам.' }, | |
| // p17 «17. Отсутствие системности информации» ← c15 «Формируем культуру, ценности и архитектурные принципы» — культурная норма делиться знаниями | |
| { source: 'c15', target: 'p17', weight: 2, notes: 'Закрепляет культуру делиться знаниями.' }, | |
| // p17 «17. Отсутствие системности информации» ← c24 «Выстраиваем канал получения обратной связи с «передовой» от клиентов» — заводим клиентские инсайты в единую систему. | |
| { source: 'c24', target: 'p17', weight: 1, notes: 'Каналы от клиентов заводим в понятную систему знаний.' }, | |
| // p17 «17. Отсутствие системности информации» ← c20 «Отслеживаем сигналы от тех, кто ежедневно создаёт ценность» — показывают, где инфа реально рвётся | |
| { source: 'c20', target: 'p17', weight: 1, notes: 'Показывает, где информация реально теряется.' }, | |
| // p18 «18. Негативный новостной фон» ← c23 «Публичные выступления, технический бренд, репутация компании» — главный канал внешних новостей | |
| { source: 'c23', target: 'p18', weight: 3, notes: 'Отстраивает честную и стабильную внешнюю коммуникацию.' }, | |
| // p18 «18. Негативный новостной фон» ← c25 «Определяем общую культуру и ценности» — внутренняя честность про проблемы и будущее | |
| { source: 'c25', target: 'p18', weight: 2, notes: 'Определяет, как говорить о проблемах внутри.' }, | |
| // p18 «18. Негативный новостной фон» ← c8 «Строим стратегию найма» — уменьшает качели массовый найм/массовые сокращения | |
| { source: 'c8', target: 'p18', weight: 1, notes: 'Сглаживает качели «массовый найм → массовые сокращения».' }, | |
| // p18 «18. Негативный новостной фон» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — работаем с тревогой, а не игнорируем её. | |
| { source: 'c21', target: 'p18', weight: 1, notes: 'Работаем с тревогами людей через обратную связь.' }, | |
| // p18 «18. Негативный новостной фон» ← c23 «Публичные выступления, технический бренд, репутация компании» — через внешнюю повестку создаём ощущение устойчивости. | |
| { source: 'c23', target: 'p18', weight: 1, notes: 'Сильный технический бренд поддерживает ощущение устойчивости.' }, | |
| // p19 «19. Отсутствие или несоблюдение стратегии» ← c1 «Синхронизируем видение рынка и стратегии» — формирует стратегическую рамку | |
| { source: 'c1', target: 'p19', weight: 3, notes: 'Формирует общую стратегическую рамку.' }, | |
| // p19 «19. Отсутствие или несоблюдение стратегии» ← c2 «Встраиваем технологическое видение в стратегию компании» — техкурс как часть стратегии | |
| { source: 'c2', target: 'p19', weight: 2, notes: 'Связывает технологический курс со стратегией.' }, | |
| // p19 «19. Отсутствие или несоблюдение стратегии» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — реалистичность стратегии по деньгам | |
| { source: 'c3', target: 'p19', weight: 2, notes: 'Учитывает экономику достижимости целей.' }, | |
| // p19 «19. Отсутствие или несоблюдение стратегии» ← c4 «Синхронизируем roadmap, цели и задачи» — разворачивает стратегию в планы | |
| { source: 'c4', target: 'p19', weight: 2, notes: 'Разворачивает стратегию в конкретный roadmap.' }, | |
| // p19 «19. Отсутствие или несоблюдение стратегии» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — делает стратегию измеримой | |
| { source: 'c12', target: 'p19', weight: 1, notes: 'Привязывает метрики к стратегическим целям.' }, | |
| // p20 «20. Отсутствие приоритетов» ← c5 «Приоритизируем продуктовый и технический бэклог» — главный инструмент явных приоритетов | |
| { source: 'c5', target: 'p20', weight: 3, notes: 'Делает явным порядок задач и техдолга.' }, | |
| // p20 «20. Отсутствие приоритетов» ← c4 «Синхронизируем roadmap, цели и задачи» — расставляет приоритеты по целям | |
| { source: 'c4', target: 'p20', weight: 2, notes: 'Уточняет, какие цели важнее в горизонте квартала.' }, | |
| // p20 «20. Отсутствие приоритетов» ← c7 «Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»» — решает, где скорость, а где надёжность | |
| { source: 'c7', target: 'p20', weight: 2, notes: 'Выбирает, где ускоряемся, а где бережём качество.' }, | |
| // p20 «20. Отсутствие приоритетов» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — экономическая сортировка задач | |
| { source: 'c3', target: 'p20', weight: 1, notes: 'Сравнивает приоритеты по экономической отдаче.' }, | |
| // p21 «21. Дискредитация стратегии» ← c1 «Синхронизируем видение рынка и стратегии» — одна общая стратегия вместо множества локальных | |
| { source: 'c1', target: 'p21', weight: 3, notes: 'Даёт единую стратегию вместо множества локальных.' }, | |
| // p21 «21. Дискредитация стратегии» ← c2 «Встраиваем технологическое видение в стратегию компании» — тех-инициативы не противоречат общей рамке | |
| { source: 'c2', target: 'p21', weight: 2, notes: 'Уточняет, какие тех-инициативы в неё вписываются.' }, | |
| // p21 «21. Дискредитация стратегии» ← c4 «Синхронизируем roadmap, цели и задачи» — планы команд под стратегию | |
| { source: 'c4', target: 'p21', weight: 2, notes: 'Подгоняет планы команд под общую стратегию.' }, | |
| // p21 «21. Дискредитация стратегии» ← c15 «Формируем культуру, ценности и архитектурные принципы» — культурное правило «локальное не ломает общее» | |
| { source: 'c15', target: 'p21', weight: 1, notes: 'Фиксирует правило «локальные решения не ломают курс».' }, | |
| // p21 «21. Дискредитация стратегии» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — связываем локальные планы с общей стратегией. | |
| { source: 'c12', target: 'p21', weight: 1, notes: 'Единые OKR/KPI связывают локальные планы с общей стратегией.' }, | |
| // p21 «21. Дискредитация стратегии» ← c25 «Определяем общую культуру и ценности» — культура не даёт превращать стратегию в ритуал. | |
| { source: 'c25', target: 'p21', weight: 1, notes: 'Культура поощряет честный разговор о стратегии.' }, | |
| // p22 «22. Постоянные отвлечения» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — главный рычаг: тихие часы и правила фокуса | |
| { source: 'c10', target: 'p22', weight: 3, notes: 'Вводит тихие часы и ограничения на митинги.' }, | |
| // p22 «22. Постоянные отвлечения» ← c4 «Синхронизируем roadmap, цели и задачи» — меньше «срочных» влетов задач | |
| { source: 'c4', target: 'p22', weight: 2, notes: 'Уменьшает число «срочных» влетов задач.' }, | |
| // p22 «22. Постоянные отвлечения» ← c5 «Приоритизируем продуктовый и технический бэклог» — снижает поток «срочных» в пользу действительно важных. | |
| { source: 'c5', target: 'p22', weight: 2, notes: 'Приоритизация уменьшает поток внезапных задач.' }, | |
| // p22 «22. Постоянные отвлечения» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — люди знают, что делать без постоянных уточнений | |
| { source: 'c11', target: 'p22', weight: 1, notes: 'Даёт ясный план работы без постоянных уточнений.' }, | |
| // p23 «23. Организационный долг» ← c14 «Определяем структуру команд» — главный рычаг: ликвидировать временные сочетания ролей | |
| { source: 'c14', target: 'p23', weight: 3, notes: 'Ликвидирует «временные» совмещения ролей.' }, | |
| // p23 «23. Организационный долг» ← c15 «Формируем культуру, ценности и архитектурные принципы» — не даём временным решениям становиться нормой. | |
| { source: 'c15', target: 'p23', weight: 2, notes: 'Ценности и принципы снижают орг-долг.' }, | |
| // p23 «23. Организационный долг» ← c8 «Строим стратегию найма» — добираем людей под устойчивую структуру | |
| { source: 'c8', target: 'p23', weight: 2, notes: 'Добирает людей под устойчивую структуру.' }, | |
| // p23 «23. Организационный долг» ← c25 «Определяем общую культуру и ценности» — поощряем починку системных багов, а не только тушение пожаров. | |
| { source: 'c25', target: 'p23', weight: 2, notes: 'Культура поощряет чинить системные баги.' }, | |
| // p23 «23. Организационный долг» ← c19 «Стандартизируем инженерные практики и подходы» — процессы становятся поддерживаемыми | |
| { source: 'c19', target: 'p23', weight: 1, notes: 'Описывает процессы так, чтобы их можно было поддерживать.' }, | |
| // p23 «23. Организационный долг» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — кто чинит процессы | |
| { source: 'c22', target: 'p23', weight: 1, notes: 'Старшие грейды улучшают процессы.' }, | |
| // p23 «23. Организационный долг» ← c28 «Работа с ключевыми партнёрами» — перестраиваем внешние договорённости, вместо вечных костылей. | |
| { source: 'c28', target: 'p23', weight: 1, notes: 'Работа с партнёрами убирает внешние орг-костыли.' }, | |
| // p23 «23. Организационный долг» ← c29 «Прохождение внешних аудитов» — аудит подсвечивает и заставляет гасить орг-долг. | |
| { source: 'c29', target: 'p23', weight: 1, notes: 'Аудиты вскрывают накопленный орг-долг.' }, | |
| // p24 «24. Технический долг» ← c5 «Приоритизируем продуктовый и технический бэклог» — главный рычаг: техдолг в общем бэклоге | |
| { source: 'c5', target: 'p24', weight: 3, notes: 'Выводит техдолг в общий бэклог.' }, | |
| // p24 «24. Технический долг» ← c15 «Формируем культуру, ценности и архитектурные принципы» — архитектурные принципы снижают накопление долга. | |
| { source: 'c15', target: 'p24', weight: 3, notes: 'Архитектурные принципы уменьшают техдолг.' }, | |
| // p24 «24. Технический долг» ← c19 «Стандартизируем инженерные практики и подходы» — тесты, CI/CD, рефакторинг как норма | |
| { source: 'c19', target: 'p24', weight: 2, notes: 'Стандарты требуют тестов, рефакторинга и CI/CD.' }, | |
| // p24 «24. Технический долг» ← c7 «Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»» — не всегда жертвуем качеством ради скорости | |
| { source: 'c7', target: 'p24', weight: 2, notes: 'Не позволяет постоянно жертвовать качеством ради скорости.' }, | |
| // p24 «24. Технический долг» ← c29 «Прохождение внешних аудитов» — внешние техаудиты не дают забыть о долге. | |
| { source: 'c29', target: 'p24', weight: 1, notes: 'Внешние техаудиты подсвечивают и сокращают техдолг.' }, | |
| // p24 «24. Технический долг» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — сравнение цены долга и рефакторинга | |
| { source: 'c3', target: 'p24', weight: 1, notes: 'Сравнивает цену долга с ценой его погашения.' }, | |
| // p24 «24. Технический долг» ← c6 «Договариваемся про бюджеты» — выделяем деньги на качество и инфраструктуру. | |
| { source: 'c6', target: 'p24', weight: 1, notes: 'Закладываем бюджеты на качество и инфраструктуру.' }, | |
| // p25 «25. Хаос в процессах» ← c19 «Стандартизируем инженерные практики и подходы» — главный набор базовых процессов | |
| { source: 'c19', target: 'p25', weight: 3, notes: 'Задаёт базовый набор процессов и практик.' }, | |
| // p25 «25. Хаос в процессах» ← c14 «Определяем структуру команд» — понятно, кто где участвует в процессе | |
| { source: 'c14', target: 'p25', weight: 2, notes: 'Определяет, кто за какой кусок процесса отвечает.' }, | |
| // p25 «25. Хаос в процессах» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — процессы строятся вокруг потока ценности | |
| { source: 'c11', target: 'p25', weight: 2, notes: 'Строит процессы вокруг потоков ценности, а не хаоса.' }, | |
| // p25 «25. Хаос в процессах» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — измеряется поток, а не случайные действия | |
| { source: 'c12', target: 'p25', weight: 1, notes: 'Помогает измерять и улучшать поток, а не случайные метрики.' }, | |
| // p26 «26. Борьба с конфликтами» ← c25 «Определяем общую культуру и ценности» — главный рычаг: конфликт как сигнал, а не зло | |
| { source: 'c25', target: 'p26', weight: 3, notes: 'Закрепляет конфликты как нормальный сигнал.' }, | |
| // p26 «26. Борьба с конфликтами» ← c20 «Отслеживаем сигналы от тех, кто ежедневно создаёт ценность» — используем конфликты как сигналы о проблемах. | |
| { source: 'c20', target: 'p26', weight: 2, notes: 'Сигналы «с поля» помогают не терять важные конфликты.' }, | |
| // p26 «26. Борьба с конфликтами» ← c15 «Формируем культуру, ценности и архитектурные принципы» — правила, как мы спорим | |
| { source: 'c15', target: 'p26', weight: 2, notes: 'Определяет правила споров и принятия решений.' }, | |
| // p26 «26. Борьба с конфликтами» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — конфликты поднимаются раньше, чем взрываются | |
| { source: 'c21', target: 'p26', weight: 1, notes: 'Даёт канал, где можно поднять проблему до конфликта.' }, | |
| // p27 «27. Фасилитация проблем» ← c25 «Определяем общую культуру и ценности» — главный фокус: лечить причины, а не фасилитировать симптомы | |
| { source: 'c25', target: 'p27', weight: 3, notes: 'Смещает фокус с фасилитации на решение причины.' }, | |
| // p27 «27. Фасилитация проблем» ← c15 «Формируем культуру, ценности и архитектурные принципы» — договариваемся о том, что нормально, а что нет | |
| { source: 'c15', target: 'p27', weight: 2, notes: 'Помогает договориться о том, что считаем нормой.' }, | |
| // p27 «27. Фасилитация проблем» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — системно подсвечивает накопившиеся боли | |
| { source: 'c21', target: 'p27', weight: 2, notes: 'Регулярно поднимает накопившиеся боли.' }, | |
| // p27 «27. Фасилитация проблем» ← c19 «Стандартизируем инженерные практики и подходы» — закрепляет решения в новых практиках | |
| { source: 'c19', target: 'p27', weight: 2, notes: 'Фиксирует изменения в устойчивых практиках.' }, | |
| // p27 «27. Фасилитация проблем» ← c14 «Определяем структуру команд» — меняем роли и структуру, если проблема в них | |
| { source: 'c14', target: 'p27', weight: 1, notes: 'Поддерживает изменения корректировкой ролей и структуры.' }, | |
| // p27 «27. Фасилитация проблем» ← c1 «Синхронизируем видение рынка и стратегии» — обсуждаем проблемы на уровне системы, а не симптомов. | |
| { source: 'c1', target: 'p27', weight: 1, notes: 'Стратегический контекст помогает обсуждать проблемы на уровне системы.' }, | |
| // p28 «28. Агенты изменений не видят всей картины» ← c1 «Синхронизируем видение рынка и стратегии» — делимся с ними общей картой рынка | |
| { source: 'c1', target: 'p28', weight: 3, notes: 'Делится с агентами общей картой рынка.' }, | |
| // p28 «28. Агенты изменений не видят всей картины» ← c2 «Встраиваем технологическое видение в стратегию компании» — дают понимание техкурса | |
| { source: 'c2', target: 'p28', weight: 2, notes: 'Объясняет, куда движется тех-курс.' }, | |
| // p28 «28. Агенты изменений не видят всей картины» ← c4 «Синхронизируем roadmap, цели и задачи» — их инициативы привязаны к roadmap и целям | |
| { source: 'c4', target: 'p28', weight: 2, notes: 'Привязывает их инициативы к roadmap и целям.' }, | |
| // p28 «28. Агенты изменений не видят всей картины» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — дают прозрачную систему целей | |
| { source: 'c12', target: 'p28', weight: 2, notes: 'Даёт прозрачные цели и ключевые результаты.' }, | |
| // p28 «28. Агенты изменений не видят всей картины» ← c20 «Отслеживаем сигналы от тех, кто ежедневно создаёт ценность» — замыкает контур «сигналы → стратегия» | |
| { source: 'c20', target: 'p28', weight: 1, notes: 'Замыкает обратную связь от людей к стратегии.' }, | |
| // p29 «29. Простои и панические релизы» ← c7 «Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»» — главный рычаг: нельзя всегда «быстро» | |
| { source: 'c7', target: 'p29', weight: 3, notes: 'Определяет, где нельзя экономить на надёжности.' }, | |
| // p29 «29. Простои и панические релизы» ← c19 «Стандартизируем инженерные практики и подходы» — тесты, rollback, мониторинг | |
| { source: 'c19', target: 'p29', weight: 2, notes: 'Внедряет тестирование, мониторинг и rollback-стратегии.' }, | |
| // p29 «29. Простои и панические релизы» ← c5 «Приоритизируем продуктовый и технический бэклог» — reliability-задачи в бэклоге | |
| { source: 'c5', target: 'p29', weight: 2, notes: 'Заводит задачи по надёжности в план.' }, | |
| // p29 «29. Простои и панические релизы» ← c27 «Поддерживаем сложные сделки и коммитменты» — делаем обещания выполнимыми без паники. | |
| { source: 'c27', target: 'p29', weight: 1, notes: 'Реалистичные коммитменты уменьшают выкаты «в последний момент».' }, | |
| // p29 «29. Простои и панические релизы» ← c6 «Договариваемся про бюджеты» — бюджет на SRE/инфру | |
| { source: 'c6', target: 'p29', weight: 1, notes: 'Выделяет бюджет на SRE и инфраструктуру.' }, | |
| // p29 «29. Простои и панические релизы» ← c24 «Выстраиваем канал получения обратной связи с «передовой» от клиентов» — быстро понимаем реальное влияние инцидентов. | |
| { source: 'c24', target: 'p29', weight: 1, notes: 'Канал от клиентов помогает быстро ловить и чинить сбои.' }, | |
| // p29 «29. Простои и панические релизы» ← c29 «Прохождение внешних аудитов» — дисциплинируем практики релизов и инцидентов. | |
| { source: 'c29', target: 'p29', weight: 1, notes: 'Процессы под аудиты дисциплинируют релизы и инциденты.' }, | |
| // p30 «30. Отсутствие резервов» ← c6 «Договариваемся про бюджеты» — главный рычаг: финансовые резервы и буферы | |
| { source: 'c6', target: 'p30', weight: 3, notes: 'Закладывает финансовые резервы и буферы.' }, | |
| // p30 «30. Отсутствие резервов» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — показывает выгоду резервов | |
| { source: 'c3', target: 'p30', weight: 2, notes: 'Показывает выгоду резервов против простоев.' }, | |
| // p30 «30. Отсутствие резервов» ← c8 «Строим стратегию найма» — кадровые резервы | |
| { source: 'c8', target: 'p30', weight: 2, notes: 'Планирует небольшой запас по людям.' }, | |
| // p30 «30. Отсутствие резервов» ← c7 «Расставляем веса и ищем компромиссы между «быстро / дорого / надёжно»» — ставим надёжность и устойчивость как ценность. | |
| { source: 'c7', target: 'p30', weight: 2, notes: 'Компромисс «стоимость/надёжность» включает резервирование.' }, | |
| // p30 «30. Отсутствие резервов» ← c9 «Балансируем «скорость найма / стоимость поиска / риски культурных расхождений»» — сглаживание найма/размеров команды | |
| { source: 'c9', target: 'p30', weight: 2, notes: 'Не разгоняет найм до неконтролируемых качелей.' }, | |
| // p30 «30. Отсутствие резервов» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — лимит загрузки | |
| { source: 'c10', target: 'p30', weight: 1, notes: 'Следит, чтобы загрузка не была 100%+.' }, | |
| // p30 «30. Отсутствие резервов» ← c27 «Поддерживаем сложные сделки и коммитменты» — не берём обязательств, убивающих все резервы. | |
| { source: 'c27', target: 'p30', weight: 1, notes: 'Сложные сделки согласуются с учётом резервов и рисков.' }, | |
| // p31 «31. Митинги по утрам, работа — вечером» ← c10 «Проверяем, соответствует ли «рабочая среда» ожиданиям» — главный рычаг: рабочие окна и тихие часы | |
| { source: 'c10', target: 'p31', weight: 3, notes: 'Фиксирует рабочие окна и тихие часы.' }, | |
| // p31 «31. Митинги по утрам, работа — вечером» ← c4 «Синхронизируем roadmap, цели и задачи» — решения в планировании, а не в endless-митингах | |
| { source: 'c4', target: 'p31', weight: 2, notes: 'Переносит часть решений из митингов в планирование.' }, | |
| // p31 «31. Митинги по утрам, работа — вечером» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — статус из систем, а не из созвонов | |
| { source: 'c12', target: 'p31', weight: 1, notes: 'Делает статус видимым в системах, а не в созвонах.' }, | |
| // p32 «32. Отсутствие онбординга (особенно для тимлидов)» ← c8 «Строим стратегию найма» — главный рычаг: онбординг как часть стратегии найма | |
| { source: 'c8', target: 'p32', weight: 3, notes: 'Закладывает онбординг в стратегию найма.' }, | |
| // p32 «32. Отсутствие онбординга (особенно для тимлидов)» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — ожидания по роли известны заранее | |
| { source: 'c22', target: 'p32', weight: 2, notes: 'Описывает ожидания от ролей ещё на входе.' }, | |
| // p32 «32. Отсутствие онбординга (особенно для тимлидов)» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — корректируем онбординг по фидбеку | |
| { source: 'c21', target: 'p32', weight: 2, notes: 'Собирает фидбек новых людей по входу в роль.' }, | |
| // p32 «32. Отсутствие онбординга (особенно для тимлидов)» ← c14 «Определяем структуру команд» — новый человек понимает своё место | |
| { source: 'c14', target: 'p32', weight: 2, notes: 'Показывает, где именно новый человек в системе.' }, | |
| // p33 «33. Раздавать задачи сверху» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — главный рычаг: учитывать мотивацию и сильные стороны | |
| { source: 'c21', target: 'p33', weight: 2, notes: 'Помогает учитывать мотивацию и сильные стороны.' }, | |
| // p33 «33. Раздавать задачи сверху» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — смещаем фокус с задач на результаты. | |
| { source: 'c12', target: 'p33', weight: 2, notes: 'OKR смещают фокус с задач на результаты.' }, | |
| // p33 «33. Раздавать задачи сверху» ← c20 «Отслеживаем сигналы от тех, кто ежедневно создаёт ценность» — кто реально тянет какую работу | |
| { source: 'c20', target: 'p33', weight: 2, notes: 'Подсвечивает, кто реально тянет какую работу.' }, | |
| // p33 «33. Раздавать задачи сверху» ← c11 «Выделяем и декомпозируем ключевые эпики и инициативы» — даём командам эпики, а не микроменеджмент | |
| { source: 'c11', target: 'p33', weight: 2, notes: 'Дает командам крупные эпики вместо мелких поручений.' }, | |
| // p33 «33. Раздавать задачи сверху» ← c25 «Определяем общую культуру и ценности» — ценность ownership vs «делай как скажут» | |
| { source: 'c25', target: 'p33', weight: 1, notes: 'Поддерживает культуру ownership вместо «делай как сказали».' }, | |
| // p34 «34. Использовать метрики, ревью и прочие практики для критики» ← c12 «Согласовываем общие OKR / KPI / дашборды / ключевые метрики» — главный рычаг: метрики как инструмент улучшения | |
| { source: 'c12', target: 'p34', weight: 3, notes: 'Определяет метрики как инструмент улучшения, а не наказания.' }, | |
| // p34 «34. Использовать метрики, ревью и прочие практики для критики» ← c22 «Разрабатываем грейды, систему оценки и ценностей» — делаем оценку инструментом развития. | |
| { source: 'c22', target: 'p34', weight: 3, notes: 'Система оценки ориентирована на развитие, а не наказания.' }, | |
| // p34 «34. Использовать метрики, ревью и прочие практики для критики» ← c25 «Определяем общую культуру и ценности» — уважение к ошибкам и росту | |
| { source: 'c25', target: 'p34', weight: 2, notes: 'Закрепляет уважительное отношение к ошибкам и росту.' }, | |
| // p34 «34. Использовать метрики, ревью и прочие практики для критики» ← c15 «Формируем культуру, ценности и архитектурные принципы» — формируем ценности, как работать с ошибками и ростом. | |
| { source: 'c15', target: 'p34', weight: 1, notes: 'Ценности задают стиль ревью и работы с ошибками.' }, | |
| // p34 «34. Использовать метрики, ревью и прочие практики для критики» ← c21 «Собираем обратную связь, поддерживаем и анализируем мотивацию» — ревью как диалог | |
| { source: 'c21', target: 'p34', weight: 1, notes: 'Строит ревью как диалог, а не разнос.' }, | |
| // p35 «35. Неправильный выбор стека технологий и подходов» ← c2 «Встраиваем технологическое видение в стратегию компании» — главный рычаг выбора стека | |
| { source: 'c2', target: 'p35', weight: 3, notes: 'Делает выбор стека частью техстратегии.' }, | |
| // p35 «35. Неправильный выбор стека технологий и подходов» ← c1 «Синхронизируем видение рынка и стратегии» — стек под рынок и продукт | |
| { source: 'c1', target: 'p35', weight: 2, notes: 'Фильтрует технологии через контекст рынка.' }, | |
| // p35 «35. Неправильный выбор стека технологий и подходов» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — TCO, окупаемость | |
| { source: 'c3', target: 'p35', weight: 2, notes: 'Считает TCO и окупаемость стека.' }, | |
| // p35 «35. Неправильный выбор стека технологий и подходов» ← c15 «Формируем культуру, ценности и архитектурные принципы» — принципы выбора технологий | |
| { source: 'c15', target: 'p35', weight: 1, notes: 'Фиксирует принципы выбора технологий в культуре.' }, | |
| // p35 «35. Неправильный выбор стека технологий и подходов» ← c26 «Формируем внешнее позиционирование технологий» — вынуждает выбирать стек, который можно убедительно защищать. | |
| { source: 'c26', target: 'p35', weight: 1, notes: 'Внешнее позиционирование требует осознанного выбора технологий.' }, | |
| // p36 «36. Массовые сокращения» ← c1 «Синхронизируем видение рынка и стратегии» — главный рычаг: стратегия вместо «резать людей» | |
| { source: 'c1', target: 'p36', weight: 3, notes: 'Помогает не доводить стратегию до «режем людей».' }, | |
| // p36 «36. Массовые сокращения» ← c2 «Встраиваем технологическое видение в стратегию компании» — не раздувать техпортфель | |
| { source: 'c2', target: 'p36', weight: 2, notes: 'Не раздувает техпортфель поверх реальных целей.' }, | |
| // p36 «36. Массовые сокращения» ← c3 «Прикидываем unit-экономику, чтобы тех-инвестиции соответствовали ожиданиям» — управлять расходами заранее | |
| { source: 'c3', target: 'p36', weight: 2, notes: 'Управляет расходами до кризиса сокращений.' }, | |
| // p36 «36. Массовые сокращения» ← c8 «Строим стратегию найма» — нанимать под реальные долгосрочные задачи | |
| { source: 'c8', target: 'p36', weight: 2, notes: 'Нанимает под реальные долгосрочные задачи.' }, | |
| // p36 «36. Массовые сокращения» ← c6 «Договариваемся про бюджеты» — управляем расходами заранее, а не через массовые сокращения. | |
| { source: 'c6', target: 'p36', weight: 2, notes: 'Планирование бюджетов уменьшает потребность в «рубильнике».' }, | |
| // p36 «36. Массовые сокращения» ← c9 «Балансируем «скорость найма / стоимость поиска / риски культурных расхождений»» — не уходить в оверхайринг | |
| { source: 'c9', target: 'p36', weight: 2, notes: 'Не гонит агрессивный найм ценой культуры.' }, | |
| // p36 «36. Массовые сокращения» ← c25 «Определяем общую культуру и ценности» — культура задаёт ограничения на практики «оптимизации» людей. | |
| { source: 'c25', target: 'p36', weight: 2, notes: 'Культура и ценности ограничивают практику массовых сокращений.' }, | |
| // p36 «36. Массовые сокращения» ← c23 «Публичные выступления, технический бренд, репутация компании» — как объяснить изменения и сохранить доверие | |
| { source: 'c23', target: 'p36', weight: 1, notes: 'Объясняет изменения так, чтобы сохранить доверие.' }, | |
| ]; | |
| // --- D3-часть ---------------------------------------------------- | |
| const svg = d3.select("svg"); | |
| const width = +svg.attr("width"); | |
| const height = +svg.attr("height"); | |
| const nodes = [ | |
| ...checklistItems.map(d => ({ ...d, type: 'checklist' })), | |
| ...pains.map(d => ({ ...d, type: 'pain' })) | |
| ]; | |
| // режим: 'force' или 'bipartite' | |
| let layoutMode = 'force'; | |
| const simulation = d3.forceSimulation(nodes); | |
| const link = svg.append("g") | |
| .attr("class", "links") | |
| .selectAll("line") | |
| .data(links) | |
| .enter().append("line") | |
| .attr("class", "link") | |
| .attr("stroke-width", d => 0.5 + d.weight); | |
| const node = svg.append("g") | |
| .attr("class", "nodes") | |
| .selectAll("g") | |
| .data(nodes) | |
| .enter().append("g") | |
| .attr("class", d => "node " + d.type) | |
| .call(d3.drag() | |
| .on("start", dragstarted) | |
| .on("drag", dragged) | |
| .on("end", dragended) | |
| ) | |
| .on("click", nodeClicked); | |
| node.append("circle").attr("r", 10); | |
| node.append("text") | |
| .attr("class", "node-label") | |
| .attr("x", 12) | |
| .attr("y", 4) | |
| .text(d => d.label); | |
| node.append("title") | |
| .text(d => { | |
| if (d.notes && Array.isArray(d.notes)) { | |
| return d.label + '\n- ' + d.notes.join('\n- '); | |
| } | |
| return d.label; | |
| }); | |
| // --- силы -------------------------------------------------------- | |
| function applyForceLayout() { | |
| simulation | |
| .force("link", d3.forceLink(links).id(d => d.id).distance(80).strength(0.7)) | |
| .force("charge", d3.forceManyBody().strength(-250)) | |
| .force("center", d3.forceCenter(width / 2, height / 2)) | |
| .force("collision", d3.forceCollide().radius(40)) | |
| .force("x", null) | |
| .force("y", null); | |
| simulation.alpha(1).restart(); | |
| } | |
| function applyBipartiteLayout() { | |
| focusedId = null; | |
| selectedBipartiteId = null; | |
| node.classed("selected", false); | |
| link.classed("highlight", false).classed("dimmed", false); | |
| clearNotes(); | |
| const marginTop = 40; | |
| const marginBottom = 40; | |
| const colLeftX = width * 0.20; | |
| const colRightX = width * 0.60; | |
| const checklistNodes = nodes.filter(n => n.type === 'checklist'); | |
| const painNodes = nodes.filter(n => n.type === 'pain'); | |
| const availableHeight = height - marginTop - marginBottom; | |
| const minStep = 28; // <-- вот тут задаёшь минимальное расстояние, поиграйся значением | |
| // левая колонка | |
| let stepLeft; | |
| if (checklistNodes.length > 1) { | |
| const baseStep = availableHeight / (checklistNodes.length - 1); | |
| stepLeft = Math.max(baseStep, minStep); | |
| } else { | |
| stepLeft = minStep; | |
| } | |
| checklistNodes.forEach((n, i) => { | |
| n.fx = colLeftX; | |
| n.fy = marginTop + stepLeft * i; | |
| }); | |
| // правая колонка | |
| let stepRight; | |
| if (painNodes.length > 1) { | |
| const baseStep = availableHeight / (painNodes.length - 1); | |
| stepRight = Math.max(baseStep, minStep); | |
| } else { | |
| stepRight = minStep; | |
| } | |
| painNodes.forEach((n, i) => { | |
| n.fx = colRightX; | |
| n.fy = marginTop + stepRight * i; | |
| }); | |
| simulation | |
| .force("link", d3.forceLink(links).id(d => d.id).distance(80).strength(0.8)) | |
| .force("charge", d3.forceManyBody().strength(0)) | |
| .force("center", null) | |
| .force("collision", null) | |
| .force("x", null) | |
| .force("y", null); | |
| simulation.alpha(0.5).restart(); | |
| } | |
| // стартуем в силовом режиме | |
| applyForceLayout(); | |
| simulation.on("tick", () => { | |
| link | |
| .attr("x1", d => d.source.x) | |
| .attr("y1", d => d.source.y) | |
| .attr("x2", d => d.target.x) | |
| .attr("y2", d => d.target.y); | |
| node.attr("transform", d => `translate(${d.x},${d.y})`); | |
| }); | |
| // --- adjacency + BFS (как у тебя) -------------------------------- | |
| function buildAdjacency(links) { | |
| const adj = {}; | |
| links.forEach(l => { | |
| const s = typeof l.source === 'object' ? l.source.id : l.source; | |
| const t = typeof l.target === 'object' ? l.target.id : l.target; | |
| if (!adj[s]) adj[s] = []; | |
| if (!adj[t]) adj[t] = []; | |
| adj[s].push(t); | |
| adj[t].push(s); | |
| }); | |
| return adj; | |
| } | |
| const adjacency = buildAdjacency(links); | |
| function bfs(startId) { | |
| const dist = {}; | |
| nodes.forEach(n => dist[n.id] = Infinity); | |
| dist[startId] = 0; | |
| const queue = [startId]; | |
| while (queue.length > 0) { | |
| const v = queue.shift(); | |
| const dv = dist[v]; | |
| const neighbors = adjacency[v] || []; | |
| neighbors.forEach(w => { | |
| if (dist[w] === Infinity) { | |
| dist[w] = dv + 1; | |
| queue.push(w); | |
| } | |
| }); | |
| } | |
| return dist; | |
| } | |
| // --- Фокус для силового режима ----------------------------------- | |
| // для силового режима — ID узла в фокусе | |
| let focusedId = null; | |
| // для двудольного режима — выбранный узел | |
| let selectedBipartiteId = null; | |
| // убрать все комментарии notes с узлов | |
| function clearNotes() { | |
| node.selectAll(".note-text").remove(); | |
| } | |
| // простая разбивка текста на строки по длине | |
| function wrapTextLines(text, maxChars) { | |
| const words = text.split(/\s+/); | |
| const lines = []; | |
| let line = ''; | |
| words.forEach(word => { | |
| const testLine = line ? line + ' ' + word : word; | |
| if (testLine.length <= maxChars) { | |
| line = testLine; | |
| } else { | |
| if (line) lines.push(line); | |
| line = word; | |
| } | |
| }); | |
| if (line) lines.push(line); | |
| return lines; | |
| } | |
| // показать notes для соседей выбранного узла (в двудольном режиме) | |
| function showNotesForNode(clickedNode) { | |
| clearNotes(); | |
| const clickedId = clickedNode.id; | |
| 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 !== clickedId && tId !== clickedId) return; | |
| const neighborId = sId === clickedId ? tId : sId; | |
| const noteText = l.notes; | |
| if (!noteText) return; | |
| // находим группу соответствующего узла | |
| const neighborSelection = node.filter(nd => nd.id === neighborId); | |
| neighborSelection.each(function(nd) { | |
| const g = d3.select(this); | |
| const baseX = 12; | |
| const baseY = 16; // ниже основной подписи (label y=4) | |
| const lines = [noteText] // wrapTextLines(noteText, 42); // ~42 символа в строке | |
| const textEl = g.append("text") | |
| .attr("class", "note-text") | |
| .attr("x", baseX) | |
| .attr("y", baseY); | |
| lines.forEach((lineStr, idx) => { | |
| textEl.append("tspan") | |
| .attr("x", baseX) | |
| .attr("dy", idx === 0 ? 0 : 10) | |
| .text(lineStr); | |
| }); | |
| }); | |
| }); | |
| } | |
| function nodeClicked(event, d) { | |
| event.stopPropagation(); | |
| if (layoutMode === 'force') { | |
| // при переходе из двудольного режима убираем подсветки/комментарии | |
| clearNotes(); | |
| link.classed("highlight", false).classed("dimmed", false); | |
| selectedBipartiteId = null; | |
| // старая логика фокуса | |
| if (focusedId === d.id) { | |
| focusedId = null; | |
| clearFocus(); | |
| return; | |
| } | |
| focusedId = d.id; | |
| applyFocus(d); | |
| } else { | |
| // двудольный режим: подсветка связей + текстовые комментарии на соседях | |
| if (selectedBipartiteId === d.id) { | |
| // повторный клик — сброс | |
| selectedBipartiteId = null; | |
| node.classed("selected", false); | |
| link.classed("highlight", false).classed("dimmed", false); | |
| clearNotes(); | |
| return; | |
| } | |
| selectedBipartiteId = d.id; | |
| node.classed("selected", n => n.id === d.id); | |
| link | |
| .classed("highlight", 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 === d.id || tId === d.id; | |
| }) | |
| .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 !== d.id && tId !== d.id; | |
| }); | |
| showNotesForNode(d); | |
| } | |
| } | |
| function clearFocus() { | |
| nodes.forEach(n => { | |
| n.fx = null; | |
| n.fy = null; | |
| }); | |
| node.classed("selected", false); | |
| simulation.alpha(1).restart(); | |
| } | |
| function applyFocus(centerNode) { | |
| const distances = bfs(centerNode.id); | |
| const levels = new Map(); | |
| let maxFiniteDist = 0; | |
| nodes.forEach(n => { | |
| const d = distances[n.id]; | |
| if (Number.isFinite(d)) { | |
| if (!levels.has(d)) levels.set(d, []); | |
| levels.get(d).push(n); | |
| if (d > maxFiniteDist) maxFiniteDist = d; | |
| } | |
| }); | |
| const infNodes = nodes.filter(n => !Number.isFinite(distances[n.id])); | |
| if (infNodes.length > 0) { | |
| const infLevel = maxFiniteDist + 1; | |
| levels.set(infLevel, (levels.get(infLevel) || []).concat(infNodes)); | |
| } | |
| const centerX = width / 2; | |
| const centerY = height / 2; | |
| const baseRadius = 0; | |
| const stepRadius = 90; | |
| const maxRadius = Math.min(width, height) / 2 - 40; | |
| const rotationStep = Math.PI / 24; | |
| levels.forEach((nodesOnLevel, dist) => { | |
| if (dist === 0) { | |
| nodesOnLevel.forEach(n => { | |
| n.fx = centerX; | |
| n.fy = centerY; | |
| }); | |
| return; | |
| } | |
| const radius = Math.min(baseRadius + dist * stepRadius, maxRadius); | |
| const count = nodesOnLevel.length; | |
| const levelRotation = rotationStep * dist; | |
| nodesOnLevel.forEach((n, i) => { | |
| const angle = (2 * Math.PI * i) / count + levelRotation; | |
| const x = centerX + radius * Math.cos(angle); | |
| const y = centerY + radius * Math.sin(angle); | |
| n.fx = x; | |
| n.fy = y; | |
| }); | |
| }); | |
| node.classed("selected", n => n.id === centerNode.id); | |
| simulation.alpha(0.7).restart(); | |
| } | |
| // --- Drag -------------------------------------------------------- | |
| function dragstarted(event, d) { | |
| if (!event.active) simulation.alphaTarget(0.3).restart(); | |
| d.fx = d.x; | |
| d.fy = d.y; | |
| } | |
| function dragged(event, d) { | |
| d.fx = event.x; | |
| d.fy = event.y; | |
| } | |
| function dragended(event, d) { | |
| if (!event.active) simulation.alphaTarget(0); | |
| if (!focusedId && layoutMode === 'force') { | |
| // в силовом режиме, без фокуса — отпускаем | |
| d.fx = null; | |
| d.fy = null; | |
| } | |
| // в двудольном режиме оставляем fx/fy, чтобы можно было «расправить» колонки руками | |
| } | |
| // --- Переключатель режимов -------------------------------------- | |
| const modeForceBtn = document.getElementById('mode-force'); | |
| const modeBipBtn = document.getElementById('mode-bipartite'); | |
| modeForceBtn.addEventListener('click', () => { | |
| if (layoutMode === 'force') return; | |
| layoutMode = 'force'; | |
| modeForceBtn.classList.add('active'); | |
| modeBipBtn.classList.remove('active'); | |
| selectedBipartiteId = null; | |
| link.classed("highlight", false).classed("dimmed", false); | |
| clearNotes(); | |
| clearFocus(); | |
| applyForceLayout(); | |
| }); | |
| modeBipBtn.addEventListener('click', () => { | |
| if (layoutMode === 'bipartite') return; | |
| layoutMode = 'bipartite'; | |
| modeBipBtn.classList.add('active'); | |
| modeForceBtn.classList.remove('active'); | |
| focusedId = null; | |
| link.classed("highlight", false).classed("dimmed", false); | |
| node.classed("selected", false); | |
| clearNotes(); | |
| applyBipartiteLayout(); | |
| }); | |
| modeBipBtn.click(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment