# Правила для кодинг-агентов

Читай этот файл **до** первой правки в Russiano2D. Здесь не пожелания, а
условия приёмки работы: правила 1–10 — ограничения, «Рабочий цикл» — порядок
действий, «Стоп-условия» — когда нужно остановиться и спросить, а не
импровизировать.

Связанные документы: [PHILOSOPHY.md](PHILOSOPHY) (конституция),
[UI_RMLUI_LAW.md](UI_RMLUI_LAW) (закон UI), [ROADMAP.md](ROADMAP) (порядок
работ), [TESTING.md](TESTING) (как проверять).

---

## Правило 1 — Существующий код побеждает

Russiano2D — существующий движок. Прежде чем что-то писать:

1. найди существующий код по теме;
2. прочитай его;
3. прочитай его документацию (`docs/`, `docs/highlevel/<имя>.md`);
4. найди его тесты (`tests/js/*_test.mjs`, `tests/agent/*_test.py`);
5. пойми публичный API;
6. и только потом проектируй изменение.

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

## Правило 2 — Никакой смены архитектуры без явной просьбы

Нельзя самостоятельно решать: переписать движок, перейти на C++, ввести ECS,
заменить QuickJS-ng, SDL, RmlUi, перепроектировать `$`, добавить второй
UI-фреймворк. Если это объективно блокирует задачу — опиши блокер, не обходи
его сменой архитектуры ([PHILOSOPHY.md](PHILOSOPHY) §3).

## Правило 3 — Сохраняй совместимость

Существующие игры должны продолжать работать. Если публичное поведение
обязано измениться: объясни причину, добавь заметки о миграции, добавь тесты и
не ломай ничего попутного.

## Правило 4 — ВЕСЬ UI — RmlUi

Не обсуждается. Никаких ImGui «временно», никаких нативных кнопок «просто для
теста», никакого второго developer GUI. Нативные custom-элементы допустимы
только как специализированное содержимое **внутри** RmlUi. Полностью —
[UI_RMLUI_LAW.md](UI_RMLUI_LAW).

## Правило 5 — Горячие пути — нативные

Избегай поштучных переходов C↔JS там, где движок умеет массовую операцию:

```js
// плохо: N переходов на кадр
$('.enemy').each(e => expensivePerEntityBridge(e));
```

Предпочитай декларативные и пакетные операции. Покадровый проход по узлам `$`
— кандидат в C (`src/nodes.c`): C читает поля узла через атомы за ≈4 нс, а
интерпретатор тратит на тот же узел микросекунды. Такой проход повторяет
JS-математику один в один и сверяется тестом «C против JS»
(`tests/agent/native_passes_test.py`, `$.debug.nativePasses(false)`). Но и
обратное неверно: **не тащи произвольную игровую логику в C**.

## Правило 6 — Измеряй

Прежде чем утверждать «стало быстрее»: замерь старое поведение, замерь новое,
запиши число объектов и конфигурацию сборки. Архитектурная интуиция — не
доказательство. Готовые инструменты: `$.debug.profile()`,
`tools/bench_highlevel.py`, `--stats`.

## Правило 7 — Детерминированные тесты

Новые возможности запросов/агента/реплея получают автотесты, где это
осуществимо: фиксированный шаг, известное зерно, управляемое состояние мира.
См. [TESTING.md](TESTING).

## Правило 8 — Структурированные данные для отладки

Машинно-ориентированные API возвращают структуру, а не декоративный вывод:
агент не должен разбирать текст терминала.

## Правило 9 — Никакой выдуманной диагностики

Диагностика сообщает **только факты, известные движку**. Движок не сочиняет
спекулятивных объяснений — рассуждение принадлежит вызывающей стороне.

```json
// хорошо
{ "visible": false, "blockedBy": "wall_42" }

// плохо
{ "reason": "Стражник, похоже, не видит игрока, потому что растерялся." }
```

## Правило 10 — Сохраняй R2D приятным

Обычный код игры должен выглядеть как R2D, а не как корпоративная
инфраструктура:

```js
$.ready(() => {
    $('<player>', { id: 'hero' }).at(100, 300).health(100).appendTo($.world);
    $('.enemy').each((i, e) => { if (e.distanceTo('#hero') < 200) e.damage(1); });
});
```

---

## Рабочий цикл

Для каждой фазы [ROADMAP.md](ROADMAP):

1. изучи реализацию (правило 1);
2. напиши короткий план изменения;
3. добавь/поправь тесты;
4. реализуй **наименьший полезный вертикальный срез**;
5. собери (`cmake --build build`);
6. прогони существующие тесты;
7. прогони новые тесты;
8. прогони детерминированный headless-сценарий (агентский режим);
9. сделай замеры, если изменение про производительность;
10. обнови документацию — **в том же изменении**.

Только после этого переходи к следующей крупной фазе.

---

## Стоп-условия

Остановись и доложи, вместо того чтобы импровизировать, если:

* существующая архитектура материально противоречит заданию;
* для реализации нужно сломать публичный API;
* нужной зависимости нет;
* существующие тесты падают **до** твоих правок;
* предлагаемая возможность дублирует существующую систему;
* документация и реализация расходятся так, что это влияет на проектирование.

Объясни конфликт и предложи наименьшее совместимое решение.

---

## Определение успеха

Успех — это **не** «все галочки роадмапа закрыты». Успех — это:

* существующий Russiano2D продолжает работать;
* API остаётся простым;
* запросы становятся мощнее;
* горячие пути остаются нативными;
* агент понимает состояние рантайма;
* баги воспроизводимы;
* весь UI остаётся на RmlUi.

---

## Правила репозитория, о которых легко забыть

* **Гейт документации.** Агент не пишет в движок, пока не прочитал целиком
  [ARCHITECTURE.md](ARCHITECTURE) → этот файл → [internal/NATIVE.md](internal/NATIVE) →
  [HIGH_LEVEL_API.md](HIGH_LEVEL_API), а при правке `src/highlevel/**` —
  ещё [highlevel/_CONTRACT.md](https://github.com/Nikide/russiano2d/blob/main/docs/highlevel/_CONTRACT.md) и страницу модуля
  `docs/highlevel/<имя>.md`. Это делает плагин
  `tools/dsh-russiano2d-docs-gate`; обойти его нельзя, делегирование не
  отменяет правило.
* **Каждый модуль `src/highlevel/<имя>.js`** имеет страницу
  `docs/highlevel/<имя>.md` и тест — это проверяет
  `tests/doc_coverage_test.py`.
* **Новый файл в `docs/`** автоматически попадает в `AGENTS.md` релизного
  пакета ([tools/agents_doc.py](https://github.com/Nikide/russiano2d/blob/main/tools/agents_doc.py)); порядок документов
  задаёт [tools/release.py](https://github.com/Nikide/russiano2d/blob/main/tools/release.py) (`AGENTS_DOC_ORDER`). Поэтому
  документ не может «отстать» от движка — и не должен врать.
* **Закрытый пункт работы исчезает из документации в том же изменении**
  (правило из [TASKS.md](TASKS) §6).
* **Язык документации — русский**, термины API — английские; код и имена в
  коде — английские.
