193 KiB
Архив хроники — отчёты пака «ЗАКОН БАНКА ЧЕСТНО» и петли D39.191 (закрыты 04–07.09)
⚠ АРХИВНЫЙ СРЕЗ. При онбординге НЕ читать — только по конкретной ссылке. Вынесено из живого
docs/PROGRESS.md11.09 по мандату владельца на снос протухшей прозы (D39.239п.4). Здесь лежат отчёты ЗАКРЫТЫХ пунктов: шесть пунктов наряда (строки 210 · 113→46 · 134 · 140 · 184(а) и дофикс чужого пака), разметка свободы, самопроверка, «что не удалось», дофикс по приёмке 04.09 и два круга петлиD39.191— второй не замкнулся, третий замкнулся по содержанию, но не по условию. ⛔ Ничего отсюда не исполняется. Всё живое из этих отчётов ратифицировано нотами и заведено строками трекера; сюда вынесена ХРОНИКА, а не долг. Проверено перед выносом: ссылок на этот блок извне живого журнала — 0 (контроль: якорей видаPROGRESS.md:NNNв живых доках 17, ни один не указывает в этот диапазон; секции по имени вне журнала — 0 хитов на каждую из четырёх проверенных).
Пункт 1 — строка 210: род ПРОИЗВОДИТСЯ. ЗАКРЫТ, с честной границей доставки
Развилка выбрана ЧЕТВЁРТАЯ, которой в промте не было: род производит существующий фокус-проход КЛАССИФИКАТОРА (runClassifier), третьим полем ответа. Довод: ноль новых вызовов (проход уже гоняется по тем же кандидатам с теми же контекстами) при цели №5 «низкий COGS»; род — свойство сущности, выводимое из контекстов, то есть акт классификатора, а не выбор рендеринга; парсер классификатора позиционный и закрыто-словарный, тогда как третье поле терминолога — уверенность, вокруг которой написана деликатная развязка мис-сплита по живому дефекту «наставник 95%». Цена: двигается RequestHash ТОЛЬКО классификаторных вызовов; терминологические чекпоинты книг живы. Ратифицировано оркестратором.
Построено. Промпт пары prompts/zh-ru/classifier.md v2 — третье поле, закрытый словарь male|female|neuter|none. ⚠ hidden в словарь НЕ входит НАМЕРЕННО: «пол скрыт до раскрытия» — решение о сюжете и спойлерной политике книги, а не наблюдение по KWIC-строкам; ошибочная догадка де-гендерила бы обычного персонажа на всю книгу. Остаётся ручным, в сиде. none — полноценный ОТВЕТ, а не пропуск колонки: без слова для «рода нет» единственный способ это сказать — не писать колонку, что неотличимо от «модель перестала отвечать».
Go: terminology.Genders + ParseTypes возвращает types, genders, stats; ReplyStats.BadGender/NoGender — два счётчика, потому что это два разных отказа; pipeline.attachClassifiedGender; miner.Term.Gender → DeltaFile → сид-YAML → сайдкары → банк.
Гарантия, которую держит тест: колонка рода НИКОГДА не стоит классу — значение вне словаря отбрасывается и считается, класс сохраняется (TestTheGenderColumnNeverCostsTheClass).
⛔ ГЛАВНАЯ НАХОДКА ПАКА: ЗАМКОВ ТРИ, И НАЗВАННЫЙ В ПРОМТЕ — НЕ СВЯЗЫВАЮЩИЙ.
bankmaterialize.go держит ДВА банка: черновая волна выбирает по baseMemory, из которого строки Source:"mined" вычеркнуты ПО ПОСТРОЕНИЮ, редактор видит обогащённый. Авто-банк пишется как mined (mining.go:671), подписанная дельта — тоже (mining.go:896, дословно «override the seed loader's Source:seed → mined (base-excluded)»). ⇒ на ЧЕРНОВОЙ провод произведённый род не едет и не поедет: там нет самой СТРОКИ. Это не дефект — это денежный контракт D39.42 п.3: инъекция черновой волны байт-стабильна поперёк обогащения банка, иначе пере-снапшот платит две волны вместо одной. Не трогал и не предлагаю.
Формулируй границу так и не короче: род производится авто-путём и доезжает до РЕДАКТОРСКОГО провода в том же прогоне, что его произвёл; на ЧЕРНОВОЙ не едет, пока цена двух волн не решена отдельно. Не «род построен».
Второй замок СНЯТ по ратификации оркестратора, и снят РАСЩЕПЛЕНИЕМ, а не целиком. Disp сворачивал два вопроса — СТАТУС строки и надёжность МАТЧА. D39.104 п.1 упраздняет разнобой по статусу («банк на проводе = закон независимо от статуса строки»), но про матч там нет ни слова и быть не может: род, приписанный не той сущности, — ошибка, а не неподписанность. Заведено поле PickedEntry.KeyTrusted + тип InjectionTrust{Disp, KeyTrusted}, который несёт ОБА факта через липкое окно (у липкого переноса нет своего ключа, и матч-половину, как и диспозицию, восстановить нечем). Род теперь гейтится KeyTrusted на ОБОИХ блоках; статус не решает ничего.
Сквозное доказательство — три двери порознь, а не «работает» (internal/pipeline/gender_wire_test.go): (1) неподписанная строка на доверенном ключе НЕСЁТ род редактору в том же прогоне; (2) collision-prone матч не несёт НИКУДА, при ЛЮБОМ статусе (юнит-проверка: на zh ветка не срабатывает физически, ханьские ключи якорятся на 2, поэтому сквозной zh-фикстурой её достать нельзя); (3) на черновой провод род не попадает НИКОГДА — и утверждение перевёрнуто нарочно: откроет кто-то дверь 3 — тест покраснеет и заставит автора назвать, какую именно.
Отрицательный контроль есть: TestASignedGenderBeatsTheProducedOne — сид владельца побеждает, и не порядком присваивания, а тем, что loadAutoBank роняет предложение движка на занятый подписью ключ.
Команда: go test ./internal/pipeline/ -run 'Gender' -v.
⚠ Пункт 4 — ПРЕДПОСЫЛКА пункта 1 в бою. Род производится только когда включён classify_types. Без банкового контура в боевом конфиге род не производится ни при каком варианте развилки.
Пункт 2 — строки 113 → 46: база записана, экран построен. ЗАКРЫТ
113 — СТОП СНЯТ, все три порога пройдены. Корпус взят исполнением: все чекпоинты всех 162 БД стенда, через СОБСТВЕННУЮ предобработку движка (splitBanknote → checks.StripThink — тот текст, который видит гейт), дедуп по хешу, только отгрузочные роли (банк-роли исключены: их ответы законно состоят из исходных термов, и включив их, мерили бы исключение, а не гейт). Обход дал 1162 ответа: 30 off-target, 1132 здоровых — но ⚠ в РЕПОЗИТОРИЙ уехала ВЫБОРКА, и все числа ниже воспроизводимы над ней, а не над обходом: 74 строки, все 30 off-target плюс 44 ЗДОРОВЫХ, отобранных нарочно трудными (20 с высшей долей исходного письма, 15 с низшей долей целевого, 3 под полом улики, остальное — спред). Тексты в git не поехали, довод — в шапке offtarget_corpus_test.go.
Разметка НЕ гейтом, иначе она была бы пересказом вердикта: off-target = доля КИРИЛЛИЧЕСКИХ букв < 0.5 — свойство ЦЕЛЕВОЙ стороны, независимое от проверяемого исходно-письменного гейта. Корпус разделяется полностью: здоровые все выше 0.9, off-target все ровно 0.0000, полоса между ними ПУСТА.
Числа воспроизведены и совпали с опубликованными до знака: худший здоровый source-share 0.011655 (контракт называл 0.0117), запас 12.87× против порога 0.15 (контракт называл 13×), ноль ложных на 44 трудных здоровых (не на 1132 — над репозиторием проверяемо именно это), поймано 28 из 30 (контракт называл 18 из 20 на более узком срезе того же стенда — та же доля, те же два промаха). Промахи — два беглых АНГЛИЙСКИХ черновика на 4690 и 4811 букв, ровно те, что названы в EFFORT_HANDLE §3.1. Худшая здоровая доля ЦЕЛЕВОГО письма 0.9767, максимум у off-target 0.0000, самый короткий off-target 346 букв — все три числа контракта воспроизведены.
Команда: go test ./internal/pipeline/ -run 'OffTargetCorpus|LiveEchoGate|LatinOffTarget' -v.
⚠ ЧЕГО ФИКСТУРА НЕ НЕСЁТ, и это мой выбор с ценой. testdata/offtarget-corpus.json несёт РУНОСЧЁТ каждого образца (всего рун, рун исходного письма, букв, букв целевого письма), происхождение, метку и шестидесятирунную голову для человека — но не тексты. Тексты — копирайтная вебновелла и её машинные переводы, которые репозиторий держит вне git намеренно (стенд версионируется отдельным репо, example/ возит собственный фрагмент по той же причине). Руносчёта достаточно ПО ПОСТРОЕНИЮ: обе проверяемые функции — отношения классов рун и ничего больше не читают, и тесты кормят НАСТОЯЩИЕ функции скрипт-верным суррогатом, собранным из счётчиков, а не считают арифметику вместо них. Названная потеря: детектор, который будет читать слова, n-граммы или орфографию, на этой фикстуре не измеряется — ему нужен повторный обход стенда.
46 — экран построен формой (а) плана §5.4 и заморозкой D39.92/D39.93. Отдельный пакет чистых функций internal/langscreen (вход: текст + скрипты цели; выход: ИМЕНОВАННЫЙ вердикт on_target|off_target|abstain + счёт и объём улики). Порог OnTargetFloor = 0.50 — КОНСТАНТА в пустом интервале, не тюнинг (гарантия Неймана–Пирсона на этом корпусе не покупается — D39.92 п.1а); пол улики MinLetters = 200 калиброван, а не выбран: самый короткий off-target 346 букв, ниже пола падают три здоровых. Носитель данных — lang.LangScripts, НОВОГО эмбед-файла не заведено.
Флаг СВОЙ — FlagOffTargetLang, FlagCJKArtifact НЕ переиспользован (D39.93 п.2), явный вход в escalatable(), не retryable. classifierVersion v2 → v3, и версия правила langscreen.Version вплетена в литерал, так что правка ВНУТРИ модуля двигает снапшот сама, а не по дисциплине.
Приёмочный критерий §5.4 шага 5 исполнен: офлайн-прогон по корпусу — экран новооткрывает РОВНО два ответа, оба английские, здоровых не двигает ни одного (в тесте это Fatal, а не Error: план требует СТОП). Вдвоём два правила ловят 30/30 при нуле ложных.
Команды: go test ./internal/langscreen/ -v · go test ./internal/pipeline/ -run 'TargetScreen|TwoScreens|BankRoleReply' -v.
Вторая половина дыры закрыта тем же диффом: detectLatinInsertion теперь под c.TargetScriptNonLatin() (internal/checks/sanitizer.go). Правило существовало в прозе доккоммента и стояло только на пути репэйра; первая же латинописьменная цель уронила бы КАЖДЫЙ чанк чистой целевой прозы как «Latin insertion». Для ru вердикты не двигаются ни на байт (предикат истинен) ⇒ бампа версии санитайзера не требуется.
⚠ НАХОДКА, приехавшая ВМЕСТЕ с паком, а не до него. Экран и эхо-гейт обязаны молчать на ответах банк-ролей: их буквы — движковые идентификаторы и исходные термы, поэтому эхо-гейт флагал бы их (и флагал: verdict=cjk_artifact при bad_lines=0 на чистой пробе 6/6), а экран флагал бы ВТОРЫМ способом. Исключение было записано как role == roleTerminologist и КЛАССИФИКАТОРА не покрывало (13-tech-debt-anchors §Б-105) — латентно, пока ни один боевой конфиг классификатор не включал. Пункт 4 его включает. Поле переименовано в NonProseReply (оно про ФОРМУ ответа), предикат один — isBankRole, рядом со строкой, которую новая банк-роль и так обязана добавить в bankRoleSettings.
Пункт 3 — строка 134: рендер снят, данные не тронуты. ЗАКРЫТ
Выбор объявлен: снят РЕНДЕР в Go. Механизм, по которому выбор сделан: cutTag сворачивает lang.EmbeddedVersion(), injection.txt лежит в internal/lang/data/ ⇒ правка данных пере-чеканила бы unit.id всей книги → manifest_key → снос unit_resolutions у платформы (строка 198). RenderFormatVersion в cutTag НЕ входит — он фолдится только в снапшот. Предъявление — первой строкой этого отчёта.
Текст заголовка не менялся вовсе, и это проверено, а не принято на веру: действующий editor_header БАЙТ-ИДЕНТИЧЕН арму AM-noclause пробы 18 (experiments/18-editor-wire-probe.md §0.3 дословно: «Закон БЕЗ оговорки = действующий editor_header без единой правки»). Оговорка области НЕ внесена (опровергнута §A.4).
Что изменилось: маркер ⟨проверить⟩ не рендерится НИ В ОДНОМ блоке; секция editor_unverified_header не рендерится, две секции редактора схлопнуты в один закон-блок; неподписанные строки стоят в нём под тем же заголовком и ничем не помечены. Статусы строк и подписная таблица не тронуты (D39.104 п.1). RenderFormatVersion v3 → v4.
Ревью-ось «маркер снят, а пост-чек жив» проверена: membank.Postcheck ключуется на p.Disp, маркера не читает — обработка Ambiguous цела, счётчики Shown/Followed живы. ⚠ Но их СМЫСЛ сузился, и это записано в код: они родились на проводе, который помечал строку и приглашал модель её отвергнуть; теперь неподписанная строка показана законом, отклонение — просто отклонение, а не «модель пользуется дарованным правом». Та же поправка внесена в доккоммент миграции v12, которая эти колонки завела.
Операторские тексты, которые стали бы ложью, переписаны (не комментарии — то, что печатается человеку): две строки tmctl про «уедет к редактору с пометкой ⟨проверить⟩», строка Unsigned bank terms в report, WARN стопа майнинга, WARN конфликта с подписанным банком.
⚠ НАХОДКА, которую я НЕ ЧИНИЛ и которая теперь висит на строке 250 (носитель заведён оркестратором): строка данных ru glossary_header САМА ОПИСЫВАЕТ снятый маркер («строки с пометкой ⟨проверить⟩ — неподтверждённые кандидаты»). После пака помеченных строк на проводе нет, а заголовок продолжает объяснять модели пометку. Это не мёртвая строка данных (editor_unverified_header и unverified_marker — те просто перестают читаться, и обе оставлены ОБЪЯВЛЕННЫМИ полями, потому что их СТРОКИ остаются в эмбеде, а parseInjection отвергает незнакомый ключ), а ЖИВАЯ строка с висячей ссылкой. Чинится только правкой injection.txt, то есть ценой cutTag. По D39.104 п.1 клаузула становится ВАКУУМНОЙ, а не ложной; вред не измерен.
Пункт 4 — строка 140: контур внесён в c1. ЗАКРЫТ с НАЗВАННЫМ предусловием развёртывания
Внесено в configs/pipeline-c1.yaml: gates.banknote.enabled: true + prompt_override: ../prompts/zh-ru/translator-banknote.md на стадии draft со своим лейблом (D39.10: включение банкноты — ДВА согласованных изменения; сам гейт только СРЕЗАЕТ блок, инструкцию писать его несёт промпт) · gates.terminology (модель deepseek-v4-flash, reasoning: low — у рендер-фазы это вынужденно, на вендорском дефолте она сжигает бюджет размышлением и возвращает пустое тело) · classify_types: true · mining.contrast_path.
Суб-бюджеты — числа и их довод. Множитель ×4.47 чинит пере-пин цен DeepSeek и ТОЛЬКО его; прежние 0.05/0.02 размерены под десятиглавую пробу, а этот файл обслуживает книги целиком. Замер (строка 16, десять глав, июльские деньги ×4.47): терминолог $0.0257, классификатор $0.0344. Бюджеты КНИГО-ШИРОКИЕ и копятся по всем прогонам книги (store.RoleSpentUSD суммирует чекпоинты роли по всем её джобам), а кандидатное пространство терминолога зависит от того, какие чанки уже отчерновлены, — значит между покупками оно меняется, request_hash другой, и книга, проданная десятью покупками, платит десять книжных консолидаций. Пол ⇒ 0.257 / 0.344. Взято 1.00 / 1.00, запас 3.9× / 2.9×.
⚠ Первая редакция дала классификатору 0.50, то есть запас 1.45×, а комментарий рядом обещал «≈3×» — число одной величины под именем другой. Поймано МОИМ ЖЕ адверсариальным проходом, исправлено: по замеру классификатор ДОРОЖЕ рендера, и «половина» пришла из старых чисел, а не из измерения. Бюджеты остаются раздельными при равных значениях: разделение про то, чтобы перерасход одной фазы не голодал другую.
Пин: TestTheBankRoleBudgetsClearTheirMeasuredCost — это ПОЛ, а не значение; поднимать можно свободно, опускать ниже замеренного нельзя.
⛔ ПРЕДУСЛОВИЕ РАЗВЁРТЫВАНИЯ, названное вслух: mining.contrast_path — единственный вход контура, которого нет в git. ОБА банк-роля живут ВНУТРИ стопа майнинга, и runBankMiningStop возвращается РАНЬШЕ построения хоть одного кандидата без корпуса контраста. Артефакт (jieba-словарь общей частотности, 5 МБ) под .gitignore намеренно, но ВОСПРОИЗВОДИМ — рецепт и sha256 запинены в docs/experiments/16-bank-mining.md. Носитель требования к рантбуку и слово оператора — строка 251 (заведена оркестратором).
Два гарда, которые делают «настроено и мертво» невозможным — и оба нашлись не по заказу, а по разбору:
- Загрузка отказывает, если гейт включён, а
mining.contrast_pathПУСТ (internal/config/pipeline.go) — тот же класс «гейт, который не может выстрелить», который лоадер ловит везде. - Наличие ФАЙЛА проверяется на ПИШУЩЕМ пути, рядом с
CheckKeys(Pipeline.CheckMiningContrast, вызов вopenRunnerвнутриforWrite). Место выбрано не случайно:os.Openвнутри прогона стоит ПОСЛЕ оплаченной черновой волны, то есть развёртывание, забывшее артефакт, платило бы за волну, чтобы это узнать. $0-поверхности не трогаются (D20.4). - ⚠ ТРЕТИЙ гард добавлен по находке адверсариального прохода, и он закрывает дыру в моих же первых двух. У раннего возврата ДВА условия, и я гейтил только одно:
r.pack == nil— а нил-пак книга получает, если не объявилаlangpack_rootвовсе или объявила корень без каталога своей пары («nil-and-run»). Такая книга могла нести полностью настроенный и забюджетированный контур и не исполнить из него ни строки. Конфиг-лоадер этого структурно не видит: гейт знает пайплайн, пак знает книга, и вместе они есть только в раннере. Отказ добавлен там, тоже только на пишущем пути.
Пункт 5 — строка 184(а): жанр выкинут. ЗАКРЫТ
grep -rl '{{genre}}' backend/prompts/ | wc -l → 6 → 0. Поле снято из канона брифа (BriefHash), {{genre}} снят из плейсхолдеров pipeline.Render — значит промпт-пакет пары, написанный позже с этим маркером, падает ГРОМКО на первом рендере, а не подставляет пустоту. Репо-гейт на ту же вещь: TestNoShippingPromptAsksForTheGenre.
BriefHash двинулся у ВСЕХ книг (c2021b1b… → 4624529b… на голден-фикстуре) — это заказано D39.138 п.2в и внесено в общее окно пере-снапшота именно потому, что платится один раз со всем батчем.
⚠ Ключ genre: ОСТАВЛЕН ПРИНИМАЕМЫМ, и это не мягкость. Платформа пишет книге book.yaml ОДИН раз из шаблона оператора и никогда не перезаписывает, протаскивая незнакомые ключи насквозь — genre там назван явно (platform/deploy/README.md). Декодер движка строгий (KnownFields), поэтому удаление поля отказало бы в загрузке книгам, которые уже лежат на диске, посреди живого прогона соседней сессии. Идиома — та же, что у ретированного adult: false. Значение не читается ничем: TestARetiredGenreKeyStillLoadsAndReachesNothing держит и загрузку, и равенство BriefHash у двух книг, отличающихся только жанром.
⚠ Лейблы промптов бампнуты и леджер пере-записан (v1-reflow → v2-reflow-nogenre, v3-discourse-reflow → v4-discourse-reflow-nogenre): байты промптов уехали, а лейбл обязан следовать за ними — иначе два прогона под одним лейблом несравнимы, что этот гейт и ловит. Тем же касанием в свип леджера добавлен КЛАССИФИКАТОР: он был вне его, пока ни один боевой конфиг его не включал, а его промпт решает КЛАСС термина, то есть маршрутизирует имя в транскрипцию, а реалию в перевод.
⚠ genre: ранобэ НАМЕРЕННО оставлен в testdata/golden/book.yaml с комментарием «не прибирать»: это место, где терпимость к ретированному ключу упражняется на каждом захвате.
Пункт 6 — дофикс чужого пака + ФЧ-7. ЗАКРЫТ
⚠ Это остаток ЧУЖОГО наряда (D39.187 п.4), а не мой заказ — сессия, делавшая тот пак, не пережила рестарт окружения.
(а) Развилка операторской строки прибита со ВТОРОЙ стороны. Воспроизвёл сам: ДВЕ посадки в новый код VolumeStop.String() переживали всё дерево (проверено с GOFLAGS=-buildvcs=false, иначе cmd/tmctl падает на VCS-штампе копии и маскирует результат) — (1) развилка заголовка всегда истинна, (2) развилка заголовка спрошена про ПЕРЕНОС вместо ОСТАТКА. Обе печатают в смешанном состоянии «reached the END of the book … Still in the book: 1 unit(s) NEVER delivered». Прибито TestTheStopLineSaysTheGrantHeldWorkBackWhenItDid — таблицей из ДВУХ строк, потому что две потери теряются на разных состояниях: всегда-истинная падает на любой, а спрошенная-про-перенос только там, где перенос и остаток оба ненулевые. Записи каталога WB1, WB2.
(б) Граница bound() прибита. Carried > 0 → Carried > 1 переживало: существующий тест переносит ДВА юнита. Прогон с ОДНИМ перенесённым на конце книги не отдавал отчёт вовсе — тихий лимит, анти-паттерн D39.165 §1б. TestOneCarriedUnitIsStillWorkOutsideTheGrant, запись WB3.
(в) Три числа отчёта — ПРОВЕРЕНЫ И СХОДЯТСЯ на HEAD. D39.187 п.4(в) говорит «протухли снова»; пере-снял все три их собственными командами до своей работы: батарея EXIT=0 с теми же тремя скипами · ^func Test 1105 · каталог 92. Отчёт 03.09 называет 1105 и 92. ⇒ пункт (в) закрыт лендингом f8d3e9a, и остатка по нему нет.
ФЧ-7 — ВОСПРОИЗВЕДЁН и ПОЧИНЕН. Починка СВЕРХ заказа, объявляю. Промт заказывал проверку исполнением и починку только при воспроизведении.
Первая попытка воспроизведения ПРОВАЛИЛАСЬ и это важно: после потолка фидер runWave перестаёт раздавать элементы, поэтому второй воркер паниковать не успевает. Нужна синхронизация, чтобы обе позиции были в полёте, — и тогда воспроизводится ровно как описано: runWave отдавал ТОЛЬКО панику, errors.As(err, &CeilingHalt) → false, errors.Is(err, errReserveCeiling) → false, terminal() падал в failed и события ceiling НЕ писал.
Почему это дефект, а не размен: platform/internal/runs/reconcile.go читает событие потолка ПЕРВЫМ и дословно говорит «that survives ANY exit: the process may have been killed on its way out, and the fact does not become less true». PD-113 закрыт ДВУМЯ независимо отказывающими каналами; одна паника забирала оба.
Починка узкая: runWave присоединяет к панике ТОЛЬКО *CeilingHalt — не context.Canceled (проверено посадкой: присоединение отмены роняет TestWaveWorkerPanicSurfacesAsAFailingError, и правильно, крах не должен читаться как вызванный им же graceful stop); terminal() проверяет панику ПЕРЕД потолком, пишет событие ceiling и исход failed. Код выхода 1 и зеркало «исход = код выхода» не двинуты. Пины: TestACrashOverACaughtCeilingKeepsBothFacts, TestACrashOverACaughtCeilingStillAnnouncesTheCeiling, TestACrashJoinedWithACeilingStillExitsAsACrash.
ПЕРЕ-СКОУП строки 197 — как заказано. ФЧ-1/4/5 закрыты паком «число согласия» (D39.187). ФЧ-6 сверен кодом и выглядит закрытым: отказ проекции репортится базисом, отчёт не валится (internal/pipeline/status.go, греп RebillBasisFailed). ФЧ-7 закрыт этим паком. ФЧ-2, ФЧ-3 и ФЧ-8 НЕ ПРОВЕРЕНЫ НИКЕМ и остаются живым остатком строки — см. секцию «Что НЕ проверено».
Свобода и её разметка — отчёт ПО КАЖДОЙ строке таблицы промта
«Делай РОВНО так» — исполнено всё, отступлений нет: порядок 113 → 46 соблюдён (база записана ДО стройки экрана) · СТОП по фикстуре не сработал, все три порога пройдены с запасом · текст заголовка не менялся · статусы строк и подписная таблица не тронуты · нота бита спеку у FlagCJKArtifact — флаг СВОЙ · суб-бюджеты ×4.47 как ПОЛ, взято выше с объявленным доводом · жанр снят и из промптов, и из канона брифа · обе посадки дофикса краснеют · ФЧ-7 проверен исполнением (и починен сверх заказа — объявлено) · все запреты «Границ» соблюдены.
«Решаешь сам и аргументируешь» — по каждому пункту решение и довод выше: развилка производства рода (§1) · второй замок — ВЫНЕСЕН пингом и ратифицирован оркестратором расщеплением, сам не снимал (§1) · данные в 134 — НЕ тронуты, объявлено первой строкой (§3) · числа суб-бюджетов (§4) · форма фикстуры 113 (§2, с названной ценой) · форма тестов и записей каталога · порядок работ (6 → 5 → 3 → 1 → 4 → 2, голден один раз в конце).
Границы: manifestVersion, StreamVersion, схема хранилища и версия контракта НЕ двинуты (предъявлено tmctl manifest) · новый эмбед-файл не заведён · FlagCJKArtifact не переиспользован · семантика переноса слота не тронута · строки 131 · 105(а) · 14 · 119 · 124 · 115 · 160 · 161 · 142 не брались · чужие зоны, .env и соседний worktree не трогались.
Самопроверка исполнением
1. Дифф ^func Test ПОФАМИЛЬНО. grep -rn '^func Test' backend --include=*_test.go | wc -l → 1105 → 1143, добавлено 39. Удалённых имён ОДНО: TestEditorSectionFollowsProvenance — переименование, разбор в шапке.
2. Голден пере-захвачен ОДИН раз, маскированный дифф разобран построчно. 22 строки провода + 252 версионных. Диспозиций, флагов и chunk_status не двинулось ни одного (diff по этим строкам пуст; 252 строки до и после).
⚠ Поправка к моей же формулировке, найденная адверсариальным проходом: сказать «финальные тексты не изменились» было БЫ неверно. final_text изменился на всех 8 chunk-строках и stage_text на 22 — но ровно на ТОКЕН ХЕША, который фейк-провайдер эхом вкладывает в свой ответ, то есть следствием сдвига запроса, а не сменой вердикта. Точная формулировка: вердикты не двинулись; каждый финальный текст отличается только эхом хеша запроса.
⚠ Вторая поправка того же прохода: в ГОЛДЕНЕ двинулись brief_hash, classifier_version, render_format_version и prompt_sha256 ЧЕРНОВОЙ стадии — а memory_version и prompt_version НЕ двинулись (у фикстуры свой лейбл v-golden, а токен фолда неподписанных строк заморожен намеренно). Мой первоначальный перечень осей был шире фактического. memory_version двигается на книге с гендерными строками, а не в этой фикстуре.
3. Собственные посадки ВНЕ шести пунктов — 8, механизмом cmd/tmmutate на копии дерева. 6 красных, 2 ПЕРЕЖИЛИ и НЕ чинены (вне заказа, носитель — строка 252): StickyDepth = 2 → 1 не ловит никто · priorityRank, отбрасывающий приоритет доверия в бюджете инъекции, не ловит никто. Третья пережившая — cutTag без lang.EmbeddedVersion() — ПОЧИНЕНА по своей инициативе, потому что на этом компоненте стоит весь довод пункта 3 (TestTheCutTagActuallyCarriesTheEngineData, TestEveryCutInputMovesTheTag, запись WB4; cutTag разложен на cutInputs/tag() — рефактор байт-нейтрален, предъявлено сборками из HEAD и из дерева).
⚠ Методическая заметка, стоившая ложного результата: tmmutate на копии дерева НЕ МОЖЕТ судить тесты cmd/tmctl, которые собирают бинарь, — копия не git-репозиторий и сборка падает на VCS-штампе, маскируя всё остальное. Гонять копию с GOFLAGS=-buildvcs=false.
4. Отдельный проход по СВОЕЙ ГОТОВОЙ работе свежим контекстом — ДВА агента, модель fable, оба read-only, с заданием ФАЛЬСИФИЦИРОВАТЬ шесть заявлений каждый (деньги и провод · вердикты и данные). Ноль не декларирую: они принесли шесть находок, и четыре я починил.
Находки собственного адверсариального прохода — что нашли и что с этим стало:
- ⛔
bank-applyСТИРАЛ произведённый род — то есть ровно тот акт, ради которого стоп существует.termFromBankкопировал толькоTypeиAliases; строка дельты уходила сgender: "", аloadAutoBankпотом ронял авто-строку как занятый ключ. ПОЧИНЕНО: род переносится вперёд, как переносятся алиасы (это находка движка ОБ СУЩНОСТИ, а решение о РЕНДЕРИНГЕ не просили её выбрасывать); дверь по-прежнему род не ПРИНИМАЕТ. ПинTestApprovingATermKeepsTheGenderTheEngineProduced, проверен красным на копии без правки. - ⛔ Мой первый гард пункта 4 закрывал только одно из ДВУХ условий раннего возврата. Второе —
r.pack == nil, а нил-пак книга получает безlangpack_rootили с корнем без каталога своей пары. Такая книга несла бы настроенный и забюджетированный контур и не исполнила бы ни строки. ПОЧИНЕНО третьим гардом в раннере (пишущий путь), где гейт и пак есть вместе — конфиг-лоадер этого структурно не видит. - ⛔
repairReGateзвалclassifyБЕЗTargetScripts— экран цели на пути ремонта воздерживался, судя везде: починка, вернувшаяся на другом языке, прошла бы ре-гейт, вся работа которого в том, чтобы спросить «это всё ещё пригодный ответ». ПОЧИНЕНО: ре-гейт зовёт тот же классификатор с теми же входами. - ⛔
classify_budget_usd: 0.50давал запас 1.45×, а комментарий рядом обещал «≈3×». ПОЧИНЕНО: 1.00, запас 2.9×, и названо, что по замеру классификатор ДОРОЖЕ рендера. - ⛔ Тест
TestTheLiveEchoGateKeepsItsMeasuredMarginпроходил на фикстуре с ПУСТЫМ off-target классом:0/0= NaN, а любое сравнение с NaN ложно. ПОЧИНЕНО знаменателем-предусловием. Тем же касанием: суррогат целевой стороны привязан к записанному счёту (как уже был исходный), добавлены проверкаtarget_script_letters ≤ lettersиTestTheScreenConstantsStillSitWhereTheCorpusPutThem— константыlangscreenсверяются с ДАННЫМИ, а не с константами (порог обязан лежать в пустом интервале корпуса, пол улики — не выше самого короткого off-target). - ⚠
allowshort_wire_test.goутверждал ОТСУТСТВИЕ маркера — после пункта 3 это утверждение не может упасть. Заменено на то, что фикстура ещё способна держать:allow_shortдоставляет строку ЦЕЛИКОМ, вместе с её родовой директивой. Плюс поправлены четыре комментария, ставшие ложью:decisions.go(«род — сид-онли без автопроизводителя»), доккомментlangscreenпро →en,BriefHashпро исторический хеш, и три стейл-упоминания маркера в тестах зоны.
Что НЕ удалось и что НЕ проверено
⚠ Исходов ТРИ, и «не проверено» ≠ «опровергнуто» ≠ «сделано».
НЕ ПРОВЕРЕНО (никем, включая меня):
- ФЧ-2, ФЧ-3, ФЧ-8 строки 197. Их я не открывал вовсе. ФЧ-2 — два докстринга
reprice.goописывают не то, что делает код (детекция перебора односторонняя; «остаток несётся по счёту» неверно). ФЧ-3 — снятый закон approved-only продолжает утверждаться в докстринге теста и вbackend/docs/D15.2-*.md:317. ФЧ-8 — докстрингTranslateBookпро «каждый выход черезterminal()» неверен для паники вне волны · комментарийdispatchCommands· шапка рига. Живой остаток строки 197. - Ничего в этом паке не проверено ПЛАТНЫМ вызовом. Ни одна модель не вызывалась: санкции на деньги у меня не было и я её не просил. Всё измерено на персистированных чекпоинтах стенда и на фейк-провайдерах.
- Качество рода не измерено. Что классификатор реально отвечает в третьей колонке на живой книге — не мерено ни разу. Промпт написан консервативно (
noneобъявлен самым частым и правильным ответом при нехватке контекстов), но верно ли он определяет пол — вопрос замера, а не стройки. ⚠ Это ПЕРВЫЙ кандидат в следующий полигон-пак: ось рода теперь производит данные, и ложныйmaleпоедет консистентно через всю книгу — то самое свойство, ради которого консистентность и строилась. - Экран цели не проверен на живом провале. Он ловит два образца, которые уже лежат в стенде; поведёт ли он себя так же на СВЕЖЕМ off-target событии — не мерено. Порог 0.50 стоит в пустом интервале и не калиброван (и это по
D39.92п.1а и не может быть иначе на этом корпусе). - Цена банкового контура в c1 на реальной книге не мерена. Числа суб-бюджетов — проекция от десятиглавого замера, не наблюдение. Первый же боевой прогон с контуром даст настоящие числа, и их надо сверить с полом.
- Наличие корпуса контраста на БОЕВОЙ машине. Я его не видел и видеть не мог. Строка 251.
НЕ СДЕЛАНО СОЗНАТЕЛЬНО (с доводом):
- Замок №0 не трогал — базовый банк исключает
Source:"mined"по денежному контрактуD39.42п.3. Следствие названо в §1: род не едет на ЧЕРНОВОЙ провод и не поедет, пока цена двух волн не решена отдельно. Не моё решение. ru glossary_headerне тронут — висячая ссылка на снятый маркер, чинится только правкойinjection.txt, то есть ценойcutTag. Носитель — строка 250.- Две пережившие мутации не чинены — вне заказа, носитель 252.
- Строка 204 /
PD-246: карту причин платформы не правил — чужая зона. Пинг отправлен напрямую (textmachine-main-34), она пере-сняла счёт своей командой и завела у себя; состав контрактного минора несёт оркестратору, потому что изобретать код замечания платформенная сессия не вправе.
НАЙДЕНО И НЕ ЧИНЕНО — ЧУЖИЕ ЗОНЫ (передаю фактом, не правкой):
- ⚠ Следствие починки ФЧ-7 на стороне платформы, которого я не предвидел.
pgstore/sink.goкладёт событиеceilingвpaused_reason, аruns/reconcile.go:1008возвращаетpausedсexit_code = nil. ⇒ прогон, который УПАЛ поверх потолка, теперь приезжаетpausedи КОД ВЫХОДА теряется — крах становится невидим на строке прогона. Это лучше прежнего для пользователя (ему говорят «добавь денег», и это правда и действие), но хуже для операций. Взвесить и решить — не мне; несу как факт. - ⚠ Стейл-упоминания снятого маркера вне моей зоны:
platform/internal/runs/spawn.go:164(прод-комментарий),platform/internal/runs/reconcile_test.go:723,platform/docs/DEFECT_REGISTER.md:412(PD-277),eval/pilot/memory_eval.py:440-452(заявляет «byte-synced with Go glossaryBlockHeader» и по-прежнему дописывает маркер построчно — зеркало провода в полигоне разъехалось). - ⚠
platform/deploy/ничего не знает о корпусе контраста (grep -rn 'contrast_path\|mining:' platform/deploy/→ пусто). Половина строки 251. - ⚠ Дыра покрытия, найденная платной сессией и переданная мне (
PD-441, её ряд): вызов, отменённый В ПОЛЁТЕ по книжному потолку, уходит веткой «No 2xx ever arrived: nothing was billed» →releaseReservationи нулевая цена вrequest_log, хотя замер 04.09 показывает отмены на 120756/156469/156470 мс — то есть запрос был выпущен и, скорее всего, оплачен. Латентность разводит два случая (20–31 мс против 156 с). Я это НЕ чинил:stagerun.goв моей зоне, но это ДЕНЕЖНЫЙ путь и отдельный предмет, а не пункт вайр-батча. Заказ на него — отдельным паком.
ЧЕГО Я НЕ ДЕЛАЛ ПО ГРАНИЦАМ: не коммитил, индекс и историю не трогал; platform/ и eval/ только читал; соседний worktree не открывал; .env не читал.
ДОФИКС ПО ПРИЁМКЕ (04.09) — четыре пункта наряда, все закрыты
⚠ Класс, который приёмка вскрыла и которого моя самопроверка не нашла: СЕМЬ ЗАЯВЛЕННЫХ ГАРАНТИЙ СУЩЕСТВОВАЛИ ТОЛЬКО КАК КОД. Двенадцать её посадок пережили полную батарею. Это ровно образец D39.187 — тот же дефект, что этот пак чинил у чужого пака, повторённый мной. И нашёлся он там, где я сам сказал «ставь гуще», то есть карта слепых зон работает; чего у меня не было — это привычки сажать мутации на СВОЙ новый код, а не только на соседний.
Д1 — пять неприбитых гарантий прибиты, каждая тестом И записью каталога (WB5–WB13, каталог 96 → 105, все красные одним прогоном).
· F2, тяжелейшая: живая доставка строки 46 не была прибита вовсе — grep -rn 'FlagOffTargetLang' --include=*_test.go давал ПУСТО. Модуль экрана был прибит офлайн (по руносчёту фикстуры) и по своему пакету, а вердикт, ради которого он построен, на живом пути не проверялся ни разу: переживали и «экран всегда воздерживается» (Screen(out, nil)), и «chunkrun не передаёт TargetScripts», и снятие флага из escalatable() — прямое требование D39.93 п.2, без которого пойманный чанк молча ТЕРЯЕТСЯ вместо пере-атаки. Прибито: TestAnOffTargetCompletionIsFlaggedAndEscalated (вердикт + деталь + escalatable + !retryable + эхо остаётся эхом), TestTheScreenIsInertWithoutTargetData, TestTheRunnerHandsTheScreenItsData (через classifyOutput — ЕДИНСТВЕННЫЙ живой call-site, плюс исключение обеих банк-ролей).
· F10: порог экрана не был ИСПОЛЬЗОВАН ни в одном тесте — случая с долей между границами не было, то есть константа могла быть любой. TestTheOffTargetThresholdIsUsed: 0.60 → ok, 0.40 → флаг.
· F1: три гарда контура — TestABankContourThatCanNeverFireIsRefused (лоадер судит КЛЮЧ и не судит ФАЙЛ) и TestTheContourRefusesAWriteRunItCannotExecute (обе половины раннего возврата: отсутствующий артефакт и нил-пак; с ПРЕДПОСЫЛКОЙ, что до порчи фикстура открывается, и с обязательной проверкой, что $0-чтение той же книги ПО-ПРЕЖНЕМУ работает — D20.4).
· F5: гард TargetScriptNonLatin в санитайзере — TestTheLatinResidueClassIsGatedOnTheTargetsOwnScript, обе стороны. ⚠ Названная узость: target-en.txt в репо нет, поэтому «латинописьменная цель» достижима только через ПУСТОЕ объявление (та же ветка wordScript == nil); строку с настоящим word_script latin тест получит в день, когда такая цель появится.
· F6: исключение банк-ролей прибито было только юнитом на isBankRole; регресс до «терминолог-only» оставлял батарею зелёной. Теперь ловится через classifyOutput (WB7).
Д2 — $0-валидация плейсхолдеров ДО первого вызова. ДЕНЬГИ.
Приёмка подтвердила исполнением то, что я принёс и не починил, сочтя вопрос про громкость: отказ на {{genre}} приходил ПОСЛЕ купленной черновой волны (stage=draft cost_usd=0.001820, edit wave started, затем отказ; drafts=1 edits=0). Вопрос был про МОМЕНТ, и я его не расслышал. Построено: CheckPlaceholders сканирует шаблон по тому же ЗАКРЫТОМУ набору, что подставляет Render — набор вынесен в одно определение (renderVals), потому что два списка это и есть способ, которым валидатор благословляет имя, которое рендер отвергнет. Вызов стоит в LoadPromptTemplate — единственной воронке, через которую проходят ВСЕ шаблоны: стадии, классы репэйра и обе банк-роли. Живой источник таких пакетов настоящий: grep -rl '{{genre}}' eval/ | wc -l → 27.
⚠ Заказанная смена поведения, объявляю (D39.183): TestRenderRejectsUnknownPlaceholder описывал отказ ОТ Render; отказ переехал на загрузку. Тест не ослаблен — он теперь держит ОБА рубежа (гейт на загрузке И собственный отказ Render), плюс что закрытый набор проходит целиком, плюс что отказ НАЗЫВАЕТ и маркер, и то, что движок принимает.
Д3 — закон-блок даёт ОДИН приказ на исходный термин. Ратификация исполнена ровно так.
Дедуп переведён с (src,dst) на src. Довод, который я принимаю целиком и не смягчаю: пока у блока было два заголовка, две передачи одного термина были двумя РАЗНЫМИ высказываниями — «это канон» и «это неподтверждённый рабочий вариант»; мой же пункт 3 схлопнул их в два ПРИКАЗА об одном термине, а с разными родовыми директивами — в два противоречивых приказа об одном персонаже. Побеждает первая строка, и «первая» тут не случайность: Select отдаёт в приоритетном порядке, priorityRank ставит Confirmed раньше Ambiguous — то есть подписанная. Конфликт не спрятан, а РАЗВЕДЁН: движок уже пишет о нём WARN оператору (seeding.go), и это правильное деление — модель получает один закон, оператор получает разногласие. Отбрасывание строки на загрузке не бралось: это онтология банка, а нужна была узкая правка провода. Пин TestTheLawBlockGivesOneOrderPerSourceTerm кормит неподписанную строку ПЕРВОЙ (дедуп, хранящий первую строку ВХОДА вместо первой строки приоритета, прошёл бы фикстуру в естественном порядке) и отдельно держит, что ГОМОНИМИЧНЫЙ dst — два разных исходных термина — остаётся двумя строками.
Д4 — числа отчёта поправлены. F7: «ноль ложных на 1132» заменено на воспроизводимое над репозиторием — ноль ложных на 44 ТРУДНЫХ здоровых, с явным разделением «обход дал 1162/1132» и «в git уехала выборка 74 строк», и с описанием, как выборка отобрана. Это ровно класс «число одной величины под именем другой», который я чинил в пункте 4 и повторил в своём же отчёте. F8: расхождение шапки и секции самопроверки (1133/29 против 1135/31) снято — обе теперь 1143, добавлено 39.
⚠ F11 — РИСК ДИЗАЙНА, не чинен, называю (вход в калибровку). На латино-тяжёлом ЗДОРОВОМ русском экран цели даёт ложные off_target: русский с пиньинь-глоссами → 0.461, инструкции с shell-командами → 0.077. Ложный флаг ЭСКАЛИРУЕТСЯ, то есть стоит платного вызова. Корпус, на котором порог поставлен, — ОДНА сянься-новелла; жанр с системными окнами, кодом или плотной латинской терминологией не мерен вовсе. Перед первым платным прогоном книги другого жанра порог обязан быть пере-калиброван на её корпусе. Это не опровержение экрана (на измеренном жанре ноль ложных на трудных), это граница его калибровки.
Батарея после дофикса: MAKE_EXIT=0, 0 issues, 19 пакетов ok, скипы те же три. Голден пере-захвачен — 0 изменений (дофикс не двинул ни одного байта провода в фикстуре). Тесты 1105 → 1143, удалённых имён по-прежнему одно и то же переименование. Каталог 92 → 105, записи WB1–WB13 красные.
КРУГ 2 ПЕТЛИ (D39.191) — НЕ ЗАМКНУЛСЯ: веер нашёл 21 пережившую посадку, все закрыты. Круг 3 обязателен
⚠ Условие замыкания жёсткое, и оно не выполнено: круг замыкается, только когда проход с НЕПУСТЫМ веером не нашёл ни одной пережившей посадки. Этот нашёл двадцать одну. Ниже — веер, все находки с диспозициями, что я перепроверила сама, и чего круг не покрыл.
Веер
Три источника, разные ракурсы. (1) Агент fable, read-only — ДОФИКС, которого свежий контекст не видел: CheckPlaceholders, дедуп по src, новые тесты гардов и экрана на ВАКУУМНОСТЬ. (2) Агент fable, read-only — НЕПОКРЫТОЕ, ровно по моему же списку слепых зон: volume.go (пункт 6, чужой дофикс), закон-блок на книге с НЕПОДПИСАННЫМИ строками, бласт-радиус InjectionTrust, свип леджера, мелкие поверхности. (3) МОИ собственные посадки — В ДАННЫЕ, чего в круге 1 не было вовсе: фикстура корпуса, prompt-labels.json, pipeline-c1.yaml, промпт классификатора, injection.txt.
Посадок всего: 12 моих + ~26 агента A + ~60 агента B. Мои: 11 красных, 1 пережила.
Что нашлось — двадцать одна пережившая, по классам
А. ЖИВОЙ ДЕФЕКТ, внесённый моим же дофиксом (1).
· Дедуп закон-блока по голому src ронял ВТОРУЮ ПОДПИСАННУЮ строку. Ключ уникальности банка — (src, sense, since, until), то есть одна поверхность законно несёт несколько подписанных канонов: 青山-фамилия и 青山-направление. Мой дедуп выбрасывал один из них МОЛЧА, при том что трансляторный блок продолжал рендерить оба — два провода разъезжались. Правило исправлено на то, чем оно должно было быть с самого начала: уступает НЕПОДПИСАННАЯ строка, и только подписанной; подпись не роняется никогда. Пин красный на возврате к старому ключу.
Б. ДЕНЬГИ (2).
· ReachableModels не знал банк-ролей. buildClients пре-строит именно этот список, CheckKeys требует именно эти ключи — оба на ОТКРЫТИИ. Модель терминолога или классификатора, не заведённая в models.yaml или без ключа в окружении, проходила ВЕСЬ преflight и убивала прогон на стопе майнинга — после купленной черновой волны. Латентно, пока контур не жил в боевом конфиге; пункт 4 делает это живым.
· Банкнотный канал покупает вывод, который на этой конфигурации никто не прочитает — единственный читатель за ранним возвратом. Не отказ (прогон корректен, срез делает свою работу), а предупреждение с ценой.
В. УТВЕРЖДЕНИЯ О СТРУКТУРЕ, ВЫДАННЫЕ ЗА ГАРАНТИИ (4) — класс, которого я в круге 1 не назвала.
· «валидатор и рендер читают одну таблицу» — прибито только ПРИМЕРАМИ; валидатор-надмножество проходил всё;
· «проверка стоит в единственной воронке и покрывает все пути» — все четыре пути загрузки промптов обводятся вокруг гейта, батарея зелёная. Моя же формулировка из отчёта по Д2;
· «порог лежит в пустом интервале» — порог 0.50 → 0.45 переживает всё И НЕ ДВИГАЕТ ВЕРСИЮ: резюмнутый чанк пере-судился бы по порогу, за который никто не платил. ⇒ langscreen.Version теперь ВЫВОДИТСЯ из констант, classifierVersion стал var, правка порога роняет голден по построению;
· «свип леджера покрывает обе банк-роли» — свип ходил по НАЙДЕННОМУ и никогда по ЗАПИСАННОМУ, поэтому удаление роли из свипа оставляло её запись сиротой, а промпт — неприбитым. ⇒ проверка сирот.
Г. ДАННЫЕ (1) — и это то, ради чего норма про посадки в данные написана. · Фикстура корпуса, размягчённая до красивого числа, проходила всё. Тест утверждает пол «не меньше 3×», а пол не измерение: обнуление исходных рун у ЕДИНСТВЕННОГО худшего здорового образца оставляло батарею зелёной и рапортовало запас ЛУЧШЕ, чем корпус когда-либо давал. ⇒ леджер записанных чисел (30/44 строк · 0.011655 · 0.976706 · 346 букв), по образцу леджера лейблов: пере-взять корпус законно, но это стоит правки здесь и фразы в отчёте, а не ничего.
Д. РАСЩЕПЛЕНИЕ Disp, прибитое только там, где две половины СОВПАДАЮТ (3).
· липкий перенос, ПЕРЕ-ВЫЧИСЛЯЮЩИЙ матч-доверие, переживал всё: единственный пин использует строку, чей src И ЕСТЬ сработавший ключ, поэтому пере-вычисление совпадает с наследованием. Разводит их строка с ханьским src и коротким фонетическим АЛИАСОМ — там перенос re-trusted, и род едет к сущности, которой на странице может не быть;
· липкий перенос, ВЫВОДЯЩИЙ доверие из диспозиции, тоже переживал: неподписанная строка на чистом ключе теряет род в момент переноса — дверь строки 210 в липкой форме;
· диспозиционная ось priorityRank не отличима от статусной ни одной фикстурой. Это одна из ДВУХ, переживших круг 1, и теперь на ней стоит мой дедуп. ⇒ прибита состоянием, которое оси разводит: две ПОДПИСАННЫЕ строки, одна на collision-prone ключе, под связывающим бюджетом.
Е. ЧУЖОЙ ПАК (пункт 6), которого свежими глазами не видел никто (6). Из двадцати посадок в volume.go шесть пережили, и все шесть — в ОПЕРАТОРСКОМ ПРЕДЛОЖЕНИИ и в двух неотфикстуренных ветках reconcile: счёт «%d paying output unit(s)» без флагнутых (недо-счёт того, за что заплачено) · клауза про $0-попутчиков · развилка головы, спрошенная про LeftFresh вместо Left() · свободный юнит, флагнувшийся на резюме, посчитанный оплаченным · пере-деланный юнит, флагнувшийся и оставшийся В ОБОИХ счётчиках · и порядок bound() ДО reconcile, от которого корректность отчёта зависит СЛУЧАЙНО. Прибиты пятью тестами; последний — документирован в waverun.go с прямым указанием, какой «естественный рефактор» его сломает.
Ж. Прочее (4): липкие записи, исчезающие из закон-блока · глубина липкого окна · сироты леджера · injection.txt без родовой строки (последнее — уже красное, поймано TestDC3GenderInjection).
Что я перепроверила сама, а что взяла со слов
Перепроверила посадкой ДО починки (все, кроме одной): дедуп по src · порог экрана · валидатор-надмножество · обход воронки на пути классификатора · диспозиционная ось · липкий перенос (обе формы) · сирота леджера (обе формы) · липкая запись в закон-блоке · банкнотный канал · размягчённая фикстура.
Взяла со слов: H2 (два ряда с одним id — недостижимо через стор), H7 (битый артефакт контраста молча даёт пустой контраст), и стейл-текст glossary_header — про него я уже знала.
⚠ И одна собственная ошибка, которую поймал каталог, а не я: первая редакция теста про ReachableModels читала pipeline-c1.yaml, где модель банк-роли СОВПАДАЕТ с моделью черновика, — то есть тест не мог упасть. Посадка сказала SURVIVED, я переписала тест на конфиг, где банк-модель своя. Механизм проаудировал мой пин; чтение бы не проаудировало.
Чего круг НЕ покрыл
- Пункт 5 (жанр) и цепь рода end-to-end — ни один агент их не атаковал: я дала им дофикс и непокрытое, считая эти два закрытыми кругом 1. Остаются проверенными одним проходом.
$0-проекции на дефектной книге —status/report/export, реально отрендеренные: и мой тест, и посадки доказывают только, что КОНСТРУКТОР открывается.- Липкий перенос до РЕДАКТОРСКОГО провода сквозным прогоном — ни одна фикстура не гонит прономинальный чанк с переносом в edit-юнит; всё прибито на уровне
membank. - Настоящая латинописьменная цель —
target-en.txtв репо нет; ветка достигается пустым объявлением, и тест это говорит. eval/-харнессы — вне модуля бэкенда, не гонялись.- Сверка двух агентов между собой — снова не делалась.
Числа круга
Батарея MAKE_EXIT=0, 0 issues, 19 пакетов, скипы те же три. Голден БАЙТ-ИДЕНТИЧЕН тому, что был до починок круга (единственное движение голдена за круг — classifier_version от вывода версии экрана из констант; вердикты не двинулись). Тесты 1105 → 1156. Каталог 92 → 120, записи WB1–WB29 красные одним прогоном. Удалённых имён по-прежнему одно — переименование TestEditorSectionFollowsProvenance.
КРУГ 3 ПЕТЛИ (D39.191) — ЗАМКНУЛСЯ ПО СОДЕРЖАНИЮ, НО НЕ ПО УСЛОВИЮ: веер нашёл 20 переживших посадок и 1 дыру исполнением, все закрыты
⚠ Условие замыкания не выполнено и здесь. Круг замыкается, только когда проход с непустым веером не нашёл НИ ОДНОЙ пережившей посадки. Этот нашёл двадцать — плюс дыру, найденную не посадкой, а исполнением. Ниже веер, все находки с диспозициями, что я перепроверила сама, и чего круг не покрыл.
Веер
Два источника, и это первый круг, где второй — не мой агент. (1) Агент fable, read-only, работавший в СВОИХ копиях дерева (рабочее дерево не тронуто — подтверждено им и сверено по git status): 68 посадок в семи предметах, 48 красных, 20 переживших, 0 несостоявшихся. (2) Круг оркестратора — независимый веер по тому же батчу, девять находок, пять новых для меня. По трём пунктам два веера сошлись НЕЗАВИСИМО (дедуп полисемии · порог без пина · класс структурных утверждений), и это первое за три круга свидетельство, что находки воспроизводимы между читателями, а не являются вкусом одного.
⛔ ГЛАВНОЕ: денежная дыра, которую круг 2 ОБЪЯВИЛ ЗАКРЫТОЙ, была открыта
Мой фикс круга 2 внёс банк-роли в ReachableModels() и на этом остановился. CheckKeys читает этот список ТОЛЬКО в лейбл-ветке. Безлейбловая книга — shipping-дефолт — идёт второй веткой, которая собирала модели стадий руками и про ворота не знала. Проверено исполнением: терминолог, классификатор и ремонт на провайдере с пустым api_key_env проходили префлайт целиком, CheckKeys возвращал nil. Прогон покупал черновую волну и умирал на воротах.
Почему тест круга 2 был зелёным поверх дыры: он утверждал СПИСОК, а не префлайт. Пин на списке не есть пин на проверке, которая его читает.
И вторая половина той же дыры: рантайм-список reachableModels() тоже не был прибит — посадка «только стадии» (без ремонта и банк-ролей) держала ВЕСЬ пакет pipeline зелёным. Причина — совпадение pipeline-c1, воспроизведённое в фикстурах: каждая фикстура ставит воротам model: fake-model, ту же модель, что у стадий. Закрыто: одно определение gateModels(), которое читают обе ветки CheckKeys и ReachableModels; тест зовёт CheckKeys, а не смотрит список; и фикстура, где банк-роль ходит СОБСТВЕННОЙ моделью, с пином на пре-строенной карте клиентов.
Что нашлось ещё — по классам
А. ЦЕЛЬ С CJK-ПИСЬМОМ НЕ ЭКРАНИРОВАЛАСЬ ВООБЩЕ (находка оркестратора). Гейт !isCJKTarget принадлежал ЭХО-правилу, а держал оба правила сразу. «Вывод в письме ИСТОЧНИКА» для →ja бессмысленно — верный перевод zh-книги полон ханьцзы; «вывод в письме ЦЕЛИ» отвечается прекрасно. Итог: →ja/→zh/→ko не судились ничем, при том что доккоммент langscreen обещал обратное. Это бьёт в цель проекта №2: на ревью-вопрос «заработает ли пара, которой в репо нет, без правки Go» ответ для CJK-целей был «нет». Экран вынесен из-под гейта, эхо-правило осталось под ним. Документированный предел супермножества (китайский вывод для →ja не флагуется) прибит как ПРОМАХ, чтобы никто не принял экран за защиту от zh-эха на →ja.
⚠ classifierVersion НЕ двигали — ратифицировано оркестратором. Для →ru поток управления побайтово тот же (!isCJKTarget истинно и до, и после, обе ветки в том же порядке), →CJK-снапшотов не существует, а строка в этом батче уже сдвинулась дважды и пере-снапшот уже предписан единым актом. Различитель на будущее: бамп должен любой смене, способной пере-вердиктить СУЩЕСТВУЮЩИЙ снапшот — не «кажется, безопасно».
Б. ПРОИЗВОДНОСТЬ ВЕРСИИ ЭКРАНА БЫЛА ЗАЯВЛЕНА И НЕ ДЕРЖАЛАСЬ (3 посадки). Доккоммент Version говорит «выведена по построению, поэтому сдвиг порога забирает громкий --resnapshot с собой». Не проверял никто. Посадка: переписать var литералом, который он сейчас печатает, и сдвинуть порог 0.50 → 0.45 — строка не двинулась, голден не двинулся, оба интервальных пина прошли (0.45 внутри пустой полосы), весь пакет зелёный. Резюмированный чанк пере-вердиктился бы порогом, за который никто не платил. Третья дверь: %.2f не выражает 0.504 — окно точности ±0.005. Закрыто: тест пересчитывает строку из констант, и round-trip-guard требует, чтобы напечатанный порог читался обратно тем же числом. Формат НЕ расширен намеренно — это стоило бы --resnapshot всем книгам за правило, которое не менялось; расширение теперь осознанный акт.
В. ГРАНИЦА СРАВНЕНИЯ, КОТОРУЮ НЕ ВЫРАЖАЕТ НИ ОДНА КОНСТАНТА. share < floor → <= пережило весь пакет: ни одна фикстура не сидела ровно на линии. Прибито фикстурой ровно на 200 буквах, из которых ровно 100 целевых — доля 0.50 без плавающего люфта.
Г. ВАЛИДАТОР ПЛЕЙСХОЛДЕРОВ — ТРИ ДВЕРИ. (1) Сканирование только System-части пережило всё — каждая фикстура кладёт плохой маркер в системную половину, а самое вероятное место для автора — пользовательский хвост, где живут почанковые переменные. (2) Снятие проверки незакрытого {{ пережило. (3) Тест «равенства множеств» обходит placeholderNames(), то есть таблицу РЕНДЕРЕРА, и доказывает только «рендерер ⊆ валидатор»; дорогое направление — обратное, и оно было прибито четырьмя ЛИТЕРАЛЬНЫМИ словами, так что пятое слово проходило насквозь. Закрыто устранением, а не пином: валидатор ТЕПЕРЬ ЕСТЬ РЕНДЕРЕР — CheckPlaceholders рендерит по настоящей таблице значений. Второго списка не существует, расходиться нечему.
Д. ЗАКОН-БЛОК: ПОДПИСЬ ПРОТИВ УВЕРЕННОСТИ (5 посадок). Подпись — это СТАТУС, а не уверенность матча: подписанная строка, сработавшая по сомнительному ключу, всё равно канон, которому уступают. Ключевание набора подписей на диспозиции пережило. Уступать должен ЛЮБОЙ неподписанный статус, а не только draft — auto пишет майнер, то есть ровно та строка, ради подчинения которой правило и существует. Плюс: подписанная строка с ПУСТЫМ переводом не канон (иначе термин исчезает из блока), несимметричный TrimSpace разрушает набор, и однопроходная версия зависит от порядка. Отдельно — вакуумность в моём собственном тесте: его комментарий утверждал, что случай (1) держит независимость от порядка, а стоящий там же sortByPriority это утверждение обнулял. Комментарий исправлен, независимость от порядка вынесена в отдельный случай, который рендерит блок НАПРЯМУЮ, в обоих порядках.
Е. ЛИПКИЙ ПЕРЕНОС: ПОЛОВИНА ДИСПОЗИЦИИ. Перенос наследует обе половины, но пересчёт диспозиции ИЗ СОБСТВЕННОЙ ПОВЕРХНОСТИ строки пережил: в прибитой фикстуре src сам и есть сомнительный ключ, поэтому пересчёт воспроизводит тот же ответ. Разделяющая фикстура (ханьский src, сомнительный кана-алиас) существовала, но утверждала только KeyTrusted. Под посадкой перенос молча повышался до Confirmed — пропуск принудительного пост-чека и место повыше в бюджете, — а провод молчал, потому что половина доверия цела. Это D16.2-повышение в чужом пальто.
Ж. ЛЕДЖЕР КОРПУСА ПИНИЛ ЭКСТРЕМУМ, А НЕ ПОПУЛЯЦИЮ (5 посадок). Второй по трудности здоровый образец можно было смягчить, второй по низости целевой — тоже, а трудную строку — заменить числами лёгкой ПОД ЕЁ ЖЕ id: счётчики, экстремумы и множество id держались. И у интервала не было записи про ВТОРУЮ сторону: доля off-target могла уехать 0.000 → 0.490 при всех зелёных тестах, и порог 0.50 сел бы прямо на образец, пока леджер говорит «полоса пуста». Закрыто: запись wantBestOffTargetTgt и дайджест по всей популяции (id · метка · четыре счётчика, сортировка по id) — пере-взятие корпуса стало осознанным актом, переписывающим строку в том же коммите.
З. ОПЕРАТОРСКОЕ ПРЕДЛОЖЕНИЕ: ЧИСЛО ФЛАГОВ ПЕЧАТАЛОСЬ ЧИСЛОМ ПЕРЕДЕЛОК. Пережило весь пакет: обе фикстуры, читающие это предложение, имели Reworked == Flagged == 1. Разведены.
И. ФЛАГ, РАДИ КОТОРОГО ПОСТРОЕН ПУНКТ 2, БЫЛ САМЫМ БЕЗОБИДНЫМ В ПАСПОРТЕ (находка оркестратора). flagReasonSeverity не знал off_target_lang → дефолт 8, ниже length (6). Глава, вернувшаяся не на том языке, показывала «length» как худшую проблему. У функции не было ни одного теста. Закрыто: switch стал картой, а исчерпаемость держит тест, читающий константы FlagReason из исходника через go/ast — список в тесте гнил бы ровно так же, как список в коде, и заверял бы гниль.
К. ВТОРОЙ CALL-SITE classify (находка оркестратора). repairReGate собирал classifyInput руками из тех же полей, что classifyOutput. Поле TargetScripts однажды уже забыли там, починили руками — и посадка показала, что починку не держит ничто. Закрыто устранением: один конструктор classifyInputFor, пин на нём через рефлексию — любое поле, пришедшее нулевым, валит тест. Список полей в тесте не пишется: его обновлял бы тот же, кто забыл обновить конструктор.
Л. ДВЕРЬ 3 ГЕНДЕРНОГО ТЕСТА ОБЕЩАЛА НЕ ТО, ЧТО ДЕРЖИТ (находка оркестратора, подтверждена исполнением). Её комментарий говорил: «впустят mined-строки в базовый банк — покраснею». Не краснеет: внутри ОДНОГО прогона черновая волна покупается ДО ответа классификатора, поэтому никакое правило про банк не положит род на тот провод. Утверждение об отсутствии оставлено как утверждение о ПОРЯДКЕ, а денежный контракт теперь утверждается там, где живёт — на двух материализованных банках: обогащённый несёт mined-строку, базовый её не выбирает.
М. ИНСТРУМЕНТ ТЕРЯЛ СВОЙСТВО «ГОНЯЕТСЯ ЦЕЛИКОМ» (находка оркестратора). Протухший якорь AF-keys-file-reason-covers-all (протух ещё до этого пака, на 8adcb86) возвращал ОШИБКУ ПРОГОНА и клал весь каталог на 33-й записи из 120 — а прогоны через -id продолжали проходить, и никто не видел. Закрыто: протухание стало ПЕРЗАПИСНЫМ вердиктом ROTTED — прогон идёт дальше, выход остаётся ненулевым, запись предъявляется. Якорь починен.
Что я перепроверила САМА, не приняв на слово
- Три находки оркестратора, где код на вид противоречил заголовку (
repair.goпередаётTargetScripts;CheckPlaceholdersсканирует весьcanonи ловит незакрытый{{;TestUnionStickyNewestWinsна вид ловит keep-first) — прогнала собственные посадки. Две подтвердились как непокрытость, одна — нет. UnionSticky(его находка №4) — ОТВЕДЕНА. Четыре независимые посадки красные. Оркестратор проверил свою на чистой копииb8154cdи снял её сам с точным разбором: его «инверсия» (обход новое→старое с keep-first) ПОВЕДЕНЧЕСКИ ЭКВИВАЛЕНТНА оригиналу (обход старое→новое с перезаписью). Третий класс ложной зелени за сутки — посадка, не меняющая поведения, рядом с моими двумя: упавшая сборка, прочитанная как зелень, и обрезанный вывод, прочитанный как ноль. Общее у всех трёх: читатель верит ВЕРДИКТУ, не проверив, что его произвело.- Дыра
CheckKeys— не поверила отчёту агента: написала тест, увидела его красным на всех трёх воротах, потом чинила. - Каждая из 19 новых записей каталога предъявлена красной прогоном. Одна (
WB41) вернулась SURVIVED — моя фикстура случайно давала верный ответ и под посадкой (неподписанная строка былаConfirmedи сама наполняла набор подписей). Фикстура переписана так, что подпись — единственный возможный источник; предъявлена красной.
⚠ Чего круг НЕ покрыл
- Причина
S6e— совпадение ли это фикстур или у банк-ролей есть второй путь к клиенту помимоclientFor. Названо агентом, не открыто; я закрыла СЛЕДСТВИЕ (пин на карте клиентов), не причину. - Сквозной прогон дыры
CheckKeysчерезNewRunner→ волна: закрыто на уровнеCheckKeysи пре-строенной карты, но что происходит на живом проводе с ключом-пустышкой, никто не гонял. - Резюме через смену версии — end-to-end пере-вердикта резюмированного чанка нет ни одного теста; вся аргументация про
--resnapshotдержится на чтении. - Конвенционный путь стадийного промпта — пер-путевой тест гоняет только
prompt_override. Маркер внутри вырезаемого комментария проходит по построению, и НАМЕРЕННОСТЬ этого никем не проверена. - Два НЕПОДПИСАННЫХ ряда одной поверхности оба рендерятся: «один приказ на термин» держится только когда подпись есть. Наблюдение агента, теста нет ни в ту, ни в другую сторону.
precomputeSticky— сброс на границе главы и запись переноса, заблокированного спойлером.- Сам харнесс
tmmutate(отпечаток и восстановление) и единственная записьexpect: survives(G-byte-gate) не ревьюились ни одним кругом из трёх. - Ракурсы, унаследованные непокрытыми из круга 2 и не открытые снова:
$0-проекции на дефектной книге · липкий перенос до редакторского провода сквозным · настоящая латинописьменная цель (target-en.txtв репо нет) ·eval/-харнессы вне модуля. - F11 остаётся риском дизайна, не чинен: порог экрана калиброван на ОДНОЙ сянься-новелле; на латино-тяжёлом здоровом русском даёт ложный
off_target(0.461 с пиньинь-глоссами, 0.077 с shell-командами), а ложный флаг ЭСКАЛИРУЕТ — то есть стоит платного вызова. Оркестратор забрал носителем. - Круг 3 не ревьюил мои правки круга 3. Копии агента сняты до них. Четвёртый круг, если он будет, начинается отсюда.
Числа круга
Батарея MAKE_EXIT=0, 0 issues, все пакеты ok (pipeline 571 s под -race), скипы те же. Голден в этом круге не трогали, и TestGoldenDeterminism проходит против него — круг не сдвинул ни одного байта провода. Тесты 1156 → 1173. Каталог 120 → 141; все двадцать одна новая запись предъявлена КРАСНОЙ (WB41 — со второй попытки, после починки фикстуры, которая случайно давала верный ответ и под посадкой).
⚠ КАТАЛОГ ПРОГНАН ЦЕЛИКОМ — впервые, и первый же целый прогон окупил починку инструмента. 141 запись: 136 RED · 0 SURVIVED · 0 NOTHING · 1 записанный survives (G-byte-gate, аргументирован) · 4 ROTTED. Протухли четыре МОИ ЖЕ записи, чьи якоря увезли рефакторы кругов 2–3: WB5 (сборка classifyInput уехала в конструктор), WB12 (правило дедупа исправлено кругом 2 — запись описывала регрессию, которую я же и починила), WB16 (у валидатора не стало собственного списка), WB21 (банк-роли уехали в gateModels). Под прежним поведением прогон лёг бы на первой из них, и трёх остальных никто бы не увидел — ровно то, что произошло с AF-keys-file-reason-covers-all и держалось незамеченным два пака. Все четыре пере-навешены на нынешние выражения тех же свойств (у WB12 и WB16 заодно переписан why: свойство изменилось, а не только адрес) и предъявлены красными. AF в целом прогоне — RED, то есть починка якоря проверена не на слово.
Файлы
Изменены: internal/pipeline/{disposition,chunkrun,waverun,events,manifest,mining,terminologist,repair,render,runner}.go · internal/membank/{memory,mempostcheck,decisions}.go · internal/terminology/{terminology,classify}.go · internal/miner/miner_emit.go · internal/checks/sanitizer.go · internal/config/{book,pipeline}.go · internal/lang/embedded.go · internal/store/migrate.go · cmd/tmctl/render.go · cmd/tmmutate/mutations.json (92 → 96) · configs/pipeline-{c1,c2,arm-*}.yaml · prompts/zh-ru/*.md (шесть — жанр; classifier.md — третье поле) · example/book.yaml · тесты и голден.
Новые: internal/langscreen/{langscreen,langscreen_test}.go · internal/pipeline/{cuttag_test,gender_wire_test,offtarget_corpus_test,volumepanic_test,offtargetflag_test,contourpreflight_test}.go · internal/pipeline/testdata/offtarget-corpus.json · internal/config/{bank_contour_test,genre_retired_test}.go · internal/checks/latinguard_test.go.
Команды приёмки
cd backend && make battery # MAKE_EXIT=0, 0 issues, 19 пакетов ok, 3 скипа
go test ./internal/pipeline/ -run 'Gender' -v # производитель рода, три двери доставки
go test ./internal/pipeline/ -run 'OffTargetCorpus|LiveEchoGate|LatinOffTarget|TargetScreen|TwoScreens|ScreenConstants' -v
go test ./internal/langscreen/ -v # изолированный модуль экрана
go test ./internal/config/ -run 'BankContour|BankRoleBudgets|Genre' -v
go test ./internal/membank/ -run 'ApprovingATermKeeps|LawBlockGivesOneOrder' -v # род переживает подпись; один приказ на термин
go test ./internal/pipeline/ -run 'OffTargetCompletionIsFlagged|RunnerHandsTheScreen|ThresholdIsUsed|ContourRefusesAWriteRun|RenderRejectsUnknownPlaceholder' -v
go test ./internal/checks/ -run 'LatinResidueClassIsGated' -v # вторая половина дыры 46, обе стороны
go test ./internal/pipeline/ -run 'ACrashOverACaughtCeiling|StopLineSaysTheGrant|OneCarriedUnit' -v
cp -a backend /tmp/mut/backend && cd /tmp/mut/backend && GOFLAGS=-buildvcs=false \
go run ./cmd/tmmutate -root . -id WB1-head-always-end-of-book,WB2-head-keyed-on-the-carry,WB3-bound-border-drops-a-single-carry,WB4-cut-tag-drops-the-embedded-data,WB5-target-screen-never-sees-the-target,WB6-off-target-flag-not-escalatable,WB7-bank-role-exemption-narrows-to-one-role,WB8-latin-residue-runs-on-a-latin-target,WB9-contour-configured-and-inert,WB10-missing-contrast-costs-a-wave,WB11-nil-pack-contour-never-runs,WB12-two-orders-for-one-term,WB13-placeholder-refusal-arrives-after-a-paid-wave
grep -rl '{{genre}}' backend/prompts/ | wc -l # 0
grep -rn '^func Test' backend --include=*_test.go | wc -l # 1143
python3 -c "import json;print(len(json.load(open('backend/cmd/tmmutate/mutations.json'))))" # 105
04.09 — записка-план вайр-батча «род · экран цели · заголовки инъекций» (промт BACKEND_WIREBATCH_SESSION_PROMPT.md, сессия textmachine-main-7e)
Скоуп — шесть пунктов промта. (1) 210: род производится авто-путём, доказательство сквозным прогоном «произведено → отрендерилось». (2) 113 → 46 в этом порядке: корпус-фикстура и регресс на реальный запас боевого гейта, потом экран цели именованным флагом + вторая половина дыры
detectLatinInsertion. (3) 134: единый закон-блок редактора, маркер ⟨проверить⟩ с провода, то же у транслятора. (4) 140: банковый контур вpipeline-c1.yaml, суб-бюджеты ×4.47. (5) 184(а):{{genre}}из шести промптов пары и поле из канона брифа. (6) ДОФИКС чужого пака D39.187 п.4 (две посадки + границаbound()+ три числа) и ФЧ-7 строки 197 — ПРОВЕРКОЙ, не стройкой. Инварианты. Не коммичу — дерево на лендинг оркестратору. НЕ двигаю: схему хранилища ·manifestVersion·StreamVersion· версию контракта. Новый эмбед-файл не завожу.FlagCJKArtifactне переиспользую (снято D39.93 п.2). Статусы строк и подписная таблица в 134 не трогаются (D39.104 п.1). Семантику переноса слота не трогаю. Текст заголовка редактора не меняю — он байт-идентичен армуAM-noclauseпробы 18 (experiments/18-editor-wire-probe.md§0.3). Развилки, объявленные ДО кода. (1) род — производится КЛАССИФИКАТОРОМ (третье поле его ответа), а не терминологом и не третьим проходом: ноль новых вызовов, парсер классификатора позиционный и закрыто-словарный. (2) Второй замок (Confirmed-фильтр рендера рода) — вынесен пингом оркестратору на ратификацию, сам не снимаю. (3) 134 — снимаю РЕНДЕР в Go,internal/lang/data/injection.txtНЕ трогаю: правка данных двигаетEmbeddedVersion→cutTag→manifest_key→ сносunit_resolutionsкниги ПАРАЛЛЕЛЬНОГО платного прогона платформы. Что НЕ делаю. Чужие зоныplatform/frontend/eval/и соседний worktree. Строки 131 · 105(а) · 14 · 119 · 124 · 115 · 160 · 161 · 142. Самопроверка исполнением. Дифф^func Testпофамильно до/после (удалённых имён 0) · маскированный дифф голдена (только названные версионные оси + ровно две строки диспозиций) · собственные посадкиtmmutateВНЕ шести пунктов на копии дерева · отдельный адверсариальный проход свежим контекстом (модель назову) · отчёт о движенииcutTag:tmctl manifestдо и после.
02.09 — эхо-записка пака «число согласия на пути второй покупки» (промт BACKEND_CONSENT_SESSION_PROMPT.md, сессия textmachine-77)
Канала к оркестратору нет: адрес в
/tmp/textmachine-channel(textmachine-33) вListAgentsотсутствует, промт писан на другой машине — вопросы едут секцией отчёта ниже. Дерево на входе чисто, HEAD494c4ef; всеfile:line-якоря промта сверены грепом на этой машине и сходятся. Скоуп — четыре пункта в порядке промта: (1) ФЧ-5, ось МОДЕЛИ: строка прайсится по модели, которую её стадия резолвит СЕЙЧАС (Stage.ResolvedModel); округление вверх при незнании = максимум из цен по ответившей модели, по текущей и — для эскалационных вызовов — по текущему хопу; оговорка «оценка, ошибается вверх, вот чем» в ОБОИХ текстах согласия; обещание точности снимается вstatus.go(комментарий уRebillUSD) и в шапкеreprice.go. (2) Строка 232, остаток «слот»: юнит, который прежний прогон НАЧАЛ (есть строки текущих позиций) и не отгрузил по осиfinalStageWave, слота гранта повторно не тратит — дописывается вне гранта, считается отдельно. (3) ФЧ-4 обе половины:rebill_historical_rowsвstatus --jsonпод тем жеrebill_basis+ basis в тексте отказа--accept-rebill=<usd>; одна формулировка basis для CLI-статуса и текста отказа. (4) ФЧ-1: ровно три названные гарантии — сперва воспроизвести мутацию на копии и увидеть зелень, потом посадка тестом + запись вcmd/tmmutate/mutations.json. Инварианты: направление ошибки — никогда не занизить молча (D39.150) ·statusиtranslate— ОДИН вывод · фигура едет с базисом (D39.181 п.1) · ось отгрузки =finalStageWave, не draft и не «любая» · схема хранилища, форма манифеста, версия контракта НЕ трогаются · тесты не подгоняются, заказанная смена поведения объявляется (D39.183). Не делать: строки 160 · 221 · 224 · 226 · 228 · 230 · 246 · 247 · 233 · 229 · 141-остаток · 131 · платный замер · новое поле в кадреfinishedшва (класс «поле в опубликованном документе» — ратификация оркестратора; счётчик «дописан вне гранта» живёт в отчёте прогона и логе, вопрос — в отчёт) · коммиты. Самопроверка исполнением: дифф^func Test(база 1083, снимок имён снят) · собственные посадкиtmmutateна копии в scratchpad · свежий адверсариальный проход субагентами Fable 5 (число назову) ·make batteryна копии до и на дереве после.
03.09 — ОТЧЁТ пака «число согласия на пути второй покупки» (сессия textmachine-77, промт BACKEND_CONSENT_SESSION_PROMPT.md)
Итог: четыре пункта состава исполнены, дерево
backend/готово к лендингу, НЕ КОММИЧУ (git diff --cached --name-only→ пусто). HEAD на входе494c4ef; после согласованного с платформой (textmachine-37)git pull --ff-only—2a63c37. Входящее (72 файла) не пересекалось ни с одним моим файлом, кромеdocs/PROGRESS.md: свою записку сняла редактором, дала git пройти fast-forward, вернула. Индекс не трогала, stash не применяла. Канала к оркестратору нет:textmachine-33вListAgentsотсутствует, промт писан на другой машине — вопросы секцией ниже. Всеfile:line-якоря промта сверены грепом здесь и сошлись. Батарея на финальном дереве:cd backend && make battery→MAKE_EXIT=0,golangci-lint0 issues,okв 18 пакетах, SKIP:TestMinerFullBookParity,TestHelperEventsRun,TestHelperKillLoop. ⚠ Скипов ТРИ, а не шесть как в базовом прогоне, и это не ослабление:TestCheckerLabelsBaseline/TestCheckerLabelsCandidates/TestK6LabelsBaselineв реальном дереве корпус находят и ИДУТ —go test ./internal/checks/ -run TestCheckerLabelsBaseline -count=1 -v→--- PASS,go test ./... -run TestK6LabelsBaseline -count=1 -v→--- PASS. Базовый прогон гнался на копии в/tmp, где маркер корня репозитория не находится. Тесты^func Test:grep -rn '^func Test' backend --include=*_test.go | wc -l→ 1083 → 1105; пофамильный дифф двух снимков (comm -23) — удалённых 0, добавленных 19.
Комплектность против заказа — по четырём пунктам и по таблице разметки.
1. ФЧ-5 — ось МОДЕЛИ. Все ЧЕТЫРЕ обязательства D39.150 п.1.
- (1) прайс по модели, которую стадия резолвит СЕЙЧАС.
internal/pipeline/reprice.go,currentModelFor(stage, escalation): для эскалационного вызова — текущийResolvedHop, иначеResolvedModel. Именно РЕЗОЛВЕННЫЙ слот, а не конфигурационныйmodel:— на книге с лейблами это разные модели, и прайсить надо по той, которую прогон вызовет (пинTestTheModelAxisReadsTheRESOLVEDSlotNotTheConfiguredOne, каталожная записьFC5-model-axis-configured-slot). Признак эскалации взят из колонкиcheckpoints.escalationполемstore.CheckpointUsage.Escalation; схема НЕ тронута (git diff --stat -- backend/internal/store/migrate.go→ пусто), колонка живёт с v3. - (2) округление ВВЕРХ при незнании — формула моя.
now = max( cost(токены @ модель, которая ОТВЕТИЛА), cost(токены @ модель, которую стадия резолвит сейчас) ). Довод: количество токенов принадлежит ответившей модели, цена — той, которая ответит; ни одна не смеет опустить число ниже другой. Оба направления проверены исполнением: стадия ушла на модель ×10 — число ×10 (замер приёмки$0.003640против$0.036400воспроизведён тестом); стадия ушла на модель ÷10 — число НЕ падает. База порогаprojectBookUSDсчитается тем жеusd(), поэтому обе половины гейта в одной валюте. - (3) оговорка в тексте согласия.
projectionBasis(rebill.go): «…an ESTIMATE that errs upward, never below what the answering model would charge for the same tokens where their usage is on file; K of the N unit(s) were bought from a model their stage no longer resolves to…». Едет в ЧЕТЫРЁХ операторских местах: пороговый отказ, его scoped-клауза, отказ по названному потолку, иtmctl statusчерезStatusReport.RebillFigureBasis(). - (4) обещание точности СНЯТО в ОБОИХ живых местах, названных промтом.
git grep -n 'can never quote a different number' -- backend/→ пусто; на входном коммитеgit grep -n 'can never quote a different number' 2a63c37 -- backend/ | wc -l→ 1 ⚠ (в первой редакции отчёта стояло «3» — число было снято широким грепом на три разных шаблона и приписано этому, узкому; исправлено дофиксом);grep -rn 'NOT projected (like the content axis' backend/internal→ пусто. Заменено: шапкаreprice.go— «ROUTING IS PROJECTED, AND IT ROUNDS UP»; комментарийRebillUSDвstatus.go— «what neither of them promises is ACCURACY… an estimate that errs UPWARD where the tokens are known». Третья копия обещания (исторический комментарий уprojectStoredMemory) снята попутно. - Решила сама, сверх буквы заказа: счётчик
RebillProjection.ModelMovedRowsи полеrebill_model_moved_rowsвstatus --json. Довод: фигура, часть которой — верхняя оценка через смену модели, без этого числа неотличима от точного пере-прайса, а D39.181 §2.3 требует базиса у опубликованной фигуры. Это ВТОРОЕ новое поле сверх названного промтом одного — вопрос 3.
2. Строка 232, вторая половина — ЗАКРЫТА ТОЛЬКО ПО ОСТАТКУ «СЛОТ».
- Ось отгрузки —
finalStageWave, как велено; не draft и не «любая». Проверена исполнением и на редакторском, и на ЧЕРНОВОМ-ТОЛЬКО конвейере (TestDeliveryIsReadFromTheSHIPPINGWaveOnADraftOnlyPipeline,TestACarriedUnitOnADraftOnlyPipeline). - Механизм. Класс
unitCarriedвvolume.go: юнит, у которого есть строка ХОТЯ БЫ ОДНОЙ позиции, исполняемой этим конвейером, но не всех, и который не отгружен по оси. Он допускается ВНЕ гранта, но платит; в отчёте — внутриDeliveredи отдельно вCarried. Сравнение с потолком —granted() = Delivered − Carried + Reworked, заменилоPaid()в ОБОИХ местах (planVolume,rescopeEditWave). - ⚠ И сам перенос ОГРАНИЧЕН ГРАНТОМ — не больше
MaxUnitsперенесённых за прогон, в порядке книги. Без этой границы потолок переставал быть потолком: прогон без--max-units, начерновивший всю книгу и умерший до редакторской волны, отдавал следующей покупке ВСЕ свои юниты. Замерено на фикстуре: грант 1 оплачивал 5 юнитов и 5 вызовов провайдера, а поскольку в остатке не оставалось ничего, прогон не отчитывался вовсе. Найдено адверсариальным проходом по МОЕЙ ЖЕ работе. Принцип границы, а не число: покупка на N может дописать столько же прерванных юнитов, сколько начинает новых, — работа прогона остаётся пропорциональна гранту. Не влезшее держится какLeftFresh(«никогда не доставлено»), потому что это ровно оно. - ⚠
bound()теперь истинен и когдаCarried > 0, а не только когда что-то удержано: прогон, дописавший юниты вне гранта, обязан это СКАЗАТЬ, иначе молчание приходится ровно на случай с наибольшим расхождением. - Решила сама (промт отдал): где вычитается потраченный слот — нигде: он НЕ БЕРЁТСЯ. Как переживает рестарт — носитель «юнит начат» — его же строки
chunk_statusпо текущим позициям (unitStarted/unitPositionsOnFile, одно перечисление сunitFullyRecorded, чтобы они не разошлись в понимании «позиции»); схемы не нужно. Частично двинутый юнит — carried, дописываются только недостающие позиции. - Замер строки исправлен: было «4 купленных юнита → 2 главы», стало 4 → 4 (
TestAUnitInterruptedBetweenWavesTakesNoSecondSlot:Delivered=4 Carried=2 LeftFresh=1, ровно 6 вызовов во второй покупке). - Семантика
--max-unitsизменена и объявлена во всех трёх операторских местах (cmd/tmctl/invocation.go,Runner.MaxUnits,backend/README.md): грант считает юниты, которые прогон БЕРЁТ СЛОТОМ — новые и пере-делываемые; перенесённые названы в строке стопа и в логе (finished_from_an_earlier_grant). ⚠ Тексты НЕ утверждают, что «слот за юнит был взят прежним прогоном»: движок этого не знает (прежний прогон мог идти без потолка), и первая редакция текстов это утверждала — снято. - ⚠ ОСТАТКИ, которые пак НЕ закрывает — названы в докстринге
deliveredUnitsи здесь:- «первая редакторская стадия» (остаток, который промт велел назвать): конвейер, получающий ПЕРВУЮ редакторскую стадию, двигает отгружающую волну с draft на edit, и уже прочитанные юниты репортятся свежими. Закрытие требует записи о том, ЧЕМ БЫЛА отгружающая волна.
- Прерванная ПЕРЕ-ДЕЛКА — новый остаток, найденный этим паком. Отгруженный юнит, чья пере-делка оборвана между волнами, имеет строку в КАЖДОЙ позиции, снова классифицируется
unitReworkи снова берёт слот. Отличить его от обычного банк-онли сдвига (черновик free, редактор пере-оплачивается — определение rework) можно только записью «какой прогон купил какую строку». Строку 232 закрываю только по остатку «слот», как и велено.
3. ФЧ-4 — ОБЕ половины, фигура едет с базисом (D39.181 п.1).
- (а)
HistoricalRowsбольше не теряется на границеstatus.go:rebillOutcomeвозвращает проекцию ЦЕЛИКОМ (подnone/failed— нулевую структуру, так что новое поле не может пережить «неизвестный» ответ, забытое в одной ветке), вStatusReport—rebill_historical_rowsиrebill_model_moved_rowsпод тем жеrebill_basis. - (б) отказ по названному потолку
--accept-rebill=<usd>несётprojectionBasis(proj)— базис ТОЙ ЖЕ run-scoped проекции, чьё число печатает. - Сверх заказа, по тому же правилу «каждая цифра предложения — из его проекции»: scoped-клауза ПОРОГОВОГО отказа печатала число этого прогона рядом с книжным базисом; теперь несёт свой (
TestTheScopedClauseOfTheRefusalCarriesItsOwnBasis). Дефект был и до пака. - Один вывод на два канала:
StatusReport.RebillFigureBasis()→ строка RE-PAYMENT вtmctl status;TestABilledDecodeRowIsDisclosedAsOldMoneyEndToEndсверяет, что проекция,--json, CLI и ОБА текста отказа называют одну строку раскрытия. - Решила сама (промт отдал: имя поля · форма basis · что печатать при
HistoricalRows=0). Имя —rebill_historical_rows, в форме соседей по префиксуrebill_*. Форма basis — НЕ второе поле-строка рядом с числом, а одна формулировкаprojectionBasis, которую методRebillFigureBasis()переиспользует для CLI: существующийrebill_basisостаётся КАЧЕСТВЕННОЙ осью (pending/stored/none/failed), а новые счётчики — количественной, и словами их описывает один текст, чтобы гейт и статус не разошлись формулировкой. При нуле — печатается ноль, а не пропуск поля:omitemptyздесь тот же дефект, ради которого его сняли сrebill_units/rebill_usd— отсутствие поля неотличимо от «свободно». Ноль подpendingзначит «всё пере-оценено», подfailed— «не считалось»; различает ихrebill_basis. В операторском тексте при нуле клауза просто не печатается: предложение не должно нести оговорку, у которой нет предмета.
4. ФЧ-1 — ровно три названные гарантии, по каждой все ТРИ шага.
- Шаг 1 — воспроизвести на копии ДО пака.
cp -a backend /tmp/.../mut0/backend,go run ./cmd/tmmutate -root . -catalog prepack_mutations.json→ все пять посадок SURVIVED: фильтр по книге в ОБОИХ пакетах, ключ ячейки безchunk_idxв ОБЕИХ формах, снятие пометки «не пере-оценена». ⇒ гарантии (2) и (3), принятые приёмкой СО СЛОВ линзы, подтверждены исполнением; ни одна не оказалась уже прибитой. - Шаг 2 — посадки тестом. (1)
TestCheckpointUsageForBookIsScopedToTheBook(две книги в одной БД, ОДНА позиция) +TestAnotherBooksMoneyNeverEntersTheConsentNumber. (2)TestEveryChunkOfAChapterIsRePricedFromItsOwnCalls— глава из нескольких чанков РАЗНОЙ стоимости: единственная форма, в которой пул ячейки виден (во всех прежних фикстурах глава = один чанк, потому мутация и переживала). (3)TestABilledDecodeRowIsDisclosedAsOldMoneyEndToEnd— продовый путь до--json, CLI и обоих отказов. - Шаг 3 — каталог.
cmd/tmmutate/mutations.json: 73 → 92. Четыре записиFC1-*на три гарантии (фильтр по книге пинится в двух пакетах) плюс двеFC5-*на несущие свойства, которые пак СОЗДАЛ (граница переноса и резолвенный слот) — их я завела по той же логике, по которой каталог существует. Денежный путь в каталоге: греп промта считает СТРОКИ —git show 2a63c37:backend/cmd/tmmutate/mutations.json | grep -c 'reprice.go\|rebill.go\|volume.go\|ledger.go'→ 0, тот же греп по дереву → 17; различных ФАЙЛОВ денежного пути — 0 → 4 (reprice.go,rebill.go,volume.go,store/ledger.go). ⚠ В первой редакции стояло «стало 5 файлов» — такого числа не даёт ни одно прочтение; исправлено дофиксом. Прогон всех шести на свежей копии: 6 RED, «0 unexpected outcome(s)», exit 0. - Четвёртого одноразового харнесса не писала;
tmmutateгоняла только на копиях в scratchpad. - Решила сама (промт отдал: форма посадок · уровень теста · текст
why). Форма — ломать ровно то утверждение, которое гарантия держит, минимальной правкой, и обязательно КОМПИЛИРУЮЩЕЙСЯ: рецепт, оставляющий переменную неиспользованной, даётtmmutateвердикт «ничего не выполнялось», а не «красное», — на этом я поймала два своих же докстринга и переписала их. Уровень — по тому, где живёт защита, а не где живёт правка: фильтр по книге пинится и вstore, и вpipeline(мутация пережила обе батареи по отдельности, значит одной мало); ключ ячейки — толькоpipeline, дефект вnewRepricer; пометка «строка не пере-оценена» —pipeline, и именно ПРОДОВЫМ путём, потому что промт называл её не ловящейся на нём. Текстwhy— называет СВОЙСТВО и причину, по которой его не видно («во всех прежних фикстурах глава = один чанк»), а не описание правки:whyчитают в тот момент, когда мутация выжила и надо понять, что именно перестало охраняться.
Правки СУЩЕСТВУЮЩИХ тестов — объявляются (D39.183).
TestAFlaggedMemberWithNoEditRowIsNotFree(volume_test.go): описывал «юнит без edit-строки ОБЯЗАН потратить грант» — поведение, которое заказывает пункт 2. Гарантия «не FREE, платит и отчитывается как платящий» СОХРАНЕНА; гарантия «берёт слот» уехала в противоположную. Фикстура расширена до 4 глав; после введения границы переноса ожидание —Delivered=2 Carried=1 LeftFresh=2.TestAnAnnouncedButFLAGGEDUnitIsStillNewBook,TestAUnitWhoseEDITFlaggedIsStillNewBook(volumedelivery_test.go): флагнутый юнит после добавления стадии теперь carried. Гарантии «анонс ≠ текст» и «судить по ОТГРУЖАЮЩЕЙ строке» сохранены; фикстуры расширены до 3 глав, сигнатуры названных мутаций пере-выведены. ⚠ Рецепты мутаций в их докстрингах были НЕИСПОЛНИМЫ (правка на месте вызова оставлялаshipStagesнеиспользованным, пакет переставал собираться, иtmmutateдал бы NOTHING вместо RED) — переписаны на правку телаunitShipped.- Смена сигнатур (
repriceCheckpoint/usd— третий возвратmoved;rebillOutcome— проекция целиком):TestRepriceCheckpointFallsBackToTheBilledAmount(таблица расширена до 11 случаев),TestRepricerCountsOnlyTheCurrentGenerationOfCheckpoints(+4 строки),TestAFailedBasisNeverCarriesAFigure(сравнивает всю структуру с нулевой — стал строже),TestRebillConsentCapBelowProjectionRefuses(+утверждение про базис),TestCheckpointsOfOneGenerationSumToTheRowsCost(адаптирован под третий возвратusd(); ослабления нет, правка механическая — ⚠ в первой редакции отчёта имя пропущено, дописано дофиксом),reprice_model_test.goиrender_test.go(формулировка оговорки: «were answered by» → «were bought from», см. ниже). TestStatusPricesTheDriftWithTheGatesOwnNumber— тронут ТОЛЬКО комментарий, цитировавший снятое обещание. Тест не менялся.- Удалённых имён — 0.
Мандат самопроверки — три артефакта.
- Дифф
^func Testисполнением: 1083 → 1102, удалённых 0, добавленных 19. - Собственные адверсариальные посадки ВНЕ трёх гарантий: каталоги
own_mutations.json(26),round2_mut.json(5),round3_mut.json(2),draftonly_mut.json(2) — 35 посадок,tmmutateна копиях. Итог: все RED. ⚠ В первом круге ДВЕ пережили, и это находки: X21 (rescopeEditWaveсравнивал грант черезPaid(), то есть считал перенесённый юнит за слот и отказал бы в свободном) и X22 (строка стадии, которой конвейер больше не исполняет, засчитывалась как «юнит начат»). Обе прибиты (TestTheRePlanCountsSlotsNotCarriedUnits,TestRowsOfARetiredStageAreNotAStart) и во втором круге RED. - Проход по СВОЕЙ готовой работе свежим контекстом. Воркфлоу из семи линз (направление ошибки · раскрытие на новой границе · слот и черновой конвейер · вывод членства
usd()· правда текста · качество тестов · скоуп и заказ), каждая находка судится тремя независимыми опровергателями (корректность · воспроизведение · сверка с промтом), большинство решает. Модели: линза качества тестов — Fable 5, остальные — Opus 5 (ограничение владельца на число Fable-агентов соблюдено: один). Числа прохода: 7 линз, 27 находок (2 HIGH · 12 MED · 13 LOW), 42 вердикта верификаторов, 46 агентов. ⚠ Верификаторов «подтверждено» — НОЛЬ, и читать это надо точно: фаза верификации шла по дереву, где все 27 находок были уже исправлены, то есть опровергатели подтверждали ПРАВКИ, а не отсутствие дефектов. Каждая находка ниже воспроизведена или прочитана мной по коду до правки. Находки и диспозиции (все ИСПРАВЛЕНЫ, каждая с посадкой):- [HIGH] перенос без границы обнулял потолок — грант 1 оплачивал 5 юнитов, и прогон об этом молчал. Введена граница
Carried ≤ MaxUnits+bound()поCarried; посадкиFC5-carry-unboundedиFC7-volume-stop-silent-outside-grant(в первой редакции вторая называлась разведочным именемY2-silent-when-nothing-left, которого в каталоге нет — переименовано дофиксом, Б7). - [MED]
reconcileмог вывестиDeliveredнижеCarried—granted()уходил в минус, строка стопа говорила «0 NEW unit(s) delivered (1 of the new ones had been started…)», предложение, которое не может быть истинным. Все ветви теперь держат вложенность; посадкиFC7-reconcile-free-branchиFC6-reconcile-fresh-branch(в первой редакции стояло разведочноеY3, которого в каталоге нет — переименовано дофиксом, Б7). - [MED] операторские тексты утверждали «слот за юнит был взят прежним прогоном» — движок этого не знает. Снято во всех трёх местах.
- [MED] ось модели не была прибита на РЕЗОЛВЕННОМ слоте — чтение
st.Modelвместоst.ResolvedModelпереживало весь пакет. Пин + каталожная записьFC5-model-axis-configured-slot. - [MED] $0-строка без usage под сдвинутой стадией публиковалась как $0 без оговорки. Теперь помечается «не удалось пере-оценить»; посадка
FC7-zero-usage-row-silent-after-a-move(в первой редакции — разведочноеZ2). - [MED] scoped-клауза порогового отказа шла без своего базиса (дефект был и до пака) — исправлено, посадка
FC7-scoped-clause-without-basis(в первой редакции — разведочноеX29). - [LOW] ветка отката (
overshoot) причисляла строку к «пере-прайсенным по сдвинутой модели», хотя цитирует БИЛЛЕННУЮ сумму, не прайсенную ни по одной сегодняшней таблице.movedтам снят; посадкаFC7-overshoot-claims-a-model-move(в первой редакции — разведочноеY4). - [LOW]
movedсчитается противModelRequested, а пять текстов говорили «модель, которая ОТВЕТИЛА» — на провайдере, канонизирующем слаг (gpt-5-mini→ дата), это разные вещи. Код верен (пере-прогон запросит модель стадии), тексты приведены к нему. - [LOW] комментарий про
zeroRowутверждал, что хвост $0-вызовов — ОДНО поколение. Это неверно: $0-стадия оставляетcost_usd == 0после каждого прогона, поколения неразличимы, и число может быть кратным. Направление при этом ратифицированное (вверх), и оговорка «errs upward» его покрывает; ложное утверждение из комментария снято, ограничение названо вслух. - [LOW] комментарий про redrive утверждал, что пере-атакованный юнит «начинается заново». Неверно:
ResetChunkStagesудаляет только FLAGGED и SKIPPED стадии, черноваяok-строка остаётся, и юнит остаётся carried. Комментарий приведён к коду. - [LOW] доки кадра
finished(runevents.VolumeLedger) отправляли читателя к полюFreeза объяснением «почему юнитов больше, чем грант», хотя теперь причина может быть и вDelivered. Тексты исправлены; поля на провод НЕ добавлено — вопрос 1. Вrunevents/изменены ТОЛЬКО комментарии (проверено: дифф без строк кода),StreamVersionне тронут. - [LOW] докстринг
CheckpointUsageForBookссылался на несуществующий id каталогаFC1-book-filter(в каталоге две записи,-storeи-pipeline);tmmutate -idматчит точно, и следующая сессия получила бы «ничего не выбрано». Исправлено. - [LOW] комментарий у
RebillHistoricalRowsназывал платформу потребителем поля — её аллоулист не берёт ни одногоrebill_*. Формулировка приведена к факту: потребитель — операторская оснастка, читающая документ; платформа поле игнорирует. - [LOW] несколько комментариев рассказывали ИСТОРИЮ починки («used to», «went stale once already», «is how four bought units became two chapters») вместо описания кода — закон владельца. Переписаны; провенанс оставлен только в докстрингах ТЕСТОВ, где он в зоне принят.
- [LOW] «первая половина» текста согласия обещала «never below…» без оговорки про строки, которые пере-оценить не удалось: они как раз могут стоять НИЖЕ сегодняшней таблицы. Добавлено «where their usage is on file» и «may sit below today's table».
- [HIGH] перенос без границы обнулял потолок — грант 1 оплачивал 5 юнитов, и прогон об этом молчал. Введена граница
Три оси ревью, названные промтом уязвимыми именно в этом паке — по каждой предъявляю.
- Направление ошибки. Двойной счёт искала специально: порог сравнивает базу и сумму, посчитанные ОДНИМ
usd()(тест сверяетprojected_book_usd, а не только сумму), максимум из двух цен берётся РОВНО один раз на вызов, добавка денег банк-ролей входит в опубликованную проекцию и НЕ входит в базу порога — как ратифицировано. Перелёт порога проверен с обеих сторон: число выросло там, где занижало, и не упало там, где стадия ушла на дешёвую модель. Одну форму двойного счёта ревью всё же нашло — кратность оценки $0-строки; направление у неё безопасное (завышение), ограничение названо вслух и в коде, и в секции «не проверено». HistoricalRowsна новой границе. Не теряется и не удваивается: единственный инкремент на строку,rebillOutcomeотдаёт проекцию целиком, под «неизвестно» — нулевую структуру. Текст отказа и--jsonназывают ОДНО число с ОДНИМ базисом — это утверждает тест, сравнивающий подстрокуRebillFigureBasis()внутри текста отказа, а не два независимых ожидания.- Слот гранта на черновом-только конвейере. Проверено исполнением, а не рассуждением:
TestACarriedUnitOnADraftOnlyPipeline— ось не выродилась в «никогда ничего не отгружено» (юнит, начатый и не отгруженный, опознаётся и дописывается), и не выродилась в обратную сторону (уже отгруженные не пере-продаются —TestDeliveryIsReadFromTheSHIPPINGWaveOnADraftOnlyPipeline).
Что НЕ удалось и что НЕ проверено.
- Остаток «первая редакторская стадия» — вне скоупа, требует носителя прошлой отгружающей волны (схема).
- Остаток «прерванная пере-делка» — найден этим паком, требует записи «какой прогон купил какую строку» (схема).
- Кратность оценки $0-строки: книга, у которой $0-стадия пере-куплена N раз, а потом уведена на платную модель, получает оценку, кратную N. Направление безопасное (завышение) и объявлено в тексте согласия, но точным его не сделать без маркера поколения на
checkpoints— та же схемная развилка, что в докстрингеusd(). - Юнит, начатый НЕОГРАНИЧЕННЫМ прогоном, слота в следующем ограниченном не берёт (но перенос ограничен грантом). Замерено тестом, на живой книге не проверялось.
- Взаимодействие переноса с ДЕНЕЖНЫМ потолком на длинном хвосте начатых юнитов не замерено: по построению объёмный потолок их не считает, держит денежный.
- Живой прогон с платными вызовами не делался — промт его не заказывал. Вендор-сверок нет: пак не трогает слаги моделей.
⚠ Якоря в ЧУЖИХ доках, уехавшие ИЗ-ЗА пака — править не могу, зона не моя; вот готовый список с новыми номерами (python3 docs/scripts/counts.py --lint; все шесть были ЦЕЛЫ на HEAD 2a63c37, проверено git show HEAD:<файл> | sed -n '<N>p'):
| док:строка | якорь был | цель сейчас |
|---|---|---|
docs/architecture/15-money-path.md:18 |
store/ledger.go:381 «SpentUSD reports (committed, reserved)» |
:392 |
docs/architecture/15-money-path.md:24 |
pipeline/status.go:290 «book_ceiling_usd,omitempty» |
:311 |
docs/architecture/15-money-path.md:24 |
pipeline/status.go:788 «100 * (committed + reserved)» |
:811 |
docs/PROGRESS.md:179 (тело строки 232) |
pipeline/status.go:866 «IT IS NO LONGER THE READ PATH'S FIRST ANSWER» |
:901 |
docs/archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md (строка 52 на момент выдачи; в архиве номера сдвинул баннер исхода) |
pipeline/status.go:217 «can never quote a different number» |
снят по заказу (ФЧ-5 п.4) |
docs/archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md (строка 54 на момент выдачи) |
pipeline/reprice.go:24 «NOT projected (like the content axis» |
снят по заказу (ФЧ-5 п.4) |
Первые четыре — сдвиг номеров от моих вставок; последние два промт заякорил на тексте, который сам же велел снять, поэтому их «поломка» и есть признак исполнения.
⚠ Про остальные 12 я сперва написала здесь «все в docs/experiments/**, пришли с полигонным мержем» — это было неверно, и поправлено разбором с платформенной сессией. Перечисляю по владению; ⚠ общее число гейта — величина ПОДВИЖНАЯ, обе смены правят дерево параллельно: на момент того разбора python3 docs/scripts/counts.py --lint печатал 18, на момент сдачи дофикса — 20 (в отчёте пака стояло «все 18 строк», и это было верно только для того часа). Разбивка по владению взята с той, 18-строчной выдачи:
- 4 — платформенной сессии (
textmachine-37):docs/PROGRESS.md:19,docs/archive/prompts/PLATFORM_P13_SESSION_PROMPT_2026-09-02.md(строка 286 на момент выдачи) иdocs/archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md(строка 227 на момент выдачи) целятся в одну снятую ею строку рантбукаplatform/deploy/README.md:213«сначала платформа, потом движок»; плюсdocs/archive/prompts/PLATFORM_P13_SESSION_PROMPT_2026-09-02.md(строка 166 на момент выдачи) на уехавшийQuarantine. ⚠ Третий из них живёт В МОЁМ промте (это его ⛔-оговорка о том, что совет рантбука опасен), но сломан не мной — целью владеет платформа. - 8 — полигонных, пришли с мержем
2a63c37: семь вdocs/experiments/**и один в теле бэклога —docs/PROGRESS.md:190наeval/conformance.py:48. - ⚠ Якорь в
docs/experiments/23-editor-tier.md:6196целится в строку 679 этого журнала, которой в нём нет: он был мёртв и до пака (тогда в файле было 472 строки), а мои вставки лишь меняют общее число, которым гейт объясняет смерть. ⚠ Записан здесь СЛОВАМИ, без токена «путь:номер» в обратных кавычках: гейт читает такой токен как якорь, и первая редакция этой строки сама добавила себе двадцатую поломку.
Урок, который стоит записи: первую версию этого абзаца я построила на подсчёте, не перечислив предмет, — тот же класс, что и мои прошлые ошибки «вывести отсутствие из счёта». Счёт по подстроке пути (grep -c 'platform/') тоже не есть счёт по владению: у платформы один из четырёх якорей целится ОТНОСИТЕЛЬНЫМ путём и в такой счёт не попадал.
Вопросы, вынесенные владельцу, и его слово (03.09) — записываю, чтобы решения не пере-открывались.
- Поле
carriedв кадреfinishedшва (runevents.VolumeLedger). Спрошено: добавлять ли число «сколько глав дописано сверх гранта», ведьdeliveredтеперь может превышатьmax_units. Цена вопроса названа: это класс «новое поле в опубликованном документе» — ратификация оркестратора плюс минорный бампStreamVersion, а промт запретил двигать контракт; платформа кадрVolumeсегодня не декодирует вовсе (platform/internal/ingest/events.go:Finished{Outcome}), потребителя у факта нет. РЕШЕНИЕ ВЛАДЕЛЬЦА: оставить как есть, поле не добавлять. Исполнено: поля нет, объяснение живёт словами в докстрингахDeliveredиFreeтого же кадра. - Семантика «юнит, начатый прогоном БЕЗ объёмного потолка, слота в следующей покупке не берёт; перенос ограничен размером гранта». Альтернативы названы: тратить на такие юниты купленное (тогда покупатель платит за главу дважды — ровно вред строки 232) либо завести схемный носитель «какая покупка оплатила какую строку». СЛОВО ВЛАДЕЛЬЦА: вынести оркестратору, решение отложено — «подумаем на этот счёт». ⇒ пункт остаётся ОТКРЫТЫМ вопросом к приёмке; в коде сейчас первый вариант, ограниченный грантом.
rebill_model_moved_rows— второе новое полеstatus --jsonсверх названного промтом одного; говорит, какая часть суммы завышена из-за смены модели стадии. Аддитивно, платформой игнорируется (её аллоулист не берёт ни одногоrebill_*); без него человекочитаемая строка и текст отказа перестают говорить дословно одно и то же. РЕШЕНИЕ ВЛАДЕЛЬЦА: оставить.- Ошибок в промте не нашла.
03.09 — ДОФИКС по приёмке №22 (наряд docs/archive/prompts/BACKEND_DOFIX_2026-09-03.md, сессия textmachine-77)
Состояние git на входе в дофикс — важнее прочего, потому что наряд писан по другому. Наряд говорит «в индексе лежит незакоммиченная работа двух смен». К моменту исполнения владелец уже закоммитил её в ЛОКАЛЬНЫЙ
e85295d«temp», аorigin/mainбыл обновлён ПРИНУДИТЕЛЬНО наea54355, в историю которогоtempне входит (git merge-base --is-ancestor e85295d origin/main→ нет). По слову владельца я откатил temp и подтянул наряды двумя командами:git reset --mixed 2a63c37, затемgit merge --ff-only origin/main(перемотка —ea54355растёт из того же2a63c37). Перед этим поставил меткуtemp-backup-e85295d, чтобы коммит с работой обеих смен нельзя было потерять; снимать её до лендинга не надо. Целостность проверена, а не предположена: изменённые файлы совпали с temp бит-в-бит (сравнение хешей двух диффов), пять добавленных файлов снова стали неотслеживаемыми и лежат на диске побайтно как в коммите (git hash-objectпротивgit rev-parse e85295d:<файл>). В дереве НА МОМЕНТ ОТКАТА было 44 файла: 22 мои, 21 платформы, один общий журнал; дальше число растёт у обеих смен по мере работы. Индекс пуст, не коммичу.Батарея после дофикса:
cd backend && make battery→MAKE_EXIT=0,golangci-lint0 issues,okв 18 пакетах, SKIP:TestMinerFullBookParity,TestHelperEventsRun,TestHelperKillLoop. Тесты^func Test:grep -rn '^func Test' backend --include=*_test.go | wc -l→ 1083 → 1105 (пак довёл до 1102, дофикс и правки по проверяющему добавили остальное), удалённых 0 (comm -23по снимкам имён). Каталогcmd/tmmutate/mutations.json: 73 → 92 (python3 -c "import json;print(len(json.load(open('backend/cmd/tmmutate/mutations.json'))))"), прирост 19 записей: паком 6 (FC1×4 — три названные гарантии,FC5×2 — свойства, которые пак создал), дофиксом и разбором его проверки 13 (FC6×4,FC7×5,FC8×3). ⚠ В первой редакции этой строки стояло «18 заведено дофиксом и проверкой», а перечень в скобке давал 14 и не называлFC1— число одной величины под именем другой, тот же класс, что чинит Б8. Команда:python3 -c "import json;from collections import Counter;d=json.load(open('backend/cmd/tmmutate/mutations.json'));print(Counter(m['id'].split('-')[0] for m in d if m['id'][:3] in ('FC1','FC5','FC6','FC7','FC8')))".
По каждому пункту Б1–Б9.
Б1 — стоп-строка и лог лгали в случае, который пак создал. ЗАКРЫТО.
Воспроизвёл сам, до правки: VolumeStop{MaxUnits:2, Delivered:2, Carried:2} → Left()=0 granted()=0 Paid()=2, и предложение печатало разом «not on money and not at the end of the book» и «Still in the book: 0 unit(s) NEVER delivered».
Правка: у String() теперь ДВА открытия по Left(). Грант придержал работу → прежний текст. Книга кончилась → «reached the END of the book under a VOLUME ceiling (--max-units N), which held nothing back», и хвост «Nothing is left in the book» вместо перечисления нулей. Смешанный случай отдельного текста не требует: это первая ветка с уже существующей клаузой про перенесённые. Тот же развилкой пошёл лог waverun.go (сообщение выбирается тем же предикатом), а протухший комментарий у scope.bound() пере-написан на то, что код делает: «set when the grant held work back OR when the run did work outside it».
Пин: TestARunThatWorkedOutsideItsGrantSaysSo дополнен — требует и «reached the END of the book», и «Nothing is left in the book», и ЗАПРЕЩАЕТ «not at the end of the book».
Б2 — ратифицированный контракт кадра finished.volume стал ложным. ЗАКРЫТО, поля НЕ добавлял.
Утверждение «present only when a volume grant actually held work back» снято во всех ЧЕТЫРЁХ местах: runevents.go (объявление поля и абзац «its PRESENCE is the boolean»), events.go (volumeLedger), bookrun.go (BookResult.Volume). Проверка: grep -rn 'only when the grant actually held something back\|present only when a volume grant actually held\|nil when no grant held anything back\|rather than because the book ended' backend/internal → пусто.
Новая формулировка говорит, что присутствие значит «грант был в силе и прогону есть что о нём сказать», и что различают два случая left_fresh/left_rework — оба ноля значат «книга кончилась». Там же прямо сказано, что счётчика перенесённых на проводе НЕТ и почему: владелец 03.09 сказал «оставить как есть». Ратификационная ссылка сохранена с оговоркой, что правило присутствия расширилось вместе со строкой 232.
Б3 — три свойства не были прибиты. ЗАКРЫТО, каждое воспроизведено и посажено. Сначала воспроизвёл все три на копии — все три SURVIVED, как и писала приёмка. После правки те же три посадки на свежей копии → все три RED.
- (а) ветка
unitFreshвreconcile: новыйTestReconcileKeepsContainmentOnTheFreshBranch. ⚠ Состояние в нём СКОНСТРУИРОВАНО, а не наблюдено, и это сказано в докстринге:Delivered == Carriedс исходом классаunitFreshне даёт сегодня ни одна фикстура. Утверждаю инвариант всё равно, потому что код заявляет его для КАЖДОЙ ветки. - (б) отказ по названному потолку:
TestTheScopedClauseOfTheRefusalCarriesItsOwnBasisдополнен половиной про--accept-rebill=<usd>— требует «1 of the 1» и запрещает «2 of the 2». - (в) оговорка про смену модели при нуле:
TestProjectionBasisNamesWhatTheAmountIsMadeOfполучил отрицательный пин, симметричный тому, что был у близнеца про старые деньги. Записи каталога:FC6-reconcile-fresh-branch,FC6-capped-refusal-borrows-book-basis,FC6-model-caveat-printed-at-zero.
Б4 — докстринг classifyUnits не пере-считан. ЗАКРЫТО. «three things this run can do to it» → «four»; проверено, что членов unitClass действительно четыре (sed -n '/^const (/,/^)/p' … | grep -c '^\tunit' → 4).
Б5 — пример в README.md:73 противоречил новой семантике. ЗАКРЫТО. «оплатить не больше 10 выходных юнитов» → «не больше 10 выходных юнитов возьмут слот», в согласии с телом README:11.
Б6 — шов store → репрайсер прибит с одной стороны. ВЗЯЛ, хотя пункт «по желанию».
Довод: мой же аргумент по фильтру книги («мутация пережила обе батареи по отдельности, значит одной мало») применим и здесь, и отказ от него был бы непоследовательностью, а не решением. Новый TestCheckpointUsageCarriesTheEscalationFlag в internal/store + запись FC6-escalation-flag-store; подмена c.escalation на 0 теперь краснеет и в store-пакете.
Б7 — отчёт ссылался на ПЯТЬ несуществующих посадок как на живые гейты. ЗАКРЫТО заведением, а не снятием ссылок.
Проверил каждую из пяти на копии: все пять ловятся существующими тестами — то есть свойства охраняются, но каталог их не помнил, а отчёт называл гейтами. Развязка честная только одна: сделать их настоящими записями. Заведены FC7-volume-stop-silent-outside-grant, FC7-reconcile-free-branch, FC7-zero-usage-row-silent-after-a-move, FC7-scoped-clause-without-basis, FC7-overshoot-claims-a-model-move; все пять пере-посажены → RED.
Б8 — четыре числа не печатались командами, которые отчёт для них называл. ЗАКРЫТО, каждое пере-считано.
- «денежного пути стало 5 файлов» — такого числа не даёт ни одно прочтение. Правда: греп промта считает СТРОКИ,
0 → 17; различных ФАЙЛОВ денежного пути0 → 4. Обе команды вписаны рядом с числами. - «на входе 3 попадания» у грепа про снятое обещание — правда 1:
git grep -n 'can never quote a different number' 2a63c37 -- backend/ | wc -l→ 1. Тройка была снята широким грепом на ТРИ разных шаблона и приписана этому, узкому. Тот же класс, что и мои прошлые ошибки со счётом: число из одной команды под именем другой. - «все 18 строк» линта — на момент сдачи дофикса гейт печатает 20 (
python3 docs/scripts/counts.py --lint). Число ПОДВИЖНОЕ: параллельная платформенная смена правит свои файлы, и её якоря уходят и возвращаются. В отчёт пака вписана оговорка об этом. - «в файле 485 строк» — сейчас 572 (
wc -l < docs/PROGRESS.md); число снималось до того, как отчёт дорос, и с каждой вставкой меняется. Формулировка в отчёте пака переписана так, чтобы не зависеть от него. - ⚠ Отчёт пака сам добавлял себе поломку гейта: строка таблицы называла чужой мёртвый якорь ТОКЕНОМ «путь-двоеточие-номер» в обратных кавычках, и гейт читал её как якорь ЭТОГО журнала. Переписана словами. ⚠ И первая редакция этого самого пункта наступила на то же место второй раз — объясняя поломку, она снова процитировала токен и снова его создала. Теперь ни одна строка обеих моих записей токена не содержит; проверка — грепом по выдаче гейта на строки этого журнала в моих секциях, пусто.
Б9 — неполнота самообъявления по D39.183. ЗАКРЫТО. TestCheckpointsOfOneGenerationSumToTheRowsCost дописан в блок самообъявления: адаптирован под третий возврат usd(), ослабления нет, правка механическая.
Б10 — к сведению, не заказ; называю, чтобы не умерло молча.
- Подсказка в докстринге
Deliveredключуется наdelivered > max_units, а в форме «весь остаток перенесён»delivered == max_units— подсказка не срабатывает, и разложить кадр читателю нечем. Связано с отложенным вопросом владельца о семантике переноса; чинится вместе с ним. - В перенос попадает и юнит, который ФЛАГНУЛСЯ и текста не отдал: он «начат и не отгружен», значит следующая покупка снова платит за его пере-атаку вне гранта. Цикл из трёх последовательных покупок не гонял никто — ни приёмка, ни я. Вход в решение владельца, не дефект.
Проверка дофикса свежим контекстом — один агент Fable 5, ограничение владельца соблюдено. Он прочитал исходный промт, наряд, оба моих отчёта и весь дифф, посадил 26 своих мутаций и пере-гнал батарею на копиях. Из его семи находок три взяты в работу и исправлены, четыре названы ниже как известные пробелы:
- [HIGH]
$0-вызов ВНУТРИ платного поколения выпадал из обхода — и уносил с собой сегодняшнюю цену. Форма: черновая стадия на локальной$0-модели с ПЛАТНЫМescalate_to; стоимость строки объясняет один хоп, поэтому обход останавливался и бесплатный primary терялся, а после сдвига стадии на платную модель число согласия выходило вдвое ниже реальной пере-покупки, БЕЗ оговорки. Воспроизвёл сам на юнит-уровне до правки:usd=0.010000 fromHistory=false moved=falseпри пере-покупке0.03. Правило переписано: вызов, стоивший ноль, никогда не останавливает обход и никогда не переполняет счёт — он берётся всегда, а обход стоит на первом ПЛАТНОМ вызове после того, как деньги строки объяснены. Цена решения названа в коде вслух: бесплатный вызов на хвосте СТАРОГО поколения тоже будет взят, то есть оценка завышается — ратифицированное направление. ПосадкаFC8-free-call-dropped-from-a-paid-generation. - [LOW→взято]
$0-строка, чей новейший вызов чужой, котировалась$0без оговорки: переполнения на нуле не бывает, поэтому детектор отката её не видел. Теперь такая строка помечается «не удалось пере-оценить»;skipped-строка остаётся честно бесплатной. ПосадкаFC8-unestablished-zero-row-published-as-free. ⚠ Существующий случай таблицы, чей комментарий говорил «skipped-строка», диспозицию не ставил — привёл тест к его собственному замыслу и добавил случай без скипа (объявляю по D39.183: поведение сменилось по находке, тест стал строже). - [LOW→взято] развилка ЛОГА из Б1 не была прибита — мутация «удалить ветку конца книги» переживала весь пакет. Новый
TestTheRunLogSaysWhichKindOfVolumeStopItWas(обе ветки, живым прогоном), посадкаFC8-log-fork-at-the-end-of-the-book. - [MED→исправлено] отчёт пака называл пять посадок разведочными именами (
Y2…,Y3,Z2,X29,Y4), которых в каталоге нет: Б7 завёл их под именамиFC7-*, но ссылки остались старыми. Переименованы;grepпо каталогу на старые имена → 0, ни одно из них больше не стоит в отчёте как имя гейта.
Второй проход того же проверяющего — по трём осям, вердикт его словами. Дерево ему было пере-сдано после правок; он адресно пере-атаковал свои находки 1, 3 и 6 (все три ДЕРЖАТ, каталожные посадки красные), отдельно проверил новое правило обхода usd() таблицей краевых форм (откат, остаток, эскалационный хоп, skipped, нулевая стоимость) и занижений не нашёл. A — исходный промт: исполнено с остатком (остатки — два схемных остатка строки 232 и отложенный вопрос владельца, все названы и заказаны такими). B — наряд Б1–Б9: все девять закрыты (Б8 был закрыт с остатком, см. N1 ниже — закрыт). C — код и отчёты: ГОДНО К ПРИЁМКЕ, блокеров нет. Три его новые находки, все LOW, закрыты здесь же:
- N1 — строка отчёта говорила «18 заведено дофиксом и проверкой», а раскладка в скобке давала 14 и не называла
FC1. Правда: прирост 18 = паком 6 (FC1×4,FC5×2) + дофиксом и разбором проверки 12 (FC6×4,FC7×5,FC8×3). Тот же класс, что чинит Б8, — число одной величины под именем другой; пере-считано командой, она стоит рядом. - N2 — условие
len(calls) > 0в метке «поколение не установлено» не было прибито: мутация переживала пакет. Добавлен случай «$0-строка без единого вызова на файле свободна, а не нераскрыта» + записьFC8-empty-cell-disclosed-as-unestablished(красная). - N3 — комментарий у той же ветки описывал
skipped-строку так, будто guard несущий, тогда как продовые вызывающие skipped-строки сюда не доводят (projectRebillих отфильтровывает,projectBookUSDроняет флаг). Комментарий говорит теперь ровно это: guard защитный, а не несущий, и почему он остаётся. Его диспозицию по находкам 4 и 5 («согласен, входы в отложенный вопрос владельца») принимаю; он же заметил, что находку 4 можно закрыть и без смены семантики — снимком plan-timeCarried. Это ВЫБОР, не необходимость, и он входит в тот же вопрос владельца.
Что НЕ удалось и что НЕ проверено (дофикс).
- Цикл из трёх покупок на флагнутом юните не замерен — см. Б10. Знаю, что не проверено; не чинил, потому что наряд прямо запретил трогать семантику переноса.
- Состояние
Delivered == Carriedс исходом классаunitFresh(Б3а) ни одной фикстурой не достигается; инвариант утверждён на сконструированном состоянии, и это сказано в самом тесте. - Живого прогона с платными вызовами не было ни в паке, ни в дофиксе.
- Оба остатка строки 232 (первая редакторская стадия; прерванная пере-делка) по-прежнему открыты и требуют схемного носителя.
- Четыре находки проверяющего названы, но НЕ чинятся — все четыре суть входы в отложенный владельцем вопрос о семантике переноса, и наряд прямо запретил её трогать:
- Клауза «finished OUTSIDE this grant» ключуется на
CarriedПОСЛЕreconcile, поэтому исчезает, когда все перенесённые юниты флагнулись: оператор видит «2 PAID FOR BUT FLAGGED», но не то, что обе оплаты шли вне гранта. Воспроизведено:VolumeStop{MaxUnits:2, Delivered:2, Carried:2}+ два флага классаunitCarried. - Перенесённый юнит с ПРОТУХШИМИ черновыми строками пере-покупает всю цепочку вне гранта, тогда как хелп флага обещает «дописать недостающее». Воспроизведено проверяющим:
granted()=0, два вызова провайдера на один юнит. - Подсказка в докстринге
Deliveredключуется наdelivered > max_unitsи молчит в форме «весь остаток перенесён», гдеdelivered == max_units(это же Б10 наряда). - Цикл из ТРЁХ последовательных покупок на флагнутом юните не гонял никто — ни приёмка, ни проверяющий, ни я.
- Клауза «finished OUTSIDE this grant» ключуется на
- Выживание трёх гарантий ФЧ-1 на дереве ДО пака проверяющий сам не воспроизводил (принял по моим красным посадкам); я это делал в паке отдельно, лог в scratch-каталоге сессии.
05.09 — ОТЧЁТ пака «денежный стоп перестаёт быть аварией» (сессия textmachine-main-be, промт BACKEND_MONEYSTOP_SESSION_PROMPT.md)
ПОЛНЫЙ ОТЧЁТ —
backend/docs/MONEYSTOP_REPORT.md(происхождение решений, пять рисков зоны по одному, самопроверка, объявления по D39.183, obstacle reporting). Здесь — итог и то, что нужно оркестратору для лендинга. Дерево НЕ закоммичено.⚠ В дереве лежат ЧУЖИЕ правки — вся
platform/(параллельный пакtextmachine-main-63). Не тронуты ни байтом. Платного прогона НЕТ: все три оси предъявлены за $0.
Четыре пункта закрыты. (1) строка 271 — правки банка больше не могут писать свои строки внутрь
system-сообщения платного вызова: одна граница (internal/membank/wirefence.go), три точки исполнения —
дверь отказывает, загрузчик сида отказывает, рендереры пропускают; предел 200 рун, запрет Cc + U+2028/9 +
bidi-переопределений (Trojan Source), при этом ZWJ/ZWNJ/LRM/RLM РАЗРЕШЕНЫ (общность §0.1); фолд версии
СКОУПНЫЙ, чистая книга хеширует байт-в-байт как до фикса — запинено значением, снятым сборкой 32be78a.
(2) строка 277 — отказ резерва защёлкивает волну и не отменяет допущенное; отказ не окончателен при
непустом полёте (ждём settle, повторяем тот же резерв); только ОБЯЗАТЕЛЬНЫЕ вызовы ждут. (3) строка
278 (событие) — недостача едет в ceiling, StreamVersion 1.2 → 1.3, денежный леджер в finished.
(4) строка 278 (проекция) — цена книги ДО покупки в manifest --json и status --json.
Числа, каждое получено командой (полный список — §6.7 отчёта). ⚠⚠ ТРИ ИЗ НИХ ПРОТУХЛИ ЧЕРЕЗ ТРИ ЧАСА, И ОДНО ПЕРЕВЁРНУТО — поправка в конце абзаца; она найдена ВЕРИФИКАТОРОМ 05.09, не зоной и не мной: тестовых функций 1172 → 1208 (+36), все тридцать шесть в трёх новых файлах; git diff -U0 -- backend | grep -E '^[+-]func Test' ПУСТ —
ни одна существующая не удалена и не переименована, два протухших починены внутри тела. Каталог мутаций 158 → 191. Батарея: MAKE_EXIT=0, 19 пакетов, 0 упавших, 0 issues (шестой прогон — первые пять красны или остановлены). Каталог ЦЕЛИКОМ: 191 запись, 187 RED, 0 SURVIVED, 0 NOTHING, 0 ROTTED, 0 неожиданных исходов — второй полный прогон; ПЕРВЫЙ не сошёлся и нашёл четыре дефекта в моих же артефактах, включая named-артефакт приёмки (§6.5 отчёта) (и go vet -vettool
собственного анализатора зоны — чисто; он поймал у меня один хенд-билд config.Stage, см. отчёт).
⚠⚠ ПОПРАВКА 05.09 (замер верификатора по дереву на d766007; числа выше НЕ переписаны — они были верны в свою минуту). Абзац заленджен коммитом ba4fd34 через девять секунд после пака 81a89e9 и за три с лишним часа ДО дофикса 616a8e4, который добавил ещё +5 тест-функций и +10 записей каталога. Сообщение коммита подписало их «final counts», и после дофикса их никто не тронул. Верно на сегодня: тестовых функций 1172 → 1213 (+41) · каталог мутаций 158 → 201 · каталог целиком — 201 запись, 197 RED, ЧЕТЫРЕ аргументированных выживших, 0 неожиданных исходов. ⛔ **⚠ Испр. 06.09 автором находки: ПРОТУХЛИ ДВА числа, не три, и „0 SURVIVED" НЕ протухло. У инструмента ДВА ведра: SURVIVED — неожиданный выживший (настоящая дыра), survives строчными — записанный и аргументированный. На ревизии, которую абзац описывает, каталог был 191 = 187 red + 4 survives, то есть все три числа верны ДЛЯ СВОЕЙ РЕВИЗИИ; четыре аргументированных были четырьмя уже тогда. Протухли 191→201 и 187→197. Третье — не протухание, а НЕПОЛНОЕ ПЕРЕЧИСЛЕНИЕ: 187+0+0+0 = 187 при собственном итоге 191, потому что ведро аргументированных не названо. Дефект другой природы и слабее. Прежняя редакция: Переворачивается именно последнее: «0 SURVIVED» против четырёх записанных выживших — а это то самое различение из D39.202 п.3 (SURVIVED как СООБЩЕНИЕ О НЕДОСТИЖИМОСТИ, а не как провал), и следующая движковая смена открывает этот журнал РАНЬШЕ акта. Акт D39.206 всё это время нёс верные числа — разошлись НОСИТЕЛИ, а не факт: класс «поправил читателя, оставил писателя» (D39.202 п.1).
⛔ ТРИ ВЕЩИ, КОТОРЫЕ ОРКЕСТРАТОРУ НАДО ЗНАТЬ ДЛЯ ЛЕНДИНГА:
- Наружу едет НЕ то число, что назвал промт, и это согласовано. §4(3) назвал
denied estimateи следующей фразой запретил его класс («цены вызовов не выходят»). Едет недостачаcommitted+reserved+estimate−ceiling, полеshortfall_micro_usd(строка 278 называлаnext_step_micro_usd). Две оговорки в доке поля: при непустом полёте это ВЕРХНЯЯ граница; дляday-скоупа поле ОПУЩЕНО (дневной потолок суммирует все книги стора, движковые цифры — одной). - Третье лечение пункта 1 («обрамление как ДАННЫХ») в ТЕКСТОВОЙ форме невыполнимо.
lang/data/injection.txtпобайтно входит вEmbeddedVersion()→cutTag→ внутрь каждогоunit.id: добавление одной строки пере-чеканило бы id всех книг. Сделано структурно. res.Volumeпри денежном стопе НЕ прикладывается. Семь счётчиковVolumeStop— план; денежный стоп оставляет допущенные-и-не-доделанные юниты посчитанными какDelivered, аLeftFreshзаниженным на них, и приLeft()==0прогон, вставший посреди книги, объявил бы «дошёл до конца». Восьмого бакета нет ⇒ у денежного стопа СВОЙ леджерFinished.Money{units_resolved, units_deferred}из тех же счётчиков, что иprogress.
⚠ ЧЕТВЁРТОЕ ДЛЯ ЛЕНДИНГА, и это вход в СТРОКУ 283, а не мой дефект: structure: detected сегодня
CJK-ONLY. Сопоставление заголовков в интейке идёт по lang.DefaultCJKSection() — КОНСТАНТА (章节節回 +
класс CJK-числительных), не данные пары. ⇒ книга в любой другой письменности возвращает none, как бы
явно её главы ни были размечены. Асимметрию пак НЕ вносит — движок уже читает данные пары для РЕНДЕРА
заголовка (configs/langpacks/*/heading.txt), а РАЗРЕЗ остаётся захардкоженным, и строка 283 называет
именно этот раскол работой. Что поле ДОБАВЛЯЕТ: у асимметрии появляется имя на проводе вместо того, чтобы
прятаться в числе глав — не-CJK книга честно говорит none, и форма заказа (D39.196) не предложит
ползунок в ГЛАВАХ против разреза, которого никто не делал. Классификация сама пар-агностична (спрашивает,
какой ПУТЬ провёл границы) и скажет detected без правки Go в день, когда разрез научится читать пару.
⚠ Первую редакцию комментария и отчёта я написала как «пар-агностично по построению» — это было
пере-утверждение, поймано собственным проходом и исправлено в обоих местах.
ПРАВКИ ЧУЖИХ ТЕСТОВ — объявление по D39.183 (все три вызваны сменой поведения, заказанной паком):
· runevents_test.go — пин «the ceiling event must carry the fact and no figures» СУЖЕН, не снят: белый
список ключей (halted|scope|shortfall_micro_usd), запрет любого $, ПЛЮС новое утверждение — book-стоп
обязан назвать недостачу, day-стоп обязан её не называть. ⚠ Фраза ратифицирована (D39.106 §2/ПТ-33) —
ноту о сужении берёт на себя оркестратор.
· wavepanic_test.go, volumepanic_test.go — оба ВИСЛИ (panic: test timed out after 1m30s): парковали
падающий воркер на <-ctx.Done(), которую вызывал ПОТОЛОК. Потолок больше не отменяет — это заказ пака.
Триггер заменён, утверждения не ослаблены.
ПРАВКА ВНЕ ЗАКАЗА, взятая по своему усмотрению: течь резервации на ветке json.Marshal(resp.Usage)
(stagerun.go) — возврат без release и без settle. Довод: денежный путь, и у него появился второй
читатель — утёкшая резервация ЗАВЫШАЕТ публикуемую недостачу. Ветка практически недостижима, поэтому её
посадка занесена аргументированным выжившим, а не находкой.
⚠ ЧЕТВЁРТЫЙ КЛАСС ЛОЖНОЙ ЗЕЛЕНИ, найденный в этой смене (общий, не про мой пак): t.Fatalf из
ПОРОЖДЁННОЙ горутины — runtime.Goexit не на той горутине: утверждение теряется, прогон висит до
таймаута ПАКЕТА. Посадка, чей отказ выглядит как таймаут, неотличима от нагрузки и потому не является
посадкой — а Makefile зоны сам документирует разброс internal/pipeline 95 → 560 с под параллельными
сессиями. Рядом с тремя известными: упавшая сборка, вырожденное утверждение, эквивалентная посадка.
ГОТОВЫЙ ТЕКСТ СТРОКИ БЭКЛОГА (таблица — зона оркестратора, поэтому текст лежит здесь, а заводит его он; уже принят и заведён как строка 291):
Отказ РЕЗЕРВАЦИИ на ретрае не деградирует и не оставляет следа — юнит может заклинить навсегда, а волна не может продолжиться без дыры.
maxTokensForAttemptудваивает бюджет на каждой регенерации (disposition.go:398) ⇒ attempt 1 резервирует вдвое больше attempt 0. Отказ ретрая уходит наверх из цикла попыток (stagerun.go:164-167) РАНЬШЕUpsertChunkStatus(stagerun.go:285) ⇒ чекпойнт attempt 0 есть (реплей за $0), строкиchunk_statusнет, читающие модели видятpending. Следствия два: (1) если потолок покупки не вмещает attempt 1 — юнит не доделается НИКОГДА, каждый резюм реплеит attempt 0 за $0 и умирает на attempt 1, прогон уходит exit 4 при полностью доставленных купленных юнитах; (2) продолжить волну после отказа ретрая нельзя без дыры в непрерывном префиксе — то есть цена глобальной защёлки (недодача юнитов, которые ВЛЕЗАЛИ; разброс резервов внутри волны замерен 2.976×, разбор 04.09) не снимается различителем «свежий/ретрай». Два пути, ВЫБОР НЕ СДЕЛАН: (а) отказ ретрая деградирует во флаг attempt 0 — смена D2.3, закрывает оба следствия; (б) минимальная покупка платформы ≥step_max_usdдвижка — закрывает только (1) и стоит продукту минимальной покупки ~5 глав | бэкенд+платформа | скоро | выбор владельца между (а) и (б) + пин | бэкенд-сессия денежного стопа 05.09
ГДЕ ПРОМТ НАПИСАН НЕ ТАК (требование §5-тер(а), полный список — §5 отчёта): §4(3) внутренне
противоречив (см. выше) · §4(1) заказывает лечение, невыполнимое без нарушения §4(6) · §3 п.1 называет
секцию 15-money-path.md, переименованную 05.09 · §4(2) обосновывает защёлку доводом, который снят самой
конструкцией (haltErr — отдельный слот, путь ошибки один при любом W); защёлка оставлена по ДРУГОМУ
доводу — продуктовому · §4-тер риск (б) назван мягче, чем он есть: счётчики не «получают новую форму», а
врут по шести полям из семи.