Second cut pass in the backend zone: restore what the review found lost, and take the sediment the first pass left behind
This commit is contained in:
parent
4a1ecc3aa6
commit
1d84cff75e
5 changed files with 145 additions and 132 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# backend/ — Go-бэкенд TextMachine
|
||||
|
||||
Зона сессии «Бэкенд». Контракт — `docs/architecture/05-decisions-log.md` (свежая голова — с хвоста файла); целевая архитектура (7 слоёв, инвариант общности §0.1 — любая книга/пара/структура; статус стройки — шапка-таблица) — `docs/architecture/09-target-architecture.md`; норматив общности — `12-go-style-notes.md`; **актуальный сессионный промт — список «Активные хендофф-промты» в `docs/README.md`**; контракты Фазы 0 — `03-implementation-notes.md` (через баннер); квирки провайдеров — `docs/experiments/00-provider-quirks.md` (читать ПЕРЕД правкой адаптеров/вызовами). **Язык-данные майнера — вне пайплайна: `internal/lang`+`configs/langpacks/` (D39.16); пар-калибровки — `configs/pairs/<пара>.yaml`, промпты — `prompts/<пара>/<роль>.md` по конвенции (D39.23).** **Подсистемы (`chunk`/`miner`/`checks`/`membank`) не импортируют друг друга и не импортируют `pipeline` — драйвер является композит-корнем (D39.23; проверяется `go list -deps`).** **`.env` не читать.**
|
||||
Зона сессии «Бэкенд». Контракт — `docs/architecture/05-decisions-log.md` (свежая голова — с хвоста файла); целевая архитектура (7 слоёв, инвариант общности §0.1 — любая книга/пара/структура; статус стройки — шапка-таблица) — `docs/architecture/09-target-architecture.md`; норматив общности — `12-go-style-notes.md`; контракты Фазы 0 — `03-implementation-notes.md` (через баннер). **Язык-данные майнера — вне пайплайна: `internal/lang`+`configs/langpacks/` (D39.16); пар-калибровки — `configs/pairs/<пара>.yaml`, промпты — `prompts/<пара>/<роль>.md` по конвенции (D39.23).** **Подсистемы (`chunk`/`miner`/`checks`/`membank`) не импортируют друг друга и не импортируют `pipeline` — драйвер является композит-корнем (D39.23; проверяется `go list -deps`).** **`.env` не читать.**
|
||||
|
||||
*(Актуализировано оркестратором 01.08 по мандату владельца, факты сверены по коду.)*
|
||||
|
||||
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
| Пакет | Что делает | Ключевые файлы |
|
||||
|---|---|---|
|
||||
| `cmd/tmctl` | CLI: `translate` / `status` (read-only N/M+паспорта глав+деньги, `--json`; работает ПРИ живом прогоне — store без flock) / `report` (request-log+леджер книги **+ per-run quality-report**: структурный KPI предл./нарратив-абзац, тире, cosmetic-strip/echo-rates, глоссарий-промахи, trust-gated — наблюдаемость, НЕ гейт; D39.2-T4) / `export` (**экспорт-поверхность для полигона**: final_hash→checkpoint→checks.ExportNormalize, manifest-join c pending/ghost-учётом, ConfigDrift-поле, `--plaintext`; D39.5) / `build` (**писатель книги**, строка 236: EPUB 3 + чистый txt из той же экспорт-проекции в `<project_db>.book.<fmt>` рядом с БД, пути — в `artifacts.book_files`; книга с ЛЮБОЙ дырой — pending/withheld/incomplete/ghost — по умолчанию отказ **exit 16** с перечнем, `--partial` пишет с пометкой на первой странице и маркером на каждой дыре; слова читателя — данные `configs/langpacks/<цель>/reader.txt`, вне снапшота; `--format epub,txt`, `--out`) / `redrive` (переатака флагнутых: `--chapter/--chunk/--reason/--dry-run`, D15.3) / `manifest` (**$0-производитель персиста манифеста глав/чанков**, строка 100: нужен ДО первого прогона — дерево глав разобранной, но не запущенной книги; `--json` печатает сам документ) / `migrate` (**$0-write-open без прогона** (D39.134): единственный путь, доводящий схему проекта до головы бинаря — read-only команды её НЕ мигрируют. Грузит ТОЛЬКО `book.yaml` — ни цен, ни ключей на $0-пути (строка 146); restore point берёт ПОД ЛОКОМ и только когда шаг реально применяется (имя `<метка>-pre-migrate.db` — вне секундного неймспейса платного пути, строка 173); несовпадение схемы у read-only путей — типизированный отказ **exit 13** с машинным токеном `schema_mismatch found=N expected=M`). **ДВА потолка прогона, и они ортогональны.** `--ceiling-usd` (строка 145) — ДЕНЬГИ: перекрывает книжный `ceilings.book_usd` ТОЛЬКО на этот прогон, в book.yaml не пишется, ноль/отрицательное = отказ запуска; каппит КУМУЛЯТИВНУЮ трату книги, а не приращение прогона. `--max-units` (D39.165 §1б) — ОБЪЁМ: не больше N ВЫХОДНЫХ ЮНИТОВ (гранулярность `units_total` манифеста, та самая, в которой платформа продаёт главы) будет ОПЛАЧЕНО этим прогоном. Юниты, которые прогон отдаёт за $0 (резюм, ре-пин), едут бесплатно и потолок не тратят; ретраи и эскалации — тоже нет, они внутри юнита. Принимает только `translate`. **Остановка по объёму — ЗАВЕРШЕНИЕ (exit 0), а не пауза:** словарь кодов выхода не расширялся, различение живёт в отчёте прогона и в логе. Отчёт различает ДОСТАВКУ (юнит, которого не было) и ПЕРЕ-ДЕЛКУ (уже доставленный юнит под сдвинутым снапшотом) — покупка, целиком ушедшая в переделку, обязана читаться как переделка. ⚠ На книге, которая МАЙНИТ банк, вторая покупка требует `--resnapshot` (авто-банк растёт между покупками и двигает edit-снапшот) — прогон предупреждает об этом в логе. main — тонкая обвязка: разбор/exit-коды/.env/рендеры в тестируемых функциях | `main.go`, `invocation.go`, `render.go`, `dotenv.go` |
|
||||
| `internal/llm` | OpenAI-совместимый транспорт + retry/backoff, **capability-слой** (budget_field/temperature/reasoning per-модель), провайдеры openai/local (no-proxy)/anthropic (DEPRECATED-референс); `failover.go` удалён паком-17 — маршрутизация лейблами живёт в config/pipeline (канал B, один хоп `chain[0]`, fail-closed) | `httpllm.go`, `capability.go`, `provider_*.go` |
|
||||
| `cmd/tmctl` | CLI: `translate` / `status` (read-only N/M+паспорта глав+деньги, `--json`; работает ПРИ живом прогоне — store без flock) / `report` (request-log+леджер книги **+ per-run quality-report**: структурный KPI предл./нарратив-абзац, тире, cosmetic-strip/echo-rates, глоссарий-промахи, trust-gated — наблюдаемость, НЕ гейт; D39.2-T4) / `export` (**экспорт-поверхность для полигона**: final_hash→checkpoint→checks.ExportNormalize, manifest-join c pending/ghost-учётом, ConfigDrift-поле, `--plaintext`; D39.5) / `build` (**писатель книги**: EPUB 3 + чистый txt из той же экспорт-проекции в `<project_db>.book.<fmt>` рядом с БД, пути — в `artifacts.book_files`; книга с ЛЮБОЙ дырой — pending/withheld/incomplete/ghost — по умолчанию отказ **exit 16** с перечнем, `--partial` пишет с пометкой на первой странице и маркером на каждой дыре; слова читателя — данные `configs/langpacks/<цель>/reader.txt`, вне снапшота; `--format epub,txt`, `--out`) / `redrive` (переатака флагнутых: `--chapter/--chunk/--reason/--dry-run`, D15.3) / `manifest` (**$0-производитель персиста манифеста глав/чанков**: нужен ДО первого прогона — дерево глав разобранной, но не запущенной книги) / `migrate` (**$0-write-open без прогона** (D39.134): read-only команды схему НЕ мигрируют. Грузит ТОЛЬКО `book.yaml` — ни цен, ни ключей на $0-пути (строка 146); restore point берёт ПОД ЛОКОМ и только когда шаг реально применяется (имя `<метка>-pre-migrate.db` — вне секундного неймспейса платного пути, строка 173); несовпадение схемы у read-only путей — типизированный отказ **exit 13** с машинным токеном `schema_mismatch found=N expected=M`). **ДВА потолка прогона, и они ортогональны.** `--ceiling-usd` — ДЕНЬГИ: перекрывает книжный `ceilings.book_usd` ТОЛЬКО на этот прогон, в book.yaml не пишется, ноль/отрицательное = отказ запуска; каппит КУМУЛЯТИВНУЮ трату книги, а не приращение прогона. `--max-units` (D39.165 §1б; механика и денежный отчёт — D39.170) — ОБЪЁМ: не больше N ВЫХОДНЫХ ЮНИТОВ (гранулярность `units_total` манифеста, та самая, в которой платформа продаёт главы) будет ОПЛАЧЕНО этим прогоном. $0-юниты (резюм, ре-пин) потолок не тратят. Принимает только `translate`. **Остановка по объёму — ЗАВЕРШЕНИЕ (exit 0), а не пауза:** различение живёт в отчёте прогона и в логе. ⚠ На книге, которая МАЙНИТ банк, вторая покупка требует `--resnapshot` (авто-банк растёт между покупками и двигает edit-снапшот) — прогон предупреждает об этом в логе. main — тонкая обвязка: разбор/exit-коды/.env/рендеры в тестируемых функциях | `main.go`, `invocation.go`, `render.go`, `dotenv.go` |
|
||||
| `internal/llm` | OpenAI-совместимый транспорт + retry/backoff, **capability-слой** (budget_field/temperature/reasoning per-модель), провайдеры openai/local (no-proxy)/anthropic (DEPRECATED-референс); маршрутизация лейблами живёт в config/pipeline (канал B, один хоп `chain[0]`, fail-closed; D4/D39.26) | `httpllm.go`, `capability.go`, `provider_*.go` |
|
||||
| `internal/ledger` | Цены по usage (вкл. reasoning/cache-поля), `PriceForResponse` по фактической модели | `pricing.go` |
|
||||
| `internal/store` | SQLite (modernc, CGO-free), цепочка миграций `schema_version`, reserve/settle+checkpoint, chunk_status, глоссарий (+подписной цикл терминолога), ruby, retrieval_state, request_log; `OpenReadOnly` — без flock/миграций/recovery для status/report/export (схема не совпала — типизированный `*store.SchemaMismatchError{Found,Expected}`, обе стороны); `Migrate` (+шов `beforeApply` под локом: restore point берётся там) — поверхность деплой-шага строки 174, `SchemaHead` — та самая `Expected`; write-open БД новее бинаря теперь ОТКАЗ, а не тихое открытие | `ledger.go`, `migrate.go`, `glossary.go`, `store.go` |
|
||||
| `internal/store` | SQLite (modernc, CGO-free), цепочка миграций `schema_version`, reserve/settle+checkpoint, chunk_status, глоссарий (+подписной цикл терминолога), ruby, retrieval_state, request_log; `OpenReadOnly` — без flock/миграций/recovery для status/report/export (схема не совпала — типизированный `*store.SchemaMismatchError{Found,Expected}`, обе стороны); `Migrate` (+шов `beforeApply` под локом), `SchemaHead` — та самая `Expected`; write-open БД новее бинаря — ОТКАЗ (D39.134) | `ledger.go`, `migrate.go`, `glossary.go`, `store.go` |
|
||||
| `internal/config` | fail-fast загрузка models/pipeline/book; **эхо-мина-гейт** `echoMineViolation`; `CheckRunnable` блокирует неисполнимое (C2/fanout/judge); **пар-слой** (D39.23): `configs/pairs/<пара>.yaml` — калибровка нарезки + коридор длины пары; **промпт-резолв КОНВЕНЦИЕЙ** `prompts/<пара>/<роль>.md` из `Book.LangPair()`+роли, **fail-loud на пару без пакета** (ja-книга не едет молча через zh-промпт), осознанное исключение — `prompt_override` на стадии | `models.go`, `pipeline.go`, `pair.go` |
|
||||
| `internal/text` | Нормализация и рун-примитивы, общие для банка/майнера/чекеров (script-agnostic слой, `lang` НЕ импортирует): `NormalizeSourceKey`/`NormalizeTargetForm` (версионированный артефакт `NormVersion()`, фолдится в снапшот), `NormalizeSource`, `TokenizeScript` (алфавит цели из данных, Mn-фолд U+0301; `TokenizeCyrillic` = ru-дефолт-обёртка), `DenseScript` — единый дом sizing-таксономии (D39.64) | `norm.go`, `runes.go`, `source.go` |
|
||||
| `internal/seed` | Схема сид-YAML книги (`File`/`Term`/`Decl`/`Alias`) — общий артефакт: майнер её ПИШЕТ (mined-дельта), банк ЧИТАЕТ (`LoadGlossarySeed`); тип общий, поэтому эмиссия не может разъехаться с загрузчиком | `seed.go` |
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
5. **Эскалация:** ровно 1 хоп, результат РЕ-гейтится, retry-бюджет не сбрасывается, editor pinned, канал adult — только permissive (fail-closed).
|
||||
6. **Детерминизм:** рендер — чистая функция snapshot; сортировки перед записью; никакого map-order в выводе; length-prefixed хэши; сорс-чанкер lossless (fuzz).
|
||||
7. **Нейтральность адаптера:** `internal/llm` не знает про перевод — контент-вердикты в раннере (disposition-слой, post-settle).
|
||||
8. **Экспорт-контракт (D39 слой 6, D39.5):** `checks.ExportNormalize` — эфемерная проекция (НЕ входит в request_hash/чекпоинты/деньги), применяется к КАЖДОМУ финальному тексту на всех выдающих поверхностях; **любая внешняя экстракция (полигон!) обязана читать `tmctl export`**, не сырые чекпоинты store — иначе видит ненормализованные байты и молча-неполную книгу (export делает manifest-join + drift-гард, сырое чтение — нет).
|
||||
8. **Экспорт-контракт (D39 слой 6, D39.5):** `checks.ExportNormalize` — эфемерная проекция (НЕ входит в request_hash/чекпоинты/деньги), применяется к КАЖДОМУ финальному тексту на всех выдающих поверхностях; **любая внешняя экстракция (полигон!) обязана читать `tmctl export`**, не сырые чекпоинты store — иначе видит ненормализованные байты и молча-неполную книгу.
|
||||
|
||||
## Подготовка ja-книги (чек-лист сида)
|
||||
|
||||
|
|
@ -44,9 +44,9 @@
|
|||
|
||||
## Как гонять
|
||||
|
||||
Стенд: WSL2 (localhost из-под прокси = 403 — для local-вызовов no-proxy транспорт). Книга-стенд: `/home/ubuntu/books/gu-zhenren/` (GB18030; тексты и производные ВНЕ git; парити-тесты майнера читают отсюда под `TM_MINER_PARITY=1`).
|
||||
Стенд: WSL2 (localhost из-под прокси = 403 — для local-вызовов no-proxy транспорт). Книга-стенд: `/home/ubuntu/books/gu-zhenren/` (GB18030; тексты и производные ВНЕ git).
|
||||
|
||||
Батарея — ОДНА команда, `make` из `backend/` (Makefile; собирать её руками больше не нужно):
|
||||
Батарея — ОДНА команда, `make` из `backend/` (Makefile):
|
||||
|
||||
```bash
|
||||
make battery # build · vet (оба тег-набора, + архитектурные анализаторы) · gofmt · lint · test -race
|
||||
|
|
@ -65,7 +65,7 @@ go run ./cmd/tmctl status --config example/book.yaml --json # $0, N/M+пасп
|
|||
go run ./cmd/tmctl report --config example/book.yaml # $0, quality-report (KPI/rates)
|
||||
go run ./cmd/tmctl export --config example/book.yaml # $0, экспорт-JSON для полигона (--plaintext для человека)
|
||||
go run ./cmd/tmctl manifest --config example/book.yaml # $0, пере-строить персист манифеста глав/чанков (--json — сам документ)
|
||||
go run ./cmd/tmctl migrate --config example/book.yaml # $0, довести схему проекта до головы бинаря (деплой-шаг: стоп прогонов → НОВЫЙ бинарь на место → migrate ИМ по каждой книге без открытых попыток → прогоны в работу)
|
||||
go run ./cmd/tmctl migrate --config example/book.yaml # $0, довести схему проекта до головы бинаря (деплой-порядок — D39.134 §3)
|
||||
go run ./cmd/tmctl translate --config example/book.yaml --ceiling-usd 0.5 # ДЕНЕЖНЫЙ потолок ТОЛЬКО на этот прогон, book.yaml не пишется
|
||||
go run ./cmd/tmctl translate --config example/book.yaml --max-units 10 # ОБЪЁМНЫЙ потолок: оплатить не больше 10 выходных юнитов; стоп = завершение (exit 0)
|
||||
# live-conformance (реальные провайдеры, платно, вне CI):
|
||||
|
|
@ -79,15 +79,15 @@ set -a; . ./.env; set +a; TM_LIVE=1 go test -tags live -run TestLive -v ./intern
|
|||
| `TestMinerFullBookParity` — единственная сверка Go-порта против Python-эталона на полной книге | `TM_MINER_PARITY=1` | jieba-словарь по внутрирепозиторному ПУТИ `eval/exp16/data/`, но ВНЕ git (`eval/.gitignore:4`) — клон его не получает, регенерируется из jieba 0.42.1 (SHA в `experiments/16-bank-mining.md:183`); плюс `~/books/gu-zhenren/{rerun/records.json, guzhenren-seed-v2.yaml}` |
|
||||
| `TestCheckerLabelsBaseline`, `TestCheckerLabelsCandidates`, `TestK6LabelsBaseline` — единственный замер precision/recall $0-гейтов | `TM_CHECKER_LABELS=1` | `~/books/gu-zhenren/labels/` |
|
||||
|
||||
Флаг переводит отсутствие данных из тихого скипа в громкий `Fatal` — то есть «я это гонял» становится проверяемым. Пути дефолтятся ОТ `$HOME` и от корня репозитория (не от `/home/ubuntu`), так что клон под любым пользователем и по любому пути находит то, что есть; точечные переопределения — `TM_CHECKER_LABELS_DIR`, `TM_MINER_PARITY_{CONTRAST,RECORDS,SEED}`.
|
||||
Пути дефолтятся ОТ `$HOME` и от корня репозитория (не от `/home/ubuntu`), так что клон под любым пользователем и по любому пути находит то, что есть; точечные переопределения — `TM_CHECKER_LABELS_DIR`, `TM_MINER_PARITY_{CONTRAST,RECORDS,SEED}`.
|
||||
|
||||
**Golden-гард детерминизма** (`golden_test.go` + `testdata/golden/`): пинит бит-в-бит snapshotID, request_hash, wire-тела, вердикты и resume-байты. Красный golden = wire/вердикты изменились = `--resnapshot` = переоплата. Обновлять ТОЛЬКО на ратифицированной смене поведения: `TM_UPDATE_GOLDEN=1 go test ./internal/pipeline/ -run TestGolden`; при re-capture — **маскированный структурный дифф** (хеши/версии → плейсхолдер) обязан быть пустым, если смена версий не меняла вердиктов.
|
||||
**Golden-гард детерминизма** (`golden_test.go` + `testdata/golden/`): пинит бит-в-бит snapshotID, request_hash, wire-тела, вердикты и resume-байты. Обновлять ТОЛЬКО на ратифицированной смене поведения: `TM_UPDATE_GOLDEN=1 go test ./internal/pipeline/ -run TestGolden`; при re-capture — **маскированный структурный дифф** (хеши/версии → плейсхолдер) обязан быть пустым, если смена версий не меняла вердиктов.
|
||||
|
||||
## Известный техдолг (не трогать молча; ЕДИНЫЙ трекер — таблица «Бэклог» в `docs/PROGRESS.md`, номера строк = она)
|
||||
|
||||
- **D15.2:** READ-половина `tmctl export` построена (D39.5); annotation/override-половина и content-addressed resume отложены (строка 49). F3 at-most-once — после D15.2 (строка 50).
|
||||
- **`Retries` НЕ фолдится в снапшот** (pre-existing, D39.4-LOW; сознательно так же для ручки `RegenerateEchoBeforeEscalate`, D39.64 — дефолт 0 = текущее поведение): в крэш-окне пониженный ретрай-бюджет молча бросает оплаченные OK-чекпоинты.
|
||||
- ⚠ ALTER-шаги миграций v8+ НЕ идемпотентны вопреки шапке `migrate.go` — полу-применённая БД не сходится (строка 49а).
|
||||
- Открытый остаток строки 79 — граница ПЛОТНОСТИ письма Go-константой `cjkScriptNames` (`internal/lang/script.go`); Cyrillic-хардкоды словесной границы DC-чекеров ПОГАШЕНЫ — она берётся из данных цели (`isTargetWordLetter`/`c.wordScript`, D39.39/D39.78).
|
||||
- Открытый остаток строки 79 — граница ПЛОТНОСТИ письма Go-константой `cjkScriptNames` (`internal/lang/script.go`).
|
||||
- `prompts/zh-ru/editor-mono.md` — DORMANT-референс D13.1 (не боевой, тестом закреплён); боевой = `prompts/zh-ru/editor.md` v3-discourse (БИЛИНГВ). Глосс-капы санитайзера (6 CJK / 24 лат-токен) — tunable-эвристики (D39.5). Флоры min_max_tokens = схема (D24.3).
|
||||
- Хвост LOW/NOTE-находок адверсариала D39.4 — в ledger-очереди (строка 53).
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ about work»*. Асимметрия уже узаконена, и аргумен
|
|||
Совершив необратимое — потратив деньги, записав файл, удалив файл, — движок обязан **сначала** выдать
|
||||
отчёт об этом и **только потом** сообщать об ошибке, случившейся позже на том же пути. Ошибка ПОСЛЕ
|
||||
необратимого действия не смеет ехать маршрутом, который отчёт подавляет.
|
||||
*Экземпляры: A3а · A2.*
|
||||
*Экземпляры: A3а.*
|
||||
|
||||
### Ст. 3. Расширение каналов — ЧЕТЫРЕ класса, и они РАЗНОЙ цены
|
||||
|
||||
|
|
@ -207,7 +207,7 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
фаза идёт после оплаченной черновой волны.
|
||||
|
||||
⛔ **ОГОВОРКА К ДЕШЕВИЗНЕ ПОЛОСЫ — она из находки A15 (§6), и без неё закон разрешает удешевлённо делать
|
||||
то, что сам же называет опасным.** Противоречие поймал оркестратор №21 при чтении дизайна; формулировка моя.
|
||||
то, что сам же называет опасным.**
|
||||
|
||||
Довод, которым полоса удешевлена, — «незнакомый номер поглощается ЧЛЕНСТВОМ и читается `refused`, а не
|
||||
`failed`». Это верно **по оси НОМЕРА и только по ней.** A15 показала, что разошёлся не номер, а **ОБЕЩАНИЕ**
|
||||
|
|
@ -253,18 +253,15 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
* ⚠ **И собственная ловушка среза, замеренная мной на живых деньгах:** `ok=0 AND cost_usd>0` **НЕ ЕСТЬ
|
||||
«оплачено впустую»**. На `coldrun-v16` в этих 11 строках ($0.12316089) лежат три РАЗНЫЕ вещи:
|
||||
`degraded=cjk_artifact` у роли **classifier** — 3 строки, $0.00918827, **мис-вердикт**, вызовы удались.
|
||||
⚠ Это утверждение я пере-обосновала КОДОМ, а не строкой бэклога 105 (адверсариальный проход показал,
|
||||
что предпосылка строки — «`classify_types` выключен во всех шиппинг-конфигах» — для ЭТОГО прогона
|
||||
ложна: он его включал). Механизм прямой: `internal/pipeline/chunkrun.go:40`=`SourceEchoExpected: role == roleTerminologist`
|
||||
⚠ Обоснование — КОДОМ, а не строкой бэклога 105: её предпосылка «`classify_types` выключен во всех
|
||||
шиппинг-конфигах» для ЭТОГО прогона ЛОЖНА — он его включал. Механизм прямой: `internal/pipeline/chunkrun.go:40`=`SourceEchoExpected: role == roleTerminologist`
|
||||
— исключение из эхо-правила выдано ТОЛЬКО терминологу, хотя формат ответа классификатора — та же
|
||||
двуязычная таблица терминов, а докстринг самого поля объясняет, чем это кончается: *«Left on, every
|
||||
healthy call of that role lands in request_log as ok=0/degraded=cjk_artifact — poisoning the one signal
|
||||
that says a provider is misbehaving»*.
|
||||
⚠ **И ПРЯМАЯ улика на сами эти три строки, а не только форма кода** — их ответы лежат в
|
||||
`checkpoints.response_text` и читаются read-only: три ответа `finish=stop`, длиной 163/101/150 знаков,
|
||||
и содержимое — здоровая таблица `<терм>\t<тип>`:
|
||||
«三转蛊师\tterm / 丙等\ttitle / 元海\tterm / … / 方源\tname». Доля CJK в ней высока ПО СПЕЦИФИКАЦИИ формата.
|
||||
⇒ вызовы удались, вердикт ложен. ⛔ **Чинить это здесь НЕЛЬЗЯ:** правка применимости эхо-правила двигает
|
||||
⚠ **И ПРЯМАЯ улика на сами эти три строки, а не только форма кода:** их ответы лежат в
|
||||
`checkpoints.response_text`, читаются read-only и здоровы — разбор с числами и содержимым
|
||||
`MONEY_HONESTY_REPORT.md` §5.4. ⇒ вызовы удались, вердикт ложен. ⛔ **Чинить это здесь НЕЛЬЗЯ:** правка применимости эхо-правила двигает
|
||||
`classifierVersion`, а он — поле снапшота (`snapshot.go`, греп `ClassifierVersion versions the intrinsic`)
|
||||
⇒ ярус B (и ровно это записано ценой в строке бэклога 105); `degraded=sanitizer_stripped` у редактора — 1 строка, $0.01865424,
|
||||
текст **ОТГРУЖЕН**; и лишь $0.09531838 действительно выброшено. **Наивная поверхность назвала бы оператору
|
||||
|
|
@ -405,8 +402,7 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
⚠ **Что поднимать НЕЛЬЗЯ:** расхождение в свёртке банка между `status` и `export` объявлено
|
||||
СОЗНАТЕЛЬНЫМ (`export.go`, греп `symmetry between two surfaces that answer different questions`).
|
||||
Общим делается ТОЛЬКО правило осиротевшей стадии.
|
||||
* ⛔ **ЛОВУШКА, из-за которой наивная правка A7 СОЗДАЁТ новый экземпляр §2.2** (снята адверсариальным
|
||||
проходом, проверена мной по коду): `projectRebill` пропускает ровно те строки, на которые сработает
|
||||
* ⛔ **ЛОВУШКА, из-за которой наивная правка A7 СОЗДАЁТ новый экземпляр §2.2:** `projectRebill` пропускает ровно те строки, на которые сработает
|
||||
новое правило — `default: continue // a stage the current pipeline does not run is never re-billed`
|
||||
(`internal/pipeline/rebill.go`). ⇒ поставив `config_drift=true`, поверхность оставит `rebill_units=0`, а
|
||||
человеческий рендер статуса превращает этот флаг в денежное утверждение о пере-оплате, которой не
|
||||
|
|
@ -422,7 +418,7 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
* **Нарушено:** §2.3 — метка есть базис без гарантии, и её равенство читается как равенство байтов.
|
||||
* **Потребитель:** оператор/замер (сравнимость прогонов). Не платформа, не деньги (деньги защищены
|
||||
`PromptSHA256` в снапшоте).
|
||||
* ⚠ **И решающий довод, которого у меня в первой редакции не было: НОРМА УЖЕ ОБЪЯВЛЕНА И УЖЕ НАРУШЕНА.**
|
||||
* ⚠ **И решающий довод: НОРМА УЖЕ ОБЪЯВЛЕНА И УЖЕ НАРУШЕНА.**
|
||||
`backend/configs/pipeline-c2.yaml:56` дословно: «**лейбл обязан следовать за новым SHA файла**». Именно
|
||||
это и произошло 01.08 с `prompts/zh-ru/editor.md` при неизменном `v3-discourse-reflow`. ⇒ гейт здесь —
|
||||
не новый закон, а МАШИНА под уже написанным правилом, которое проза удержать не смогла. Планка
|
||||
|
|
@ -453,14 +449,11 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
`projected_book_usd`.
|
||||
* **Класс правки:** новое число (сессия вправе). ⚠ Замер этого прогона: терминологический контур —
|
||||
$0.04980482 из $0.43610966 = **11.42% захода**, и ни цента из этого в проекцию не входило.
|
||||
* ⛔ **ОСЬ, НАЗВАННАЯ В СТРОКЕ 194, ОПРОВЕРГНУТА ЖИВЫМИ ДАННЫМИ — и это самое важное здесь.** Строка
|
||||
говорит: «на сдвиге снапшота они реально пере-покупаются». Пере-покупка наступает НЕ от сдвига
|
||||
снапшота. Разложение прогона по покупкам (`request_log`, `read-only`):
|
||||
П1 `f6bb59d4` — терминология $0.02056340 (классификатор 2 батча + терминолог 2 батча, всё свежее);
|
||||
П2 `ce5990b3` — **$0.02924141, ВСЕ батчи свежие** (`tm_hit=0`), при том что черновой снапшот не
|
||||
двигался; П3 `a0958e53` — **$0.00, ВСЕ батчи попали в чекпоинты** (`tm_hit=1`), при том что снапшот
|
||||
как раз СДВИНУЛСЯ (в П3 сработал снапшот-гард). ⇒ ось пере-покупки — **БАЙТЫ БАТЧА**: батчи
|
||||
пере-собираются, когда растёт множество кандидатов, а оно растёт от каждой новой дочерновленной главы.
|
||||
* ⛔ **ОСЬ, НАЗВАННАЯ В СТРОКЕ 194 («на сдвиге снапшота они реально пере-покупаются»), ОПРОВЕРГНУТА
|
||||
ЖИВЫМИ ДАННЫМИ — и это самое важное здесь.** Ось пере-покупки — **БАЙТЫ БАТЧА**: батчи пере-собираются,
|
||||
когда растёт множество кандидатов, а оно растёт от каждой новой дочерновленной главы; на оси
|
||||
терминологии снапшот за весь прогон не двигался ни разу. Разложение покупок П1/П2/П3 и прямая улика из
|
||||
таблицы `jobs` — `MONEY_HONESTY_REPORT.md` §5.1 (опровержение ратифицировано D39.181 §3).
|
||||
Чинить по названной в строке оси значит чинить не то.
|
||||
* ⇒ **A10 и A9 — ОДИН дефект с двух сторон**, и §5 A9 ниже несёт его вторую половину.
|
||||
|
||||
|
|
@ -626,7 +619,7 @@ json-тегов его типа, и рефлексия читает его бе
|
|||
исключений по образцу существующего `exempt` (по импорт-пути + базовому имени) и **последним по
|
||||
очереди**: сначала Г1–Г3, он дороже и слабее.
|
||||
|
||||
### ⛔ ГЛАВНОЕ ОГРАНИЧЕНИЕ ГЕЙТА, и первая редакция его не назвала
|
||||
### ⛔ ГЛАВНОЕ ОГРАНИЧЕНИЕ ГЕЙТА
|
||||
|
||||
**Гейты покрывают НЕ ТЕ каналы, в которые закон маршрутизирует большинство корпуса** (сверка §5 против
|
||||
§7): шесть строк из десяти закон отправляет в
|
||||
|
|
@ -641,9 +634,9 @@ A3(а) → отчёт + WARN, A3(б) → строка сборки, A4 → те
|
|||
Статус на 31.08: **Г1 не построен · Г2 не построен · Г3 построен точечно (A4, по снапшотной оси) ·
|
||||
репо-гейт A8 построен · Г4 не построен.**
|
||||
|
||||
⇒ **машинная половина закона достаёт до четырёх строк из десяти.** Это не довод против закона — статьи
|
||||
§2.1–§2.5 остаются ревью-вопросами и без машины, — но это ЧЕСТНАЯ цена, и приёмка обязана её знать:
|
||||
**закон, поданный как «спроектирован с гейтом», сегодня загейчен на 40%.** Дозакрыть прозаические каналы
|
||||
⇒ **машинная половина закона достаёт до четырёх строк из десяти — закон загейчен на 40%.** Это не довод
|
||||
против закона: статьи §2.1–§2.5 остаются ревью-вопросами и без машины, — но это ЧЕСТНАЯ цена, и приёмка
|
||||
обязана её знать. Дозакрыть прозаические каналы
|
||||
можно только гейтом на ТЕКСТ (посадка на сообщение с проверкой красноты при подмене строки, D39.171), и
|
||||
это отдельная работа, которую я НЕ проектировала.
|
||||
|
||||
|
|
@ -660,13 +653,9 @@ A3(а) → отчёт + WARN, A3(б) → строка сборки, A4 → те
|
|||
|
||||
## 8. Что закон ТРЕБОВАЛ на ратификацию — и что с этим стало
|
||||
|
||||
⚠ **ВСЕ ТРИ РАТИФИЦИРОВАНЫ 31.08 (D39.181) И ПОСТРОЕНЫ.** Список оставлен как он уехал, с исходом каждого:
|
||||
1. **A5 — поля леджера доставки в кадре `finished`** → ратифицировано, построено. Признак едет ЧИСЛАМИ, и
|
||||
присутствие объекта `volume` и есть признак; ни нового кода выхода, ни нового значения `Outcome`.
|
||||
2. **A7/A12 — `config_drift_basis` в `status --json`** → ратифицировано, построено на ОБЕИХ поверхностях,
|
||||
и `build` его слушает.
|
||||
3. **Сам закон** → норма зоны.
|
||||
⚠ **A10 оркестратор отнёс к пункту 1**, а не к новому полю: это исправление ДЕРИВАЦИИ существующей фигуры,
|
||||
**Все три пункта ратифицированы 31.08 (D39.181) и построены** — перечень в шапке файла, разбор каждого
|
||||
экземпляра — `MONEY_HONESTY_REPORT.md` §9.
|
||||
⚠ **A10 оркестратор НЕ отнёс к классу «новое поле»**: это исправление ДЕРИВАЦИИ существующей фигуры,
|
||||
что закон и предписывает. Условие — «ни одна фигура, которую читает платформа, не смеет сменить смысл» —
|
||||
выполнено и предъявлено тестом (`committed_usd` остаётся `SUM(checkpoints)` до микро-доллара).
|
||||
|
||||
|
|
@ -674,6 +663,5 @@ A3(а) → отчёт + WARN, A3(б) → строка сборки, A4 → те
|
|||
|
||||
* **Не проверяла, согласится ли платформа** декодировать предложенные поля — чужая зона, вопрос уехал
|
||||
пингом вместе с дизайном.
|
||||
* **A13 и A14 помечены PLAUSIBLE**: они выведены из кода и комментариев, живьём не воспроизводились.
|
||||
* Реестр Г1 оценён по составу документов, но **не написан**; цена «одна запись на поле» — оценка, а не
|
||||
замер.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@
|
|||
(оркестратор №21, 31.08). Написана **ДО первой правки** дерева; ниже — состояние на момент написания,
|
||||
она не переписывается задним числом (дополнения помечаются датой и словом «дописано»).
|
||||
|
||||
> ⚠ **Дописано 02.09 — указатели и исходы; тело записки НЕ переписывается (это пре-регистрация).**
|
||||
> Промт переехал: `docs/archive/prompts/BACKEND_MONEY_HONESTY_SESSION_PROMPT.md`. Прожитый дамп пака из
|
||||
> секции «Бэкенд» `docs/PROGRESS.md` снят 02.09 — исходы живут в `MONEY_HONESTY_REPORT.md`.
|
||||
> Пак ЗАЛЕНДЖЕН `bb541a8` и принят **D39.182**; закон раскрытия ратифицирован **D39.181**.
|
||||
> ⚠ Два места ниже опровергнуты собственной же работой пака, и оба разобраны в отчёте:
|
||||
> «22.6%» (§4) — ответ на ДРУГОЙ вопрос, величина завышения = **29.2%** (отчёт §5.4); пред-регистрированная
|
||||
> посадка A9 (§2, «воспроизведение перерасхода фикстурой + посадка») НЕ написана — долг назван прямо
|
||||
> в отчёте §8 п.1.
|
||||
|
||||
**Личность старта.** HEAD `9d27c0b`, дерево ЧИСТО (`git status --short` → пусто).
|
||||
Go-модуль `backend/`. Пак **$0**: платных вызовов не содержит и не планирует.
|
||||
|
||||
|
|
|
|||
|
|
@ -131,6 +131,12 @@ A0, и свёртку трогать не нужно. Свёртку я не т
|
|||
| `TestShippingPipelinesRegenerateEchoBeforeEscalating` | снять ключ из `pipeline-arm-glm.yaml` | `--- FAIL … pipeline-arm-glm.yaml: … = 0, want 1` |
|
||||
| `TestEchoRegenFiresONLYForEcho` | снять проверку ПРИЧИНЫ, оставив `attempt < echoRegen` | `--- FAIL … primary calls = 2, want 1` |
|
||||
|
||||
⚠ **Граница, которую §6 промта требует различать, а одна строка «проверены краснотой» стирает:**
|
||||
буквально «красная на состоянии ДО правки» здесь ОДНА — `TestShippingPipelinesRegenerateEchoBeforeEscalating`
|
||||
(правка A1 есть ДАННЫЕ, и он краснеет на конфигах HEAD пятью строками, по одной на файл). Остальные три
|
||||
на состоянии ДО правки ЗЕЛЁНЫЕ: они держат МЕХАНИЗМ, которым правка пользуется, и краснеют на мутациях
|
||||
кода. Это не подгонка, а разные предметы — но отчёт обязан их различать.
|
||||
|
||||
⚠ **Ручка была БЕЗ ЕДИНОГО ТЕСТА** до этого пака (`grep -rn RegenerateEchoBeforeEscalate --include=*_test.go` → пусто).
|
||||
Включать в шиппинг ручку на денежном пути, которую держит только чтение кода, я не стала.
|
||||
|
||||
|
|
@ -293,6 +299,27 @@ WARN'а, процитированного промтом. Следующий б
|
|||
* **Ярус B** — не тронут ничем: эффорт редактора, потолок вывода, свёртка ре-генов, метка-из-хеша.
|
||||
* **`platform/`** — только чтение. Найденное там (A15) уехало пингом, файл не тронут.
|
||||
|
||||
## 6.2 Адверсариальный проход по СВОЕЙ ГОТОВОЙ работе (промт §7.5/§7.8) — обязательный артефакт
|
||||
|
||||
**Два веера, 29 агентов.** Веер 1 — грунтовка корпуса (22: два картографа каналов + десять читателей по
|
||||
строке корпуса + десять адверсариальных верификаторов ПОВЕРХ отчёта каждого читателя; вход — код обеих
|
||||
зон read-only, БД прогона `?mode=ro`, текст промта КАК ПРИОР). Веер 2 — проход по ГОТОВОЙ работе (7:
|
||||
шесть линз — посадки · каждое число · закон против своего корпуса · код-дифф · заказ против выдачи ·
|
||||
решение по A9 — плюс седьмая, механическая сверка с заказом по трёхисходной шкале §6, то есть
|
||||
интервальная сверка субагенту с явными критериями). Мандат дословно: «найди, где она выдаёт
|
||||
непроверенное за проверенное». Линзе посадок было велено мутировать КОПИЮ дерева в `/tmp`; реальное
|
||||
дерево агенты не трогали (проверено ими же по md5).
|
||||
|
||||
**Вердикты шести линз:** 2 × `MATERIALLY_WRONG` (закон против корпуса; код-дифф), 4 ×
|
||||
`SOUND_WITH_CORRECTIONS`; линз, не нашедших ничего, НОЛЬ. **25 находок, из них 7 блокеров** — они
|
||||
переписали §3.3, добавили три посадки, которых без них не было (`TestAUnitWhoseEDITFlaggedIsStillNewBook`,
|
||||
`TestEchoRegenFiresONLYForEcho`, `TestDeliveryIsReadFromTheSHIPPINGWaveOnADraftOnlyPipeline`) и сняли
|
||||
мой же довод §5.3 п.3 как неверный.
|
||||
Диспозиции вплетены в §3–§9 по месту.
|
||||
|
||||
⚠ **Отступление, которое называю сама: модель агентам я ЯВНО НЕ ЗАДАВАЛА** — они унаследовали модель
|
||||
сессии (Opus 5), тогда как промт §7 велит задавать её ИМЕНЕМ.
|
||||
|
||||
---
|
||||
|
||||
## 7. ПИНГИ оркестратору №21 — доставлены; открытыми остались ДВА
|
||||
|
|
@ -418,7 +445,7 @@ consolidated» — потому что `unanswered` в одиночку чита
|
|||
а не `null`).
|
||||
|
||||
⚠ Новое поле кадра бампает МИНОР потока: `StreamVersion` = `1.2` (`internal/runevents/runevents.go`) —
|
||||
правило записано в комментарии над самой константой, и первая редакция правки его нарушила. Платформенное
|
||||
правило записано в комментарии над самой константой. Платформенное
|
||||
зеркало не тронуто: мажор совпадает.
|
||||
|
||||
### 9.6 A6 — деньги слепы к правке исходника на месте
|
||||
|
|
@ -494,11 +521,8 @@ was taken`). Посадка `TestTheContourDoesNotWeakenTheConsentGate`: мут
|
|||
Я не стала печатать старую фразу рядом с новой ради совпадения грепа: это было бы вводить в заблуждение
|
||||
ради зелени, то есть нарушать закон, который я же пишу. Предпосылка переведена с подстроки на ФАКТ
|
||||
(`lastTerminology.BatchesDropped == 0`) — строго сильнее и ровно то, что предписывает D39.171.
|
||||
Оркестратор правку ОСТАВИЛ, проверив дифф сам (удалены ровно две строки предпосылки, утверждение стоит
|
||||
контекстной строкой): запрет канона бьёт по УТВЕРЖДЕНИЮ теста, а сменён был МЕХАНИЗМ ПРЕДПОСЫЛКИ — с
|
||||
механизма, который проект ратифицированно считает дефектным (D39.171), на структурный факт. ⚠ Общей нормы
|
||||
«правка предпосылки ≠ правка утверждения» он НЕ устанавливает — она унесена владельцу вопросом (D39.182
|
||||
§2). ⚠ Порядок был нарушен: правка, потом пинг, а правило говорит «пинг, НЕ правка».
|
||||
Оркестратор правку ОСТАВИЛ, проверив дифф сам; условия и разбор всех трёх касаний — **D39.182 §2**.
|
||||
⚠ Порядок был нарушен: правка, потом пинг, а правило говорит «пинг, НЕ правка».
|
||||
|
||||
⚠ **ВТОРАЯ ПОЛОВИНА ТОГО ЖЕ ТЕСТА ОСТАВЛЕНА НА ТОЙ ЖЕ БОЛЕЗНИ — СОЗНАТЕЛЬНО, и это строка для следующего.**
|
||||
Сохранённое утверждение `strings.Contains(out, "EMPTY completion")` стоит на ТОМ ЖЕ механизме, который я
|
||||
|
|
@ -542,8 +566,5 @@ D39.182 §2): ПРЕДПОСЫЛКА `bankfixpack_test.go` (§9.10) · УТВЕ
|
|||
|
||||
## 11. Состояние на закрытии пака
|
||||
|
||||
Обе фазы отработаны. Закон ратифицирован (D39.181) и применён к десяти экземплярам; корпус вырос до
|
||||
четырнадцати, и четыре лишних нашла мерка, а не заказ. Тридцать три посадки, каждая красная под своей
|
||||
мутацией; батарея зелёная с кодом, снятым с самого `make`, и тремя названными скипами. Открытое оставлено
|
||||
НАЗВАННЫМ, а не закрытым: долг по посадке A9 (§8 п.1) и вторая половина чужого теста на дефектном
|
||||
механизме (§9.10). Пак принят и заленджен 31.08 — `bb541a8`, нота D39.182.
|
||||
Обе фазы отработаны, пак принят и заленджен (§0, шапка). **Открытое оставлено НАЗВАННЫМ, а не
|
||||
закрытым:** долг по посадке A9 (§8 п.1) и вторая половина чужого теста на дефектном механизме (§9.10).
|
||||
|
|
|
|||
|
|
@ -190,19 +190,17 @@ file or directory` — та же причина, по которой красе
|
|||
«пак улучшает»**: на таком числе событий это шум (Фишер p≈0.5); решающее и достаточное — что флейк
|
||||
живёт на дереве, которого пак не касался. Окончательная атрибуция — 5-раундовый A/B в §31.
|
||||
|
||||
## 11. Три правила протокола, вынесенные инцидентами сессии
|
||||
## 11. Два правила протокола, вынесенные инцидентами сессии
|
||||
|
||||
1. **Харнесс мутаций обязан фингерпринтить цели.** Прогон `mutate.py` был убит таймаутом инструмента,
|
||||
`finally` не отработал, и посадка M4 (снятый гейт байтового no-op) просидела в
|
||||
`internal/pipeline/bankdecisions.go` ~40 минут, выглядя продакшн-кодом; сторонний ревьюер снял с
|
||||
этого дерева замеры и доложил «дефект гейта идемпотентности». Поймал посадку пин
|
||||
`TestBankApplyRepeatIsAByteNoOp` на первом прогоне после. Харнесс починен (sha256 целей до и после).
|
||||
Пин усилен по следу: повтор проверяется над файлом с РУЧНЫМ комментарием в шапке — это то, что
|
||||
пере-рендер уничтожает и чего не заметила бы проверка содержимого — плюс что `changed:false` не врёт.
|
||||
2. **Снимай отпечаток дерева ПЕРЕД сборкой бинаря замера.** Симметричная половина того же класса:
|
||||
ревьюер собрал `tmctl` из незакоммиченного дерева, не сняв отпечаток, и инструмент унаследовал
|
||||
посадку. За сессию на это наступили обе стороны.
|
||||
3. **Одиночный прогон — не замер.** Атрибуцию флейков я сперва вывел из одного прогона («зелено в
|
||||
1. **Эталон самопроверки снимается ДО первого изменения, и харнесс мутаций обязан фингерпринтить цели.**
|
||||
Незавершённый прогон `mutate.py` оставил посадку M4 в дереве ~40 минут, выглядящей продакшн-кодом, и
|
||||
сторонний ревьюер снял с этого дерева замеры (он же собрал `tmctl` из незакоммиченного дерева, не
|
||||
сняв отпечаток, — на класс наступили обе стороны). Посадку поймал и правило теперь держит пин
|
||||
`TestBankApplyRepeatIsAByteNoOp`: он же документирует и форму инцидента, и довод (инод плюс
|
||||
рукописный комментарий в шапке — то, что пере-рендер уничтожает, а проверка содержимого не заметила
|
||||
бы). ⚠ Класс повторился следующей сессией ВНУТРИ самого харнесса — §25; отпечаток целей и каталога у
|
||||
инструмента сегодня свой — §16.
|
||||
2. **Одиночный прогон — не замер.** Атрибуцию флейков я сперва вывел из одного прогона («зелено в
|
||||
изоляции ⇒ нагрузка»), затем другой одиночный прогон дал ровно обратное. Решает только чередующийся
|
||||
A/B (§10 п.7).
|
||||
|
||||
|
|
@ -227,10 +225,8 @@ file or directory` — та же причина, по которой красе
|
|||
|
||||
## 13. Дифф `^func Test` — исполнением
|
||||
|
||||
**Удалено: НОЛЬ.** Добавлено 59 тест-функций в шести НОВЫХ файлах + `TestTheRefusalTableIsTotal` в
|
||||
существующем `cmd/tmctl/exitcontract_test.go` + 2 фаззера — снято командами
|
||||
`git diff -U0 -- backend | grep -E "^[+-]func Test"` и `git ls-files --others --exclude-standard --
|
||||
backend | grep '_test.go$' | xargs grep -h '^func Test' | wc -l`.
|
||||
**Удалено: НОЛЬ** — сводный счёт по трём пакам и обе команды в §40. Новых тест-функций пака шесть файлов
|
||||
несут в себе, плюс `TestTheRefusalTableIsTotal` в существующем `cmd/tmctl/exitcontract_test.go`.
|
||||
|
||||
**Тронуто в существующих файлах — шесть, ни у одной сигнатура не изменилась:**
|
||||
- `exitcontract_test.go` — в список полосы добавлены `exitSchemaMismatch` и `exitDecisionsRejected`
|
||||
|
|
@ -248,8 +244,7 @@ backend | grep '_test.go$' | xargs grep -h '^func Test' | wc -l`.
|
|||
# Дофикс той же двери (сессия 25.08.2026)
|
||||
|
||||
Промт (16 пунктов §4) архивирован — `docs/archive/prompts/BACKEND_SEAM_FIX_SESSION_PROMPT_2026-08-27.md`;
|
||||
записка-план — `SEAM_FIX_PLAN.md`. Секции 0–13 выше — улика приёмки, не тронуты. **Каждое число ниже — с
|
||||
командой, которой получено;** команды из `backend/`.
|
||||
записка-план — `SEAM_FIX_PLAN.md`. Секции 0–13 выше — улика приёмки, не тронуты.
|
||||
|
||||
## 14. Батареи
|
||||
|
||||
|
|
@ -566,12 +561,12 @@ YAML не накладывает ничего. Новый гоняет прои
|
|||
## 25. Правило протокола, вынесенное инцидентом ЭТОЙ сессии
|
||||
|
||||
**Инструмент, который сторожит от подсадки, сам подсадил.** Первая версия `tmmutate`
|
||||
читала-правила-писала файл ОДИН РАЗ НА ПРАВКУ. У мутации B две правки в ОДНОМ файле — и «нетронутая»
|
||||
копия второй правки была снята с уже пропатченного файла; восстановление вернуло пропатченное содержимое,
|
||||
а sha256-самопроверка сравнила его с пропатченным же хешем и **прошла**. Дерево копии осталось
|
||||
мутированным, и **два полных раунда измерений после этого шли по мутированному коду**: несколько пинов
|
||||
отчитались как поймавшие мутации, к которым не имели отношения. Вскрыто ровно тем, чему учит §11 п.3:
|
||||
один подозрительный «RED», пере-проверенный изолированным прогоном, не воспроизвёлся.
|
||||
читала-правила-писала файл ОДИН РАЗ НА ПРАВКУ: у мутации B две правки в ОДНОМ файле, «нетронутая» копия
|
||||
второй снималась с уже пропатченного файла, и sha256-самопроверка сравнивала пропатченное с пропатченным
|
||||
же хешем — **проходила**. ⚠ Цена: дерево копии осталось мутированным, и **два полных раунда измерений
|
||||
после этого шли по мутированному коду** — несколько пинов отчитались как поймавшие мутации, к которым не
|
||||
имели отношения. Вскрыто ровно тем, чему учит §11 п.2: один подозрительный «RED», пере-проверенный
|
||||
изолированным прогоном, не воспроизвёлся.
|
||||
|
||||
**Починено дважды:** одно чтение и одна запись на файл (порядок объявлен контрактом в комментарии), плюс
|
||||
второй независимый рубеж — отпечаток ВСЕХ файлов каталога, снятый на заведомо чистом дереве и
|
||||
|
|
@ -611,9 +606,8 @@ YAML не накладывает ничего. Новый гоняет прои
|
|||
|
||||
## 27. Дифф `^func Test` — исполнением
|
||||
|
||||
**Удалено: НОЛЬ** — `git diff -U0 -- backend | grep -cE "^-func (Test|Fuzz)"` → 0, и это проверено
|
||||
дважды: грепом по диффу и поимённо по семнадцати пинам, которые отчёт пака называет по имени (каждый
|
||||
существует ровно один раз). Дофикс добавил 38 тест-функций и 1 фаззер поверх 59 + 2 фаззера пака.
|
||||
**Удалено: НОЛЬ** — сводный счёт и обе команды в §40; поимённая половина проверки прошла по семнадцати
|
||||
пинам, которые отчёт пака называет по имени (каждый существует ровно один раз).
|
||||
|
||||
**Тронуто (тело изменено, сигнатура — нет), и вот почему это законно:**
|
||||
- `cmd/tmctl/exitcontract_test.go` — `TestTheRefusalTableIsTotal` перестал держать ручной список и
|
||||
|
|
@ -630,7 +624,8 @@ YAML не накладывает ничего. Новый гоняет прои
|
|||
## 28. Состав дофикса
|
||||
|
||||
**Новое:** `internal/seed/normalize.go` (канонический вид документа) · `internal/membank/problems.go`
|
||||
(вердикт загрузчика по субъектам) · `cmd/tmmutate/` (харнесс мутаций + каталог посадок, `python3 -c "import json;print(len(json.load(open('cmd/tmmutate/mutations.json'))))"` → **36**) ·
|
||||
(вердикт загрузчика по субъектам) · `cmd/tmmutate/` (харнесс мутаций + каталог посадок; счёт записей на
|
||||
дату дофикса и команда актуального счёта — §16) ·
|
||||
`internal/pipeline/bankchain_test.go`.
|
||||
**Тронуто:** `internal/membank/decisions.go` (доказывающий рендер, нормализация запроса, набор-осознанный
|
||||
алиас, перевёрнутое окно, байты результата, `note` не стирается) · `memseed.go`, `memvoice.go` (вердикт
|
||||
|
|
@ -644,11 +639,9 @@ YAML не накладывает ничего. Новый гоняет прои
|
|||
|
||||
## 29. Ревью старшей моделью: три дефекта, каждый воспроизведён МНОЙ и починен
|
||||
|
||||
Ревью запрашивалось по семи решениям, где заказ оставлял форму на сессии. Оно согласилось с пятью, не
|
||||
согласилось с одним и нашло три вещи, которых сессия не видела. **Каждую сессия воспроизвела сама
|
||||
прежде, чем чинить** — не потому что не доверяет, а потому что чужой результат, взятый на веру, ровно
|
||||
так же становится нормой. У двух подтверждённых решений ревью дало довод СИЛЬНЕЕ, и довод заменён в
|
||||
комментариях кода: у конверта путей на манифесте — что бамп версии выбросил бы все сохранённые сайдкары
|
||||
Ревью запрашивалось по решениям, где заказ оставлял форму на сессии. **Каждую находку сессия
|
||||
воспроизвела сама прежде, чем чинить** — чужой результат, взятый на веру, ровно так же становится
|
||||
нормой. У двух подтверждённых решений ревью дало довод СИЛЬНЕЕ, и довод заменён в комментариях кода: у конверта путей на манифесте — что бамп версии выбросил бы все сохранённые сайдкары
|
||||
и пере-нарезал каждую книгу ради аддитивного поля; у SIGTERM — атомарность и порядок записей вместо
|
||||
длины непрерываемого участка.
|
||||
|
||||
|
|
@ -721,9 +714,9 @@ nil, …)` → true и **записала бы файл нулевой длин
|
|||
|
||||
## 30. Интервальная самоверификация субагентом: ещё пять дефектов, все воспроизведены и починены
|
||||
|
||||
Ревью гонялось В СЕРЕДИНЕ работы против семи ЯВНЫХ критериев, read-only, в копии. Дерево двигалось под
|
||||
ним трижды, поэтому его вердикты пере-исполнены на финальном снимке. Каждый дефект сессия воспроизвела
|
||||
своим прогоном прежде, чем чинить; воспроизведение каждого теперь живёт в его пине, а не здесь.
|
||||
Ревью гонялось В СЕРЕДИНЕ работы против явных критериев, read-only, в копии; дерево под ним двигалось,
|
||||
поэтому его вердикты пере-исполнены на финальном снимке. Каждый дефект сессия воспроизвела своим
|
||||
прогоном прежде, чем чинить; воспроизведение каждого теперь живёт в его пине, а не здесь.
|
||||
|
||||
### 1. ⛔ Правило маски проглатывало ливлок, который вносил САМ вызов
|
||||
|
||||
|
|
@ -890,7 +883,10 @@ ApplyBankDecisions → openDecisionRequest · readBookState · decisionReport
|
|||
|
||||
⚠ **Считать длину функции надо по ТЕЛУ** (от `^func` до первой строки ровно `}`), а не от `^func` до
|
||||
следующего `^func`: второе правило на методах даёт мусор, и именно им была получена несуществующая
|
||||
«норма репозитория в 75 строк» — такой нормы в проекте НЕТ.
|
||||
«норма репозитория в 75 строк» — такой нормы в проекте НЕТ. **Замерено по ТЕЛУ:** две точки входа — **92**
|
||||
и **90** строк против **42** у следующей по длине функции тех же двух файлов; максимумы пакетов совсем
|
||||
другие — **218** (`Status`, `internal/pipeline`) и **105** (`loadVoiceSections`, `internal/membank`);
|
||||
после разбора самая длинная функция обоих файлов — **44** (`signatureState`).
|
||||
|
||||
⚠ **И вот чем доказательство эквивалентности ОКАЗАЛОСЬ слабее, чем здесь было написано.** Первая
|
||||
редакция утверждала «весь каталог пере-прогнан, как записано». На деле рефакторинг сломал ДВЕ записи
|
||||
|
|
@ -898,32 +894,26 @@ ApplyBankDecisions → openDecisionRequest · readBookState · decisionReport
|
|||
провал СБОРКИ красным, то есть две записи не проверяли ничего, а отчёт называл тесты, которые не могли
|
||||
отработать. Нашло воркфлоу-ревью; обе записи пере-выражены, у инструмента появился третий вердикт — §34.
|
||||
|
||||
## 34. Воркфлоу-ревью: шесть осей, 50 находок, 26 переживших скептиков
|
||||
## 34. Воркфлоу-ревью дофикса: шесть осей, все находки воспроизведены и закрыты
|
||||
|
||||
Третье и последнее ревью дофикса — **воркфлоу**, а не одиночный агент: шесть независимых полос читают
|
||||
дерево параллельно, каждая находка отдаётся отдельному скептику с заданием ЕЁ ОПРОВЕРГНУТЬ, выживает
|
||||
только то, что он не смог. Полосы выбраны по тому, чего не касались два предыдущих ревью: гонка двух
|
||||
`bank-apply` · последствия новых полей для платформы (read-only) · эквивалентность только что сделанного
|
||||
рефакторинга · сам `cmd/tmmutate` (он теперь в репозитории, значит продакшн-код) · честность
|
||||
хендофф-документов · общность и безопасность данных. **50 сырых находок, 26 пережили скептиков.** Каждая
|
||||
перепроверена своим прогоном прежде, чем чинить; правки доводов в комментариях и семь правок в самом этом
|
||||
документе живут по месту, здесь — только то, что осталось фактом.
|
||||
Третье и последнее ревью дофикса — **воркфлоу**, а не одиночный агент (форма — §45). Полосы выбраны по
|
||||
тому, чего не касались два предыдущих ревью: гонка двух `bank-apply` · последствия новых полей для
|
||||
платформы (read-only) · эквивалентность только что сделанного рефакторинга · сам `cmd/tmmutate` (он
|
||||
теперь в репозитории, значит продакшн-код) · честность хендофф-документов · общность и безопасность
|
||||
данных. Каждая находка перепроверена своим прогоном прежде, чем чинить; правки доводов в комментариях и
|
||||
правки в самом этом документе живут по месту, здесь — только то, что осталось фактом.
|
||||
|
||||
### ⛔ Главное: две посадки каталога НЕ КОМПИЛИРОВАЛИСЬ — и это внёс мой же рефакторинг
|
||||
|
||||
`P-alias-judged-on-the-set` и `AB-alias-escape` патчат тело `refuseInertDeclines`, ссылаясь на `in.Delta`.
|
||||
Рефакторинг §33 убрал `in` из области видимости этой функции. **Проверено:** прогон всех посадок с
|
||||
`go build` после каждой — ровно эти две не собираются (`undefined: in`). А инструмент считал их КРАСНЫМИ,
|
||||
потому что `red` был буквально `terr != nil`, и провал СБОРКИ выглядел так же, как поймавший пин.
|
||||
`P-alias-judged-on-the-set` и `AB-alias-escape` патчат тело `refuseInertDeclines`, ссылаясь на `in.Delta`,
|
||||
которое рефакторинг §33 убрал из области видимости, — а инструмент считал их КРАСНЫМИ, потому что `red`
|
||||
был буквально `terr != nil`, и провал СБОРКИ выглядел так же, как поймавший пин.
|
||||
|
||||
**Починено на двух уровнях, и это живое свойство инструмента.**
|
||||
(1) Обе записи пере-выражены под новую сигнатуру и краснеют на своих пинах поимённо.
|
||||
(2) У инструмента появился ТРЕТИЙ вердикт. `RED` теперь требует, чтобы хоть один тест назвал себя
|
||||
(`--- FAIL:`); прогон, в котором не отчитался ни один тест, — это `NOTHING`, и он **роняет гейт**. Плюс
|
||||
перед первой посадкой каждый пакет прогоняется НЕТРОНУТЫМ и обязан быть зелёным: без базовой линии «этот
|
||||
пин ловит эту мутацию» опирается на код возврата, который выдают также сборка, флейк, таймаут и опечатка
|
||||
в имени пакета. **Негативная проба:** посадка, которая заведомо не компилируется, даёт
|
||||
`NOTHING … 1 unexpected outcome(s)` и exit 1.
|
||||
**Починено на двух уровнях.** Обе записи пере-выражены под новую сигнатуру и краснеют на своих пинах
|
||||
поимённо; у инструмента появился ТРЕТИЙ вердикт (`NOTHING` — ни один тест не назвал себя, гейт падает)
|
||||
плюс обязательная зелёная базовая линия пакета ДО первой посадки. ⚠ Оба механизма и провенанс инцидента
|
||||
живут в самом инструменте — `cmd/tmmutate/main.go`, комментарии «THE PACKAGE MUST BE GREEN BEFORE
|
||||
ANYTHING IS PLANTED» и «NOT a red …»; второй копии этот отчёт не держит.
|
||||
|
||||
### Продуктовые дефекты — все воспроизведены мной
|
||||
|
||||
|
|
@ -946,11 +936,11 @@ ApplyBankDecisions → openDecisionRequest · readBookState · decisionReport
|
|||
|
||||
## 35. Проверка ЗАКРЫТИЯ — отдельным воркфлоу, и она нашла, что закрыто не всё
|
||||
|
||||
На вопрос «все замечания исправлены?» сессия не отвечала по памяти: четыре независимых агента прошли по
|
||||
всем 26 пережившим находкам §34 и по живому дереву решали КАЖДУЮ — закрыта / не закрыта / частично /
|
||||
отклонена осознанно. **Из 28 проверенных пунктов закрытыми оказались 16, осознанно отклонёнными 2,
|
||||
частично 7 и НЕ закрытыми 3.** Все остатки доделаны, и их результат живёт не здесь, а в исправленных по
|
||||
месту секциях (§15, §16, §18, §26, §27, §31, §33) — второй копии этот отчёт намеренно не держит.
|
||||
На вопрос «все замечания исправлены?» сессия не отвечала по памяти: независимые агенты прошли по всем
|
||||
пережившим находкам §34 и по живому дереву решали КАЖДУЮ — закрыта / не закрыта / частично / отклонена
|
||||
осознанно. Закрыто оказалось не всё; все остатки доделаны, и их результат живёт не здесь, а в
|
||||
исправленных по месту секциях (§15, §16, §18, §26, §27, §31, §33) — второй копии этот отчёт намеренно не
|
||||
держит.
|
||||
|
||||
**Два остатка были признаны вне полномочий пака, и оба закрылись позже:** межкнижная гонка за один
|
||||
`mined_delta` — снятием объявляемых ключей (D39.158 п.5; остаток «второй конфиг ТОЙ ЖЕ книги» заведён
|
||||
|
|
@ -958,9 +948,10 @@ ApplyBankDecisions → openDecisionRequest · readBookState · decisionReport
|
|||
(§43 4.10).
|
||||
|
||||
⚠ **Вывод, который стоит унести дальше самого пака.** Это было ТРЕТЬЕ ревью подряд, и каждое находило
|
||||
настоящие дефекты, которых не видели предыдущие: одиночный старший ревьюер — три, интервальное — пять,
|
||||
воркфлоу — двадцать шесть, проверка закрытия — ещё десять остатков. **Ни одно «все замечания исправлены»
|
||||
в этой сессии не оказалось верным при проверке.** Вывод не «ревью бесполезны», а обратный: закрытие надо
|
||||
настоящие дефекты, которых не видели предыдущие: одиночный старший ревьюер — три (§29), интервальное —
|
||||
пять (§30), воркфлоу — двадцать шесть, проверка закрытия — ещё десять остатков (из 28 её пунктов: 16
|
||||
закрыто, 2 отклонено осознанно, 7 частично, 3 не закрыто). **Ни одно «все замечания исправлены» в этой
|
||||
сессии не оказалось верным при проверке.** Вывод не «ревью бесполезны», а обратный: закрытие надо
|
||||
ПРОВЕРЯТЬ отдельно от починки, и не тем, кто чинил.
|
||||
|
||||
---
|
||||
|
|
@ -1067,6 +1058,9 @@ $ git diff -U0 -- . | grep -cE "^-func (Test|Fuzz)" → 0
|
|||
$ git ls-files --others --exclude-standard -- . | grep '_test.go$' \
|
||||
| xargs grep -h '^func Test' | wc -l → 117 # было 97: +20 тест-функций (фаззеров по-прежнему 3)
|
||||
```
|
||||
**Сводно по трём пакам:** пак оставил 59 тест-функций + 2 фаззера, дофикс добавил 38 + 1, фикс2 — ещё 20;
|
||||
**удалено за все три пака НОЛЬ**, и это проверено дважды — грепом по диффу и поимённо по пинам, которые
|
||||
отчёты паков называют по имени.
|
||||
Переименовано (не удалено): `TestTheStopClearsWhenTheOwnerDecidesTheWholeSignatureMap` →
|
||||
`TestTheChainOwnerDecidesTheWholeMapAndTheRunGoesOn` (замена по заказу §4.12, новая семантика; вторая цепь —
|
||||
`TestTheStopIsAFlagNotAGateOnDecisions` — и есть пин старой формулы) · `TestDecisionPathsDefaultByConventionOnAnEmptyKey`
|
||||
|
|
@ -1102,12 +1096,15 @@ $ git ls-files --others --exclude-standard -- . | grep '_test.go$' \
|
|||
- **Гипотеза §4.13 о пере-оплате терминолога при подписании** механизмом не подтверждена и выигрышем не
|
||||
заявляется: память предъявленного не трогает ни состав кандидатов, ни ключ чекпоинта (хеш
|
||||
отрендеренных сообщений); `TestTerminologistResumeIsFree` держит $0-резюм в обеих семантиках.
|
||||
- **Поимённой разметки новизны в карте подписи НЕТ**: оператор видит РАЗМЕР карты, а не число новых
|
||||
термов (баннер стопа больше не выдаёт одно за другое — `renderSignatureStop`, §45). Пер-термная
|
||||
новизна — продуктовая поверхность, не этот пак.
|
||||
|
||||
## 42. Интервальная самоверификация субагентом (§5.1): четыре находки, все minor
|
||||
|
||||
Ревью шло против десяти явных критериев, адверсариально, с исполнением (точечные тесты + посадки в своей
|
||||
копии). Код по всем десяти сошёлся; находки — класс «довод/покрытие», ровно тот, что предыдущая сессия
|
||||
назвала своим худшим. Три из них — неверные доводы в докстроках при верном коде (отменённая механика
|
||||
Ревью шло против явных критериев, адверсариально, с исполнением (точечные тесты + посадки в своей
|
||||
копии). Код сошёлся по всем; находки — класс «довод/покрытие», ровно тот, что предыдущая сессия назвала
|
||||
своим худшим. Три из них — неверные доводы в докстроках при верном коде (отменённая механика
|
||||
«промотируй/отклони, потом re-run» у `renderSignatureStop`; предикат v16 в `migrate.go`, читавшийся как
|
||||
«любая поверхность вне памяти», тогда как код стреляет только на кластере, чья ВСЯ поверхность вне;
|
||||
описание стоп-окна в `bankapply.go`), все переписаны по месту. ⚠ Третья правка сама внесла ложь про
|
||||
|
|
@ -1153,11 +1150,10 @@ retired-ключи ловятся полями, а не голым strict-decode
|
|||
|
||||
Прогнана по презумпции «каждое заявленное закрытие ложно, пока не увидено исполнением»: все 13 строк §43
|
||||
и все 4 диспозиции §42 подтверждены в дереве (13 точечных тестовых прогонов + 3 полных пакета — зелёные;
|
||||
носители по file:line; реверс-пин признан невакуумным с названным механизмом падения). Найдено ПЯТЬ
|
||||
расхождений — традиция «ни одно "всё исправлено" не выдерживает проверки» держится и на этой сессии.
|
||||
Все пять закрыты по месту (правки видны в §38, §40 и §42), и одно стоит того, чтобы его запомнили:
|
||||
пере-замер §4.4 жил только в скратчпаде — то есть был «числом без первоисточника» ровно того класса, за
|
||||
который заказ корил чужие числа; первоисточник положен в дерево постоянным якорем-пином
|
||||
носители по file:line; реверс-пин признан невакуумным с названным механизмом падения). Расхождения нашлись
|
||||
и здесь (⚠-вывод §35 держится и на этой сессии), все закрыты по месту — правки видны в §38, §40 и §42.
|
||||
Одно стоит того, чтобы его запомнили: пере-замер §4.4 жил только в скратчпаде — то есть был «числом без
|
||||
первоисточника» ровно того класса, за который заказ корил чужие числа; первоисточник положен в дерево постоянным якорем-пином
|
||||
`internal/miner/emissioncap_test.go`.
|
||||
|
||||
## 45. Воркфлоу-ревью фикс2: две кодовые находки и три остатка, которые оно сузило
|
||||
|
|
@ -1165,9 +1161,8 @@ retired-ключи ловятся полями, а не голым strict-decode
|
|||
Форма: шесть параллельных полос-искателей под антипаттерны проекта (неверные доводы при верном коде ·
|
||||
вакуумные пины · семантика флажка глубоким чтением · дверь/отчёт глубоким чтением · общность движка ·
|
||||
шов/контракт), каждая находка — через трёх адверсариальных скептиков с разными линзами (корректность
|
||||
трассой · достижимость · «не принятый ли уже остаток»), выживание — большинство. 23 сырых находки,
|
||||
20 выживших, 16 уникальных, все закрыты. Правки доводов в комментариях и документах живут по месту;
|
||||
здесь — то, что осталось фактом.
|
||||
трассой · достижимость · «не принятый ли уже остаток»), выживание — большинство. Все выжившие находки
|
||||
закрыты; правки доводов в комментариях и документах живут по месту, здесь — то, что осталось фактом.
|
||||
|
||||
**Кодовые (2), обе закрыты правкой + пином + посадкой:**
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue