# Техническое задание для Claude: собери нейропродавца в Telegram, MAX, ВКонтакте и Instagram

Это спецификация, которую вы отдаёте своему Claude на сервере. По ней он соберёт стабильного
нейропродавца, который сам ведёт переписку от вашего имени, доводит человека до оплаты,
напоминает о себе тем, кто не оплатил, каждое утро присылает вам отчёт с цифрами и сам ищет
ошибки в своих переписках. Отдайте Claude этот файл целиком и скажите: «Собери по этому ТЗ,
спрашивай, если чего-то не хватает». Ниже – всё, что мы прошли на практике, чтобы бот работал
стабильно и реально продавал, а не просто отвечал.

> Оператор (тот, кто собирает) заранее готовит: выделенный Telegram-аккаунт под продажи (не
> личный), `API_ID`/`API_HASH` с my.telegram.org, сервер с установленным Claude и страницу
> оплаты. Продающий мозг (файл `prompt-prodazha.md`) и описание продукта с ценой и ссылкой
> на оплату оператор присылает следующим сообщением. Ключи для MAX, ВКонтакте и Instagram
> он пришлёт, когда дойдёт до этих площадок (§21).

---

## 1. Что это за система (архитектура одним абзацем)

Один мозг и несколько входов. Для каждой площадки свой демон-транспорт: Telegram (библиотека
**Telethon**, выделенный аккаунт), MAX (бот), ВКонтакте (сообщения сообщества), Instagram
(профессиональный аккаунт через API Meta). Транспорт принимает личное сообщение и передаёт его
в общий модуль мозга. Мозг собирает промпт (правила продаж + карточка фактов + история
переписки с этим человеком) и вызывает **Claude в headless-режиме** (`claude -p`). Мозг
возвращает строгий JSON: что ответить, на какой стадии диалог и что сделать по воронке (дать
ссылку на оплату, позвать оператора, замолчать и т.д.). Транспорт отправляет текст человеку,
история обновляется, отдельный цикл по расписанию сам напоминает о себе тем, кто пропал. Раз
в сутки нейросеть-контролёр читает переписки за день, а утром оператору приходит отчёт. Всё
крутится под systemd с автоперезапуском.

Почему именно так, а не «бот-конструктор»: мозг на Claude ведёт живой диалог под конкретного
человека, а не по жёсткому дереву кнопок. Это и есть разница между «отвечалкой» и продавцом.

---

## 2. Раскладка файлов

```
/home/<user>/seller/
  brain.py             # общий модуль: сборка промпта, вызов claude -p, защиты, воронка
  seller.py            # демон Telegram (Telethon)
  max_seller.py        # демон MAX
  vk_seller.py         # демон ВКонтакте
  ig_seller.py         # демон Instagram (принимает webhook)
  followup.py          # цикл напоминаний для всех площадок
  paid_sync.py         # обновление списка оплативших
  selftest.py          # тестовые переписки с трудными покупателями
  controller.py        # нейросеть-контролёр переписок
  report.py            # утренний отчёт
  knowledge/
    prompt.md          # ВСЕ правила продаж и манера речи (из prompt-prodazha.md)
    facts.md           # карточка фактов: цены, условия, гарантия, сроки, ссылка на оплату
    product.md         # подробное описание продукта (подгружается по словам-триггерам)
    triggers.txt       # только слова, по которым подгружается product.md, без правил
  dialogs/<площадка>_<id>.json   # история переписки по каждому человеку (создаёт демон)
  paid.json            # список оплативших (пишет paid_sync.py)
  reports/             # отчёты и находки контролёра
  backups/             # копии файлов знаний перед каждой правкой
  work/                # рабочая папка для запуска claude -p
  logs/                # логи
  outbox/              # MAX, ВКонтакте и Instagram кладут сюда уведомления, Telegram-демон их пересылает
  DRAFT                # флаг-файл: режим черновиков (см. §9)
  PAUSE                # флаг-файл: молчание (см. §9)
  .env                 # токены и ключи, права 600
```

🔴 **Каждое правило записано в одном месте – в `prompt.md`.** У нас правила продаж лежали в двух
файлах, и они разошлись: один файл запрещал упоминать гарантию в каждом сообщении, второй этого
требовал. Правки в одном файле просто не работали. Поэтому в `facts.md` только факты,
в `product.md` только описание продукта, в `triggers.txt` только слова-триггеры. Меняете
правило – меняете его в `prompt.md` и больше нигде.

