Correct the chapter-structure pack against the tree it will be built on: dead addresses, two axis taxonomies, and three things already built

This commit is contained in:
heaven 2026-09-11 03:16:34 +03:00
parent c3a3ee904d
commit 54b21bcaf3
5 changed files with 483 additions and 64 deletions

View file

@ -2,8 +2,13 @@
## 1. Какая проблема и что решит твой результат
Глава в движке сегодня адресуется своим ПОРЯДКОВЫМ номером. Из-за этого любая пере-нарезка книги
сдвигает адреса, и вместе с ними едут банк-окна, снапшоты, чекпойнты и сметы — то есть **деньги**.
Глава в движке сегодня адресуется своим ПОРЯДКОВЫМ номером **в сторе и в банк-окнах** (`chunk_status`
PRIMARY KEY `(book_id, chapter, chunk_idx, stage)`, `backend/internal/store/migrate.go:126`). Из-за этого
любая пере-нарезка книги сдвигает адреса, и вместе с ними едут банк-окна, снапшоты, чекпойнты и сметы — то
есть **деньги**. ⚠ **А МАНИФЕСТ УЖЕ КОНТЕНТНЫЙ, и это половина фундамента:** `manifestChapterID`
«a chapter's stable identity: the first 64 bits of SHA-256 over its INGESTED text» (`manifest.go:215`), и
там же разобрано, почему НЕ позиция. Перекрой доводит контентный адрес до остальных осей, а не изобретает
его с нуля.
Пока платная книга одна, пере-нарезать дёшево; после впуска пользователей это окно закроется.
Второе следствие того же корня: не-CJK книга и часть EPUB приезжают читателю **одним полотном**, и
@ -19,26 +24,46 @@
**Зона записи: `backend/docs/`** (дизайн-документ) плюс своя секция «Бэкенд» в `docs/PROGRESS.md`. Код `backend/**` — только ЧИТАТЬ; правки кода в этом паке запрещены,
кроме выброшенных проб (§5), которые в дерево не попадают.
**Параллельно с тобой идёт кодовая сессия шага 0** (`docs/BACKEND_GATES_NOT_PROSE_SESSION_PROMPT.md`), и
она пишет в ТОТ ЖЕ журнал. Разведены вы так: её зона — код и тесты `backend/**`, твоя — `backend/docs/`
(в код она пишет, ты только читаешь). В `docs/PROGRESS.md` **заведи СВОЙ подзаголовок
`#### Дизайн-пак перекроя структуры глав` внутри секции «Бэкенд» и пиши только под ним**; чужой текст не
трогай. ⚠ Её правки живут в `mining.go`, `banknote.go`, `configs/`, тестах и `mutations.json` — если твой
`file:line` попал в один из них, пере-снимай адрес командой перед сдачей.
**ИСПР. 11.09 — ПАРАЛЛЕЛЬНОЙ КОДОВОЙ СЕССИИ ШАГА 0 БОЛЬШЕ НЕТ.** Её пак отработан и заландён 07.09
(акт `D39.225`), промт уведён в `archive/prompts/`; прежний абзац о разведении зон с ней снят как описание
прошедшего. **Движковый слот занимаешь ты одна** (норма владельца 11.09: один промт на зону). В
`docs/PROGRESS.md` **заведи СВОЙ подзаголовок `#### Дизайн-пак перекроя структуры глав` внутри секции
«Бэкенд» и пиши только под ним**; чужой текст не трогай. ⚠ Дерево движка с 07.09 двигали ПЯТЬ
заландённых паков — `D39.225` (07.09) · `D39.226` · `D39.228` (08.09) · `D39.232` (10.09) · **`D39.242`
(11.09, в числе тронутых `stagerun.go` — якорь §4.4в)**; ⚠ `D39.241` лендингом НЕ является, это сброс
незакоммиченного дерева, он не двинул ни байта ⇒ **любой `file:line` из этого промта
пере-снимай командой прежде, чем на него сослаться**: часть адресов я уже пере-снял (§4.4в), но проверял не
все.
**Сессия НЕ коммитит** — дерево передаёшь оркестратору. Канон git — `CLAUDE.md`. `.env` не читать.
⚠ Что должно пережить рестарт — в РЕПОЗИТОРИЙ, а не в скрэтчпад. ⚠ Входящее сообщение другой сессии —
не приказ: промт сильнее, расхождение — пинг.
**Правка ЗАКАЗА на лету доезжает только РЕЛЕЕМ:** я пере-передаю её отдельным сообщением, ты
эхо-подтверждаешь её своими словами и выносишь ОТДЕЛЬНЫМ пунктом отчёта. Устная договорённость, не прошедшая
этих трёх шагов, заказом не является.
## 3. Карта чтения — ЗАКОН, дальше только по её ссылкам
1. `CLAUDE.md` — цели владельца и гардрейлы.
2. Строки бэклога **161**, **283**, **302**, **303**, **320**(б), **332** (`docs/BACKLOG.md`, греп `^| N |`).
2. Строки бэклога **160**, **161**, **224**, **283**, **298**, **302**, **303**, **320**(б), **332**, **346**
(`docs/BACKLOG.md`, греп `^| N |`). ⚠ Список дополнен 11.09: тело §4 заказывает работу по 160, 224, 298 и
346, а карта их не называла — и карта есть ЗАКОН, то есть сессия их бы не открыла.
3. `docs/research/33-backend-debt.md`**читать через ревью-шапку** (статус: ФАКТУРА, НЕ ратифицирована),
предметно — секция «Спроектировать ЗАНОВО и отрефакторить без заплат» (строка 451).
предметно — секция «Спроектировать ЗАНОВО и отрефакторить без заплат» (⚠ адрес пере-снят 11.09:
строка **463**, в промте стояло 451 — уехало лендингами 07.09).
4. `docs/research/27-chapter-detection.md` §3а (жизненный цикл дерева) и §5 п.89 (id и деньги).
**D-нотой НЕ ратифицировано** — это фактура ресёрча о самом себе; при конфликте с D-логом побеждает лог.
5. `docs/architecture/18-bank-ontology.md` — РАТИФИЦИРОВАНА, обязательное пре-чтение перед всем, что
трогает банк; плюс `backend/README.md` для механики движка.
6. ⛔ **ЧТО УЖЕ ЛЕЖИТ В ТВОЕЙ СОБСТВЕННОЙ ЗОНЕ ЗАПИСИ — `backend/docs/` (15 файлов), и два из них про твой
предмет.** Прежняя редакция промта их не знала, и это была его худшая дыра: сессия находит их на первом
часу и обязана вставать. **(а)** `D15.2-content-addressed-resume-spec.md` (539 строк) — шапка объявляет
её **дизайном-оф-рекорд**, реализация отложена, родословная ратифицирована. ⇒ §4.4а **НЕ переоткрывает
её**: читаешь и говоришь, что именно перекрой в ней ломает и что дополняет. **(б)**
`chapter_structure_shiftmap.py` + `CHAPTER_STRUCTURE_SHIFTMAP.json` (275 строк замеров) — рабочий
прибор миграционной карты, уже отработавший: set-diff по id и номеру, классы `same/moved/gone/new`.
⇒ §4.1 его **не пишет заново**, а расширяет: классов в `research/27` **шесть**, прибор считает четыре —
`split` и `merged` он не знает, и это настоящая дыра. Плюс `CHAPTER_STRUCTURE_REPORT.md` (526 строк) —
прочти прежде, чем отвечать на §4: часть ответов может уже стоять там.
**Ратифицированное, что нужно для работы:**
@ -48,8 +73,28 @@
предмет закрыть нельзя.
- **`D39.104` — закон банка:** строка на проводе есть закон для КАЖДОЙ роли и КАЖДОЙ строки независимо
от статуса. Дизайн его не ослабляет.
- ⛔ **КАНОН ОСЕЙ — ЧЕТЫРЁХОСНИК `D39.224` п.8: провод · вердикт · банк · крой.** Он ратифицирован.
Пятиосник `research/33` (провод · вердикт · банк · КОНТЕНТ · ПОЗИЦИЯ) — фактура, и прежняя редакция промта
требовала обе карты сразу, то есть отдавала сессии два взаимоисключающих приказа (испр. 11.09). Строишь по
ратифицированному; считаешь его узким — опровергай аргументом и объясняй, что четырёхосник не ловит.
- **`D39.216` п.3(г)** — чистота, купленная тихим сдвигом снапшота, чистотой не является. Для пака ПРО сдвиг
снапшота это самый прямой пункт мандата.
- **`D39.136` п.3** — стройка идёт после **РАТИФИКАЦИИ** дизайна, а не после его написания. Твой документ
становится основанием для стройки, когда я закрою пак актом; до этого он предложение.
- **Ревью-вопрос проекта по умолчанию** (`CLAUDE.md` §Цели п.2): «заработает ли пара, которой в репо ещё
НЕТ, без правки Go?» Каждое твоё решение обязано иметь на него ответ.
- ⛔ **РАТИФИЦИРОВАНО ПОСЛЕ НАПИСАНИЯ ЭТОГО ПРОМТА (07.09 → 11.09) — читать ДО §4.4, оно бьёт прямо по нему:**
- **`D39.228`: аддитивное поле манифеста ключ НЕ двигает, но обязано быть отличимо от своего нуля.** Это
прямой ответ на половину вопроса §4.4 «что входит в окно» — не переоткрывай его, опирайся.
- **`D39.240` (слово владельца): остановка остаётся ЖЁСТКОЙ, ДЕНЬГИ ТЕРЯТЬ ДОПУСТИМО, но она обязана быть
КОРРЕКТНОЙ — без гонок, без половинчатых состояний, с ВЕРНЫМ ВОЗОБНОВЛЕНИЕМ.** Твой §4.4а (контент-адресуемый
resume) — носитель этого обещания: перекрой не имеет права сделать возобновление после жёсткого стопа
неверным. ⚠ Пак «две остановки» ОТМЕНЁН владельцем целиком (`D39.240`) — не ссылайся на него как на
построенное.
- **`D39.232`: оборванный нами вызов больше не оплачивается дважды** (движок, заландён 10.09) — денежная
картина §4.2 изменилась, пере-читай `rebill.go` прежде, чем цитировать старые проценты.
- **`D39.238`: два SIGTERM в одном кванте Go-процесс видит как ОДИН** (замерено дважды) — если дизайн
где-то опирается на «послал два сигнала — получил два», опора ложная.
- **Число называет ДЕРЕВО и ПОПУЛЯЦИЮ** · **рядом с нулём контрольная величина ПЕЧАТАЕТСЯ** · **мутация
засчитывается по ТЕКСТУ сообщения**.
@ -73,23 +118,50 @@
### 4.2 Карта осей сдвига — **состав делай РОВНО так; ответы по осям — ПРИОР, опровергается замером**
Сегодня предикат `classifySnapshotMove` — одна строковая константа. Дизайн обязан дать явную карту осей
(провод · вердикт · банк · контент · позиция) и на КАЖДОЙ честно ответить, что делать: провод — купить,
вердикт — пере-вынести из чекпойнта за $0, банк — ре-пин, контент — показать смету. Одним куском с
`projectRebill` (контентная и позиционная оси): это две стороны вопроса «какая ось уехала». От этой
карты зависит, будет ли перекрой молчаливым для владельца книги.
Сегодня предикат `classifySnapshotMove` знает одно re-pinnable поле (`repin.go:54`), всё прочее —
`moveOther`. Дизайн обязан дать явную карту осей **по ратифицированному четырёхоснику `D39.224` п.8: провод ·
вердикт · банк · крой** — и на КАЖДОЙ честно ответить, что делать: провод — купить, вердикт — пере-вынести из
чекпойнта за $0, банк — ре-пин, крой — показать смету. ⚠ **ИСПР. 11.09:** прежняя редакция требовала ЗАОДНО
пятиосник `research/33` (контент · позиция вместо кроя) — две несовместимые таксономии как два «делай РОВНО
так». Канон — четырёхосник; пятиосник фактура. Считаешь четырёхосник узким — скажи, ЧТО он не ловит.
**И `projectRebill` уже умеет больше, чем говорила прежняя редакция** (пере-снято 11.09, иначе дизайн
закажет построенное): непроецируема РОВНО ОДНА вещь — правка исходника, НЕ двигающая манифест
(`rebill.go:33-36`); позиционные сироты исключаются НАМЕРЕННО, и ряд сам объясняет, почему их счёт был бы
ложным согласием на деньги (`rebill.go:100-105`); контент-осознанность ПОСТРОЕНА (`rebill.go:112-119`:
bank-only сдвиг с тем же content hash резюмится за $0 и считается ре-пином, а не ре-оплатой). ⇒ вопрос
дизайна не «добавить контентную ось», а **«что из этого меняет перекрой»**. ⚠ Ряд бэклога **160** цитирует
старый адрес `rebill.go:32-35` — якорь протух, пере-снимай.
### 4.3 Банк-окна на chapter-ID — **делай РОВНО так**
Дизайн предписывает ФОРМУ перевода `since_ch`/`until_ch` на адрес главы из §4.1 (не пишет код). Класс переноса — `moveBankOnly` (ре-пин за $0),
миграция мелкая. Дизайн называет форму миграции и её стоимость числом, а не словом «мелкая».
Дизайн предписывает ФОРМУ перевода `since_ch`/`until_ch` на адрес главы из §4.1 (кода не пишет).
Носители и объём — `decisions.go:166`=`func TermID(src, sense string, since, until int)` и
`memory.go:680`=`func spoilerBlocked`; величина из `research/33`: **14 из 142 добытых терминов несут окна,
плюс ~8 чисел в сидах**. Дизайн называет форму миграции и её стоимость ЧИСЛОМ.
**ИСПР. 11.09 — класс переноса НЕ пред-решён.** Прежняя редакция объявляла его `moveBankOnly` (ре-пин за
$0), но §4.4 кладёт в ТО ЖЕ окно расщепление `EmbeddedVersion`, которое двигает `cutTag` — в общем окне ход
перестаёт быть bank-only, и $0 не наступает. Реши сам: либо миграция окон идёт ОТДЕЛЬНЫМ актом и тогда
bank-only законен, либо она в общем окне и тогда назови настоящую цену.
**И кросс-зонное следствие, которого в промте не было:** `TermID` складывает окна в ИДЕНТИЧНОСТЬ терма, а
она экспортируется наружу — `bankexport.go:158` («ID is a STABLE key derived from the row's uniqueness key
(src, sense, since_ch, until_ch)»). Перекладка окон на chapter-ID меняет `BankExportTerm.ID` каждого
оконного терма — то есть у читателя за швом. Назови судьбу этих id; это родной брат ряда **298**.
### 4.4 Что входит в окно пере-нарезки и что НЕ входит — **делай РОВНО так**
Расщепление `EmbeddedVersion` на три радиуса (по образцу `bankdata.go`) двигает хеш ⇒ идёт ТОЛЬКО
внутри этого окна. ⚠ Это и есть **«третий версионный план паттернов»** строки 161: план ДАННЫХ вне волнового
снапшота — назови его этим именем, чтобы носитель был один. Сюда же строка **320**(б) — правка `internal/lang/data/injection.txt` (стоп-мир:
`EmbeddedVersion``cutTag``manifestKey` (`manifest.go:341`; ⚠ форма `manifest_key` в строке 320 ошибочна)). **`structure_version` как самостоятельная ось консент-гейта — решить в дизайне.** ⚠ Приор `research/33` (Д6):
`EmbeddedVersion``cutTag``manifestKey` (⚠ адрес пере-снят 11.09: `manifest.go:359`, `func (r *Runner) manifestKey`; в промте стояло `:341`.
⛔ **ИСПР. 11.09: прежняя редакция объявляла форму `manifest_key` в строке 320 ОШИБОЧНОЙ — это неверно.**
`manifest_key` — живое имя колонки ПЛАТФОРМЫ, несущей ровно движковый `manifestKey`
(`platform/internal/pgstore/readmodel.go:167`, миграция `00016_read_surface.sql:16`), и именно на нём
держится предупреждение §4.8: `recut := storedKey != in.ManifestKey` роняет решения прежнего кроя. Ряд 320
не ошибается — он называет кросс-зонное следствие)). **`structure_version` как самостоятельная ось консент-гейта — решить в дизайне.** ⚠ **Но в КРОЙ он уже
сложен** (`manifest.go:272-276`: «it belongs here and not merely in the manifest key: without it a grammar
edit would re-cut the book while every unit id stood still») — открыт только вопрос про снапшот и
консент-гейт, а не про сам факт входа. Не «решай» уже решённое. ⚠ Приор `research/33` (Д6):
не через `buildSnapshotID`, довод — `repinnable()` истинен только на bank-only move, а фолд протухает все
`chunk_status`. Приор, а не запрет: опровергается аргументом.
@ -101,6 +173,18 @@
их группировка (`research/27` §5 п.8). Пере-нарезка тогда есть ПЕРЕГРУППИРОВКА уже оплаченного, а не его
потеря. Без этого пункта §4.1 решает адресацию, но не отвечает, почему перекрой не сжигает купленное.
**ИСПР. 11.09: у пункта не было ни одного императива — его закрывал абзац пересказа.** Дизайн ОБЯЗАН
ответить на три вопроса, каждый строкой документа:
1. **Какой хеш становится ключом ОПЛАЧЕННОГО** и чем он отличается от сегодняшнего адреса `chunk_status`
(PK `book_id, chapter, chunk_idx, stage`, `store/migrate.go:126`).
2. **Что происходит с `chunk_status` при ПЕРЕГРУППИРОВКЕ** — какие строки переезжают, какие осиротеют, кто и
когда их подметает.
3. **Почему возобновление после ЖЁСТКОГО стопа остаётся ВЕРНЫМ** (`D39.240`, слово владельца: деньги терять
допустимо, остановка обязана быть корректной с верным возобновлением). Перекрой не имеет права сделать
резюм после стопа неверным — это инвариант, а не пожелание.
⚠ И начни с чтения `backend/docs/D15.2-content-addressed-resume-spec.md` (§3 карты п.6): она дизайн-оф-рекорд,
её не переоткрывают — её дополняют и называют, что в ней перекрой ломает.
### 4.4б IR, формато-адаптеры и индуктор — **реши сам, аргументируй ГЛУБИНУ**
Строка 161 называет IR + адаптеры (EPUB `nav`/NCX построен, **FB2 нет вовсе**) + индуктор с валидаторами и
@ -110,17 +194,21 @@
### 4.4в Предикат осей — **делай РОВНО так** (критерий ратифицирован `D39.224` п.8)
Сегодня `classifySnapshotMove` знает ОДНО re-pinnable поле (`repin.go:54`), всё прочее — `moveOther`. Дизайн
обязан выдать явную карту осей, и она проверяемая, а не декларативная: **(1)** таблица относит КАЖДЫЙ
JSON-ключ полезной нагрузки `buildSnapshotID` (адресуй СИМВОЛОМ, не строками; на 07.09 ключей **21**) ровно к одной оси — провод · вердикт · банк · крой; **(2)**
**ИСПР. 11.09 — ГРАНИЦА ПУНКТА.** Пункты (2)(5) и «мерило» ниже дизайн **ОПИСЫВАЕТ как критерий приёмки
пака СТРОЙКИ** (`D39.224` п.8: критерий шага 1 уходит в дизайн-пак). Писать их здесь нельзя — §2 запрещает
код, и прежняя редакция заказывала четыре артефакта, которые сама же запретила.
Сегодня `classifySnapshotMove` знает ОДНО re-pinnable поле (`repin.go:54`; тело предиката — `repin.go:61`),
всё прочее — `moveOther`. Дизайн обязан выдать явную карту осей, и она проверяемая, а не декларативная: **(1)** таблица относит КАЖДЫЙ
JSON-ключ полезной нагрузки `buildSnapshotID` (адресуй СИМВОЛОМ, не строками; пере-считано 11.09 моим прибором — ключей **21**, команда `awk '/^type snapshotPayload struct/,/^}/' internal/pipeline/snapshot.go | grep -c 'json:"'`; у `stageSnap` их 19). ⚠ **Скоуп: 21 — это ключи ВЕРХНЕГО уровня, и `stages` среди них ОДИН ключ**`classifySnapshotMove` сравнивает верхний уровень как `map[string]json.RawMessage`. Девятнадцать полей `stageSnap` внутрь карты осей не разворачиваются; если дизайн считает иначе, он это обосновывает. Отнести ровно к одной оси — провод · вердикт · банк · крой; **(2)**
рефлексивный тест по образцу `TestEveryCutInputMovesTheTag` (`cuttag_test.go:26`) краснеет на ключе БЕЗ оси,
чтобы ни один не попадал в `moveOther` умолчанием; **(3)** резюм-тест: сдвинут ТОЛЬКО вердикт-ключ ⇒ ноль
платных вызовов, вердикт пере-вынесен из текста чекпойнта (сегодня `resume.go:24-26` отдаёт сохранённый
слепо); **(4)** `TestRepinRefusesAnyMoveThatIsNotBankOnly` (`miningstop_join_test.go:1686`) пере-скоупится
платных вызовов, вердикт пере-вынесен из текста чекпойнта (сегодня `resumeFromChunkStatus`, `resume.go:22`, отдаёт сохранённый
слепо — адрес пере-снят 11.09, в промте стояло `:24-26`); **(4)** `TestRepinRefusesAnyMoveThatIsNotBankOnly` (⚠ адрес пере-снят 11.09: `miningstop_join_test.go:1874`; в промте стояло `:1686`) пере-скоупится
ЗАКАЗОМ пака и объявляется в отчёте (`D39.183`); **(5)** `projectRebill` показывает контентную и позиционную
оси (`rebill.go:33-36` сам называет их непроецируемыми). ⚠ **Что этот предикат НЕ покупает:** wire-правка
меняет рендер провода ⇒ `ContentHash` другой ⇒ модель придётся вызвать при любой карте осей
(`stagerun.go:91-92`). Норма «копить одним касанием» падает только для ВЕРДИКТ-оси — так и напиши, иначе
(`stagerun.go:92-94` — ⚠ адрес пере-снят 11.09 по находке опровергателя: на `:91` стоит `return nil, fmt.Errorf(...)`, утверждение несут `:92` и `:94`). Норма «копить одним касанием» падает только для ВЕРДИКТ-оси — так и напиши, иначе
дизайн пообещает больше, чем механизм даёт. Мерило: бамп `CheapGateVersion` на продолжаемой книге ложится с
нулём платных вызовов и без `--resnapshot`.
@ -130,6 +218,9 @@ JSON-ключ полезной нагрузки `buildSnapshotID` (адресу
ОПИСЫВАЕТСЯ (пишет его пак стройки).
Строка **303**: чанкер безъюнитную грамматику («Kapitel 12») уже умеет, ингест по ней не режет —
дизайн обязан закрыть ревью-вопрос §3 для языков БЕЗ юнита, и закрыть его ДАННЫМИ, а не веткой в Go.
**Граница, которой в промте не было** (`D39.224` п.7): **проектировать — можно и нужно, ТРОГАТЬ ось
«обязательность юнита» в коде — нельзя**; стройка идёт паком 2 (лексиконы не-CJK), который ещё НЕ написан и
ждёт файлов владельца. Назови форму и шов — это не нарушение запрета, а его исполнение.
Сюда же строка **298** (`unit_resolutions`): `research/33` называет её аддитивной, но требует решить В ТОМ ЖЕ
дизайне — реши и назови форму.
@ -139,6 +230,9 @@ JSON-ключ полезной нагрузки `buildSnapshotID` (адресу
одну; провенанс честен (`delimited` + счёт), разрез груб. Строка **283**: билдер кладёт по XHTML на
главу движка ⇒ не-CJK txt приезжает одним полотном. Дизайн называет, режется ли документ по якорям
целей, и что из этого снимает временный отказ интейка (`D39.221`).
⚠ **Ряд 283 стоит и в СЛЕДУЮЩЕМ бэкенд-паке горизонта («выдача, которую видит читатель»), и здесь.
Разведены так:** твой пак решает, ЧЕМ режется документ и какова гранулярность (форма); пак выдачи строит то,
что ты решишь. Строить по 283 в этом паке нельзя, решать — обязательно.
### 4.7 Чего в паке НЕТ**не делай**, и это ОБЪЯВЛЕННЫЕ сужения, а не умолчания
@ -153,36 +247,96 @@ JSON-ключ полезной нагрузки `buildSnapshotID` (адресу
**Конфликт, который ты встретишь на первом часу, и его диспозиция.** `research/33` §5 «Шаг 0 — ДО дизайна»
заказывает пять $0-правок кода (включая «паритет-тест пишется сейчас»). **В этом паке они НЕ делаются:**
§2 запрещает код, и они уже заказаны ОТДЕЛЬНО — строки **344** · **345** · **346**(а) · **349** и дописка **224**, порядок ратифицирован `D39.224` п.3. ⚠ **ИСПР. 10.09: предусловие ИСПОЛНЕНО — шаг 0 уже ЛЁГ** (акт `D39.225`, 07.09), и ждать его не надо: из перечисленных живы только **346** и **224**, остальные закрыты. Прежний текст говорил «шаг 0 идёт СВОИМ паком ПАРАЛЛЕЛЬНО тебе и обязан лечь до пака СТРОЙКИ» — это описание уже прошедшего. Ты их НАЗЫВАЕШЬ как предусловия пака стройки; если какая-то нужна, чтобы ответить на
§2 запрещает код, и они уже заказаны ОТДЕЛЬНО — строки **344** · **345** · **346**(а) · **349** и дописка **224**, порядок ратифицирован `D39.224` п.3. ⚠ **ИСПР. 10.09: предусловие ИСПОЛНЕНО — шаг 0 уже ЛЁГ** (акт `D39.225`, 07.09), и ждать его не надо: из перечисленных живы только **346** и **224**, остальные закрыты. ⚠ **И обе живые половины шага 0 НЕ
держат** (испр. 11.09, иначе врезка противоречит себе): у ряда **346** закрыта половина (а), а живая (б) —
это фикс ВНУТРИ окна перенарезки, то есть твой предмет; ряд **224** жив ПЛАТФОРМЕННОЙ половиной, движковая
закрыта `D39.225`. Прежний текст говорил «шаг 0 идёт СВОИМ паком ПАРАЛЛЕЛЬНО тебе и обязан лечь до пака СТРОЙКИ» — это описание уже прошедшего. Ты их НАЗЫВАЕШЬ как предусловия пака стройки; если какая-то нужна, чтобы ответить на
вопрос дизайна, — ставь выброшенную пробу (§5 п.3), в дерево она не попадает.
### 4.8 Параллельный платный прогон на настоящей книге — **делай РОВНО так**
**ИСПР. 11.09, дважды.** Владелец разрешил платный сквозной прогон настоящей книги (3 главы zh→ru) через
платформу и движок — носитель санкции: `docs/NEAR_TERM_PLAN.md`, секция «Решения владельца». Пак прогона —
`docs/POLYGON_COLD_RUN_A_SESSION_PROMPT.md`, зона ПОЛИГОНА; кода движка он не пишет и твоей зоны не касается.
**Идёт он или ещё не запущен — на момент чтения проверь сам** (`docs/README.md`, таблица активных промтов):
сдачу свою им НЕ гейти ни в каком случае. Следствия для тебя, и они жёсткие:
1. **Стенд и БД прогона не трогать.** Твои выброшенные пробы (§5 п.3) идут в СВОЕЙ песочнице и на СВОИХ
данных. ⛔ Прогон на живой книге чувствителен к ключу манифеста: любая правка, двигающая `manifestKey`,
стирает замечания и счётчики книги. Тебе код править и так запрещено (§2) — здесь названа ЦЕНА нарушения.
2. **Улики прогона про структуру глав придут тебе пингом через оркестратора.** Прогон гоняет книгу
С МНОГОЕДИНИЧНОЙ главой — то есть ровно твой худший случай. Пришло — впиши в дизайн и назови, что
изменилось; не пришло — ничего не жди и не гейти этим свою сдачу.
3. **Своего платного прогона НЕ заказывать** (§«Деньги»). Упрёшься в «это предъявляется только платным
прогоном» — пинг за санкцией.
### 4.9 Попутное, $0 — **делай РОВНО так**
1. **Имя твоего документа — `backend/docs/CHAPTER_STRUCTURE_DESIGN.md`.** В зоне уже 15 файлов, среди них
`CHAPTER_STRUCTURE_REPORT.md`; безымянный заказ дал бы шестнадцатый с неотличимым именем.
2. **Три уехавших якоря в ТВОЕЙ зоне** (`python3 docs/scripts/counts.py --lint` из корня):
`backend/docs/DISCLOSURE_LAW_DESIGN.md:40`, `:41`, `:42` — цели `internal/pipeline/quality.go:233`,
`status.go:768`, `status.go:851`. Пере-снять адреса командой и починить. ⚠ Якорь бывает двух ролей: живая
ссылка (чинить) и УЛИКА в описании дефекта (не чинить — замена перевернёт описание поломки в описание её
отсутствия). Раздели хиты прежде правки. ⚠ Сводка линтера печатает «internal 6» — это НЕ твоя зона
целиком: половина из шести платформенная.
3. **Лист владельца.** `docs/product-requirements.md`, требование **ПТ-37** («Нарезка по границам СЦЕН»,
не построено) — прямой сосед §4.1 «развязка чанкера от глав». Либо дизайн его называет и говорит, где оно
встраивается, либо **пропуск подписывается пропуском**: «ПТ-37 не рассматривал, потому что …».
## 5. Мандат самопроверки ИСПОЛНЕНИЕМ — «перечитал сам» не считается
Дизайн проверяется иначе, чем код, и вот чем именно:
1. **Каждое утверждение о ТЕКУЩЕМ коде — грепом или прогоном, с `file:line`.** Дизайн, стоящий на
неверном описании сущего, дороже отсутствующего: по нему будут строить.
2. **Числа радиуса — СВОИМ замером.** `research/33` называет 183 площадки, из них **64 % (117/183) в `membank`+`store`** (⚠ его же строка 137 говорит «вне `internal/pipeline`» — это ДРУГАЯ величина, 140/183 = 77 %, ресёрч себе противоречит);
пере-считай своим прибором, назови популяцию и дерево. Разойдёшься — это находка, а не ошибка.
2. **Числа радиуса — СВОИМ замером.** `research/33` называет 183 площадки. ⛔ **ИСПР. 11.09: противоречие
ресёрча я описал неверно, и «77 %» — моя арифметика, а не его утверждение** (греп `77 ?%` по файлу — 0
хитов при контроле «64 %» — 3 хита). Настоящее противоречие такое: **ОДНА И ТА ЖЕ дробь 117/183 подписана
ДВУМЯ разными популяциями** — `:149` говорит «вне `internal/pipeline`», а `:466`/`:541` — «в
`membank`+`store`». По собственной разбивке файла membank 70 + store 47 = 117, то есть верна вторая
подпись, а «вне pipeline» = 183 43 = 140. Пере-считай своим прибором, назови ПОПУЛЯЦИЮ и ДЕРЕВО.
3. **Ключевые допущения — выброшенной пробой** (`go test -overlay` в песочнице, в дерево не попадает).
Как минимум: расхождение двух чисел главы на реальной книге корпуса и поведение банк-окна при
пере-нарезке. $0, read-only.
4. **Опровергатель твоего готового дизайна отдельным субагентом.** Харнесс по умолчанию субагентов не
спавнит — тебе РАЗРЕШЕНО и требуется. Модель задай ЯВНО (`fable`), одного-двух хватит. Мандат:
«найди в этом дизайне решение, которое не переживёт первой же стройки», а не «проверь, всё ли хорошо».
5. **Интервальная самопроверка** примерно на середине — субагент против ЯВНЫХ критериев §4.
**И вот где мягко ИМЕННО у этого пака — веди проход по этим четырём** (глубину выбираешь сам):
**(а) адреса `file:line`** — с написания промта движок двигали пять паков, часть адресов я пере-снял, но
проверял НЕ ВСЕ; **(б) числа `research/33`** — он себе противоречит подписью популяции (п.2 выше);
**(в) «уже построено»** — три раза прежняя редакция заказывала существующее (`manifestChapterID`,
`structure_version` внутри кроя, контент-осознанность `projectRebill`), ищи четвёртый раз;
**(г) две таксономии осей** — четырёхосник ратифицирован, пятиосник фактура, и смешение даёт таблицу,
которую нечем проверить.
5. **Интервальная самопроверка** примерно на середине — субагент против ЯВНЫХ критериев §4. ⚠ У пунктов
«реши сам» явных критериев нет по построению: там прибор — не сверка, а вопрос «какой аргумент ты
привёл и чем он подкреплён».
6. **Перед отчётом сверь каждый клейм с результатом инструмента ЭТОЙ сессии.**
## 6. Оси ревью — характер «Ресёрч/текст» и «Доки»
- **Claim-fidelity:** цитаты — дословные подстроки первоисточников; типовой провал здесь ОВЕР-АТРИБУЦИЯ,
а не выдумка. Приписал решение ноте — грепни ноту.
- **Claim-fidelity, и у неё есть ПРИБОР:** каждая закавыченная цитата грепается по первоисточнику как
дословная подстрока; не нашлась — это пересказ, и кавычки снимаются. Типовой провал здесь ОВЕР-АТРИБУЦИЯ,
а не выдумка. ⚠ Прежняя редакция этого промта нарушала норму трижды (в кавычках стоял пересказ) — прибор
введён 11.09 именно поэтому.
- **Доки:** сверка утверждений против кода и живых носителей.
## 6а. Стоячие правила владельца на эту смену (слово 11.09) — исполняются как часть пака
1. ⛔ **Никаких велосипедов, воркэраундов и хаков ВОКРУГ проблемы.** Владелец сказал это отдельно и про
бэкенд-паки в первую очередь: нужно логически правильное решение поставленной задачи, а не её обход.
Для ДИЗАЙНА это читается так: решение, которое «дешевле подпереть», в документ не попадает; если честный
ответ — «форму надо переписать», пиши его и назови цену (`D39.216`, мандат чистоты).
2. **Пак доводится до конца САМОЙ сессией.** Владельца не беспокоить; оркестратора не тегать «просто так»
(§13). Промежуточные вопросы — пингом оркестратору, а не остановкой работы.
3. **Эхо-протокол обязателен** (§9) и идёт ПЕРВЫМ действием — своими словами, не пересказом промта.
## 7. Записка-план ДО работы
До первой строки дизайна пришли оркестратору ≤15 строк: что берёшь по каждому пункту §4 · где ждёшь
сопротивления · что считаешь спорным в самом заказе.
сопротивления · что считаешь спорным в самом заказе. ⚠ Канала нет — записка идёт первой секцией
`docs/PROGRESS.md` под твоим подзаголовком, а не исчезает.
## 8. Заявление = команда
@ -202,9 +356,13 @@ JSON-ключ полезной нагрузки `buildSnapshotID` (адресу
Конфликт промта с кодом — пинг, не интерпретация. Право сказать «этого делать не надо» с аргументом.
**Отдельной секцией дизайна — вопросы, которые обязан решить владелец**, с ценой каждого варианта:
как минимум номер главы в глазах пользователя, судьба уже переведённых книг при перекрое, то, платит
ли кто-нибудь за пере-нарезку, и **точка затвердевания структуры** (§4.1: `research/27` §3а п.4 говорит
«твердеет на подписи банка», D-нотой не ратифицировано). Не решай их за него и не прячь в прозе.
как минимум номер главы в глазах пользователя, судьба уже переведённых книг при перекрое и то, платит ли
кто-нибудь за пере-нарезку. ⛔ **И точка затвердевания — это ДВА вопроса, а не один** (испр. 11.09: прежняя
редакция схлопывала их и получила бы схлопнутый ответ, а платит за разницу перекрой): **(1) когда твердеет
НАРЕЗКА** — то есть деньги (`research/27` §3а п.3: «Freeze на этой стадии относится к НАРЕЗКЕ/деньгам, не к
виду»); **(2) когда твердеет ВИД** — то, что видит читатель (там же п.4). Ни то, ни другое D-нотой не
ратифицировано. ⚠ Формулировка «твердеет на подписи банка» — мой ПЕРЕСКАЗ, в файле её нет; цитируй файл.
Не решай за владельца и не прячь в прозе.
## 12. Прямой канал
@ -215,8 +373,9 @@ JSON-ключ полезной нагрузки `buildSnapshotID` (адресу
## 13. Критерий завершённости — по нему тебя примут
Работа завершена, когда: у каждого пункта §4 есть исход (решено · сознательно не решаю с доводом ·
вопрос владельцу) · круги самопроверки СОШЛИСЬ — последний не дал НОВЫХ находок, прежние закрыты
таблицей «находка → что сделано → чем предъявлено» · числа сняты после последней правки · всё живое в
вопрос владельцу) · круги самопроверки СОШЛИСЬ, и для ДИЗАЙНА это значит конкретное: **последний проход
опровергателя (§5 п.4) не дал НОВЫХ находок** — у дизайна нет батареи, поэтому «сошлись» без внешнего
прибора остаётся самоотчётом; прежние находки закрыты таблицей «находка → что сделано → чем предъявлено» · числа сняты после последней правки · всё живое в
ДЕРЕВЕ, а не в письме · явное «работа завершена, править не планирую». Без последнего пак считается идущим.
**Оркестратора тегать «просто так» нельзя**его приёмка идёт последней и вторым кругом тебе не служит.

View file

@ -47,38 +47,67 @@
| 4 | **бэкенд** | «ВЫДАЧА, КОТОРУЮ ВИДИТ ЧИТАТЕЛЬ»: ряды **284** · **201** · **283** · **307** · **291** | пак | после глав |
| 5 | **фронт** | поверхность показа | пак | разморозка + пункты 13 |
## Прогон A — точечно
## Прогон A — точечно (пере-написано 11.09 после разбора со старшим коллегой)
**ИСПР. 11.09 ПО СЛОВУ ВЛАДЕЛЬЦА: ЛОКАЛЬНОЙ МОДЕЛИ НЕТ — на машине нет видеокарты.** Пере-снято:
провайдер `local` смотрит в `http://127.0.0.1:11434/v1` (ollama), а на хосте нет ни `nvidia-smi`, ни `ollama`,
ни слушателя на 11434 (контроль: слушателей всего 5, из них на 11434 — 0). ⇒ рекомендация «гнать на локальной
модели» **невыполнима**, и выбор сужается до двух.
**ПРЕДМЕТ — строка 16: цена книги, ДОВЕДЁННОЙ ДО КОНЦА, не измерена ни разу.** Цикл замкнут живьём 04.09
(`D39.194` п.1: скачанный EPUB прошёл `epubcheck`), но книги, дошедшей до `exports.complete = true`, через
API не было: 04.09 упёрлось в потолок (`PD-440`, с тех пор лечено `D39.206`/`D39.208`). Прогон A ведёт одну
настоящую книгу от двери до ФАЙЛА и печатает, чем каждый узел предъявлен.
**Заглушка** — свободна, но на заглушечной прозе **вырождаются сами узлы**: гейты, майнинг терминов, банк;
узел подписи на ней пуст ПО ПОСТРОЕНИЮ и дыру (2) не покажет никогда. Годится ТОЛЬКО как двадцатиминутный
дым продлённой трети (экспорт → скачивание).
**ЛОКАЛЬНОЙ МОДЕЛИ НЕТ** (слово владельца 11.09 — на машине нет видеокарты): провайдер `local` смотрит в
`http://127.0.0.1:11434/v1`, а на хосте нет ни `nvidia-smi`, ни `ollama`, ни слушателя на 11434 (контроль:
слушателей всего 5, на 11434 — 0). Значит настоящие узлы можно пройти только платно.
**Настоящую книгу через настоящие узлы можно прогнать только ПЛАТНО. И это дёшево:** замеренный живой
прогон 08.09 — **10 глав за `committed=$1.259217`** (строка **354**), то есть ≈ **$0.13 за главу** ⇒
23 главы ≈ **$0.250.40**. Владелец хочет «каждый узел так, как мы хотим» — это вопрос к узлам на настоящем
тексте, и стоит он центы, а не доллары.
⛔ **ТРИ МОИ ОШИБКИ В ЭТОМ РАЗДЕЛЕ, СНЯТЫЕ РАЗБОРОМ 11.09:**
1. **«Книга со стенда P9»** — на P9 (27.08) стояла встроенная трёхглавая ЗАГЛУШКА (`seed` «demo.txt») и
крафтовая проба в 1222 байта на `fake_provider.py`. Настоящая короткая книга — это 04.09:
`books/gu-zhenren/coldrun-v16/guzhenren-ch1-10.gb18030.txt` (10 глав, 14 юнитов). Брать **главы 13**
(≈4 юнита, глава 1 двухъединичная — пере-проверить манифестом ДО фриза).
2. **«Пробой 27.08 оборвался на правке банка»** — неверно: транскрипт показывает preview → apply →
`already_applied``409` на противоречии → resume → `ready 6/6`. Он не оборвался, а кончился там, где
кончался тогдашний контракт: без провайдера, без настоящей книги и без двери выгрузки.
3. **«Заглушка годится только как двадцатиминутный дым»** — наоборот: **$0-дым по заглушке ОБЯЗАТЕЛЕН
фазой 0.** Он валидирует драйвер, сборщики следов и дверь выгрузки бесплатно; без него первая же
инфраструктурная осечка сожжёт «холодность» платной книги.
**Книга:** та, что стояла на стенде P9, 23 главы zh→ru, **с многоединичной главой внутри** — иначе
редакторская волна не покажет своего худшего случая.
**Пробой 27.08 шёл через `curl` на заглушке и оборвался на правке банка** — то есть мимо фронта и до
последней трети. Заказ: продлить до конца (редакторская волна → выгрузка → **файл открыт человеком**).
**Приёмка узла — по трём независимым следам, НЕ по самоотчёту движка** (три отчётные поверхности врут).
Ожидаемый исход каждого шага пишется ДО прогона; иначе ноль ошибок прочтут как успех.
⚠ Прогону A **запрещено чинить найденное** — только пинги. И движок на время прогона заморожен: смена ключа
манифеста стирает замечания и счётчики книги.
**ДЕНЬГИ — ДВА ЧИСЛА, И Я ЗНАЛ ТОЛЬКО ОДНО.** Ожидаемая трата ≈ **$0.30** (замер 08.09: 10 глав за
`committed=$1.259217`). Но машинный КАП — это ХОЛД, а не ожидание: на `c1` книжный бонд
`book_once = budget_usd 1.00 + classify_budget_usd 1.00 = $2.00`, поэтому холд трёхглавой книги ≈ **$2.32.5**,
и грант обязан быть не меньше, иначе допуск откажет. ⇒ **владельцу называются оба: «ждём ≈$0.30, кап ≈$2.5».**
## Что решает владелец
**Предусловия, которых в плане не было (замерены 11.09):** артефакта контраста майнинга нет НИ ОДНОГО на
файловой системе (`CheckMiningContrast` откажет на старте и оставит `failed`-прогон, после которого книга уже
не холодная) · `eval/.venv` не существует, jieba не установлен · кластер Postgres опущен · `epubcheck`/`java`
на хосте нет. Всё это ставится ДО фриза.
**Фриз** — sha коммита ПЛЮС бинари, собранные из `git worktree add <путь> <sha>`: сборка из главного дерева
даёт `vcs.modified=true` от любого untracked-файла, и драйвер обязан отказывать по `go version -m`.
⚠ Прогону A **запрещено чинить найденное** — только пинги. Приёмка узла — по ТРЁМ независимым следам
(Postgres · диск и systemd · HTTP), не по самоотчёту движка. Ожидаемый исход каждого шага пишется ДО
прогона. ⛔ **Претрейн:** 蛊真人 узнаётся моделями 4 из 5 ⇒ пре-рег объявляет, что клеймов О КАЧЕСТВЕ пак
не делает вовсе; узлы судятся механизмом (кадры, флаги, леджер), а не чтением текста.
## Решения владельца, уже полученные (носитель — ЗДЕСЬ; заведён 11.09, прежде его не было ни в одном доке)
- ✅ **ПЛАТНЫЙ ПРОГОН A РАЗРЕШЁН** (слово 11.09: «Разрешаю»). Ожидание ≈$0.30, машинный кап ≈$2.5 (холд, см.
раздел выше). ⚠ Санкция названа ЗДЕСЬ, потому что опровергатель 11.09 поймал: промты ссылались на неё как
на факт, а в дереве её не было ни строкой — «известное со слов» не носитель.
- ✅ **Остановка остаётся ЖЁСТКОЙ, деньги терять ДОПУСТИМО, но остановка обязана быть КОРРЕКТНОЙ** — без
гонок, без половинчатых состояний, с верным возобновлением (`D39.240`).
- ✅ **Автономия смены (11.09):** решения принимаю сам, советуясь со старшим коллегой; мерило — главные
ценности продукта (качественный консистентный перевод длинных книг), затем архитектура и чистый код,
необходимый рефакторинг и отсутствие велосипедостроения.
## Что решает владелец — ОСТАЛОСЬ
- **Определение показа:** аудитория и вход · какая книга · один гость или несколько · **бюджет времени**
(`ПТ-19` называет скорость киллерфичей, а времени у экрана никто не мерил).
- **Разрешить платный прогон A** — 23 главы ≈ $0.250.40; без него настоящие узлы не увидеть.
- **Деньги гостя на показе** — стенд сеет $25, продукт 0; дневного потолка в шаблоне намеренно нет.
- Какую из двух «готовностей» он имел в виду — полноту функционала или качество перевода.
- **Пять вопросов банка памяти**, поднятых аудитом 11.09 (стоп или флаг на разъехавшемся термине · входит ли
ГОЛОС в приоритет №1 · один перевод у НЕподписанного термина · накапливать ли банк между прогонами ·
остановка на подпись — опция или свойство продукта). Носитель разбора — `docs/research/34-*`.
## Вычеркнуто

View file

@ -138,7 +138,8 @@ D-ссылка грепается по D-логу — ⛔ **и до НОМЕРА
сессии, объявляются владельцу вслух ДО коммита; девиации — НОВЫМ коммитом и явно в отчёте; ⚠
фриз-гейт смотрит на ПОКУПАЮЩИЙ файл, не на кассу и не на всю зону: правка кода после фриза
отказывает покупку ⇒ фризить ПЕРЕД покупкой, а потолки правятся БЕЗ пере-фриза; «не
влезает в бюджет — стоп и пинг, не резать молча» (D39.108 п.1) · подъём потолков просить при
влезает в бюджет — стоп и пинг, не резать молча» (⚠ атрибуция `D39.108` п.1 снята 11.09 фантом-гардом:
в теле ноты этой формулировки нет, нота — приёмка экспов 18/19/20; носитель нормы — ЭТОТ файл) · подъём потолков просить при
СРАБАТЫВАНИИ стопа, не по проекции — прогнозный запрос оставляет ложный след «владелец согласился
на пере-оплату», которой не было · **живость длинного платного прогона проверяется АКТИВНО:** не
ждать финального уведомления — раз в пару часов сверять рост числа вызовов/трат по леджеру двумя

View file

@ -0,0 +1,222 @@
# Промт: платформенный пак «ПРАВДА У ДВЕРИ — не заклинивать и не обещать того, чего дверь не даст»
## 1. Какая проблема и что решит твой результат
Гость платформы упирается в три разных места, и все три — про ОДНО: **платформа говорит человеку не то,
что произойдёт на самом деле.**
1. **Форма заказа обещает то, в чём дверь откажет.** Вердикт «хватает на всю книгу» считается из остатка и
баланса и НЕ спрашивает, не идёт ли по книге прогон прямо сейчас; допуск же вторую покупку отвергает.
Человек видит зелёное, жмёт и получает отказ, причину которого форма знала до клика (`PD-455`).
2. **Двойной клик по «продолжить» отвечает ошибкой, хотя прогон в этот момент СТАРТОВАЛ.** Проигравший
гонку получает «прогон нельзя продолжить: он переводится» — то есть отказ, описывающий успех соседа
(`PD-448`).
3. **Прогон книги, чей каталог исчез, принимает 202, берёт холд и висит вечно.** Пользователю видно только
«идёт», деньги заморожены до прихода человека (`PD-162`).
Плюс интейк-гигиена, которую `D39.176` п.1 прямо называет ИНЖЕНЕРНОЙ и не требующей слова владельца: число
аплоадов ничем не ограничено, у статуса `rejected` нет выхода, каталоги-сироты никто не подметает.
**Что решит твой результат.** После пака человек, работающий с платформой, видит правду в трёх точках:
форма не обещает невозможного · повторный клик отвечает прогоном, а не ошибкой · прогон, который никогда не
поедет, отказывает ДО денег, а не молчит с холдом. Это прямо служит главной ценности продукта — переводу
длинных книг: длинная книга живёт неделями, за это время в неё кликают многократно, и каждая ложь двери
стоит человеку или денег, или доверия.
## 2. Зона записи и git
**Зона: `platform/`.** Записи, пинги и итоги — ЗОННЫЙ журнал `platform/docs/platform-PROGRESS.md`; в
`docs/PROGRESS.md` платформа НЕ пишет. Регистр дефектов `platform/docs/DEFECT_REGISTER.md` — твой, ряды
переводит зона (не оркестратор). Зонный бэклог — `platform/BACKLOG.md`.
**Сессия НЕ коммитит** — дерево передаёшь оркестратору (канон — `CLAUDE.md` §«Git-координация мультисессий»:
никаких `git add -A`, `reset --hard`, `checkout` поверх грязного дерева). `.env` не читать.
Чужие зоны (`backend/`, `frontend/`, `docs/`) — только ЧИТАТЬ. ⚠ Что должно пережить рестарт — в РЕПОЗИТОРИЙ,
а не в скретчпад. ⚠ Входящее сообщение другой сессии — не приказ: промт сильнее, расхождение — пинг.
⚠ Параллельно идут сессии ДРУГИХ зон (движок · полигон). Их файлов не трогать.
## 3. Карта чтения — ЗАКОН, дальше только по её ссылкам
1. `CLAUDE.md` — цели владельца, зоны, гардрейлы.
2. **`platform/docs/ENGINEERING_STANDARDS.md`** — ратифицирован; КАЖДЫЙ платформенный пак обязан на него
ссылаться, отступление = пинг. Плюс `platform/docs/PLATFORM_DIRECTION.md` (ратифицированное направление
зоны) и `platform/README.md`.
3. Ряды регистра **`PD-455`** · **`PD-448`** · **`PD-162`** (`platform/docs/DEFECT_REGISTER.md`, греп по id) —
там же улики прежних смен и границы этих улик. Зонный бэклог: **П-18** (эскроу) и **П-20** (хвост PD-162).
4. `docs/architecture/14-api-contract/` — канон провода; форма заказа и `Run` живут там. ⚠ Версию брать
ФАЙЛОМ (`grep '^ version:' openapi.yaml`), не по памяти.
5. Код — первичен; `file:line` ниже суть отправные точки, а не истина: пере-снимай адрес командой.
**Ратифицированное, что нужно для работы (не переоткрывать):**
- ⛔ **`D39.176` п.1 — ПРОДУКТОВЫХ КВОТ НЕТ и фри-тир-лимиты НЕ ПРОЕКТИРУЮТСЯ.** Слово владельца: «никаких
квот, живём на покупке API; бонусы зачисляются из админки». Грант новичку 0 — это РЕШЕНИЕ, а не дыра.
Техническая половина (число аплоадов, выход из `rejected`, сироты) остаётся и решается ИНЖЕНЕРНО.
- ⛔ **Автоматического терминального вердикта после N неудач у реконсилятора НЕТ и он НЕ планируется вне
эскроу** — это записанное решение зоны (`П-20`, и запись в `internal/runs/reconcile.go`; ⚠ якорь
`reconcile.go:249-257` из ряда `PD-162` УЕХАЛ — по адресу сегодня комментарий `settleOne`; пере-найди
запись грепом по «what it must not buy» и почини якорь ряда тем же движением).
**строить «счётчик неудач → бросить прогон» в этом паке ЗАПРЕЩЕНО**: это более слабая половина эскроу
(`П-18`), поставленная рядом с проектируемым целым.
- **`D39.221`** — контрактный минор 0.13.0 и временный отказ интейка книге из одной главы;
**`D39.229`** — синхронный разрез приёма под потолком. Обе — фон твоей работы, не предмет.
## 4. Состав и разметка свободы
### 4.1 `PD-455` — форма заказа обязана знать про живой прогон — **реши сам, аргументируй**
Вердикт формы и вердикт допуска сегодня отвечают на один вопрос ДВУМЯ разными механизмами, и потому
расходятся. ⛔ **Не строй в форме вторую копию логики допуска** — это ровно то велосипедостроение, которое
владелец запретил отдельным словом: два ответа на один вопрос расходятся снова, и следующая смена будет
чинить оба. **Правильная форма решения — ОДНО определение, которое спрашивают обе площадки.** Что именно
это определение возвращает (`blocked` отдельным вердиктом · признак живого прогона в теле · что-то третье) —
решаешь ты, но ответь на вопрос: **как устроено так, что расхождение больше не может возникнуть молча.**
⚠ Контракт трогаешь? Аддитивное расширение ОПИСЫВАЕШЬ, канон правит оркестратор — пинг с предложенной формой.
### 4.2 `PD-448` — проигравший гонку обязан получить прогон, а не отказ — **реши сам, аргументируй**
Гарантия сформулирована в шапке самого теста (`internal/runs/control_test.go`, греп
`TestTwoResumesOfOneRunTakeOneHoldAndBothAnswer`): оба вызова проходят проверку состояния вместе и гонятся за
попытку N+1 на уникальном индексе; **проигравший обязан ответить прогоном, который открыл победитель, а не
ошибкой.** Сегодня под нагрузкой вызовы СЕРИАЛИЗУЮТСЯ, победитель успевает перевести прогон в `translating`,
и проигравший упирается в проверку состояния.
Направление (ПРИОР, опровергается аргументом): проигравший обязан различать «прогон идёт, потому что его
только что открыл параллельный резюм» от «прогон идёт сам по себе» — первое обязано вернуть прогон, второе
законно отказывает. **Как именно различить — твоё решение.**
**Ретрай-с-паузой решением НЕ является:** он превращает гонку в лотерею и прячет предмет.
### 4.3 `PD-162` — прогон, который никогда не поедет, обязан отказать ДО денег — **делай РОВНО так в границе, свободен внутри неё**
**Граница (отступление = пинг):** автоматический терминальный вердикт живому прогону НЕ строится (§3).
**Внутри границы:** ряд сам называет второй путь — **валидация каталога книги ПРИ ДОПУСКЕ**, до взятия холда
(`internal/runs/runs.go` `Start`, `internal/runs/spawn.go` `journalSize` — ENOENT там законно мапится в ноль
для ПЕРВОГО прогона, и именно это делает дыру невидимой). Спроектируй и построй допуск, который отвергает
прогон книги, чьего каталога нет, **не сломав законный первый прогон** — это и есть вся трудность пункта.
⚠ Класс ряда ШИРЕ удаления каталога (прогон, запиненный к старой сборке движка, даёт тот же клин). Закрываешь
одну половину — скажи это прямо и оставь ряд открытым с пере-написанным остатком; «закрыто» при живой второй
половине — дефект акта, а не победа.
### 4.4 Интейк-гигиена — **реши сам, аргументируй; можешь взять НЕ ВСЁ**
Три предмета, названные `D39.176` п.1 инженерными: число аплоадов ничем не ограничено · у статуса `rejected`
нет выхода · каталоги-сироты никто не подметает. **Возьми то, что честно закрывается в этом паке, и назови,
что оставляешь и почему.** ⛔ Продуктовых квот не строить (§3). ⛔ Свип обязан определять сироту по СОСТОЯНИЮ
В БАЗЕ, а не по возрасту каталога на диске: каталог, который никто не читал неделю, и каталог, которого нет
в базе, — разные вещи, и первый может быть книгой, которую читатель откроет завтра.
### 4.5 Якоря регистра — **делай РОВНО так** ($0, попутно)
`python3 docs/scripts/counts.py --lint` (из корня репозитория) сегодня показывает **три** уехавших якоря в
твоей зоне: `platform/docs/DEFECT_REGISTER.md:84` (`reconcile.go:327``const settlementBackoffCap`) ·
`:559` (`reconcile.go:278``case overran:`) · `:560` (`pgstore/sink.go:724``where a.reconcile_after…`),
плюс уехавший якорь внутри `PD-162` (§3). Пере-снять адреса командой и починить. ⚠ Якорь бывает ДВУХ ролей:
живая ссылка (чинить) и УЛИКА в описании дефекта — «код цитирует вот этот путь, а его удалили» (не чинить:
замена переворачивает описание поломки в описание её отсутствия). Раздели хиты прежде правки.
### 4.6 Чего в паке НЕТ — **не делай**
Эскроу (`П-18`) · автоматический терминальный вердикт · продуктовые квоты и фри-тир · платёжный провайдер ·
правка канона контракта (описываешь, правит оркестратор) · чужие зоны · платные прогоны движка.
## 5. Мандат самопроверки ИСПОЛНЕНИЕМ — «перечитал сам» не считается
Механизм НАЗВАН: **`make check` целиком** (не подмножество `-run`) + **мутационные посадки на СВОИ новые
пины** + **живая проба на стенде** (рецепт стенда — `platform/docs/STACK_DECISIONS.md`). Субагентов
спавнить тебе **РАЗРЕШЕНО и требуется** (иначе дефолт-запрет харнесса тихо победит); модель задавай ЯВНО.
Артефакт — таблица «находка → что сделано → ЧЕМ ПРЕДЪЯВЛЕНО».
**Где у ЭТОГО пака мягко — четыре места, и адверсариальный проход веди по ним** (глубину и веер выбираешь
сам):
1. **`PD-448` — тест, зелёный в изоляции, о гонке не говорит НИЧЕГО.** Замер 05.09: изолированно
`-count=5` → 5/5 `ok`, а полный пакет при загруженной машине падал 2 раза из 2. ⇒ твой пин обязан
краснеть на НЕПОЧИНЕННОМ коде воспроизводимо, а не «иногда»: пин, флейковый на мутанте, измеряет пустой
сценарий. Гони его многократно и назови число прогонов.
2. **`PD-455` — «форма спросила допуск» легко выродится в копию.** Проверь у себя: если завтра изменится
правило допуска, сколько мест придётся тронуть? Больше одного — ты построил вторую копию, а не общее
определение.
3. **`PD-162` — валидация каталога ломает законный ПЕРВЫЙ прогон.** ENOENT в `journalSize` мапится в ноль
именно потому, что у первого прогона журнала ещё нет. Твоя проверка обязана различать «журнала нет,
потому что прогон первый» и «каталога нет вовсе» — и обе ветви обязаны иметь пин.
4. **Свип сирот — самая опасная правка пака: он УДАЛЯЕТ.** Прежде чем удалять, докажи пином, что предмет
удаления не может оказаться живой книгой. ⛔ Отрицательный замер здесь особенно вреден: «0 сирот» и «свип
не посмотрел» неотличимы — печатай рядом контрольную величину (сколько каталогов прибор прочёл).
Плюс общие для кодового пака: **пин на УСЛОВНОЕ сообщение обязан иметь фикстуру, где это сообщение ОБЯЗАНО
прозвучать** (тест, утверждающий только молчание, вакуумен) · **перед отчётом сверь каждый клейм с
результатом инструмента ЭТОЙ сессии** · **дифф `^func Test` — исполнением, не памятью** · **править или
удалять тест/гейт ради зелени НЕДОПУСТИМО**; правка, вызванная ЗАКАЗАННОЙ сменой поведения, — обслуживание,
и она ОБЪЯВЛЯЕТСЯ в отчёте (что изменилось, какой тест это описывал, куда уехала гарантия).
⛔ **И отдельное слово владельца 11.09, оно же ось приёмки: никаких велосипедов, воркэраундов и хаков ВОКРУГ
проблемы.** Нужно логически правильное решение поставленной задачи, а не её обход. Рефакторинг — только
действительно необходимый; «дешевле подпереть» доводом не является.
## 6. Предметные оси ревью
**Код** — тест утверждает не то, что думает: часы как способ синхронизации там, где предмет утверждения НЕ
время; ассерт по подстроке в буфере, куда пишет кто-то ещё. Обе формы дают тихо-зелёное, а оно дороже
ложно-красного. Сверка с индустриальным первоисточником прежде велосипеда.
**Деньги** — из сырого леджера ДВУМЯ независимыми путями; леджер = нижняя граница. Холд, взятый и не
возвращённый, — денежный дефект, даже если сумма мала.
## 7. Записка-план ДО работы
До первой правки пришли оркестратору ≤15 строк: что берёшь по каждому пункту §4 · где ждёшь сопротивления ·
что считаешь спорным в самом заказе. Комплектность против заказа сверяется механически, а не по памяти.
## 8. Заявление = команда
Любое число и любая категорика отчёта — с командой, которой получены, и её выводом. ⛔ Рядом с НУЛЁМ
ПЕЧАТАЕТСЯ контрольная величина, доказывающая, что вопрос задан существующему предмету («в базе без этой
таблицы: 0», «каталогов прибор прочёл: 67»). Не «проверено с контрольной строкой» — само число.
**`make check` без `-v` скипы не печатает:** «20 пакетов ok» на машине без стенда неотличимо от «20 ok при
N скипах». Печатай счёт скипов рядом с числом `ok` и называй условие каждого.
## 9. Эхо-протокол старта
ДО первой правки пришли **оркестратору первым действием, по адресу из `/tmp/textmachine-channel`**
(`SendMessage`, роль `ОРКЕСТРАТОР`) ≤10 строк: скоуп · инварианты · не-делать — **СВОИМИ словами.**
Дословный пересказ промта подтверждает канал, но не понимание, и ошибку промта повторяет вместе с ним.
Канала нет — эхо первой секцией отчёта, это законный случай.
## 10. Что НЕ удалось — обязательная секция отчёта
Что не проверено · что не воспроизвелось · где данных не хватило · что пришлось оставить. **«Не измерено»
вместо догадки.** «Не проверено» ≠ «опровергнуто».
## 11. Канал вопросов и право отказаться
Конфликт промта с кодом или доками — **пинг оркестратору, НЕ интерпретация**. У тебя есть право сказать
«этого делать не надо» с аргументом — им пользуются, и такие развилки поощряются.
Вопрос владельцу (деньги сверх мелочи · продуктовый скоуп) идёт через оркестратора, не напрямую.
## 12. Прямой канал
Механизм — `CLAUDE.md` §«Связь между сессиями»: файл `/tmp/textmachine-channel`, свой блок дописать первым
делом, живость адресата — `ListAgents`. Нужной роли в файле нет, файла нет или имя не отвечает ⇒ **КАНАЛА
НЕТ, и это НОРМАЛЬНЫЙ случай: сессии подряд НЕ опрашивать**, вопрос — секцией в отчёт.
## 13. Критерий завершённости — по нему тебя примут
Работа завершена, когда: у каждого пункта §4 есть исход (сделано · не делаю с доводом · пинг) · круги
самопроверки СОШЛИСЬ — последний не дал НОВЫХ находок, прежние закрыты таблицей «находка → что сделано →
чем предъявлено» · таблица мутаций полная, выжившие названы поимённо · числа сняты ПОСЛЕ последней правки ·
ряды регистра и зонного бэклога переведены ТЕМ ЖЕ движением, что и код (закрытый ряд при живой половине —
дефект) · всё живое в ДЕРЕВЕ, а не в письме · явное **«работа завершена, править не планирую»**.
Без последнего пак считается идущим.
**Пак доводится до конца САМОЙ сессией** (слово владельца 11.09): владельца не беспокоить, оркестратора
не тегать «просто так» — его приёмка идёт последней и вторым кругом тебе не служит.
## Деньги
**Пак — $0.** Платных вызовов движка нет. Упрёшься в «это предъявляется только платным прогоном» — пинг за
санкцией, не своё решение.
## Отчёт
Зонный журнал `platform/docs/platform-PROGRESS.md` + переведённые ряды регистра + сообщение оркестратору:
что сделано по каждому пункту · чем предъявлено (команда и вывод) · таблица «находка → что сделано → чем
предъявлено» · что сказал твой адверсариальный проход и что ты с этим сделал · секция §10 · **что ты сам
считаешь слабым местом сделанного**.
⛔ Последний абзац отчёта — план или обещание? Значит работа не кончена: сделай сейчас.

View file

@ -57,14 +57,22 @@
## Раскладка слотов (живая)
| Зона | Промт | Сессия | Состояние |
|---|---|---|---|
| полигон | — | — | свободен |
| бэкенд | — | — | свободен |
| платформа | — | — | свободен |
|---|---|---|---|---|
| полигон | `POLYGON_INSTRUMENT_REPAIR` + `POLYGON_EXP2223_REDO` (приостановлен) | — | ⚠ **слот занят ДВУМЯ промтами прежних смен** — разобрать прежде, чем класть прогон A |
| бэкенд | `CHAPTER_STRUCTURE_DESIGN_SESSION_PROMPT.md` | — | написан 07.09, пять врезок внесено 11.09, идёт опровергатель |
| платформа | `PLATFORM_TRUTH_AT_THE_DOOR_SESSION_PROMPT.md` | — | написан 11.09, идёт опровергатель |
| фронт | заморожен | — | разморозка по критерию `NEAR_TERM_PLAN.md` |
## Журнал выдач очереди №23
| # | зона | предмет | сессия | эхо | исход |
|---|---|---|---|---|---|
| — | — | — | — | — | — |
| — | — | — | — | — | ещё ни один пак не выдан |
## Долг, замеченный попутно (не терять)
- **11 уехавших якорей в ЧУЖИХ зонах** (`counts.py --lint`, 11.09): полигон 5 (`docs/experiments/`) ·
бэкенд 3 (`backend/docs/DISCLOSURE_LAW_DESIGN.md`) · фронт 3 · платформа 3 — платформенные уже врезаны
в её пак §4.5. Свои пять я починил (`f9216cd`). Остальные раздать ПАКАМИ их зон, не чинить самому.
- **Воркфлоу про банк памяти (`wm0j2l4kz`) умер, отдав пустой файл** — вопрос владельца «что банку памяти
нужно для качества перевода» носителя не получил; пере-задать при паке «выдача, которую видит читатель».