Accept the platform pack, record the shift's norms as their own note, and take the owner's word that the engine may say how much to add

This commit is contained in:
heaven 2026-09-05 14:08:13 +03:00
parent c533618a82
commit 84886d5b34
5 changed files with 104 additions and 8 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
# Реестр D-нот — карта актуальности v2 (D1D39.200; титул — носитель головы, бампать при каждом аппенде)
# Реестр D-нот — карта актуальности v2 (D1D39.203; титул — носитель головы, бампать при каждом аппенде)
> ⚠ **Колонку «тело» `counts.py --check` НЕ сторожит по устройству:** он сверяет полноту НОМЕРОВ, а не
> место тела, поэтому колонка держится дисциплиной лендинга. Не нашёл тело по колонке — иди в слайсы,
@ -259,3 +259,6 @@
| D39.198 | 05.09 | **Приоритет качества назван владельцем: (1) 100% консистентность, никаких разнопереведённых терминов · (2) никаких выдуманных сюжетных линий и смыслов · (3) художественность.** ⛔ Тем же словом СНЯТ вопрос «веса рубрики K1K12»: веса меряют РАЗНЫЕ УЗЛЫ (консистентность — банк памяти; выдумки — редактор; художественность — редактор И черновик), поэтому единого веса быть не может, а одно взвешенное число измеряет, но НЕ ДИАГНОСТИРУЕТ — чинить надо узел. Мерить по узлам; приоритет говорит, чей отказ ОСТАНАВЛИВАЕТ выпуск. ⚠ Консистентность проверяема детерминированно за $0 — это ГЕЙТ, не строка рубрики. Сняты как блокеры «добора идеала»: 13а · 24 · 149 · 55 ⇒ формулировка оркестратора «качество не может стартовать» была НЕВЕРНА, строка 275 пере-снята | жив | ЖИВОЕ: метрика, сливающая узлы в одно число, измеряет, но не диагностирует | качество приоритет рубрика узлы банк редактор черновик |
| D39.199 | 05.09 | **АКТ: движковый пак ПРИНЯТ С ДОФИКСОМ, приёмочный коммит `74ffe4f`; эррата 04.09-д «пак НЕ принят» ИСЧЕРПАНА.** Каталог 158 — 156 RED · 0 SURVIVED · 0 ROTTED · 2 `survives`; батарея чистая, тесты 1173→1178. Приёмка по обязательным нормам: дерево названо КОММИТОМ, №1 судил дифф НЕ ЧИТАЯ отчёт (вердикт «достигает»), №2 искал ВНЕ карты. ⚠ Граница: №2 прогнал 5 записей из 19, остальные на слово. Находки вне карты — строки 287·288·289·290; закрыта 264. ⚠ Остаток зоны: последние шесть починок чужими глазами НЕ ревьюились | жив | ЖИВОЕ: ось с читателем и писателем прибивается С ОБЕИХ сторон — «прибил читателя» без писателя не находка, а половина | приёмка движок акт мутации верификаторы |
| D39.200 | 05.09 | **Вторая ревизия документации: десять строк бэклога закрыты (169·191·202·216·234·105·13а·149·167·205, счёт 220→210), снесены ТРИ фантомных противоречия, восстановлена норма языка кода, которую снесла первая ревизия; батч Б16 был закрыт при красной собственной приёмке; отзыв запрета «денег в UI» доехал прозой до всех носителей** | ратифицировано | живое тело | доки · бэклог · контракт · ревизия |
| D39.201 | 05.09 | **АКТ: платформенный пак «пустить внутрь можно» ПРИНЯТ С ДОФИКСОМ** (`7e2226a` + `3e84716`; 20 находок, 5 снято, 15 устояло, 5 major — ТРИ в самом механизме бэкапа: книга в интейке не попадала в точку ни одним файлом при `complete: true`, ложная посылка дискриминатора вешала гейдж возраста в `+Inf` навсегда, рецепт восстановления не останавливает прогоны). Ратификации прозой: `bearerToken` минтится вне полосы, `character_count` — признак точности рядом с числом. Строки 269 · 270 · 274 · 282 закрыты; заведена 293 | ратифицировано | живое тело | приёмка · платформа · бэкап · контракт |
| D39.202 | 05.09 | **НОРМЫ СМЕНЫ: один корень у восьми случаев — прибор отвечает на свой вопрос, а читают его как ответ на свой.** Четыре вида неразличимого зелёного отчёта · девять форм ложной зелени (включая ГЕЙТ, ЗАЩИЩАЮЩИЙ ДЕФЕКТ) · правила посадок, указателей, замеров · «замер, попавший в посылку заказа, — стоп и вопрос владельцу» · норма о нормах: правило, требующее бдительности, исполняется настолько, насколько она есть | ратифицировано | живое тело | нормы · приёмка · инструменты |
| D39.203 | 05.09 | **Владелец: движку МОЖНО говорить «сколько добавить»** — раскрытие оценки отказанного вызова легитимно (стена и есть цена вызова, формой не обходится). ⚠ Запрет ПТ-35 на СТОИМОСТЬ цел: наружу идёт до-вызовная ОЦЕНКА, не сеттлмент. Тензия жила внутри заказа (п.3 против п.4: `step_max_usd` — тоже оценка вызова). Создаёт работу: величина `max(shortfall, step_max headroom)` + ПЕРЕИМЕНОВАНИЕ поля + минор `StreamVersion` 1.3→1.4; пак лендится как построен | ратифицировано | живое тело | деньги · шов · контракт · продукт |

