Ratify the machine move as D39.157: repair the dead decision-log anchors, teach the gate to catch them structurally, and stop the registry lying about seventeen bodies
This commit is contained in:
parent
6335211183
commit
e83e94be46
8 changed files with 93 additions and 33 deletions
File diff suppressed because one or more lines are too long
|
|
@ -1,11 +1,11 @@
|
|||
# Реестр D-нот — карта актуальности v2 (D1–D39.156;
|
||||
# Реестр D-нот — карта актуальности v2 (D1–D39.157;
|
||||
|
||||
> ⚠ **ЗНАЙ СЛАБОЕ МЕСТО ЭТОГО ФАЙЛА (вписано 22.08 аудитом доков).** Реестр продан как «статус и тело
|
||||
> ЛЮБОГО номера одним хопом» (D39.126) — и колонка ТЕЛА у нот D39.107…D39.123 говорит «жив», хотя
|
||||
> тела уехали в слайс `../archive/architecture/05-decisions-D39-106-123.md` подрезкой D39.139.
|
||||
> Не нашёл тело по колонке — иди в слайсы, их шесть, перечень в шапке `05-decisions-log.md`.
|
||||
> `counts.py --check` этот класс НЕ ловит по устройству: он сверяет полноту номеров, а не то, где
|
||||
> лежит тело. Пере-снимать колонку целиком — отдельная работа, здесь названа, чтобы не молчала.
|
||||
> ⚠ **СЛАБОЕ МЕСТО, КОТОРОЕ БЫЛО ЗДЕСЬ (вписано 22.08, ЗАКРЫТО 24.08 — D39.157 п.6).** Колонка ТЕЛА
|
||||
> у нот D39.107…D39.123 говорила «жив», хотя тела уехали в слайс подрезкой D39.139; семнадцать строк
|
||||
> исправлены и пере-проверены скриптом (лжи 0). Остаточное предупреждение в силе: `counts.py --check`
|
||||
> этот класс НЕ ловит по устройству — он сверяет полноту номеров, а не место тела, поэтому колонка
|
||||
> держится дисциплиной лендинга. Не нашёл тело по колонке — иди в слайсы, перечень в шапке
|
||||
> `05-decisions-log.md`.
|
||||
строка 167; титул — носитель головы, бампать при каждом аппенде — испр. оркестратором №17 15.08 по аудиту: отставал на четыре ноты)
|
||||
|
||||
> Одна строка на КАЖДУЮ ноту журнала решений: № · дата · суть · статус · где тело · темы. Ведёт оркестратор при лендингах: новая нота = новая строка ТЕМ ЖЕ коммитом (полноту сторожит `docs/scripts/counts.py --check`). Суть и статус здесь — НАВИГАЦИЯ, не контракт: при конфликте побеждает ТЕЛО ноты (живой [`05-decisions-log.md`](05-decisions-log.md) → слайсы `../archive/architecture/05-decisions-*.md`). Несущие эрраты к фактам старых нот живут в шапке живого D-лога — их читать ОБЯЗАТЕЛЬНО, реестр их не дублирует. Темы (для грепа оси «какой закон по X»): деньги · шов · банк · промпт · судья · гейты · контракт · платформа · фронт · полигон · ToS · общность · процесс · нарезка · голос · инфра · модели.
|
||||
|
|
@ -217,3 +217,4 @@
|
|||
| D39.154 | 22.08 | Приёмка и лендинг P8-FIX платформы (фикс-лист приёмки P7 + врезанный первым блокер свипа): **ПРИНЯТ**; `PD-169` — единственная строка регистра, солгавшая ДВУМ приёмкам, — закрыт четырьмя механизмами (разделение прохода на фазы · отсрочка с бэкоффом на выбравший бюджет прогон · порог `StalledAfter` с гейджем и `runs --stalled` · терминальный вердикт оператора `run abandon`), оба числа стали ручками и `RunBudget` присвоен впервые; вся цепь пере-проверена ЖИВОЙ пробой оркестратора (`FAILS 6` → гейдж 1 → `--stalled` с настоящей ошибкой движка), деньги двумя путями из сырого леджера сошлись до цента и холд вернулся целиком; батарея 18 пакетов EXIT=0, линтер 0 issues, тестов 561 против 532; ⚠ «скипов 0» НЕ воспроизведён — третий, неназванный гейт батареи (менеджер systemd), `PD-374`; одиннадцать собственных посадок мутаций, убито восемь, выжили три и различены руками: `StalledAfter` законно (носитель один), `maxAttempts` — `PD-373` (второй носитель прозой в рантбуке), `truncateReason` в `DeferRun` — `PD-372` (пин на функции, ни один из четырёх вызовов не проверен); находка вне карты `PD-371` (исключение «стоп перевешивает отсрочку» без границы, измерено живьём); ⚠ объявлена ОШИБКА харнесса приёмки — две посадки дали ложное «выжила» из-за не того пакета; спил пер-термной подписи банка принят, пол поверхности 15→14 сдвинут явно и гейт СРАБОТАЛ; `PD-370` уезжает открытым мажором (контрактная половина — ломающий минор 0.4.0→0.5.0); порядок паков вышел ОБРАТНЫМ очереди — названная цена перестановки НЕ заплачена, зато §4.7 релея пуст | ЖИВОЕ: `PD-370`/`PD-371`/`PD-372`/`PD-373`/`PD-374`; строка 199(а) ждёт ратификации; читающий пак не запускался | жив | платформа приёмка свип деньги мутации |
|
||||
| D39.155 | 22.08 | Сквозная актуализация доков по многоагентному аудиту (14 линз + опровергатель на каждую находку, 180 агентов; 132 находки, 30 опровергнуто) + **передача роли №18 → №19**. Срезано: `PROGRESS.md` 471→291, зонный журнал платформы 897→239 (слайсы `PROGRESS-2026-08-17`, `-08-10-15`, `platform-PROGRESS-P8`); перед срезом вынесены носители — инвентарь каналов шва в `STACK_DECISIONS` (и там ПОЛНЕЕ: дописан канал текста `tmctl export --pairs`). Ложь, которую читала каждая сессия: `12-go-style-notes` §0 п.4 предписывал снятый ключ `prompts:`, на котором движок НЕ поднимется; таблица §3 компаньона объявляла не построенными шесть работающих поверхностей. Новые строки 206–210; **210 — род не производится авто-путём вовсе** (доставка построена, данных нет: терминолог возвращает три поля без рода, майнер берёт `gender` только из сида) + `gates.voice` нет ни в одном шиппинг-конфиге. ⚠ **СНЯТА ратификация 203(з)/191(б):** гейт движка проверяет полноту ФАЙЛА решений, а не подписей, один файл его снимает — конфликта с моделью «один ОК» нет, обход был костылём под отсутствующую доставку; единственный блокер темы — владение `book.yaml` (199а). Контрактный батч разделён по БЛОКЕРАМ: 0.5.0 гигиена сейчас, 0.6.0 ручка+прогресс после ратификаций. sqlc: гейт SQL съел бо́льшую часть ценности (162 оператора против 41), остаток — арность `Scan` на двух запросах. Названы пять собственных ошибок №18, все в ПРОЗЕ О ФАКТАХ | ЖИВОЕ: строки 199а · 206 · 208 · 210 · 172-г — на владельце; читающий пак платформы выдан и не запускался | жив | доки приёмка банк контракт передача-роли |
|
||||
| D39.156 | 23.08 | **Ратифицирован закон входной двери шва движок↔платформа** — дисциплина из семи пунктов (`17-seam-inbound-law.md`), не каталог команд: двери встают паками без нового решения владельца. Развилка 199(а) РАСТВОРЕНА (конвенционные дефолты путей + движковый глагол-писатель), три выноса по требованию ревьюера (форма Б · фикс-имена шва · отказ лока ровно классом 12), эррата к `research/25`. Заведены строки 211–213, закрыта слепота гейта якорей | жив | живой файл |
|
||||
| D39.157 | 24.08 | Переезд на новую машину: стенд пересобран без root (обе батареи EXIT=0 под `-race`, сквозняк живьём), носитель подъёма — `dev-stand.md`; корень книг переопределён на `<репозиторий>/books` со своим git, якорь `/books/` в игноре починен; цена переезда измерена (движок — 3 хелпера, строка 218; полигон — 104+86 файлов, строка 217); решения владельца: легаси выкидывать, а не чинить (санкция паку на удаление эксп-12–16), GPU на машине нет; маршрут холодного входа починен по СЛЕПОМУ замеру трёх ролей; класс «line-якорь в D-лог» закрыт (51 из 55 съехал), реестр перестал врать про 17 тел, гейт вооружён структурной сверкой и доказан мутацией; транспортный коммит `temp` снят по слову владельца | ЖИВОЕ: строки 217/218; очередь — CURRENT-STATE | жив | инфра процесс доки полигон бэкенд |
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Журнал решений оркестратора — контракт D1–D39.156 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
|
||||
# Журнал решений оркестратора — контракт D1–D39.157 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
|
||||
|
||||
> **⟶ КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Работая с контрактом (греп номера: живой файл → слайсы, целиком НЕ читать — D39.125), держи под рукой, что чем перекрыто:
|
||||
> ⚠ **Эррата 09.08 (D39.125):** D39.111 п.1 предписывал промту S3 «максимум = баланс МИНУС открытые холды» — формула ОШИБОЧНА (вычитание дважды), исправлена D39.115 п.2(а): максимум = Balance КАК ЕСТЬ; тело D39.111 живёт ниже в этом файле (голова D39.106+).
|
||||
|
|
@ -648,3 +648,19 @@
|
|||
**6. Порядок работ, вытекающий из нормы.** Движковый пак (конвенционные дефолты двух путей · глагол приёма правок банка · путь к файлу ключей аргументом · строгость сид-загрузчика) → контрактный минор ОДНИМ куском (снос отменённой пер-термной модели + новая дверь, тело которой выводится из словаря глагола, а не сочиняется до него) → платформенный пак (воркер решений · путь ключей из конфига · снятие дубля вывода пути · дев-супервизор на тот же механизм ключей). Гигиена контракта держится до этого сознательно: снести дверь сейчас и завести в следующем миноре — две перегенерации фронта вместо одной.
|
||||
|
||||
**7. Заведено тем же заходом:** строки **211** (движок на SaaS не получает провайдерских ключей — блокер живого прогона 202; дев-путь наследует окружение платформы, прод-путь нет, поэтому стенд зелёный, а прод голодает), **212** (нестрогий загрузчик сида), **213** (платформа дублирует движковую конвенцию пути). Оба пинга доставлены зонам. **Гейт якорей: закрыта его собственная слепота** — множество зонных префиксов было побайтно равно корневому, из-за чего сломанный зонно-относительный якорь тихо числился «внешней ссылкой»; починено и доказано мутацией. (23.08.2026, оркестратор №19) ✅
|
||||
|
||||
## D39.157 — ПЕРЕЕЗД НА НОВУЮ МАШИНУ: СТЕНД ПЕРЕСОБРАН, КОРЕНЬ КНИГ ПЕРЕОПРЕДЕЛЁН, МАРШРУТ ХОЛОДНОГО ВХОДА ПОЧИНЕН ПО СЛЕПОМУ ЗАМЕРУ (24.08, оркестратор №19). ✅
|
||||
|
||||
**1. Стенд.** Тулчейн на машине был нулевой. Носитель подъёма — [`../dev-stand.md`](../dev-stand.md); версий и рецептов зон он не дублирует, а называет их носитель и команду чтения. Root потребовали ровно два пакета (`build-essential` — `-race` требует cgo, снять его значило бы выдать отсутствие тулчейна за зелёный прогон; `python3-venv` — в системном питоне нет `ensurepip`), поставил владелец. Обе батареи прогнаны ЦЕЛИКОМ под `-race`: бэкенд `make battery` EXIT=0, платформа `make check` EXIT=0 при 18 пакетах и скипах 0. Сквозняк проверен живьём: демон → сид через настоящий интейк → движок распарсил книгу. Чего стенд НЕ проверяет — отдельный раздел там же (ни одного платного вызова · Playwright · GPU · OIDC).
|
||||
|
||||
**2. Корень книг — `<репозиторий>/books`, отдельный git.** Каталог перенесён владельцем внутрь дерева и версионируется своим репозиторием со своим origin; внешний держит `/books/` в `.gitignore`. Инвариант «книга и производные вне git» в силе — вне ЭТОГО git. Два следствия внесены в `CLAUDE.md`: `git status` внешнего репо правок книг не показывает, а `clean -xdf` снёс бы каталог с историей. ⚠ Правило игнора без якоря (`books/`) ловило ЛЮБОЙ каталог с этим именем, включая живой `platform/internal/books/`, — новый файл там уходил в игнор молча; заякорено в `/books/`, доказано пробой в обе стороны.
|
||||
|
||||
**3. Цена переезда измерена, не оценена.** Движок задет ТРЕМЯ тест-хелперами (дефолт `$HOME/books`), и переопределения в коде уже есть: с ними корпус-батарея зелена, красен только `TestMinerFullBookParity` из-за отсутствующего jieba (строка 123, к переезду отношения не имеет) — строка **218**. Полигон ломает не переезд книг, а переезд МАШИНЫ: `REPO = Path("/home/ubuntu/projects/textmachine")` одной дословной строкой в 104 файлах, плюс корень книг 163 строками в 86; живых носителей 30, включая рабочий гейт фазы Д — строка **217**. Все 20 `book.yaml` репозитория книг несут мёртвые пути по девяти ключам.
|
||||
|
||||
**4. Решения владельца 24.08.** (а) **Чинить всё; что легаси — выкидывать, а не поддерживать** («незачем копить техдолг») — это САНКЦИЯ полигонному паку на УДАЛЕНИЕ скриптов закрытых эксп-12–16 вместо их починки; довод, снимающий возражение о потере воспроизводимости: те прогоны шли на Ubuntu 24 / CPython ~3.12 с НЕИЗВЕСТНЫМИ версиями, и `eval/requirements.txt` сам объявляет их перепрогон НОВЫМ замером, а не репродукцией. (б) **GPU на машине нет**, локальную модель мерить нечем; ветка не закрыта — «в будущем может понадобиться».
|
||||
|
||||
**5. Онбординг замерен СЛЕПЫМ входом, а не мнением.** Три сессии без истории проекта прошли маршрут `CLAUDE.md` в ролях бэкенда, платформы и полигона. Сошлись на трёх дефектах, все починены: (а) холодная развилка не вела к таблице активных промтов — послушная сессия читала ~300 тыс. знаков и лишь потом узнавала, что её работа уже заказана; (б) шаг 2 требовал «живую голову» D-лога (33 ноты) вопреки правилу «целиком НЕ читать» в этом же файле — заменён на шапку + реестр + 2–3 последние; (в) пути шага 3 были написаны от `docs/` и от корня не резолвились — даны от корня, все 14 проверены. Структура маршрута здорова; ломался вход.
|
||||
|
||||
**6. Класс «line-якорь в D-лог» закрыт, гейт вооружён (строка 219 ЗАКРЫТА).** Замер по git-blame (для каждого якоря — версия лога на коммит, которым он написан): из 55 якорей живого корпуса съехал **51** — подрезки D39.125/D39.139 сдвинули нумерацию. Починены поштучно 24 якоря двух живых нормативных доков (`16-events-emitter` — обязательное пре-чтение перед кодом эмиттера — и `13-tech-debt-anchors`); тела `research/17` и `research/20` НЕ правились (D23.3, внешняя улика) — они получили пометку в шапке. Реестр нот врал про место тела у 17 нот подряд (D39.107–123 — «жив» при теле в слайсе); исправлено, пере-проверено скриптом: лжи 0. **Гейт `counts.py --lint` научен структурной сверке без токена** — владелец целевой строки обязан совпасть с номером, названным рядом. ⚠ **Первая редакция правила была молчащим no-op** (голые имена без `/` отсеивались до неё) и это поймала ПОСАДКА МУТАЦИИ, а не перечтение: урок ровно тот же, что D39.155 п.11.
|
||||
|
||||
**7. Транспортный коммит снят.** `temp` (`2f17752`), которым владелец перевозил дерево, снят по его слову `reset --mixed`: он уносил `START_PROMT.MD`, который канон коммитить запрещает. Дерево не тронуто — сверено побайтно по каждому из 20 файлов; страховка — бандл вне репо и reflog. Работа полигона снова НЕЗАКОММИЧЕНА, приёмка фазы за параллельным оркестратором. (24.08.2026, оркестратор №19) ✅
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
### [RESCOPE] Строка 81 — ja-преп B6-ja: Поливанов-валидатор + kana-омограф POS/known-word гейтинг (D17.1) + чек-лист kana-алиасов сида (D16.4)
|
||||
|
||||
Два компонента реально отсутствуют: (1) Поливанов-валидатор — backend/internal/store/migrate.go:186 «translit_policy … field only in v1; validator = Phase 2» и :194 «ruby_reading … bridge to Polivanov dst validation, B6 Phase 2 — NOT a dst»; grep polivanov/Поливанов по backend/*.go даёт только значения конфига в тестах/примерах и комментарий backend/internal/config/book.go:50 — валидирующего кода нет. (2) kana-омограф гейтинг — backend/internal/membank/memory.go:1048–1051: «KANA and HAN are deliberately NOT boundary-checked … their ≥4 precision is deferred to the kana-precision measurement + the B6 tokenizer»; подтверждено D-логом (05-decisions-log.md:214: митигация kana-омографов → «скоуп B6»). НО третий компонент УЖЕ ПОСТРОЕН: чек-лист kana-алиасов сида существует — backend/README.md:38 «## Подготовка ja-книги (чек-лист сида)» с пунктом «Kana-написания имён = matchable … внеси в aliases: руками — иначе „тихо пусто"», а сам механизм D16.4 (ruby-чтение → авто-алиас ручного термина с громким скипом омофонной коллизии) реализован: backend/internal/pipeline/seeding.go:43–50 (membank.AttachRubyAliasesToManual) — это ровно интерим-фикс из D16 п.4 (05-decisions-log.md:203).
|
||||
Два компонента реально отсутствуют: (1) Поливанов-валидатор — backend/internal/store/migrate.go:186 «translit_policy … field only in v1; validator = Phase 2» и :194 «ruby_reading … bridge to Polivanov dst validation, B6 Phase 2 — NOT a dst»; grep polivanov/Поливанов по backend/*.go даёт только значения конфига в тестах/примерах и комментарий backend/internal/config/book.go:50 — валидирующего кода нет. (2) kana-омограф гейтинг — backend/internal/membank/memory.go:1048–1051: «KANA and HAN are deliberately NOT boundary-checked … their ≥4 precision is deferred to the kana-precision measurement + the B6 tokenizer»; подтверждено D-логом (D17, тело — слайс `D1-D38`: митигация kana-омографов → «скоуп B6»). НО третий компонент УЖЕ ПОСТРОЕН: чек-лист kana-алиасов сида существует — backend/README.md:38 «## Подготовка ja-книги (чек-лист сида)» с пунктом «Kana-написания имён = matchable … внеси в aliases: руками — иначе „тихо пусто"», а сам механизм D16.4 (ruby-чтение → авто-алиас ручного термина с громким скипом омофонной коллизии) реализован: backend/internal/pipeline/seeding.go:43–50 (membank.AttachRubyAliasesToManual) — это ровно интерим-фикс из D16 п.4.
|
||||
|
||||
**Фикс/скоуп:** Сузить строку 81 до двух реально отложенных работ: «Поливанов-валидатор (translit_policy Phase 2, store/migrate.go:186/194) + kana-омограф POS/known-word гейтинг / B6-токенизатор (memory.go:1048)»; компонент «чек-лист kana-алиасов сида (D16.4)» пометить built (backend/README.md:38 + seeding.go:47) — в чек-листе остаётся лишь Ф2-хвост «двойные чтения (強敵→とも) полная дизамбигуация», который и так под B6.
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ grep -rni 'VACUUM|integrity_check|backup' по backend/cmd/tmctl/ и backend/int
|
|||
|
||||
### [CONFIRMED_LOST] Строка 85 — пилот-преп добор: Bertalign GOLD-пары (D29.2в) · R2 shadow (D25.2) · exp08 v3 (D21.8)
|
||||
|
||||
Bertalign: grep -rni bertalign по eval/ и backend/ — 0 вхождений (нет ни кода, ни данных). exp08 v3: в docs/experiments/ существует только 08-cost-model-v2.md; его шапка (строка 3) прямо говорит «Пере-съём заказан как exp08 v3 (D21.8 … D25.8 …)» — т.е. заказан, не исполнен; в eval/ есть только cost_model_v2.py (v3-скрипта нет). Подтверждается и D-логом: 05-decisions-log.md:261 «→ exp08 v3 … до фиксации budget_usd-дефолтов Ф2» — висящее поручение, и 02-mvp-plan.md:34 «пере-съём exp08 v3» как открытый.
|
||||
Bertalign: grep -rni bertalign по eval/ и backend/ — 0 вхождений (нет ни кода, ни данных). exp08 v3: в docs/experiments/ существует только 08-cost-model-v2.md; его шапка (строка 3) прямо говорит «Пере-съём заказан как exp08 v3 (D21.8 … D25.8 …)» — т.е. заказан, не исполнен; в eval/ есть только cost_model_v2.py (v3-скрипта нет). Подтверждается и D-логом (D21): «→ exp08 v3 … до фиксации budget_usd-дефолтов Ф2» — висящее поручение, и 02-mvp-plan.md:34 «пере-съём exp08 v3» как открытый.
|
||||
|
||||
**Фикс/скоуп:** Не требуется — занесено правильно (пилот-преп-промт, Ф2.5); дельта уже вписана в docs/POLYGON_PACKAGE4_SESSION_PROMPT.md:4.
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ backend/internal/lang/langpack.go:824 (parseCategoryRows): `cats[f[0]][f[1]] = v
|
|||
|
||||
### [CONFIRMED_LOST] Дописка к строке 11 — судьба v1.1 quote-absorption при флипе coverage-гейта (D12-Q1)
|
||||
|
||||
Go-гейт стоит на v1 без поглощения кавычек: backend/internal/checks/coverage.go:39 `CoverageGateVersion = "coverage-v1-naive-split-lower-bound"`; grep quote/кавыч/absor/поглощ по coverage.go — 0 вхождений. Python-оракул тоже: eval/refusal_bench.py split_sentences (строка 81) без absorption-логики (grep absorb/quote — 0 содержательных попаданий). Дефер задокументирован в обе стороны: eval/coverage_precision.py:14–16 «naive sentence segmentation can undercount RU sentences vs a CJK source (quote-absorbing §3.7 is deferred to v1.1)» и D-лог 05-decisions-log.md:20 (D12 Q1) «§3.7 „поглощение кавычек" → v1.1 (координированно)». Гейт при этом выключен (шапка coverage.go: «opt-in (gates.coverage.enabled)») — решение о судьбе v1.1 реально висит на флипе.
|
||||
Go-гейт стоит на v1 без поглощения кавычек: backend/internal/checks/coverage.go:39 `CoverageGateVersion = "coverage-v1-naive-split-lower-bound"`; grep quote/кавыч/absor/поглощ по coverage.go — 0 вхождений. Python-оракул тоже: eval/refusal_bench.py split_sentences (строка 81) без absorption-логики (grep absorb/quote — 0 содержательных попаданий). Дефер задокументирован в обе стороны: eval/coverage_precision.py:14–16 «naive sentence segmentation can undercount RU sentences vs a CJK source (quote-absorbing §3.7 is deferred to v1.1)» и D-лог (D12 Q1) «§3.7 „поглощение кавычек" → v1.1 (координированно)». Гейт при этом выключен (шапка coverage.go: «opt-in (gates.coverage.enabled)») — решение о судьбе v1.1 реально висит на флипе.
|
||||
|
||||
**Фикс/скоуп:** Не требуется — занесено правильно (решение владельца при флипе, Python-first лок-степ).
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ Go-гейт стоит на v1 без поглощения кавычек: backe
|
|||
|
||||
grep sanitiz по backend/configs/pipeline-c2.yaml — 0 вхождений (exit 1), при том что секцию `sanitizer:` несут pipeline-c1.yaml:87 и все три arm-конфига (pipeline-arm-mistral.yaml:47, pipeline-arm-glm.yaml:50, pipeline-arm-deepseek-pro.yaml:51). C2 — спящий скелет (pipeline-c2.yaml:1–4: «Фаза 0 фиксирует СХЕМУ … исполнение fan-out/селекции — механика раннера Фазы 2»), поэтому отсутствие сейчас безвредно, но при оживлении C2 без правки конфига финал пойдёт без санитайзера — строка корректно держит это как условие оживления. Нюанс цитаты: «D33.4б» как секции в 05-decisions-log.md нет (есть D33/D33.1, строки 409/422; нотация D33.4a встречается в research/18-quality-levers.md:213) — на вердикт не влияет.
|
||||
|
||||
**Фикс/скоуп:** Не требуется по существу; опционально при док-пассе поправить ссылку «D33.4б» на фактический носитель решения (серия D33.x в теле D33, 05-decisions-log.md:409+).
|
||||
**Фикс/скоуп:** Не требуется по существу; опционально при док-пассе поправить ссылку «D33.4б» на фактический носитель решения (серия D33.x в теле D33).
|
||||
|
||||
**Сводка среза:** Срез 81/83/85 + дописки 11/33/53/59 D39.66: 6 из 7 пунктов CONFIRMED_LOST — занесены правильно и живы. F4-бэкап (83): 0 вхождений VACUUM/integrity_check/backup во всём backend/, tmctl без такой подкоманды (main.go:73-83). Bertalign+exp08 v3 (85): bertalign 0 вхождений в eval/ и backend/, v3 «заказан» шапкой 08-cost-model-v2.md:3 и не исполнен. GLM-overflow (59): finish проходит RAW (provider_openai.go:166-171, тест «deferred GLM-overflow item»), classify() без ветки — пустой выход = ложно-retryable FlagEmpty, непустой = ложный OK. Внутрифайловый дубль (53): langpack.go:824 молчаливый last-wins, громкость только base↔overlay (langpack.go:466-474), открытость подтверждена PACK15-отчётом:274. Quote-absorption (11): coverage.go:39 = v1-naive, оба слоя (Go+refusal_bench.py) без поглощения, дефер в v1.1 задокументирован. Sanitizer в c2 (33): 0 вхождений в pipeline-c2.yaml при наличии в c1:87 и трёх arm-конфигах. ЕДИНСТВЕННЫЙ RESCOPE — строка 81: Поливанов-валидатор (migrate.go:186/194 «Phase 2») и kana-омограф гейтинг (memory.go:1048-1051 deferred) реально отсутствуют, но третий компонент «чек-лист kana-алиасов сида (D16.4)» уже построен — чек-лист написан (backend/README.md:38) и механизм авто-алиасов реализован (seeding.go:43-50, AttachRubyAliasesToManual); строку сузить до валидатора+гейтинга.
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ grep sanitiz по backend/configs/pipeline-c2.yaml — 0 вхождений (exi
|
|||
|
||||
### [CONFIRMED_LOST] Строка 80: резюме-слой памяти (глава→арка→книга) + fact-gate
|
||||
|
||||
В backend/internal/ резюме-механизма НЕТ: grep summary/резюме даёт только несвязанное — RedriveSummary (pipeline/status.go:592-593, план redrive), SanitizerResult.Summary() (checks/sanitizer.go:165-167, текст флага), детектор ХВОСТОВОГО edit-summary модели (sanitizer.go:90), коммент-плейсхолдер «approved-glossary+summary+series-bible» в pipeline/snapshot.go:391 при том, что memoryVersion() материализует ТОЛЬКО frozen APPROVED glossary rows (snapshot.go:179-189); в схеме store/migrate.go нет таблицы/колонки резюме (строка 18 — лишь коммент о payload снапшота). Не закрыт решением: 05-decisions-log.md:373 (D30.8 п.8) — «слой авто-памяти/состояния (Annotator, межглавные резюме…) — Ф2, связка с пилотом Ф2.5 зафиксирована» — отложено, не отменено; в списке «ЗАКРЫТО ЯВНО» D39.66 его нет.
|
||||
В backend/internal/ резюме-механизма НЕТ: grep summary/резюме даёт только несвязанное — RedriveSummary (pipeline/status.go:592-593, план redrive), SanitizerResult.Summary() (checks/sanitizer.go:165-167, текст флага), детектор ХВОСТОВОГО edit-summary модели (sanitizer.go:90), коммент-плейсхолдер «approved-glossary+summary+series-bible» в pipeline/snapshot.go:391 при том, что memoryVersion() материализует ТОЛЬКО frozen APPROVED glossary rows (snapshot.go:179-189); в схеме store/migrate.go нет таблицы/колонки резюме (строка 18 — лишь коммент о payload снапшота). Не закрыт решением (D30.8 п.8): «слой авто-памяти/состояния (Annotator, межглавные резюме…) — Ф2, связка с пилотом Ф2.5 зафиксирована» — отложено, не отменено; в списке «ЗАКРЫТО ЯВНО» D39.66 его нет.
|
||||
|
||||
**Фикс/скоуп:** → **Диспозиция ДАНА D39.69: закрыт по нужности; строка 80 = гейт пилота Ф2.5.** (Историческая формулировка: дизайн-пак 73 обязан дать диспозицию «строить в Ф2.5 или закрыть с обоснованием».)
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ grep sanitiz по backend/configs/pipeline-c2.yaml — 0 вхождений (exi
|
|||
|
||||
### [CONFIRMED_LOST] Строка 84: канон D39.21 «generic „гу" = средний род» без носителя
|
||||
|
||||
Канон ратифицирован (05-decisions-log.md:7, карта: «D39.21 = … generic-«гу» СРЕДНИЙ род, именные — по-термово из банка»), ⚠ **ПЕРЕ-СВЕРЕНО 23.08 (№19): ЧЕТЫРЕ пункта из пяти ПРОТУХЛИ — носитель в коде ПОСТРОЕН.** Было «носителя в коде НЕТ». Стало, по фактам: (1) `genderConstraintNote` принимает `neuter`/`n` и отдаёт `tx.GenderNeuter` (`backend/internal/membank/memory.go:842-850`=`case "neuter", "n":`) — прежний якорь `:815-823` съехал; (2) ключ пары ЕСТЬ — `GenderNeuter` в структуре и в разборе (`backend/internal/lang/embedded.go:398`=`GenderNeuter string`, `:456`=`case "gender_neuter":`); (4) `neuter` встречается в `lang/embedded.go`, `lang/data/injection.txt`, `membank/memory.go` и двух тестах — грепа «0 хитов» больше нет; (5) род ВАЛИДИРУЕТСЯ: `knownGenders` включает `neuter`/`n`, а `GenderVocabViolations` ловит выход из словаря, и её собственный докстринг называет этот класс (`backend/internal/membank/memseed.go:503-513`=`var knownGenders = map[string]bool{`). **ЖИВЫМ ОСТАЁТСЯ РОВНО ПУНКТ (3):** комментарий схемы БД до сих пор перечисляет `male|female|hidden|''` без neuter (`backend/internal/store/migrate.go:184`=`male|female|hidden|`) — и прежний якорь звал `:183`, то есть был на строку мимо. Это косметика комментария, не поведение. Альтернативный носитель decl.Invariant существует (memory.go:128,151,311; seed.go:85), но несёт лишь несклоняемость формы, не род для согласования глагола/прилагательных.
|
||||
Канон ратифицирован (D39.21; ⚠ прежний якорь вёл в строку карты шапки, которой в живом логе БОЛЬШЕ НЕТ — проверено грепом 24.08: «D39.21 = … generic-«гу» СРЕДНИЙ род, именные — по-термово из банка»), ⚠ **ПЕРЕ-СВЕРЕНО 23.08 (№19): ЧЕТЫРЕ пункта из пяти ПРОТУХЛИ — носитель в коде ПОСТРОЕН.** Было «носителя в коде НЕТ». Стало, по фактам: (1) `genderConstraintNote` принимает `neuter`/`n` и отдаёт `tx.GenderNeuter` (`backend/internal/membank/memory.go:842-850`=`case "neuter", "n":`) — прежний якорь `:815-823` съехал; (2) ключ пары ЕСТЬ — `GenderNeuter` в структуре и в разборе (`backend/internal/lang/embedded.go:398`=`GenderNeuter string`, `:456`=`case "gender_neuter":`); (4) `neuter` встречается в `lang/embedded.go`, `lang/data/injection.txt`, `membank/memory.go` и двух тестах — грепа «0 хитов» больше нет; (5) род ВАЛИДИРУЕТСЯ: `knownGenders` включает `neuter`/`n`, а `GenderVocabViolations` ловит выход из словаря, и её собственный докстринг называет этот класс (`backend/internal/membank/memseed.go:503-513`=`var knownGenders = map[string]bool{`). **ЖИВЫМ ОСТАЁТСЯ РОВНО ПУНКТ (3):** комментарий схемы БД до сих пор перечисляет `male|female|hidden|''` без neuter (`backend/internal/store/migrate.go:184`=`male|female|hidden|`) — и прежний якорь звал `:183`, то есть был на строку мимо. Это косметика комментария, не поведение. Альтернативный носитель decl.Invariant существует (memory.go:128,151,311; seed.go:85), но несёт лишь несклоняемость формы, не род для согласования глагола/прилагательных.
|
||||
|
||||
**Фикс/скоуп:** Строка верна; уточнение в тело: (а) сегодня `gender: neuter` в сиде — ТИХИЙ no-op без линта, т.е. дыра хуже «невыразимо» — при стройке носителя добавить и seed-lint-отбраковку неизвестных значений рода; (б) «decl.invariant достаточно» закрывает только несклоняемость, не согласование — фиксировать это в формулировке альтернативы.
|
||||
|
||||
|
|
@ -165,13 +165,13 @@ backend/prompts/zh-ru/editor.md:6 — «Правь стиль: убирай ка
|
|||
|
||||
### [CONFIRMED_LOST] (1) Echo-семантика дропнутого c-lite-члена (строка 86, D39.18): код сохраняет pre-c-lite семантику «эхо где угодно, вкл. дропнутых членов»
|
||||
|
||||
Код реально реализует pre-c-lite семантику, альтернатива не построена. backend/internal/pipeline/quality.go:216-218: «echo_draft is counted DIRECTLY from the draft rows (no c-lite per-unit re-derivation — a dropped member's own draft row already carries cjk_artifact)»; quality.go:295-318: draftEcho считается по ВСЕМ draft-stage рядам (FlagReason/FirstFlagReason == cjk_artifact), без фильтра по member-drop — т.е. эхо дропнутого c-lite-члена ВХОДИТ в метрику; backend/cmd/tmctl/render.go:308: «draft = the translator echoed (incl. dropped c-lite members)». Альтернативный путь «echo только в шипнутом тексте» в коде ОТСУТСТВУЕТ (в quality.go нет ветки, исключающей дропнутые члены из draftEcho). D-лог: 05-decisions-log.md:583 (D39.18) — «ОТКРЫТОЕ решение владельцу: сохранена pre-c-lite семантика…; альтернатива — one-line, за владельцем»; D39.66 (строка 1209) повторно числит его открытым. Решения после D39.18 не найдено (grep по голове D39.x).
|
||||
Код реально реализует pre-c-lite семантику, альтернатива не построена. backend/internal/pipeline/quality.go:216-218: «echo_draft is counted DIRECTLY from the draft rows (no c-lite per-unit re-derivation — a dropped member's own draft row already carries cjk_artifact)»; quality.go:295-318: draftEcho считается по ВСЕМ draft-stage рядам (FlagReason/FirstFlagReason == cjk_artifact), без фильтра по member-drop — т.е. эхо дропнутого c-lite-члена ВХОДИТ в метрику; backend/cmd/tmctl/render.go:308: «draft = the translator echoed (incl. dropped c-lite members)». Альтернативный путь «echo только в шипнутом тексте» в коде ОТСУТСТВУЕТ (в quality.go нет ветки, исключающей дропнутые члены из draftEcho). D-лог (D39.18): «ОТКРЫТОЕ решение владельцу: сохранена pre-c-lite семантика…; альтернатива — one-line, за владельцем»; D39.66 (строка 1209) повторно числит его открытым. Решения после D39.18 не найдено (grep по голове D39.x).
|
||||
|
||||
**Фикс/скоуп:** Не требуется — строка 86 точна: решение реально отложено и живо, код в заявленном состоянии.
|
||||
|
||||
### [CONFIRMED_LOST] (2) Magnitude-кап тяжёлой CJK-утечки (строка 86, D38.3 п.4в): сейчас только strip+flag, капа >X%→drop нет
|
||||
|
||||
Капа в коде нет. backend/internal/checks/sanitizer.go:770 StripCosmetic — косметический стрип; backend/internal/pipeline/disposition.go:96-104 FlagSanitizerStripped — «cleaned, exported flagged, NOT dropped». detectCJKLeak (sanitizer.go:636) вообще не считает долю утечки — только собирает раны. Единственные share-пороги: disposition.go:275 cjkEchoThreshold=0.15 (это класс ЭХА → FlagCJKArtifact, не кап под-эховой утечки) и sanitizer.go:137 latinHeavyShare=0.25 (Latin-класс, не CJK). Промежуточного порога «CJK-доля >X% (X<15) → drop» нет нигде в checks/ и disposition.go. D-лог: 05-decisions-log.md:530 (D38.3 п.4в): «альтернатива magnitude-кап (>X%→drop) НЕ реализована — нужен ли кап, за владельцем»; D39.66 повторно числит открытым.
|
||||
Капа в коде нет. backend/internal/checks/sanitizer.go:770 StripCosmetic — косметический стрип; backend/internal/pipeline/disposition.go:96-104 FlagSanitizerStripped — «cleaned, exported flagged, NOT dropped». detectCJKLeak (sanitizer.go:636) вообще не считает долю утечки — только собирает раны. Единственные share-пороги: disposition.go:275 cjkEchoThreshold=0.15 (это класс ЭХА → FlagCJKArtifact, не кап под-эховой утечки) и sanitizer.go:137 latinHeavyShare=0.25 (Latin-класс, не CJK). Промежуточного порога «CJK-доля >X% (X<15) → drop» нет нигде в checks/ и disposition.go. D-лог (D38.3 п.4в): «альтернатива magnitude-кап (>X%→drop) НЕ реализована — нужен ли кап, за владельцем»; D39.66 повторно числит открытым.
|
||||
|
||||
**Фикс/скоуп:** Не требуется — строка 86 точна.
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ backend/prompts/zh-ru/editor.md:6 — «Правь стиль: убирай ка
|
|||
|
||||
### [CONFIRMED_LOST] (5) Слот инъекции голоса (дописка 24): инъекционная половина построена условно и НЕ включена, оба провода
|
||||
|
||||
Оба провода подтверждены. Провод 1 (инъекция): половина построена в membank УСЛОВНЫМ фолдом — backend/internal/membank/memory.go:248-252 (`InjectVoice reports whether the voice/address rows reach the WIRE... It is the CONDITION`), 370-377 («A book with no voice rows, or a run with the injection off, hashes BYTE-IDENTICALLY»), 448-465 (фолд под `if !in.InjectVoice`); но pipeline захардкоживает выключенность: backend/internal/pipeline/seeding.go:130-133 — «InjectVoice is FALSE and has no config knob: pack-19 builds the schema and the flagger, and D21 п.2 holds the injection conditional until the polygon experiment... Wiring the injection means setting it and accepting a full --resnapshot». Провод 2 (флаггер): гейтится Gates.Voice.Enabled, opt-in OFF (backend/internal/pipeline/voicerun.go:46; config/pipeline.go:264-281). Совпадает с D39.55 (05-decisions-log.md:1177): «слот инъекции НЕ выбран, оба провода, решит полигон-эксперимент».
|
||||
Оба провода подтверждены. Провод 1 (инъекция): половина построена в membank УСЛОВНЫМ фолдом — backend/internal/membank/memory.go:248-252 (`InjectVoice reports whether the voice/address rows reach the WIRE... It is the CONDITION`), 370-377 («A book with no voice rows, or a run with the injection off, hashes BYTE-IDENTICALLY»), 448-465 (фолд под `if !in.InjectVoice`); но pipeline захардкоживает выключенность: backend/internal/pipeline/seeding.go:130-133 — «InjectVoice is FALSE and has no config knob: pack-19 builds the schema and the flagger, and D21 п.2 holds the injection conditional until the polygon experiment... Wiring the injection means setting it and accepting a full --resnapshot». Провод 2 (флаггер): гейтится Gates.Voice.Enabled, opt-in OFF (backend/internal/pipeline/voicerun.go:46; config/pipeline.go:264-281). Совпадает с D39.55: «слот инъекции НЕ выбран, оба провода, решит полигон-эксперимент».
|
||||
|
||||
**Фикс/скоуп:** Не требуется — дописка 24 точна (решение по gates.voice и инъекции — на следующем живом прогоне).
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ backend/prompts/zh-ru/editor.md:6 — «Правь стиль: убирай ка
|
|||
|
||||
### [RESCOPE] (7) Протокол гендер-твиста D5.1 (дописка 49): «redrive есть, селективного by-until_ch пути нет»
|
||||
|
||||
Посылка «селективного пути нет» ОПРОВЕРГНУТА: селективная пере-редактура по изменению банка + смета ПОСТРОЕНЫ и живьём проверены. backend/internal/pipeline/repin.go:14-35 — «POINTWISE re-edit by key (pack-20 point 5, D39.42 п.5)»: bank-only сдвиг снапшота + неизменный content_hash → пере-пин юнита за $0, изменённые инъекции — платно; «The same predicate drives the ESTIMATE: projectRebill uses it» (смета «N units, ~$X»); встроено в штатный резюм — stagerun.go:87 (repinnable); согласие на пере-оплату — rebill.go:11-40 (D20.2-Q2). until_ch-апдейт = правка строки банка → двигается ТОЛЬКО memory_version → ровно этот путь (D39.42 п.5: «поздняя подпись и ЛЮБАЯ правка», 05-decisions-log.md:1089; D39.45, :1113-1115: «точечная ре-редактура по ключу с $0-пере-пином — построено, живьём проверено... 20 юнитов пере-пинены за $0 при bank-only-сдвиге»). При этом верно: tmctl redrive существует (cmd/tmctl/main.go:81-82, 214), но его селектор — только chapter/chunk/reason по ФЛАГНУТЫМ чанкам (status.go:564-582), until_ch-пути в НЁМ нет — селективность живёт в другом инструменте (translate-резюм + repin + rebill), и это by-design правильный носитель.
|
||||
Посылка «селективного пути нет» ОПРОВЕРГНУТА: селективная пере-редактура по изменению банка + смета ПОСТРОЕНЫ и живьём проверены. backend/internal/pipeline/repin.go:14-35 — «POINTWISE re-edit by key (pack-20 point 5, D39.42 п.5)»: bank-only сдвиг снапшота + неизменный content_hash → пере-пин юнита за $0, изменённые инъекции — платно; «The same predicate drives the ESTIMATE: projectRebill uses it» (смета «N units, ~$X»); встроено в штатный резюм — stagerun.go:87 (repinnable); согласие на пере-оплату — rebill.go:11-40 (D20.2-Q2). until_ch-апдейт = правка строки банка → двигается ТОЛЬКО memory_version → ровно этот путь (D39.42 п.5: «поздняя подпись и ЛЮБАЯ правка»; D39.45: «точечная ре-редактура по ключу с $0-пере-пином — построено, живьём проверено... 20 юнитов пере-пинены за $0 при bank-only-сдвиге»). При этом верно: tmctl redrive существует (cmd/tmctl/main.go:81-82, 214), но его селектор — только chapter/chunk/reason по ФЛАГНУТЫМ чанкам (status.go:564-582), until_ch-пути в НЁМ нет — селективность живёт в другом инструменте (translate-резюм + repin + rebill), и это by-design правильный носитель.
|
||||
|
||||
**Фикс/скоуп:** Пере-формулировать дописку в строке 49: тех-механизм «until_ch-апдейт → селективная пере-оплата затронутых юнитов + смета» УЖЕ построен (repin.go/rebill.go, D39.42 п.5, D39.45) — слова «селективный redrive» убрать (redrive — инструмент флагнутых чанков, не носитель). Остаток дописки — только операторский ПРОТОКОЛ-документ релиза D5.1 (последовательность: выставить until_ch у gender=hidden-терма → tmctl translate → согласие на rebill-смету; + курация 白凝冰 из строки 24), либо закрыть дописку явной ссылкой на D39.45.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,15 +12,15 @@
|
|||
|
||||
> «**NDJSON-эмиттер прогонных событий со стабильным словарём** (машинный канал живого статуса для платформы, `research/23` §2): NDJSON-логи уже есть (`LOG_FORMAT=json`, авто-оси trace/book/chapter/stage/role — `obs/logging.go:15-54`), но сообщения прозой, version-хендшейка нет, а **событие потолка отсутствует вовсе** (деньги только в тексте ошибки `stagerun.go:472-494`); нужен словарь-enum + version-хендшейк первой строкой (образец terraform -json: минор = ignore-unknown, мажор = reject) + событие потолка; все границы — единичные call-sites в pipeline рядом с готовыми slog; человеческие логи уже на stderr — stdout-дисциплина соблюдена. **Форма ратифицирована D39.106 (research/25 §эмиттер):** `events.jsonl` каталога книги = outbox-проекция коммитов SQLite (та же транзакция, что чекпойнт) · fsync/seq/hello-версия · события денег и потолка · развилка формата (JSONL против пофайловых/CRC-фрейминга) — решить дизайном · `status --json` отдельным каналом (ремонт, тот же flock)».
|
||||
|
||||
**Зачем (две ноги).** (а) *Свежесть статуса*: по слову владельца 08.08 «эмиттер нужен СВЕЖЕСТИ статуса и деньгам шва, не первым экранам — резерв на это время = периодический `status --json`-резюнк (построен в P1)» (D39.119 п.1, `05-decisions-log.md:390`). (б) *Деньги шва*: пока события нет, «экран покажет „ошибка“ там, где верно „остановлено: лимиты“» (PD-113, `DEFECT_REGISTER.md:18`), причём после PD-158 «PD-113 остаётся ЕДИНСТВЕННЫМ открытым major до эмиттера; … консервативный потолок останавливает ровно на исчерпании холда, и „деньги кончились“ неотличимо от „инфраструктура упала“» (D39.123 п.2(ж), `05-decisions-log.md:428`).
|
||||
**Зачем (две ноги).** (а) *Свежесть статуса*: по слову владельца 08.08 «эмиттер нужен СВЕЖЕСТИ статуса и деньгам шва, не первым экранам — резерв на это время = периодический `status --json`-резюнк (построен в P1)» (D39.119 п.1). (б) *Деньги шва*: пока события нет, «экран покажет „ошибка“ там, где верно „остановлено: лимиты“» (PD-113, `DEFECT_REGISTER.md:18`), причём после PD-158 «PD-113 остаётся ЕДИНСТВЕННЫМ открытым major до эмиттера; … консервативный потолок останавливает ровно на исчерпании холда, и „деньги кончились“ неотличимо от „инфраструктура упала“» (D39.123 п.2(ж)).
|
||||
|
||||
**Что уже есть со стороны движка.** NDJSON-инфраструктура логов: `obs.NewLogger` пишет slog в **stderr**, `LOG_FORMAT=json` даёт JSONHandler, UTC-время (`backend/internal/obs/logging.go:15-31`); оси trace_id/book/chapter/chunk/stage/role навешиваются из контекста автоматически (`logging.go:41-54`). Деньги при стопе по потолку существуют только в тексте ошибки: `" (committed=$%.6f reserved=$%.6f, denied estimate=$%.6f, ch%d/chunk%d/%s)"` и `"pipeline: book USD ceiling reached ($%g)%s — %s or stop: %w"` / `"pipeline: daily USD ceiling reached ($%g)%s: %w"` с сентинелом `errReserveCeiling` (`backend/internal/pipeline/stagerun.go:489-513`, сентинел — `escalation.go:49`). Trace id чеканится на каждый вызов в `cmd/tmctl/main.go:67-70` — это сегодняшний кандидат в `engine_run_id` (так и записано платформой, `platform/internal/ingest/events.go:75`).
|
||||
|
||||
**Что эмиттер НЕ решает** (не тащить в пак): реконсилятор и свип — построены платформой, строки 138·139 закрыты (D39.123 п.3, `05-decisions-log.md:430`) · write-ahead intent / `uncertain`-эскроу / `closing` — отдельная строка 136 (`docs/PROGRESS.md:85`) · пиннинг версии бинаря на прогон — «исполняется и резюмом — PD-143/134 закрыты» (D39.123 п.3) · движковая оценка $/глава — строка 166 (`docs/PROGRESS.md:114`) · тейлер/декодер платформы — уже построены (пакет `platform/internal/ingest/`), эмиттер пишет ПОД их контракт.
|
||||
**Что эмиттер НЕ решает** (не тащить в пак): реконсилятор и свип — построены платформой, строки 138·139 закрыты (D39.123 п.3) · write-ahead intent / `uncertain`-эскроу / `closing` — отдельная строка 136 (`docs/PROGRESS.md:85`) · пиннинг версии бинаря на прогон — «исполняется и резюмом — PD-143/134 закрыты» (D39.123 п.3) · движковая оценка $/глава — строка 166 (`docs/PROGRESS.md:114`) · тейлер/декодер платформы — уже построены (пакет `platform/internal/ingest/`), эмиттер пишет ПОД их контракт.
|
||||
|
||||
## 2. Ратифицированная форма (D39.106 · research/25)
|
||||
|
||||
Канон — D39.106 п.2 (`05-decisions-log.md:228`), дословно:
|
||||
Канон — D39.106 п.2, дословно:
|
||||
|
||||
> «**2. Форма (заменяет ТРАНСПОРТ D39.85 §1; остальное D39.85 в силе):** движок = транзиентный systemd-юнит на прогон (`Restart=no`, SIGTERM); события = `events.jsonl` каталога книги как проекция коммитов SQLite движка (outbox, та же транзакция, что чекпойнт); платформа тейлит, курсор `(engine_run_id, seq)` коммитится с эффектом в одной Postgres-транзакции; `status --json` — ремонт по остановленному прогону. Формат NDJSON/hello/seq, деньги (холд+потолок = защита, события = свежесть, D39.84/D39.100) и запрет на живой SQLite — без изменений.»
|
||||
|
||||
|
|
@ -33,17 +33,17 @@
|
|||
- **Сброс буфера на всех путях выхода**: «сброс буфера на всех путях выхода (`os.Exit` пропускает defer — теряются финальные события)» (`25:82`); то же PD-61(а) — см. §4.
|
||||
- **Живость**: «живость = растущий `seq`, не удерживаемый лок; политика обратного давления выбирается явно» (`25:83`).
|
||||
|
||||
**Отвергнутые альтернативы** (`25:33-44`; повторены в доккомменте зоны, «so that none of them comes back as a fresh idea» — `events.go:21-23`): платформа-родитель + пайп stdout/fd — **0 из 15** («время жизни движка — подмножество платформы: деплой/рестарт убивает или осиротляет прогон», `25:38`) · выделенный fd 3 — **0** (`25:43`) · stdout/journald как источник событий — **0** («journald молча роняет под всплеском и ротирует сам; людям — да, контракту — нет», `25:44`) · gRPC/HTTP поверх движка — 0 (`25:39`) · push в платформу — 2→0 (`25:40`) · брокер — 0 (`25:41`) · монолит — 0 из ~18 (`25:37`). Пайп-путь `supervisor.go` — ДЕВ-режим и только (D39.106 п.3 `05-decisions-log.md:230`; `events.go:23`).
|
||||
**Отвергнутые альтернативы** (`25:33-44`; повторены в доккомменте зоны, «so that none of them comes back as a fresh idea» — `events.go:21-23`): платформа-родитель + пайп stdout/fd — **0 из 15** («время жизни движка — подмножество платформы: деплой/рестарт убивает или осиротляет прогон», `25:38`) · выделенный fd 3 — **0** (`25:43`) · stdout/journald как источник событий — **0** («journald молча роняет под всплеском и ротирует сам; людям — да, контракту — нет», `25:44`) · gRPC/HTTP поверх движка — 0 (`25:39`) · push в платформу — 2→0 (`25:40`) · брокер — 0 (`25:41`) · монолит — 0 из ~18 (`25:37`). Пайп-путь `supervisor.go` — ДЕВ-режим и только (D39.106 п.3; `events.go:23`).
|
||||
|
||||
**Словарь событий — ПРЕДЛОЖЕНИЕ платформы, записанное кодом**: «The vocabulary below is therefore the platform's PROPOSAL, written as code so the engine zone can answer it with a diff» (`events.go:5-6`). Состав (`events.go:37-147`): `StreamVersion = "1.0"` · типы `hello` / `progress` / `unit_done` / `bank_stop` / `ceiling` / `spend` / `finished` · конверт `{seq, type, time, data}` · `Hello{stream_version, engine_run_id, book_id, chunker_version}` · `Progress` — пофазные счётчики draft/edit + `eta_seconds` (семантика `done` = «разрешено волной», ok/flagged/skipped — D39.122 п.2(б), `05-decisions-log.md:416`) · `UnitDone{chapter, unit, wave, shipped, flagged, reason}` · `BankStop{terms_proposed}` (полная таблица — артефактом, не потоком: `events.go:117-118`) · `Ceiling{halted}` · `Spend{committed_micro_usd}` · `Finished{outcome: clean|flagged|bank_stop|failed}`.
|
||||
**Словарь событий — ПРЕДЛОЖЕНИЕ платформы, записанное кодом**: «The vocabulary below is therefore the platform's PROPOSAL, written as code so the engine zone can answer it with a diff» (`events.go:5-6`). Состав (`events.go:37-147`): `StreamVersion = "1.0"` · типы `hello` / `progress` / `unit_done` / `bank_stop` / `ceiling` / `spend` / `finished` · конверт `{seq, type, time, data}` · `Hello{stream_version, engine_run_id, book_id, chunker_version}` · `Progress` — пофазные счётчики draft/edit + `eta_seconds` (семантика `done` = «разрешено волной», ok/flagged/skipped — D39.122 п.2(б)) · `UnitDone{chapter, unit, wave, shipped, flagged, reason}` · `BankStop{terms_proposed}` (полная таблица — артефактом, не потоком: `events.go:117-118`) · `Ceiling{halted}` · `Spend{committed_micro_usd}` · `Finished{outcome: clean|flagged|bank_stop|failed}`.
|
||||
|
||||
## 3. Контракт декодера и дублей (PD-105 · D39.123 п.2(в))
|
||||
|
||||
Ратификация — D39.119 п.3 (`05-decisions-log.md:394`), дословно:
|
||||
Ратификация — D39.119 п.3, дословно:
|
||||
|
||||
> «доставка событий шва = at-least-once; ДУБЛЬ `seq` — норма повторного чтения, декодер обязан принимать идемпотентно без фатала; тот же `seq` с ДРУГИМ payload = карантин прогона (research/25)».
|
||||
|
||||
⚠ **Расхождение, разрешённое позже**: «карантин прогона» (D39.119 п.3 и `research/25:77-78` «тот же seq с другим payload = карантин прогона, не тихий no-op») уточнён D39.123 п.2(в) (`05-decisions-log.md:428`): «**PD-105-реализация: карантин ПРОЕКЦИИ (попытки), не прогона** — уточнение D39.119; деньги прогона сеттлятся ремонт-каналом». Побеждает D39.123 как более свежая нота.
|
||||
⚠ **Расхождение, разрешённое позже**: «карантин прогона» (D39.119 п.3 и `research/25:77-78` «тот же seq с другим payload = карантин прогона, не тихий no-op») уточнён D39.123 п.2(в): «**PD-105-реализация: карантин ПРОЕКЦИИ (попытки), не прогона** — уточнение D39.119; деньги прогона сеттлятся ремонт-каналом». Побеждает D39.123 как более свежая нота.
|
||||
|
||||
Фактическое поведение читателя (текущий текст PD-105, `platform/docs/DEFECT_REGISTER.md:192` — закрыт ратификацией и реализацией):
|
||||
|
||||
|
|
@ -73,11 +73,11 @@
|
|||
|
||||
⚠ **ЭТОТ АБЗАЦ — СНИМОК ДО ПАКА, а не действующий контракт (испр. 22.08 аудитом доков; исходный текст оставлен, потому что документ — заказ эмиттер-сессии, а не справочник).** Пак D39.131 РАСШИРИЛ словарь ровно так, как этот раздел и просил: добавлены **exit 4** (потолочная остановка) и **exit 5** (graceful stop), плюс полоса отказов **10–19**; действующий словарь читать в коде движка и в `platform/internal/ingest/exit.go`. Ниже — состояние на момент постановки задачи: 0 clean · 2 completed-with-flags (`*pipeline.CompletedWithFlags`) · 3 signature-stop банка (`*pipeline.WaveSignatureStop`) · 1 — infra failure и всё прочее (`backend/cmd/tmctl/main.go:30-52`).
|
||||
|
||||
**Семантика `--ceiling-usd`** (эмиттер-сессия трогает потолочную окрестность — знать обязана). D39.122 п.2(в) (`05-decisions-log.md:416`):
|
||||
**Семантика `--ceiling-usd`** (эмиттер-сессия трогает потолочную окрестность — знать обязана). D39.122 п.2(в):
|
||||
|
||||
> «**`--ceiling-usd` = КНИЖНЫЙ потолок в силе, не бюджет прогона**: леджер сравнивает с накопленным committed+reserved книги; пересчёт „пользовательский прирост → абсолют“ — обязанность ПЛАТФОРМЫ, данные уже отдаются (`committed_usd`/`reserved_usd` в `status --json`); вторая денежная ось НЕ заводится».
|
||||
|
||||
Поправлено D39.123 п.2(б) (`05-decisions-log.md:428`) для стороны платформы:
|
||||
Поправлено D39.123 п.2(б) для стороны платформы:
|
||||
|
||||
> «**ПОПРАВКА к D39.122(в)/пингу: формула аргумента потолка = `committed + прирост×ставка`, БЕЗ reserved (PD-158)** — `store.Open` движка зануляет утёкший reserved до первой судимой резервации, read-only `status` этого не делает ⇒ reserved из status всегда leftover».
|
||||
|
||||
|
|
@ -99,18 +99,18 @@
|
|||
|
||||
1. **Формат журнала** — главная развилка, «решить дизайном» (строка 103). `research/25:74-76` (GPT): «**формат — развилка строки 103 (GPT):** одиночный JSONL с ftruncate-ремонтом имеет гонку живого читателя и слеп к битой записи с валидным `\n`; альтернативы — пофайловые события (`events/<seq>.json`, temp+rename) либо CRC-фрейминг; побайтовая идентичность не требуется». ⚠ Учесть: тейлер и декодер платформы УЖЕ построены под одиночный `events.jsonl` (`tail.go:17`); выбор пофайловой/CRC-формы = согласованное изменение обеих сторон, пингом через оркестратора.
|
||||
2. **Политика «журнал не пишется»** (PD-60): fsync-политика · ротация · отставание тейлера · заполненный диск; блокировать или деградировать — выбрать и записать явно, «обе позиции законны, молчаливой третьей нет» (`DEFECT_REGISTER.md:24`). Смежное: «диск ограничить (`ENOSPC` на ФС леджера ломает денежные инварианты…)» (`research/25:87-88`) — опс-слой, но поведение эмиттера при ENOSPC — его дизайн.
|
||||
3. **fsync каталога** — NOTE без строки при приёмке D39.122: «NOTE без строк: … fsync каталога» (`05-decisions-log.md:418`); решить в дизайне записи (durability rename/append на ext4).
|
||||
3. **fsync каталога** — NOTE без строки при приёмке D39.122: «NOTE без строк: … fsync каталога»; решить в дизайне записи (durability rename/append на ext4).
|
||||
4. **Значение нового exit-кода** для потолка/graceful-stop (строка 165): 0/2/3 заняты (`main.go:30-52`) — выбрать и внести в shell-контракт.
|
||||
5. **Словарь событий**: форма `events.go` — предложение платформы, «so the engine zone can answer it with a diff» (`events.go:5-6`); движок вправе ответить диффом (состав полей `progress`/`unit_done`, `eta_seconds`, `chunker_version` и т.д.), расхождения — пингом, не молча.
|
||||
|
||||
## 6. Чек-лист входного чтения эмиттер-сессии
|
||||
|
||||
Ратифицированный список — D39.123 п.4 (`05-decisions-log.md:432`): «промт эмиттера (103 + деньги шва; читать PD-95/105/79/99/107/60/61 + D39.106 + новые 165)»; продублирован в CURRENT-STATE (`docs/PROGRESS.md:5`).
|
||||
Ратифицированный список — D39.123 п.4: «промт эмиттера (103 + деньги шва; читать PD-95/105/79/99/107/60/61 + D39.106 + новые 165)»; продублирован в CURRENT-STATE (`docs/PROGRESS.md:5`).
|
||||
|
||||
| # | Что | Где | Зачем |
|
||||
|---|---|---|---|
|
||||
| 1 | Этот док | `docs/architecture/16-events-emitter.md` | сборка всего ниже |
|
||||
| 2 | D39.106 (форма шва) | `docs/architecture/05-decisions-log.md:224-230` | канон транспорта |
|
||||
| 2 | D39.106 (форма шва) | грепать `D39.106` (тело — слайс) | канон транспорта |
|
||||
| 3 | D39.119 п.3 · D39.122 п.2(в) · D39.123 п.2(б,в), п.3 | там же `:394`, `:416`, `:428`, `:430` | at-least-once · семантика `--ceiling-usd` · формула PD-158 · карантин проекции |
|
||||
| 4 | research/25 | `docs/research/25-seam-cold-review.md` §Форма (:16-31) · §эмиттер (:72-83) · отвергнутое (:33-44) | механизмы + чтобы отвергнутое не вернулось |
|
||||
| 5 | PD-95 | `platform/docs/DEFECT_REGISTER.md:180` | история двух устаревших транспортных текстов зоны; что НЕ строить |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Внешняя критика «восхождение»: независимая карта и дифф
|
||||
|
||||
> **⚠ Пометка 24.08.2026 (оркестратор №19, тело НЕ редактируется — D23.3): ВСЕ line-якоря вида `05-decisions-log.md:<строка>` в теле ниже МЕРТВЫ.** Две подрезки живого журнала решений (D39.125, D39.139) сдвинули нумерацию и увезли тела нот в слайсы `archive/architecture/`. Замер: по git-blame каждого якоря взята версия лога на коммит, которым якорь написан, — из 55 якорей живого корпуса съехал 51. Читать их как «номер ноты искать грепом», а не как строку: адрес ноты — её НОМЕР, место тела — реестр `architecture/05-decisions-index.md`. Тело не правится: это внешняя улика, а не инструкция.
|
||||
|
||||
> **⚠ Ревью-шапка оркестратора (11.07.2026, D25; тело документа ниже НЕ редактировалось).** Провенанс: внешний критик GPT-5.6 по мандату `GPT_EXTERNAL_ASCENT_PROMPT.md` (анти-якорный трёхфазный протокол), 2026-07-10. Вердикт адверсариального ревью (12 агентов: 19 первоисточников по живым URL, протокол-аудит, line-refs, red-team §C/§D): **ACCEPT_WITH_FIXES — абсорбция ТОЛЬКО через D25**, не напрямую. Поправки чтения:
|
||||
> 0. **(добавлено D31, 12.07)** Тело пре-датирует D30: §C-таблица (строка «Редактор») описывает проектную колонку как «D1 монолингвальный editor, понижен D17» — **устарело: D30.1 флипнул D1, редактор БИЛИНГВ** (рекомендация критика «bilingual adequacy-preserving edit» принята досрочно через exp12; подтверждающий арм пилота D13.1 сохранён). «$0.69/ранобэ» (§B1.5) → ~$0.85 (D30.4), но КЛЕЙМ «не all-in cost» верен и абсорбирован D25.8.
|
||||
> 1. **Метки §B2 и «Итога» читать как PLAUSIBLE, не CONFIRMED**: ценностные сравнения «чей путь сильнее» — неизмеренные гипотезы по определению §1 самого документа; «PARTIAL» (§B2-голос) — вне его словаря вердиктов.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# research/20 — Авто-формирование банка памяти книги из черновиков (W1.5 / банк-майнинг)
|
||||
|
||||
> **⚠ Пометка 24.08.2026 (оркестратор №19, тело НЕ редактируется — D23.3): ВСЕ line-якоря вида `05-decisions-log.md:<строка>` в теле ниже МЕРТВЫ.** Две подрезки живого журнала решений (D39.125, D39.139) сдвинули нумерацию и увезли тела нот в слайсы `archive/architecture/`. Замер: по git-blame каждого якоря взята версия лога на коммит, которым якорь написан, — из 55 якорей живого корпуса съехал 51. Читать их как «номер ноты искать грепом», а не как строку: адрес ноты — её НОМЕР, место тела — реестр `architecture/05-decisions-index.md`. Тело не правится: это внешняя улика, а не инструкция.
|
||||
|
||||
> **⚠ АМЕНДМЕНТ 26.07 (D39.41/D39.42, синк пака-20).** Два расхождения кода со спекой признаны и ратифицированы: **§B3 «отдельный evidence-файл кандидатов»** — кандидаты живут В СТОРЕ (`retrieval_state.banknote_detail`), файл не строится; **§C2 «консолидация не-мажоритарностью»** — в джойне карты подписи сегодня мажоритарность со смягчением (альтернативы в `note`), полная формула §C2 п.3 уезжает в роль ТЕРМИНОЛОГ (D39.42 п.1: переводит весь смердженный банк по контекстам после черновой волны). §C2 п.7 (двухрежимная эмиссия auto/draft) — ратифицированный контракт эмиссии терминолога.
|
||||
|
||||
> **РЕВЬЮ-ШАПКА ОРКЕСТРАТОРА (17.07, лендинг D39.6).** Верификация: **§A-хеш воспроизведён байт-в-байт**
|
||||
|
|
|
|||
|
|
@ -333,6 +333,30 @@ LINT_SKIP_DOCS = {
|
|||
}
|
||||
|
||||
|
||||
# Ноты D-лога адресуются НОМЕРОМ, а не строкой: две подрезки живого журнала (D39.125, D39.139) сдвинули
|
||||
# нумерацию и увезли тела в слайсы, из-за чего 51 якорь из 55 стал указывать в ЧУЖУЮ ноту, а токенный
|
||||
# линт этого не видел — у таких якорей токена нет. Проверка структурная и токена не требует: владелец
|
||||
# целевой строки — ближайший сверху `## D<номер>`, и он обязан совпасть с номером, названным В ТОЙ ЖЕ
|
||||
# строке дока. ⚠ `docs/research/**` исключён СОЗНАТЕЛЬНО: тела отчётов — внешняя улика, D23.3 запрещает
|
||||
# править их задним числом, поэтому мёртвые якоря там закрыты пометкой в ревью-шапке, а не правкой.
|
||||
DLOG_NAMES = ("05-decisions-log.md", "05-decisions-D")
|
||||
DLOG_BASENAMES = {p.name: str(p.relative_to(ROOT)) for p in
|
||||
[ROOT / "docs/architecture/05-decisions-log.md",
|
||||
*sorted((ROOT / "docs/archive/architecture").glob("05-decisions-*.md"))]
|
||||
if p.is_file()}
|
||||
DNUM = re.compile(r"^## (D\d+(?:\.\d+)*)")
|
||||
|
||||
|
||||
def dlog_owner(body: list[str], lineno: int) -> str | None:
|
||||
"""Номер ноты, чьё ТЕЛО содержит строку lineno (ближайший `## D<номер>` сверху)."""
|
||||
cur = None
|
||||
for i, l in enumerate(body[:lineno], 1):
|
||||
m = DNUM.match(l)
|
||||
if m:
|
||||
cur = m.group(1)
|
||||
return cur
|
||||
|
||||
|
||||
def doc_text(rel: str) -> str | None:
|
||||
"""Текст СКАНИРУЕМОГО ДОКА для линта.
|
||||
|
||||
|
|
@ -429,6 +453,12 @@ def lint_anchors() -> tuple[list[tuple[int, str]], dict[str, int]]:
|
|||
rel, lineno, tail, token = m.group(1).lstrip("/"), int(m.group(2)), m.group(3) or "", m.group(4)
|
||||
shown = f"{rel}:{lineno}{tail}"
|
||||
where = f"{doc_rel}:{n}"
|
||||
# ⚠ ГОЛОЕ имя журнала решений разрешается ДО общего отсева безслэшевых форм: корпус
|
||||
# пишет его именно так (`05-decisions-log.md:390`), и без этой строки структурная
|
||||
# проверка ниже не исполнялась НИ РАЗУ — поймано посадкой мутации 24.08, первая
|
||||
# редакция правила была молчащим no-op.
|
||||
if "/" not in rel and rel in DLOG_BASENAMES:
|
||||
rel = DLOG_BASENAMES[rel]
|
||||
if "~" in rel or "/" not in rel or "..." in rel:
|
||||
tally["unjudged"] += 1
|
||||
continue # ран-локальные пути, голые имена и «…»-сокращения
|
||||
|
|
@ -449,6 +479,13 @@ def lint_anchors() -> tuple[list[tuple[int, str]], dict[str, int]]:
|
|||
if lineno > line_counts[hit]:
|
||||
bad.append((1, f"{where}: якорь `{shown}` — в {hit.relative_to(ROOT)} всего {line_counts[hit]} строк"))
|
||||
continue
|
||||
if any(k in rel for k in DLOG_NAMES) and not doc_rel.startswith("docs/research/"):
|
||||
owns = dlog_owner(body_cache[hit], lineno)
|
||||
named = set(re.findall(r"\bD(\d+(?:\.\d+)*)", line))
|
||||
if owns and named and owns[1:] not in named:
|
||||
bad.append((0, f"{where}: якорь `{shown}` лежит в теле {owns}, а рядом названы "
|
||||
f"D{'/D'.join(sorted(named))} — адресуй ноту НОМЕРОМ, строка D-лога не переживает подрезку"))
|
||||
continue
|
||||
if token is not None:
|
||||
body = body_cache[hit]
|
||||
window = " ".join(
|
||||
|
|
@ -495,6 +532,9 @@ def main() -> int:
|
|||
f"{tally['notoken']} · внешних ссылок пропущено: {tally['external']} · "
|
||||
f"неразбираемых форм пропущено: {tally['unjudged']}"
|
||||
)
|
||||
print(" Якоря в ЖУРНАЛ РЕШЕНИЙ (живой файл и слайсы) сверяются СТРУКТУРНО и без токена:")
|
||||
print(" владелец целевой строки — ближайший `## D<номер>` — обязан совпасть с номером в той же")
|
||||
print(" строке дока; `docs/research/**` из этого исключён намеренно (тела отчётов — улика, D23.3).")
|
||||
print(" НЕ проверяется: якорь без токена (только существование файла и длина) · подмена цели")
|
||||
print(" файлом с тем же путём · смысловая актуальность текста · archive/** и LINT_SKIP_DOCS.")
|
||||
print(" ⚠ Цели читаются из ДЕРЕВА (истина кода — дерево), поэтому чужой незакоммиченный WIP")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue