> ⚠️ **ЧАСТИЧНО УСТАРЕЛО (пометка 2026-09-24).** Модель `delete_params`/`inverse`/`off_value` относится > к **отменённому** механизму модификаторов (метки в YAML + реестр в генераторе). > Но факты внутри — верны и переиспользуются: `count=0` канонический inverse, порядок destroy, > `ipSpaceName="no-needed"`, `needEnableAVI=false`. Актуально: `NOTES/40_chat_summaries/CHAT_RESUME_IAC_2026-09-24.md`. # Inverse-откат модификаторов: анализ ответа Опуса — 2026-09-23 Источник: prompt_for_opus_inverse_architecture.md → ответ Опуса (принят, анализ ниже). ## Принятые решения (по Опусу) 1. **Модель delete_params** → заменить плоский `{Code, Value}` на `{Code, Mode, Value?}`: - `Mode: static` — значение из `Value` (дефолт, обратная совместимость). - `Mode: zero_count` — обнулить integer-поля в элементах array-map-fixed, взяв live. 2. **Баланс данные/логика**: форма преобразования выводится из `dataType` (boolean→"false", array-map-fixed→zero integer); сентинелы-значения — ТОЛЬКО данные в реестре. 3. **Маркер поля**: явный `zero_fields:["count"]` (или флаг на sub_param), а НЕ «обнулить все integer» (риск: порт/приоритет/индекс в том же object). 4. **Порядок destroy** — обратный порядок создания из `depends_on`. ## Мои замечания к ответу (что Опуc недоговорил) - **A. Граф уже правильный.** Факт: `edge_net` (SNAT) зависит от `org_ips` (IP), `org_ips` — от `edge`. Обратный порядок destroy: `edge_net → org_ips → edge → vdc` уже корректен. Рекомендация Опуса «сделать ip_space зависимым от edge_net» — перепутана направлением; граф уже такой. - **B. Источник live для zero_count в Delete не указан.** `Delete` модификатора имеет только TF `state`, а live `vIPConfigure` надо читать через `GetInstanceStateParams` в рантайме Delete. - **C. Отличие sentinel от имени в valueList не разобрано** (valueList без разметки sentinel в данных API). - **D. Идемпотентность zero_count при повторном destroy не поднята** (count=0 → снова 0: no-op?). ## Открытые вопросы (второй раунд к Опусу) — ЗАКРЫТЫ 1. **Источник live для zero_count в Delete** → `GetInstanceStateParams` (не TF state). ✅ 2. **Sentinel в valueList** → явный `off_value:"no-needed"` в реестре (данные, не логика). ✅ 3. **Идемпотентность zero_count** → пропускать `run`, если live уже `count=0` (применимо и к static). ✅ 4. **count=0** → канонический inverse; полное удаление ipSpace = отдельный опциональный `Mode:remove` (не подменять zero_count). ✅ ## ИТОГ — финальная модель inverse `delete_params: []{ Code, Mode, Value?, zero_fields?, off_value? }` - `Mode: static` — обратное значение = `Value` (boolean→"false"; string→off_value). - `Mode: zero_count` — взять live array-map-fixed, обнулить поля из `zero_fields:["count"]`. - `Mode: remove` (опц., не для FullPipe) — полное удаление элемента. Рантайм: Delete → `GetInstanceStateParams` → построить inverse → если live уже целевое → no-op (skip run) → иначе `modify`. Реестр (yaml-generator main.go): - `vc_org.ip_space`: `inverse`, param `vIPConfigure` `Mode:zero_count, zero_fields:[count]`. - `vc_nsxt.network`: `inverse`, params `needEnableAVI`=static `"false"`, `ipSpaceName`=static off_value `"no-needed"`. Порядок destroy (уже корректен в .tf): `edge_net → org_ips → edge → vdc`. ## Факты (не менять, проверено) - `count=0` принимается API (minvalue:1 в схеме — не отвергает), идемпотентно (ORG_IP_MODIFIER_TEST_2026-09-22). - SNAT off = `ipSpaceName="no-needed"` (sentinel в valueList, HAR_SNAT_MODIFY_FINDINGS). - `needEnableAVI` boolean → inverse `"false"`. - vc_org.ip_space: `error` → нужен `inverse` (zero_count). vc_nsxt.network: inverse+static `needEnableAVI=false`, добавить `ipSpaceName="no-needed"`.