Read both zones' documentation end to end and record what it gets wrong: the status board said the cycle was broken on the day it was closed, and the anchor lint never walked the engine's own docs

This commit is contained in:
heaven 2026-09-04 23:03:17 +03:00
parent 7db84219b6
commit a787bae1ea
3 changed files with 80 additions and 5 deletions

View file

@ -50,6 +50,76 @@
- **`pkill` по имени процесса на машине с параллельными сессиями бьёт по чужим.**
- **Число или «доказано» уходит владельцу только после СВОЕГО прогона.**
## ⚠ ПИНГ ЗОНЕ БЭКЕНДА (оркестратор №22, 04.09, вечер) — РЕВИЗИЯ ДОКУМЕНТАЦИИ ЗОНЫ ЦЕЛИКОМ
Внешний ревизор прочитал `backend/README.md`, все 11 файлов `backend/docs/` (включая оба PUML текстом)
и арх-доки движка от первой строки до последней. Правит ЗОНА. Порядок — по цене ошибки.
**1. ⛔ `README.md:36` описывает инвариант через ключи, которые загрузка ОТВЕРГАЕТ.** «Канал adult —
только permissive (fail-closed)»: `permissive:` и `channel:` — RETIRED и валят конфиг
(`internal/config/models.go`, греп `LegacyPermissive`; `internal/config/pipeline.go`, греп
`LegacyChannel`). Настоящий механизм — `content_labels` книги × `accepts_labels` модели — в README не
назван ВООБЩЕ. Сессия, строящая маршрутизацию контента по README, получит неподнимающийся конфиг.
Ту же ложь несут оба PUML.
**2. ⛔ ОБА PUML БЕЗ ⚠-БАННЕРА рисуют снесённое**, при том что `docs/README.md` подаёт их как
канонические диаграммы, правящиеся «одним коммитом с кодом»: exit-контракт из ЧЕТЫРЁХ кодов (в
`cmd/tmctl/main.go` — коды 4, 5 и полоса 1019), глаголов 6 против 11, `mined_delta`/`mined_rejects`
как ключи `book.yaml` (RETIRED, валят загрузку), машинная `.bank-stop.json` (снесена D39.158),
`Adult bool`. В заголовке обоих — «синхронизировано с D1D39.25» при живой голове D39.195.
**3. `README.md:95` и `10-prompt-architecture.md:23` называют боевой редакторский промпт `v3`** —
в `configs/pipeline-c1.yaml` метка `v4-discourse-reflow-nogenre`, и с D39.182 она НЕСУЩАЯ
(`TestPromptLabelsPinTheirBytes`). Поверивший README либо бампнет v3→v4 в уже-v4 файле, либо получит
красный гейт.
**4. `README.md:3` обещает автоматику, которой нет:** «подсистемы не импортируют друг друга
(проверяется `go list -deps`)». Сама изоляция ДЕРЖИТСЯ — проверено, — но проверки нет:
`grep -rn 'go list' backend --include=*_test.go --include=Makefile` → 0, а `internal/archguard` несёт
три анализатора, границы импортов среди них нет. `13-tech-debt-anchors.md` это констатирует, README нет.
**5. ⚠ ОБЩНОСТЬ ПЕРЕОЦЕНЕНА, и долг без носителя.** `README.md:23` («гейты по данным, Go-веток по паре
нет») и `README.md:16``internal/text` — script-agnostic, без языковой политики») — сверх-утверждения:
`internal/text/norm.go` встраивает китайскую таблицу трад→упр, складывает катакану в хирагану и
БЕЗУСЛОВНО сливает `ё→е` для ЛЮБОЙ цели (белорусская цель ломается тихо); санитайзер считает только
`latinLetters`/`cyrLetters`, поэтому греческая/арабская/хинди цель получает «латинскую вставку» на
каждом слове; граница слова в банке проверяется только для Latin/Cyrillic. ⇒ Ревью-вопрос «пара,
которой в репо нет, без правки Go» для не-кириллической цели отвечается НЕТ, а README это скрывает.
**6. Ратифицированная норма зоны держится на СНЯТОЙ строке.** `DISCLOSURE_LAW_DESIGN.md:219-221`:
«Пока строка бэклога 246 открыта, новый класс вводится в полосу ТОЛЬКО вместе со сверкой… Закроется
246 — оговорка снимается». 246 ЗАКРЫТА 04.09 (D39.194) ⇒ оговорка снялась молча, и это надо
подтвердить или переписать сознательно, а не по факту исчезновения строки.
**7. ⚠ СЕМЬ ПРОТУХШИХ ТОКЕН-ЯКОРЕЙ В `backend/docs/` — и до сегодня их не видел никто.** Корень
`backend/docs` в линтере ОТСУТСТВОВАЛ с самого его заведения; добавлен 04.09 (`docs/scripts/counts.py`,
греп `backend/docs` в `lint_anchors`). Сегодня краснеют: `DISCLOSURE_LAW_DESIGN.md:40-44` (пять целей
подряд — `quality.go`, `status.go` ×3, `bookbuild.go`), `:264` и `MONEY_HONESTY_REPORT.md:285`
(`chunkrun.go:40`). ⚠ Эррата D15.2 от 02.09 УЖЕ указывала мимо — гейт не мог этого увидеть по
построению. Команда: `python3 docs/scripts/counts.py --lint`.
**8. Ссылки «строка N» на строки, ВЫПАВШИЕ из таблицы при закрытии:** `README.md:26` (103 — фантом,
снят 31.08), `pipeline.puml` (99 · 100 · 101 · 125 · 145), `DISCLOSURE_LAW_DESIGN` (246 · 238 · 239 ·
194), `internal/membank/decisions.go:84` (210 — закрыта 04.09). Бэклог закрытые строки НЕ хранит, а
доки зоны адресуют их как живые.
**9. Мелочи с адресом:** `README.md:5` «актуализировано 01.08», тело цитирует ноты 2328.08 ·
`13-tech-debt-anchors.md:174` цитирует `STACK.md` в состоянии, которого там уже нет (ручка эффорта
`pro`оба носителя датированы 04.09 и противоречат) · `SEAM_PACK_FINDINGS.md:130` «у `bank-apply`
ноль вызывающих на платформе» — `platform/internal/runner/bankapply.go` строит вызов · `:1133` «два
хита» → четыре · `MONEY_HONESTY_PLAN-NOTE.md:35` «22 поля» → 21 на её же HEAD.
**10. НЕ ОПИСАНО, А НАДО:** пакет `internal/langscreen` (новый, на денежном пути вердиктов) в README
не упомянут вовсе · карта пакетов не называет ~20 несущих файлов `internal/pipeline` (`volume.go`,
`rebill.go`, `reprice.go`, `refusal.go`, `terminologist.go`, `bookbuild.go`…) и пять в `internal/store` ·
`cmd/tmmutate` (каталог 141 посадки, объявленный ГЕЙТОМ) и `cmd/tmvet` не названы · цена закона
раскрытия («загейчен на 40 %», Г1/Г2 не построены) в статус-борде 09 не оговорена.
**Что оркестратор поправил СВОЕЙ рукой в свою зону тем же заходом:** статус-борд
`09-target-architecture.md` говорил «цикл РАЗОМКНУТ» и «канон 0.9.0» в день своего же «освежения» —
оба ложны с `adf5e53`/`58bca19`; висячая ссылка на закрытую 246 в шапке секции «Бэкенд»; корень
`backend/docs` в линтере.
## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора)
Закрытые строки здесь НЕ хранятся — они уходят в D-лог с номером решения. **ID строки стабилен навсегда** (не перенумеровывается и не переиспользуется — на «строку N» ссылаются доки и промты, D39.80). Вес: «блокер-очереди» = мешает текущему шагу · «скоро» = ближайшие 12 касания · «когда-нибудь» = записано, не потеряно. Длинная строка начинается жирным лидом — таблица сканируется по лидам; «диспозиция сверху, археология вниз», ячейка >800 байт — кандидат на выселение в `architecture/13-tech-debt-anchors.md` (D39.125 п.3/D39.126). ⚠ **Счёт очереди — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов в 104 и честность в 105); ленту ✅ шапки читать как «долга нет» неверно (D39.89). **Зонные бэклоги (решение владельца 02.08, D39.84):** фронт и платформа ведут СВОИ бэклоги (`frontend/docs/BACKLOG.md` · `platform/BACKLOG.md`) — их строки сюда НЕ заходят; здесь движок/полигон/доки, включая движковые стыки фронта (зона «бэкенд», как 99102); строки 96/97 переехали в платформенный (П-1/П-2), надгробия-указатели сохранены.
@ -197,7 +267,7 @@
| 249 | **Девять рядов бэклога потеряли слово веса, и гейт на них НЕ краснеет.****Лечение ПОСТРОЕНО (сверено кодом 02.09): вес судится ПРЕФИКСОМ ячейки**`docs/scripts/counts.py`, греп `BACKLOG_WEIGHTS` (три слова: «блокер-очереди» · «скоро» · «когда-нибудь»), и «скоро» считается тем же префиксом. Этим убита ВТОРАЯ половина класса: подстрока ловила слово в ПРОЗЕ, и фраза «переведена из «скоро»» ре-добавляла ряд в счёт — число скакнуло **53 → 56** при одной новой строке (замер 02.09, пере-счёт скриптом). ⚠ Гейт рождён ЗЕЛЁНЫМ, а не красным: девять известных рядов внесены «дедовщиной» — греп `WEIGHT_GRANDFATHERED` там же, ряды **5 · 13б · 94 · 96 · 97 · 149 · 205 · 221 · 246**. **ЖИВОЙ ОСТАТОК — сами ячейки:** у 96/97 прочерк ЗАКОНЕН (надгробия строк, уехавших в зонный бэклог, D39.84), остальные семь потеряли вес молча и чинятся оркестратором — каждая починенная выходит из списка дедовщины. ⚠ Два ряда шире класса: **149** («исполнен и заленден 10.08») и **205** («сделано 21.08») объявляют себя ИСПОЛНЕННЫМИ прямо в колонке веса, хотя по правилу таблицы закрытые строки в ней не живут — это либо живой остаток без веса, либо непойманный класс C; **246** несёт самодельное «СРОЧНО», которого в словаре нет. | оркестратор | скоро ($0, гигиена трекера) | правка семи ячеек → выход из `WEIGHT_GRANDFATHERED` | ревизия доков 02.09, приёмка контролёра |
| 217 | **Скрипты полигона захардкодили АБСОЛЮТНЫЕ пути двух корней и не работают на этой машине вовсе.** ДВА РАЗНЫХ слома. **Корень репо** — смена пользователя: литерал в 121 файле, из них 104 дословно `REPO = Path("/home/ubuntu/projects/textmachine")`, портабельных форм всего 5. **Корень книг**оба события порознь: литерал `/home/ubuntu/books` 86 файлов (пользователь), портабельный `Path.home()/"books"` 89 файлов (переезд каталога; на прежних машинах работал). Объединение 173 файла. Пользователь теперь `ubuntu-26`, книги переехали в `<репозиторий>/books` ⇒ ломается и то и другое, включая ЖИВОЙ гейт фазы Д `eval/conformance.py:49`=`REPO = Path("/home/ubuntu/projects/textmachine")`. Живых носителей 26 по корню книг (среди них портабельная форма преобладает 20:6) плюс корневые гейты и сборщики корпусов; остальное — скрипты закрытых эксп-1216, их владелец велел ВЫБРОСИТЬ, а не чинить (D39.157 п.4а). Форма правки — за зоной; приор оркестратора: один модуль путей, корень резолвится МАРКЕРОМ вверх по дереву (движок так и делает — `backend/internal/miner/miner_parity_test.go:29`=`derived from the repository MARKER`), книги от него, обе ручки перекрываются env | полигон | скоро (блокирует любой прогон зоны) | пак путей полигона | переезд машины 24.08, №19 |
| 219 | **Line-якоря в тела D-лога обречены съезжать, и механизм именно в дисциплине эррат.** Эрраты вписываются в КАРТУ ШАПКИ (append-only, D23.3), то есть в начало файла, — значит каждая эррата сдвигает номера строк ВСЕХ тел ниже, и любой якорь вида `05-decisions-log.md:NNN` умирает молча. ⚠ Замерено на себе 27.08: три эрраты за сессию убили якоря в `docs/architecture/17-seam-inbound-law.md` (греп `Эррата, которую ратифицирующая нота обязана поставить`) и `docs/research/25-seam-cold-review.md:5`=`адресуем НОМЕРОМ, а не строкой` (оба целили в `:232`, тело уехало на `:239`; ⚠ 02.09 обе площадки уже переведены на форму номера ноты — прежний голый указатель `17-seam-inbound-law.md:120` показывает пустую строку). Лечение — не пере-нацеливание (оно повторится через эррату), а СМЕНА ФОРМЫ якоря: в тела D-лога целиться номером ноты (`^## D39.106`), который стабилен навсегда, а не строкой. ⚠ **Первая половина лекарства ПОСТРОЕНА:** `counts.py --lint` сверяет якоря в тела D-лога СТРУКТУРНО и без токена — владелец целевой строки (ближайший `^## D<номер>`) обязан совпасть с номером, названным рядом; остаётся перевести живые якоря на форму номера | оркестратор | скоро (растёт с каждой эрратой) | `--lint` учит форму `файл:^## D<номер>`, живые якоря в D-лог переводятся на неё | ревью доков 24.08, механизм и отсутствие носителя — 27.08, D39.160 |
| 220 | **Репо-широкий гейт доков бутстрапится пакетным менеджером ОДНОЙ зоны, и та заморожена.** Диспетчер `.git/hooks/pre-commit` зоно-нейтрален по построению (`for hook in */scripts/githooks/pre-commit`, `#!/bin/sh`, node не нужен) и судит `CLAUDE.md` + `docs/**` + `platform/docs/**` + `frontend/docs/**` (`docs/scripts/counts.py:554`=`ROOT / "CLAUDE.md"`), но единственный его УСТАНОВЩИК — `frontend/scripts/githooks/install.mjs`, вызываемый ключом `prepare` из `frontend/package.json`. Охват и бутстрап не совпадают ⇒ инструмент решает свою задачу не в полной мере. Проверено исполнением 24.08: на этой машине `.git/hooks/` содержал только `*.sample`, гейт МОЛЧАЛ, ничего не проверив, и поймал первые четыре дефекта только после ручной установки; сессия бэкенда или доков `npm install` не делает никогда. Приор: зоно-нейтральный установщик в `docs/scripts/githooks/` как ЕДИНСТВЕННЫЙ писатель диспетчера, `prepare` фронта зовёт его — фронтовая половина выписана пингом №19 в зонный журнал фронта. ⚠ Ручная установка — временная мера, пока строка открыта; записывать её как порядок работы ЗАПРЕЩЕНО (это ровно тот обход, цену которого называет шапка `CLAUDE.md`) | доки + фронт | скоро | зоно-нейтральный бутстрап + правка `prepare` при разморозке | аудит переезда 24.08, №19 |
| 220 | **Репо-широкий гейт доков бутстрапится пакетным менеджером ОДНОЙ зоны, и та заморожена.** Диспетчер `.git/hooks/pre-commit` зоно-нейтрален по построению (`for hook in */scripts/githooks/pre-commit`, `#!/bin/sh`, node не нужен) и судит `CLAUDE.md` + `docs/**` + `platform/docs/**` + `frontend/docs/**` (`docs/scripts/counts.py:559`=`ROOT / "CLAUDE.md"`), но единственный его УСТАНОВЩИК — `frontend/scripts/githooks/install.mjs`, вызываемый ключом `prepare` из `frontend/package.json`. Охват и бутстрап не совпадают ⇒ инструмент решает свою задачу не в полной мере. Проверено исполнением 24.08: на этой машине `.git/hooks/` содержал только `*.sample`, гейт МОЛЧАЛ, ничего не проверив, и поймал первые четыре дефекта только после ручной установки; сессия бэкенда или доков `npm install` не делает никогда. Приор: зоно-нейтральный установщик в `docs/scripts/githooks/` как ЕДИНСТВЕННЫЙ писатель диспетчера, `prepare` фронта зовёт его — фронтовая половина выписана пингом №19 в зонный журнал фронта. ⚠ Ручная установка — временная мера, пока строка открыта; записывать её как порядок работы ЗАПРЕЩЕНО (это ровно тот обход, цену которого называет шапка `CLAUDE.md`) | доки + фронт | скоро | зоно-нейтральный бутстрап + правка `prepare` при разморозке | аудит переезда 24.08, №19 |
| 49 | **Этапы Б+В спеки D15.2** (content-addressed resume / `guard_hash` — D39.31 сознательно не строил) ; этап В = tmctl export-контракт D29.1 (annot-v1 · цвет-мап+rollup · политика красных fail-closed) + операторский протокол-документ релиза гендер-твиста (D5.1): сам механизм УЖЕ построен — until_ch-правка → точечный re-edit со сметой и $0-пере-пином (`repin.go`/`rebill.go`, D39.42 п.5/D39.45) | бэкенд | скоро (ПОДТЯНУТА D39.81: annot-v1 = источник замечаний для фронта — критический путь подключения) | отдельное решение (annot-половина — по контракту 14, D39.99) | D39.34(4), D33 п.5, D39.81 |
| 49а | **ALTER-шаги миграций v8v14 не идемпотентны вопреки шапке `migrate.go:9-11`** (полу-применённая БД не сходится; счётчик версий скрывает) — находка критика полноты пака-19 | бэкенд | когда-нибудь | отдельное решение | D39.56, PACK19_BUILD §6.9 |
| 50 | F3-остаток идемпотентности | бэкенд | когда-нибудь | отдельное решение | D39.34(4) |
@ -286,7 +356,7 @@
> строки бэклога закрыты тем же лендингом — **D39.185**. Диспозиция по D25.1 ратифицирована D39.175 п.2
> (drift — не дыра файла; лестница — владельцу между паком и дверью).
>
> **Свободная работа зоны — строками бэклога:** **246** (СРОЧНО, две копии полосы отказов обещают РАЗНОЕ) ·
> **Свободная работа зоны — строками бэклога:** ~~**246**~~ (ЗАКРЫТА 04.09 актом D39.194 — копия потребителя приведена к производителю) ·
> **247** · **232** · **233** · **197** (ресурс ушёл в фазу 1, строка не взята) · **228** · **229** · **230** ·
> **141**-остаток · **131**. ⚠ Строк 231 и 236 в таблице БОЛЬШЕ НЕТ — 231 съел пак «деньги», 236 сужена D39.175.
>

