Pull to refresh
32K+
11
Максим@alien-engineerread⁠-⁠only

40 лет. Инженер

20,7
Rating
22
Subscribers
Send message

«Без чёткого ТЗ» — да, именно так. Это и есть та самая скучная фаза реализации, про которую тебе написал AEON в карте 6.Тень.

То, что ты прогнал промпты через Codex напрямую — это честный эксперимент, и хорошо, что сработало. Вся логика вопросов и карт живёт в YAML. Обвязка с событиями, стабильностью и памятью — это уже про то, чтобы система работала не разово, а накапливала профиль во времени. Но суть — в модели, и ты до неё добрался.

«Доведение после того, как мозгу стало скучно» — это, кстати, ровно то, что я сам строю внутри Founder Mode. Не вдохновение, не новая задача, а один вопрос вечером: было ли движение? Маленький внешний взгляд, который не даёт закрыть таб.

В общем, большинство так и делает, что ничего не делает. Короткие вертикальные видео уничтожат человечество :D

Кстати, если тема небезразлична — сейчас на свободный-интернет.рф идёт сбор подписей на петицию о введении парламентского контроля над блокировками ресурсов с аудиторией более 100 000 российских пользователей, вместо нынешнего ведомственного. Это не решит всех проблем, но хотя бы добавит публичности и подотчётности в процесс, который сейчас полностью непрозрачен.

Согласен с вашим анализом — это структурная проблема, а не вопрос того, пользуются ли создатели своим продуктом. Доступность переписки по запросу — это не баг, это фича с точки зрения регулятора, и никакой UX это не компенсирует.

ÆON  сейчас в разработке — бот ещё не запущен, в репозитории пока спека, архитектура и часть кода, которая будет обновляться итерационно (об этом следующие статьи).

Founder Mode — есть в Telegram, это отдельный бот, он уже работает. Ссылка есть в профиле здесь или в ТГ "qip_aibot".

Справедливая критика — статья действительно написана изнутри, и я не сделал нормального «входа» для читателя снаружи. Поправлю.

Коротко: ÆON  — это бот для самопознания, который строит многослойный профиль личности через диалог. Не тест с четырьмя буквами в конце, а система, которая помнит каждый твой ответ как факт и со временем показывает паттерны — как ты думаешь, что тебя реально мотивирует, где ты повторяешь одни и те же сценарии.

Founder Mode — отдельная, более простая штука. Это практика фиксации: раз в день отвечаешь на три вопроса — был ли прогресс по недельному приоритету, что делал вместо, и что мешало. Никакого анализа, никакой аналитики — просто освещение. Основная идея из второй статьи: когда фиксируешь факт честно, критик теряет пространство для манёвра.

Знакомый маршрут. Интересно, что ты описываешь его как финал — «перешёл в ИТ-специалиста в крупной компании». Для кого-то это и есть правильный выход: среда снова есть, она тебя держит, ты работаешь в полную силу. Для меня это тоже было бы честным решением — если бы я не обнаружил, что хочу разобраться именно с тем, что происходит без этой среды.

vibepp: "0.2"
methodology: "PDA"  # Possibility-Driven Architecture v1.1 (Максим, 2026)

# ═══════════════════════════════════════════════════════
# ÆON MAP SYSTEM — MAX BOT
# Машинная спецификация для агентной разработки
# ═══════════════════════════════════════════════════════

project:
  name: "AeonMapMaxBot"
  type: "conversational-ai-bot"
  platform: "MAX (VK messenger, Bot API)"
  summary: >
    ИИ-бот в мессенджере MAX, который ведёт адаптивный диалог с пользователем
    и строит многослойный профиль личности по архитектуре ÆON Map System.
    Каждый ответ пользователя — это событие. Профиль — это read model поверх
    event log. Диалог — это живая система, управляемая LLM-ядром и PDA-инвариантами.

purpose:
  goal: >
    Снизить неопределённость пользователя о себе: кто он, как думает,
    чего хочет, где его ограничения, какой архетип, куда расти.
  problem: >
    Человек не понимает своих паттернов — когнитивных, эмоциональных,
    стратегических. Существующие тесты (MBTI, соционика) статичны,
    поверхностны и не дают персонализированного пути развития.
  outcome: >
    Пользователь получает ÆON-профиль: визуальная карта личности по 7 слоям,
    текстовые инсайты, архетип, зоны роста, и Book of Consciousness —
    история трансформации, которая пополняется при каждой сессии.
  pda_framing: >
    Приложение — это машина, которая снижает неопределённость пользователя
    о себе, закрепляя устойчивые инварианты идентичности через акты
    определённости (ответы в диалоге).

# ───────────────────────────────────────────────────────
# ПОЛЬЗОВАТЕЛИ
# ───────────────────────────────────────────────────────

audience:
  primary:
    - "люди в точке выбора: карьера, отношения, смыслы"
    - "практики саморазвития, коучинга, психологии"
    - "предприниматели и лидеры, строящие команды"
  secondary:
    - "коучи и терапевты (используют бот как диагностику)"
    - "HR-специалисты (совместимость, роли)"
  jtbd:
    - "не понимаю, в чём моя реальная сила"
    - "хочу понять свои паттерны, не проходя долгую терапию"
    - "хочу видеть, как я меняюсь со временем"
    - "хочу понять, почему у меня не выходит X"

# ───────────────────────────────────────────────────────
# КАРТА НЕОПРЕДЕЛЁННОСТИ (PDA Step 1)
# ───────────────────────────────────────────────────────

