# Радар объявлений: подготовка к проекту, а не проект

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

Кейс, с которого всё списано: человек под ником Штанга собрал за вечер конвейер,
который читал десяток испанских площадок, склеивал дубли, оценивал каждую машину
регрессией и слал находки в телеграм. Из 3 825 объявлений получилось 2 476 машин,
из них 251 «сделка», из них 66 подходящих, из них куплена одна — Jaguar F-Pace
2018 за €16 990 при расчётных €23 000.

Повторить это на российских площадках нельзя копипастой: сайты другие, защита
другая, данные другие. Поэтому здесь не «сделай так», а «выясни вот это, проверь
вот на этом, и только потом планируй».

**Как пользоваться.** Положи файл в корень пустой папки, открой её в Codex или
Claude Code на самой свежей модели и скажи: «прочитай CAR-RADAR-RU.md и веди меня
по нему». Скажи сразу, какую машину рассматриваешь. Агент должен начать с
интервью, а не с кода.

---

## Правило номер один

**Пока не пройдены шаги 0–4, никакого кода, кроме одноразовых проверок.**

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

---

## Шаг 0. Интервью. Ведёт агент, отвечает человек

Не переходи дальше, пока в `state.md` не записаны ответы на всё это. Спрашивай по
одному вопросу, не списком: списком человек отвечает односложно.

**Про машину**

1. Какая именно машина? Марка, поколение, годы, мотор, коробка, привод.
2. Почему эта? Ответ «нравится» не годится. Нужно: что она делает лучше соседей
   по цене и что ты готов терпеть взамен.
3. Какие у неё известные болячки в этом поколении и на этом моторе? Если человек
   не знает — это первое исследование, а не повод пропустить вопрос. Записать
   отдельно: пробеги, на которых болячка вылезает, и сколько стоит её лечить.
4. Что для тебя стоп-фактор? Такси, каршеринг, залог, перебитый номер, три
   владельца за год, кузовной ремонт. Список должен быть конечным.
5. Бюджет: нижняя и верхняя граница. Верхняя — с деньгами на ремонт после покупки
   или без?
6. Где смотришь: свой город, соседние области, вся страна? Готов ли ехать за
   машиной и как далеко.
7. Срок. «Куплю в течение месяца» и «присматриваюсь полгода» — это два разных
   проекта, и второй чаще всего не надо строить вообще.

**Про то, зачем нужна система**

8. Сколько объявлений по твоим критериям сейчас на рынке? Пусть человек откроет
   площадку и посмотрит. Если их меньше двух сотен, скажи прямо: система не
   нужна, хватит сохранённого поиска с уведомлениями.
9. Что именно ты делаешь руками, и что в этом больно? Не «долго», а конкретно:
   листать, сравнивать, помнить цену, ловить свежие, проверять историю.
10. Что будет считаться успехом? «Нашёл машину дешевле рынка» — не цель, а
    формулировка «за две недели получил десять машин, которые стоит смотреть, и
    ни одну не пропустил» — цель.

**Про то, что человек тянет**

11. Умеешь ли ты читать код настолько, чтобы понять, почему парсер перестал
    работать? Если нет — проект придётся строить так, чтобы его чинил агент по
    твоей команде, а не ты руками. Это другая архитектура.
12. Есть ли машина, которая может работать круглосуточно? Ноутбук, который
    закрывают на ночь, — не она.
13. Готов ли платить за прокси, если без них не выйдет? Порядок — несколько сотен
    рублей в месяц. Если нет — часть площадок отпадёт, и это надо принять сейчас,
    а не через неделю.

**Стоп-сигналы.** Если человек не может назвать ни одной болячки своей машины, не
знает, сколько сейчас объявлений, и хочет «чтобы система сама покупала» — не
строй. Проведи с ним исследование по машине, и на этом остановись. Это тоже
результат.

---

## Шаг 1. Проверка на дурака

Пятнадцать минут. Всё, что не сходится, записывается в `state.md` в раздел
«упёрлись».

- `node --version` — 20 или свежее.
- `git --version`, настроены `user.name` и `user.email`.
- Аккаунт на гитхабе, пустой приватный репозиторий создан, `git push` из этой
  папки проходит.
- Подписка на агента активна, лимиты не выбраны.
- Место на диске: хотя бы гигабайт под кэш страниц.
- `curl -sI https://auto.drom.ru/` отвечает 200. Если нет — дальше идти незачем,
  разбираемся с сетью.

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

---

## Шаг 2. Файлы состояния. Заводятся до первой строчки кода

Смысл: **новый чат не должен начинать с нуля.** Агент теряет контекст, ты
закрываешь вкладку, через три дня возвращаешься — состояние проекта живёт в
файлах и в гите, а не в переписке.