View file

@ -10,7 +10,7 @@
> ⚠ **КАК ЧИТАТЬ ШАПКУ (освежена 04.09).** Таблица «слой → статус → пак/D» ниже — единственный статус-борд этого файла: она БЬЁТ тело документа, а D-лог бьёт её. **Хроники лендингов паков здесь больше нет** — кто что построил и когда живёт в журнале решений: `05-decisions-log.md` + реестр `05-decisions-index.md` + слайсы `../archive/architecture/` (эры D39.100D39.190 покрывают всю стройку платформы, шва, писателя книги и числа согласия).
> ⚠ **ЗАКОН РАСКРЫТИЯ (D39.181) — норма зоны `backend/`, а не пункт одного пака:** число, которое движок публикует, обязано ехать со СВОИМ БАЗИСОМ, а присутствие поля не может быть булевым признаком, если оно перестало им быть. Из него же — `config_drift_basis` в `status --json` и леджер доставки в кадре `finished` (`StreamVersion` 1.2, D39.182 §4). **D39.182** («деньги и честность выдачи») добавил класс BANK в разложение денег и `noteSourceVintage`.
> ⚠ **ПОСТРОЕНО, но в семь слоёв НЕ укладывается** (движковые оси рядом со слоями — читать шапку как полную нельзя без них): объёмный потолок оплаченной работы `--max-units`/`VolumeStop` (`backend/internal/pipeline/volume.go`, D39.170; ратифицированная единица продажи — D39.165 §1) · гейт схемы движка (`backend/internal/store/sqlgate_test.go`, D39.173: каждый SQL-оператор компилируется против схемы, поднятой продовой цепью миграций) · дверь правок банка `POST /books/{bookId}/bank/corrections` смонтирована синхронно (D39.162) · ключи деплоя доезжают до движка аргументом `--keys-file` (строка 211 ЗАКРЫТА, блокером живого прогона больше не является) · полоса прогресса СКВОЗНАЯ, подпись стадии — второе исключение границы (D39.162/163) · пере-проход можно КУПИТЬ (D39.166) · инъекция банка не теряется на провайдере с одним системным слотом (D39.164) · **ЧИСЛО СОГЛАСИЯ НА ПУТИ ВТОРОЙ ПОКУПКИ (03.09, D39.187):** пере-покупка прайсится по модели, которую стадия резолвит СЕЙЧАС, с округлением ВВЕРХ и оговоркой в тексте согласия (D39.150 п.1) — а **обещание точности снято с провода** во всех пяти местах, где стояло: контракт механизма теперь «не точность, а НАПРАВЛЕНИЕ ошибки — никогда не занизить молча»; фигура едет с базисом двумя новыми полями `status --json` (`rebill_historical_rows` · `rebill_model_moved_rows`) · **слот объёмного гранта (вторая половина строки 232):** юнит, начатый прежним прогоном и не отгруженный по оси `finalStageWave`, дописывается ВНЕ гранта и слота повторно не тратит ⚠ **следствие денежное и НЕ ратифицированное:** грант `--max-units N` оплачивает ДО 2N выходных юнитов (замер приёмки: грант 2 → четыре юнита, шесть вызовов провайдера), слово владельца 03.09 — «подумаем на этот счёт», до его решения `--max-units` держит СЛОТЫ, а деньги держит только `--ceiling-usd` (эррата 03.09-а к D39.170).
> ⚠ **Канон контракта — 0.9.0** (D39.180, лендинг пака P12 31.08), не 0.4.0 и не 0.7.0. Носители — `docs/architecture/14-api-contract/openapi.yaml` и `platform/internal/httpapi/capabilities.go`, они сходятся гейтом.
> ⚠ **Канон контракта — 0.10.0** (D39.194, лендинг 04.09 вместе с дверью выдачи), не 0.9.0 и не 0.4.0. Носители — `docs/architecture/14-api-contract/openapi.yaml` и `platform/internal/httpapi/capabilities.go`, они сходятся гейтом.
>
> ⚠ **ПЛАТФОРМЕННЫЙ ШОВ — что построено 03.09 (D39.188, пак P13).** Оплаченный прогон продолжается на ТЕ деньги, за которые продан: `reopen` читает бюджет ИЗ ХОЛДА первой попытки, а прогон без холда отвечается ОШИБКОЙ, не цифрой (прежде бюджет пере-выводился по текущей ставке — `PD-168`) · **владение потоком переживает проход свипа:** чтение ОСТАНАВЛИВАЕТСЯ на чужом handshake'е (`ErrForeignStreamAhead`), потому что до этого чужие события ложились на оплаченную попытку — чужой `ceiling` ставил `paused` живому прогону, `unit_done` писал непокупленные главы (`PD-438`, major) · операторские ручки: `run unquarantine` и колонка QUARANTINE · условия хоста батареи ВЫВОДЯТСЯ из тестовых исходников (`make conditions`), а не держатся списком в прозе · два гейта в `platform/internal/gates/`: перечень условий против исходников и класс «тревожный ряд ушёл из счёта незамеченным». ⚠ **Бамп формы манифеста безопасного порядка деплоя НЕ ИМЕЕТ ни в одну сторону** (`PD-436`): гейт интейка — строгое равенство одной константе, окна двух форм нет ⇒ стоп-мир. Пока окно двух паков открыто, форма ЗАМОРОЖЕНА (D39.190 п.5).
>
@ -22,7 +22,7 @@
> | 3 Контракт t/e | ✅ ПОСТРОЕН ЗА `enabled:false`: `checks.RepairCandidates` (позиционная детекция) · read-only скан остатка · машинерия ремонта §15.2; **включение платного пути = решение владельца по замеру остатка**; эмпирика контракта: диффы ОТЛОЖЕНЫ (D39.108, экспы 19/20; D21.4/D21.10 закрыты), full-regen ПОДТВЕРЖДЁН, точечная починка как ЗАМЕНА редактора отклонена и принята формой «механический пре-гейт ПЕРЕД редактором» (D39.117; строка 142, строка 106 понижена) | пак-16 (D39.24), **D39.108**, **D39.117** |
> | 4 Память | ✅ ПОСТРОЕН + ДОСТРОЕН паком-20 + ✅ **ВХОДНАЯ ДВЕРЬ ПОСТРОЕНА (D39.158)**: $0-глагол `tmctl bank-apply` (проекция `--dry-run`, всё-или-ничего, байтовый no-op идемпотентен), писатель решений `internal/membank/decisions.go`, стоп банка — ФЛАЖОК, который движок чтит сам (память предъявления `bank_stop_presented`, схема store v16), класс отказа 15 `write_incomplete`. Роли носителей и поток «источники → вид → проекции» — `18-bank-ontology.md`; состав пака-20 (ТЕРМИНОЛОГ · флаговый стоп `--verify-bank` · двухсекционная редакторская инъекция · точечная ре-редактура · банкнота отдельным шиппинг-файлом · языковой экран `target_script`) — D39.4145/5053; ⚠ D39.104: инъекция схлопывается в ЕДИНЫЙ закон-блок, маркер ⟨проверить⟩ снимается с провода — внесение = строка 134 ПОСЛЕ пробы 18; жанровый словарь ОТМЕНЁН (D39.47) | пак-1 · пак-11 · **пак-20 (D39.4145/47/5053)** |
> | 5 Качество | ✅ детерм. часть: `QualityReport` · число/omission-гард · DC/пак-13-чекеры · repair-остаток; семантический span-судья/полярность — НЕ строился (защита = editor-swap, D38.4) | D39.2 · D38.3 · пак-13 (`2f91b04`) · пак-16 |
> | 6 Export | ✅ ДВИЖКОВАЯ половина ПОСТРОЕНА: `checks.ExportNormalize` на каждом финале; санитайзер-классы strip+export · **писатель книги: `internal/bookfile` + `tmctl build` (EPUB 3 + txt, D39.175)**; холодный прогон 31.08 предъявил собранный EPUB настоящего перевода, `epubcheck` 0/0/0/0. **ПЛАТФОРМЕННАЯ половина НЕ ПОСТРОЕНА — цикл РАЗОМКНУТ:** канон обещает `createExport`/`getExport`, платформа их не монтирует (`grep -rn 'createExport\|getExport' platform/internal/ --include=*.go` → 0; смонтировано 15 операций из 20). Долг с P8; строится паком «закрыть цикл», выдан 04.09 (D39.190 п.5) | D39.2 · D38.3 · D39.175 · D39.178 |
> | 6 Export | ✅ ДВИЖКОВАЯ половина ПОСТРОЕНА: `checks.ExportNormalize` на каждом финале; санитайзер-классы strip+export · **писатель книги: `internal/bookfile` + `tmctl build` (EPUB 3 + txt, D39.175)**; холодный прогон 31.08 предъявил собранный EPUB настоящего перевода, `epubcheck` 0/0/0/0. **ПЛАТФОРМЕННАЯ половина ПОСТРОЕНА 04.09, ЦИКЛ ЗАМКНУТ ЖИВЬЁМ** (`adf5e53`, D39.194): пользователь получил EPUB настоящего ПЛАТНОГО перевода ЧЕРЕЗ API, `epubcheck` 5.3.0 на СКАЧАННОМ файле 0/0/0/0. Дверь — три адреса (`createExport`/`getExport`/`downloadExport`), `202`+`Location`, поллинг с `Retry-After`, Range 206, TTL с уборкой, идемпотентность. Проверка вместо счёта: `grep -rn 'createExport\|getExport' platform/internal/ --include=*.go`НЕ пусто; операций в каноне 21, смонтировано 18. ⚠ **Но книгу через API НЕЛЬЗЯ ДОЧИТАТЬ**`PD-440`, разбор в `15-money-path.md` §«ОТКРЫТАЯ РАЗВИЛКА 04.09»: короче десяти глав книга не переводится вовсе | D39.2 · D38.3 · D39.175 · D39.178 |
> | 7 Гигиена | ✅ ПОСТРОЕН: реестр role→инъекция · вынос `foldModelWire` · снос сирот/`gatesEnabled` · **target-aware гейты ПО ДАННЫМ — П1 «цель-шов» (фаза 2, D39.64: `isRuTarget` удалён, `TargetActive`/`TargetScriptNonLatin`, токенизатор цели из `word_script`); остаток — ё-фолд/segmentation за подписью (бэклог-строка 14)** | D39.2 · паки 1116 · **фаза 2 (D39.64)** |
>
> **Общность (фаза 2) ИСПОЛНЕНА И ПРИНЯТА — D39.64**, отчёт `../archive/reports/GENERALITY_PHASE2_2026-08-01.md`: П0 хеш эмбед-данных (`embedded_version` в снапшоте) · П1 цель-шов (слой 7) · П2 скрипт-шов источника (`lang-script.txt`) · П3 нарезка/оценка (один дом `DenseScript`) · П4 манифест-по-каналам (`packAlgoVersion` не бампался); голден вердикт-нейтрален (0/172); П5 майнер гейтится второй книгой; 9 флагов §5 — очередь владельца (бэклог-строка 14). **Карта языковой привязки ВСЕГО движка — `../archive/reports/GENERALITY_RESEARCH_2026-07-31.md` (D39.60)**; пак-19 «голос/состояние» — D39.5456.

View file

@ -551,8 +551,13 @@ def lint_anchors() -> tuple[list[tuple[int, str]], dict[str, int]]:
"""
bad: list[tuple[int, str]] = [] # (ранг тяжести, текст) — ранг нужен для приоритета под капом
tally = {"content": 0, "notoken": 0, "external": 0, "unjudged": 0, "files": 0}
# ⚠ `backend/docs` добавлен 04.09 (оркестратор №22): корень отсутствовал с самого заведения линтера,
# и доки зоны ДВИЖКА не проверял никто — при том что они несут токен-якоря и сами ссылаются на этот
# гейт как на защиту. Цена дыры предъявлена внешней ревизией: эррата от 02.09 в
# `D15.2-content-addressed-resume-spec.md` УЖЕ указывала мимо, и линтер не мог этого увидеть по
# построению. Гейт, не покрывающий корень, доказывает состояние только тех корней, которые обходит.
targets = [ROOT / "CLAUDE.md"] + [
p for base in ("docs", "platform/docs", "frontend/docs")
p for base in ("docs", "platform/docs", "frontend/docs", "backend/docs")
for p in (ROOT / base).rglob("*.md")
if "archive" not in p.parts and str(p.relative_to(ROOT)) not in LINT_SKIP_DOCS
]