View file

@ -1,4 +1,4 @@
# Журнал решений оркестратора — контракт D1D39.200 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
# Журнал решений оркестратора — контракт D1D39.203 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
> **КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Работая с контрактом (греп номера: живой файл → слайсы, целиком НЕ читать — D39.125), держи под рукой, что чем перекрыто:
> ⚠ **Эррата 09.08 (D39.125):** D39.111 п.1 предписывал промту S3 «максимум = баланс МИНУС открытые холды» — формула ОШИБОЧНА (вычитание дважды), исправлена D39.115 п.2(а): максимум = Balance КАК ЕСТЬ; тело D39.111 — в слайсе `../archive/architecture/05-decisions-D39-106-123.md` (испр. 05.09: прежнее «живёт ниже в этом файле» протухло подрезкой D39.139) (голова D39.106+).
@ -2353,3 +2353,96 @@ Gemini как построенный (его в `internal/llm/` нет) · дв
бестокенных якорей не сверялись, и линт их тоже не судит. ⇒ **класс «строка посылает строить
построенное» среди непроверенных строк мог остаться, и следующая ревизия начинает с них**
(05.09.2026, оркестратор №22). ✅
## D39.201 — АКТ ПРИЁМКИ ПЛАТФОРМЕННОГО ПАКА «ПУСТИТЬ ВНУТРЬ МОЖНО»: ПРИНЯТ С ДОФИКСОМ, `7e2226a` + `3e84716`; три дыры были в самом бэкапе (05.09). ✅
**1. Пак ПРИНЯТ.** Лендинги: приёмочный **`7e2226a`** (32 файла, +5307/72) · дофикс **`3e84716`** (10 файлов, +427/95) · зонный журнал `4230b5e`; последним касанием — секция норм в зонном журнале (+95/4), заказанная оркестратором после того, как зона предъявила: её же залёнженный журнал учил проверять якоря НЕГОДНЫМ способом — фильтром по своей зоне. Приёмка по обязательным нормам: два верификатора с асимметричными мандатами (№1 судил ЗАКАЗ и ДИФФ, НЕ ЧИТАЯ отчёт; №2 строил карту отчёта и искал ВНЕ неё), каждая находка атакована скептиком с заданием СНЯТЬ её. **20 находок · 5 снято с предъявленным основанием · 15 устояло · 5 major.**
**2. ⛔ ТРИ ИЗ ПЯТИ MAJOR — В САМОМ МЕХАНИЗМЕ БЭКАПА, то есть в том, ради чего пак и заказывался.** (а) Книга, не дошедшая до реза, не попадала в точку НИ ОДНИМ файлом — включая загруженный пользователем исходник, который сам пакет называет незаменимым, — **а точка при этом `complete: true`**; статус `parsing` при сломанном шаблоне книги не терминален НИКОГДА, то есть окно не минутное. (б) Дискриминатор стоял на ложной посылке «каталог отвергнутой книги уходит вместе с исходником»: каталог сносится лишь при одной причине из двух, книга проваливается между ветвями, и **гейдж возраста бэкапа залипает в `+Inf` навсегда** — единственный сигнал настоящей потери обесценивается, а защита `prune` «не выбрасывать самую свежую ПОЛНУЮ точку» становится холостой. (в) Рецепт восстановления гасит демона, но **прогоны демону НЕ дети** (транзиентные юниты, переживающие деплой по построению — тот же документ объясняет это семьюстами строками выше), и `mv` подсунул бы файл под открытым дескриптором живого оплаченного прогона; PLAUSIBLE — живым прогоном не воспроизведено, шаг добавлен, но на стенде зоны неисполним (`Failed to connect to bus`), проверит только боевой хост.
**3. Четвёртый major — «поправил читателя, оставил писателя» на паре писателей ОДНОЙ колонки.** Гард на управляющие символы в титуле получила только дверь переименования; интейк шёл мимо, `NUL` давал 500 и ERROR-строку в журнале за ошибку вызывающего. **Отчёт называл этот дефект починенным.** Починка развела поведение осознанно: интейк ЧИСТИТ (тело мультипарта уже принято, ронять десятки мегабайт из-за одной руны нельзя), дверь переименования по-прежнему ОТКАЗЫВАЕТ с указателем на `/title`.
**4. Пятый major нашли ОБА верификатора независимо: абзац рантбука о «тихом денежном» симптоме ИНВЕРТИРОВАН.** Потерянный КЛЮЧ `mining.contrast_path` валит загрузку конфига ГРОМКО на всех путях, включая $0-читающие (`backend/internal/config/pipeline.go`, греп `mining.contrast_path` is not set — `bad()` фатален); тихо ломается отсутствие ФАЙЛА. Проверено оркестратором самостоятельно и живым прогоном верификатора (ключ убран → `exit 10`, манифеста нет вовсе; файл убран → `exit 0`, `book_once_usd: 2`). Заменено ТАБЛИЦЕЙ ЗАМЕРА, а не новой прозой. ⚠ Зона написала оркестратору «симптом пере-проверен по коду с замером обеих веток» — померена была одна; она же назвала это своим классом «записано точнее, чем проверено».
**5. Ратификации канона — ПРОЗОЙ, схема впереди кода не едет** (дефект, за который в тот же день написана эррата 04.09-в). (а) `bearerToken`: абзац «Nothing issues such a token today» стал ложным в момент лендинга — токен минтится ВНЕ ПОЛОСЫ оператором (`tmplatformctl token issue`), сессия обычная, гасится `POST /auth/logout`; **эндпоинта для выдачи нет и по умолчанию не будет — дверь, выдающая себе учётные данные по HTTP, есть другая модель угроз и ратифицируется отдельно**, иначе следующий прочитает его отсутствие как недоделку. Компаньон приведён к канону тем же актом (сутки они противоречили друг другу). (б) `character_count`: ратифицирована форма **признак точности РЯДОМ с числом**, а НЕ смена семантики `null` — довод решающий: `null` уже значит «ещё грузится», живой клиент рисует его как `0`, перегрузка сломала бы развёрнутого читателя. Число точно только для UTF-8 текста: для EPUB это руны ZIP-КОНТЕЙНЕРА. **Поле приезжает с паком формы заказа**, который и делает это число ЦЕНОЙ.
**6. ⚠ ЧЕСТНЫЙ ОСТАТОК ПРИЁМКИ, названный поимённо.** Из тринадцати починок дофикса оркестратор проверил ТРИ (разделение копирования и дискриминатора · таблица замера в рантбуке · пересылка DSN целиком минус пароль); **остальные десять приняты по пинам зоны и зелёным гейтам и оркестратором НЕ ПРОВЕРЕНЫ** — это записано так, а не «всё подтверждено», ровно потому что смена дважды заплатила за обобщение выборки. Восстановление рехёрсено зоной пять раз, последний — на дофикснутом коде с настоящим `drop database` до нуля таблиц. Платного прогона в паке не было; денег не потрачено.
**7. Диспозиции строк бэклога:** **269** (бэкапов нет ни у оплаченной работы, ни у денежного реестра) — ЗАКРЫТА лендингом · **270** (у продукта ноль дверей: контракт объявляет `bearerToken`, выдать нечем) — ЗАКРЫТА · **274** (имя книги) — ЗАКРЫТА платформенной половиной; ⚠ доставка титула В ФАЙЛ остаётся и уходит к строке **284**: форма описана (`tmctl build --title` аргументом при спавне, прецедент `--ceiling-usd`), **но патч НЕ проверен** — движок отвергает незнакомый флаг по построению · **282** (ложная подпись «Знаков») — состав минора внесён прозой, поле за паком формы заказа. Новая строка **293** — файл под любым каталогом `books/` невидим для git.
**8. Норма, купленная этим паком и стоящая дороже находок.** Зона сама свела итог: **четыре из пяти major — не новые дефекты, а её собственные ПОСЫЛКИ, записанные как факты** («каталог уходит с исходником» · «у книги в интейке терять нечего» · «граница одна на две двери» · «замер обеих веток»). ⇒ **Верификатор не нашёл кода, который зона не додумала, — он нашёл предложения, которые она не проверила.** Это меняет ФОРМУ приёмки, а не только список находок: искать надо не «где код неверен», а **«какое утверждение отчёта никто не исполнил»** (05.09.2026, оркестратор №22). ✅
## D39.202 — НОРМЫ СМЕНЫ 05.09: ОДИН КОРЕНЬ У ВОСЬМИ СЛУЧАЕВ — ПРИБОР ОТВЕЧАЕТ НА СВОЙ ВОПРОС, А ЧИТАЮТ ЕГО КАК ОТВЕТ НА СВОЙ (05.09). ✅
**0. Зачем отдельной нотой.** За смену три сессии и два акта приёмки родили полтора десятка правил, и в актах им не место: акт говорит, ЧТО принято и с каким остатком, а не читает мораль (форма D-ноты — `ORCHESTRATOR_SESSION_PROMPT.md` §«Ратифицируешь?»). Здесь — только правила и их ГРАНИЦЫ; кто и на чём их купил, живёт в актах `D39.201` и следующем за ним. ⚠ Восемь случаев ниже выглядели РАЗНЫМИ дефектами и оказались одним.
**1. ⛔ КОРЕНЬ: вывод инструмента отвечает на вопрос, который инструмент умеет задать, а читают его как ответ на СВОЙ.** Восемь случаев одной смены: длина списка посадок прочитана как ПОКРЫТИЕ · `SURVIVED` прочитан как ОТСУТСТВИЕ находки · зелёный линт — как «носители целы» (а он видит лишь то, у чего ЕСТЬ номер строки) · линт с фильтром по своей зоне — как «якоря зоны целы» (а он мерит только ИСХОДЯЩИЕ) · `--stat` прочитан как столбец вставок (а это ЗАТРОНУТЫЕ строки) · зелёная батарея — как «починка покрыта» (а посадку без теста ловит только полный каталог) · пустой выход упавшей утилиты — как «файлы идентичны» · греп `A|B` без `-E` — как отрицание.
**2. Четыре вида ЗЕЛЁНОГО ОТЧЁТА, неразличимые чтением.** Отчёт зелен одинаково, когда: (а) проверено МАЛО (выборка, предъявленная как доказательство, доказывает ровно себя) · (б) проверено НЕ ТО (посылка истинна не по той причине, по которой её проверяли) · (в) записано ТОЧНЕЕ, чем проверено (число звучит как замер, замером не являясь) · (г) утверждение ИСТИННО, но отвечает не на тот вопрос, который решает приёмку («каталог прогнан целиком» ≠ «прогнан и СОШЁЛСЯ»). **Различает их только исполнение** ⇒ «проверено» без предъявленной команды и её вывода утверждением не является.
**3. Формы ЛОЖНОЙ ЗЕЛЕНИ, найденные за смену** (реестр, а не рассказ): упавшая сборка · обрезанный вывод · **эквивалентная посадка** · **отказ, принявший форму таймаута или тишины** (восемь случаев за смену — свойство инструмента, не невезение) · **вырожденное утверждение** (предмет отсутствует в фикстуре) · **триггер, существующий только в ПОЧИНЕННОМ мире** · **посадка с нерезолвящимся якорем** (запись есть, не утверждает ничего, а ДЛИНА списка читается как покрытие) · **`SURVIVED` как сообщение о НЕДОСТИЖИМОСТИ** (единственная форма, которая приносит дефект, а не прячет: так найден мёртвый код) · ⛔ **гейт, ЗАЩИЩАЮЩИЙ дефект** — тест ПИНИТ неверное поведение, починить не покраснев нельзя, и ревизия по зелени проходит мимо; самая устойчивая из всех.
**4. Посадки и починки.** Посадка, чей отказ выглядит ТАЙМАУТОМ, посадкой не является (`t.Fatalf` из порождённой горутины — `runtime.Goexit` не на той горутине). **Починка из двух частей требует посадки из двух частей** (одинокая половина воспроизводит третий мир, которого не было). **Починка, у которой проверена только одна половина, — половина починки** (громкая смерть, ставшая тихим исчезновением, — класс из шапки `CLAUDE.md`, допущенный В ПОЧИНКЕ). **Починка с посадкой, но без теста, выглядит покрытой ровно до полного прогона каталога.** Проверка «якорь резолвится ровно один раз» гоняется ПОСЛЕ КАЖДОГО касания кода, а не перед сдачей.
**5. Указатели.** Носитель БЕЗ якоря не проверяется инструментом, который ищет якоря (комментарий в Go пережил линт и нёс снятое различение как действующее). Ноту адресуют НОМЕРОМ: строка журнала подрезку не переживает. **Номер строки протухает от акта СВОЕЙ ЖЕ записи, если запись стоит выше цели в том же файле** ⇒ форма указателя: сначала ТОКЕН, потом номер с оговоркой «на момент этой редакции». **Протухший ЧУЖОЙ указатель ПОМЕЧАЮТ, а не переписывают.** Правка файла, на который целятся якоря, требует линта БЕЗ фильтра по своей зоне: «поправил читателя, оставил писателя» бывает и через НУМЕРАЦИЮ — правка, законная в своей зоне, ломает чужую по механике файла; худший случай — замороженная зона, у которой нет своего линта в цикле.
**6. Замеры и приборы.** `--stat` даёт ЗАТРОНУТЫЕ строки; «сколько добавлено» — только `--numstat`. Инструмент, чей отказ даёт ПУСТОЙ выход, обязан печатать РАЗМЕР рядом с вердиктом. Отрицание сопровождается КОМАНДОЙ, воспроизводимой другим (греп с `|` требует `-E`). **Сходимость «чистая дельта файла = сдвиг самого нижнего якоря» — ТРЕВОЖКА, а не прибор:** импликация односторонняя в обе стороны (сошлось ⇒ про число ханков ничего; РАЗНЫЕ сдвиги ⇒ ханков ≥2, доказательно), выход всегда «иди мерь», никогда «вот причина»; мерит по-настоящему перегреп токена. **«Покрыть нечем» — ЗАМЕР, а не мнение, и стоит одной попытки.** **Линт якорей в чужие доки — гейт ЛЕНДИНГА, а не сессии:** на грязном чужом дереве у вопроса нет определённого ответа, и называть результат («транзиент» либо «долг») значит выдавать неопределённость за замер.
**7. Ратификация и передача довода.** Замер, попавший в ПОСЫЛКУ ЗАКАЗА, — стоп и вопрос владельцу, а НЕ артефакт под подпись (нарушено оркестратором 05.09 и отозвано в тот же день). **Ратификация, приносящая зоне готовый довод, обязана нести и КОМАНДУ, которой он проверяется**; зона обязана эту команду прогнать, кем бы довод ни был принесён. ⚠ **Норма О НОРМАХ, объясняющая, почему половина написанного здесь не сработает: правило, требующее БДИТЕЛЬНОСТИ, исполняется ровно настолько, насколько бдительность есть; правило, снижающее ЦЕНУ проверки, исполняется.** По этому критерию из всего списка выживают немногие — сходимость дельты, «ратификация несёт команду», «якорь резолвится ровно один раз», «размер рядом с вердиктом»: все они дают КОМАНДУ, а не призыв.
**8. Приёмка как механизм.** Промт, называющий верификатору КОММИТ (D39.172), обязан выдавать ему ГОТОВЫЙ ПУТЬ отдельного рабочего дерева (`git worktree add <путь> <коммит>`), а не только запрет `checkout`: запрет уже стоял (`ORCHESTRATOR_SESSION_PROMPT.md`, греп `state-changing git`) и не сработал на 22 агентах. ⚠ 05.09 общее дерево оказалось отцеплено на судимый коммит, следующий коммит оркестратора ушёл мимо ветки, и заметила это ЧУЖАЯ зона; **актор не установлен, и запись «переключил верификатор» снята как вывод, поданный за замер.** Симптом был виден за полчаса — верификатор доложил «появились чужие незакоммиченные правки трёх файлов `docs/`», и это отпечаток «HEAD на коммите, файлы на ветке»; отпечаток не был опознан. **Дешёвый механизм, которого не было: одна строка в pre-commit — `git symbolic-ref -q HEAD >/dev/null || exit 1`**.
**9. ⛔ ГЛАВНЫЙ ПРОБЕЛ СМЕНЫ, У КОТОРОГО СЕГОДНЯ НЕТ МЕХАНИЗМА (назван зоной движка).** Все ЧЕТЫРЕ major
её приёмки оказались **утверждениями, а не поведением**: код делал то, что должен, а врали про него
слова — доккоммент контрактного типа, шапка поля, обоснование фенса, подпись числа. То же на платформе:
четыре из пяти major — её собственные ПОСЫЛКИ, записанные как факты. ⇒ **Батарея сторожит поведение,
каталог мутаций сторожит поведение, линтер сторожит форму — и НИ ОДИН из них не сторожит того, что код
о себе ГОВОРИТ.** Единственное, что поймало все восемь, — чтение вслух ЧУЖИМИ ГЛАЗАМИ: приёмка и внешний
ревьюер. У следующей смены их может не быть, и тогда слова разъедутся с кодом МОЛЧА.
**Направление, а не решение (кандидат в заказ, НЕ ратифицирован).** Механизм у проекта уже есть в
доках — опт-ин токен-якорь `` `путь:12-14`=`подстрока` ``, сверяемый ПО СОДЕРЖИМОМУ (`docs/scripts/counts.py`,
греп `def lint_anchors`), с разведёнными ролями дельты: ТРЕБОВАТЬ токен — на тронутых строках, ПРОВЕРЯТЬ
написанные — по всему корпусу каждый прогон. Перенос в КОД: **комментарий, дающий ГАРАНТИЮ, называет тест,
который её пинит.** Триггер обязан быть ЯВНЫМ маркером, а не эвристикой по прозе: механизм, применяемый
по суждению, — не механизм.
**Замер зоны на её ПЯТИ major (а не на здравом смысле):** два поймано СТРУКТУРНО (`Finished.Money`
«present only on `outcome: ceiling`» и `status.go` «absent when there is no current manifest» — оба
заявляют правило присутствия ⇒ тест пишется ⇒ падает); один вскрыт ЧАСТИЧНО и самым интересным образом
(`runevents.go` «discloses nothing about what any one call cost» — теста быть не может, это отрицательное
свойство над деривацией, и попытка назвать тест обнажила бы, что фраза АРГУМЕНТ, а не гарантия); два
ПРОМАХ (история фенса и подпись числа — не гарантии о поведении).
**ВОЗРАЖЕНИЕ, УБИВАЮЩЕЕ ПРОСТУЮ ФОРМУ: указатель на ПУСТОЙ тест хуже отсутствия указателя.** За одну
смену у зоны было ЧЕТЫРЕ зелёных теста, не доказывавших ничего: `TestWaitingForHeadroomDeliversTheWholeBook`
(строка ожидания не появлялась ни разу — починен `waits > 0`) · `TestAFutileRefusalDoesNotHoldTheWaveOpen`
(проходил по неверной причине, `attempt_timeout` — удалён) · фолд-тест, сравнивавший два РАЗНЫХ набора
рядов · тест `bookOnceUSD`, ПИНИВШИЙ неверное число. Под линтом в форме «назови тест» все четыре стали бы
машинно-проверенными указателями от гарантии к тесту, который её не держит ⇒ **отмывание уверенности ровно
там, где замер говорит, что уверенность была неверна.**
⭐ **ПОПРАВКА, СОБИРАЕМАЯ ИЗ УЖЕ ПОСТРОЕННОГО: названный тест обязан быть тем, про который КАТАЛОГ доказал,
что он умеет ПАДАТЬ.** `tmmutate` уже печатает по каждой посадке имена покрасневших тестов и имеет режим
«keep only the failing test names» (`backend/cmd/tmmutate/main.go`, греп `-logs`) — величина вычисляется
сегодня и просто не сохраняется; добавка — писать эти списки файлом. Тогда линт проверяет ТРИ машинных
условия: тест существует · тест НАЗВАН красным хотя бы одной посадкой · посадка про тот же предмет (через
`why`, глазами один раз при заведении). ⇒ «указатель» превращается в «указатель, про который ПОКАЗАНО, что
он краснеет, когда гарантию ломают» — единственная версия, которая сильнее заменяемого ею чтения. Побочно
проект получает долговременную запись, КАКИЕ ТЕСТЫ НЕСУЩИЕ.
**ПРЕДЕЛ, записанный РЯДОМ, а не вместо:** кандидат НЕ берёт класс, стоивший сегодня дороже всего — три
major из пяти были предложениями, которые НЕ гарантии (история · подпись числа · довод). Для них
инструмент другой и дешевле: **утверждение, ссылающееся на замер, обязано цитировать КОМАНДУ** («$1.00 из
$2.00» не мерил никто), **а утверждение о ПРОШЛОМ обязано быть ДАТИРОВАНО** («раньше это было невозможно»
звало доверять не той границе). Оба — правила письма, проверяемые тем же опт-ин токеном
(05.09.2026, оркестратор №22). ✅
## D39.203 — ВЛАДЕЛЕЦ РАЗРЕШИЛ ДВИЖКУ ГОВОРИТЬ «СКОЛЬКО ДОБАВИТЬ»: раскрытие оценки вызова легитимно, поле переименовывается, запрет на СТОИМОСТЬ цел (05.09). ✅
**1. Решение владельца 05.09, дословно: «Можно, в форме „сколько добавить“».** Снимает `pending owner` с `Ceiling.ShortfallMicroUSD` и закрывает вопрос, поставленный после того, как приёмка предъявила ЖИВЫМ ПРОГОНОМ: из публикуемого числа и потолка, который потребитель поставил сам, восстанавливается оценка отказанного вызова с точностью до микродоллара (`shortfall + ceiling committed`, где `committed` идёт кадром `spend`).
**2. ⚠ Что именно разрешено, и чего решение НЕ отменяет.** Разрешено движку называть платформе сумму, которой не хватает, ЗНАЯ, что она ограничивает цену вызова: **стена и ЕСТЬ цена вызова, поэтому обойти это формой невозможно — можно только решить, секрет ли это.** Владелец решил, что нет. ⛔ **Запрет ПТ-35 остаётся в силе и НЕ сужен:** «цены моделей, стоимость стадий и вызовов». Различение, на котором стоит решение и которое обязано пережить эту ноту: **наружу идёт ДО-ВЫЗОВНАЯ ОЦЕНКА (резервация, которую движок просит ПЕРЕД звонком), а не СТОИМОСТЬ (что списано по факту).** Оценка есть потолок, стоимость есть факт; запрет написан про факт. Сеттлмент по-прежнему не выходит.
**3. Тензия жила ВНУТРИ ЗАКАЗА, а не в одном поле — найдено зоной движка.** Пункт (3) промта `BACKEND_MONEYSTOP_SESSION_PROMPT.md` запрещал цене вызова выходить наружу; пункт (4) ТРЕБОВАЛ публиковать `step_max_usd` — «the largest single INDIVISIBLE reservation… the number the wall was made of» (`backend/internal/pipeline/manifest.go`, греп `StepMaxUSD`), то есть тоже оценку ОДНОГО вызова. ⇒ Снятие недостачи вопроса не закрыло бы. Решение владельца закрывает ОБЕ половины разом.
**4. ⛔ Ошибка оркестратора, которую это решение исправляет, — процедурная, и она названа прямо.** Замер приёмки попал не в работу зоны, а в ПОСЫЛКУ ЗАКАЗА, который писал оркестратор. Норма на этот случай («замер бьёт по посылке — стоп и вопрос владельцу, не артефакт под подпись») была нарушена: оркестратор **ратифицировал сам, объявив внутренний провод исключением, и спросил владельца ПОСЛЕ**. Ярлык «внутренний провод» придуман после замера — собственный промт применял запрет к ПРОВОДУ («наружу»), а не к интерфейсу. Ратификация отозвана в тот же час, до слова владельца поведение не менялось. ⚠ Сопутствующая ошибка того же захода: сужение объявлялось «ратификацией фразы D39.106 §2» — такой фразы в журнале НЕТ, она жила только в комментарии теста ⇒ это было ОБСЛУЖИВАНИЕ по D39.183, а овер-атрибуция скрыла настоящий конфликт (ПТ-35). Обе поправки — от внешнего ревьюера, проверены оркестратором командами.
**5. ЧТО ЭТО СОЗДАЁТ КАК РАБОТУ (не дофикс сданного пака — НОВЫЙ заказ).** Построенное поле легитимно и НЕ ложно: оно называет «сколько не хватило на ЭТОТ вызов» и именно это и считает. Выбранная владельцем форма СИЛЬНЕЕ: «сколько добавить, чтобы прошёл ЛЮБОЙ следующий вызов» = `max(shortfall, step_max headroom)`. Разница для покупателя практическая: сегодняшняя недостача закрывает текущий вызов, а следующий может быть крупнее, и человек доплатит дважды. ⇒ Состав новой работы, названный зоной и принятый: **(а)** новая величина; **(б)** **ПЕРЕИМЕНОВАНИЕ поля**`shortfall_micro_usd` станет ЛОЖНЫМ ИМЕНЕМ, кандидат `top_up_micro_usd`; **(в)** минорный бамп `StreamVersion` (1.3 → 1.4) и правка зеркала словаря на стороне платформы; **(г)** пере-снятие пина белого списка кадра `ceiling`. ⚠ **Это НЕ однострочник, и объявлять его дешёвым было бы третьей ошибкой того же дня.**
**6. Диспозиция: пак движка лендится КАК ПОСТРОЕН, форма (б) уходит строкой бэклога.** Довод: построенное не ложно, а уже — оно слабее выбранной формы, но честно называет то, что считает; принудить зону к третьему полному прогону каталога (~2 часа) ради работы, которая по составу тянет на свой пак, — плата не за качество, а за темп. ⚠ Это НЕ случай эрраты 04.09-д («найденное и не починенное не превращается в долг решением о темпе»): здесь не найденный дефект откладывается, а СОЗДАЁТСЯ новая работа решением владельца. Шапка `pending owner` в `Ceiling.ShortfallMicroUSD` заменяется указателем на эту ноту при ближайшем касании зоны (05.09.2026, оркестратор №22). ✅