```
repo/
  CAR-RADAR-RU.md      этот файл, не меняется
  state.md             что сделано, что следующее, где упёрлись
  agents.md            правила для агента: что можно, что нельзя
  decisions.md         принятые решения и почему именно так
  research/
    car.md             машина: болячки, на что смотреть, чего бояться
    sites.md           площадки: что отдают, что закрыто, чем защищены
    legal.md           что говорят пользовательские соглашения
  data/                выгрузки, в гит не едут
  scripts/             одноразовые проверки
```

**`state.md`** — единственный файл, который агент перечитывает первым в каждом
новом чате и дописывает в конце каждого. Формат жёсткий:

```markdown
# Состояние на <дата>

## Машина
<что выбрали и почему, одной строкой>

## Сделано
- [x] интервью
- [x] проверка на дурака
- [ ] разведка площадок

## Следующий шаг
<ровно один, конкретный>

## Упёрлись
<что не работает и что пробовали>

## Числа
<сколько объявлений нашли, сколько полей заполнено, сколько времени ушло>
```

**`agents.md`** — правила, которые агент обязан соблюдать. Минимум:

```markdown
- Начинай с чтения state.md. Заканчивай его дописыванием.
- Не пиши код, пока шаг не описан в state.md как следующий.
- Каждая проверка — отдельный маленький скрипт в scripts/, а не правка большого.
- Сырые выгрузки в data/, в гит не коммитим.
- Ничего не удаляй без спроса. Файлы исследований не переписывай — дописывай.
- После каждого закрытого шага: git add -A, коммит с человеческим сообщением, push.
- Если упёрлись — пиши в state.md раздел «упёрлись» и останавливайся, а не
  обходи препятствие своими силами.
```

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

---

## Шаг 3. Разведка площадок. Читаем, не парсим

Задача — не собрать данные, а понять, где они вообще есть. Пишем в
`research/sites.md`.

Российские площадки, с которых начинают:

- **Авто.ру** — самая полная выдача по иномаркам, есть фильтры по всему.
- **Авито Авто** — самый большой объём, много частников.
- **Дром** — сильнее в регионах и по восточным машинам, отдаёт страницы проще
  остальных.
- Телеграм-каналы перекупов — сюда машина попадает раньше, чем на площадки.
- **Автотека**, **Автокод** — не объявления, а история по VIN. Платно, поштучно.
- Реестр залогов ФНП, проверка ограничений ГИБДД — бесплатно, по одной машине.

По каждой площадке ответить письменно:

1. Сколько объявлений по критериям человека прямо сейчас? Просто открыть и
   посмотреть число в выдаче.
2. Что видно в списке, а что только в карточке? Пробег, VIN, число владельцев,
   тип продавца.
3. Отдаётся ли страница обычным `curl`, или нужен браузер? Проверить руками:
   `curl -s '<адрес выдачи>' | wc -c`. Если пришло меньше нескольких десятков
   килобайт — страница рисуется скриптом, нужен настоящий браузер.
4. Что говорит пользовательское соглашение про автоматический сбор? Найти пункт,
   выписать дословно в `research/legal.md`. У всех крупных площадок он есть.
5. Есть ли официальный способ получить данные: API для продавцов, выгрузки,
   партнёрские фиды.

**Отдельным абзацем в `legal.md`:** обход антибот-защиты и автоматический сбор в
обход соглашения — это не «серая зона». Для личного поиска в один поток риск
один, для сервиса на продажу — другой. Решение принимает человек, а не агент, и
записывается в `decisions.md` с датой.

---

## Шаг 4. Минимальный шаг. Один сайт, один запрос, один файл

Цель — за час получить ответ: реально ли вообще достать эти данные. Не система, а
проверка.

**Что делаем.** Один скрипт. Одна площадка — та, что в разведке оказалась самой
открытой. Один поисковый запрос — ровно по критериям человека. Первая страница
выдачи. Складываем в `data/probe.json`.

**Что должно получиться.** Пятьдесят строк, в каждой: марка, модель, год, пробег,
цена, ссылка, город, дата объявления.

**Что проверяем на этих пятидесяти строках** — это и есть маленькое исследование,
ради которого шаг существует:

1. Сколько полей заполнено? Если пробег есть у сорока из пятидесяти, а VIN у
   пяти — это меняет весь проект: модель цены на таких данных считать нечем.
2. Сколько дублей? Одна машина под разными объявлениями. Посчитать руками по
   связке «год + пробег + цена». Если дублей треть — склейка становится первой
   задачей, а не последней.
3. Есть ли цена у всех? «Цена по запросу» ломает любую оценку.
4. Сколько объявлений младше недели? Это скорость рынка. Если за неделю
   обновляется пять процентов, проверять чаще раза в сутки незачем.
5. Сколько времени занял один проход и сколько запросов ушло? Отсюда считается,
   выдержит ли площадка регулярный обход.

**Записать в `state.md` числами.** Не «данные грязноватые», а «пробег у 40 из 50,
VIN у 5 из 50, дублей 12».

**Стоп-условие.** Если страница не отдаётся, если данных в списке почти нет, если
дублей больше половины — останавливаемся и возвращаемся к человеку с этими
числами. Возможно, проект не нужен. Это нормальный исход, и он стоил одного часа,
а не двух недель.

---

## Шаг 5. Только теперь план

План пишется в `decisions.md` и отвечает на пять вопросов. Каждый ответ опирается
на числа из шага 4, а не на общие соображения.

1. **Сколько площадок в первой версии?** Ответ почти всегда «одна». Вторая
   добавляется, когда первая работает неделю без починки.
2. **Как часто ходим?** Из скорости рынка, а не из желания. Раз в сутки — почти
   всегда достаточно.
3. **Где живёт база?** На первом шаге — один файл. SQLite появляется, когда файл
   перестаёт открываться, а не раньше.
4. **Чем считаем цену?** Пока объявлений меньше трёхсот и половина полей пустая —
   ничем. Медиана по году и пробегу честнее регрессии на грязных данных. Регрессия
   имеет смысл, когда набралось несколько сотен строк с заполненными полями, и
   тогда её средняя ошибка — первое, что надо померить и записать.
5. **Что человек видит на выходе?** Сначала — таблица в файле. Дашборд появляется,
   когда таблица перестаёт помещаться в голову.

**Правило, которое экономит больше всего:** каждый следующий шаг должен занимать
не больше дня и заканчиваться чем-то, что человек может посмотреть. Если шаг
занимает три дня и в конце «ну, оно теперь на бэкенде» — шаг разбит неправильно.

---

## Дашборд, когда до него дойдёт

Не раньше, чем таблица перестанет читаться глазами. Что в нём должно быть, видно
по кейсу Штанги:

- **Список с сортировкой по разрыву** — главная страница. Рядом с разрывом всегда
  вторая колонка: насколько машина отвечает требованиям. Дешёвая машина не по
  требованиям — мусор в уведомлениях, а не находка.
- **Карточка машины**: цена продавца, расчётная цена, история цены по каждой
  площадке, где она висит, и флаги риска отдельным блоком.
- **Флаги важнее скидки.** «История неизвестна», «владельцы не указаны», «про
  аварии молчат» — это то, из-за чего минус семьдесят процентов оказывается не
  находкой, а вопросом.
- **Уведомление** приходит только на то, что прошло оба фильтра. В нём: обе цены,
  разрыв, пробег, мотор и все площадки, где машина висит одновременно.

Оформление, если делаете в моей стилистике:

- Тёмная бумага, никакой рамки вокруг графика, никакой панели-легенды сбоку.
- Заголовок рубленым, подзаголовок моноширинным, подписи — обычный текст, а не
  подрисуночные микроскопические буквы.
- Цвета пастельные и малочисленные: серый — рынок, зелёный — находка, красный —
  флаг. Яркий акцент только на том, ради чего всё считается.
- У каждого числа подписана его точность. Модель, у которой не написана средняя
  ошибка, всегда выглядит убедительнее, чем есть.
- Горизонтальные полосы вместо круговых диаграмм. Всегда.

---

## Грабли, которые автор кейса называет сам

- **Антибот не решается один раз.** Защита обновляется, парсер ложится, его чинят,
  через месяц он ложится снова. Эта работа не исчезает из сметы.
- **Данные грязные.** У половины объявлений нет истории обслуживания. Модель
  считает по тем полям, что есть, и цифра на выходе выглядит такой же уверенной,
  как везде.
- **Ошибка растёт там, где цена ошибки выше.** На редких машинах выборка меньше, и
  средняя ошибка оценки на них была втрое больше, чем на массовых.
- **Модель не видит машину.** Ни убитой подвески, ни скрученного пробега, ни
  свежекрашеного крыла. Скидка бывает находкой, а бывает суммой предстоящего
  ремонта, и решает это подъёмник, а не конвейер.

---

## Чего этот проект не делает

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

Он делает ровно одно: превращает тысячи объявлений в десяток, которые имеет смысл
посмотреть глазами. У Штанги из 3 825 объявлений до звонка дошло 66. Дальше он
ехал сам.