uncertainty_map:
  user_level:
    - "Как я думаю и принимаю решения?"
    - "Что меня на самом деле мотивирует?"
    - "Почему я повторяю одни и те же сценарии?"
    - "Каковы мои реальные ценности, а не декларируемые?"
    - "Где мои скрытые таланты?"
    - "Что мне мешает — страхи, барьеры, тень?"
    - "Какая среда и ритм жизни мне подходят?"
    - "С какими людьми я в резонансе?"
    - "Как я выгляжу в команде vs как себя чувствую?"
    - "Куда мне развиваться в следующие 12 месяцев?"
  system_level:
    - "Насколько уверенно назначена та или иная карта?"
    - "Не противоречат ли ответы пользователя друг другу?"
    - "Готов ли пользователь к следующему слою?"
    - "Нет ли признаков кризисного состояния?"
    - "Корректен ли профиль или нужна калибровка?"

# ───────────────────────────────────────────────────────
# ГРАФ ДОМЕНА (PDA Step 3)
# ───────────────────────────────────────────────────────

domain_graph:
  entities:
    User:
      fields: [id, max_user_id, created_at, locale]
      note: "идентификатор из MAX, никакой PII за пределами этого"
    Session:
      fields: [id, user_id, layer, status, started_at, completed_at]
      statuses: [active, completed, abandoned, paused]
    Answer:
      fields: [id, session_id, question_id, value, answered_at]
      note: "неизменяемый факт — только append"
    CardSignal:
      fields: [id, user_id, card_type, weight, source_answer_id, source_layer, created_at]
      note: >
        копилка сигналов для карты; один ответ может породить несколько записей
        (сквозной routing на разные card_type). Агрегация веса — вход для готовности Card.
    Card:
      fields: [id, user_id, card_type, confidence, version, computed_at]
      card_types:
        - CognitiveIdentityMap
        - BehavioralPatternMap
        - AeonConsciousnessMap
        - AffectiveResonanceMap
        - CoreValuesMap
        - LatentPotentialMap
        - StrategicSelfMap
        - LimitMap
        - EvolutionMap
        - ArchetypeMatrix
        - SocialPersonaMap
        - ShadowMirrorMap
        - RoutineGrowthMap
        - EnergyFlowMap
        - ResonanceMap
        - CompatibilityMap
        - LearningMap
        - EnvironmentMap
    AeonProfile:
      fields: [id, user_id, glyph_code, activation_phrase, version, built_at]
      note: "read model — пересобирается из events"
    Glyph:
      fields: [id, user_id, image_url, meaning, created_at]
      note: "визуальный символ идентичности; OpenAI Images (DALL·E), см. SPEC Блок 4"
    BookOfConsciousness:
      fields: [id, user_id, entries]
      note: "таймлайн трансформации — только append"
    LlmCall:
      fields: [id, session_id, model, prompt_version, input_hash, output, latency_ms, called_at]
      note: "каждый вызов LLM фиксируется для воспроизводимости"

  edges:
    - "User has_many Session"
    - "User has_one AeonProfile"
    - "User has_one BookOfConsciousness"
    - "User has_many Card"
    - "User has_many Glyph"
    - "Session has_many Answer"
    - "Session belongs_to Layer"
    - "Answer contributes_to Card (через event-проекцию)"
    - "Answer contributes_signal_to Card (cross-layer; через CardSignal)"
    - "User has_many CardSignal"
    - "CardSignal targets Card by card_type (агрегация веса перед card.computed)"
    - "Card aggregates_into AeonProfile"
    - "Session generates LlmCall"
    - "LlmCall produces next_question"
    - "AeonProfile generates Glyph"
    - "BookOfConsciousness records Session.completed"

# ───────────────────────────────────────────────────────
# ИНВАРИАНТЫ (PDA Step 4)
# ───────────────────────────────────────────────────────

invariants:
  domain:
    - id: INV-01
      rule: "Session может иметь ровно один статус из {active, completed, abandoned, paused}"
      enforcement: "domain validator + DB constraint"

    - id: INV-02
      rule: "Answer неизменяем после записи. Пользователь не может редактировать ответ — только пройти новую сессию"
      enforcement: "append-only table, no UPDATE/DELETE in ORM"

    - id: INV-03
      rule: "Card назначается только при confidence >= CARD_CONFIDENCE_THRESHOLD (default: 0.72)"
      enforcement: "Stability Engine, не LLM"

    - id: INV-04
      rule: "Card не может быть в двух взаимоисключающих состояниях одновременно (например, CognitiveType=Analytical и CognitiveType=Intuitive с равным весом без флага 'синтетик')"
      enforcement: "domain validator перед записью Card"

    - id: INV-05
      rule: "Session следующего слоя не открывается, пока предыдущий слой не имеет минимум MIN_ANSWERS_PER_LAYER ответов"
      enforcement: "Stability Engine"

    - id: INV-09
      rule: >
        Card не назначается (card.computed), пока суммарный вес сигналов по card_type
        < MIN_AGGREGATE_SIGNAL_WEIGHT_FOR_CARD — независимо от того, с каких слоёв пришли
        сигналы; unlock слоя регулирует ход диалога, не заменяет порог сигналов
      enforcement: "Stability Engine + агрегация CardSignal"

    - id: INV-06
      rule: "LlmCall сохраняется до выдачи ответа пользователю, не после"
      enforcement: "транзакция: write LlmCall → send message"

    - id: INV-07
      rule: "Одно сообщение пользователя = не более одного Answer event (идемпотентность)"
      enforcement: "idempotency_key = max_update_id"

    - id: INV-08
      rule: "AeonProfile пересобирается только из зафиксированных событий, никогда не редактируется вручную"
      enforcement: "profile builder принимает только event store на вход"

  safety:
    - id: INV-S01
      rule: "При обнаружении кризисных маркеров (суицид, самоповреждение, насилие) бот прекращает профилирование и предлагает горячую линию"
      enforcement: "safety Gate 1 в stability/ на каждом пользовательском input до любого дорогого вызова; Gate 2 в system prompt LLM"

    - id: INV-S02
      rule: "Бот не даёт медицинских, юридических, финансовых советов — только рефлексивные вопросы и инсайты"
      enforcement: "системный промпт + content filter"

