diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 7c893a0b..25664c56 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -130,7 +130,7 @@ | 228 | **Отклонённая поверхность возвращается АЛИАСОМ уцелевшей строки — движок не держит того, что канон уже обещает** (находка воркфлоу-ревью P9 в форме Д1, УЗКО пере-сформулирована бэкенд-сессией 28.08 и принята приёмкой): канон говорит дословно «declining a surface removes EVERY window of that surface» (`docs/architecture/14-api-contract/openapi.yaml:2362`=`declining a surface removes EVERY window`; адрес пере-нацелен 02.09 — минор 0.9.0 сдвинул прежний 2051), а эмиссия майнера энтити-широка (`backend/internal/pipeline/miner_emit.go`, `clusterTouches`), тогда как фильтр авто-банка ключуется только по собственному `src` строки (`backend/internal/pipeline/mining.go:179`=`NormalizeSourceKey(m.Src)`). ⚠ **Правильная форма — снять АЛИАС со строки, а не снести строку:** расширение `decline` до энтити противоречило бы ратифицированному контракту, и именно поэтому бэкенд-сессия применила право §9 и НЕ чинила это попутно. Предмет — банковая онтология (`18-bank-ontology.md`), не тихая порча | бэкенд | скоро (гейт: заказ по читающей стороне банка) | отдельный заказ узкой формы | воркфлоу-ревью P9; форма — бэкенд-сессия 28.08, D39.164 | | 229 | **Снапшот не фолдит модель ВНУТРЕННИХ гейтов — флип провода под неизменным `request_hash`** (самонаходка бэкенд-сессии 28.08, подтверждена приёмкой): снапшот фолдит `Capability` СТАДИЙНЫХ моделей и их эскалации (`backend/internal/pipeline/snapshot.go:316-340`), но модель `gates.terminology.model` / `gates.repair.model` (`backend/internal/config/internal_call.go:72`) не фолдится сознательно — а терминолог шлёт ДВА системных сообщения, так что смена оси `capabilities.system_messages` у провайдера, которым пользуется только гейт, меняет байты запроса при неизменном хеше: тихий false-hit класса D5.2. ⚠ **Сегодня ЛАТЕНТНА и денег не стоит — проверено приёмкой: гейта `terminology` нет НИ В ОДНОМ конфиге репозитория** (`grep -c terminology configs/pipeline-c1.yaml` = 0). Триггер починки — день, когда гейт включат с провайдером, объявляющим НЕдефолтную возможность. ⚠ Цена лечения — денежная: фолд гейт-моделей сдвигает хеши и обесценивает чекпойнты; дешёвая форма — фолдить ТОЛЬКО недефолтное (приём `omitempty`, прецедент `MinMaxTokens`), тогда сегодняшние снапшоты остаются байт-равными | бэкенд | когда-нибудь (гейт: включение внутреннего гейта либо следующее касание снапшот-контракта) | правка снапшот-контракта | самонаходка бэкенд-сессии, D39.164 | | 230 | **Инертный `decline` подписанного сид-терма отвечает `already_applied` вместо единственной работающей инструкции** (названный размен пака «тихая порча», D39.164): сузив отказ по поверхности ради СХОДИМОСТИ повтора, движок потерял поучение в одном углу — когда отказ и записан, и по-прежнему инертен против `glossary_seed`, пользователь получает «уже применено» вместо «убери терм из сида». Сходимость сочтена более тяжёлой обязанностью (на ней стоит вся раскладка класса 15 и синхронная дверь платформы), но размен РЕАЛЕН. **Форма закрытия — поле отчёта со стоячим фактом**, то есть аддитивная правка формы шва: платформенный `BankReport` — аллоулист, лишнее поле на провод не уедет само | бэкенд + контракт | скоро (с ближайшим касанием отчёта двери) | аддитивное поле отчёта | размен пака «тихая порча», D39.164 | -| 232 | ⚠ **ЛИД ПРОТУХ — испр. 05.09: вторая половина (слот гранта на прерванном между волнами юните) ЗАКРЫТА** паком «число согласия» (`D39.187`, пин `TestAUnitInterruptedBetweenWavesTakesNoSecondSlot`; эррата 03.09-а). **Настоящий остаток** — две схемные оси («первая редакторская стадия», «прерванная пере-делка») и отложенное слово владельца о семантике переноса. **Ось «свежий/пере-делка» выведена из ПОЛНОТЫ СТРОК, а не из факта отгрузки** (D39.170, находки охотника 3 и 4). Следствия ДЕНЕЖНЫЕ на слух покупателя: добавление стадии в пайплайн превращает ДОЧИТАННУЮ книгу в «3 unit(s) NEVER delivered» и приглашает купить её снова; юнит, прерванный между волнами (signature stop, денежный потолок, Ctrl-C), второй раз считается свежим и тратит слот гранта повторно — замерено 4 купленных юнита → 2 главы. Носитель у движка УЖЕ есть: реестр анонсов `events_outbox.once_key` (`backend/internal/pipeline/events.go:401`=`unitOnceKey is the identity of one announcement`), ключ `unit:<книга>:<волна>:<глава>:<юнит>`, монотонный на всю жизнь книги и переживающий и добавление стадии, и обрыв между волнами. ⚠ **ПЕРВАЯ ПОЛОВИНА ИСПОЛНЕНА 31.08** (`bb541a8`, экземпляр A11; испр. 02.09): читающий метод `store.AnnouncedOnceKeys()` построен, его докстринг называет эту строку по номеру, предикат — `delivered[key] && unitShipped(rows)`. **ЖИВОЙ ОСТАТОК — ВТОРАЯ ПОЛОВИНА:** юнит, прерванный МЕЖДУ ВОЛНАМИ, повторно тратит слот гранта (разбор — `backend/docs/MONEY_HONESTY_REPORT.md` §4.5). ⚠ РАЗВИЛКА, которую надо назвать в промте: ключ несёт ВОЛНУ, значит «юнит отгружен» — факт per-wave. **Ответ есть и он не новый механизм:** отгрузкой считается волна, владеющая ОТГРУЖАЮЩЕЙ (последней) стадией — `backend/internal/pipeline/snapshot.go:243`=`finalStageWave is the wave that owns the SHIPPING (last) stage`; на редакторском конвейере это edit, на черновом-только — draft. Проверять надо ИМ, иначе черновой-только конвейер получит ось, которая никогда ничего не считает отгруженным (предложено движковой сессией при сдаче, сверено мной по коду) | бэкенд | скоро | Читающий метод стора + перевод оси на факт отгрузки; отдельный пак | приёмка D39.170 | +| 232 | ⚠ **ЛИД ПРОТУХ — испр. 05.09: вторая половина (слот гранта на прерванном между волнами юните) ЗАКРЫТА** паком «число согласия» (`D39.187`, пин `TestAUnitInterruptedBetweenWavesTakesNoSecondSlot`; эррата 03.09-а). **Настоящий остаток** — две схемные оси («первая редакторская стадия», «прерванная пере-делка») и отложенное слово владельца о семантике переноса. **Ось «свежий/пере-делка» выведена из ПОЛНОТЫ СТРОК, а не из факта отгрузки** (D39.170, находки охотника 3 и 4). Следствия ДЕНЕЖНЫЕ на слух покупателя: добавление стадии в пайплайн превращает ДОЧИТАННУЮ книгу в «3 unit(s) NEVER delivered» и приглашает купить её снова; юнит, прерванный между волнами (signature stop, денежный потолок, Ctrl-C), второй раз считается свежим и тратит слот гранта повторно — замерено 4 купленных юнита → 2 главы. Носитель у движка УЖЕ есть: реестр анонсов `events_outbox.once_key` (`backend/internal/pipeline/events.go:401`=`unitOnceKey is the identity of one announcement`), ключ `unit:<книга>:<волна>:<глава>:<юнит>`, монотонный на всю жизнь книги и переживающий и добавление стадии, и обрыв между волнами. ⚠ **ПЕРВАЯ ПОЛОВИНА ИСПОЛНЕНА 31.08** (`bb541a8`, экземпляр A11; испр. 02.09): читающий метод `store.AnnouncedOnceKeys()` построен, его докстринг называет эту строку по номеру, предикат — `delivered[key] && unitShipped(rows)`. **ЖИВОЙ ОСТАТОК — ВТОРАЯ ПОЛОВИНА:** юнит, прерванный МЕЖДУ ВОЛНАМИ, повторно тратит слот гранта (разбор — `backend/docs/MONEY_HONESTY_REPORT.md` §4.5). ⚠ РАЗВИЛКА, которую надо назвать в промте: ключ несёт ВОЛНУ, значит «юнит отгружен» — факт per-wave. **Ответ есть и он не новый механизм:** отгрузкой считается волна, владеющая ОТГРУЖАЮЩЕЙ (последней) стадией — `backend/internal/pipeline/snapshot.go:248`=`finalStageWave is the wave that owns the SHIPPING (last) stage`; на редакторском конвейере это edit, на черновом-только — draft. Проверять надо ИМ, иначе черновой-только конвейер получит ось, которая никогда ничего не считает отгруженным (предложено движковой сессией при сдаче, сверено мной по коду) | бэкенд | скоро | Читающий метод стора + перевод оси на факт отгрузки; отдельный пак | приёмка D39.170 | | 233 | **Трата терминолога вне объёмного потолка масштабируется КНИГОЙ, а не грантом** (D39.170). Замер: три последовательные покупки по одному юниту на четырёхглавной книге дали три полнокнижных консолидации по $0.005460 каждая — покупка одного юнита обходится в ~1.5× стоимости самого юнита. Книга на 500 юнитов, проданная по одному, оплатит 500 полнокнижных проходов. Место траты — в ЦЕНЕ, а не в потолке (решение подтверждено), но при мелкой нарезке продажи она перестаёт быть накладной и становится основной статьёй: это ВХОД В КАЛИБРОВКУ ЦЕНЫ, а не сноска | бэкенд | скоро | Учесть в модели цены при следующей калибровке; либо чекпойнт консолидации, переживающий покупку | приёмка D39.170 | | 237 | **Два загейченных триггера НАЖАТЫ и не отработаны** (реестр `13-tech-debt-anchors.md` §Б-108, сверено 30.08). **(а) `go.work`:** условие «появление Go-кода платформы» выполнено давно — `platform/go.mod` есть, `ls go.work` в корне даёт «No such file or directory». Ратифицировано D39.85 §8 п.4 (`docs/research/23-engine-platform-seam.md:66` = `go.work — коммитить, когда у платформы появится Go-код`); цена — один файл, по тому же §6 он решает только dev-удобство и не меняет ни видимости, ни версий. **(б) вендор-сверка маппинга эффорта `deepseek-v4-pro`:** вахта D39.92 сработала 13.08 changelog'ом вендора. ⚠ **Испр. 05.09: НОСИТЕЛИ БОЛЬШЕ НЕ ПРОТИВОРЕЧАТ** — и квирки (`docs/experiments/00-provider-quirks.md` §3г), и `STACK.md` говорят одно: ручка ДОХОДИТ до модели. Прежняя редакция обвиняла оба носителя в утверждении «ручки у pro НЕТ», которого ни один из них уже не несёт, и это заставляло сессию искать спор, которого нет. Живой остаток — вендор-сверка САМОГО МАППИНГА и величина эффекта, и по гардрейлу владельца это закрывается ТОЛЬКО вендор-докой, а не выбором стороны. Держит жильца Д5 и калибровку цены редакторского арма. ⚠ **Класс важнее двух пунктов: спроектированный механизм без носителя события тихо становится долгом, и никто не проверяет, не нажат ли спусковой крючок.** | оркестратор | скоро | (а) один файл в корень; (б) заказ полигону на вендор-сверку | аудит очереди 30.08 | | 241 | **Канон противоречит сам себе на ДОЧИТАННОЙ книге, и принятая правка банка умирает молча** (названо телом D39.165 §3 28.08, носителя не получило; заведено оркестратором №20 30.08 по находке сессии P12). Две фразы: правка банка «takes effect on the NEXT run» (`docs/architecture/14-api-contract/openapi.yaml:529`=`takes effect on the NEXT run`) против «finished work is not bought twice» + подъём потолка только у ПРИОСТАНОВЛЕННОЙ книги (`:590`=`finished work is not bought twice`). У дочитанной книги следующего прогона купить нечем: пользователь правит банк, получает квитанцию об успехе — и правка не доезжает ни до одной строки никогда. ⚠ Смежное лечение уже существует и не связано с этой дырой: пере-проход ПОКУПАЕТСЯ членом `RunRequest.re_pass` (канон 0.7.0, D39.166) — то есть механизм есть, а фраза канона его не признаёт для дочитанной книги. Решать формой: либо канон признаёт пере-проход входом для дочитанной книги, либо дверь правок отказывает такой книге ЧЕСТНО вместо ложной квитанции | контракт (+платформа) | скоро (следующее касание контракта) | контрактный минор + пин на дочитанной книге | D39.165 §3, эррата 30.08-б, находка сессии P12 |