docs(plan): внести правки ревью Опуса в план (порядок, ID-миграция, override, array-map-fixed)
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user