# ───────────────────────────────────────────────────────
# КОНСТАНТЫ (PDA Step 5)
# ───────────────────────────────────────────────────────

constants:
  - key: MIN_AGGREGATE_SIGNAL_WEIGHT_FOR_CARD
    value: 0.5
    why: "черновой порог суммарного веса (шкала 0–1); калибровать до запуска MVP"
    breaks_without: "карты без смысла или слишком рано; либо игнор сквозных связей"
    calibration: "A/B с retention и качеством профиля; зафиксировать число в docs/constants.md"

  - key: CARD_CONFIDENCE_THRESHOLD
    value: 0.72
    why: "ниже — карта ненадёжна и вводит пользователя в заблуждение"
    breaks_without: "профиль будет строиться на слабых сигналах"
    calibration: "A/B по retention и user feedback после профиля"

  - key: MIN_ANSWERS_PER_LAYER
    value: 4
    why: "меньше — LLM не имеет достаточно контекста для следующего слоя"
    breaks_without: "профиль будет поверхностным, слои не связаны"
    calibration: "анализ completion rate по слоям"

  - key: MAX_QUESTIONS_PER_SESSION
    value: 12
    why: "больше — усталость, дропы; меньше — недостаточно сигналов"
    breaks_without: "либо дроп в середине, либо слабый профиль"
    calibration: "замер session_completion_rate по длинам"

  - key: SESSION_IDLE_TIMEOUT_MIN
    value: 30
    why: "30 минут молчания = сессия брошена; восстанавливаем контекст при возврате"
    breaks_without: "ghost sessions, утечка памяти в Redis"
    calibration: "медиана времени между ответами + буфер"

  - key: LLM_QUESTION_TEMP
    value: 0.7
    why: "достаточно вариативно для живого диалога, не галлюцинирует вопросы"
    breaks_without: "слишком предсказуемо (0.0) или хаотично (1.0+)"
    calibration: "blind A/B оценка качества вопросов операторами"

  - key: DAILY_SESSION_LIMIT
    value: 3
    why: "защита от злоупотреблений и LLM-затрат; 3 сессии в день — норма"
    breaks_without: "спам-атаки, неожиданные расходы"
    calibration: "анализ percentile-99 по сессиям/день"

  - key: MAX_BOT_REPLY_TIMEOUT_SEC
    value: 8
    why: "MAX UI показывает typing indicator; > 8 сек — пользователь думает, что сломалось"
    breaks_without: "плохой UX, повторные нажатия, дубли"
    calibration: "p95 latency LLM + overhead"

# ───────────────────────────────────────────────────────
# EVENT CORE (PDA Step 6)
# ───────────────────────────────────────────────────────

events:
  schema_version: 1
  contract:
    required_fields:
      - event_id        # uuid v7
      - event_type      # snake_case string
      - occurred_at     # ISO 8601 UTC
      - actor           # {id, role}
      - subject         # {entity, id}
      - payload         # object
      - idempotency_key # max_update_id или generated uuid
      - schema_version  # integer
    optional_fields:
      - causation_id    # uuid предыдущего event
      - correlation_id  # uuid сессии/флоу

  catalog:
    - type: user.started
      trigger: "первый /start в MAX"
      payload: [max_user_id, locale, referral_source]

    - type: session.opened
      trigger: "бот открыл новую сессию"
      payload: [session_id, layer, question_count_plan]

    - type: question.asked
      trigger: "бот отправил вопрос пользователю"
      payload: [session_id, question_id, question_text, layer, llm_call_id]

    - type: answer.given
      trigger: "пользователь ответил"
      payload: [session_id, question_id, answer_value, answer_type]
      note: "НЕИЗМЕНЯЕМ после записи (INV-02)"

    - type: card_signal.received
      trigger: "ответ спроецирован на копилку сигналов целевой карты (сквозной routing)"
      payload: [answer_id, user_id, card_type, weight, source_layer]
      note: "может быть несколько на один answer.given; causation от answer.given"

    - type: llm.called
      trigger: "вызов Claude API"
      payload: [session_id, model, prompt_version, input_hash, latency_ms]
      note: "фиксируется до отправки ответа (INV-06)"

    - type: card.computed
      trigger: "Stability Engine назначил карту"
      payload: [card_type, confidence, input_answer_ids, version]

    - type: session.completed
      trigger: "сессия завершена (все вопросы отвечены)"
      payload: [session_id, duration_sec, answers_count, layers_covered]

    - type: profile.built
      trigger: "ÆON-профиль пересобран из событий"
      payload: [profile_version, cards_included, glyph_id]

    - type: safety.triggered
      trigger: "safety Gate 1 (или реже Gate 2 / эскалация) поймал кризисный маркер"
      payload: [session_id, trigger_category, action_taken]
      note: "НЕ содержит оригинальный текст пользователя"

    - type: session.abandoned
      trigger: "SESSION_IDLE_TIMEOUT истёк"
      payload: [session_id, last_answer_at, answers_count]

# ───────────────────────────────────────────────────────
# АРХИТЕКТУРА (PDA Step 6)
# ───────────────────────────────────────────────────────