View file

@ -1010,7 +1010,7 @@ $1.6, спишем по факту», и закрытие после прого
| `POST`/`GET /exports` | движок: `tmctl build [--format epub,txt] [--out path] [--partial]` — EPUB 3 + чистый txt (`backend/internal/bookfile`), конверт `tm-build-v1`, пути в `StatusArtifacts.book_files`, отказ exit 16 `book_incomplete` | ⚠ **ПЕРЕ-СНЯТО 05.09: ОБЕ ПОЛОВИНЫ ПОСТРОЕНЫ.** Движковая — D39.175 (`8adcb86`); ПЛАТФОРМЕННАЯ дверь заленджена `adf5e53` (D39.194) и предъявлена живьём платным EPUB через API. Прежнее «открыта только дверь платформы» протухло на сутки. Дверь СТРОИТ через `tmctl build` (не читать файл у БД: там копия прежней сборки) и сверять `BuildReport` (`config_drift`/`stale_unknown`). ⚠ Это про ФАЙЛ КНИГИ; редакторский `tmctl export`/annot-v1 (D29.1а) — ОТДЕЛЬНАЯ, не закрытая работа | движковая половина — D39.175; дверь — пинг зоне платформы (её журнал, греп `Движок отдаёт книгу файлом`); annot-v1 — строка 49 / D29.1 |
| Условные чтения (`ETag`/304), сжатие | — | **ПОСТРОЕНО P7**`httpapi/conditional.go`; валидатор считается от БАЙТ ответа. Остаток строки 186 — шаги 35 (скоуп кадра, дельта-чтение, `staleTime`) | шаги 12 закрыты D39.153 |
| `Idempotency-Key` | — | **ПОСТРОЕНО P7**`httpapi/idempotency.go` + `pgstore/idempotency.go`, на ТРЁХ создающих вызовах (третий — дверь выдачи, `httpapi/exports.go`; было два до 04.09); ⚠ живой дефект под конкуренцией — `PD-369` | закрыто D39.153 |
| `bearerToken` — чем ВЫДАЁТСЯ токен | вход только ставит HttpOnly-куку (`login.go:338`) | сервер токен ПРИНИМАЕТ, выдать его нечем | носитель: research/28 §2 (Б-15) + **строка бэклога 270** (⚠ испр. 05.09: прежнее «строки нет» ложно); развилка «выдать либо снять обещание из канона» заказана платформенным паком 05.09 |
| `bearerToken` — чем ВЫДАЁТСЯ токен | вход ставит HttpOnly-куку (`login.go:338`); токен минтится ВНЕ ПОЛОСЫ оператором | ✅ **ЗАКРЫТО 05.09 платформенным паком:** `tmplatformctl token issue --user … --client …`, сессия обычная — видна в журнале входов под операторским провайдером и гасится `POST /auth/logout`. ⚠ Эндпоинта для выдачи НЕТ и по умолчанию не будет: дверь, выдающая себе учётные данные по HTTP, — другая модель угроз и ратифицируется отдельно. Прежняя редакция («выдать его нечем») стала ложной в момент лендинга и сутки противоречила самому канону (`openapi.yaml`, греп `minted OUT OF BAND`) | носитель: research/28 §2 (Б-15) + **строка бэклога 270** (⚠ испр. 05.09: прежнее «строки нет» ложно); развилка «выдать либо снять обещание из канона» заказана платформенным паком 05.09 |
| `Problem.localized` | — | объявлено, ни одним кодом не используется | носитель: research/28 §8 п.4 |
| `Note.code` как enum спеки | карта приложения А | не enum, пока не написаны фразы | ⚠ **прежний носитель «строка 148» МЁРТВ** (`a023e39`, 21.08; разбор — приложение А, п.3); живой носитель — строки бэклога **203 + 204** (словарь фраз) |
| Настоящие названия глав (`Chapter.heading` ≠ null) | парсер структуры | НЕ ПОСТРОЕНО | строка 160 (Этап 0) |

