[2026-09-17] eagle: personal/projects/zont-config-compiler.md
This commit is contained in:
@@ -1844,6 +1844,9 @@ rm -rf zont_config/_wip
|
|||||||
| 51 | 🔴 **`elif` по типу цели недостижим — различать по НАЛИЧИЮ объекта** | `#Z9964=59,'set varname',42,0,1`: `42` — `int`, заходил в объектную ветку, объекта нет → падал в `descr`+`args`. Различать `target in Z_dict`, не `isinstance` |
|
| 51 | 🔴 **`elif` по типу цели недостижим — различать по НАЛИЧИЮ объекта** | `#Z9964=59,'set varname',42,0,1`: `42` — `int`, заходил в объектную ветку, объекта нет → падал в `descr`+`args`. Различать `target in Z_dict`, не `isinstance` |
|
||||||
| 52 | 🔴 **Тело цели разворачивать на месте РОДИТЕЛЯ, но собирать ЕГО строкой** | Родитель несёт `target: <id>`, тело живёт своей строкой под тем же id. Попытка встроить тело в родителя без id ломает обратную сборку (на этом упал потерянный подход, §10.8) |
|
| 52 | 🔴 **Тело цели разворачивать на месте РОДИТЕЛЯ, но собирать ЕГО строкой** | Родитель несёт `target: <id>`, тело живёт своей строкой под тем же id. Попытка встроить тело в родителя без id ломает обратную сборку (на этом упал потерянный подход, §10.8) |
|
||||||
| 53 | 🔴 **`_body_type` обходить ВЕСЬ YAML, включая вложенные секции** | Плоский обход верхнего уровня не находит объекты в `executors.*` (напр. `9263`) → `unknown event 'on' for object 9263 (type None)`. Нужен рекурсивный `_collect_ids` |
|
| 53 | 🔴 **`_body_type` обходить ВЕСЬ YAML, включая вложенные секции** | Плоский обход верхнего уровня не находит объекты в `executors.*` (напр. `9263`) → `unknown event 'on' for object 9263 (type None)`. Нужен рекурсивный `_collect_ids` |
|
||||||
|
| 54 | 🔴 **Полный `raw` типа 59 НЕ пересобирать — выводить как есть** | Орфан-блок (~стр. 1015) для любого `raw[0]==59` звал `_parse_script_raw` и пересобирал строку; `var`-ветка жёстко писала `0,0`. `#Z9964=…,42,0,1` → `42,0,0`. Правило: `len(raw)>=5` → `reconstruct_from_raw`, разворот — только для неполных raw. `_seen_lines` НЕ ловит подмену: `42,0,0 ≠ 42,0,1`, а `z_dict` берёт последнюю |
|
||||||
|
| 55 | 🔴 **Отладку вести инъекцией печати, а не правкой файла** | Вместо гипотез — `src.replace(...)` + `exec(compile(src,…))` в отдельном модуле: печать в `_set_var_body`/`_register`/`build_line` **не трогая конвертер**. Доказала за один прогон: `REGISTER` верный → `BUILD` искажён, т.е. виноват не `emit_step`, а ветка ниже. До этого две версии диагноза были неверны |
|
||||||
|
| 56 | 🔵 **Порядок строк в выводе = унаследованное поведение (не регрессия)** | Расхождение порядка проверять на **чистом `b75c51f`** (`git show b75c51f:yml-to-config.py > /tmp/base/`), а не по счётчику круга. Содержимое сверять `comm -3` по `sort`-нутым файлам, не `diff`: `diff` даёт 545 «расхождений», из них значимых — 0. См. §10.10 |
|
||||||
|
|
||||||
> 📌 **Корень аварии — процессный, не технический.** Работа шла **кругами** (34 круга формы),
|
> 📌 **Корень аварии — процессный, не технический.** Работа шла **кругами** (34 круга формы),
|
||||||
> каждый круг переписывал предыдущий, и **ни один не фиксировался**. При таком режиме любая
|
> каждый круг переписывал предыдущий, и **ни один не фиксировался**. При таком режиме любая
|
||||||
@@ -1855,10 +1858,11 @@ rm -rf zont_config/_wip
|
|||||||
|
|
||||||
### 10.9. ✅ ВОССТАНОВЛЕНО 2026-09-17 (продолжение сессии) — код написан заново
|
### 10.9. ✅ ВОССТАНОВЛЕНО 2026-09-17 (продолжение сессии) — код написан заново
|
||||||
|
|
||||||
> ✅ **Статус: развёртывание РЕАЛИЗОВАНО заново** поверх `b75c51f`. `set_var` (4 формы),
|
> ✅ **Статус: развёртывание РЕАЛИЗОВАНО заново** поверх `b75c51f`, дефект `#Z9964` **закрыт**.
|
||||||
> `param`/`event` (тип 49), `op`/`time`/`days_mask` (тип 50), тела 59 (`objstate`/`expr`/
|
> `set_var` (4 формы), `param`/`event` (тип 49), `op`/`time`/`days_mask` (тип 50), тела 59
|
||||||
> `const`/`var`) — **в рабочей копии, НЕ закоммичено**. Круг `21-13-18` → `749 → 749`,
|
> (`objstate`/`expr`/`const`/`var`) — **в рабочей копии, НЕ закоммичено**.
|
||||||
> строк `774 → 774`, **остаётся 1 расхождение**: `#Z9964` теряет поле 4.
|
> Круг `21-13-18` → строк `774 → 774`, **потеряно 0, лишнее 0**; `18-43-24` → `686 → 686`,
|
||||||
|
> **потеряно 0, лишнее 0**. Отличается только **порядок строк** — унаследованное поведение (§10.10).
|
||||||
|
|
||||||
**Как восстанавливали.** Источник — **Zulip-база**, тред `personal / ZONT Config compiler`
|
**Как восстанавливали.** Источник — **Zulip-база**, тред `personal / ZONT Config compiler`
|
||||||
(3380 сообщений). Рабочий отрезок `15:15–15:37` (msg `105060`–`105486`) содержит полный
|
(3380 сообщений). Рабочий отрезок `15:15–15:37` (msg `105060`–`105486`) содержит полный
|
||||||
@@ -1908,13 +1912,87 @@ ORDER BY m.date_sent;"
|
|||||||
| B | `set_var needs 'value'…got {…'value': 2}` | ветка «цель-число» стояла **до** ветки «цель-сама-set» | переставлен порядок: `_script_value_row` → затем `var`+`value` |
|
| B | `set_var needs 'value'…got {…'value': 2}` | ветка «цель-число» стояла **до** ветки «цель-сама-set» | переставлен порядок: `_script_value_row` → затем `var`+`value` |
|
||||||
| C | `id:` уезжал **в конец** записи | `parsed['id'] = step_id` в конце словаря | словарь пересобирается с `id` первым ключом |
|
| C | `id:` уезжал **в конец** записи | `parsed['id'] = step_id` в конце словаря | словарь пересобирается с `id` первым ключом |
|
||||||
|
|
||||||
**Остаточный дефект (не закрыт).** `#Z9964=59,'set varname',42,0,1` → собирается `42,0,0`
|
**Остаточный дефект `#Z9964` — ✅ ЗАКРЫТ (продолжение той же сессии).**
|
||||||
(теряется поле 4). `9964` **есть в `steps` сценария 8456** с корректным
|
|
||||||
`set_var: {name: varname, value: 42, args: [0, 1]}` (проверено `yaml.safe_load`), но в
|
Симптом был описан неверно: «`9964` не доходит до ветки `set_var` в `emit_step`». Отладка
|
||||||
`lines` из steps не попадает — управление до ветки `'set_var' in step` в `emit_step` не доходит,
|
инструментально (подмена `_set_var_body`/`_register`/`build_line` печатью через
|
||||||
и строка собирается из другого места без `args`.
|
`exec(compile(src,…))` — **без правки самого файла**) показала обратное:
|
||||||
**Следующий шаг:** отладка в `emit_step` — печатать, доходит ли управление до `'set_var' in step`
|
|
||||||
для `9964`, и откуда берётся `42,0,0`.
|
```
|
||||||
|
CALL 9964 {'name': 'varname', 'value': 42, 'args': [0, 1]}
|
||||||
|
REGISTER 9964 [59, 'set varname', 42, 0, 1] ← верно!
|
||||||
|
BUILD 9964 "#Z9964=59,'set varname',42,0,0" ← уже искажено
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть `emit_step` **отрабатывал верно** и регистрировал `[0, 1]`. Искажение вносил блок
|
||||||
|
вывода орфан-секций (`yml-to-config.py`, ~строка 1015): для любого `scenario_scripts`-объекта
|
||||||
|
с `raw[0] == 59` он **заново** парсил raw через `_parse_script_raw` и пересобирал строку.
|
||||||
|
`9964` попадал в `var`-ветку (`set varname` без объекта), а та жёстко подставляла `0, 0`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
_script_value_row(_sv, _oid) if _sv.get('type') != 'var' \
|
||||||
|
else [59, 'set %s' % _sv.get('name', 'var1'), _sv.get('value', 0), 0, 0]
|
||||||
|
```
|
||||||
|
|
||||||
|
Дедупликация `_seen_lines` не спасала: `42,0,0` ≠ `42,0,1`, поэтому «дубль» проходил как
|
||||||
|
новая строка и `z_dict[9964]` (последняя побеждает) затирал верное значение.
|
||||||
|
|
||||||
|
**Фикс.** Полный `raw` типа 59 (5 полей) выводится **как есть**, без пересборки; разворот
|
||||||
|
оставлен только для неполных raw:
|
||||||
|
|
||||||
|
```python
|
||||||
|
_raw = _obj.get('raw')
|
||||||
|
if isinstance(_raw, list) and _raw and _raw[0] == 59 and len(_raw) >= 5:
|
||||||
|
line = reconstruct_from_raw(_obj['id'], _raw)
|
||||||
|
if line not in _seen_lines:
|
||||||
|
_seen_lines.add(line)
|
||||||
|
lines.append(line)
|
||||||
|
continue
|
||||||
|
# ниже — прежний разворот для raw без полного набора полей
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат после фикса — оба круга содержательно чистые:**
|
||||||
|
|
||||||
|
| Снимок | Строк | Потеряно | Лишнее |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `21-13-18` | 774 → 774 | **0** | **0** |
|
||||||
|
| `18-43-24` | 686 → 686 | **0** | **0** |
|
||||||
|
|
||||||
|
**Проверено:** `#Z9925=…,14.5,0,1` и `#Z9964=…,42,0,1` — оба на месте.
|
||||||
|
|
||||||
|
> 📌 **Команда проверки содержимого** (порядок игнорируется, см. §10.10):
|
||||||
|
> ```bash
|
||||||
|
> cd /Users/admin/Automation/HA-ZONT-Modbus
|
||||||
|
> python3 config-to-yml.py zont_config/config_local_2026-09-17_21-13-18.txt >/dev/null
|
||||||
|
> python3 yml-to-config.py zont_config/config_local_2026-09-17_21-13-18.yml > /tmp/back.txt
|
||||||
|
> sort zont_config/config_local_2026-09-17_21-13-18.txt > /tmp/a; sort /tmp/back.txt > /tmp/b
|
||||||
|
> comm -3 /tmp/a /tmp/b # пусто = содержимое совпадает побайтово
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### 10.10. 🔵 Порядок строк — УНАСЛЕДОВАННОЕ поведение, НЕ регрессия
|
||||||
|
|
||||||
|
Наивный `diff` круга даёт **~545 строк расхождения** на `21-13-18` и ~678 на `18-43-24` —
|
||||||
|
но это **только перестановка**, множества строк совпадают полностью:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comm -23 <(sort orig) <(sort back) # → пусто (ничего не потеряно)
|
||||||
|
comm -13 <(sort orig) <(sort back) # → пусто (ничего лишнего)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Проверено на `b75c51f` (коммит ДО всех правок восстановления):** те же расхождения порядка,
|
||||||
|
на тех же позициях (`#S200` должен идти до `#S12`/`#S36`). Пример — `18-43-24` на чистом
|
||||||
|
`b75c51f`: **678 перестановок**, первое расхождение — позиция 1 (`S200` vs `S12`).
|
||||||
|
|
||||||
|
**Причина.** Парсер хранит исходный порядок (`Z` — список), но в YAML он **не пишется**:
|
||||||
|
объекты разложены по секциям-типам. Энкодер выводит по жёстким спискам
|
||||||
|
(`FIRST_S_BLOCK_ORDER` — `[7,12,36,200,…]`, `TYPE_ORDER`) и по порядку секций YAML.
|
||||||
|
|
||||||
|
**Вывод:** ZONT читает объекты по id, не по позиции; содержимое от перестановки не меняется.
|
||||||
|
**Не чинить в рамках других задач** (подтверждает прежнюю запись дока).
|
||||||
|
|
||||||
|
**Если чинить — вариант: `seq`-номер.** Парсер пишет в каждый объект YAML его исходный индекс,
|
||||||
|
энкодер сортирует вывод по нему. Требует правки **обоих** конвертеров (~30 мин). Вариант
|
||||||
|
«читать порядок из исходного `.txt`» отвергнут: делает YAML несамодостаточным.
|
||||||
|
|
||||||
> 📌 **Форма, которая читается** (проверено глазами, `grep` по сгенерированному YAML):
|
> 📌 **Форма, которая читается** (проверено глазами, `grep` по сгенерированному YAML):
|
||||||
> ```yaml
|
> ```yaml
|
||||||
@@ -1941,20 +2019,28 @@ ORDER BY m.date_sent;"
|
|||||||
| Файл | Статус |
|
| Файл | Статус |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `config-to-yml.py` | ✅ форма §5 (`trigger:` подъём через `pop('if')`, шаг = `{id, [flag], action}` или `{id, [flag], if, then, [else]}`) **плюс** развёртывание тел (§10.9): `_script_value`, `_set_var_target_body`, `_target_set_name`, `PARAM_CODES`/`COND_EVENTS`/`_OP_NAMES`, разворот орфанов-59 · ⚠️ **не закоммичено** |
|
| `config-to-yml.py` | ✅ форма §5 (`trigger:` подъём через `pop('if')`, шаг = `{id, [flag], action}` или `{id, [flag], if, then, [else]}`) **плюс** развёртывание тел (§10.9): `_script_value`, `_set_var_target_body`, `_target_set_name`, `PARAM_CODES`/`COND_EVENTS`/`_OP_NAMES`, разворот орфанов-59 · ⚠️ **не закоммичено** |
|
||||||
| `yml-to-config.py` | ✅ `emit_step` читает `then`/`action`/`else`/`flag`; `f5` из `trigger:`/`interval_ms` + бит 8 **плюс** сборка тел (§10.9): `_parse_script_raw`, `_script_value_row`, `_set_var_target_row`, `_set_var_body`, `_body_type`/`_collect_ids`, `_PARAM_TO_CODE`/`_EVENT_TO_CODE`/`_OP_TO_CODE`/`_SEC_TYPE` · ⚠️ **не закоммичено**, 1 расхождение (`#Z9964`) |
|
| `yml-to-config.py` | ✅ `emit_step` читает `then`/`action`/`else`/`flag`; `f5` из `trigger:`/`interval_ms` + бит 8 **плюс** сборка тел (§10.9): `_parse_script_raw`, `_script_value_row`, `_set_var_target_row`, `_set_var_body`, `_body_type`/`_collect_ids`, `_PARAM_TO_CODE`/`_EVENT_TO_CODE`/`_OP_TO_CODE`/`_SEC_TYPE` · ✅ **расхождение `#Z9964` ЗАКРЫТО** (полный `raw` 59 выводится как есть, питфолл 54) · ⚠️ **не закоммичено** |
|
||||||
| `test_roundtrip.py` | ✅ без изменений (в коммите `199f2b1`) · ✅ **оба круга зелёные после восстановления** |
|
| `test_roundtrip.py` | ✅ без изменений (в коммите `199f2b1`) · ✅ **оба круга зелёные после восстановления** |
|
||||||
| `zont_config/config_local_2026-09-17_21-13-18.{txt,yml}` | 🆕 **актуальный рабочий снимок** (774 строки, 749 `#Z`) — «Простой тестовый сценарий» `#Z8456` содержит шаги `9925…9990`, `Values test` `#Z9324` не изменился. Круг ✅ `774 → 774`, различий **0** |
|
| `zont_config/config_local_2026-09-17_21-13-18.{txt,yml}` | 🆕 **актуальный рабочий снимок** (774 строки, 749 `#Z`) — «Простой тестовый сценарий» `#Z8456` содержит шаги `9925…9990`, `Values test` `#Z9324` не изменился. Круг ✅ `774 → 774`, различий **0** |
|
||||||
| `zont_config/config_local_2026-09-17_18-43-24.{txt,yml}` | ↩️ **ВОССТАНОВЛЕН 2026-09-17** из `b75c51f` после ошибочной чистки. Форма `trigger:` + `action:` — 66/66. Круг ✅ `661 → 661` |
|
| `zont_config/config_local_2026-09-17_18-43-24.{txt,yml}` | ↩️ **ВОССТАНОВЛЕН 2026-09-17** из `b75c51f` после ошибочной чистки. Форма `trigger:` + `action:`. Круг ✅ строк `686 → 686`, **потеряно 0, лишнее 0** (661 — это счёт `#Z`, 686 — все строки) |
|
||||||
|
| `zont_config/config_local_2026-09-17_19-53-21.{txt,yml}` | 🔴 **удалён в рабочей копии** (`git status` = `AD`) — удаление не закоммичено; восстанавливается `git checkout b75c51f -- …`. Алекс: «блядь почисти файлы а» → «ДА» |
|
||||||
| `zont_config/config_0FA7C33CC89F_…_12-12-28.txt` + 4 исторических `.txt` | ↩️ **ВОССТАНОВЛЕНЫ** из `b75c51f` (см. §10.8) |
|
| `zont_config/config_0FA7C33CC89F_…_12-12-28.txt` + 4 исторических `.txt` | ↩️ **ВОССТАНОВЛЕНЫ** из `b75c51f` (см. §10.8) |
|
||||||
| `zont_config/archive/` | `-2`/`-3`/`-4` — закоммичены (`7ae0e32`) |
|
| `zont_config/archive/` | `-2`/`-3`/`-4` — закоммичены (`7ae0e32`) |
|
||||||
|
|
||||||
> 📌 **Состояние на 2026-09-17, конец сессии.** HEAD = `b75c51f`, не запушен.
|
> 📌 **Состояние на 2026-09-17, конец сессии.** HEAD = `b75c51f`, не запушен.
|
||||||
> Рабочая копия **содержит восстановленное развёртывание тел** (§10.9) — **не закоммичено**.
|
> Рабочая копия **содержит восстановленное развёртывание тел** (§10.9) — **не закоммичено**.
|
||||||
> Развёртывание тел мини-скриптов и условий (`set_var`, `param`, `event`, `op`/`time`/`days_mask`,
|
> Развёртывание тел мини-скриптов и условий (`set_var`, `param`, `event`, `op`/`time`/`days_mask`,
|
||||||
> `expr`/`objstate`/`const`) — **в коде, работает**, остаётся **1 расхождение** по `#Z9964` (поле 4).
|
> `expr`/`objstate`/`const`) — **в коде, работает**; дефект `#Z9964` **закрыт** (§10.9).
|
||||||
> 🔴 **Первым делом следующей сессии — закоммитить** рабочую копию (питфолл 41/44: незакоммиченная
|
> 🔴 **Первым делом следующей сессии — закоммитить** рабочую копию (питфолл 41/44: незакоммиченная
|
||||||
> работа уже терялась один раз).
|
> работа уже терялась один раз).
|
||||||
> Круги: `21-13-18` → `749 → 749` / строк `774 → 774` (1 расхождение), `18-43-24` → `661 → 661` ✅.
|
> Круги: `21-13-18` → строк `774 → 774` (потеряно 0, лишнее 0), `18-43-24` → `686 → 686`
|
||||||
|
> (потеряно 0, лишнее 0). Расходится только **порядок строк** — унаследованное, не регрессия (§10.10).
|
||||||
|
|
||||||
|
> 🔴 **Удаление `19-53-21.{txt,yml}` НЕ закоммичено** (`git status`: `AD`). Плюс в корне 13
|
||||||
|
> мусорных отладочных скриптов (`audit2.py`, `audit_8456.py`, `chk_extra.py`, `check_ops.py`,
|
||||||
|
> `dump_new_types.py`, `fit_temp.py`, `fit_temp2.py`, `probe_sched.py`, `probe_types.py`,
|
||||||
|
> `read_scenarios.py`, `trace_scenarios.py`, `verify_answers.py`, `why_raw.py`) и папки
|
||||||
|
> `zont_api_docs/`, `zont_local_ui_recon/` — **не тронуты, ждут команды Alex**.
|
||||||
|
|
||||||
|
|
||||||
> ⛔ **`_f2` / `_f5` — МУСОРНЫЕ КЛЮЧИ, удалены из кода (круг 26).** В `config-to-yml.py` был блок
|
> ⛔ **`_f2` / `_f5` — МУСОРНЫЕ КЛЮЧИ, удалены из кода (круг 26).** В `config-to-yml.py` был блок
|
||||||
|
|||||||
Reference in New Issue
Block a user