architecture:
  approach: "Event-sourced, domain-centric, stability-first"

  layers:
    max_adapter:
      role: "принимает webhook от MAX, отдаёт ответы"
      responsibilities:
        - "парсинг MAX update"
        - "идемпотентность по update_id"
        - "форматирование сообщений и кнопок MAX"
      must_not: "содержать бизнес-логику"

    api_layer:
      role: "HTTP endpoints, auth, rate limiting"
      note: "только роутинг и валидация входа"

    domain_layer:
      role: "инварианты, валидаторы, доменные сущности"
      must: "работать без I/O — чистый код"
      must_not: "знать о MAX, LLM, БД"

    stability_engine:
      role: "лимиты, пороги уверенности, анти-абуз, safety Gate 1"
      responsibilities:
        - "проверка DAILY_SESSION_LIMIT"
        - "проверка CARD_CONFIDENCE_THRESHOLD"
        - "safety Gate 1: rule-based / лёгкий классификатор ДО любого дорогого вызова (отдельные тесты)"
        - "rate limiter по user_id"
      must: "быть отдельным модулем в src/stability/, не размазан по коду"

    signal_classifier:
      role: "шаг 1 пайплайна ответа: ответ → веса по card_type → card_signal.received"
      responsibilities:
        - "дешёвый: правила или малая модель, не обязательно LLM"
        - "несколько card_signal.received на один answer при необходимости"
      must_not: "блокировать p95 ответа тяжёлым LLM"

    dialog_engine:
      role: "адаптивный диалог, управление состоянием сессии"
      responsibilities:
        - "выбор следующего вопроса (через LLM или fallback)"
        - "трекинг прогресса по слоям"
        - "определение момента перехода к следующему слою"
      must: "работать через events — каждый шаг = event"

    llm_client:
      role: "вызовы Claude API (основной диалог), OpenAI (fallback), промпты"
      responsibilities:
        - "системный промпт с контекстом пользователя + safety Gate 2 (границы в промпте)"
        - "версионирование prompt templates"
        - "логирование каждого вызова (LlmCall event)"
        - "fallback: OpenAI при недоступности Claude"
        - "глиф: OpenAI Images (DALL·E), не смешивать с текстовым Claude без явного разделения"

    aeon_engine:
      role: "вычисление карт, построение профиля; глиф через OpenAI Images"
      input: "только event store"
      output: "Card, AeonProfile, Glyph"

    event_core:
      role: "append-only event store"
      storage: "PostgreSQL, таблица events"
      must: "не иметь UPDATE/DELETE"

    read_models:
      role: "проекции для быстрого чтения"
      models:
        - "UserProfile (сжатый профиль: карты, confidence, архетип)"
        - "CardSignalRollup (незакрытые сигналы по порогу)"
        - "AnswerTail (последние 3–5 ответов для LLM)"
        - "SessionContext (текущее состояние сессии для LLM)"
        - "BookOfConsciousness (таймлайн; не в промпт LLM — UI и метрики)"
      rebuild: "из event store при необходимости"

  data_flow: |
    MAX Webhook
        │
        ▼
    [MAX Adapter] ──idempotency check──▶ skip if duplicate
        │
        ▼
    [Stability Engine] ──safety Gate 1──▶ crisis: send hotline, stop (без LLM)
        │           └──rate limit──▶ 429, stop
        ▼
    [Dialog Engine] reads SessionContext + профиль + хвост + незакрытые CardSignal
        │
        ├──▶ [Signal Classifier] ──▶ card_signal.received (дешёво)
        │
        ├──▶ [LLM Client Claude; Gate 2 в system prompt] ──▶ llm.called ──▶ next question
        │         └── fallback OpenAI при сбое Claude
        │
        ▼
    answer.given event ──▶ [Event Core]
        │
        ├──▶ [Aeon Engine] ──▶ card.computed (порог сигналов + confidence)
        │
        └──▶ [MAX Adapter] ──▶ send message to user

  stack:
    language: "TypeScript 5.x"
    runtime: "Node.js 22 LTS"
    web: "Fastify"
    database: "PostgreSQL 16"
    cache: "Redis 7 (сессии, rate limits)"
    llm:
      primary: "Anthropic Claude API"
      fallback: "OpenAI (текст)"
      glyph_image: "OpenAI Images (DALL·E)"
    share_render: "sharp + @resvg/resvg-js (SVG → PNG, без headless browser)"
    migrations: "node-postgres + db-migrate | Drizzle ORM — уточнить при инициализации репо"
    containerization: "Docker + docker-compose"
    testing: "Vitest + fast-check (property-based для инвариантов)"
    observability: "OpenTelemetry + Prometheus-совместимые метрики"

# ───────────────────────────────────────────────────────
# СТРУКТУРА ПРОЕКТА
# ───────────────────────────────────────────────────────

project_structure:
  style: "domain-centric monolith (v1), готов к разделению"
  directories:
    - path: "src/domain/"
      purpose: "сущности, инварианты, валидаторы — чистый код без I/O"
    - path: "src/events/"
      purpose: "event store, контракты, идемпотентность"
    - path: "src/stability/"
      purpose: "Stability Engine: лимиты, safety Gate 1, пороги (отдельные тесты на gate)"
    - path: "src/dialog/"
      purpose: "движок диалога, FSM слоёв, управление сессией"
    - path: "src/signal_classifier/"
      purpose: "дешёвый шаг: ответ → card_signal.received (правила или малая модель)"
    - path: "src/aeon/"
      purpose: "карты ÆON Map, профиль, глиф, Book of Consciousness"
    - path: "src/llm/"
      purpose: "Claude (основной), OpenAI fallback, DALL·E для глифа; prompt templates"
    - path: "src/integrations/max/"
      purpose: "MAX Bot API клиент, webhook handler"
    - path: "src/read_models/"
      purpose: "проекции: SessionContext, UserProfile, CardSignalRollup, AnswerTail, BookOfConsciousness"
    - path: "src/api/"
      purpose: "HTTP endpoints, роутинг"
    - path: "tests/invariants/"
      purpose: "property-based тесты на инварианты (Vitest + fast-check)"
    - path: "tests/scenarios/"
      purpose: "end-to-end сценарные тесты диалогов"
    - path: "migrations/"
      purpose: "SQL миграции (db-migrate | Drizzle — по выбору при старте)"
    - path: "docs/"
      purpose: "SPEC, SPEC_SUMMARY, uncertainty-map, domain-graph, invariants, constants, events, architecture, observability, roadmap, GITHUB_ISSUES, GIT_STRATEGY"
    - path: "prompts/"
      purpose: "версионированные prompt templates для LLM"

