// ════════════════════════════════════════════════════════════════
// 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) => (
{String(i + 1).padStart(2, '0')}
{step.title}
{step.detail}
))}
{/* 03 — Competitors */}
{competitors.slice(0, 6).map((c, i) => (
))}
{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 */}
{/* Session meta */}
{/* Participants */}
{['Е. Орлов', 'А. Седов', 'И. Громова', 'М. Карпов', 'Д. Лебедева'].map((p, i) => (
{p.split(' ')[0].charAt(0)}{p.split(' ')[1].charAt(0)}
{p}
))}
{/* Notes */}
{notes.map((n, i) => (
{n.author}
{n.date}
{n.text}
))}
+ добавить заметку
{/* 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 (
);
}
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 (
);
}
function ActionField({ label, value, mono }) {
return (
);
}
function SidePanel({ title, children }) {
return (
);
}
function SideRow({ label, value, mono }) {
return (
{label}
{value}
);
}
function VerdictButton({ active, onClick, hue, label }) {
return (
{label}
);
}
// ── 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;