From 58414fb1419974deda6cc007a602e1cfbe8791eb Mon Sep 17 00:00:00 2001 From: heaven Date: Sat, 29 Aug 2026 02:01:30 +0300 Subject: [PATCH] Dump the state of two unfinished acceptances before compaction: what is verified, what is only reported, and what gates the pipe --- docs/PROGRESS.md | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index d4810f86..8f5c36cb 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -17,6 +17,36 @@ > - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 28.08 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **175** строк · зона бэкенд **83** строго / **120** широко (175 пере-скоуплена D39.134; 176/177 заведены 15.08; 178 — D39.136; 179 ЗАКРЫТА D39.138; 180/181 — D39.137; 182 — wire-батч, аудит 15.08; 183–187 — контракт-ревью 28, D39.138; 188–190 — аудит бэклога, D39.140; 191/192 — модель подписи банка и пост-ридинговый цикл, D39.144; 193 — молчащие дыры выдачи, D39.147; 194–196 — приёмка пака честности, D39.149; 197 — фикс-лист ФЧ, D39.150; **198–204 — приёмка P7 и слова владельца 20.08, D39.153; 205 — слепота гейта якорей, аудит 21.08; 206–207 — приёмка P8-FIX, D39.154; 208–209 — аудит доков 22.08 (потеря глоссария на Gemini, риг живых проб); 210 — трассировка цепи банка 22.08 (род не производится авто-путём); **211–213 — консилиум шва 22–23.08: ключи провайдеров не доезжают до движка на SaaS (блокер 202), нестрогий загрузчик сида, дубль конвенции пути у платформы — 211 ЗАКРЫТА и 213 сужена лендингом P9 (D39.162); 214–216 — разбор журнала трассировки банка: подпись не оставляет следа, $0-репин недостижим с платформы, три несущих сценария не проверены живым движком; 217–218, 220 — аудит переезда машины 24.08: абсолютные пути полигона, дефолты корпуса в движке, бутстрап гейта доков чужой замороженной зоной; 219 (съехавшие line-якоря D-лога) ЗАКРЫТА тем же заходом — D39.157 п.6**) (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0**, платные прогоны разблокированы · «скоро» **49** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строки эксп-22: 55·153 (плюс 150 — руки владельца); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). > - Архивы хроники: `archive/PROGRESS-2026-07-04-10.md` (D31) · `-10-13` (D39.6-гигиена) · `-13-25` (стройка паков 11–16, rerun2) · **`-25-31` (паки 17–20 · мини-прогон · полигон-пакеты 5–8 · ToS · холодный прогон; D39.26–58)** · **`-08-01-02` (сессии №9/№10: общность · качество банка · coldrun-b · открытие фронта/платформы; D39.59–90, срез D39.105)** · **`-08-02-04` (сессии №11–№13: ручки эффорта · стандарты · контракт API · платформа P0 · банк-арбитраж; D39.91–105 + снимок шапки эры №15)** · `-08-04-09` (пинги закрытых паков эры №15) · **`-08-14-15` (закрытые бэкенд-записи №16–17: эмиттер шва · migrate · пере-пин DeepSeek; вынесено D39.139)**. Записи ниже — живой хвост (№16+, эра D39.124+; подрезка D39.139). +## 📌 ДАМП СОСТОЯНИЯ ПЕРЕД СЖАТИЕМ КОНТЕКСТА (оркестратор №19, 29.08) — приёмка двух паков НЕ закончена + +⚠ **ЗАКОММИЧЕНО ИЗ ЭТОЙ РАБОТЫ — НИЧЕГО.** Последний коммит `ac6f9a1`. Незакоммичено: `docs/` 1 (канон 0.8.0), `platform/` 30, `backend/` 24, `frontend/` 1 (мой пинг), `eval/` 19 (полигон, чужое, не трогать). + +**МОЁ НЕЗАКОММИЧЕННОЕ, готовое:** +- **Канон 0.8.0** — кадр `session_ended` в enum, строке таблицы и схеме `EventSessionEnded` (парсится, висячих `$ref` 0). ⚠ **`ContractVersion` НЕ поднята — поднимаю Я одной строкой ПРИ ЛЕНДИНГЕ**, вместе с каноном одним коммитом. Сессия c0 сознательно её не трогала, и это верно. +- **Пинг фронту** в `frontend/docs/frontend-PROGRESS.md`: без обработчика `session_ended` отзыв сессии неотличим от обрыва, клиент уйдёт переподключаться в 401 — половина `PD-379`, видимая ЧИТАТЕЛЮ, не доставлена. + +**ДВЕ СЕССИИ РАБОТАЮТ (обе `busy`):** +- **`textmachine-e4`** — бэкенд-пак «деньги». Доводит код по слову владельца («приемлемое качество определяешь сам»). Второй круг дал ЕЩЁ ШЕСТЬ настоящих находок, все свои; тяжелейшая — потолок тратил покупку на ПЕРЕ-ДЕЛКУ вперёд доставки (куплено 2 юнита, переделаны главы 1–2, глава 3 не начата, деньги списаны). Сейчас гоняет три ратификатора на развилках, где не уверена. +- **`textmachine-c0`** — платформенный P11. Пак отчитан, сверх него я выдал ей `STACK_DECISIONS` §13 (ратифицировано мной, правит она) + галочка ASVS 7.4.1. + +**ПРИЁМКА — ГДЕ ОСТАНОВИЛСЯ:** +- **Бэкенд-пак: НЕ принят.** Сделано мной: пере-прогон батареи (флейк разобран), две свои посадки мутаций (обе топичны), слепой верификатор по заказу+диффу и охотник вне карты отчёта. Дали **4 денежных дефекта**, отправлены на починку. ⚠ Отдельно: c0 убила `pkill`-ом шесть ревью-агентов e4 в окне 01:36–01:37, включая линзу покрытия посадками — **приёмку не закрывать, пока не увижу, что пере-прогон e4 состоялся**, иначе риск принять ложное зелено. +- **Платформенный P11: приёмка НЕ НАЧАТА.** Ни батареи, ни верификатора, ни охотника. ⚠ Числа её отчёта (836 тестов, 18 пакетов, 0 скипов) — **СО СЛОВ СЕССИИ, мной не пере-мерены**. + +**ОТКРЫТЫЕ ДИСПОЗИЦИИ:** +- ⛔ **Проводка `--max-units` ГЕЙЧЕНА:** платформа не имеет права проводить объёмный потолок, пока не вылечен хвост «майнящая книга → вторая покупка падает без `--resnapshot`». Причина: платформа передаёт флаг по условию `book.BankMoved`, а рост авто-банка это условие не ставит ⇒ бьёт по флагманскому пути. +- ⛔ **Отозвано моё подтверждение сужения D20.2-Q2:** сумма по допущенным юнитам при книжном пороге даёт обход гейта согласия циклом мелких покупок (замерено: 4 прохода по $0.003640 там, где безпотолочный прогон отказывает на $0.109200). Направление — порог не должен побеждаться дроблением. +- Остаток «трата терминолога/консолидации вне объёмного потолка» — в цену, не в потолок. + +**СТРОКИ, КОТОРЫЕ НАДО ЗАВЕСТИ ПРИ ЛЕНДИНГЕ:** +- **Нагрузочно-хрупкий тест `TestTheSeamIsNotChargedToTheStoreOperationBudget`** (`backend/internal/store/migrate_test.go:408-429`): ужимает `opTimeout` до 150 мс, под параллельной нагрузкой одиночный ALTER не укладывается. Проверено сессией e4 правильным методом — чистый HEAD через `git archive` в отдельный каталог, пять прогонов вперемежку: **её дерево падает 4 из 5, HEAD падает 4 из 5** ⇒ от правок пака НЕ зависит. Цена экономии «без мёртвого времени» — ложное красное у каждой следующей приёмки. +- Терминолог вне объёмного потолка · семь строк реестра от c0 · строки от e4 по её второму кругу. + +**НОРМЫ, ЗАРАБОТАННЫЕ СЕГОДНЯ (в акт лендинга):** +- **Зелёная батарея — это ПОЛНЫЙ список пакетов ПЛЮС отсутствие FAIL, а не отсутствие FAIL.** Найдено e4 на себе: её первый «зелёный» прогон был 20 пакетов из 21 с FAIL в хвосте, замаскированный `exit 0` обёртки. Сверять против `go list ./...`. ⚠ Я проверил на себе: 17 с вердиктом + 4 без тестов = 21, полнота была, но я её НЕ проверял — просто считал строки `ok`. +- **`pkill` по имени процесса на машине с параллельными сессиями бьёт по чужому по построению.** Гасить по идентификаторам, которые сам и получил. +- **Число или «доказано» уходит владельцу только после СВОЕГО прогона.** Чужое — с пометкой «со слов сессии». Нарушено мной сегодня по P11. + ## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора) Закрытые строки здесь НЕ хранятся — они уходят в D-лог с номером решения. **ID строки стабилен навсегда** (не перенумеровывается и не переиспользуется — на «строку N» ссылаются доки и промты, D39.80). Вес: «блокер-очереди» = мешает текущему шагу · «скоро» = ближайшие 1–2 касания · «когда-нибудь» = записано, не потеряно. Длинная строка начинается жирным лидом — таблица сканируется по лидам; «диспозиция сверху, археология вниз», ячейка >800 байт — кандидат на выселение в `architecture/13-tech-debt-anchors.md` (D39.125 п.3/D39.126). ⚠ **Счёт очереди — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов в 104 и честность в 105); ленту ✅ шапки читать как «долга нет» неверно (D39.89). **Зонные бэклоги (решение владельца 02.08, D39.84):** фронт и платформа ведут СВОИ бэклоги (`frontend/docs/BACKLOG.md` · `platform/BACKLOG.md`) — их строки сюда НЕ заходят; здесь движок/полигон/доки, включая движковые стыки фронта (зона «бэкенд», как 99–102); строки 96/97 переехали в платформенный (П-1/П-2), надгробия-указатели сохранены. @@ -293,8 +323,8 @@ |---|---|---| | **§3.1** потолок ОБЪЁМА рядом с денежным | Флаг `--max-units N` у `translate`; единица — **выходной юнит** (`ManifestUnit`=`editUnit`, `units_total` манифеста); допуск считается ДО волн (`planVolume`, `backend/internal/pipeline/volume.go`), волны не начинают элемент вне скоупа | `TestTheVolumeCeilingStopsAtWhatWasBought` — 5 глав, потолок 2: отгружено ровно 2, `res.Volume` заполнен, у глав 3–5 **нет ни одной строки `chunk_status`**, вызовов провайдера ровно 4 (2 юнита × 2 стадии) | | §3.1 — «проверять ПЕРЕД началом единицы» (грабля LiteLLM) | Свойство конструктивное: элемент вне скоупа не начинается вовсе | Тот же тест, клауза (3): отсутствие строк у N+1 и точный счёт вызовов; мутация «потолок на единицу больше» (`Granted <= MaxUnits`) — падают 3 теста | -| §3.1 — «остановка НАЗЫВАЕТ свой потолок» (грабля OpenHands) | `BookResult.Volume` (`VolumeStop{MaxUnits,Granted,Deferred,Free}`), строка лога, строка вывода CLI | `TestAVolumeStopIsNotAMoneyStop` — денежный стоп остаётся типизированным `*CeilingHalt` (exit 4), объёмный не ошибка вовсе и несёт `res.Volume` | -| §3.1 — счёт РЕПИНОВ | Не считаются: считаются только юниты, по которым прогон сделает ≥1 вызов | `TestAResumeDoesNotSpendItsVolumeOnFreeUnits` — вторая покупка 2 юнитов на книге, где 2 уже сделаны: `Free=2`, `Granted=2`, `Deferred=1`, свежих вызовов ровно 4. Мутация «свободные тратят грант» — тест падает | +| §3.1 — «остановка НАЗЫВАЕТ свой потолок» (грабля OpenHands) | `BookResult.Volume` (`VolumeStop{MaxUnits, Delivered, Reworked, Free, LeftFresh, LeftRework}` — ⚠ поля ПЕРЕСТРОЕНЫ на втором круге, см. находку 2), строка лога, строка вывода CLI | `TestAVolumeStopIsNotAMoneyStop` — денежный стоп остаётся типизированным `*CeilingHalt` (exit 4), объёмный не ошибка вовсе и несёт `res.Volume` | +| §3.1 — счёт РЕПИНОВ | Не считаются: считаются только юниты, по которым прогон сделает ≥1 вызов | `TestAResumeDoesNotSpendItsVolumeOnFreeUnits` — вторая покупка 2 юнитов на книге, где 2 уже сделаны: `Free=2`, `Delivered=2`, `LeftFresh=1`, свежих вызовов ровно 4. Мутация «свободные тратят грант» — тест падает | | §3.1 — счёт РЕТРАЕВ | Не считаются: ретрай/эскалация внутри юнита | `TestRetriesDoNotBurnTheVolumeCeiling` — провайдер отдаёт `finish_reason: length` на первом черновике: юнитов всё равно 2, вызовов >4 | | §3.1 — форма ответа через шов | Решение оркестратора исполнено: код выхода **0**, словарь `main.go:115-140` не тронут, словарь `runevents` не тронут | `res.ExitCode()==0` в тесте; сверено чтением `platform/internal/runs/reconcile.go:703-706` — exit 0 = статус ПРОГОНА `ready`, книга дочитанной не объявляется | | §3.1 — ортогональность | `--max-units` не касается леджера, резерваций и кумулятивной семантики `--ceiling-usd` | `TestAVolumeStopIsNotAMoneyStop`; `MaxUnits` не входит ни в `BriefHash`, ни в снапшот-пейлоад | @@ -305,7 +335,7 @@ | §3.2 — **тождество** сметы и прогона | `storeOrder` воспроизводит `ORDER BY` стора; фолд один на оба пути | `TestTheInMemoryFoldIsIdenticalToTheStoreRoundTrip` — оба пути на одном состоянии: строки, voices, pairs, `Version()`, `BaseVersion()` и **карта отрендеренных content-hash** совпадают. Мутация «убрать сортировку» — падает с топичным «row 0 differs» | | §3.2 — мина `omitempty` | `rebill_units`/`rebill_usd` больше не `omitempty`; добавлено `rebill_basis` (`pending`/`stored`/`none`/`failed`) | `TestTheWireTellsFreeFromUnknown` — «нечего пере-оплачивать» и «посчитано, и это ноль» на проводе различимы | | §3.2 — книга остаётся инспектируемой | Отказ фолда не валит чтение: фолбэк на сохранённый глоссарий + честный `basis` + WARN | `TestTheEstimateSurvivesABookWhoseFoldRefuses` — сид-коллизия: `status` отвечает, `basis=stored` | -| §3.1 — потолок не отказывает законной работе | Гейт согласия (D20.2-Q2) считает СУММУ по допущенным юнитам; порог остаётся книжным | `TestABoundedRunIsNotAskedToConsentToTheWholeBook` — порог книги между ценой одного юнита и всей книги: без потолка гейт отказывает, с `--max-units 1` прогон идёт и делает ровно 1 вызов | +| §3.1 — потолок не отказывает законной работе И не даёт обойти порог дроблением | ⚠ **Строка ПЕРЕПИСАНА после отзыва первой редакции — см. второй круг, находка 1.** Порог судится по ВСЕЙ книге (дробить бесполезно); именованный кап `--accept-rebill=X` судится по тому, что заплатит ЭТОТ прогон (законная работа не отклоняется); прогон, который не пере-оплачивает ничего, гейта не встречает вовсе | `TestABoundedRunCannotOutrunTheConsentThreshold` (обе стороны на одном состоянии) + `TestARunThatRePaysNothingIsNotAskedForConsent` (третья ветка). Мутации: порог по прогону · кап по книге · снятие ранней ветки — все три падают адресно | | §3.1 — потолок не даёт перерасхода на неполном юните | Терминальность = ПОКРЫТИЕ всех ожидаемых позиций (`unitFullyRecorded`), а не вердикт `resolveChunkState` | `TestAFlaggedMemberWithNoEditRowIsNotFree` — флагнутый член + ноль edit-строк; без фикса юнит признаётся свободным и оплачивается сверх потолка | | §3.1 — неопределённость всегда в сторону «платно» | `!ok \|\| h != ContentHash` ⇒ невоспроизводимый хеш = платно | `TestAnUnreproducibleHashIsNeverFree` (6 состояний, включая `skipped` и снятую стадию) | | §3.1 — допускается ВЕСЬ юнит, а не его лидер | Допуск помечает каждого члена | `TestTheCeilingAdmitsEveryMemberOfAUnit` — мелкая нарезка ⇒ 3 чанка в главе; мутация «только лидер» даёт усечённую главу | @@ -320,11 +350,11 @@ Веер: шесть линз (деньги · тождество фолда · шов · регрессии пака · параллелизм/детерминизм · качество моих же тестов), тяжёлая модель — РОВНО ОДИН агент (денежная линза), остальным попроще; затем по одному независимому опровергателю на каждую находку. Сырых находок 10, после опровержения осталось 7 настоящих. **Все семь внёс сам этот пак — приёмке они не видны, поэтому называю первыми.** -**1. ⛔ ПЕРЕРАСХОД: юнит с флагнутым членом и без edit-строки считался БЕСПЛАТНЫМ.** `unitsServedFree` спрашивал терминальность у `resolveChunkState`, а тот отдаёт `ChunkFlagged`, как только флагнута ЛЮБАЯ строка, — ДО проверки, что все ожидаемые позиции на месте. Юнит, у которого черновик одного члена флагнут, а edit-строки ещё нет (состояние после подписного стопа банка, Ctrl-C или любого обрыва в редакторской волне), признавался терминальным и свободным, проходил БЕЗ списания гранта и потом оплачивался редактором. Прогон платил за юнитов больше, чем куплено, и, поскольку `Deferred` оставался нулём, **даже не сообщал об объёмном стопе.** +**1. ⛔ ПЕРЕРАСХОД: юнит с флагнутым членом и без edit-строки считался БЕСПЛАТНЫМ.** `unitsServedFree` спрашивал терминальность у `resolveChunkState`, а тот отдаёт `ChunkFlagged`, как только флагнута ЛЮБАЯ строка, — ДО проверки, что все ожидаемые позиции на месте. Юнит, у которого черновик одного члена флагнут, а edit-строки ещё нет (состояние после подписного стопа банка, Ctrl-C или любого обрыва в редакторской волне), признавался терминальным и свободным, проходил БЕЗ списания гранта и потом оплачивался редактором. Прогон платил за юнитов больше, чем куплено, и, поскольку остаток оставался нулём, **даже не сообщал об объёмном стопе.** **Лечение:** предикат заменён на `unitFullyRecorded` — покрытие ВСЕХ ожидаемых позиций строками; полнота и есть терминальность, и именно она предсказывает «вызова не будет». **Доказано:** `TestAFlaggedMemberWithNoEditRowIsNotFree` (обрыв редактора на прогоне 1 → флагнутый член + ноль edit-строк; прогон 2 с потолком 1). Возврат к прежнему предикату мутацией — тест падает с «the other unit was judged free and paid for anyway». **2. ⛔ ОТКАЗ ЗАКОННОЙ РАБОТЕ: гейт согласия судил ВСЮ книгу при обрезанном прогоне.** Нашёл сам, до линз. `checkRebillConsent` стоял ПЕРЕД `planVolume` и проецировал пере-оплату по всем строкам, тогда как прогон с `--max-units 2` пере-оплатит максимум два юнита. Р6 требует согласия на КОНКРЕТНУЮ трату — а тут отказ (или запрос согласия) шёл на деньги, которые никто не потратит. Это ровно то, о чём предупреждает сам `rebill.go`: «число, которое одобрили и не списали, — это то, из-за чего такие числа перестают читать». -**Лечение:** скоуп считается ДО гейта; СУММА сужена до допущенных юнитов, ПОРОГ оставлен книжным (5% книги — свойство книги, не покупки). **Инертно без флага** (`scope==nil` ⇒ фильтр тождественный ⇒ число байт-в-байт прежнее) — это и делает правку ратифицированного гейта безопасной. **Доказано:** `TestABoundedRunIsNotAskedToConsentToTheWholeBook`; мутация «фильтр в тождество» воспроизводит отказ дословно. +**Лечение:** скоуп считается ДО гейта; СУММА сужена до допущенных юнитов, ПОРОГ оставлен книжным (5% книги — свойство книги, не покупки). **Инертно без флага** (`scope==nil` ⇒ фильтр тождественный ⇒ число байт-в-байт прежнее) — это и делает правку ратифицированного гейта безопасной. **Доказано на первом круге** мутацией «фильтр в тождество». ⚠ **Это решение ОТОЗВАНО на втором круге** (находка 1 ниже) — читать вместе с ним, а не отдельно. **3. Отказ `redrive` учил ЛОЖНОМУ факту об движке.** Текст говорил «`redrive` не гоняет книжную волну, которую это могло бы ограничить» — неправда: `redrive` зовёт `TranslateBook` (`status.go:984`). Мой же комментарий четырьмя строками выше говорил обратное и верное. **Лечение:** у `redrive` теперь свой текст, называющий НАСТОЯЩУЮ причину (деструктивный сброс ограничен своим селектором, и потолок в юнитах ограничил бы вторую половину команды, читаясь как ограничение целого). Тест дотянут: он проверяет не только имя флага, но и что причина не врёт про адресата.