# ───────────────────────────────────────────────────────
# СЛОИ ÆON MAP — РЕАЛИЗАЦИЯ
# ───────────────────────────────────────────────────────

# Unlock order — линейный; signal routing — сквозной (см. SPEC Блок 2, CardSignal, card_signal.received).
aeon_layers:
  mvp:
    - id: I
      name: "Core Layer"
      cards: [CognitiveIdentityMap, BehavioralPatternMap]
      min_questions: 4
      unlock_condition: "session.started"

    - id: II
      name: "Emotional & Motivational Layer"
      cards: [AffectiveResonanceMap, CoreValuesMap]
      min_questions: 4
      unlock_condition: "Layer I completed"

    - id: IV
      name: "Archetype Layer"
      cards: [ArchetypeMatrix]
      min_questions: 4
      unlock_condition: "Layer II completed"

  v1_addition:
    - id: III
      name: "Strategic Layer"
      cards: [StrategicSelfMap, LimitMap]
    - id: V
      name: "Dynamic AI Layer"
      cards: [EnergyFlowMap, ResonanceMap]

  v2_addition:
    - id: VI
      name: "Integration Layer"
      cards: [CompatibilityMap, LearningMap, EnvironmentMap]
    - id: VII
      name: "Meta Layer"
      cards: [AeonConsciousnessMap]
      note: "включает генерацию Glyph и Book of Consciousness"

# ───────────────────────────────────────────────────────
# ДИАЛОГ
# ───────────────────────────────────────────────────────

dialog:
  mode: "adaptive — следующий вопрос генерирует LLM с учётом всех предыдущих ответов"
  branching: "без явных веток сценария — только адаптивный LLM по полному контексту"
  prompts:
    structure: "один общий system prompt + дополнения/шаблоны по слоям (I, II, IV MVP)"
    note: "отклонения (не знаю, оффтоп, провокации) — в рамках этой структуры, не отдельные продуктовые ветки"
  fallback: "статичный список вопросов на случай LLM timeout"
  answer_formats:
    - type: buttons
      use_when: "закрытые вопросы (выбор из 2–4 вариантов)"
      max_options: 4
    - type: free_text
      use_when: "открытые вопросы глубокого слоя"
    - type: scale
      use_when: "оценка интенсивности"
      range: "1–7"

  persona:
    name: "ÆON"
    tone:
      - "глубокий, но не тяжёлый"
      - "любопытный исследователь, не судья"
      - "конкретный — без воды и эзотерики"
      - "тёплый, но не сюсюкающий"
    boundaries:
      - "не терапевт"
      - "не ставит диагнозы"
      - "не предсказывает будущее"
      - "не сравнивает с другими людьми"

  safety:
    gates:
      gate_1:
        where: "src/stability/ — до любого дорогого вызова (Claude/OpenAI)"
        how: "rule-based и/или лёгкий классификатор; отдельные тесты"
      gate_2:
        where: "system prompt основного LLM"
        how: "границы и запреты; второй рубеж для edge cases"
    triggers:
      - "суицидальные высказывания"
      - "самоповреждение"
      - "насилие (в отношении себя или других)"
      - "острый психотический эпизод (контроль реальности)"
    action: >
      Остановить профилирование. Ответить тепло и без паники.
      Предложить ресурсы: телефон доверия 8-800-2000-122 (РФ, бесплатно).
      Зафиксировать safety.triggered event (без текста пользователя).

# ───────────────────────────────────────────────────────
# НАБЛЮДАЕМОСТЬ (PDA Step 7)
# ───────────────────────────────────────────────────────

observability:
  dashboards:
    user_clarity:
      metrics:
        - "time_to_clarity_sec: медиана времени от /start до profile.built"
        - "session_completion_rate: доля сессий со статусом completed"
        - "layer_dropoff_rate: где именно бросают"

    domain_health:
      metrics:
        - "invariant_violations_total: нарушения инвариантов (должно быть ~0)"
        - "card_rejection_rate: доля отклонённых карт (confidence < threshold)"
        - "answer_conflict_rate: противоречивые ответы на похожие вопросы"

    llm_quality:
      metrics:
        - "llm_latency_p95_ms"
        - "llm_timeout_rate"
        - "prompt_version_distribution: какие версии промптов в проде"

    reliability:
      metrics:
        - "webhook_duplicate_rate: доля дедуплицированных MAX updates"
        - "error_rate_5xx"
        - "queue_lag_sec (если используется очередь)"

    safety:
      metrics:
        - "safety_trigger_rate: доля сессий с safety.triggered"
        - "crisis_category_distribution"

  alerts:
    - "invariant_violations_total > 0 за 5 минут → PagerDuty Critical"
    - "session_completion_rate < 0.40 за 1 час → Slack Warning"
    - "llm_latency_p95_ms > 6000 за 5 минут → Slack Warning"
    - "safety_trigger_rate > 0.05 за 1 час → Slack Critical"

# ───────────────────────────────────────────────────────
# FEATURES
# ───────────────────────────────────────────────────────

