Add the chapter-boundary pack built on the measured seam, and retarget the drifted anchors across the notes, the experiments and the research files
This commit is contained in:
parent
0594a85c20
commit
595a8ab46b
16 changed files with 465 additions and 63 deletions
402
docs/BACKEND_CHAPTER_STRUCTURE_SESSION_PROMPT.md
Normal file
402
docs/BACKEND_CHAPTER_STRUCTURE_SESSION_PROMPT.md
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
# Промт бэкенд-сессии: ГРАНИЦА ГЛАВЫ — ФАКТ КНИГИ, А НЕ ДОГАДКА ДВИЖКА
|
||||
|
||||
> Выдан оркестратором очереди №23. Пак **$0**. Зона записи — `backend/`.
|
||||
> Ты не коммитишь: дерево передаётся оркестратору на лендинг.
|
||||
>
|
||||
> ⛔ **Это НЕ пак «починить осколки английской книги».** Осколки — симптом, и самый дешёвый из трёх.
|
||||
> Предмет пака — **кто и на каком основании решает, где начинается глава**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Какая проблема и что решит твой результат
|
||||
|
||||
Движок переводит книги мультиагентным пайплайном. Пары языков — ДАННЫЕ, не код; ревью-вопрос по умолчанию:
|
||||
«заработает ли пара, которой в репо ещё НЕТ, без правки Go?».
|
||||
|
||||
Скоро пойдёт платный холодный прогон двух книг: около 20 глав китайской и равный по токенам срез английской.
|
||||
⛔ **Слово владельца, под которым выдан этот пак:** «цель — не бежать поскорее приступить к холодному
|
||||
прогону, а подготовить бэкенд так, чтоб этот холодный прогон исполнить **максимально правильно**. Сколько
|
||||
паков и бэклога нам для этого нужно закрыть, не очень важно. Халтурить не надо, подгонять тоже ничего не
|
||||
надо, спиливаем долг из бэкенда, реализуем актуальный, нужный, чистый архитектурно код».
|
||||
|
||||
**Что сломано, замерено мною по книге прогона (пере-снимешь своим прибором — все числа воспроизводимы $0).**
|
||||
Целей навигации **71**: шесть ярлыков частей (`BOOK ONE`…`BOOK SIX`) и **65 ярлыков глав** вида
|
||||
`Chapter XIX. A Taste of Home`. Издательский конвертер разрезал страницу оглавления на отдельные файлы и
|
||||
объявил навигационную цель на каждый осколок ⇒ **62 цели из 71 указывают во ВТОРУЮ половину spine** (позиции
|
||||
целей 8…124 при 126 документах, медиана 89), тогда как проза лежит в первой.
|
||||
|
||||
**Тела целей, разбиение полное и сумма сходится с 71:** **60** побуквенно равны своему ярлыку · **7** коротки,
|
||||
но ярлыку НЕ равны — два титула частей (`BOOK ONE`+`DEATHSEEKER`, `BOOK FOUR`+`THIS BLACKENED VEIL`) и пять
|
||||
осколков оглавления, у которых вторая строка есть имя СЛЕДУЮЩЕЙ части (`Chapter XIX. A Taste of Home` +
|
||||
`Book Three. To Kill a King`) · **4** несут прозу (`BOOK TWO/THREE/FIVE/SIX`, 14–82 тыс. знаков).
|
||||
|
||||
⛔ **А настоящих глав в книге — 84, и это первое, что я ставил неверно.** Открывает каждую **ДВА подряд абзаца
|
||||
одного класса**: римское числительное, затем имя прописными, затем проза другим классом. Замер: абзацев, чей
|
||||
текст есть голое римское числительное, — **84** (81 в шести частях и 3 в открывающей секции), все в одном и
|
||||
том же классе; контроль, доказывающий, что прибор читал книгу, — абзацев с классом в ней **11 397**.
|
||||
⚠ И мой первый замер дал **3** вместо 84, потому что регексп требовал `class` первым атрибутом, а у
|
||||
большинства первым стоит `id`. **Отрицательный замер здесь особенно дёшев и особенно лжив — печатай
|
||||
контрольную величину рядом.**
|
||||
|
||||
⭐ **ГЛАВНОЕ, и ради этого пак переписан.** Ярлык навигации «Chapter IV. Unforgiven» есть СКЛЕЙКА ровно того,
|
||||
что проза держит двумя абзацами — `IV` и `UNFORGIVEN`. ⇒ **навигация несёт правильные ИМЕНА и неправильные
|
||||
АДРЕСА; проза несёт правильные АДРЕСА и расщеплённое имя.** Ни один источник не лжёт целиком, и ни одного не
|
||||
хватает в одиночку.
|
||||
|
||||
⛔ **Отсюда — чего в этом паке делать НЕЛЬЗЯ, и я сам чуть этого не заказал:** нельзя объявить навигацию
|
||||
врущей и выбросить её. Прежняя редакция промта говорила «настоящих глав шесть» и «навигация о заголовках не
|
||||
знает» — **оба утверждения ложны**, и сессия, получив 84, сверила бы их с «шестью» и решила, что верное
|
||||
правило неверно.
|
||||
|
||||
⇒ Задача — не «поймать мусор эвристикой» и не «отвергнуть навигацию», а **склеить два источника**: АДРЕС
|
||||
берётся у грамматики, ИМЯ — у того, кто его несёт. Твой результат: английская книга режется по своим
|
||||
настоящим главам, каждая получает имя, и достигнуто это ДАННЫМИ книги, а не веткой в Go.
|
||||
|
||||
---
|
||||
|
||||
## 2. Зона записи и git
|
||||
|
||||
Пишешь только в `backend/`. Чужие зоны читать можно, править нельзя. Исключение — своя секция в
|
||||
`docs/PROGRESS.md`. Ты не коммитишь: дерево передаётся на лендинг. В дереве могут работать другие сессии —
|
||||
их незакоммиченные файлы не трогай.
|
||||
|
||||
⛔ **НИКОГДА не читай `.env` и `.env.*`** — там боевые ключи.
|
||||
|
||||
---
|
||||
|
||||
## 3. Карта чтения — пять позиций, и она ЗАКОН
|
||||
|
||||
**Код-факты добываешь САМА: адреса ниже — отправные точки, а не истина.**
|
||||
|
||||
1. `CLAUDE.md` — канон, цели, гардрейлы.
|
||||
2. `backend/docs/CHAPTER_STRUCTURE_DESIGN.md` — дизайн-оф-рекорд предмета, **2062 строки**. ⛔ Читай **§7.1-бис · §7.2 · §7.3 · §7.4 · §8.1 · §8.2** и шапку. ⚠ **§9 и §11 НЕ читай:** там тринадцать пинов
|
||||
БОЛЬШОГО перекроя с миграциями и вопросы владельца по нему — §4.5 выносит его из пака, и чтение втянет тебя
|
||||
в предмет, которого тебе не заказывали. **Статус документа — «ПРЕДЛОЖЕНИЕ, НЕ РАТИФИЦИРОВАНО»**: четыре
|
||||
круга опровержения, сходимости нет; предметная часть устояла, механика исполнения — нет. ⇒ ссылаться на
|
||||
него как на решённое НЕЛЬЗЯ; брать оттуда форму — можно и нужно.
|
||||
3. `backend/internal/chunk/epubtoc.go` — разбор навигации и группировка документов.
|
||||
4. `backend/internal/lang/structure.go` + `backend/internal/chunk/ingest.go` — грамматика заголовка и её
|
||||
потребители.
|
||||
5. `docs/BACKLOG.md`, ряды **283 · 302 · 303 · 201 · 284**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Работа
|
||||
|
||||
### 4.0 ⛔ КОРЕНЬ: ДВА ПУТИ РЕШАЮТ ГРАНИЦУ ГЛАВЫ ПО-РАЗНОМУ И НЕ СПРАШИВАЮТ ДРУГ ДРУГА
|
||||
|
||||
Я ставил задачу дважды и дважды неверно: сперва обошёл предмет срезом, потом искал, какой эвристикой ловить
|
||||
мусор. Верная постановка пришла от владельца одной фразой — «у нас есть статический код, который смотрит,
|
||||
глава ли это и как она названа, там как-то это всё должно склеиваться», — и замер её подтвердил.
|
||||
|
||||
**Замер, пере-снимешь своим прибором.** Диспетчер ингеста получает грамматику источника и отдаёт её **только
|
||||
одному из двух путей**:
|
||||
- `backend/internal/chunk/ingest.go:243`=`func ingestTXT(p, encoding, sourceLang string, st *lang.SourceStructure)`
|
||||
— грамматику **получает**;
|
||||
- `backend/internal/chunk/ingest.go:678`=`func ingestEPUB(p string, im *lang.InlineMarkup)` — **не получает
|
||||
вовсе**, только инлайновую разметку.
|
||||
|
||||
⇒ **Статический код, который умеет сказать «это глава и вот её имя», построен и работает — на одном пути из
|
||||
двух.** На пути EPUB его никто не спрашивает: там границу единолично назначает навигация издателя. Отсюда
|
||||
**71 «глава» вместо 84 настоящих**.
|
||||
|
||||
⛔ **А вот пустой детерминированный заголовок сюда НЕ относится, и я едва не свалил его в ту же кучу.**
|
||||
Он пуст по ДРУГОЙ причине, и твой пак его не заполнит: шаблон берётся из пар-данных
|
||||
(`backend/internal/chunk/chunker.go:131`=`An absent TEMPLATE`), а у английской пары файла нет вовсе —
|
||||
в `backend/configs/langpacks/en-ru/` лежат `inline-markup.txt` и `terminology.txt`, и всё
|
||||
(у `zh-ru` `heading.txt` есть). ⇒ **либо назови «детерминированный заголовок для en — не результат этого
|
||||
пака», либо закажи `en-ru/heading.txt` ДАННЫМИ** и скажи, как это трётся о ряды 201 и 284. Чего нельзя —
|
||||
оставить его в причинной цепи: тогда отчёт пообещает то, чего правка не делает.
|
||||
|
||||
⭐ **И ЭТОТ ПАК ЕСТЬ «ПАК 2» ПО РЯДУ 303 — объявляю прямо, потому что без этого ты упрёшься в ратифицированный
|
||||
запрет.** `D39.224` п.7 велит «ось „обязательность юнита" вне пака 2 не трогать (носитель — строка 303)», а сам
|
||||
ряд 303 называет себя «названным ВХОДОМ в пак 2». ⇒ **запрет снимается ИМЕННО ЭТИМ паком, и ось трогать
|
||||
можно.** Предмет 303: `detectChapterUnit` итерирует `UnitOrdered` и без юнита возвращает 0, поэтому грамматика
|
||||
вида «Chapter 12» (маркер + номер, без юнита) книгу не режет — хотя чанкер такой заголовок СНЯТЬ уже умеет.
|
||||
Форма лечения набросана в дизайне §8.2 (доминанта над ФОРМАМИ заголовка, «без юнита» — последний кандидат);
|
||||
она НЕ ратифицирована, и ты вправе предложить другую с доводом.
|
||||
|
||||
⚠ **А вот «283 и 303 — один шов» было моей натяжкой, и её сними.** Это РОДСТВЕННЫЕ, но разные предметы: 303 —
|
||||
текстовый резак ингеста; 283 — БИЛДЕР ВЫДАЧИ (`backend/internal/bookfile/`), делающий главу из каждого
|
||||
документа spine у читалки человека. Общее у них — «грамматика не участвует там, где решают границу», и этого
|
||||
довода достаточно; выдавать их за одну строку значит обещать закрыть 283, чего этот пак не делает.
|
||||
|
||||
### 4.1 РОВНО ТАК: грамматика участвует на ОБОИХ путях, а навигация остаётся источником ИМЁН
|
||||
|
||||
**Предмет пака — склеить существующие механизмы, а не построить третий.** Грамматика даёт АДРЕС границы,
|
||||
навигация даёт ИМЯ. Ни новой эвристики, ни порога, ни ветки по языку.
|
||||
|
||||
**РЕШИ САМА** форму проводки и то, как два источника сводятся в один ответ. **Жёстко задаю четыре правила, и
|
||||
каждое — следствие замера, а не вкус:**
|
||||
|
||||
**(а) ДОКУМЕНТ, ИСЧЕРПАННЫЙ СВОИМ ЯРЛЫКОМ, — НЕ ГЛАВА, НО ИМЯ ОН НЕСЁТ.** Это тождество, а не порог: тело,
|
||||
равное ярлыку, прозы не содержит по построению. **60 из 71.** ⚠ И его имя не выбрасывается — оно
|
||||
единственное место, где «IV» и «UNFORGIVEN» уже склеены в «Chapter IV. Unforgiven».
|
||||
|
||||
⛔ **ОСТАТОК НАЗВАН ЧИСЛОМ, И ПРЯТАТЬ ЕГО НЕЛЬЗЯ: строгое тождество снимает 60, а ПЯТЬ осколков переживут** —
|
||||
у них вторая строка несёт имя следующей части. **«Почти-тождество» я запрещаю**: порога не заводить. Решай по
|
||||
роду — либо правило формулируется так, что ловит и эти пять (например «каждая строка тела есть ярлык
|
||||
навигации»), либо остаток НАЗЫВАЕТСЯ числом и принимается осознанно. ⛔ Чего нельзя — сдать «сделано» и
|
||||
получить 89 глав вместо 84.
|
||||
|
||||
**(б) ТАМ, ГДЕ НАВИГАЦИЯ НЕ ПОСТАВИЛА ЦЕЛИ, ГРАНИЦУ СТАВИТ ГРАММАТИКА.** Настоящие начала глав живут внутри
|
||||
прозы и навигационных якорей не имеют вовсе; сегодня их не видит никто. ⚠ **Формулировать это как «навигация
|
||||
молчит» — ошибка:** она называет 65 глав поимённо, она лишь целит не туда.
|
||||
|
||||
**(в) ИМЯ БЕРЁТСЯ У ТОГО, КТО ЕГО НЕСЁТ.** Грамматика, взятая одна, даст `title_raw = "IV"` — то есть ХУЖЕ
|
||||
сегодняшнего, потому что имя в прозе стоит СЛЕДУЮЩИМ абзацем. ⇒ **сшивка обязана назвать, откуда каждая из 84
|
||||
глав получает имя**, и это входит в приёмку. Вход ряда **284** и §7.1-бис дизайна (title_raw обязан
|
||||
заполняться любым новым детектором) — читай их до стройки.
|
||||
|
||||
**(г) ТИТУЛ ЧАСТИ ОБЯЗАН ОСТАТЬСЯ ГРАНИЦЕЙ, И СЕГОДНЯ ЕГО СПАСАЕТ СЛУЧАЙНОСТЬ.** Два титула уцелели лишь
|
||||
потому, что несут подзаголовок (`BOOK ONE`+`DEATHSEEKER`). **Титул без подзаголовка был бы тождеством**, и
|
||||
правило (а) сняло бы границу ЦЕЛОЙ ЧАСТИ — молча, при зелёной батарее. Для «пары, которой в репо ещё нет» это
|
||||
класс, а не частность. ⇒ **пин ровно на эту форму**: тождественный титул, за которым идут документы без
|
||||
навигационных целей, ⇒ граница СОХРАНЯЕТСЯ.
|
||||
|
||||
⛔ **ГРАНИЦЫ, КОТОРЫЕ Я СТАВЛЮ ЖЁСТКО:** порога в знаках в Go **не заводить** · список служебных ролей
|
||||
**не расширять** (узость намеренна: `backend/internal/chunk/epubtoc.go:327`=`func isServiceRole(role string) bool`) ·
|
||||
ветки по паре или языку **не появляется ни одной**.
|
||||
|
||||
⛔ **И ОДНО, ЧТО ПРОМТ ОБЯЗАН БЫЛ РЕШИТЬ И НЕ РЕШАЛ — ИСХОД ДОКУМЕНТА, НА КОТОРОМ ГЛАВУ НЕ ОТКРЫЛИ.** Прежняя
|
||||
редакция писала «не потерять ни знака» и тут же требовала переписать докблок
|
||||
`backend/internal/chunk/epubtoc.go:289`=`NO DOCUMENT IS DROPPED HERE` — это ДВА РАЗНЫХ исхода, и я их склеил.
|
||||
Замер: группировка приклеивает любой неграничный документ к ПРЕДЫДУЩЕЙ группе, а осколки стоят ПОСЛЕ всей
|
||||
прозы ⇒ «просто не открывать главу» отправит 65 строк оглавления в хвост последней части, и они будут
|
||||
переведены и отгружены читателю — та же трата, что в ряду **283**, только в другой главе.
|
||||
⇒ **РОВНО ТАК: документ-тождество ИСКЛЮЧАЕТСЯ из чтения, а не приклеивается**, с названной причиной и
|
||||
размером; инвариант сохранения получает это третье состояние; докблок переписывается тем же движением и
|
||||
называет условие, при котором вывод держится. ⚠ Судьбу документа, у которого нет навигационной цели и который
|
||||
сегодня приклеивается к последней части, назови отдельной строкой отчёта.
|
||||
|
||||
**РОВНО ТАК по видимости:** рядом с существующими счётчиками аномалий (`unresolved`, `collapsed`, `attached`)
|
||||
появляется свой, и число доезжает до человека.
|
||||
|
||||
### 4.2 ГРАММАТИКА КОНКРЕТНОЙ КНИГИ ПРИЕЗЖАЕТ ЕЁ ДАННЫМИ
|
||||
|
||||
Сегодня грамматика читается **только** из пар-данных языка
|
||||
(`backend/internal/lang/structure.go:142`=`func LoadSourceStructure(root, sourceLang string)`), лестница из
|
||||
трёх ступеней, книжной ступени нет. А грамматика заголовков КОНКРЕТНОГО файла есть свойство **конверсии
|
||||
издателя**, то есть книги, а не письменности: тот же роман у другого издателя размечен иначе.
|
||||
|
||||
⛔ **И вот здесь я ошибся, проверь сама и не повтори за мной.** Я написал было «дом уже ратифицирован —
|
||||
книжный оверлей» (`backend/internal/config/book.go:105`=`LangpackExtend string`,
|
||||
`backend/internal/lang/langpack.go:413`=`func LoadWithOverlay(root, src, tgt, overlayRoot string)`). **Это
|
||||
переоценка: существующий оверлей такой файл ОТКАЖЕТ.** Он сливает только файлы манифеста, и его собственная
|
||||
ошибка это говорит — `backend/internal/lang/langpack.go:463`=`an overlay merges only the source/pair manifest files`;
|
||||
`structure.txt` не входит ни в `backend/internal/lang/langpack.go:283`=`var srcFiles = []string{`, ни в
|
||||
`backend/internal/lang/langpack.go:290`=`var pairFiles = []string{"palladius.txt"`. Ратифицирован он для
|
||||
частного канона, не для грамматики.
|
||||
|
||||
**РОВНО ТАК по дому:** книжная ступень у ЛЕСТНИЦЫ ГРАММАТИКИ
|
||||
(`backend/internal/lang/structure.go:142`=`func LoadSourceStructure(root, sourceLang string)` — сегодня три
|
||||
ступени, книжной нет), со СВОИМ отпечатком через
|
||||
`backend/internal/lang/structure.go:127`=`func structureFingerprint(origin string, b []byte) string`. **НЕ через
|
||||
`LoadWithOverlay` и НЕ полем брифа.** Довод денежный: поле брифа уходит в хеш брифа,
|
||||
оттуда в КАЖДЫЙ хеш запроса, и вдобавок рендерится модели. Грамматике границ ехать туда незачем — ей место в
|
||||
КРОЕ, а крой уже фолдит отпечаток структуры.
|
||||
|
||||
**РЕШИ САМА,** что грамматика обязана уметь для этой книги. Приоры, каждый опровергается замером:
|
||||
безмаркерный заголовок (сегодня маркер требуется) · класс римских числительных (сегодня арабские и CJK) ·
|
||||
класс римских числительных (сегодня арабские и CJK) · «абзац, чей текст есть голое числительное» ·
|
||||
«имя главы — СЛЕДУЮЩИЙ абзац того же класса».
|
||||
|
||||
⛔ **Приор «центрированный абзац» я СНИМАЮ, и вот почему — иначе он столкнул бы тебя лбом с §4.5.**
|
||||
Вычисленный стиль виден только внутри обходчика `backend/internal/chunk/ingest.go:1155`=`func extractXHTML`, а
|
||||
§4.5 запрещает его трогать: там четыре пина байт-паритета и ошибка ТИХАЯ. Наружу сегодня выходит курсив —
|
||||
глифом, — а канала «центрирован» нет вовсе. ⇒ либо обойдись без стиля (замерь, даёт ли «абзац = голое римское
|
||||
числительное» ровно 84 на ЧИСТОМ тексте и сколько даёт ложных), либо **приходи с доводом и ПИНОМ**, а не
|
||||
правь обходчик молча. ⚠ Мой приор был внутренне противоречив; это моя ошибка, не твоя развилка.
|
||||
|
||||
### 4.2-бис ⛔ ПРАВИЛО ЗАГОЛОВКА УЖЕ ПРОТИВОРЕЧИТ САМО СЕБЕ — ряд **346** половина (б), и ты встанешь ровно на него
|
||||
|
||||
**Найдено оркестратором 18.09 чтением бэклога, в пак внесено намеренно.** Ты собираешься заставить грамматику
|
||||
участвовать там, где режут. Но правило «что такое заголовок» **сегодня разъехалось по двум предикатам, и они
|
||||
дают РАЗНЫЕ ответы на одном входе**. Строить поверх противоречия — значит закрепить его в третьем месте.
|
||||
|
||||
**Замер, уже снятый и пере-снятый на копии дерева (ряд 346, повторишь своим прибором):**
|
||||
- Страж ДЛИНЫ живёт только в ингесте — `backend/internal/chunk/ingest.go:341`=`const chapterHeaderMaxRunes = 60`;
|
||||
в чанкере длина не проверяется вовсе.
|
||||
- Осмысленность НОМЕРА живёт только в чанкере — `backend/internal/chunk/chunker.go:315`=`v := section + num`.
|
||||
- ⇒ на заголовке С СЕПАРАТОРОМ после юнита (`第四章:…`) длиной 61–84 руны ингест говорит `false`, чанкер —
|
||||
`ok=true`. ⚠ **Без сепаратора расхождения НЕТ** ни на одной длине, и без этой оговорки строка читается как
|
||||
ложная: такую строку отвергают оба предиката.
|
||||
- Отдельно: `第零章` (пролог нулевой главой) ингест режет главой, а чанкер заголовок НЕ снимает ⇒ `heading=""`,
|
||||
и сырой CJK-маркер уезжает МОДЕЛИ.
|
||||
|
||||
**Половина (а) уже закрыта** актом `D39.225`: пин расхождения и паритет-тест стоят, оба под мутациями. Пин
|
||||
написан так, что **краснеет ровно тогда, когда приземлится фикс** — это сделано намеренно, чтобы фиксер не смог
|
||||
починить молча. ⇒ **ты — тот фиксер, и покрасневший пин здесь НЕ «протухший тест», а приглашение**; правишь его
|
||||
вместе с правилом и объявляешь это в отчёте по норме «правка, вызванная заказанной сменой поведения».
|
||||
|
||||
⛔ **И вот зачем это в ЭТОМ паке, а не отдельным:** предмет один — «чем определяется, что строка есть заголовок
|
||||
главы». Пока он живёт в двух предикатах, «подключить грамматику к EPUB» означает выбрать, к КОТОРОМУ из двух
|
||||
подключаться, и любой выбор молча объявит второй неправым. ⇒ **сведи правило в ОДНО место и позови оттуда
|
||||
всех троих** — ингест текстовый, ингест EPUB, чанкер. Это и есть «чистый архитектурный код» в формулировке
|
||||
владельца, а не рефактор ради рефактора.
|
||||
|
||||
⚠ **Ряд 346 пере-проверь сама:** его прошлая редакция уже была однажды исправлена как ложная, и оговорка про
|
||||
сепаратор — след той правки.
|
||||
|
||||
### 4.3 ЧТО ПРОИСХОДИТ, КОГДА ПОЛИТИКА НЕ ОБЪЯВЛЕНА: ПРОХОД С НАЗВАННОЙ АНОМАЛИЕЙ
|
||||
|
||||
**РОВНО ТАК, и довод взят из самой кодовой базы:** `backend/internal/pipeline/runner.go:389`=`merely costs money it did not mean to spend` — конфигурация,
|
||||
которая верна и лишь стоит денег, которых не собиралась тратить, есть форма, о которой этот код
|
||||
**ПРЕДУПРЕЖДАЕТ, а не отказывает**; отказы — для механизма, который не может работать вовсе. Кривое
|
||||
оглавление — первое, а не второе.
|
||||
|
||||
⇒ книга без объявленной грамматики едет как сегодня в части (б), но человек **видит числом**
|
||||
⚠ **Оговорка, без которой абзац лжёт:** правило (а) живёт в Go и действует на КАЖДЫЙ EPUB с осколками-тождествами,
|
||||
объявлена грамматика или нет. Без грамматики отсутствует только (б).
|
||||
⇒ человек видит числом, что получил: сколько глав,
|
||||
сколько из них несут прозу, какова медиана и самая длинная, сколько фрагментов оглавления опознано
|
||||
тождеством. Одной строкой в человеческой сводке и теми же числами в машинной.
|
||||
|
||||
⚠ **Почему не отказ:** большинство реальных EPUB собраны такими же конвертерами. Отказ на «оглавление
|
||||
выглядит странно» сделал бы движок капризным к массовой форме входа и заставил бы объявлять грамматику для
|
||||
каждой книги. Это не «приличная мультиязычность», а её противоположность.
|
||||
|
||||
### 4.4 ⛔ ЗАМЕР ПЕРЕД СТРОЙКОЙ — ПЕРВЫМ ДЕЛОМ, И БЕЗ ЕДИНОЙ СТРОКИ Go
|
||||
|
||||
Прежде чем править код, **реализуй правило грамматики на python и прогони по книге прогона**. Ответь числом:
|
||||
сколько глав даёт «центрированный короткий абзац + римская цифра + строка капсом» против записей навигации.
|
||||
|
||||
⇒ **это и есть приёмочное число пака.** Если правило даёт число, не похожее на настоящую структуру книги, —
|
||||
стройка начинается не с того, и лучше это узнать за ноль долларов и без правок дерева. Так же вчера был
|
||||
пере-снят механизм группировки, и это сэкономило пак.
|
||||
|
||||
### 4.4-бис ⛔ ЧТО ЭТОТ ПАК СДВИНЕТ В ДЕНЬГАХ — сказано ЗАРАНЕЕ, потому что узнать это после лендинга дорого
|
||||
|
||||
**Правка правила ингеста двигает ключ манифеста, и не только у английской книги.** Конвенция записана в самом
|
||||
коде: `backend/internal/pipeline/manifest.go:355`=`treats an ingest-rule change as a chunkerVersion bump`.
|
||||
А в ключ сворачиваются оба — `backend/internal/pipeline/manifest.go:281`=`Chunker: chunkerVersion` и
|
||||
`backend/internal/pipeline/manifest.go:283`=`Structure: r.structure.Fingerprint()`, причём отпечаток несёт
|
||||
версию алгоритма ДАЖЕ у пустой грамматики (`backend/internal/lang/structure.go:104`=`structureAlgoVersion + "-none"`).
|
||||
⇒ **ключ манифеста КИТАЙСКОЙ книги сдвинется тоже.** Вдобавок §4.2-бис меняет ТЕКСТ чанка.
|
||||
|
||||
⛔ **И потому: акт `D39.269` п. B1 утверждал «китайская половина неподвижна» — это было верно про ПРЕДЫДУЩИЙ
|
||||
пак и перестаёт быть верным про твой.** Не «обходи», а **НАЗОВИ**: в отчёте отдельной строкой — что сдвинулось,
|
||||
у каких книг, и какой пере-снапшот это требует. Эррату к акту пишет оркестратор, не ты.
|
||||
⚠ **И ещё одно следствие, за пределы твоей зоны:** пак холодного прогона
|
||||
(`docs/COLDRUN_TWO_BOOKS_SESSION_PROMPT.md`) несёт ПРЕ-РЕГИСТРИРОВАННЫЕ числа среза английской книги и
|
||||
стоп-правило «срез не совпал с пре-регистрированным → СТОП». После тебя крой другой, и те числа протухают.
|
||||
**Твой пак лендится ДО фриза прогона**; пере-регистрацию делает пак прогона. Тебе — только строка в отчёте.
|
||||
|
||||
### 4.5 ЧТО В ЭТОТ ПАК НЕ ВХОДИТ — чтобы ты не расширяла его по своей инициативе
|
||||
|
||||
**Ряд 302** (несколько глав в ОДНОМ документе, разделённых якорями, схлопываются в одну) — **противоположный**
|
||||
предмет, и дизайн вынес его из окна с названной ценой: единственное место, трогающее байтовый путь
|
||||
извлечения, где ошибка ТИХАЯ. Не трогай.
|
||||
**Ряд 201** (движковое «Глава N» доезжает читателю внутри текста) и **284** (название книги и заголовки
|
||||
через термины) — соседние предметы того же дизайна; в этот пак не входят. Увидишь, что твоя правка их
|
||||
задевает, — скажи, не чини.
|
||||
**Большой перекрой** из дизайна (адресация главы контентом, четыре таблицы по ординалу) — **НЕ этот пак**.
|
||||
Его механика в четырёх кругах не сошлась, и заходить в неё сейчас значит открыть предмет, который мы не
|
||||
закроем до прогона.
|
||||
|
||||
---
|
||||
|
||||
## 5. Самопроверка исполнением — и где у ЭТОГО пака мягко
|
||||
|
||||
Ревью исполнением обязательно: своего кода, своих проб, своих результатов. **Субагенты разрешены.**
|
||||
**Fable 5 — ОДИН советчик** с постоянным контекстом; он советчик, а не источник истины.
|
||||
|
||||
**ЧЕТЫРЕ МЕСТА, ГДЕ ЭТОТ ПАК МЯГОК ИМЕННО ПОТОМУ, ЧТО ОН ТАКОЙ:**
|
||||
|
||||
1. ⛔ **Твоя правка меняет КРОЙ, а крой versionируется.** По конвенции проекта правка правила нарезки
|
||||
бампает версию нарезки, а та фолдится БЕЗУСЛОВНО — то есть у КАЖДОЙ книги, включая китайскую.
|
||||
**Сегодня это бесплатно** (книг продуктового пути с оплаченными чанками нет), и именно поэтому пак идёт
|
||||
ДО прогона, а не после. Предъяви цену явно, не умолчи её.
|
||||
2. ⛔ **Тождество легко сделать почти-тождеством, и тогда оно станет порогом.** «Равно ярлыку» и «начинается
|
||||
с ярлыка плюс немного» — разные правила: первое доказуемо, второе — эвристика с невидимой границей.
|
||||
Замер: **60 тождеств и ОДНО почти-тождество** (титульная страница части). Если возьмёшь «почти», скажи,
|
||||
где теперь граница и чем она обоснована.
|
||||
3. ⛔ **Грамматика, которая режет ЭТУ книгу, легко окажется грамматикой этой книги.** Признак «римская
|
||||
цифра в центрированном абзаце» обязан быть выведен из свойства ВЁРСТКИ, а не подобран под Кристоффа.
|
||||
⛔ **Контрольный набор я назвал неверно, и неверно он звучал правдоподобно:** «китайская книга» — это TXT
|
||||
(`books/gu-zhenren`), и EPUB-пути она не касается вовсе. **Настоящий контроль — два EPUB дерева:**
|
||||
`books/isekai_majutsushi_jp.epub` (CJK-EPUB, получает умолчательную грамматику на EPUB-пути) и
|
||||
`books/fifty_shades_1_en.epub` (латиница, цели навигации 1:1 с документами — отрицательный контроль:
|
||||
правило (а) обязано на нём не сработать ни разу). Китайская книга — контроль только на сдвиг версии.
|
||||
4. ⛔ **Пин на новую грамматику легко построить на той же фикстуре, из которой она выведена.** Тогда он
|
||||
докажет, что правило работает на том, из чего сделано. Образец правильной формы в дереве есть — пин,
|
||||
который режет книгу ИЗ ОДНОГО ФАЙЛА ДАННЫХ и падает без него.
|
||||
|
||||
---
|
||||
|
||||
## 6. Оси ревью
|
||||
|
||||
- **Код:** батарея + живые пробы + СВОИ адверсариальные посадки вне твоего списка. Пак, меняющий крой,
|
||||
принимается прогоном через настоящий драйвер, а не чтением диффа.
|
||||
- **Данные:** каждое значение грамматики — с доводом, из какого свойства вёрстки выведено.
|
||||
- **Швы:** отпечаток структуры едет в крой; проверь, что он двигается ровно тогда, когда должен.
|
||||
|
||||
**Кодовому паку дополнительно:** пин на УСЛОВНОЕ сообщение обязан иметь фикстуру, где оно ОБЯЗАНО
|
||||
прозвучать · перед отчётом сверь каждый клейм с результатом инструмента ЭТОЙ сессии · последний абзац
|
||||
отчёта оказался планом — сделай сейчас · **править тесты ради зелени недопустимо**, но правка, вызванная
|
||||
ЗАКАЗАННОЙ сменой поведения, есть обслуживание и ОБЪЯВЛЯЕТСЯ · дифф `^func Test` предъявляй исполнением.
|
||||
|
||||
---
|
||||
|
||||
## 7. Записка-план
|
||||
|
||||
До первой правки кода — записка: что делаешь, в каком порядке, что считаешь спорным. ⚠ Замер §4.4 идёт
|
||||
ПЕРВЫМ и входит в записку числом, а не обещанием.
|
||||
|
||||
---
|
||||
|
||||
## 8. Заявление есть команда
|
||||
|
||||
Каждое число — с командой. У каждого НУЛЯ печатается контрольная величина.
|
||||
**Ловушки среды:** обёртка `grep` чтит игнор-файлы и не видит `books/` — бери `command grep` · `find` здесь
|
||||
**bfs**: относительное время только `-mmin`, и он тоже чтит игнор-файлы · командной утилиты для баз нет ·
|
||||
⚠ **знаки и байты — разные популяции**, «текст файла» и «текст тела» — тоже: на этом я сегодня получил ноль
|
||||
тождеств там, где их шестьдесят.
|
||||
|
||||
---
|
||||
|
||||
## 9. Эхо старта
|
||||
|
||||
До работы — ≤10 строк **СВОИМИ словами**: скоуп · инварианты · чего не делаешь. Шли первым действием.
|
||||
|
||||
---
|
||||
|
||||
## 10. Что НЕ удалось и где прибор слеп
|
||||
|
||||
Обязательная секция, две половины: «что не получилось» и **«что ты знаешь и не сказала»** — что невидимо ·
|
||||
почему не чинила · чем закрывается.
|
||||
|
||||
---
|
||||
|
||||
## 11. Канал вопросов и право отказаться
|
||||
|
||||
Конфликт промта с деревом — **пинг, а не интерпретация**. Право сказать «этого делать не надо» с аргументом
|
||||
есть и поощряется.
|
||||
⚠ Этот промт написан после того, как я **сам ошибся в постановке дважды**: сперва обошёл предмет срезом,
|
||||
потом склеил два факта в один. Оба раза поправил замер, а не рассуждение. Найдёшь третью — говори.
|
||||
|
||||
---
|
||||
|
||||
## 12. Прямой канал
|
||||
|
||||
`/tmp/textmachine-channel` — впиши свой блок первым делом. ⚠ Адрес из файла не доказывает, что сессия жива:
|
||||
сверься с `ListAgents`.
|
||||
|
||||
---
|
||||
|
||||
## 13. Когда пак считается завершённым
|
||||
|
||||
- [ ] Замер §4.4 предъявлен ЧИСЛОМ до первой правки Go.
|
||||
- [ ] У каждого пункта §4 — исход: сделано · не делаю с доводом · пинг.
|
||||
- [ ] **Английская книга режется по своим настоящим главам**, и это предъявлено прогоном, а не рассуждением.
|
||||
- [ ] **Китайская книга не изменилась** — предъявлено хешем.
|
||||
- [ ] Ни одной ветки по языку или паре не добавлено — предъявлено грепом с контрольной величиной.
|
||||
- [ ] Круги СОШЛИСЬ; прежние находки закрыты таблицей «находка → что сделано → **чем предъявлено**».
|
||||
- [ ] Таблица мутаций полная, ТРИ исхода: поймано · выжило · **НЕ ИЗМЕРЕНО**; новые записи введены в гейт.
|
||||
- [ ] Числа сняты ПОСЛЕ последней правки; гейт прогнан целиком; рядом с `ok` напечатан счёт скипов.
|
||||
- [ ] Явное **«работа завершена, править не планирую»**.
|
||||
|
||||
⛔ **И последнее.** Предмет пака — **кто решает, где начинается глава**. Ответ, к которому надо прийти:
|
||||
тождество решает движок, потому что это факт, а не догадка; АДРЕС границы решает грамматика книги; ИМЯ берётся
|
||||
у того, кто его несёт. Всё, что сверх этого, решают данные книги. Если твоё
|
||||
решение где-то ставит догадку движка на место данных — оно не готово, сколько бы тестов ни было зелёными.
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -138,7 +138,7 @@
|
|||
|
||||
**Б7 — Шов и эмиттер 16, 17**
|
||||
Находки: N042, N043, N044, N045, N046, N047, N048, N049, N115, N116, N117
|
||||
**Приёмка:** N046 — форма якоря `mining.go:243-244`=`re-seed the bank with the auto rows`; N047 — атрибуция D39.159 п.7 и пере-суд «строки 139»; N048 — ОБЕ строки таблицы (97 и 103); N049 — хвост с `PD-427`; N044/N115 — StreamVersion **1.2** ⚠ (испр. 05.09: на HEAD она **1.3** — минор приехал лендингом `81a89e9`; критерий читать как «версия записана ВЕРНО», а не как литерал `1.2`); N045 — двенадцать якорей в токен-форме. (Прежний критерий про N032 снят: N032 живёт в Б6, испр. по замечанию контролёра.) §5–§6 дока 16 сам себя баннирует как отработанный хендофф, внешних ссылок ноль — кандидат на вынос в `archive/reports/` с указателем (решение объявить, не делать молча).
|
||||
**Приёмка:** N046 — форма якоря `backend/internal/pipeline/mining.go:246-246`=`re-seed the bank with the auto rows`; N047 — атрибуция D39.159 п.7 и пере-суд «строки 139»; N048 — ОБЕ строки таблицы (97 и 103); N049 — хвост с `PD-427`; N044/N115 — StreamVersion **1.2** ⚠ (испр. 05.09: на HEAD она **1.3** — минор приехал лендингом `81a89e9`; критерий читать как «версия записана ВЕРНО», а не как литерал `1.2`); N045 — двенадцать якорей в токен-форме. (Прежний критерий про N032 снят: N032 живёт в Б6, испр. по замечанию контролёра.) §5–§6 дока 16 сам себя баннирует как отработанный хендофф, внешних ссылок ноль — кандидат на вынос в `archive/reports/` с указателем (решение объявить, не делать молча).
|
||||
|
||||
|
||||
**Б8 — Движковые арх-доки 03, 09, 10, 12**
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1747,13 +1747,13 @@ langpacks — **0 файлов** при **16** прочитанных прибо
|
|||
|
||||
| читатель | адрес | что получает |
|
||||
|---|---|---|
|
||||
| `attachConsolidatedDst` → режим эмиссии | `backend/internal/pipeline/terminologist.go:1415`=`Terms the role did not answer are left untouched` | передачу ⇒ `draft` вместо отката к догадке куска |
|
||||
| `attachClassifiedType` / `attachClassifiedGender` | `backend/internal/pipeline/terminologist.go:1430`=`attachClassifiedGender stamps` | тип и род из базиса |
|
||||
| `consolidatedRows` → `ConsolidationKeyConflicts` | `backend/internal/pipeline/terminologist.go:747`=`membank.ConsolidationKeyConflicts(consolidatedRows(cands, out), bank)` | судится, см. решение ниже |
|
||||
| `CanonConflicts` | `backend/internal/pipeline/terminologist.go:725`=`terminology.CanonConflicts(cands, out, canon)` | судится, см. решение ниже |
|
||||
| `attachConsolidatedDst` → режим эмиссии | `backend/internal/pipeline/terminologist.go:1418`=`Terms the role did not answer are left untouched` | передачу ⇒ `draft` вместо отката к догадке куска |
|
||||
| `attachClassifiedType` / `attachClassifiedGender` | `backend/internal/pipeline/terminologist.go:1433`=`attachClassifiedGender stamps` | тип и род из базиса |
|
||||
| `consolidatedRows` → `ConsolidationKeyConflicts` | `backend/internal/pipeline/terminologist.go:750`=`membank.ConsolidationKeyConflicts(consolidatedRows(cands, out), bank)` | судится, см. решение ниже |
|
||||
| `CanonConflicts` | `backend/internal/pipeline/terminologist.go:728`=`terminology.CanonConflicts(cands, out, canon)` | судится, см. решение ниже |
|
||||
| `ConsolidationConflicts` (§G2, свои против своих) | рядом, тот же цикл | судится |
|
||||
| `labelRows` → `TypeLabelMismatches` | там же | судится |
|
||||
| счётчики `Consolidated`/`Declined`/`Unanswered` | `backend/internal/pipeline/terminologist.go:719`=`res.Consolidated++` | ⛔ НЕ вливать базисные в общий набор до цикла счёта: поле сменит смысл без единой строки об этом |
|
||||
| счётчики `Consolidated`/`Declined`/`Unanswered` | `backend/internal/pipeline/terminologist.go:722`=`res.Consolidated++` | ⛔ НЕ вливать базисные в общий набор до цикла счёта: поле сменит смысл без единой строки об этом |
|
||||
| таблица стопа и её сайдкар | ⚠ ИСТОРИЧЕСКОЕ (до этого пака формула была `row.Invented = dst != "" && !proposedByDrafts(dst, c.Variants)`, и адрес намеренно НЕ в якорной форме: цель не уехала, а ИЗМЕНИЛАСЬ — её починил этот пак, и подставить найденный в цели токен значило бы подогнать якорь под то, что там оказалось). Живая строка — `backend/internal/pipeline/mining.go:525`=`row.Invented = dst != "" && !row.SettledByBasis` | отдельное состояние, см. ниже |
|
||||
| очередь спорных | `backend/internal/pipeline/stopcontest.go:83`=`if r.SettledByBank` | ⛔ решается ОТДЕЛЬНО, не наследуется по совпадению имени |
|
||||
| проекция банка наружу | `backend/internal/pipeline/bankexport.go:128`=`NeverAsked: t.BankSettled` и `backend/internal/pipeline/bankexport.go:269`=`Contradicts: row.Contradicts, BankHolds: row.BankHolds` | АДДИТИВНОЕ поле, см. §5 |
|
||||
|
|
@ -1797,7 +1797,7 @@ langpacks — **0 файлов** при **16** прочитанных прибо
|
|||
##### 6. Юниты (§4.5) — ОТДЕЛЬНЫЙ ПРОХОД, батчер не трогаю
|
||||
|
||||
Семьи и серии сегодня детектируются НАД `paid`, то есть ПОСЛЕ фильтра
|
||||
(`backend/internal/pipeline/terminologist.go:574`=`terminology.DetectFamilies(paid, fp)`), и комментарий выше объясняет причину: детектировать над полным
|
||||
(`backend/internal/pipeline/terminologist.go:577`=`terminology.DetectFamilies(paid, fp)`), и комментарий выше объясняет причину: детектировать над полным
|
||||
набором значит рассогласовать юниты с батчами, из них построенными. **Но это довод про БАТЧИ, а не про
|
||||
предикат.** Если считать юнит над `paid`, юнит будет определён тем самым фильтром, который он питает, —
|
||||
круг. ⇒ юнит для предиката считается **отдельным чистым проходом над ВСЕМИ кандидатами**, батчер остаётся
|
||||
|
|
@ -1828,7 +1828,7 @@ langpacks — **0 файлов** при **16** прочитанных прибо
|
|||
- **Ряд 490** (страж разрыва окон глав) — $0, беру, образец `backend/internal/membank/memvoice.go:271`=`func VoiceWindowGaps`;
|
||||
у образца беру и ГАРАНТИЮ: намеренный разрыв законен ⇒ исход громкая строка, а не отказ загрузки.
|
||||
- **Ряд 448** — пере-формулировка обязана обновить И голден каталога операторских сообщений
|
||||
(`backend/internal/pipeline/testdata/operator-messages.txt:141`=`terminology: this book had already paid`), и это
|
||||
(`backend/internal/pipeline/testdata/operator-messages.txt:143`=`terminology: this book had already paid`), и это
|
||||
обслуживание заказанной смены поведения (`D39.183`), а не подгонка под зелень. Объявляю заранее.
|
||||
- **Ряд 487** пак НЕ чинит, но посылку «решено ⇒ `draft`» пиню: без пина завтрашняя починка скачком двинет
|
||||
набор решённых, то есть деньги.
|
||||
|
|
@ -2411,7 +2411,7 @@ decision»).
|
|||
|
||||
| пункт | исход | чем предъявлено |
|
||||
|---|---|---|
|
||||
| §4.1 громкий отказ, когда у ЦЕЛИ нет строк инъекции | сделано, и ШИРЕ заказа: арм пять, а не три | `backend/internal/pipeline/injectionpreflight.go:96`=`func (r *Runner) checkInjectionTexts` + вызов `backend/internal/pipeline/runner.go:389`=`if err := r.checkInjectionTexts(logger); err != nil {` рядом с соседним отказом `:364`=`if forWrite && r.Pipeline.Gates.Terminology.Enabled && r.pack == nil {`; пин `TestABankItsTargetCannotStateRefusesBeforeItIsBought` (6 подтестов) |
|
||||
| §4.1 громкий отказ, когда у ЦЕЛИ нет строк инъекции | сделано, и ШИРЕ заказа: арм пять, а не три | `backend/internal/pipeline/injectionpreflight.go:96`=`func (r *Runner) checkInjectionTexts` + вызов `backend/internal/pipeline/runner.go:401`=`if err := r.checkInjectionTexts(logger); err != nil {` рядом с соседним отказом `:364`=`if forWrite && r.Pipeline.Gates.Terminology.Enabled && r.pack == nil {`; пин `TestABankItsTargetCannotStateRefusesBeforeItIsBought` (6 подтестов) |
|
||||
| §4.1 предикат ПОЛНОТЫ, а не заголовка | сделано | `lang.InjectionTexts.MissingKeys` / `Authored` / `GenderKeyGaps` + реестр `roleInjectionKeys` (`chunkrun.go`); пины `TestTheInjectionKeysAreOneVocabulary`, `TestAPartialInjectionSetIsVisibleToTheGuard` |
|
||||
| §4.2 отказ роли перестаёт быть передачей (путь **а**) | сделано; сентинел НЕ тронут | `terminology.go` — ветвь `declined` рядом с `isNoDst`; пин `TestAProseDeclineLandsInTheDeclineBucketAndNotInTheBank` |
|
||||
| §4.2 мусор разведён с отказом по корзинам | сделано | ветвь `hasLetter` + счётчики `NoLetters`/`DeclinedByPhrase`; пины `TestARenderingWithNoLettersReadsAsUnansweredNotAsCanon` (парсер) и `TestADeclineAndGarbageLandInDifferentBuckets` (сквозной, все три исхода в одном ответе) |
|
||||
|
|
@ -2431,7 +2431,7 @@ decision»).
|
|||
2. `gates.banknote` — черновик спрашивается о таблице терминов;
|
||||
3. `book.yaml glossary_seed` — сид;
|
||||
4. **`<book_id>.mined-delta.yaml`** — подписанные владельцем строки. ⚠ Путь ДЕРИВИРУЕТСЯ (`backend/internal/config/book.go:210`=`b.MinedDelta = filepath.Join(dir, b.BookID+MinedDeltaSuffix)`), поэтому `book.MinedDelta != ""` истинно ВСЕГДА и как арм негоден — проверяется НАЛИЧИЕ файла (`decisionFilePresent`);
|
||||
5. **авто-банк, оставленный в сторе предыдущим прогоном** (`backend/internal/pipeline/mining.go:723`=`func (r *Runner) loadAutoBank`). Гейт — ран-локальный конфиг книги (`D39.126` п.2а), а строки в сторе — нет: книга с выключенными гейтами, без сида и с банком от прошлого прогона инжектит так же молча.
|
||||
5. **авто-банк, оставленный в сторе предыдущим прогоном** (`backend/internal/pipeline/mining.go:754`=`func (r *Runner) loadAutoBank`). Гейт — ран-локальный конфиг книги (`D39.126` п.2а), а строки в сторе — нет: книга с выключенными гейтами, без сида и с банком от прошлого прогона инжектит так же молча.
|
||||
|
||||
Армы спрашиваются в порядке цены (`backend/internal/pipeline/injectionpreflight.go:40`=`func (r *Runner) bankRowsReachTheWire`): два поля конфига → один `stat` → чтение стора, и стор трогается только когда всё дешёвое сказало «нет». **Ошибка чтения дверью не считается** — WARN и «строк нет», по норме «предупреждение о деньгах не выдумывается из ошибки».
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ excision_suspect / ok) 1:1, не изобретать заново. Метрик
|
|||
`configs/models.yaml` (модели/цены/таймауты, с датой проверки). В конфиг ядра входят: состав/порядок стадий,
|
||||
роль→модель, версии промптов, пороги гейтов, **режим инъекции глоссария (selective | full_prefix)** (Р5
|
||||
требует обе схемы), токен-бюджеты сборки контекста (инъекция, STM, overlap), лимит регенераций до эскалации,
|
||||
**именованные эскалационные цепочки** (список моделей; ⚠ **испр. 10.09:** какую цепочку берёт прогон, решает ЗАГРУЗКА по `content_policy`, а не раннер — `backend/internal/config/pipeline.go:529`=`LOAD, not by the runner` (⚠ испр. 17.09: было :502); раннер лишь исполняет уже разрешённый хоп, `backend/internal/pipeline/escalation.go:125`=`st.ResolvedHop`. Слово «channel» отставлено — `backend/internal/config/pipeline.go:266`=`LegacyChannel is the RETIRED`), fan-out N для
|
||||
**именованные эскалационные цепочки** (список моделей; ⚠ **испр. 10.09:** какую цепочку берёт прогон, решает ЗАГРУЗКА по `content_policy`, а не раннер — `backend/internal/config/pipeline.go:597`=`LOAD, not by the runner` (⚠ испр. 17.09: было :502); раннер лишь исполняет уже разрешённый хоп, `backend/internal/pipeline/escalation.go:125`=`st.ResolvedHop`. Слово «channel» отставлено — `backend/internal/config/pipeline.go:332`=`LegacyChannel is the RETIRED`), fan-out N для
|
||||
C2, cache TTL per-стадия. В models.yaml: цены (+cache write/read), профиль таймаутов/ретраев per-модель,
|
||||
`extra_body`. Зашито в раннер: циклы по главам/чанкам, ветвление по гейтам, механика эскалации/ретраев,
|
||||
семантика «эскалация → re-gate → флаг» (диаграмма pipeline.puml перегейтовку не рисует — реализую re-gate
|
||||
|
|
@ -103,7 +103,7 @@ C2, cache TTL per-стадия. В models.yaml: цены (+cache write/read), п
|
|||
|
||||
## 5. [НУЖНО РЕШЕНИЕ] — СНЯТО, всё развязано
|
||||
|
||||
> ⚠ **§5 СНЯТ — а код на него ещё ссылается, поэтому вот куда он уехал** (заглушка, испр. 10.09, по образцу заглушки §2 выше). Три не-тестовых сайта продолжают адресовать эту секцию: `backend/internal/config/pipeline.go:498`=`a defect flips the chunk to flagged` (⚠ испр. 17.09: было :471) (формула премиум-бюджета — см. `01-decisions.md`, там же сказано, что в коде её НЕТ и почему), `backend/internal/llm/llm.go:106`=`JSONOnly bool` (провайдерский стриминг — отнесён к Ф2, §3 этого дока), `backend/internal/pipeline/render.go:34`=`explicit re-translation, not a silent cache miss` (§3.4 того же дока). ⇒ читающий из кода приходит сюда и находит указатель, а не пустоту.
|
||||
> ⚠ **§5 СНЯТ — а код на него ещё ссылается, поэтому вот куда он уехал** (заглушка, испр. 10.09, по образцу заглушки §2 выше). Три не-тестовых сайта продолжают адресовать эту секцию: `backend/internal/config/pipeline.go:566`=`a defect flips the chunk to flagged` (⚠ испр. 17.09: было :471) (формула премиум-бюджета — см. `01-decisions.md`, там же сказано, что в коде её НЕТ и почему), `backend/internal/llm/llm.go:106`=`JSONOnly bool` (провайдерский стриминг — отнесён к Ф2, §3 этого дока), `backend/internal/pipeline/render.go:34`=`explicit re-translation, not a silent cache miss` (§3.4 того же дока). ⇒ читающий из кода приходит сюда и находит указатель, а не пустоту.
|
||||
|
||||
Пять вопросов 04.07 закрыты, карта развязок — в баннере вверху (тела D11/D14/D19/D23 — в слайсе `../archive/architecture/05-decisions-D1-D38.md`); пятый, не попавший в карту, — пункты оркестратору (фазовые пометки диаграмм, владелец задачи cache-hit), отработан арх-ресетом D39. Формулировки вопросов — `../archive/PROGRESS-2026-07-04-10.md`.
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -129,7 +129,7 @@ Go-гейт стоит на v1 без поглощения кавычек: `back
|
|||
|
||||
### [CONFIRMED_LOST] (4) Golden-счётчики голоса (дописка 41): в capture.golden voice-счётчиков нет
|
||||
|
||||
Подтверждено отсутствие: `grep -c -i voice backend/internal/pipeline/testdata/golden/capture.golden` = 0 (ни одного вхождения); в testdata/golden/pipeline.yaml ключа `voice:` нет (grep пуст) — гейт opt-in OFF по умолчанию (`backend/internal/config/pipeline.go:315`=`type VoiceGate struct` — ⚠ испр. 16.09: было :279-281), фикстура его не включает, значит golden не пинит ни n_voice_flags/voice_detail, ни VoiceFlags/SpoilerLeaks (quality.go:269-278, 436 — счётчики существуют в коде, но в golden-контур не заведены). Хвост D39.58 реален и жив.
|
||||
Подтверждено отсутствие: `grep -c -i voice backend/internal/pipeline/testdata/golden/capture.golden` = 0 (ни одного вхождения); в testdata/golden/pipeline.yaml ключа `voice:` нет (grep пуст) — гейт opt-in OFF по умолчанию (`backend/internal/config/pipeline.go:381`=`type VoiceGate struct` — ⚠ испр. 16.09: было :279-281), фикстура его не включает, значит golden не пинит ни n_voice_flags/voice_detail, ни VoiceFlags/SpoilerLeaks (quality.go:269-278, 436 — счётчики существуют в коде, но в golden-контур не заведены). Хвост D39.58 реален и жив.
|
||||
|
||||
|
||||
### [CONFIRMED_LOST] (5) Слот инъекции голоса (дописка 24): инъекционная половина построена условно и НЕ включена, оба провода
|
||||
|
|
@ -174,7 +174,7 @@ Go-гейт стоит на v1 без поглощения кавычек: `back
|
|||
|
||||
### Б-106 — тело строки 106 на 09.08.2026
|
||||
|
||||
**Слой 3 НЕ достроен: контракт редактора = full-regen, а целевой — узкие мандаты + ДИФФЫ.** `docs/architecture/09-target-architecture.md:111`=`узкие мандаты + диффы` дословно: «research/07 предписывает узкие мандаты + диффы, а не полную перегенерацию — сейчас ровно наоборот (4 мандата, full-regen), что и породило хвост инверсий» (⚠ прежний голый якорь `:121-126` съехал на слой 5/6); целевой контракт — редактор правит anchored search/replace-спанами с детерминированным Go-apply (ограниченный blast-radius, дешевле, аудируемо, структурно omission-safe). Пак-16 построил петлю РЕМОНТА (починка флагнутого спана постфактум), а не diff-контракт роли ⇒ это разные вещи. **Строки не было ни одной** — дыра учёта, найденная сверкой 02.08 (грепы `diff`/`мандат`/`span` по бэклогу = 0). Смежное: арм Q4b «diff-fidelity+style редактор» (`exp15:108`) не прогонялся НИ РАЗУ, хотя трек B объявлен завершённым. **ЭМПИРИКА ПОЛУЧЕНА (D39.108, экспы 19/20):** дифф-контракт механически исправен (комплаенс 0.966 на боевой единице, аппликатор 15/15), но по замороженному гейту Q4b диффы ОТЛОЖЕНЫ (fidelity-trap 11/12; дороже full-regen на dspro×ru ×2.5–2.9 при невскрытой причине; D21.4/D21.10 закрыты явно). **Эксп-21 (D39.117):** полный regen выигрывает у точечного ремонта (`C2/A_law` −3.75 Holm 0.0006) — довод против диффов, НЕ опровержение: чинил дешёвый фиксер по предложению, а не сильный редактор узким мандатом; гейт «перепроверить до стройки» в силе, приоритет понижен
|
||||
**Слой 3 НЕ достроен: контракт редактора = full-regen, а целевой — узкие мандаты + ДИФФЫ.** `docs/architecture/09-target-architecture.md:115`=`узкие мандаты + диффы` дословно: «research/07 предписывает узкие мандаты + диффы, а не полную перегенерацию — сейчас ровно наоборот (4 мандата, full-regen), что и породило хвост инверсий» (⚠ прежний голый якорь `:121-126` съехал на слой 5/6); целевой контракт — редактор правит anchored search/replace-спанами с детерминированным Go-apply (ограниченный blast-radius, дешевле, аудируемо, структурно omission-safe). Пак-16 построил петлю РЕМОНТА (починка флагнутого спана постфактум), а не diff-контракт роли ⇒ это разные вещи. **Строки не было ни одной** — дыра учёта, найденная сверкой 02.08 (грепы `diff`/`мандат`/`span` по бэклогу = 0). Смежное: арм Q4b «diff-fidelity+style редактор» (`exp15:108`) не прогонялся НИ РАЗУ, хотя трек B объявлен завершённым. **ЭМПИРИКА ПОЛУЧЕНА (D39.108, экспы 19/20):** дифф-контракт механически исправен (комплаенс 0.966 на боевой единице, аппликатор 15/15), но по замороженному гейту Q4b диффы ОТЛОЖЕНЫ (fidelity-trap 11/12; дороже full-regen на dspro×ru ×2.5–2.9 при невскрытой причине; D21.4/D21.10 закрыты явно). **Эксп-21 (D39.117):** полный regen выигрывает у точечного ремонта (`C2/A_law` −3.75 Holm 0.0006) — довод против диффов, НЕ опровержение: чинил дешёвый фиксер по предложению, а не сильный редактор узким мандатом; гейт «перепроверить до стройки» в силе, приоритет понижен
|
||||
|
||||
### Б-108 — тело строки 108 на 09.08.2026
|
||||
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ cmp-сверка обязательна (D39.138 п.3).
|
|||
(`platform/internal/books/books.go:118-121`=`books: the intake form is not usable`) и равенство `source == target` не проверяет никто, а
|
||||
пар-промпты в репозитории есть ТОЛЬКО для `zh-ru`; отсутствие промпта пары — жёсткая ошибка
|
||||
конфигурации, не деградация («no prompt for pair %q role %q … never silently substitute another
|
||||
pair's conventions», `backend/internal/config/pipeline.go:1065`=`no prompt for pair` — ⚠ испр. 17.09: было :1038, ранее :952-956). До 0.3.0 книга в
|
||||
pair's conventions», `backend/internal/config/pipeline.go:1169`=`no prompt for pair` — ⚠ испр. 17.09: было :1038, ранее :952-956). До 0.3.0 книга в
|
||||
неподдерживаемой паре принималась, ложилась на диск, разбиралась, проводила пользователя через
|
||||
денежный экран — и умирала на старте прогона без причины. Отсюда `Capabilities.language_pairs[]`
|
||||
со статусом и код отказа на интейке (`errors[].code: unsupported_pair`).
|
||||
|
|
@ -305,7 +305,7 @@ SQL и до 0.3.0 не отдавалась: `b.chapter_count - (select count(*)
|
|||
|
||||
Флагнутый юнит легально приходит С ТЕКСТОМ в двух случаях: косметическая зачистка санитайзера («the
|
||||
chunk is NOT lost — the cleaned text is committed as the export», `backend/internal/pipeline/disposition.go:160`=`the cleaned text is committed as the export` — ⚠ испр. 16.09: было :96-104) и
|
||||
c-lite member-drop (`pipeline/export.go:203-207`=`if exp.GhostRows > 0`). Поэтому состояние выводится из ПАРЫ (вердикт +
|
||||
c-lite member-drop (`backend/internal/pipeline/export.go:203-207`=`if exp.GhostRows > 0`). Поэтому состояние выводится из ПАРЫ (вердикт +
|
||||
наличие финального текста): флаг+текст → `translated` с замечанием; флаг+пусто → `withheld`.
|
||||
|
||||
Причина флага при этом ПРОИЗВОЛЬНА («единственный легальный случай» снято ревью round-2): при c-lite
|
||||
|
|
@ -356,7 +356,7 @@ drop юнит несёт причину ПЕРВОГО выпавшего чле
|
|||
|
||||
**Фантом `auto` в провенансе убран ещё в 0.2.0:** комментарий схемы движка (`migrate.go:193`:
|
||||
`seed|ruby|auto`) устарел — `"auto"` пишет СТАТУС, не провенанс (`backend/internal/membank/memseed.go:424`=`Status: "auto", Source: "ruby"` — ⚠ испр. 16.09: было :328:
|
||||
`Status:"auto", Source:"ruby"`), майнинг ставит `mined` (`backend/internal/pipeline/mining.go:763`=`e.Source = "mined"` — ⚠ испр. 16.09: было :424).
|
||||
`Status:"auto", Source:"ruby"`), майнинг ставит `mined` (`backend/internal/pipeline/mining.go:794`=`e.Source = "mined"` — ⚠ испр. 16.09: было :424).
|
||||
|
||||
**Ложный друг `source`.** У движка колонка `source` — это ПРОВЕНАНС. Поэтому в контракте провенанс
|
||||
зовётся `origin`, формы термина — `src`/`dst`, а имя `source` в схеме банка не используется вовсе.
|
||||
|
|
@ -372,7 +372,7 @@ drop юнит несёт причину ПЕРВОГО выпавшего чле
|
|||
|
||||
### 2.9. Подпись — набор решений — ✓ выведено
|
||||
|
||||
Конвейер заменяет банк целиком (`store/migrate.go:169-170`=`aggregation/classification live in the pipeline`), поэтому `PATCH /term/{id}` молча не
|
||||
Конвейер заменяет банк целиком (`backend/internal/store/migrate.go:169-170`=`aggregation/classification live in the pipeline`), поэтому `PATCH /term/{id}` молча не
|
||||
работает. Механика дословно: «for EACH term either promote it into the mined-delta file OR decline it
|
||||
in the mined-rejects file, then resume» (`backend/internal/pipeline/mining.go:58`=`func (r *Runner) runBankMiningStop` — ⚠ испр. 16.09: было :81,243; ⚠ фраза «the stop clears once
|
||||
every proposed term is promoted or rejected» ОПРОКИНУТА D39.144 — движок авто-продолжает с
|
||||
|
|
@ -1505,8 +1505,8 @@ focus»), то есть цена платится на горячем пути
|
|||
### G. Draft-only конвейер (PD-202) — ОТВЕЧАЮ: ДА, начерновленная глава «сделана»; правлю канон
|
||||
|
||||
Проверено чтением обеих зон, и цена выше заявленной. У движка деплой без второго прохода — не
|
||||
экзотика: разбиение выводится из РОЛЕЙ стадий (`pipeline/waverun.go:43-53`=`non-translator (editor/other) stage`), конфиг требует лишь
|
||||
«хотя бы одна стадия» (`backend/internal/config/pipeline.go:953`=`at least one stage is required` — ⚠ испр. 17.09: было :926, ранее :841), ветка живая и покрыта тестом
|
||||
экзотика: разбиение выводится из РОЛЕЙ стадий (`backend/internal/pipeline/waverun.go:43-53`=`non-translator (editor/other) stage`), конфиг требует лишь
|
||||
«хотя бы одна стадия» (`backend/internal/config/pipeline.go:1035`=`at least one stage is required` — ⚠ испр. 17.09: было :926, ранее :841), ветка живая и покрыта тестом
|
||||
(`contractblockers_test.go:115-136`); в репозитории такого конфига пока нет, но выбирает его
|
||||
оператор, и платформа шаблон не читает. У платформы `units_done` — жёстко второй проход
|
||||
(`pgstore/sink.go:252-263`, `readmodel.go:200-208`).
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
- **Потолки — wiring, не семантика:** `Ceilings` намеренно исключены из `BriefHash` («Wiring fields (paths, ceilings, db) deliberately excluded», `backend/internal/config/book.go:345`=`Wiring fields (paths, ceilings, db) deliberately excluded`; канон — `backend/internal/config/book.go:369`=`canon := struct {`) ⇒ смена ДЕНЕЖНОГО потолка не двигает ни снапшот, ни ре-билл (D39.110 п.2б). ⚠ Верно ровно про ДЕНЬГИ: потолок СЕГМЕНТАЦИИ `edit_ceiling_out` в снапшот ВХОДИТ и меняет границы чанков (`backend/internal/pipeline/snapshot.go:34`=`EditCeilingOut int`).
|
||||
- **`status --json` отдаёт фигуры платформе:** `committed_usd`, `reserved_usd`, `book_ceiling_usd`, `ceiling_pct` = 100·(committed+reserved)/book_ceiling (`backend/internal/pipeline/status.go:342`=`book_ceiling_usd,omitempty`; арифметика `ceiling_pct` — `backend/internal/pipeline/status.go:949`=`100 * (committed + reserved)`). Дневной фигуры в status нет (PD-157 — `platform/docs/DEFECT_REGISTER.md`, греп `PD-157`).
|
||||
- **Леджер = НИЖНЯЯ граница; строка 78 снята с трекера 10.09, но её ЖИВОЙ ОСТАТОК несёт строка 377.** ⛔ **Испр. 10.09 — прежняя редакция этого пункта, написанная в тот же день, была НЕВЕРНА, и ошибка моя.** Она утверждала, будто оплаченный `2xx` с нечитаемым телом «прежде в `request_log` не попадал» и что это починил пак оборванных вызовов. Замер: ветвь `BilledDecodeError` писала свою строку с пометкой оценки ещё до пака — на `3f05fab^` это `stagerun.go:629`, введено коммитом `2f91b04` **24.07**, а пак этой ветви не касался вовсе (хитов `Estimated` в его диффе по `stagerun.go` — **0**). И носитель я процитировал ЧУЖОЙ: `backend/internal/pipeline/cutcall.go:133`=`rl := r.baseRequestLog(c.stage, c.chunk` обслуживает `*llm.AttemptCutError` (`backend/internal/pipeline/stagerun.go:745`=`var cut *llm.AttemptCutError` — ⚠ испр. 17.09: было :802, ранее :741), а речь шла о `*llm.BilledDecodeError` (`stagerun.go:709`) — это разные классы, и второй до `cutcall.go` не доходит. **Что пак действительно купил:** строку `request_log` за вызов, который оборвали МЫ (прежде он падал в ветвь «ничего не куплено» и получал $0-строку) — вот это `cutcall.go:133`. **Что остаётся правдой:** леджер — нижняя граница, потому что обрыв, за которым ретрай УСПЕЛ, исчезает бесследно (строка **377**). Живой замер `D39.86` — 3 вызова из 14, неизвестность $0.015111 при леджере $0.114378.
|
||||
- **ГРАНИЦА ДЕНЕГ ЗА ОБОРВАННЫЙ НАМИ ВЫЗОВ — ФАКТ ДОСТАВКИ, а не статус-строка** (пак строки 360, акт `D39.232`; слово владельца — `D39.230`). Деньги берутся, только когда провайдер подтвердил запрос ответным объектом: `backend/internal/llm/attemptcut.go:221`=`Billable: answered && tr.afterHeaders()`. Наш собственный дедлайн даёт свой класс `attempt_timeout` без ретрая; дедлайн вычисляется ИЗ БЮДЖЕТА вызова, а не назначается (`backend/internal/llm/attemptcut.go:269`=`func (p RetryProfile) deriveDeadline`), так что эскалация, удвоившая `max_tokens`, удваивает и время. Оплаченный обрыв получает чекпойнт, и резюм его НЕ перепокупает. ⛔ Пометка «это оценка» — УСЛОВИЕ слова владельца (`D39.230` п.1) — сегодня в движке живёт ТРЕМЯ носителями (колонка `Estimated` в `request_log` — `backend/internal/store/requestlog.go:41`=`Estimated marks a row whose CostUSD`; пара `estimated_rows`/`estimated_usd` в `status --json` — `backend/internal/pipeline/status.go:911`=`Re-payment projection (spec`; печать оператору — `backend/cmd/tmctl/render.go:402`=`the degraded/err tail`), но НАРУЖУ не выходит ни одним каналом шва: строка **382**. ⚠ Формулировка испр. 10.09 — прежняя («живёт только в `status --json`») звала следующего чинить пометку, которая уже есть.
|
||||
- **ГРАНИЦА ДЕНЕГ ЗА ОБОРВАННЫЙ НАМИ ВЫЗОВ — ФАКТ ДОСТАВКИ, а не статус-строка** (пак строки 360, акт `D39.232`; слово владельца — `D39.230`). Деньги берутся, только когда провайдер подтвердил запрос ответным объектом: `backend/internal/llm/attemptcut.go:221`=`Billable: answered && tr.afterHeaders()`. Наш собственный дедлайн даёт свой класс `attempt_timeout` без ретрая; дедлайн вычисляется ИЗ БЮДЖЕТА вызова, а не назначается (`backend/internal/llm/attemptcut.go:269`=`func (p RetryProfile) deriveDeadline`), так что эскалация, удвоившая `max_tokens`, удваивает и время. Оплаченный обрыв получает чекпойнт, и резюм его НЕ перепокупает. ⛔ Пометка «это оценка» — УСЛОВИЕ слова владельца (`D39.230` п.1) — сегодня в движке живёт ТРЕМЯ носителями (колонка `Estimated` в `request_log` — `backend/internal/store/requestlog.go:41`=`Estimated marks a row whose CostUSD`; пара `estimated_rows`/`estimated_usd` в `status --json` — `backend/internal/pipeline/status.go:911`=`Re-payment projection (spec`; печать оператору — `backend/cmd/tmctl/render.go:432`=`the degraded/err tail`), но НАРУЖУ не выходит ни одним каналом шва: строка **382**. ⚠ Формулировка испр. 10.09 — прежняя («живёт только в `status --json`») звала следующего чинить пометку, которая уже есть.
|
||||
|
||||
- **Согласие на пере-оплату — ДВИЖКОВЫЙ гейт**. Прогон, который пере-покупает уже оплаченные юниты дороже порога, ОСТАНАВЛИВАЕТСЯ и требует явного согласия. Порог по умолчанию ратифицирован D20.2-Q2: `min($0.50, 5% × ProjectedBookUSD)`. Носитель — `backend/internal/pipeline/rebill.go`, греп `rebillConsentThreshold`; единственная ручка книги — `rebill_consent_usd` (валидатор `backend/internal/config/book.go`, греп `rebill_consent_usd`; 0 = ратифицированный дефолт). ⚠ Порог считается БЕЗ контура банк-ролей (D39.182 §3), то есть срабатывает позже, чем подсказывает полная проекция.
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
*Прецеденты:* потолок аргументом (D39.110 п.2б → `--ceiling-usd`, D39.122) · `--verify-bank`
|
||||
флагом (`platform/internal/runner/engine.go:116`=`func TranslateArgs(workdir string, verifyBank bool`) · дефолт `project_db` по конвенции каталога
|
||||
(`backend/internal/config/book.go:200`=`b.ProjectDB = filepath.Join(dir, b.BookID+".db")`) · конвенционное опциональное чтение `.auto-bank.yaml`
|
||||
(`backend/internal/pipeline/mining.go:703`=`.auto-bank.yaml`).
|
||||
(`backend/internal/pipeline/mining.go:734`=`.auto-bank.yaml`).
|
||||
|
||||
2. **Посреди прогона внутрь идёт ТОЛЬКО сигнал.** `SIGTERM` = «дочти чанк и отпусти лок» — ⚠ **это ратифицированная ЦЕЛЬ, а не сегодняшнее дерево (пометка 10.09).** Владелец ратифицировал две остановки (`D39.234` п.1а): первый сигнал — мягкий, он и означает «дочти и отпусти». В КОДЕ его ещё нет: `backend/cmd/tmctl/main.go:208`=`signal.NotifyContext(context.Background()` — ⚠ испр. 16.09: было :207 (пустая строка) отменяет контекст прогона, летящий вызов рвётся, книжится по оценке и метится `cancelled`. ⇒ норму НЕ переписывать под дерево, дерево догоняет норму; носитель работы — строка бэклога **381**, где этот адрес назван третьим. Всё
|
||||
остальное — на границах процессов. Арбитр — эксклюзивный flock проекта на всю жизнь прогона
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
4. **Незнакомый флаг = громкий отказ при спавне.** Сегодня это так по устройству разбора аргументов
|
||||
(`backend/cmd/tmctl/invocation.go:128`=`flag.NewFlagSet(cmd, flag.ContinueOnError)`); зафиксировать законом, а не полагаться на случайность.
|
||||
|
||||
5. **Глагол зовётся ТЕМ ЖЕ пиннутым бинарём, что и возобновляемая попытка** (`runs/spawn.go:250-258`=`engineBinary is the path an attempt is PINNED to`,
|
||||
5. **Глагол зовётся ТЕМ ЖЕ пиннутым бинарём, что и возобновляемая попытка** (`platform/internal/runs/spawn.go:250-258`=`engineBinary is the path an attempt is PINNED to`,
|
||||
строка бэклога 139). Иначе файл, записанный новым бинарём, читается старым — а при нестрогом
|
||||
загрузчике сида (строка **212**) новое поле теряется МОЛЧА (⚠ **адрес испр. 10.09: строки 212 в живом трекере НЕТ** — она закрыта; факт оставлен как довод, номер снят, чтобы не звать читателя в пустоту).
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -5271,9 +5271,9 @@ user-сообщения» на глаз. 2 436 токенов на 7 525 зна
|
|||
|
||||
✅ **ДЕФЕКТ ДВИЖКА УЖЕ ЗАКРЫТ, И Я ЭТО ПРОВЕРИЛ КОДОМ, А НЕ ПРЕДПОЛОЖИЛ.** Лендинг `7d0c6f2`
|
||||
(28.08) ввёл ось `Capability.SystemMessages`: у провайдера `gemini` стоит
|
||||
`backend/configs/models.yaml:137`=`system_messages: single`, адаптер склеивает ВЕДУЩИЙ system-ран в
|
||||
`backend/configs/models.yaml:183`=`system_messages: single`, адаптер склеивает ВЕДУЩИЙ system-ран в
|
||||
одно сообщение и громко падает на системном ходе после не-системного
|
||||
(`backend/internal/llm/httpllm.go:528`=`func toOpenAIMessages`), инвариант запинен тестом
|
||||
(`backend/internal/llm/httpllm.go:766`=`func toOpenAIMessages`), инвариант запинен тестом
|
||||
(`backend/internal/llm/systemmessages_test.go:78`=`TestSystemMessagesSingleCarriesTheInjection`).
|
||||
⚠ Первая редакция ЭТОГО ЖЕ абзаца, написанная час назад, объявляла дефект живым и слала пинг в
|
||||
бэкенд — она стояла на строке `00-provider-quirks.md:158`, устаревшей на один день.
|
||||
|
|
@ -7786,7 +7786,7 @@ $0.040093 — расхождение 0.0%). Значит прайс-таблиц
|
|||
|
||||
**Что остаётся верным после правки:** редакторская стадия покупает **беглость и термин**; ось
|
||||
верности она не двигает; и **прибора этой оси у нас по-прежнему нет** — панель объявлена слепой к
|
||||
ней (`23-editor-tier.md:6056`=`оси ВЕРНОСТИ владельца`). Утверждение «мы измеряем половину цели»
|
||||
ней (`docs/experiments/23-editor-tier.md:6057`=`оси ВЕРНОСТИ владельца`). Утверждение «мы измеряем половину цели»
|
||||
устояло; утверждение «за вторую половину мы платим» — снято.
|
||||
|
||||
**Класс моей ошибки:** «не покупает» прочитано как «платит» — усиление вывода в сторону тревоги.
|
||||
|
|
@ -8465,6 +8465,6 @@ sd(log R̂(low₂) − log R̂(low₁)) = 1.493 по n=19 ⇒ σ = 1.493/√
|
|||
|
||||
⛔ **И существеннее адресов: претензия тела «носитель решения врёт прямо сейчас» (про арм-конфиги) ЗАКРЫТА — носители ИСПРАВЛЕНЫ.**
|
||||
Обоснования «×2 дешевле glm» в дереве больше нет ни в одном из двух файлов; на его месте пере-пин цен `D39.137` п.4:
|
||||
`backend/configs/pipeline-c1.yaml:97`=`ПЕРЕВЁРНУТА пере-пином цен` и `backend/configs/pipeline-arm-glm.yaml:6`=`ПЕРЕВЁРНУТА пере-пином цен`
|
||||
`backend/configs/pipeline-c1.yaml:99`=`ПЕРЕВЁРНУТА пере-пином цен` и `backend/configs/pipeline-arm-glm.yaml:6`=`ПЕРЕВЁРНУТА пере-пином цен`
|
||||
— «в ПИК dspro дороже glm ×1.26, офф-пик дешевле ×1.59». Контроль: «дешевле» встречается в каждом файле РОВНО ОДИН раз,
|
||||
и оба раза — про пере-пин; «×2» — ноль вхождений в обоих. ⇒ читающий тело НЕ должен заводить по этой претензии работу.
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
Контрпример проверен исполнением: две книги различаются персонажем в предыдущей главе; следующая начинается одинаковым «终于答应了» — «наконец согласился/согласилась». Реальный `TranslateBook` с текущими zh→ru промптами и подставным провайдером дал разные запросы предыдущих единиц и побайтно одинаковые запросы текущих переводчика и редактора. Условия: пустой одинаковый банк, майнинг выключен, банкнота включена; две главы и две редакторские единицы на вариант. Это проверка доступности информации; частоту неправильных переводов живой модели она не устанавливает. Артефакт и воспроизведение — в конце документа.
|
||||
|
||||
Отрицательные результаты carryover не закрывают весь класс: в exp15 широкое чтение, lookahead и состояние сцены остались неисполненными (`docs/experiments/15-segmentation-empirics.md:489`=`не исполнены (бюджет/приоритет`). Сам target-architecture ограничивает перенос результатов классом исследованных книг (`docs/architecture/09-target-architecture.md:138`=`НИКОГДА не переносится в продукт`). Работа над структурой глав полезна, но она отвечает на другой вопрос.
|
||||
Отрицательные результаты carryover не закрывают весь класс: в exp15 широкое чтение, lookahead и состояние сцены остались неисполненными (`docs/experiments/15-segmentation-empirics.md:489`=`не исполнены (бюджет/приоритет`). Сам target-architecture ограничивает перенос результатов классом исследованных книг (`docs/architecture/09-target-architecture.md:142`=`НИКОГДА не переносится в продукт`). Работа над структурой глав полезна, но она отвечает на другой вопрос.
|
||||
|
||||
**Коррекция:** проверить зависимости через границы редакторских единиц: субъект, адресат, намеренная неоднозначность, смена регистра, позднее раскрытие смысла термина. Сначала сравнить текущий вход с минимальным необходимым исходным контекстом; затем выбирать окно, поиск исходных фрагментов или состояние сцены. Не начинать со строительства универсальных summaries/графа. В строке 80 бэклога (`docs/PROGRESS.md:153`) уточнить: ссылка на исходник проверяется детерминированно, её семантическое толкование — нет. Требование безошибочного детерминированного толкования заранее заблокирует исследование этой задачи.
|
||||
|
||||
|
|
|
|||
|
|
@ -1646,10 +1646,10 @@ D39.50 (просьба владельца против «до него kwic не
|
|||
|
||||
§П3 утверждает: «Исхода движка „это не термин“ нет и не вводится. Класс отказ-сигналов закрыт D39.102 п.2». **Это верно
|
||||
про НОТУ и неверно про ДЕРЕВО.** В боевом проводе zh-ru отказ-сигнал жив и приглашается самим промтом:
|
||||
`backend/prompts/zh-ru/terminologist.md:36`=`не можешь выбрать перевод уверенно` («верни ⟦TM-NO-DST⟧… это нормальный»),
|
||||
`backend/prompts/zh-ru/terminologist.md:32`=`не можешь выбрать перевод уверенно` («верни ⟦TM-NO-DST⟧… это нормальный»),
|
||||
парсер ждёт его вместе с искажёнными формами (`backend/internal/terminology/terminology.go:694`=`const NoDst = "⟦TM-NO-DST⟧"`,
|
||||
`backend/internal/terminology/terminology.go:1248`=`func isNoDst`), а счёт печатается прогоном
|
||||
(`backend/internal/pipeline/terminologist.go:649`=`"declined", res.Declined`).
|
||||
(`backend/internal/pipeline/terminologist.go:806`=`"declined", res.Declined`).
|
||||
|
||||
⚠ Различение, без которого поправка читается грубее, чем есть: §П3 прав в том, что у СТРОКИ БАНКА нет исхода «не термин» —
|
||||
отказ роли не становится решением, а превращается в передачу черновика (это сам отчёт и говорит абзацем ниже). Неверно
|
||||
|
|
@ -1691,7 +1691,7 @@ D39.50 (просьба владельца против «до него kwic не
|
|||
номера строк, а в этот итог целятся якоря других доков.
|
||||
|
||||
**Уехал один адрес.** Счёт отказов терминолога печатается на
|
||||
`backend/internal/pipeline/terminologist.go:702`=`"declined", res.Declined` — в теле стоит `:649`. Причина: пак «лестница
|
||||
`backend/internal/pipeline/terminologist.go:806`=`"declined", res.Declined` — в теле стоит `:649`. Причина: пак «лестница
|
||||
попытки» (акт `D39.264`) вынес цикл повторной попытки в `backend/internal/pipeline/attemptladder.go` и сдвинул строки файла.
|
||||
**Утверждение тела при этом верно и не меняется** — отказ-сигнал жив в боевом проводе zh-ru, приглашается промтом роли и
|
||||
считается прогоном; устарел только способ найти строку.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue