Зачем: путеводитель рассказывает путь данных через слои словами, а карта дает его увидеть и потрогать: у одного смысла в каждом слое свое имя и своя поверхность, а переносят данные три разных механизма — матвью непрерывно, даг пачкой, представление без копии. Постановка — тикет #222, форма — резолюция #208 (один самодостаточный HTML, исходники рядом). Что: docs/handbook/architecture-map.html — готовая карта; исходники в docs/handbook/architecture-map/ (map.yaml — слои, узлы, стрелки, карточки; template.html — разметка, стили, скрипт; render.py — сборка и --check; README.md). Щелчок по узлу открывает карточку и подсвечивает путь, щелчок по стрелке — кто и каким SQL переносит данные; переключатель потока приглушает чужую часть карты. Ссылки карточек ведут в справочники и DDL на Gitea. Путеводитель и глава о хранилище ведут на карту; make lint проверяет ruff для сборщика и свежесть рендера; testing.md и AGENTS.md обновлены. Проверка: uv run docs/handbook/architecture-map/render.py --check и make lint зеленые; внешних запросов в HTML нет; ссылки и якоря карточек сверены с Gitea; карта прощелкана в headless Chromium на ширинах 1280–1920: подсветка пути, фильтр, Esc, карточки узлов и стрелок. Ревью: постановка — Opus; реализация — Codex (Sol), два слепых ревью Opus (уместность и код), вычитка прозы Sol.
180 lines
15 KiB
Markdown
180 lines
15 KiB
Markdown
# AGENTS.md
|
||
|
||
Короткий контракт для работы в репозитории учебной дата-платформы кликстрима.
|
||
|
||
## Цель репозитория
|
||
|
||
Проект учебный: учебная ценность разработок — одна из его базовых ценностей.
|
||
Стенд строится по спеке
|
||
[«Боевой реализм стенда (v2)»](docs/specs/2026-07-30-stand-v2-realism.md).
|
||
|
||
Отсюда вопрос к любой доработке — коду, проверке, документу: **чему на ней
|
||
научится менти?** Ответ называется одной фразой до того, как писать. Не
|
||
складывается фраза — это вопрос владельцу, а не строчка кода: проверки в этом
|
||
репозитории однажды уже переросли продукт.
|
||
|
||
**Усложнение не бесплатно, и платит за него учебная ценность.** Чем сложнее
|
||
стенд, тем хуже он как учебный материал: внимание менти конечно, и каждая
|
||
конструкция, которую он обязан расшифровать по дороге к уроку, списывается с
|
||
этого счёта. Поэтому вопрос выше имеет вторую половину: **что менти платит,
|
||
чтобы это прочесть, и что получает взамен?** Ответ «вопрос — и ничего»
|
||
означает, что писать не нужно.
|
||
|
||
Оборонительный код дороже прочего. Читатель не отличает «стоит здесь, потому
|
||
что есть настоящая опасность» от «стоит здесь, потому что кто-то был
|
||
остроумен», — и предполагает первое. Лишний сторож не безобиден: он
|
||
утверждает, будто опасность заслуживает внимания, и этим врёт. Особенно это
|
||
касается защиты от ошибки, которую человек делает сам себе и тут же видит:
|
||
разбирательство с ней и есть урок, отнимать его не надо.
|
||
|
||
Ревью само по себе умеет только прибавлять: каждая находка просится в правку,
|
||
и за прогон их набираются десятки. Поэтому перед приёмкой заметной работы
|
||
идёт отдельный **проход на вычитание** — с правом только резать и с явным
|
||
списком неприкосновенного. Сомнение «резать или нет» решается в пользу
|
||
реза: вещь, которая себя не защитила, себя не защитила.
|
||
|
||
## Кому что поручать
|
||
|
||
Читатель здесь не побочный потребитель, а тот, ради кого стенд существует:
|
||
код, комментарии и документы и есть продукт. Поэтому всё, что человек будет
|
||
читать и разбирать, пишет модель с чувством меры — сейчас это Opus. Codex
|
||
берёт техническую работу без вкусовых решений: миграции, разбор журналов и
|
||
объёмного вывода, обход репозитория, повторяющиеся правки. Там его запас
|
||
лимитов работает на нас, а экономить их на читаемом коде — экономия ложная:
|
||
переписывать выйдет дороже, чем сразу написать хорошо.
|
||
|
||
Делить работу между ними стоит не целыми задачами, а подзадачами, и решать
|
||
это при планировании. Вкусовая часть идёт первой: она задаёт форму, имена и
|
||
границы, под которые механическая потом подстраивается.
|
||
|
||
Ревью держит две линии, и назначаются они по разным основаниям. Линию
|
||
дефектов ведёт тот, кто код не писал: здесь работает различие — разные
|
||
родословные промахиваются по-разному. Линию уместности назначает не
|
||
различие, а умение: её ведёт модель со вкусом, даже если она же писала код.
|
||
Отдать её «второму исполнителю» ради независимости заманчиво, но модель без
|
||
вкуса на этой линии бесполезна.
|
||
|
||
Плата у такого решения есть: общая слепота автора и ревьюера одной
|
||
родословной проходит дважды. Гасится она свежей сессией без общего контекста
|
||
и явно другой линзой, но не до конца — поэтому там, где цена ошибки этого не
|
||
терпит, линию уместности берёт третья модель.
|
||
|
||
## Язык
|
||
|
||
Пиши на ясном русском языке. Иностранные слова оставляй только там, где у
|
||
термина нет устоявшегося русского аналога: имена технологий (Kafka, ClickHouse,
|
||
Airflow) и названия из кода. Если для понятия есть обычное русское слово —
|
||
используй его, не выдумывай транслитерации.
|
||
|
||
Документы и комментарии держи короткими и понятными читателю, который их не
|
||
писал: простые слова, короткие фразы, сложную мысль поясняй при первом
|
||
упоминании. Если понятность и буквальная точность спорят — выбирай понятность.
|
||
|
||
Внутренние рассуждения и промежуточные пометки по ходу работы веди на
|
||
английском — он экономнее по токенам. На русском остаётся всё, что видит и
|
||
хранит проект: итоговые ответы, документы, комментарии в коде и SQL, сообщения
|
||
коммитов.
|
||
|
||
## Код и данные
|
||
|
||
- Python — только через `uv`; проверка и формат — `ruff`. Цель `make lint`
|
||
есть за двумя дверями и охватывает разное: в корне — код стенда, в
|
||
`generator/` — код генератора. Правишь даги или Superset — зови корневую,
|
||
правишь генератор — зови из `generator/`.
|
||
- Изменения держать минимальными и в границах задания.
|
||
- `make clean` полностью удаляет постоянное состояние стенда. Перед этой
|
||
командой назови состояние вне прикладного мира, которое требуется удалить,
|
||
и объясни, почему `make rebuild-storage` его не удаляет. При изменении DDL
|
||
или проверке на чистых данных по умолчанию используй адресную очистку либо
|
||
`make rebuild-storage`.
|
||
- Куда класть новую проверку, что утверждает каждая цель `make` и почему смоук
|
||
обязан оставаться быстрым — [`docs/architecture/testing.md`](docs/architecture/testing.md).
|
||
- Секреты не коммитить: настройки — через `.env`, образец — `.env.example`.
|
||
- При изменении инфраструктуры или DDL обновлять документацию тем же PR.
|
||
- Коммиты — Conventional Commits: заголовок `type(scope): результат`, тело на
|
||
русском по схеме Зачем / Что / Проверка.
|
||
- «Грязные» записи не должны валить пайплайн: ошибки разбора уходят в таблицы
|
||
`*_errors`.
|
||
- Данные не читать целиком без необходимости: по умолчанию малый срез. Для
|
||
демо и тестов быстрый повторяемый прогон важнее полноты данных.
|
||
|
||
## Проверка API через MCP Context7 (обязательно)
|
||
|
||
Для спорных или меняющихся API (Airflow и провайдеры, DDL ClickHouse) сначала
|
||
уточнять актуальную версию: `resolve-library-id` -> `query-docs`. Принятое
|
||
решение кратко фиксировать в коде или документации: что проверили и почему
|
||
выбрали этот вариант.
|
||
|
||
## Задачи
|
||
|
||
Трекер — Gitea на `git.dementev.space`, работа через CLI `tea` (логин по
|
||
умолчанию настроен, репозиторий определяется по git remote). Команды и
|
||
подводные камни — в [`docs/agents/issue-tracker.md`](docs/agents/issue-tracker.md).
|
||
|
||
- Спека фичи — файл в `docs/specs/`, источник истины, версионируется с кодом.
|
||
- Корневой issue фичи — тонкий: ссылка на спеку и чек-лист дочерних issues
|
||
(`- [ ] #NN`). Содержание спеки в issue не дублируется.
|
||
- Дочерние issues — самодостаточные постановки: цель, критерии приёмки
|
||
чекбоксами, границы, «сначала прочитать», команды проверки.
|
||
- Итоговые решения переносятся в спеку или ADR тем же PR.
|
||
- Метки триажа — пять ролей: `needs-triage`, `needs-info`, `ready-for-agent`,
|
||
`ready-for-human`, `wontfix`. Карта и её тикеты — метки `wayfinder:*`.
|
||
|
||
## Agent skills
|
||
|
||
### Развилки решений
|
||
|
||
Существенные развилки — в грилинге, на тикетах wayfinder-карт и вне их —
|
||
вести через скилл `brainstorm-with-docs`: сначала веер вариантов, потом
|
||
конвергенция. Состав веера и запись отклонённых вариантов — в самом скилле.
|
||
|
||
### Issue tracker
|
||
|
||
Задачи — в Gitea на `git.dementev.space`, все операции через CLI `tea`.
|
||
См. [`docs/agents/issue-tracker.md`](docs/agents/issue-tracker.md).
|
||
|
||
### Triage labels
|
||
|
||
Пять канонических меток триажа без переименований, уже заведены в трекере.
|
||
См. [`docs/agents/triage-labels.md`](docs/agents/triage-labels.md).
|
||
|
||
### Domain docs
|
||
|
||
Один контекст: `CONTEXT.md` в корне и `docs/adr/`.
|
||
См. [`docs/agents/domain.md`](docs/agents/domain.md).
|
||
|
||
## Структура
|
||
|
||
- Новые документы — в `docs/` или в профильных подпапках, не в корне.
|
||
- Состав доков v2 определяется по ходу этапов, набор предшественника не
|
||
копируется (спека, раздел 12).
|
||
- Имена файлов в `docs/specs/` и `docs/research/` — `ГГГГ-ММ-ДД-краткое-имя.md`:
|
||
дата создания документа и слаг строчными латинскими буквами через дефис
|
||
(`2026-07-30-stand-v2-realism.md`). Дата фиксирует, когда документ появился,
|
||
и при правках не меняется: файлы сортируются по времени, а история живёт
|
||
в git.
|
||
- Имена файлов в `docs/formats/` — слаг строчными латинскими буквами через
|
||
дефис (`clickstream-event.md`). Ни даты, ни номера: документ не событие
|
||
истории, а текущее описание живого формата — и собирается из кода, а не
|
||
пишется руками.
|
||
- Имена файлов в `docs/labs/` — слаг строчными латинскими буквами через дефис
|
||
(`top-pages-daily.md`), индекс папки — `README.md`. Здесь живут ТЗ учебных
|
||
заданий. Ни даты, ни номера: задание — не событие истории, а живой документ,
|
||
и правится он вместе с тем, о чем говорит. Слаг называет предмет задания.
|
||
- Имена файлов в `docs/handbook/` — слаг строчными латинскими буквами через
|
||
дефис, индекс папки — `README.md`. Здесь живет путеводитель по стенду:
|
||
учебные главы для менти. Ни дат, ни номеров: глава — живой документ и
|
||
правится вместе с тем, что описывает. Исходники интерактивной карты лежат
|
||
подпапкой `architecture-map/`, а ее рендер — файлом `architecture-map.html`
|
||
рядом с главами.
|
||
- Имена файлов в `docs/adr/` — `NNNN-краткое-имя.md`: сквозной номер из четырёх
|
||
цифр и слаг (`0001-stand-services.md`). Решения нумеруются подряд, дата
|
||
в имени не нужна.
|
||
- Имена файлов в `docs/architecture/` — слаг строчными латинскими буквами через
|
||
дефис (`storage.md`). Здесь живут рабочие справочники по зонам
|
||
ответственности: не событие истории и не решение, а текущее устройство —
|
||
один файл на зону, правится по мере постройки. Крупный компонент живёт
|
||
подпапкой: индекс `README.md` и файл на каждую часть устройства
|
||
(`architecture/orders/`), имена по тому же правилу
|
||
([ADR 0011](docs/adr/0011-component-docs.md)).
|