features:
  core:
    - "Адаптивный диалог по слоям ÆON Map (MVP: слои I, II, IV)"
    - "Каждый ответ сохраняется как неизменяемый event"
    - "LLM-ядро генерирует следующий вопрос на основе всех предыдущих ответов"
    - "Stability Engine контролирует пороги перед назначением карты"
    - "ÆON-профиль строится как read model из event log"
    - "Safety Gate 1 до любого дорогого вызова на каждом сообщении"
    - "Идемпотентность: дубли MAX-апдейтов игнорируются"
    - "Book of Consciousness: каждая завершённая сессия добавляет запись"
    - "Конец сессии: msg1 глиф+фраза-суть → пауза 2–3 с → msg2 краткий профиль 3–4 блока текста (без HTML)"
    - "Push MAX через 24 ч после завершённой сессии: персонализированный крючок по карте с напряжением"

  secondary:
    - "Glyph: уникальное изображение профиля (OpenAI Images / DALL·E)"
    - "Шеринг: PNG-карточка (SVG → PNG sharp + @resvg/resvg-js): глиф + архетип + строка сути"
    - "Кнопки-ответы в MAX для закрытых вопросов"
    - "Напоминание о незавершённой сессии через 24 часа"
    - "Команда /profile — показать текущий профиль в любой момент"
    - "Команда /history — Book of Consciousness"

  v1_addition:
    - "Еженедельный глиф-дайджест: изменения профиля, накопление сигналов"
    - "Публичная ссылка на веб-профиль (после Mini App или лендинга)"

  out_of_scope_mvp:
    - "Mini App / лендинг / публичная ссылка на профиль (см. v1_addition)"
    - "NFT-глифы и блокчейн"
    - "Совместимость с другими пользователями (Compatibility Map)"
    - "Экспорт профиля в PDF"
    - "API для коучей и HR"
    - "Мультиязычность (только RU в MVP)"

profile_delivery:
  end_session_messages:
    delay_sec_between: [2, 3]
    message_1: "глиф + одна фраза-суть (эмоциональная точка)"
    message_2: "3–4 текстовых блока: архетип, когнитивный стиль, зона роста, энергия"
  push_after_complete:
    delay_hours: 24
    template: "персонализировано: слой + карта с max напряжением"
  share_card:
    format: "PNG"
    pipeline: "SVG template → PNG (sharp + @resvg/resvg-js)"
    contains: [glyph, archetype_name, essence_one_liner]
    no_external_urls: true

max_platform:
  mvp:
    bot_account: "уже создан"
    transport: "webhook only (long polling только dev-костыль)"
    https: "обязателен; валидный TLS (не self-signed)"
    domain: "стабильный; фиксированный IP не обязателен"
    port_note: "443 | 80 | 88 | 8443 — уточнить в документации MAX Bot API"
  ui: "только чат в MVP (Mini App — v1)"

deploy:
  production:
    tls: "Let's Encrypt (Caddy или nginx)"
    proxy: "Caddy как reverse proxy (рекомендовано для простоты)"
    hosting_ru: ["Yandex Cloud", "VK Cloud", "Selectel"]
  local_dev:
    tunnel: "ngrok | cloudflared — HTTPS URL для регистрации webhook"
    compose: "опционально отдельный сервис туннеля в docker-compose"

business:
  load:
    mau_honest_start: "сотни"
    mau_with_audience_channel: "тысячи"
    single_node_estimate_mau: 5000
    note: "один Node.js + PostgreSQL на одном сервере — до порядка ~5k MAU без горизонтального масштабирования (оценка)"
  kubernetes_mvp: false
  privacy:
    level: "серьёзный продукт, GDPR-like"
    automated_deletion: true
    pii_separate_from_analytics: true
    data_residency: "только РФ"
  process:
    team: "соло + Cursor agent"
    repo: "открытый GitHub"
    tracking: "GitHub Issues, Projects, Milestones, Labels"
    issues_export: "docs/GITHUB_ISSUES.md"
    git_strategy_doc: "docs/GIT_STRATEGY.md"

git_strategy:
  principle: "коммит когда стабильно и не хочется терять, не когда «всё идеально готово»"
  commit_triggers:
    - "функция + тест зелёный"
    - "закрыт один acceptance criterion из issue"
    - "перед рефакторингом рабочего кода — точка возврата"
    - "конец дня — коммит с префиксом wip: если не закончил"
  commits_per_day_active_solo: [5, 15]
  branches_when:
    long_running_feature: "feat/<name> — мерж когда итерация/фича закрыта"
    experiment: "exp/<name> — можно выбросить"
    otherwise: "прямо в main"
  branches_project:
    main: "всегда рабочее, задеплоено"
    iteration: "feat/iter-N — например feat/iter-1 Event Core, feat/iter-2 Dialog Engine"
  iteration_cycle: "закрыл итерацию → merge в main → удалил ветку → следующая feat/iter-"

monetization:
  mvp_model: "freemium + QIP Coin"
  free_tier: "базовый профиль"
  paid_qip: ["глубокие слои", "расширенный анализ"]
  not_mvp:
    pay_per_profile: "низкий барьер, хуже retention — не выбрано"
    subscription: "нужна еженедельная ценность — в MVP ещё нет"
  architecture:
    principle: "платные действия = события; Stability Engine проверяет доступ; без обхода event log"
    tbd: ["цены в QIP", "API кошелька QIP", "event types для списаний"]

# ───────────────────────────────────────────────────────
# ПРАВИЛА
# ───────────────────────────────────────────────────────

rules:
  hard:
    - "НИКОГДА не писать UPDATE или DELETE в таблицу events — только INSERT"
    - "НИКОГДА не пропускать safety Gate 1 перед любым дорогим вызовом (LLM)"
    - "НИКОГДА не назначать Card без проверки CARD_CONFIDENCE_THRESHOLD"
    - "НИКОГДА не хранить оригинальный текст пользователя в safety.triggered event"
    - "НИКОГДА не строить профиль вне aeon_engine — только из event store"
    - "НИКОГДА не разрешать более DAILY_SESSION_LIMIT сессий в день на пользователя"
    - "Инварианты живут в domain/, а не в контроллерах или БД-триггерах"

  firm:
    - "Каждый LLM-вызов фиксируется в llm.called event ДО отправки ответа пользователю"
    - "Константы — в конфиге, не в коде"
    - "Prompt templates — версионированные файлы в /prompts, не строки в коде"
    - "Property-based тесты на все инварианты (Vitest + fast-check)"
    - "Webhook handler возвращает 200 немедленно, обработка — async"

  soft:
    - "Предпочитать читаемый код компактному"
    - "Каждый новый инвариант сопровождается тестом до мержа"
    - "При сомнении — добавить Constant Card в docs/constants.md"