Отдельный Linux-пользователь **только под продавца** (например `seller`). 🔴 Не селите его в
одну папку/пользователя с другими вашими ботами: тяжёлый `claude -p` одного бота может уронить
соседа.

---

## 3. Транспорт Telegram (Telethon)

- Заход в аккаунт по `API_ID`/`API_HASH` + номер телефона, сессия хранится в файле
  `seller.session`. При первом входе попроси у оператора код, который придёт в Telegram.
  🔴 Одна сессия – одна запущенная копия. Если залогиниться той же сессией где-то ещё
  (например, на своём компьютере), сервер разлогинит – держите ровно одну копию.
- Реагируем **только на личные сообщения от людей**. Игнорируем: других ботов, каналы,
  пересылки из каналов, спам и бессмыслицу (на них мозг вернёт `action: silent`).
- **Дебаунс 1 секунда.** Человек часто дописывает мысль в 2-3 сообщения. Ждём секунду и
  склеиваем всё пришедшее в один вход, чтобы ответить разом, а не на каждый обрывок.
- Пока думает мозг, держим статус **«печатает…»** (не меньше 5 секунд), чтобы человек видел,
  что ему отвечают, и не ушёл.

Дебаунс, статус «печатает» (где площадка его даёт) и все защиты из §6 одинаковы для всех
площадок: вынеси их в `brain.py`, а в транспортах оставь только приём и отправку.

**Вариант безопаснее: бот Telegram.** Если оператор выбрал бота, которого человек запускает
кнопкой Start, вместо Telethon сделай транспорт на официальном Bot API (токен от @BotFather).
Telegram не блокирует бота за переписку, но человек видит, что говорит с ботом. Мозг, защиты
и всё остальное по этому ТЗ те же. Отдельный аккаунт и my.telegram.org тогда не нужны.

---

## 4. Мозг: вызов Claude и формат ответа

- Запуск: `claude -p --model claude-sonnet-5`, промпт подаём в stdin, `cwd` = рабочая папка
  `work/`. Таймаут ~240 с.
- 🔴 **Три попытки, а не одна.** Разовый сбой запуска или таймаут не должен оставлять человека
  без ответа: пробуем ещё раз с паузой в пару секунд. Только после третьей неудачи логируем
  и уведомляем оператора. До этой правки каждая случайная ошибка превращалась в молчание
  в живом диалоге.
- 🔴 В промпте прямо запрещаем мозгу пользоваться инструментами: «Не используйте инструменты,
  не читайте файлы, не запускайте команды. Ответьте строго одним JSON-объектом». Иначе он
  вместо ответа человеку начнёт «работать по серверу».
- Ответ мозга – строго один JSON, из него достаём поля (парсер должен вытащить JSON, даже если
  модель обернула его в ```json```-блок):

```json
{
  "action": "reply | escalate | silent",
  "text": "текст сообщения человеку",
  "stage": "greeting | qualify | pitch | price | objection | closing | waiting | after_sale | done",
  "lead_action": "none | call_request | link_sent | payment_promised | paid_claimed | sale_done | stop_followups",
  "contact": "почта или телефон, если человек назвал их сам, иначе пусто",
  "payment_when": "дословно, когда человек обещал оплатить, иначе пусто",
  "payment_date": "та же дата в виде ГГГГ-ММ-ДД, если её можно вычислить, иначе пусто",
  "reason": "одна строка: почему такое решение",
  "escalate_note": "что передать оператору, если action=escalate"
}
```

- `action: reply` – отправляем `text` человеку.
- `action: escalate` – шлём уведомление оператору. 🔴 Поле `text` при этом ПУСТОЕ: человеку
  в этот момент не пишем ничего. Фразы «сейчас уточню и вернусь» выглядят так, будто автор
  не знает собственный продукт и бегает у кого-то спрашивать. Вопрос уходит молча, оператор
  подсказывает, и бот отвечает сразу по делу – как будто просто знал ответ. Исключение одно:
  человек уже ждёт и переспрашивает («мне ждать?») – тогда одна короткая строка «уточню
  и вернусь» без обещания сроков.
- `action: silent` – не отвечаем: спам, реклама, пересылка, бессмыслица, а также человек
  попрощался или попросил больше не писать (тогда ещё и `lead_action: stop_followups`).

