// ════════════════════════════════════════════════════════════════ // SynthesisPage — рабочая сессия по проработке идеи // Открывается из IdeaExpansion → "Открыть синтез-сессию" // Долгая editorial-страница с пронумерованными разделами + правым рейлом // ════════════════════════════════════════════════════════════════ const { useMemo: useMemoSyn, useState: useStateSyn } = React; function SynthesisPage({ idea, onBack }) { const D = window.SDH_DATA; // Deterministic seed from idea number const seed = idea.number; const r = (n) => ((seed * 9301 + n * 49297) % 233280) / 233280; const pick = (arr, n) => arr[Math.floor(r(n) * arr.length)]; // Methodology family info const family = D.FAMILIES.find(f => f.id === idea.family); const methodSteps = METHOD_STEPS[idea.family] || METHOD_STEPS.spe; // Section completeness (deterministic) const sections = [ { id: '01', title: 'Постановка задачи', done: true }, { id: '02', title: 'Методологический протокол', done: true }, { id: '03', title: 'Конкурентный ландшафт', done: true }, { id: '04', title: 'Клиент и работа', done: r(11) > 0.4 }, { id: '05', title: 'Гипотезы для проверки', done: r(12) > 0.55 }, { id: '06', title: 'Риски', done: r(13) > 0.5 }, { id: '07', title: 'Следующее действие', done: r(14) > 0.45 }, ]; const completion = sections.filter(s => s.done).length / sections.length; // Mock named competitors const competitors = useMemoSyn(() => { const subset = D.corpus .filter(s => s.niche === idea.niche) .slice(0, idea.competitors); return subset.map((s, i) => ({ ...s, verdict: i < idea.verdicts.viable ? 'viable' : i < idea.verdicts.viable + idea.verdicts.validate ? 'validate' : 'risky', })); }, [idea.number]); // Notes feed const notes = useMemoSyn(() => { const authors = ['Е. Орлов', 'А. Седов', 'И. Громова', 'М. Карпов', 'Д. Лебедева']; const texts = [ 'Подняли сессию по идее. Семья методологии очевидна — переходим к шагу 02.', 'Из 7 конкурентов 4 закрылись за последние 18 месяцев. Это сигнал к проверке Customer Pain.', 'Закрыли первый раунд интервью с потенциальными покупателями. Готовлю выкладку.', 'Гипотеза о ценовом коридоре подтвердилась. Двигаемся к прототипу.', 'Снизил уровень риска регуляторики после консультации с юридическим.', ]; return Array.from({ length: 4 }).map((_, i) => ({ author: pick(authors, i * 3), date: new Date(Date.now() - (3 + i * 4) * 86400000).toISOString().slice(0, 10), text: texts[(seed + i) % texts.length], })); }, [idea.number]); // Hypothesis list const hypotheses = useMemoSyn(() => [ { id: 'h1', text: 'Целевая аудитория готова платить на 30% выше текущего рыночного предложения.', status: pick(['validated', 'testing', 'pending'], 1) }, { id: 'h2', text: 'Конкуренты решают задачу нелинейно — есть возможность для упрощения.', status: pick(['validated', 'testing', 'pending'], 2) }, { id: 'h3', text: 'Канал привлечения через сообщества разработчиков даст CAC ниже $200.', status: pick(['validated', 'testing', 'pending'], 3) }, { id: 'h4', text: 'Технологический стек реализуется силами команды из 4 человек за 8 недель.', status: pick(['validated', 'testing', 'pending'], 4) }, ], [idea.number]); // Risks const risks = useMemoSyn(() => [ { level: 'high', title: 'Регуляторная неопределённость', detail: 'Сектор подпадает под обновляемые нормы 2026 года.' }, { level: 'medium', title: 'Зависимость от единого поставщика', detail: 'Ключевая компонента доступна у одного вендора.' }, { level: 'medium', title: 'Длинный цикл продажи', detail: 'B2B-цикл от первого контакта до контракта 4–6 месяцев.' }, { level: 'low', title: 'Технологическая зрелость', detail: 'Базовые технологии стабильны, риски минимальны.' }, ], [idea.number]); // Decision state const [verdict, setVerdict] = useStateSyn(null); // null | 'risky' | 'validate' | 'viable' // Owner / due const owners = ['Е. Орлов', 'А. Седов', 'И. Громова']; const owner = pick(owners, 99); const dueDate = new Date(Date.now() + (3 + Math.floor(r(50) * 10)) * 86400000).toISOString().slice(0, 10); return (
{/* HERO */}
{/* breadcrumb */}
идея № {String(idea.number).padStart(2, '0')} синтез-сессия
{/* title row */}
рабочая сессия {idea.focus && ★ в фокусе}

{idea.title}

{idea.familyLabel} {idea.nicheLabel} сессия #{seed}
{/* Progress side card */}
прогресс сессии
{Math.round(completion * 100)}%
{sections.filter(s => s.done).length} / {sections.length} разделов
{/* MAIN BODY: 2 columns */}
{/* LEFT — editorial sections */}
{/* 01 — Постановка */}

Команда исследует возможность создания продукта по направлению{' '} «{idea.title}». На сегодня семантическая близость к корпусу составляет{' '} {idea.similarity.toFixed(2)} , что говорит о{' '} {idea.similarity >= 0.75 ? 'высокой плотности рынка' : 'формирующемся пространстве возможностей'}.

{idea.recommendation}

{/* 02 — Methodology */}
{family.label2 || family.label} {family.full}
    {methodSteps.map((step, i) => (
  1. {String(i + 1).padStart(2, '0')}
    {step.title}
    {step.detail}
  2. ))}
{/* 03 — Competitors */}
{competitors.slice(0, 6).map((c, i) => (
{c.name}
{c.desc}
{c.geo}
))} {competitors.length > 6 && (
ещё {competitors.length - 6} конкурентов
)}
{/* 04 — JTBD */}
{/* 05 — Hypotheses */}
{hypotheses.map((h, i) => (
H{i + 1} {h.text}
))}
{/* 06 — Risks */}
{risks.map((rk, i) => (
риск · {rk.level === 'high' ? 'высокий' : rk.level === 'medium' ? 'средний' : 'низкий'}
{rk.title}
{rk.detail}
))}
{/* 07 — Next action */}
что делаем

Провести 5 углублённых интервью с целевой аудиторией для валидации H1 и H3.

{/* RIGHT RAIL */}
{/* DECISION FOOTER (sticky) */}
решение по идее
{verdict ? выбрано: {verdict === 'viable' ? 'в работу' : verdict === 'validate' ? 'дополнительная валидация' : 'отложить'} : 'выберите вердикт сессии'}
setVerdict('risky')} hue="rose" label="отложить" /> setVerdict('validate')} hue="amber" label="нужна валидация" /> setVerdict('viable')} hue="emerald" label="в работу" />
); } // ── Subcomponents ──────────────────────────────────────────────── function SectionBlock({ num, title, done, children }) { return (
{num}

{title}

{children}
); } function StepStatus({ status }) { const map = { done: { hue: 'emerald', label: 'готово', icon: '✓' }, active: { hue: 'amber', label: 'в работе', icon: '◐' }, pending: { hue: 'info', label: 'ожидает', icon: '◯' }, }; const s = map[status] || map.pending; return ( {s.icon}{s.label} ); } function VerdictBadge({ verdict }) { const map = { risky: { hue: 'rose', label: 'рискованно' }, validate: { hue: 'amber', label: 'валидация' }, viable: { hue: 'emerald', label: 'жизнеспособно' }, }; const v = map[verdict] || map.risky; return {v.label}; } function HypothesisStatus({ status }) { const map = { validated: { hue: 'emerald', label: 'подтверждена' }, testing: { hue: 'amber', label: 'тестируется' }, pending: { hue: 'info', label: 'не начата' }, }; const s = map[status] || map.pending; return ( {s.label} ); } function JTBDCard({ label, content, hue }) { return (
{label}

{content}

); } function ActionField({ label, value, mono }) { return (
{label}
{value}
); } function SidePanel({ title, children }) { return (
{title}
{children}
); } function SideRow({ label, value, mono }) { return (
{label} {value}
); } function VerdictButton({ active, onClick, hue, label }) { return ( ); } // ── Methodology step library ───────────────────────────────────── const METHOD_STEPS = { spe: [ { title: 'Артикуляция симбиоза', detail: 'Описать взаимовыгодную пару продукт–рынок: какую двустороннюю ценность создаём.' }, { title: 'Карта зависимостей', detail: 'Зафиксировать критические зависимости продукта от партнёрских ресурсов.' }, { title: 'Поиск негативного цикла', detail: 'Найти, где симбиоз может выродиться в паразитизм при росте.' }, { title: 'Прототип ценностного потока', detail: 'Собрать минимальный поток обмена ценностью между сторонами.' }, { title: 'Метрика стабильности', detail: 'Определить наблюдаемый показатель здоровья симбиоза.' }, ], cape: [ { title: 'Карта способностей', detail: 'Описать целевые способности (capabilities) клиента, которые расширяет продукт.' }, { title: 'Разрыв состояний', detail: 'Замерить дельту между текущим и целевым состоянием способности.' }, { title: 'Каскад приёма', detail: 'Расписать, как новая способность интегрируется в существующие практики.' }, { title: 'Проба на сопротивление', detail: 'Найти точки психологического и организационного сопротивления.' }, { title: 'Шкалирование', detail: 'Определить условия передачи способности внутри организации.' }, ], inot: [ { title: 'Распознавание узла', detail: 'Описать узел сети: что в нём накапливается и что течёт сквозь.' }, { title: 'Топология связи', detail: 'Зафиксировать тип связей между узлами: иерархия, граф, mesh.' }, { title: 'Интеллект на ребре', detail: 'Определить, какие решения принимаются локально, а какие централизованно.' }, { title: 'Протокол согласия', detail: 'Описать механизм достижения согласия между узлами в условиях задержки.' }, { title: 'Деградация и устойчивость', detail: 'Прописать поведение сети при отказе подмножества узлов.' }, ], rosi: [ { title: 'Снимок состояния', detail: 'Собрать ландшафт всех сигналов о направлении на момент Т.' }, { title: 'Векторы интерпретации', detail: 'Выделить 3–5 интерпретаций ситуации, противоречащих друг другу.' }, { title: 'Натяжение между векторами', detail: 'Описать, где интерпретации сходятся и где расходятся.' }, { title: 'Синтетическая гипотеза', detail: 'Сформулировать гипотезу, объясняющую противоречия.' }, { title: 'План фальсификации', detail: 'Определить эксперимент, способный опровергнуть синтез.' }, ], }; window.SynthesisPage = SynthesisPage;