recognize: название из метабазы санитизируется перед попаданием в план

- чистка стоит на каждой точке входа значения метабазы в план — сборка матча,
  копия кандидата для ревью, набор закреплённых значений источника и его
  чтение: гарантия, поставленная только на запись, обходится данными,
  сохранёнными прежними версиями
- название, непригодное как имя каталога (пустое или без единой буквы и
  цифры), не подставляется — раздача уходит в review с названной причиной
- гейт подтверждения матча не сдвинут: сравнение с планом идёт по значениям
  провайдера, чистится только копия, уходящая дальше
This commit is contained in:
av
2026-08-10 10:41:16 +03:00
parent bb278e8744
commit 9aecf757e0
26 changed files with 1653 additions and 53 deletions
+42
View File
@@ -181,6 +181,10 @@ Go-сервиса и что здесь уже проскакивало. Устр
- `security`: читается ли тело ответа внешнего сервиса целиком без предела —
лимита на размер ответа LLM в проекте нет, и это единственный недоверенный
канал, где предел не стоит ([security.md](security.md) → «Что вне модели»)
- `operations`: гарантия, которую вводит изменение, поставлена на запись или на
чтение — и что будет с данными, записанными до деплоя, которые обычный путь
не перезаписывает? (журнал, 2026-08-10: чистка названия стояла на записи, и
очередь ревью её обходила)
- `operations`: не удваивает ли новая ветка расход лимита метабаз и платного
LLM — повтор, ретрай, «распознать заново» на том же входе? (кэша ответов нет,
задача `metadata-cache`)
@@ -316,6 +320,44 @@ Go-сервиса и что здесь уже проскакивало. Устр
случаи до этой даты не восстанавливались — восстановленная постфактум причина
непоймания недостоверна, а именно она и нужна.
## 2026-08-10 — чистка названия метабазы стояла только на записи, и очередь ревью её обходила [пойман]
- **Где:** `internal/worker/review.go``sourcePins`, `applyOverrides`,
`buildSources`. Норма — `openspec/specs/metadata-match/spec.md`, требование
«Санитайзинг названий кандидатов, уходящих в ревью», и
`openspec/specs/review/spec.md`, «Подтверждение матча обновляет отображаемое
имя».
- **Симптом:** найден на ревью самой задачи `metadata-title-sanitize`, до
мерджа. В эксплуатации не всплывал. Сошлись независимо четыре прохода:
`adversary` (построенный путь с падающим тестом), `ops` (постмортем),
`specs` и `code`.
- **Причина:** правка чистила значение метабазы **в момент записи** — при
копировании кандидата в список для ревью. Из этого следовали три дыры разом.
(1) Кандидаты, сохранённые прежними версиями, лежат в хранилище грязными, а
их выбор человеком закреплял название дословно. (2) `applyOverrides` читал
значение, закреплённое до деплоя, дословно, и обычное «Применить» без
повторного выбора источника создавало ровно тот каталог, ради которого
правка затевалась. (3) Предпросмотр источника на экране считался из сырого
названия, а гейт пригодности стоял только на закреплении — экран показывал
одно, раскладка делала другое, при том что «превью = применение» записано
требованием `web-ui`.
- **Чем воспроизведён:** тремя тестами, каждый падает без правки (проверено
прогоном с временно снятой правкой): `TestBuildSources_PreviewMatchesApply`,
`TestChooseCandidate_DirtyLegacyTitleSanitized`,
`TestApplyOverrides_LegacyDirtyPinSanitized`. Плюс прогон `adversary`:
превью `- (2014) [tvdbid-269613]/…` против применяемого
`Догадка (2014) [tvdbid-269613]/…` на одном экране.
- **Почему не поймали:** ловить было нечему — дефект поймали на этом же ревью,
до мерджа. Записывается ради причины его появления: **гарантия, поставленная
на запись, молчаливо не распространяется на данные, записанные раньше.**
Ревью дизайна дошло до «закрыть оба пути подтверждения матча», но точкой
закрытия выбрало запись, а не чтение; вопрос «а что с тем, что уже лежит в
хранилище» не задал никто из трёх проходов стадии дизайна. Его задал
эксплуатационный проход — на оси времени, где он и живёт.
- **Что меняем:** вопрос темы `operations` (ниже) — про гарантию, поставленную
на запись. Решение по существу — ADR-2026-08-10-sanitize-at-every-entry:
чистка стоит на каждой точке входа, включая чтение.
## 2026-08-06 — уборка своего торрента после отмены сносит чужие файлы [проскочил]
- **Где:** `internal/worker/worker.go:501-556` — гард `:501-509`, удаление