`lead_action` – это «руль» воронки, демоны реагируют на него (см. §8). `contact` сохраняем
в диалог: по нему идёт сверка оплат (§11).

---

## 5. Сборка промпта (что подаём мозгу каждый ход)

По порядку: `prompt.md` → `facts.md` → площадка, на которой идёт разговор → текущее состояние
диалога (стадия, отправлена ли ссылка на оплату, обещанный срок) → история переписки (последние
~40 реплик, помечаем «ЧЕЛОВЕК» / «ВЫ») → новое сообщение человека (или системное событие для
напоминания) → напоминание про формат JSON.

🔴 **Экономия на входе – это не про скорость, это про качество ответов.** Замер на боевом
продавце: промпт дорос до 95 тысяч знаков, и мозг начал терять инструкции – пропустил прямое
указание открыть присланную человеком картинку, просто потому что оно утонуло в объёме.

Правило: всегда грузим только `prompt.md` и `facts.md`, а `product.md` – только когда разговор
действительно про содержание продукта (сработало слово из `triggers.txt`). Если тяжёлых файлов
несколько (подробная программа, другие продукты, детали рассрочки), у каждого свой список слов
в `triggers.txt`. После такой диеты
обычный ход стал занимать 50 тысяч знаков вместо 95, а ответы стали точнее.

🔴 **Слова-триггеры делайте узкими.** У нас в списке было «тем » – и оно срабатывало на «тем
более», подтягивая 35 тысяч знаков конспекта на пустом месте. Проверьте каждое слово на живых
фразах, прежде чем оставить.

🔴 **Кладите в карточку диалога дату, день недели и время.** Без этого бот врёт про события:
во вторник объявлял «сегодня среда, эфир в 12:00», а в десять утра говорил, что эфир «уже
прошёл». Если у вас есть регулярное событие, подставляйте готовый статус: «сегодня в 12:00,
ещё не начался» / «сегодня уже прошёл, есть запись» / «ближайший через N дней».

---

## 6. 🔴 Защиты (без них бот выглядит как бот и сливает людей)

1. **Одно сообщение за ход.** Ровно одно. Запрещено ответить на вопрос и следом прислать
   «уточню и вернусь» – это противоречие самому себе. Либо ответ, либо эскалация (§4).
2. **Снятие устаревшего ответа.** Пока генерился ответ, человек мог дописать ещё. Запоминаем
   время последнего входящего по каждому человеку; если во время генерации пришло новое
   сообщение – **старый ответ не отправляем**, следующий ход ответит на всё вместе. Иначе
   получаются два сообщения подряд невпопад.
3. **Пауза и статус «печатает».** Перед ответом пауза и статус набора текста, как в обычной
   переписке (§3).
4. **Чистка текста.** Модель нет-нет да вставит длинное тире «—». Правим кодом на «–» всегда
   (на промпт тут не полагаемся). Заодно схлопываем лишние пробелы и переносы, режем до лимита
   площадки (в Telegram 4000 символов).
5. **Лимиты частоты.** Не больше ~40 сообщений в час одному человеку и ~150 в час всего. На
   `FloodWaitError` от Telegram (и такие же ограничения других площадок) – замолкаем
   на указанное время + запас, оператору уведомление.
6. **Тихие часы 21:00–10:00 МСК** (или по часовому поясу оператора) – напоминания
   и инициативные сообщения не шлём (на живое сообщение человека отвечаем всегда).
7. **Не писать первым тому, кто не писал сам** (кроме напоминаний в своём же диалоге).
8. **Проверка на иероглифы.** Модель изредка подставляет китайский знак вместо русского слова:
   «боты для 小 бизнеса», «текст выходит 水 общим». За сутки такое ушло двум живым людям.
   Ловим регулярным выражением по диапазонам CJK: нашли – просим мозг переписать ответ
   по-русски, а если знак уцелел на последней попытке, вырезаем перед отправкой.
9. **Ссылку и вопрос о сроке не повторяем два хода подряд.** Правило в промпте модель
   продавливает, поэтому подставляем факт из кода: если в прошлом нашем сообщении была ссылка
   на оплату, добавляем в промпт прямой запрет давать её снова и переспрашивать про срок.
   То же самое с вопросом «что вас останавливает». Через ход и дальше ссылку давать можно
   и нужно.