# ───────────────────────────────────────────────────────
# ИТЕРАЦИИ (ROADMAP)
# ───────────────────────────────────────────────────────

iterations:
  - id: 0
    name: "Скелет"
    deliverables:
      - "репо, docker-compose (PostgreSQL + Redis + app)"
      - "MAX webhook handler → ответ 'привет'"
      - "первая миграция: таблица events"
    done_when: "бот отвечает в MAX, событие user.started записано в БД"

  - id: 1
    name: "Event Core"
    deliverables:
      - "event store (append-only), контракт события"
      - "идемпотентность по max_update_id"
      - "user.started event при первом /start"
    done_when: "дубль MAX update не создаёт дубль события"

  - id: 2
    name: "Первый вопрос"
    deliverables:
      - "dialog engine: открытие сессии (session.opened)"
      - "статичный первый вопрос Core Layer (question.asked)"
      - "сохранение ответа (answer.given)"
    done_when: "пользователь отвечает, ответ в event store"

  - id: 3
    name: "LLM-диалог"
    deliverables:
      - "LLM client: Claude API"
      - "следующий вопрос генерируется Claude на основе предыдущих ответов"
      - "llm.called event, версионированный prompt"
      - "fallback при timeout"
    done_when: "5 адаптивных вопросов, каждый учитывает предыдущие ответы"

  - id: 4
    name: "Первая карта"
    deliverables:
      - "Stability Engine: проверка CARD_CONFIDENCE_THRESHOLD"
      - "aeon_engine: CognitiveIdentityMap"
      - "card.computed event"
      - "INV-03 и INV-04 с property-based тестами"
    done_when: "карта назначается при достижении порога, не раньше"

  - id: 5
    name: "MVP профиль"
    deliverables:
      - "слои I + II + IV (Core, Emotional, Archetype)"
      - "AeonProfile read model"
      - "команда /profile выдаёт текстовый профиль"
      - "session.completed → запись в Book of Consciousness"
    done_when: "пользователь проходит полную сессию и получает профиль"

  - id: 6
    name: "Наблюдаемость"
    deliverables:
      - "все метрики из observability.dashboards"
      - "алерты"
      - "dashboard в Grafana (или аналог)"
    done_when: "все метрики видны, INV-алерт срабатывает на тест-нарушение"

  - id: 7
    name: "Safety + Glyph + share card"
    deliverables:
      - "safety Gate 1 в stability/ (тесты), safety.triggered; Gate 2 в system prompt"
      - "генерация Glyph: OpenAI Images (DALL·E)"
      - "PNG share card: sharp + @resvg/resvg-js"
    done_when: "кризисное сообщение останавливает профилирование без дорогого LLM; глиф и шеринг-карточка генерируются"

# ───────────────────────────────────────────────────────
# КРИТЕРИИ ПРИЁМКИ
# ───────────────────────────────────────────────────────

accept:
  - "Пользователь пишет /start в MAX — бот приветствует и задаёт первый вопрос"
  - "Каждый ответ фиксируется в event store как неизменяемый факт"
  - "Следующий вопрос зависит от предыдущих ответов (адаптивность проверяется вручную)"
  - "Кризисное сообщение останавливает диалог и предлагает горячую линию"
  - "Дубль MAX update не создаёт дубль события (тест: отправить одинаковый update_id дважды)"
  - "Card не назначается, если confidence < CARD_CONFIDENCE_THRESHOLD"
  - "Все инварианты покрыты property-based тестами"
  - "После завершения сессии: /profile выдаёт структурированный ÆON-профиль"
  - "AeonProfile пересобирается из event store без потери данных"
  - "Метрики invariant_violations_total видны в дашборде"
  - "p95 latency ответа бота < MAX_BOT_REPLY_TIMEOUT_SEC"
.

👉 https://github.com/Quantum-Insight-Lab/aeon_map_system
Скрытый текст

Хорошая вещь

Согласен, что принцип не новый. ÆON здесь про другое — не про структуру управления, а про инструмент самопознания через ИИ. Это часть 3 из серии, первые две дают контекст.

Это один из самых точных комментариев, что я получил за всё время. Вы пришли к тому же, к чему я шёл четыре года — только другим путём и, кажется, быстрее.

Фраза «невозможно проиграть, если не начинаешь игру» — точнее, чем я сформулировал в тексте. Я написал про иллюзию занятости, вы нашли механизм под ней: защита идентичности через незапуск. Одно и то же, но ваша версия острее.

И узнал себя ещё в одном месте — паяете в одиночестве, офис без людей, фитнес один. У меня всё то же самое. Это не интроверсия в классическом смысле — скорее инженерный архетип: нужен живой человек рядом для энергии, но только по делу, не просто «потусоваться».

Как планируете решать вопрос с командой в своём формате — собирать людей физически, или ищете другой способ закрыть этот кусок?

Сделал по примеру https://stukalin.ru/vibepp/vibepp-prompt-rubik.txt себе vibepp.yaml в https://github.com/Quantum-Insight-Lab/aeon_map_system. На 845 строк файл вышел...

Интересно, с текущей скоростью Composer 2.0 Fast такой проект в 2-3 человека за неделю соберут?

Спасибо за инструмент — я его сразу применил. Взял пример из статьи, добавил документацию по своей методике и проект (ИИ-психопрофилирование через адаптивный диалог в мессенджере MAX), прогнал через vibepp-prompt-rubik — и получил готовый промпт для Cursor, который задал вопросы и сгенерировал все артефакты по спек-листу.

Итог: SPEC на 9 блоков, vibepp.yaml, git-стратегия, GitHub Issues по итерациям. Репозиторий уже открыт: github.com/Quantum-Insight-Lab/aeon_map_system — пока без README, но docs внутри.

