# DevTools — `$.devtools`

Инспектор сущностей: список → выбор → свойства → «скопировать селектор»
(ROADMAP, фаза 8; требования — [DEVTOOLS.md](DEVTOOLS)).

Панель — **RmlUi-документ**, собранный кодом (`engine.ui.loadMarkup`), а не
`.rml`-файл в игре: инструмент обязан работать в любой игре и не требовать
ассетов. ImGui здесь не используется — закон интерфейса
([UI_RMLUI_LAW.md](UI_RMLUI_LAW)).

```js
$.devtools.toggle();                 // или F2
$.devtools.selectBy('#hero');        // выбрать сущность
$.devtools.selector();               // '#hero' — то, что кладёт кнопка в буфер
$.devtools.panel();                  // { open, doc, rows, entities, selected, selector, refreshed }
```

---

## 1. Методы

| Вызов | Смысл |
|---|---|
| `open()` / `close()` / `toggle()` / `isOpen()` | панель; в сборке без RmlUi `open()` честно вернёт `false` |
| `select(uid)` / `selectBy(sel)` | выбрать сущность по uid или селектору |
| `selector()` | селектор выбранной сущности (кнопка копирует его в буфер обмена) |
| `panel()` | машиночитаемое состояние панели — факты для тестов и агента |
| `refresh()` | перерисовать немедленно |

Клавиша **F2** открывает и закрывает панель (F1 занята отладочным оверлеем
движка, [debug.md](highlevel/debug)).

## 2. Что показывает

* **Список** — до 24 сущностей из `$.agent.nodes('*')`: id (или `тег#uid`), тег,
  здоровье; выбранная строка подсвечена;
* **Инспектор** — transform (позиция, размер, угол), физика (тело), здоровье,
  команда, живость, видимость, семантика `aria`;
* **Кнопка «Скопировать селектор»** — кладёт `#id`, `.class` или тег в буфер
  обмена (`engine.setClipboard`) и пишет строку в журнал.

## 3. Источник истины

Панель **только читает** мир. Она не сохраняет изменения и не становится
каноническими данными проекта ([DEVTOOLS.md](DEVTOOLS) §6): правки
делаются кодом, DevTools — способ посмотреть и скопировать селектор.

## 4. Цена

* содержимое обновляется раз в 6 кадров (~10 Гц), а не каждый кадр;
* обработчики вешаются **один раз** при открытии (24 строки + кнопка);
  разметка не перерисовывается, иначе RmlUi унёс бы слушателей вместе с
  элементами — обновляются только тексты и классы;
* пока панель закрыта, кадровый шаг не делает ничего, кроме проверки F2.

## 5. Проверка

```bash
build/_deps/quickjs-build/qjs tests/js/devtools_test.mjs   # без GUI
python3 tests/agent/devtools_test.py                        # в движке
```

## 6. Диагностика runtime (F1)

`openRuntime()` / `closeRuntime()` открывают/скрывают RmlUi диагностику.
`runtimePanel()` возвращает `{open,doc,snapshot}`; `refreshRuntime()` обновляет
её с периодом 6 кадров. Snapshot содержит stats/profile/limits/textures,
gravity/reloads/error/watches из существующих публичных API.
F1 / `--overlay` / `$.debug.on()` используют эту же панель. Поля гравитации
проверяют конечные числа; reload выполняется существующим `$.script.request()`.
Это временная отладка текущего мира, без записи проекта или Scene Editor.
Проверка: `tests/agent/sdk_runtime_ui_test.py`.