10. **Односложные ответы разбираем отдельно.** «Ок», «понятно», «спасибо» – не повод
    пересказывать сказанное. А «согласен», «беру», «давайте» – согласие, и здесь надо закрывать
    сделку, а не рассказывать дальше. Проверяйте реплику по словам: если все слова из короткого
    списка согласий, кладите в промпт соответствующую пометку.
11. **Голосовые и картинки.** Сообщение без текста нельзя просто выбрасывать – человек
    останется без ответа и даже не поймёт почему. Голосовое прогоняем через распознавание речи
    на сервере и подставляем как обычную реплику, картинку скачиваем и даём мозгу прочитать
    (для этого ему разрешается инструмент чтения файла именно на этот ход). Люди присылают
    скриншоты ошибок оплаты – по картинке бот сразу видит, что случилось, и отвечает по делу.
    Если вложение не разобралось, отвечаем человеку «напишите текстом», а не жалуемся
    оператору.
12. **О спорном случае узнаёт оператор.** Возврат денег, сбой оплаты, нестандартная просьба –
    эскалация (§4), оператору короткое сообщение с сутью.

---

## 7. Хранение диалогов

По каждому человеку – файл `dialogs/<площадка>_<id>.json`: площадка, имя, ник (если площадка
его даёт), почта и телефон (только если человек назвал их сам), история сообщений с ролями
и временем, стадия, состояние воронки (`funnel`: отправлена ли ссылка, обещанный срок, номер
напоминания, время следующего, сколько наших сообщений подряд без ответа, флаг «остановлено»),
флаг «эскалирован», время последнего сообщения человека (для окна Instagram, §17). История
в промпт – последние ~40 реплик, не весь файл.

---

## 8. Воронка и напоминания (это делает бота продавцом, а не консультантом)

Демоны реагируют на `lead_action` из ответа мозга:

- **`call_request`** – человек просит созвон или разбор. Напоминания стоп, оператору
  уведомление с именем, ссылкой на переписку и запросом. Дальше ведёт человек.
- **`link_sent`** – мы дали ссылку на оплату. Запускаем напоминания.
- **`payment_promised`** – человек назвал срок оплаты; сохраняем его дословно, запускаем
  напоминания.
- **`paid_claimed`** – 🔴 только когда с оплатой что-то не так: человек говорит, что заплатил,
  а доступа нет, или деньги ушли непонятно куда. Напоминания стоп, оператору – «проверьте
  оплату».
- **`sale_done`** – человек оплатил, и всё в порядке. Напоминания стоп, оператору короткое
  «💰 продажа», человеку – заранее заготовленный текст: куда идти, где чаты, с чего начать.
  🔴 Заведите эту метку отдельно от `paid_claimed` и `stop_followups`. Пока её не было,
  состоявшаяся продажа попадала в отчёт как «остановлен, просил не писать».
- **`stop_followups`** – попросил не писать / отказался. Больше не пишем этому человеку никогда.

**Напоминания (`followup.py`).** Отдельный цикл раз в ~5 минут проверяет, кому пора напомнить.
План в часах: после отправки ссылки – `[3, 24, 72, 168]` (через несколько часов, через сутки,
через два-три дня, через неделю), если до ссылки не дошли – `[2, 24, 72]`. После последнего
напоминания – тишина. Когда наступает время, демон будит мозг **системным событием** («человек
молчит N часов, это напоминание №K из 4»), и мозг сам пишет уместный текст. 🔴 Правила:

- Каждое напоминание несёт **новое** (аргумент, снятие барьера, вопрос), а не «ну что решили?».
  Повод берите из ЕГО разговора: вопрос, который он задавал, срок, который сам назвал.
  Одинаковое «страница открылась нормально?», разосланное шестерым, – это рассылка.
- 🔴 **Считайте не только напоминания, но и факт: сколько наших сообщений подряд осталось без
  ответа.** Счётчик напоминаний сбрасывается по дороге (например, когда мы отправили ссылку),
  и из-за этого человеку ушло семь сообщений подряд при формальном лимите в четыре. Защита –
  пять неотвеченных сообщений подряд, дальше тишина, даже если план ещё не кончился.
- 🔴 **Никаких прощальных обещаний в напоминаниях.** «Это последнее сообщение», «больше не буду
  напоминать» – запрещено: человек видит нарушенное слово. После четвёртого напоминания
  нейропродавец замолкает молча.