Если интересно, как Vibe++ лёг на нетехнический проект с психологической моделью в основе — готов показать детали.

Это очень узнаваемо, и то, что вы сами пришли к «собранию понедельник-пятница» — уже почти та самая практика, просто с другой стороны. Ключевое, что вы сказали: «перестал себя обманывать и почувствовал облегчение». Это главный признак, что механизм запустился. Не дисциплина, не мотивация — именно облегчение. Потому что поддержание иллюзии занятости стоит дороже, чем честная фиксация.

Если захочется — попробуйте добавить к собраниям одну вещь: вечерний вопрос себе «было ли сегодня движение по главному — да, нет или частично». Одно слово, никакой расшифровки. Иногда этого достаточно, чтобы увидеть паттерн, который в недельной рамке не виден.

Честно — возможно, вы правы. Драфт был живее, да. Я его потом причёсывал, потому что боялся, что «как есть» будет слишком рыхло для длинного текста. Видимо, пережал — потерял ту самую живость в обмен на гладкость. Это правда полезное наблюдение, буду иметь в виду на следующих текстах. Спасибо.

Спасибо, что развернули — это серьёзный заход, и отвечу по-серьёзному.

В трёх вещах с вами соглашусь сразу. Вопрос «Зачем?» действительно первичен. Идея «успех = свой бизнес» реально продаётся как товар, и вокруг неё построена индустрия, которая зарабатывает на чужих попытках. Большинство фаундеров не выигрывает — это честная математика.

Где разойдусь — в одном месте. У вас получается, что если человек честно задаст себе «Зачем?», он придёт к ответу «не надо». А если всё равно делает — значит, не задал по-настоящему. У меня по-другому. Я этот вопрос себе задаю регулярно, и ответ каждый раз выходит не «не надо», а «надо — но проверить, получится ли, тот ли выбрал способ». Если в конкретной попытке выигрыша не видно, я не перестаю делать своё — я ищу другой подход или меняю нишу. Это, кстати, тоже про вопрос «Зачем?»: он работает не только на входе в деятельность, но и внутри неё, как постоянная проверка направления. Сама деятельность — делать своё — для меня ценна. Конкретная ниша — нет, её я пересматриваю.

И маленькое уточнение про лотерею. Лотерея — это чистая случайность. Предпринимательство ближе к покеру: там есть и удача, и навык. Большинство играющих в покер тоже проигрывают — но из этого не следует, что игра бессмысленна, следует только то, что надо иметь edge и что его отсутствие не компенсируется количеством раздач.

Если коротко: согласен, что «Зачем?» первичен. Расхожусь в том, к какому ответу он обязательно ведёт. У меня — к продолжению, просто с другими глазами, чем до того, как я начал его задавать.

Это узнаваемо. И, мне кажется, ровно то, что вы описали — желание быть готовым ко всему — и есть тот самый перфекционизм тревог из первой части предыдущего поста. Не лень, не слабость — просто мозг, который пытается контролировать неконтролируемое и платит за это входным барьером. Поэтому «просто возьми и позвони» не работает. Работает другое — снижение цены отдельного звонка, чтобы «не готов» перестало быть аргументом.

Это самый важный вопрос ко всему тексту, и спасибо, что задали его так прямо.

Короткий ответ: вы правы про вашего знакомого, и я этого не оспариваю. Есть люди, для которых принятие решений в бизнесе устроено органично — снял трубку, позвонил, не задумался. Они существуют, и в среднем они выигрывают у тех, кто себя переучивает. Игра действительно неравна.

Длинный ответ — про то, где, как мне кажется, в вашей рамке есть тонкая подмена. Вы предполагаете, что у человека есть выбор: «остаться собой и заниматься тем, что даётся органично» vs «переучивать себя под бизнес». Для значительной части людей этого выбора нет. Не потому, что они хотят страдать, а потому, что «то, что даётся органично» либо не кормит, либо не существует как отдельная деятельность, либо требует ровно той же среды (работодатель, команда, структура), которой человек больше не имеет по другим причинам.

Я ушёл в своё не потому, что хотел стать «реально эффективным человеком в бизнесе». Я ушёл, потому что в найме упёрся в потолок, который для меня был структурным, а не финансовым. Альтернатива «не идти в своё» означала бы не «остаться собой», а «остаться в роли, которая мне была мала». Это другая боль, не меньшая.

И ещё одно — про вашего серийника. Вы видели его снаружи. Я не знаю ни одного успешного предпринимателя, у которого внутри всё устроено так, как кажется снаружи. «Поднимает трубку и звонит» — это часто результат двадцати лет работы над собой, после которых остался виден только результат, а не путь. Возможно, ваш знакомый правда родился левшой. А возможно, он просто настолько давно переучился, что перестал это замечать. Снаружи это неотличимо.

Стоит ли потенциальный успех боли — на этот вопрос у меня нет универсального ответа. У меня есть только мой: мне стало легче после того, как я перестал делать вид, что у меня внутри всё устроено как у того серийника. Это не сделало меня им. Но это сняло вторую боль — поверх первой — которая стоила мне больше, чем сама работа.

Думал добавить пометку в начало, но решил не делать. Расклад честный: структура, тезисы, отбор исследований и итоговая редактура — мои; черновики, формулировки и часть проверок — с ИИ, около четырёх часов суммарно. Не добавил сознательно — побоялся, что дисклеймер сам станет предметом обсуждения вместо содержания. Возможно, зря — но решение пока такое. Если где-то в тексте видно склейку или фактическую ошибку — покажите, поправлю.

1

Information

Rating
Does not participate
Location
Дубаи, Дубаи, О.А.Э.
Date of birth
Registered
Activity

Specialization

Директор по работе с клиентами, Архитектор программного обеспечения
Управление проектами
Руководство стартапом
Автоматизация процессов
Разработка программного обеспечения
UI/UX дизайн
Разработка электроники
Прототипирование