- баннеры «ЛОЖНЫЙ ПУТЬ — ОТМЕНЕНО» на 4 файла HISTORY/OPUS/2026-09-22_modifier_* и docs/60_strategy/modifier_resources_ideology_and_specification.md - vIPConfigure: replace-семантика, НЕ накопительная (по тесту docs/ORG_IP_MODIFIER_TEST_2026-09-22.md) - обновлены ссылки на перенесённые материалы (docs/... -> NOTES/..., HOW_TO/...)
5.6 KiB
⛔ ЛОЖНЫЙ ПУТЬ — ОТМЕНЕНО (пометка 2026-09-24). ТАК ДЕЛАТЬ НЕЛЬЗЯ. Ревью плана отменённого захода (
kind: modifierв YAML + реестр в генераторе). История. Актуально:NOTES/40_chat_summaries/CHAT_RESUME_IAC_2026-09-24.md.
Opus: ревью плана редизайна модификаторов — 2026-09-22
Источник: ответ на prompt_for_opus_modifier_plan_review.md (план PLAN_modifier_redesign.md).
1. Порядок шагов — скрытые зависимости
- Шаг 4 (шаблон) ссылается на API из шагов 6–7 → сначала 5→6→7, потом 4.
- Шаг 8 (yaml-generator) должен идти ДО регенерации
devи до сборки.
Скорректированный порядок: 1 → 2 → 3 → 5 → 6 → 7 → 4 → 8 → регенерация → 9 → 10.
2. Шаг 5 (вынос JSON-эквивалентности)
Путь верен. Оставить реэкспорт-обёртку JSONStringsEquivalent в json_normalize.go,
не заменять вызовы по всему resources_core (иначе диф на инстансы, вопрос 7).
Переносятся самодостаточные 5 функций: JSONStringsEquivalent, normalizeJSONIfPossible,
encodeCanonicalJSON, writeCanonicalJSON, normalizeJSONScalarsToStrings.
Вариант «готовые строки в core» — отклонить (размазывает нормализацию, не снимает потребность в JSONStringsEquivalent в core).
3. Шаг 6 — сигнатура и сравнение
- Маппинг code→param по двум алиасам:
p.CodeИp.SvcOperationCfsParam(как в operation_run_bycode.go:50-58). ОдинCodeдаст пропуски. - Имя
modifierDesiredEqualsCurrent— unexported, вызов внутри core. Слово «экспортированный» убрать. - bool/int/string —
normalizeUniversalValueV6+ сравнение. map-fixed —JSONStringsEquivalent. - array-map-fixed — дыра:
normalizeUniversalValueV6строит дефолт только дляmap-fixed/HasPrefix "map"(params.go:33);array-map-fixedтуда не попадает → сравнивать сырые значения черезjsonutil.JSONStringsEquivalent, не через normalize. - desired = только явно заданные коды (до досылки live/default), иначе pre-check всегда «равно».
4. Шаг 4.4 Delete=inverse — подводный камень
- Delete не имеет
plan(толькоreq.State).reconcile(ctx, plan *Model)не подходит. →reconcile(ctx, model *Model, override map[string]string); для inverse override = delete_params. deleteParams— финальные wire-строки ("false", готовый JSON), БЕЗ прогонки черезParamFormat/тип. В реестреdeleteParam{Code, Value}несёт готовую строку.
5. Шаг 8 — расширение реестра
Верно. Держать в serviceSpecificModifiers (main.go:34), не отдельным реестром.
Структура modifierException корректна. При переходе со map[string]string на структуру:
ModifierName берётся из структуры (сейчас modName, ok := serviceSpecificModifiers[name]
— строка 95).
6. Пропущенные кейсы
- taint/replace +
delete_strategy=error— конфликт: replace = Delete→Create, Delete=error блокирует → пользователь не сможет заменить error-модификатор. Решить явно: запретить replace у error (документировать) или отличить «чистый destroy» от replace. - unknown в pre-check — при unknown (computed ref) сравнение невозможно; шаг 6 должен skip-ить pre-check при unknown (иначе пустая строка даст ложный diff/панику).
- partial apply — досылка live для незаданных + pre-check; проверить кейс «часть задана, часть live».
7. Риск сломать инстансы
Низкий при условиях:
- НЕ удалять
CompactParams(helpers.go:68) — убирается только из modifier-шаблона; функция нужна инстанс/action. - Шаг 7 — новый метод
RunOperationByCodeIdempotent, НЕ менять сигнатуруRunOperationByCodeWithTimeout/RunInstanceOperationUniversalByCode(зовут инстансы). - Шаг 1 (поля OperationSpec) аддитивен — безопасно.
Дополнительно (не в вопросах)
- Шаг 4.3 (ID=identity) — ломающая миграция state. Смена формата ID изменит ID уже задеплоенных модификаторов → Terraform форснёт replace. Нужно: либо сохранить старый формат ID, либо явный state-migration plan. В плане не отмечено.
- Шаг 3 —
normalizeDeleteStrategy/normalizeIdempotency— где живут (в loader.go, рядом с веткой modifier). Не указано. - ValidateSpec — проверка
delete_params.code ∈ op.Paramsпо lower-code; сверить полеCode.