- Ночью не пишем (тихие часы, §6), без выдуманных дедлайнов и упрёков «вы не оплатили».
- Как только человек ответил – счётчики сбрасываются (разговор пошёл заново).
- 🔴 **Instagram:** писать можно только в течение суток после последнего сообщения человека.
  Поэтому там напоминаний два, и оба уходят в первые сутки: через 3 часа и через 20 часов
  после его последнего сообщения. Если время попало в тихие часы, сдвигай напоминание на утро,
  но только пока окно ещё открыто, иначе пропускай.

🔴 **Не напоминать тем, кто уже оплатил.** Перед каждым напоминанием сверка со списком
оплативших `paid.json` (§11).

---

## 9. Управление и безопасный запуск

- **Флаг-файлы** в папке продавца: `DRAFT` – бот не пишет людям, а присылает оператору
  черновик «вот что я бы ответил» (для обкатки без риска); `PAUSE` – полное молчание. Каждая
  новая площадка стартует в `DRAFT`.
- **Команды оператора** – с его личного Telegram-аккаунта в личку рабочему аккаунту (только
  с admin-id оператора): `пауза` · `работай` · `черновики вкл` · `черновики выкл` · `статус` ·
  `тест` (§10) · `отчёт` (§12) · `правь N` (§13).
- Все уведомления, эскалации, черновики и отчёты со всех площадок приходят оператору
  в Telegram: MAX, ВКонтакте и Instagram кладут их в `outbox/`, Telegram-демон забирает
  и пересылает (чтобы всё падало в один чат).
- **Admin-id оператора.** Попроси оператора написать рабочему аккаунту любое сообщение со своего
  личного Telegram, запиши его id в `.env` и принимай команды только с него.
- 🔴 **`черновики выкл` – только после тестовых переписок (§10) и подключённой сверки оплат
  (§11).** Первые дни бот работает в `DRAFT`: оператор читает черновики и сам решает, когда
  выключить.

---

## 9а. 🔴 Оператор разговаривает с ботом, а не только диктует реплики

Всё, что оператор пишет боту в личку, по умолчанию считается указанием передать клиенту.
Из-за этого у нас случился конфуз: на вопрос «а ты можешь переслать сюда переписку?» бот
написал КЛИЕНТУ «можно вас попросить: перешлите сюда нашу переписку целиком», и человек две
реплики выяснял, как это сделать в мессенджере. Оператор при этом ответа не получил.

Сделайте развилку. Перед тем как что-то передавать, отдельным быстрым запросом к мозгу
определите адресата:

- **клиенту** – оператор диктует реплику: «напиши ему, что…», «ответь, что оплату видим»,
  «передай», готовый текст для человека;
- **оператору** – он обращается к самому боту: спрашивает, просит показать переписку, разобрать
  диалог, объяснить решение, поправить правила, дать цифры.

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

В режиме разговора бот должен уметь читать переписки, файлы знаний и логи, считать по ним
и отвечать своими словами, а длинные ответы отдавать частями. Полезно хранить последние
20–30 реплик этого разговора отдельно, чтобы можно было обсуждать по цепочке, а не с чистого
листа. Правки файлов знаний из этого режима допустимы, но с копией файла в `backups/` перед
изменением.

---

## 9б. Уведомления оператору – только по делу

Живой оператор быстро перестаёт читать поток сообщений от бота. Присылайте только то, где без
человека не обойтись: эскалация, заявка, «человек говорит, что оплатил», продажа, сбой связи,
человек остался без ответа. Всё остальное – в лог и в утренний отчёт.

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

---

## 10. Тестовые переписки с трудными покупателями (`selftest.py`)

Черновики, которые оператор успеет прочитать за пару дней, ловят не всё. Поэтому, пока стоит
`DRAFT`, ты сам проверяешь нейропродавца: один раз сразу после настройки мозга и потом
по команде `тест`. Скрипт прогоняет через тот же мозг 8–10 выдуманных покупателей и никому
ничего не отправляет:

- «дорого»;
- «я подумаю»;
- «а есть гарантия?»;
- «оплачу потом» с размытым сроком;
- скептик: «а это вообще работает?»;
- односложное «беру»;
- вопрос, ответа на который нет в `facts.md` (ожидаем эскалацию, а не выдумку);
- сравнение с другим продуктом;
- просьба вернуть деньги (ожидаем эскалацию).

