Третья статья из серии. Предыдущие:манифест до первой строчки кодаиитерация 0 — скелет и первый вебхук.
Я обещал публиковать честно: и где всё идёт по плану, и где разбиваешься о реальность. Вот статья про и то, и другое.
Три итерации — ровно. Четвёртая — веткаfeat/iter-4удалена, откат наmain. Причина не в технических проблемах. Причина в том, что я наконец честно посмотрел на то, что построил, и понял: модель диалога слабая.
Итерации 1–3: когда спека работает
Каждая итерация — 15–20 минут с агентом, плюс столько же на ревью и документирование.
Итерация 1: Event Core
Контракт событий изvibepp.yamlстал рабочим кодом. Таблицаevents— append-only: триггер в PostgreSQL запрещает UPDATE и DELETE на уровне базы. Идемпотентность поmax_update_id— повторный вебхук от MAX не создаёт дубльanswer.given.
Property-based тесты (Vitest + fast-check) на инварианты INV-02, INV-03, INV-04, INV-07. Не «проверил один случай», а «сгенерируй 1000 случайных последовательностей событий и убедись, что инварианты держатся».
Итерация 2: первый вопрос
Управление жизненным циклом диалога. Открытие сессии (session.opened), первый статичный вопрос (question.asked,question_id = core:first), сохранение ответа (answer.given).inferDialogState— чистая функция над массивом событий, без I/O внутри.
Идемпотентность сессии:session.opened:iter2:${max_user_id}— одна сессия на пользователя. Повторный/startне ломает состояние.
Итерация 3: LLM-диалог
После ответа на первый вопрос — цепочка адаптивных вопросов, сгенерированных Claude на основе всех предыдущих ответов сессии. Anthropic как primary, OpenAI как fallback при ошибке или таймауте.
Порядок строгий по инварианту INV-06:llm.calledпишется в базудоотправки сообщения пользователю. Если сервис упал между вызовом LLM и ответом — факт вызова сохранён, можно восстановить.
Промпт версионируется: полеprompt_versionвllm.calledи файлprompts/dialog-next-question.md.input_hash— SHA-256 итогового контента промпта. Через месяц можно воспроизвести, какой именно промпт породил конкретный вопрос.
Итерация 4: убита
Итерация 4 по спеке — «Первая карта»: Stability Engine, классификатор сигналов,CognitiveIdentityMap,BehavioralPatternMap,card.computed.
Что было сделано технически
Классификатор сигналов.После каждогоanswer.given— отдельная маленькая LLM (OpenAI с коротким таймаутом) анализирует пару «вопрос + ответ» и возвращает массив сигналов:card_type,scale,polarity,weight. При ошибке или таймауте — rule-based fallback. Каждый сигнал пишется какcard_signal.receivedсcausation_id = answer_event_id.
Две карты —CognitiveIdentityMap(шкалыsource/horizon/tempo: как человек мыслит) иBehavioralPatternMap(шкалыobstacle/locus/energy: как действует под давлением).
Stability Engine.Карта назначается детерминированно (card.computed), когда:
- суммарный вес сигналов ≥MIN_AGGREGATE_SIGNAL_WEIGHT_FOR_CARD(0.5)
- по каждой шкале есть хотя бы один сигнал с весом ≥ 0.2
- уверенность доминирующего полюса ≥CARD_CONFIDENCE_THRESHOLD(0.72)
Инвариант INV-03: только детерминированный код решает, готова карта или нет. LLM предлагает сигнал — код принимает решение.
Контекст Layer I в промпте.Вместо полного транскрипта диалога — компактный блок: хвост последних ответов, rollup сигналов по сессии, слабые шкалы, флаг stall. Флаг stall: если за последние 3 ответа суммарный прирост сигналов < 0.15 — модели передаётся инструкция задать более прямой вопрос.
Промпт классификатора вынесен вprompts/signal-classifier-layer1.mdи версионируется отдельно.
Почему ветка удалена
Я запустил диалог руками. И понял: это не работает как продукт.
Модель диалога слабая.Схема «задать вопрос → модель классифицирует сигнал → накопить → назначить карту» работает как технический пайплайн. Но не работает как разговор. Пользователь отвечает, бот задаёт следующий вопрос. Никакого зеркала обратно. Никакого «о, это точно про меня». Просто анкета с вежливым интерфейсом.
Время до ценности — слишком долгое.Карта назначается только когда накоплен достаточный вес сигналов. На это нужно несколько ответов. Пользователь уйдёт раньше, чем увидит хоть что-то значимое о себе.
Нейросеть адаптируется к ответам — этого мало.«Адаптивный вопрос на основе предыдущих ответов» — это ещё не методика. Это механизм. Методика — это другое: как выстроить последовательность, чтобы человек чувствовал движение и открытие, а не допрос.
Профилирование ботом — это центральный пайплайн сервиса. Это то единственное, что делает продукт уникальным: своя методика, своя модель личности. Технический стек можно скопировать. Методику — нет.
Откатился наmain. Удалил ветку.
Что дальше: другая модель диалога
Следующая итерация будет другой по структуре.
Вместо бесконечной цепочки вопросов —короткие тематические опросыпо конкретным граням личности. После каждого опроса пользователь получает маленькое зеркало — не «вы набрали X баллов», а живой инсайт о том, что система увидела.
Параллельно с этими диалогами сигналы формируют несколько слоёв:
-Архетипы и типы мышления— CognitiveIdentityMap, BehavioralPatternMap и дальше по слоям.
-ÆON-профиль— read model поверх event log, который уточняется с каждой сессией.
-Book of Consciousness— таймлайн трансформации пользователя: каждая завершённая сессия добавляет запись. Это и есть будущий платный слой: история себя, паттерны во времени, то, что никакой одноразовый тест не даст.
Разница с тем, что было: пользователь получает что-тосразу после сессии, а не «когда накопится». Ценность появляется раньше. Retention строится на том, что каждый возврат добавляет новую грань, а не просто проходит ещё один круг вопросов.
Перед следующей итерацией — проектирование методики. Не промпта, не алгоритма. Именно методики: как устроен короткий опрос, что пользователь видит на выходе, как это складывается в Book of Consciousness.
Эту работу агент не сделает. Реализовать — сделает. Придумать — моя задача.
Следующая статья — когда методика будет готова и ветка откроется снова.
Репозиторий:github.com/Quantum-Insight-Lab/aeon_map_system
Предыдущие статьи: [манифест] [итерация 0]
Было у вас такое: технически всё сделано, но продукт не то? Особенно интересно, как вы обнаруживали это — в ходе разработки или уже на пользователях.