[2026-09-18] eagle: personal/projects/zont-config-compiler.md

This commit is contained in:
Alexey Martemyanov
2026-09-18 00:42:42 +06:00
parent 573b1e2471
commit 60c044520f
+68 -21
View File
@@ -3831,40 +3831,87 @@ for obj in obj_list:
пропадает **без единого сообщения об ошибке**. Признак: `exit=0`, строка отсутствует и в старом, и в
новом номере.
### 25.10. 🎯 ОТКРЫТОЕ РЕШЕНИЕ (вопрос задан Alex, ответа нет)
### 25.10. ✅ ЗАКРЫТО: вариант 1 — только объекты-листья (решение Alex: «1»)
Правка трёх барьеров = открыть авто-id для всех секций. Выбор объёма:
| Вариант | Решение |
|---|---|
| ~~2. Все секции~~ | ⛔ отвергнут: требует `_body_type` до присвоения id + снятие барьера в 6+ циклах |
| **1. Только объекты-листья** | ✅ **ВЫБРАН ALEX** |
| Вариант | Что делается | Объём / риск |
**Реализация (круг 50, закрыт):**
| Что | Место | Статус |
|---|---|---|
| **1. Только объекты-листья** *(рекомендация)* | 3 правки условий допуска; объекты, на которые ссылаются по типу, продолжают требовать явный `id` | ~30 мин, риск низкий |
| **2. Все секции** | дополнительно снять барьер «`id` у каждой записи» в 6+ циклах + разобрать `_body_type` (тип объекта нужен ДО присвоения id) | ~2 ч, риск средний — можно молча сломать ссылки по типу |
| Барьер `'id' in obj` снят в цикле `TYPE_ORDER` | `yml-to-config.py` | ✅ |
| То же в цикле орфанов | там же | ✅ |
| `_LEAF_TYPES = {9}` — белый список (только `relay_commands`) | модульная константа | ✅ |
| `_is_leaf_without_id(obj, obj_type)` — отказ с понятным текстом для остальных | там же | ✅ |
| **Валидация ссылок в актуальной форме** (`trigger`/`steps`) | `validate_config` | ✅ |
Аргумент за вариант 1: закрывает реальный сценарий («написал новую реле-команду, номер придумался
сам»). Объекты-источники всегда заводит прибор, и номер им выдаёт контроллер, а не мы.
**Формы, которые теперь принимает энкодер:**
### 25.11. 📌 Статус на конец сессии 2026-09-18 (для следующей)
```yaml
# id не указан -> выдаётся свободный из 4098..19999 (тип 9)
- set_relay:
descr: 'Включить реле «Реле 13/9: Рад. ванная 2эт»'
target: 9464
value: true
# -> #Z4101=9,'Включить реле «Реле 13/9: Рад. ванная 2эт»',9464,'1'
```
#### ✅ Валидация ссылок — что теперь отклоняется (exit=4, конфиг НЕ пишется)
```
❌ VALIDATION ERRORS:
- Object 9564: set_relay.target references non-existent id 99999 (нет строки #Z99999 в выводе)
- Object 8456: call_sub references non-existent id 88888 (нет строки #Z88888 в выводе)
```
Проверяются: `set_relay`/`set_contour_target`/`activate_mode`/`set_sensor`/`set_analog_output`/
`set_contour_temp``target`; `value` — если ссылка (`{id: ...}`); `call_sub`, `send_sms`;
`trigger.step_id`, `trigger.object`, `trigger.left.object`; рекурсивно `then`/`else`/`action`/`steps`/`if`.
База допустимых id — **сами строки вывода** (`_present = set(output_ids)`), не YAML: объект может
быть в YAML и не выпуститься, тогда ссылка висит в воздухе (питфолл 97).
#### 🔴 ПИТФОЛЛ 105 — «валидация ссылок есть» ≠ «валидация ссылок работает»
Блок «4. Validate ID references in scenarios» в `validate_config` **существовал** — но читал
`scenario.get('when', {}).get('relay_id')` и `then.actions`. Это форма **до кругов 39-49**; в актуальном
YAML этих ключей нет вовсе. Валидатор работал вхолостую: подмена `target` на `99999` проезжала молча
(exit=0, мусор уезжал в контроллер).
**Урок:** при смене формы хранения ключа искать **всех** читателей, включая валидаторы. Признак мёртвого
кода — ключ, которого нет ни в одном артефакте (`grep 'when\.\|then\.actions'` по `zont_config/*.yml` → 0).
### 25.11. 📌 Статус на конец круга 50 (2026-09-18) — ЗАКРЫТ, ЗАПУШЕН
**HEAD: `7e34ee1`** — «авто-id для листьев + валидация ссылок (круг 50)», `origin/main` = HEAD.
| Позиция | Состояние |
|---|---|
| Аллокатор, окно, hard fail | ✅ **написано** в `yml-to-config.py` (**НЕ закоммичено**) |
| Аллокатор, окно `4098..19999`, hard fail | ✅ в `yml-to-config.py`, **закоммичено** |
| Регресс 9/9 | ✅ `759 → 759`, расхождений 0 |
| Авто-id end-to-end | **не работает**: барьеры §25.9 не сняты |
| Валидация ссылок | ❌ нет (питфолл 103) |
| Рабочее дерево | `yml-to-config.py` изменён, **113+/26**, поверх `5d31d6e` |
| Авто-id end-to-end (тип 9, без id) | **работает**: одна строка заменена, тело и target сохранены |
| Валидация ссылок | **есть**: exit=4, конфиг не пишется, текст с указанием объекта |
| Push | ✅ `5d31d6e..7e34ee1` → Gitea |
🔴 **Работа НЕ закоммичена.** Коммит — по команде Alex (питфолл: он сам скажет).
Правки внесены скриптами `/tmp/patch_autoid.py`, `/tmp/patch_autoid2.py`, `/tmp/patch_autoid3.py`
(идемпотентные, проверка `count == 1`, печатают OK/SKIP).
**Скрипты правок (идемпотентные, `count == 1`, печатают OK/SKIP):** `/tmp/patch_autoid.py`,
`/tmp/patch_autoid2.py`, `/tmp/patch_autoid3.py`, `/tmp/patch_autoid4.py`, `/tmp/patch_validate_refs.py`.
**Инструменты диагностики (в `/tmp`, не в репо):** `/tmp/dbg50.py` (трассировка `build_line`,
минимальный кейс сценария), `/tmp/dbg_relaycmd.py` (барьер `'id' in obj`),
`/tmp/test_autoid.py` (тест авто-генерации), `/tmp/test_autoid_granica.py` (граница: какие объекты
можно без id), `/tmp/accept_autoid.py` (приёмка: замена id + ссылка в никуда).
минимальный кейс), `/tmp/dbg_relaycmd.py` (барьер `'id' in obj`), `/tmp/test_autoid.py` (тест генерации),
`/tmp/test_autoid_granica.py` (граница: какие объекты можно без id), `/tmp/accept_autoid.py`
(приёмка: замена id + ссылка в никуда), `/tmp/show_ref_error.py` (текст ошибки валидации).
**Риски (актуальны):** (а) ссылки в новые объекты — реальная проблема, требует решения шага 3;
(б) порядок эмиссии: `S`-блоки первыми, `Z` — после, id нужен раньше строки;
(в) ~~верхняя граница~~ — ✅ **ЗАКРЫТО**: фикс-окно `4098..19999`, решение Alex.
**Остаток (не сделано):**
1. Авто-id для объектов-источников (ссылки по типу: контуры 16, датчики 27) — нужна правка `_body_type`.
2. Секции `actions` / `mqtt_topics` / `gui_switches` — цикл требует `id` у каждой записи.
3. Расширение `_LEAF_TYPES`: каждый новый тип обязан пройти замер `test_autoid_granica.py`.
**Риски:** (а) ссылки в новые объекты — решены валидацией (ссылка в никуда = ошибка);
(б) порядок эмиссии: `S` первыми, `Z` — после, id нужен раньше строки — учтено через `_alloc_id` в трёх
узких местах; (в) ~~верхняя граница~~ — ✅ закрыто фикс-окном.
---