Каждый диалог 4–6 ходов. Реплики покупателя пишет отдельный вызов Claude в роли человека,
который спорит и сомневается. Потом ты проверяешь ответы нейропродавца по правилам
из `prompt.md`: ответ на возражение по формуле, одна рекомендация вместо списка, гарантия
не больше одного раза, нет выдуманных цен и сроков, нет допроса вопросами, согласие закрыто
ссылкой на оплату, род эксперта соблюдён. Где ответ слабый – правишь `prompt.md` (копия
в `backups/`) и прогоняешь тест снова. Оператору присылаешь итог: что было не так, что
поправлено, два-три примера ответов после правки.

---

## 11. Сверка оплат (`paid_sync.py`)

🔴 **Не напоминать тем, кто уже оплатил.** Раз в 15 минут скрипт обновляет `paid.json` из базы
оплат оператора. Спроси оператора, где его оплаты. Если платёжная система умеет присылать
уведомление о каждой оплате на адрес сервера (например, у Продамуса это URL для уведомлений),
подними на сервере приёмник уведомлений и пиши каждую оплату в журнал, а оператору скажи, какой
адрес вписать в настройках. Если уведомлений нет – выгрузка или таблица. Выгружайте не только ник, но и имя, почту, телефон, пакет, сумму и дату оплаты.

🔴 **Сверка по нику работает только там, где есть ники.** В MAX ников нет вообще, и защита
по нику там просто не срабатывает: у нас двое оплативших спокойно стояли в очереди на
напоминание, а человеку, купившему годовой пакет, бот даже не отправил письмо с доступами.
Поэтому сверяйте по всему, что есть:

- Telegram – ник, почта или телефон, которые человек назвал сам;
- MAX – почта или телефон, которые человек назвал сам (мозг естественно спрашивает почту,
  когда даёт ссылку на оплату);
- ВКонтакте – короткий адрес страницы, почта или телефон;
- Instagram – имя пользователя, почта или телефон.

🔴 **Но догадка не останавливает напоминания.** Совпадение по имени – это не доказательство:
в одном мессенджере на одну оплату нашлись три разных Александра. Останавливаем цепочку только
при точном сопоставлении, когда человек сам написал, что оплатил, или когда он отказался.
Во всех остальных случаях напоминаем дальше: лишнее напоминание оплатившему – мелкая неловкость,
а остановленная по догадке цепочка стоит вам клиента. Если человек всё-таки оплатил, он ответит
сам, и сработает `sale_done`.

---

## 12. Утренний отчёт (`report.py`)

Каждое утро в 09:00 по времени оператора (и по команде `отчёт`) оператору в Telegram приходит
сообщение. Считать вручную ему ничего не нужно.

- **За вчера и за всё время:** сколько человек написали, сколько ответили хотя бы раз, скольким
  ушла ссылка на оплату, сколько оплатили.
- **Конверсия** из сообщения в оплату и из ссылки в оплату.
- **Сумма продаж**, средний чек и **сколько приносит один написавший** (сумма продаж / число
  написавших).
- Те же цифры по каждой площадке отдельно: Telegram, MAX, ВКонтакте, Instagram. Одна площадка
  может продавать втрое лучше другой, и это видно только в разрезе.
- До пяти находок нейросети-контролёра (§13).

🔴 **Оплаты считаем по базе оплат, а не по меткам бота.** Бот ставит «продажу» со слов человека,
и часть оплат он не видит вовсе. Скрипт по почте и нику сам находит, из какой переписки пришла
каждая оплата. У нас при такой сверке нашлось четыре оплаты, о которых бот не знал: такие
переписки помечай `sale_done`, а в отчёте перечисляй отдельной строкой. Оплаты, которые
не удалось привязать ни к одной переписке, тоже отдельной строкой.

🔴 **Один платёж – одна оплата.** У нас нашёлся платёж, посчитанный дважды: отметка об оплате
ставилась по почте на все незакрытые заявки человека, а он оставлял заявку два раза. Выручка
в отчёте оказалась завышена на цену годового пакета. Привязывай платёж к одной переписке.

---

## 13. Нейросеть-контролёр (`controller.py`)

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

Раз в сутки, ночью перед отчётом, скрипт собирает все переписки, обновлённые за день, и пачками
отдаёт их `claude -p` со списком известных ошибок:

- иероглифы и длинное тире в отправленных сообщениях;
- не тот день недели, время или статус события;
- одна и та же фраза слово в слово ушла разным людям;
- ссылка или вопрос о сроке два хода подряд;
- каждое сообщение кончается вопросом (переписка превратилась в допрос);
- цены, скидки, сроки, «осталось N мест», которых нет в `facts.md`;
- прощальные обещания в напоминаниях;
- напоминание человеку, который уже оплатил;
- «беру» или «согласен» без ссылки на оплату;
- гарантия больше одного раза за разговор, список тарифов вместо одной рекомендации;
- не тот род («поняла» у эксперта-мужчины);
- человек остался без ответа.

Контролёр возвращает до пяти самых важных находок за день: цитата, площадка и ссылка
на переписку, какое правило нарушено, какую правку внести в `prompt.md`. Находки уходят
в утренний отчёт (§12) и сохраняются в `reports/`. Оператор отвечает `правь N` – ты вносишь
правку N в `prompt.md` (копия в `backups/`) и подтверждаешь. Новую ошибку, которой нет
в списке, контролёр добавляет в список сам.

---

## 14. Стабильность (чтобы не падал и не разлогинивался)

- **systemd-сервис** на каждый демон: `Restart=always`, `RestartSec=15`, логи в файл. Демоны
  переживают падение и перезагрузку сервера. `paid_sync.py`, `controller.py` и `report.py` –
  по таймерам systemd.
- 🔴 Ровно одна копия одной сессии Telegram (см. §3). Две копии = разлогин.
- 🔴 Отдельный Linux-пользователь под продавца, не смешивать с другими ботами.
- Токены и ключи – только в `.env` с правами 600, не в коде и не в логах.
- Логи – в `logs/`, чтобы было видно, что происходит и почему.

---

## 15. Подключение MAX (после Telegram)

MAX подключается отдельным демоном `max_seller.py`, **мозг и знания – те же самые** (импортируем
из `brain.py`, отдельно только транспорт):

- Бот в MAX создаётся у @masterbot, оператор присылает токен.
- 🔴 API: базовый адрес **`https://botapi.max.ru`**, заголовок `Authorization: <токен>` без
  «Bearer». Адрес `platform-api2.max.ru` из части документации с зарубежного сервера может не
  отвечать, а `?access_token=` в URL объявлен устаревшим.
- Транспорт: long polling `GET /updates`, отправка `POST /messages?chat_id=`.
- Уведомления оператору – через `outbox/` (§9).

---

## 16. Подключение ВКонтакте

Отдельный демон `vk_seller.py`, мозг и знания те же. Нейропродавец отвечает в сообщениях
сообщества оператора.

- Оператор в управлении сообществом включает **Сообщения**, в разделе **Работа с API** создаёт
  ключ доступа с правом на сообщения сообщества и включает **Long Poll API** с событием
  входящего сообщения. Ключ и id сообщества присылает тебе. Если он не найдёт нужный пункт,
  проведи его по экрану шаг за шагом.
- Транспорт: Bots Long Poll API (`groups.getLongPollServer`), отправка `messages.send`
  с `peer_id` и уникальным `random_id`, статус «печатает» – `messages.setActivity`.
- Голосовые сообщения приходят вложением с аудиофайлом: скачиваем и распознаём (§6, п. 11).
- Писать можно только тем, кто сам написал сообществу. Уведомления оператору – через `outbox/`.

---

## 17. Подключение Instagram

Отдельный демон `ig_seller.py`, мозг и знания те же.

- Нужен **профессиональный аккаунт** Instagram (бизнес или автор) и приложение в кабинете
  разработчика Meta с продуктом Instagram API (вход через Instagram) и правами
  `instagram_business_basic` и `instagram_business_manage_messages`. Проведи оператора
  по созданию приложения и получению токена, шаги давай по одному.
- Сообщения приходят **через webhook**: нужен публичный адрес HTTPS на сервере (домен,
  сертификат, nginx перед `ig_seller.py`), подтверждение webhook и подписка на событие
  `messages`. Отправка ответа и статуса «печатает» – через Graph API, метод
  `/{ig-user-id}/messages`.
- 🔴 **Окно 24 часа:** отвечать и напоминать можно только в течение суток после последнего
  сообщения человека. Поэтому напоминаний два, и оба уходят в первые сутки (§8).
- Токен долгоживущий, но со сроком действия: поставь автопродление и уведомление оператору,
  если продлить не удалось.
- Пока приложение Meta не прошло проверку (App Review) на расширенный доступ, бот отвечает
  только аккаунтам, добавленным в приложение. Чтобы он отвечал всем, подготовь оператору всё
  для заявки на проверку и проведи по ней.
- API Meta из России не открывается: этот демон работает только на сервере за пределами России.
  Проще всего держать весь нейропродавец на одном зарубежном сервере (Telegram, MAX и ВКонтакте
  оттуда работают). Если основной сервер в России, предложи оператору перенос или отдельный
  зарубежный сервер под `ig_seller.py` и согласуй выбор с ним.
- Уведомления оператору – через `outbox/`.

---

## 18. Продающий мозг: как заполнить знания

Оператор присылает файл `prompt-prodazha.md` и описание своего продукта: название, цена, что
внутри, гарантия, ссылка на оплату.

- Переложи `prompt-prodazha.md` в `knowledge/prompt.md`, подставь имя эксперта, род («проверил»
  или «проверила») и продукт во все места, где стоят квадратные скобки.
- Собери `facts.md`: цены, условия, гарантия, сроки, ссылка на оплату. Только то, что прислал
  оператор. Чего нет – спроси, не придумывай.
- Подробное описание продукта – в `product.md`, слова-триггеры к нему – в `triggers.txt` (§5).
- 🔴 Правил в `facts.md`, `product.md` и `triggers.txt` нет (§2).

---

## 19. Железные правила продаж (сами правила – в `prompt.md`, здесь – что проверять кодом)

Эти правила – в текстовых знаниях бота, но перечислю, чтобы ты заложил проверки и учёл их
в тестах (§10) и контролёре (§13):

- Пишем от лица эксперта, на «вы». На прямой вопрос «это бот?» – честно «я ассистент, эксперт
  подключится лично», и эскалация.
- В каждом сообщении – продающий элемент и **следующий шаг**. 🔴 Шаг не обязан быть вопросом:
  предложение действия или конкретная подсказка тоже считаются. Вопросом заканчивать каждое
  сообщение нельзя – разговор превращается в допрос.
- Гарантия/снятие риска – 🔴 максимум один раз за разговор и только когда человек боится
  потерять деньги. Приклеенная к каждой ссылке, она звучит как заученная страховка; сказал,
  что возврат не интересен, – не упоминаем вообще.
- 🔴 Если у продукта несколько тарифов, бот рекомендует ОДИН под задачу человека, а не выдаёт
  список с вопросом «какой ближе?». Развилка перекладывает выбор и уводит человека думать.
- 🔴 Заученные формулировки запрещены. Фразы, которые бот повторяет слово в слово, контролёр
  находит (§13), и они попадают в `prompt.md` как запрещённые: за сутки один и тот же вопрос
  про сомнения ушёл десяти разным людям.
- 🔴 Про оплату говорим только при точном сопоставлении (§11). Совпадение по имени – не
  основание: чужая покупка, названная постороннему, убивает доверие мгновенно.
- Никаких выдуманных скидок, дедлайнов, «осталось 3 места», обещаний дохода.
- Не выдумывать факты о продукте – только из `facts.md` и `product.md`. Чего нет – эскалация.
- Не просить и не принимать номера карт, паспорта, пароли.

---

## 20. Что остаётся оператору после запуска

Читать переписки и считать оплаты оператору не нужно: это делают контролёр (§13) и утренний
отчёт (§12). Оператор читает отчёт, отвечает `правь N` на находки, с которыми согласен,
и отвечает на эскалации. Если отчёт показывает, что одна площадка продаёт заметно хуже других,
разбери её переписки сам и предложи правки.

---

## 21. Порядок сборки

1. Telegram: `brain.py`, `seller.py`, защиты (§6), напоминания (§8), systemd. Запуск в `DRAFT`.
2. Оператор присылает `prompt-prodazha.md` и описание продукта: заполни знания (§18).
3. Тестовые переписки (§10), правки `prompt.md`, итог оператору.
4. Сверка оплат (§11).
5. Утренний отчёт (§12) и контролёр (§13).
6. Скажи оператору, что можно отправить `черновики выкл`. После команды нейропродавец отвечает
   людям.
7. MAX (§15), ВКонтакте (§16), Instagram (§17) – по одной площадке, когда оператор пришлёт
   ключи. Каждая стартует в `DRAFT`, мозг общий.
