docs: промпт Opus раунд 4 + журнал правок ядра/модификаторов

- NOTES/20_prompts/prompt_for_opus_remediation_round4.md — 5 коротких вопросов
  (retry POST, осиротевшая операция, zero-value по подстроке, единый словарь
  жизненного цикла, что упущено в ядре); ответ ≤ 25 строк.
- HISTORY/2026-09-30_core_and_modifiers_remediation.md — журнал: 6 коммитов,
  что отклонено (A3/A4/A5) и почему, что отложено (A2/B8/B9).
This commit is contained in:
Repinoid
2026-09-30 20:42:30 +03:00
parent 0e26e98384
commit 5a0bb432ab
2 changed files with 102 additions and 0 deletions
@@ -0,0 +1,59 @@
# Правки ядра и модификаторов по итогам анализа 2026-09-30 (раунд Flash)
**Репо:** `/home/naeel/TF/tf_provider`. **Дата:** 2026-09-30.
**Источник заданий:** `NOTES/20_prompts/prompt_for_deepseek_pro_remediation_plan.md`
(гипотезы A1–A5, B1–B9) + диалог с Opus `HISTORY/OPUS/2026-09-30_provider_architecture_modifiers_dialog.md`.
---
## Что сделано (6 коммитов)
| Коммит | Пункт | Файлы | Суть |
|---|---|---|---|
| `047d53a` | C | `TOOLS/ARCHITECTURE.md` | Спека приведена к коду: ручные ресурсы, 401, удалённый `serviceSpecificModifiers`, раздел «Lifecycle Vocabulary». |
| `c5a4499` | B3 | `TOOLS/scripts/check_hardcoded_service_ids.sh`, `org_ip_allocation_resource.go` | Страж сканирует `TOOLS/` + `provider/internal/` (кроме `resources_gen/`), второй паттерн — литеральный ref-svc id. `ResolveRefSvcParamValue(ctx, 19, …)` → константа `svcIDVcOrg`. |
| `383f8ea` | A1 | `core/http.go`, `core/client_test.go`, `ARCHITECTURE.md` | 401 добавлен в `isRetryable` (действует для GET). Тест `TestIsRetryable`. |
| `ea75cac` | B6 | `core/modifier_compare.go`, `operation_run_bycode.go`, `nsxt_snat_resource.go` | Idempotency pre-check сравнивает с **live** (`state.params`), а не с `paramValue` формы. `setSnat` → `ByIdempotent`. Тест `TestModifierDesiredEqualsLive`. |
| `8519ba0` | B7 | `org_ip_allocation_resource.go`, `nsxt_snat_resource.go`, `org_ip_allocation_test.go` | `ImportState` заполняет Required (`vip_configure` из live/`[]`; `ip_space_name` из live/`no-needed`). Тесты на чистые хелперы. |
| `0e26e98` | — | `core/refsvc.go`, `docs/60_strategy/terraform_case_sensitivity_fix.md` | Убран устаревший комментарий про несуществующий блок «Restore user-provided casing»; §4 помечен как исторический. |
**Проверка после каждого коммита:** `go build ./...` OK, `go test ./internal/... -short` PASS,
`bash TOOLS/scripts/check_hardcoded_service_ids.sh` → OK.
**Бэкапы:** `TMP/backup_2026-09-30/` (исходные версии всех правимых файлов).
---
## Что ОТКЛОНЕНО после проверки по коду (важно)
- **A5 (нормализация регистра в `Read`) — был бы РЕГРЕССОМ.**
Принятое решение (проверено): state хранит регистр **пользователя**; ref_svc-атрибуты **исключены
из read-back** (шаблон `instance.go` добавляет `InputField` только при `eq .RefSvcId 0`); UUID
внутри JSON нормализуются при **отправке** (`resources_core.BuildJSON` →
`jsonutil.LowercaseUUIDsInText`). См. `docs/60_strategy/terraform_case_sensitivity_fix.md` §4 (пометка),
§10–§11. Нормализация state к lowercase сломала бы соответствие plan=config.
- **A3 (не обрывать modify при сбое live) — осознанная защита, а не дефект.**
`instanceLiveParams` намеренно возвращает ошибку: тихий fallback на `paramValue` (дефолт ФОРМЫ)
возвращает reset-баг (затирание параметров инстанса, HAR/edge_.har: `needEnableAVI`). Требуется
отдельное решение (см. Q2 промпта раунда 4).
- **A4 (угадывание типа по подстроке имени) — нужен замер.**
Fallback применяется только к required-параметру без `paramValue`/`defaultValue`
(`instance_create.go:105-113`) и при досылке modify. Гарантированного улучшения нет, риск сломать
больше, чем починить. Оставлено как есть.
---
## Отложено
- **A2 — retry POST.** Слепой ретрай создающего `POST /instanceOperations` опаснее обрыва
(дубликат операции). Решение — за владельцем (варианты в промпте раунда 4, Q1).
- **B8** — создавать ли оверлей `modifiers.yaml` или узаконить ручные модификаторы категорией в спеке.
- **B9** — единый словарь жизненного цикла (в спеку внесён как незакрытый вопрос; решение — Q4 промпта).
---
## Артефакты
- Промпт раунда 4 для Opus: `NOTES/20_prompts/prompt_for_opus_remediation_round4.md`
(5 коротких вопросов, лимит ответа ≤ 25 строк).
- Ограничение сессии: чат с Opus по раундам 1–3 исчерпан по токенам → раунд 4 в новом чате.
@@ -0,0 +1,43 @@
# Opus — раунд 4: короткие решения (2026-09-30)
**Репо:** `/home/naeel/TF/tf_provider` — `terraform-provider-nubes` (Go, Terraform Plugin Framework).
## Формат ответа (ЖЁСТКО)
- На каждый вопрос — **1–3 строки**, с `файл:строка`.
- **Весь ответ ≤ 25 строк.** Без вступлений, пересказа, «а ещё могу», без повторения вопросов.
- Не хватает данных — одна короткая строка-вопрос, не догадка.
## Уже сделано — не обсуждать
401 в `isRetryable`; страж хардкодов покрыл `provider/`; idempotency pre-check переведён на live
(`core/modifier_compare.go`); `ImportState` модификаторов заполняет Required.
## Вопросы
**Q1. Retry POST.** `core/http.go:87-108` ретраит только GET. Слепой retry создающего
`POST /instanceOperations` рискует дубликатом операции. Как правильно: (а) не ретраить +
задокументировать; (б) ретраить только безопасный POST (`validate-cfs`); (в) иное?
**Q2. Осиротевшая операция.** `core/operation_run.go:150`, `core/operation_run_bycode.go:108`: при
сбое `instanceLiveParams` уже созданная операция остаётся невыполненной. Продолжение с fallback
вернёт reset-баг (защита поставлена сознательно). Есть ли безопасный третий путь (cancel/delete
операции через API) или оставить как есть? Нужен API-метод — назови его.
**Q3. Zero-value по подстроке имени.** `core/params.go:47-59`: при пустом `dataType` тип угадывается
по `name/code/label`. Пути применения: `instance_create.go:105-113` (required без значения), досылка
modify. Менять (убрать угадывание) или оставить?
**Q4. Словарь жизненного цикла.** Три несогласованных контракта: `suspend_on_destroy`/`keep_on_destroy`
(генерируемые ресурсы), `delete_strategy` (генерируемые модификаторы), `keep_on_destroy` (ручные).
Какой единый контракт зафиксировать в `TOOLS/ARCHITECTURE.md`?
**Q5. Что упущено.** Назови **один** самый критичный для устойчивости/корректности **ядра** дефект,
не упомянутый выше: 1 строка — суть → `файл:строка`.
## Границы доступа
Читать: `provider/internal/**`, `TOOLS/ARCHITECTURE.md`,
`TOOLS/resource-generator/internal/{templates,loader,params,helpers}/**`.
Не читать: `HISTORY/**`, `NOTES/**`, `docs/**`, `HAR/**`, стенды, git-историю. Нужен файл вне списка → вопрос.