View file

@ -21,7 +21,7 @@
- **`--max-units` — ОБЪЁМНЫЙ потолок прогона, ортогональный денежному** (D39.165 §1б, принят D39.170). Ограничивает не деньги, а РАБОТУ: не больше N выходных ЮНИТОВ (гранулярность `units_total` манифеста — та же, в которой платформа продаёт главы) возьмут СЛОТ гранта в этом прогоне; юниты, отданные за $0 (резюм, ре-пин), ретраи и эскалации внутри юнита потолок не тратят. ⚠ **«Слот» ≠ «оплата», и с 03.09 это РАЗНЫЕ числа** (пак «число согласия», строка бэклога 232): юнит, который прежний прогон НАЧАЛ и не отгрузил, дописывается ВНЕ гранта, поэтому грант N оплачивает ДО 2N выходных юнитов — замерено приёмкой на живом раннере (грант 2 → `Paid()=4`, шесть вызовов провайдера). Единственный денежный бонд здесь — `--ceiling-usd`. ⛔ **Семантика переноса НЕ ратифицирована — слово владельца 03.09 «подумаем на этот счёт»**, и до его решения читать это как замеренный факт, а не как норму. Принимает только `translate`. **Остановка по объёму — ЗАВЕРШЕНИЕ (exit 0), не пауза:** словарь кодов выхода не расширялся и нового значения `Finished.Outcome` тоже нет — ⚠ **но с 31.08 признак едет ЧИСЛАМИ в кадре `finished` шва, а не только прозой** (D39.181 п.2, закон раскрытия: прозаическая строка отчёта до потребителя потока не доезжала): носитель — `Finished.Volume`, леджер доставки. Различение при этом живёт и в отчёте прогона, и в логе; отчёт разводит ДОСТАВКУ и ПЕРЕ-ДЕЛКУ. Носитель — `backend/internal/pipeline/volume.go:13`=`the VOLUME ceiling — the run's second stop`; словарь флага дословно — `backend/cmd/tmctl/invocation.go:143`=`Stopping on it is a COMPLETION (exit 0), not a pause`. ⚠ Проводка в платформу ГЕЙЧЕНА (`PD-422`): единственный писатель признака движения банка — дверь правок, рост АВТО-банка от майнинга флага не ставит.
- **`--ceiling-usd` — КНИЖНЫЙ потолок, не бюджет прогона.** Дословно из флага: «the book USD ceiling in force for THIS RUN ONLY — it OVERRIDES book.yaml `ceilings.book_usd` and is never written back. It caps the book's CUMULATIVE committed+reserved spend, not this run's increment…» (`backend/cmd/tmctl/invocation.go:142`=`the book USD ceiling in force for THIS RUN ONLY`; ⚠-коммент `backend/cmd/tmctl/main.go:260`=`--ceiling-usd is NOT a per-run budget`; многоточие закрывает обрыв цитаты — во флаге дальше стоит «, and must be > 0»). Ратификация — D39.122 п.2(в): пересчёт «пользовательский прирост → абсолют» — обязанность ПЛАТФОРМЫ, вторая денежная ось не заводится. День-потолок флаг НЕ перекрывает (PD-157). Проводка внутри: `Ceilings.BookUSD` в `Reserve` и именование сработавшего потолка в ошибке — `backend/internal/pipeline/stagerun.go:495`=`BookUSD: r.bookCeilingUSD()` и `backend/internal/pipeline/stagerun.go:559`=`overrides the book's ceilings.book_usd` (стоп = `errReserveCeiling`, `backend/internal/pipeline/escalation.go:49`=`var errReserveCeiling`).
- **Потолки — wiring, не семантика:** `Ceilings` намеренно исключены из `BriefHash` («Wiring fields (paths, ceilings, db) deliberately excluded», `backend/internal/config/book.go:345`=`Wiring fields (paths, ceilings, db) deliberately excluded`; канон — `backend/internal/config/book.go:369`=`canon := struct {`) ⇒ смена ДЕНЕЖНОГО потолка не двигает ни снапшот, ни ре-билл (D39.110 п.2б). ⚠ Верно ровно про ДЕНЬГИ: потолок СЕГМЕНТАЦИИ `edit_ceiling_out` в снапшот ВХОДИТ и меняет границы чанков (`backend/internal/pipeline/snapshot.go:34`=`EditCeilingOut int`).
- **`status --json` отдаёт фигуры платформе:** `committed_usd`, `reserved_usd`, `book_ceiling_usd`, `ceiling_pct` = 100·(committed+reserved)/book_ceiling (`backend/internal/pipeline/status.go:311`=`book_ceiling_usd,omitempty`; арифметика `ceiling_pct``backend/internal/pipeline/status.go:858`=`100 * (committed + reserved)`). Дневной фигуры в status нет (PD-157 — `platform/docs/DEFECT_REGISTER.md`, греп `PD-157`).
- **`status --json` отдаёт фигуры платформе:** `committed_usd`, `reserved_usd`, `book_ceiling_usd`, `ceiling_pct` = 100·(committed+reserved)/book_ceiling (`backend/internal/pipeline/status.go:311`=`book_ceiling_usd,omitempty`; арифметика `ceiling_pct``backend/internal/pipeline/status.go:869`=`100 * (committed + reserved)`). Дневной фигуры в status нет (PD-157 — `platform/docs/DEFECT_REGISTER.md`, греп `PD-157`).
- **Леджер = НИЖНЯЯ граница** (строка 78 бэклога, `docs/PROGRESS.md`, греп `Леджер денег = НИЖНЯЯ граница`): «2xx body decode failed (call IS billed)» — провайдер списал, попытка в `request_log` не попадает; живой замер D39.86 — 3 вызова из 14, неизвестность $0.015111 при леджере $0.114378; движок сеттлит оценку и печатает `estimated-cost rows: 3`. Канал виден, фикс — money-паком (дизайн GENERALITY_PHASE2 §5.6).
- **Согласие на пере-оплату — ДВИЖКОВЫЙ гейт**. Прогон, который пере-покупает уже оплаченные юниты дороже порога, ОСТАНАВЛИВАЕТСЯ и требует явного согласия. Порог по умолчанию ратифицирован D20.2-Q2: `min($0.50, 5% × ProjectedBookUSD)`. Носитель — `backend/internal/pipeline/rebill.go`, греп `rebillConsentThreshold`; единственная ручка книги — `rebill_consent_usd` (валидатор `backend/internal/config/book.go`, греп `rebill_consent_usd`; 0 = ратифицированный дефолт). ⚠ Порог считается БЕЗ контура банк-ролей (D39.182 §3), то есть срабатывает позже, чем подсказывает полная проекция.