Cut documentation sediment in the backend zone: agents read each file end to end and removed layered history whose content lives in the decision journal
This commit is contained in:
parent
6c26ac231b
commit
5b187db0d2
9 changed files with 518 additions and 1278 deletions
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
Зона сессии «Бэкенд». Контракт — `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` не читать.**
|
||||
|
||||
*(Актуализировано оркестратором 01.08 по мандату владельца, факты сверены по коду; предыдущая ревизия 17.07 — эры D39.16, до паков 16–20 и фазы 2 общности D39.64.)*
|
||||
*(Актуализировано оркестратором 01.08 по мандату владельца, факты сверены по коду.)*
|
||||
|
||||
## Карта пакетов
|
||||
|
||||
| Пакет | Что делает | Ключевые файлы |
|
||||
|---|---|---|
|
||||
| `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 без прогона**, строка 174: read-only команды требуют ТОЧНОГО совпадения схемы и не мигрируют, поэтому апгрейд бинаря запирал все существующие книги — платформа зовёт `status --json` перед каждым спавном, а write-команда, которая мигрировала бы, не наступала никогда. Грузит ТОЛЬКО `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` |
|
||||
| `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` |
|
||||
| `internal/ledger` | Цены по usage (вкл. reasoning/cache-поля), `PriceForResponse` по фактической модели | `pricing.go` |
|
||||
| `internal/store` | SQLite (modernc, CGO-free), цепочка миграций `schema_version` (⚠ ALTER-шаги v8+ не идемпотентны вопреки шапке — бэклог-строка 49а), 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` под локом: restore point берётся там) — поверхность деплой-шага строки 174, `SchemaHead` — та самая `Expected`; write-open БД новее бинаря теперь ОТКАЗ, а не тихое открытие | `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` |
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
| `internal/membank` | Банк памяти v2, memmatch-v4: Aho-Corasick, спойлер-окна, disposition, **trust-gated longest-match** (draft-длиннее НЕ съедает вложенный approved; отказ = громкая телеметрия — терм-дрейф закрыт в КОДЕ, D39.2-T1), post-check, рендереры инъекции, загрузка/валидация сида (`SeedLint`) | `memory.go`, `memseed.go`, `mempostcheck.go` |
|
||||
| `internal/miner` | Детерминированный оффлайн-майнер банка (WS3, $0): `MineBank` над нормализованными чанками + контраст-корпус → `[]Term`, `DeltaYAML` — сид-дельта на подпись владельца; все пар-данные приходят `*lang.Pack` | `miner.go`, `miner_*.go` |
|
||||
| `internal/checks` | Детерминированные $0-вердикты над текстом чанка, **target-aware ПО ДАННЫМ (D39.64): `Checkers` компилируется из цель-данных, `TargetActive()`/`TargetScriptNonLatin()` гейтят всё — цель без данных инертна, Go-веток по паре нет**: санитайзер v7 (fold-first, CJK/Hangul-leak, CJK-глосс-whitelist) + `ExportNormalize` (**export-contract слой 6**, no-op без цель-данных), cheap-гейты и DC-чекеры (пар-данные из пака), coverage-гейт эксцизии, regression-guard. Флаг-вокабуляр НЕ импортирует: возвращает факт, диспозицию назначает драйвер | `sanitizer.go`, `cheapgates.go`, `checkers.go`, `coverage.go` |
|
||||
| `internal/pipeline` | Композит-корень (драйвер): сетап `runner.go` → снапшот `snapshot.go` → сид `seeding.go` → цикл книги `bookrun.go` → волны `waverun.go` → петля чанка `chunkrun.go` → стадия `stagerun.go` → эскалация с ре-гейтом `escalation.go` → resume `resume.go`; classify/disposition; **реестр `roleInjectionRenderers`** (новая роль = данные+рендерер, не правка switch); `export.go`/`quality.go`/`status.go` — read-only проекции (общая derivation member-drop = `memberDrops`); **read-out файлы для платформы** (D39.85 — приватный SQLite движка ей закрыт): `manifest.go` (структура глав/чанков + стабильный id главы, строка 100), `bankexport.go` (весь банк тремя статусами, 125), машинная стоп-таблица в `mining.go` (101); все три пишутся через `artifact.go` (write-then-rename — их читают ПОКА идёт прогон) | `bookrun.go`, `waverun.go`, `stagerun.go`, `export.go`, `manifest.go`, `disposition.go` |
|
||||
| `internal/pipeline` | Композит-корень (драйвер): сетап `runner.go` → снапшот `snapshot.go` → сид `seeding.go` → цикл книги `bookrun.go` → волны `waverun.go` → петля чанка `chunkrun.go` → стадия `stagerun.go` → эскалация с ре-гейтом `escalation.go` → resume `resume.go`; classify/disposition; **реестр `roleInjectionRenderers`** (новая роль = данные+рендерер, не правка switch); `export.go`/`quality.go`/`status.go` — read-only проекции (общая derivation member-drop = `memberDrops`); **read-out файлы для платформы** (D39.85 — приватный SQLite движка ей закрыт): `manifest.go` (структура глав/чанков + стабильный id главы, строка 100), `bankexport.go` (весь банк тремя статусами, 125); оба пишутся через `artifact.go` (write-then-rename — их читают ПОКА идёт прогон) | `bookrun.go`, `waverun.go`, `stagerun.go`, `export.go`, `manifest.go`, `disposition.go` |
|
||||
| `internal/obs` | trace_id, структурные логи (contextHandler несёт book/chapter/chunk/stage/role из ctx), safego | |
|
||||
|
||||
## Инварианты — ЛОМАТЬ НЕЛЬЗЯ (каждый закреплён тестами)
|
||||
|
|
@ -81,21 +81,13 @@ set -a; . ./.env; set +a; TM_LIVE=1 go test -tags live -run TestLive -v ./intern
|
|||
|
||||
Флаг переводит отсутствие данных из тихого скипа в громкий `Fatal` — то есть «я это гонял» становится проверяемым. Пути дефолтятся ОТ `$HOME` и от корня репозитория (не от `/home/ubuntu`), так что клон под любым пользователем и по любому пути находит то, что есть; точечные переопределения — `TM_CHECKER_LABELS_DIR`, `TM_MINER_PARITY_{CONTRAST,RECORDS,SEED}`.
|
||||
|
||||
Полная батарея на стенде:
|
||||
```bash
|
||||
go build ./... && go vet ./... && go vet -tags live ./... && test -z "$(gofmt -l .)" && \
|
||||
TM_MINER_PARITY=1 TM_CHECKER_LABELS=1 go test ./... -race -count=1
|
||||
```
|
||||
|
||||
**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 — **маскированный структурный дифф** (хеши/версии → плейсхолдер) обязан быть пустым, если смена версий не меняла вердиктов.
|
||||
|
||||
Финал каждой вехи — агентское адверсариальное селфревью (мандат CLAUDE.md 12.07); внешнее ревью — оркестратор.
|
||||
|
||||
## Известный техдолг (не трогать молча; ЕДИНЫЙ трекер — таблица «Бэклог» в `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а).
|
||||
- Остаточные Cyrillic-хардкоды пар-гейтед DC-чекеров (`checks/repair.go:131`, `checks/checkers.go:457,474`) — инертны без dc-данных пары; кандидат на `c.wordScript` (строка 79).
|
||||
- Открытый остаток строки 79 — граница ПЛОТНОСТИ письма Go-константой `cjkScriptNames` (`internal/lang/script.go`); Cyrillic-хардкоды словесной границы DC-чекеров ПОГАШЕНЫ — она берётся из данных цели (`isTargetWordLetter`/`c.wordScript`, D39.39/D39.78).
|
||||
- `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).
|
||||
|
|
|
|||
|
|
@ -6,70 +6,21 @@ guard_hash/verdict-split/fast-path v2) в ledger-очереди ПОСЛЕ сл
|
|||
resume-путь денежно-критичен, реализация всё-или-ничего. ⚠ Скоуп спеки = ТОЛЬКО content-addressed
|
||||
resume: `tmctl export` сюда НЕ входит и его READ-половина уже ПОСТРОЕНА отдельно (D39.5,
|
||||
`internal/pipeline/export.go`); annotation/override-половина экспорта — отдельный отложенный кусок.
|
||||
Исходный статус v3.1 (для истории):** v3.1 закрывает два ОБЯЗАТЕЛЬНЫХ амендмента D22.2 (§0-бис ниже) + пре-имплементационные
|
||||
пункты (axis-тест, паритетные не-цели §8, освежение line-refs). Зона: спека в `backend/docs/`
|
||||
(зона бэкенда); при лендинге оркестратор сворачивает её в
|
||||
Зона: спека в `backend/docs/` (зона бэкенда); при лендинге оркестратор сворачивает её в
|
||||
`docs/architecture/03-implementation-notes.md` новым разделом.
|
||||
|
||||
## 0-бис. v3.1-амендменты (D22.2 два обязательных + пре-имплементационные)
|
||||
**Родословная — в НОТАХ, а не здесь.** Направление v1+v2 и три правки v3 ратифицированы **D20** п.1
|
||||
(расщепить `snapshotID` на wire/вердикт-части; ключ чекпоинта — на wire-идентичности; вердикт-смену
|
||||
re-classify-ить на resume бесплатно); ответы на три вопроса, которые спека держала открытыми
|
||||
(пер-стадийная гранулярность · порог и флаг согласия · судьба `Adult`) — **D20** п.2; два ОБЯЗАТЕЛЬНЫХ
|
||||
амендмента v3.1 (`SourceLang`/`TargetLang` → `verdictSnapshotID`; расщепление `cache_ttl`) и
|
||||
пре-имплементационные пункты (axis-тест `RequestHash`, «паритетные не-цели» §8) — **D22** п.2. Тела: D20 — слайс
|
||||
`docs/archive/architecture/05-decisions-D1-D38.md`, D22 — живой журнал решений. Каждая правка помечена в
|
||||
тексте НИЖЕ словами «правка D20.1(a/b/c)» и «(v3.1-a/b)» — читать их надо там, где они действуют.
|
||||
|
||||
Ревью D22.2 сконструировало и ИСПОЛНИЛО stale-hit, который v3 пропускал. Два обязательных
|
||||
амендмента до реализации:
|
||||
|
||||
- **(v3.1-a) `Book.SourceLang`/`Book.TargetLang` → `verdictSnapshotID`.** Языки — ВЕРДИКТ-входы,
|
||||
потребляемые ВНЕ рендера: `classify` использует `TargetLang` для cjk-echo-проверки
|
||||
(`disposition.go:196` `isCJKTarget`), `coverageCheck` использует пару `SourceLang`/`TargetLang`
|
||||
для коридора `len_ratio` (`chunkrun.go:56`). `editor.md` НЕ рендерит `{{target_lang}}` (после
|
||||
флипа D30.1 билингв-редактор рендерит `{{source_lang}}`, но не target) → на editor-стадии
|
||||
`content_hash` их НЕ ловит, а вердикт (cjk/coverage) от них зависит. Сегодня они в ключе через
|
||||
`brief_hash` (book-поле), но v3 дропает `brief_hash` → `content_hash`; значит нужен ЯВНЫЙ
|
||||
вердикт-фейт. **Правило §4 переформулировано: судьбу обязано получить ЛЮБОЕ brief-поле,
|
||||
потребляемое ВНЕ рендера** (языки — в `verdictSnapshotID`; инцидентально они и в translator
|
||||
`content_hash` через рендер, но вердикт-зависимость — несущая). §4-строка добавлена.
|
||||
- **(v3.1-b) `cache_ttl`-расщепление: `Context.CacheTTL` — advisory (НЕ в `wireSnapshotID`);
|
||||
`prov.CacheTTL` — в `wireSnapshotID`.** Проверено кодом: `clients.go:38` передаёт клиенту
|
||||
`CacheTTL: prov.CacheTTL` (провайдер-уровень, models.yaml, Anthropic-kind cache_control) —
|
||||
**`Context.CacheTTL` (pipeline `context.cache_ttl`, «5m») НЕ доходит НИ ДО ОДНОГО клиента =
|
||||
wire-ИНЕРТЕН.** v3 клал в `wireSnapshotID` инертный `Context.CacheTTL` и терял wire-влияющий
|
||||
`prov.CacheTTL` — задом наперёд. v3.1: `Context.CacheTTL` демотирован до advisory (response-
|
||||
нейтрален, reuse безопасен; НЕ пиним); `prov.CacheTTL` (пер-стадийно через резолвнутый провайдер)
|
||||
→ `wireSnapshotID` + `guard_hash` (меняет cache_control на Anthropic-проводе). Anthropic снят со
|
||||
стека (models.yaml) → экспозиция нулевая, но механизм чист. §4-строки поправлены.
|
||||
|
||||
**Пре-имплементационные (D22.2):** (1) axis-sensitivity тест `RequestHash` — флип `role`/`stage`
|
||||
меняет хеш (сейчас мутация «удалить role» пережила бы сьют) → §12.9 тест-лист (`г-тер`);
|
||||
(2) абзац «паритетные не-цели» §8 (classify-Source для editor-строк; `Retries`/`Escal.BudgetUSD`
|
||||
вне хешей; транспорт-ретраи вне ключа); (3) line-refs освежены — **⚠ рефактор D23 расщепил
|
||||
`runner.go` на `stagerun.go`/`chunkrun.go`/`escalation.go`/`bookrun.go`/`resume.go`/`status.go`;
|
||||
исторические `runner.go:NNN`-ссылки ниже ИНДИКАТИВНЫ (по классу кода), актуальные локации —
|
||||
в §12-плане и по grep имени функции.**
|
||||
|
||||
**Supersedes:** v2 (направление v1+v2 ратифицировано D-лог §Ратификации 09.07 п.2 и D20.1: расщепить
|
||||
`snapshotID` на wire/вердикт-части; ключ чекпоинта — на wire-идентичности; вердикт-смену
|
||||
re-classify-ить на resume бесплатно; три дыры v1 закрыты v2). **v3 закрывает три правки D20.1**
|
||||
(«направление и 90% деталей ратифицированы; реализация разблокируется после v3-правок»):
|
||||
|
||||
- **(a)** guard_hash **обязан нести `role` + имя стадии** — без них формула НЕ суперсет текущей
|
||||
защиты: конструируемый stale-VERDICT fast-path hit при флипе роли (клейм «строго сильнее» был
|
||||
ложен). → §5, контрпример + §3.3/§3.4 формула.
|
||||
- **(b)** dry-run §7 нуждается в **аналитическом правиле editor-каскада**: любая стадия НИЖЕ
|
||||
re-bill-юнита того же чанка сама считается re-bill (иначе консент-проекция занижает ~2× на самом
|
||||
дорогом классе правок — temp/reasoning/model translator'а, чей новый вывод $0-dry-run
|
||||
материализовать не может). → §7 п.1-бис.
|
||||
- **(c)** полевой маппинг §4 **доукомплектован**: `style_check_version`; слой YoPolicy/StyleAllowlist;
|
||||
target-часть `memoryNormVersion` (→ и в postcheck-версию); судьба `jobs.snapshot_id`; verdict-фолд
|
||||
конфига гейтов только при enabled. → §4, §6, §9.
|
||||
|
||||
**Ответы D20.2 вписаны в текст v3:** Q1 — пер-стадийная гранулярность `wireSnapshotID`/`guard_hash`
|
||||
**ПОДТВЕРЖДЕНА** (§3.1); Q2 — порог `min($0.50, 5%×ProjectedBookUSD)` + флаг `--accept-rebill[=usd]`
|
||||
(опциональный потолок суммы) + fallback-флор при `ProjectedBookUSD=0` **ПРИНЯТЫ**, но фикс каскада
|
||||
(b) — ПЕРВЫМ (§7); Q3 — `Adult` остаётся wire/вердикт-НЕЙТРАЛЬНЫМ, слой не назначается: вместо хеша
|
||||
— **load-time adult-линт** (реализован бэкенд-пакетом №3: `Pipeline.CheckAdultChannel`; §4, §13).
|
||||
|
||||
**v2-контекст (сохранён):** v2 закрыл три дыры внешнего ревью — (a) fast-path-гард слабее текущего →
|
||||
колонка `guard_hash`; (b) расщепление `memory_version` сделано ОБЯЗАТЕЛЬНЫМ; (c) loud-гейт согласия
|
||||
заменён pre-flight dry-run. v3 доводит (a) до суперсета (role+stage), (b) до полноты (target-norm в
|
||||
postcheck), (c) — маппинг §4 доукомплектован и каскад в проекции аналитический.
|
||||
⚠ **Line-refs вида `runner.go:NNN` ниже ИНДИКАТИВНЫ (по классу кода):** рефактор D23 расщепил `runner.go`
|
||||
на `stagerun.go` / `chunkrun.go` / `escalation.go` / `bookrun.go` / `resume.go` / `status.go`; актуальные
|
||||
локации — в §12-плане и по grep имени функции.
|
||||
|
||||
**Гейтит:** онгоинг-режим (`add-chapters`, сегмент «ИИ-фабрик», Р9 / D15 п.2). Текущий
|
||||
all-or-nothing resnapshot остаётся **приемлемым для статичной приёмочной книги Ф1 (D15.1 / D18 蛊真人)
|
||||
|
|
@ -185,7 +136,7 @@ jsonOnly, maxTokens, wireSnapshotID, msgs)`. Замена: `snapshotID` → `wir
|
|||
|
||||
| Поле (сегодня) | Класс | Куда в v2 | Почему |
|
||||
|---|---|---|---|
|
||||
| `brief_hash` | wire | **dropped** → `content_hash` | Метаданные книги рендерятся в шаблон (`render.go:108-121`) → в `msgs`; per-chunk `content_hash` ловит правку брифа гранулярно. **Правило (v3.1-a): ЛЮБОЕ brief-поле, потребляемое ВНЕ рендера, обязано получить явную судьбу** (`content_hash` его не ловит). Назначено: `SourceLang`/`TargetLang` → `verdictSnapshotID` (cjk-gate/coverage-коридор — строка ниже, v3.1-a); `YoPolicy`/`StyleAllowlist` → `verdictSnapshotID` (кормят стиль-флаггер); `Adult` (`book.go`) остаётся **wire/вердикт-НЕЙТРАЛЬНЫМ** (D20.2-Q3): слой не назначается, вместо хеша — **load-time adult-линт** `Pipeline.CheckAdultChannel` (реализован пакетом №3: `adult:true` без `channel:adult`-стадии → fail-loud). Первый рантайм-потребитель `Adult` (если появится) обязан ЯВНО вернуть его в `wireSnapshotID`/`verdictSnapshotID` — §13-Q3. |
|
||||
| `brief_hash` | wire | **dropped** → `content_hash` | Метаданные книги рендерятся в шаблон (`render.go:108-121`) → в `msgs`; per-chunk `content_hash` ловит правку брифа гранулярно. **Правило (v3.1-a): ЛЮБОЕ brief-поле, потребляемое ВНЕ рендера, обязано получить явную судьбу** (`content_hash` его не ловит). Назначено: `SourceLang`/`TargetLang` → `verdictSnapshotID` (cjk-gate/coverage-коридор — строка ниже, v3.1-a); `YoPolicy`/`StyleAllowlist` → `verdictSnapshotID` (кормят стиль-флаггер); `Adult` (`book.go`) остаётся **wire/вердикт-НЕЙТРАЛЬНЫМ** (D20.2-Q3): слой не назначается, вместо хеша — **load-time adult-линт** `Pipeline.CheckAdultChannel` (реализован пакетом №3: `adult:true` без `channel:adult`-стадии → fail-loud). Первый рантайм-потребитель `Adult` (если появится) обязан ЯВНО вернуть его в `wireSnapshotID`/`verdictSnapshotID` (D20 п.2, Q3). |
|
||||
| `chunker_version` | wire | **dropped** → `content_hash` | Правила чанкера дают `ch.Text` → `msgs`. Ре-чанкинг меняет границы/число чанков → `content_hash` почти всех → честный broad re-bill, гранулярно. |
|
||||
| `estimator_version` | wire (деривация) | **guard_hash** (не в `RequestHash`) | Деривирует `maxTokens`, а фактический `maxTokens` — уже прямое поле `RequestHash`. В ключе избыточен; fast-path нуждается — кладём в `guard_hash`. Бамп busts fast-path каждого чанка; платят только те, чей `maxTokens` реально сменился (остальные — checkpoint-hit, re-classify $0). |
|
||||
| `max_tokens_policy` | wire (деривация) | **guard_hash** | Как `estimator_version`, для attempt≥1 (`maxTokensForAttempt`). Избыточен в ключе (фактический `maxTokens` там), нужен fast-path-у. |
|
||||
|
|
@ -410,12 +361,10 @@ job-snapshot-mismatch из fail-loud в пер-чанковое `content_hash`/`
|
|||
без явного флага `--accept-rebill[=usd]`**: форма с ОПЦИОНАЛЬНЫМ потолком суммы (`--accept-rebill`
|
||||
принимает проецируемый re-bill целиком; `--accept-rebill=1.50` — только если проекция ≤ $1.50, иначе
|
||||
стоп: Р6 = согласие на КОНКРЕТНУЮ трату, не бланкетное). Гейт content-scoped: срабатывает только на
|
||||
РЕАЛЬНУЮ проецируемую трату, а не на любой вердикт-only $0-change. `--resnapshot` остаётся
|
||||
алиасом-синонимом (семантика — «прими проецируемый re-bill», не «пере-пинай всё»).
|
||||
РЕАЛЬНУЮ проецируемую трату, а не на любой вердикт-only $0-change.
|
||||
|
||||
Это сохраняет Р6-класс согласия на трату, убирая ложные тревоги (вердикт-only смена больше не просит
|
||||
согласия — она $0). `--resnapshot` как флаг остаётся синонимом-алиасом для обратной совместимости, но
|
||||
его семантика — «прими проецируемый re-bill», а не «пере-пинуй всё».
|
||||
согласия — она $0).
|
||||
|
||||
## 8. Resume: легальность reuse и безопасность re-classify (F1)
|
||||
|
||||
|
|
@ -582,38 +531,3 @@ per chunk×stage, а не рассуждает аналитически):**
|
|||
каскада» роняет проекцию до ~½);** (е) миграция: онгоинг-книга под v3 не пере-пинается на `add-chapters`;
|
||||
**(ж, v3.1-b) `Context.CacheTTL` вне `wireSnapshotID` (правка «5m»→«1h» не re-bill-ит); `prov.CacheTTL`
|
||||
в `wireSnapshotID` (правка re-bill-ит Anthropic-стадию).**
|
||||
|
||||
## 13. Решённые вопросы (ответы D20.2 — вписаны в текст v3)
|
||||
|
||||
Все три §13-вопроса v2 РЕШЕНЫ D20.2; сохранены здесь как запись контракта.
|
||||
|
||||
1. **Пер-стадийная гранулярность `wireSnapshotID`/`guard_hash` — ПОДТВЕРЖДЕНА** (D20.2-Q1). Живой
|
||||
довод оркестратора: вероятная смена редактора glm-5→grok-4.3 при book-global пере-оплатила бы весь
|
||||
translator-бэклог; поверхность мала — `snapshotID` уже итерирует стадии. Взято пер-стадийно (§3.1).
|
||||
2. **Порог dry-run и флаг — ПРИНЯТЫ** (D20.2-Q2) с поправками: порог `min($0.50, 5%×ProjectedBookUSD)`,
|
||||
флаг `--accept-rebill[=usd]` (опциональный потолок суммы, отдельный от `--resnapshot`-алиаса),
|
||||
fallback-флор при `ProjectedBookUSD=0`. ⚠ Порядок: **фикс каскада §7.1-бис ПЕРВЫМ** (иначе порог
|
||||
считается от заниженной вдвое суммы). Форма вписана в §7 п.3 / §12 п.8.
|
||||
3. **`Adult` остаётся wire/вердикт-НЕЙТРАЛЬНЫМ, слой НЕ назначается** (D20.2-Q3). Вместо хеша —
|
||||
**load-time линт консистентности**: `adult:true` без единой `channel:adult`-стадии → громко. Линт
|
||||
**реализован бэкенд-пакетом №3** (`Pipeline.CheckAdultChannel`, вызывается в `NewRunner`; обратная
|
||||
сторона — `channel:adult` при `adult:false` — сознательно НЕ гейтится, Adult нейтрален до первого
|
||||
рантайм-потребителя, который обязан ЯВНО назначить слой). §4 (строка `brief_hash`).
|
||||
|
||||
---
|
||||
|
||||
**Резюме для оркестратора.** Дефект — `snapshotID` в ключе вызова смешивает wire-, вердикт- и
|
||||
избыточные входы. Фикс: три хеша на трёх слоях — `wireSnapshotID` (пер-стадийный, в `RequestHash`),
|
||||
`verdictSnapshotID` (в `chunk_status`, не в ключе), `guard_hash` (пер-стадийный суперсет wire-плана,
|
||||
гейт fast-path). Три дыры v2 закрыты + **три правки v3 (D20.1)**: **(a)** `guard_hash` покрывает
|
||||
прямые wire-поля (temp/reasoning/maxTokens/escalate) **И `stageName`+`role`** → строгий суперсет, нет
|
||||
ре-открытия stale-serve ни на wire-, ни на вердикт-оси (контрпример с флипом роли — §5); **(b)**
|
||||
`memory_version` расщеплён ОБЯЗАТЕЛЬНО — inject-часть в `content_hash`, post-check+gate+decl+**target-norm**
|
||||
→ `verdictSnapshotID` (пересчёт бесплатен); dry-run §7 несёт **аналитическое правило editor-каскада**
|
||||
(любая стадия ниже re-bill-юнита = re-bill, иначе консент занижен ~2×); **(c)** loud-гейт согласия
|
||||
заменён pre-flight dry-run «N чанков, ~$X» с порогом `min($0.50, 5%×ProjectedBookUSD)` и флагом
|
||||
`--accept-rebill[=usd]` (Р6 сохранён); маппинг §4 доукомплектован (`style_check_version`,
|
||||
YoPolicy/StyleAllowlist, `jobs.snapshot_id`, coverage-фолд-при-enabled); `Adult` нейтрален — линт
|
||||
`CheckAdultChannel` (уже в пакете №3). Безопасность F1 усилена. Онгоинг-мина D15 снята: append
|
||||
re-bill-ит только реально затронутые чанки×стадии. Реализация мала и хирургична, но **остаётся
|
||||
ЗАБЛОКИРОВАННОЙ до ратификации v3** (реализацию НЕ начинать без подписи оркестратора — D20.1).
|
||||
|
|
|
|||
|
|
@ -7,14 +7,9 @@
|
|||
> ниже; она сужает полномочие, а не расширяет его.
|
||||
> ⚠ Честная цена, названная при ратификации: **закон загейчен примерно на 40%** — см. §7.
|
||||
>
|
||||
> Ниже — текст дизайна, каким он уехал на ратификацию, с поправками, снятыми адверсариальным проходом и
|
||||
> оркестратором. Прежняя шапка:
|
||||
> **ДИЗАЙН, НЕ НОРМА.** Написан бэкенд-сессией `textmachine-main-8a` по промту
|
||||
> `docs/BACKEND_MONEY_HONESTY_SESSION_PROMPT.md` §1. **Сессия его НЕ ратифицирует.** Уезжает пингом
|
||||
> оркестратору №21 → владельцу. До ответа правки классов A0/A2/A3/A4/A5/A6/A7/A8/A10 не вносятся.
|
||||
>
|
||||
> ⚠ **Каждый факт ниже снят ИСПОЛНЕНИЕМ на HEAD `9d27c0b`**, командой, названной рядом. Где я
|
||||
> опровергаю промт — говорю это прямо и показываю чем.
|
||||
> Написан бэкенд-сессией `textmachine-main-8a` (промт — `docs/archive/prompts/BACKEND_MONEY_HONESTY_SESSION_PROMPT.md` §1),
|
||||
> ратифицирован владельцем через оркестратора №21.
|
||||
> ⚠ **Каждый факт ниже снят ИСПОЛНЕНИЕМ на HEAD `9d27c0b`**, командой, названной рядом.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -57,7 +52,7 @@
|
|||
статье приёмке проще всего: она не вводит новой философии, а даёт имя и гейт тому, что зона уже признала
|
||||
правильным на одном поле и не распространила на остальные.
|
||||
|
||||
⚠ **Не больше того, и первая редакция здесь себе польстила (снято адверсариальным проходом).** У §2.1 и
|
||||
⚠ **И не больше того — разделение своего и заимствованного (ратифицировано, D39.181 §2).** У §2.1 и
|
||||
§2.2 родословная другая — норма «unknown, not zero» и дисциплина причин; §2.4 и §2.5 родословной в этом
|
||||
коде НЕ имеют вовсе, это НОВЫЕ нормы, и приёмка обязана судить их как новые. ⚠ И сам `RebillBasis` богаче
|
||||
§2.3: он ЧЕТЫРЁХзначен, и три его значения (`pending`/`stored`/`none`) означают «факт известен», различая
|
||||
|
|
@ -124,13 +119,12 @@ OutcomeOf reads off an exit code. The two are one vocabulary because they are on
|
|||
twice.»* Значения помечены номерами: `clean`=0 · `failed`=1 · `flagged`=2 · `bank_stop`=3 ·
|
||||
`ceiling`=4 · `stopped`=5.
|
||||
|
||||
⚠ **ПОПРАВКА К МОЕЙ ЖЕ ПЕРВОЙ ФОРМУЛИРОВКЕ, снята адверсариальным проходом и проверена мной.** Я написала
|
||||
«пара БИЕКТИВНА, новое значение её разваривает». Это НЕВЕРНО: `OutcomeRefused` уже существует и
|
||||
counterpart'а в потоке НЕ имеет — та же константа, дословно: *«OutcomeRefused is the band, and it has no
|
||||
⚠ **Довод «пара БИЕКТИВНА» НЕВЕРЕН и не годится** (D39.181 п.2 стоит на другом): `OutcomeRefused` уже
|
||||
существует и counterpart'а в потоке НЕ имеет — та же константа, дословно: *«OutcomeRefused is the band, and it has no
|
||||
`finished` counterpart: an invocation that was turned down did no work, so the engine writes no verdict
|
||||
about work»*. Асимметрия уже узаконена, и аргумент «так нельзя, потому что нельзя» падает.
|
||||
|
||||
**Точный аргумент — другой, и он сильнее.** Асимметрия сегодня односторонняя: у КАЖДОГО значения
|
||||
**Точный аргумент — другой.** Асимметрия сегодня односторонняя: у КАЖДОГО значения
|
||||
`finished.outcome` есть код-двойник, а у кодовой стороны есть одно лишнее. Значение, живущее ТОЛЬКО в
|
||||
потоке, было бы первым в обратную сторону — и тогда для ОДНОГО прогона два канала назвали бы РАЗНЫЙ
|
||||
исход: поток сказал бы `volume`, а `OutcomeOf(0)` на том же прогоне — `clean`. Это ровно то, что
|
||||
|
|
@ -175,7 +169,7 @@ about work»*. Асимметрия уже узаконена, и аргумен
|
|||
*Экземпляры: A7 · A2 · **A12 (одиннадцатый, §6)**.*
|
||||
|
||||
**§2.4 — КАНАЛ НАЗНАЧАЕТ ПОТРЕБИТЕЛЬ, А НЕ УДОБСТВО ПИШУЩЕГО.**
|
||||
⚠ **Отношение к §2.1 названо, а не оставлено читателю (снято адверсариальным проходом):** §2.4 — не
|
||||
⚠ **Отношение к §2.1 названо, а не оставлено читателю:** §2.4 — не
|
||||
независимая обязанность, а ПРОЦЕДУРА исполнения §2.1. §2.1 говорит «факт обязан быть на канале своего
|
||||
потребителя»; §2.4 говорит, КАКОЙ это канал и как его выбрать. Строка корпуса нарушает §2.1 всегда, когда
|
||||
нарушает §2.4; отдельный номер у §2.4 есть потому, что нарушают его по-разному — молчанием (§2.1) или
|
||||
|
|
@ -203,8 +197,8 @@ about work»*. Асимметрия уже узаконена, и аргумен
|
|||
| **НОВОЕ СЛОВО в замкнутом словаре** | значение `Outcome` · тип кадра · значение `flag_reason`, пересекающее шов · код выхода ВНЕ полосы (0–5) | ратификация ВЛАДЕЛЬЦА |
|
||||
| **НОВЫЙ КЛАСС ОТКАЗА ВНУТРИ полосы 10–19** | новая константа в `refusalExit` + `pipeline.RefusalClass`; незнакомый номер у потребителя поглощается ЧЛЕНСТВОМ в полосе и читается «refused», а не «failed» — полоса спроектирована ровно под это | ратификация ОРКЕСТРАТОРА (прецедент — код 13) |
|
||||
|
||||
⚠ **ПОПРАВКА, снята адверсариальным проходом и проверена мной.** Первая редакция валила все коды выхода
|
||||
в один класс «слово владельца». Это неверно для ПОЛОСЫ: `platform/internal/ingest/exit.go` дословно —
|
||||
⚠ **Коды выхода НЕ валятся в один класс «слово владельца» — ПОЛОСА растёт иначе:**
|
||||
`platform/internal/ingest/exit.go` дословно —
|
||||
*«It is a BAND and not a list because the vocabulary is the engine's and it will grow. A consumer looks the
|
||||
number up; a class this build has never heard of still lands inside the band and reads as "refused"»*, а
|
||||
`17-seam-inbound-law.md` называет прецедент: код **13** встал в полосу «без нового решения ВЛАДЕЛЬЦА»,
|
||||
|
|
@ -274,8 +268,7 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
`classifierVersion`, а он — поле снапшота (`snapshot.go`, греп `ClassifierVersion versions the intrinsic`)
|
||||
⇒ ярус B (и ровно это записано ценой в строке бэклога 105); `degraded=sanitizer_stripped` у редактора — 1 строка, $0.01865424,
|
||||
текст **ОТГРУЖЕН**; и лишь $0.09531838 действительно выброшено. **Наивная поверхность назвала бы оператору
|
||||
на 29.2% больше потерь, чем было** ($0.12316089 против истинных $0.09531838; ⚠ испр. — первая
|
||||
редакция делила на НАИВНУЮ цифру и получала 22.6%, что отвечает на другой вопрос) — то есть сама была бы экземпляром §2.2.
|
||||
на 29.2% больше потерь, чем было** ($0.12316089 против истинных $0.09531838) — то есть сама была бы экземпляром §2.2.
|
||||
⇒ Разложение обязано печатать не «впустую», а КЛАССЫ: `отброшено · отгружено-с-флагом · мис-вердикт`.
|
||||
|
||||
### A2 — фаза стартует, зная, что не влезает
|
||||
|
|
@ -284,11 +277,11 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
* **Делает:** печатает `estimate_usd` и `budget_usd` рядом, следующий оператор — проверка ошибки ЧТЕНИЯ
|
||||
бюджета, **сравнения нет**; обрывается на середине пер-батчевым гейтом, оставив оплаченную частичную работу.
|
||||
* **Нарушено: §2.3.** Частичный результат подаётся как результат, без базиса «пасс оборван бюджетом».
|
||||
⚠ **Поправка, снятая адверсариальным проходом и проверенная мной: §2.5 здесь НЕ нарушен.** §2.5 —
|
||||
⚠ **§2.5 здесь НЕ нарушен.** §2.5 —
|
||||
правило ПОРЯДКА ОТЧЁТА, а фаза как раз отчитывается: пер-батчевый гейт печатает WARN, НАЗЫВАЮЩИЙ
|
||||
необратимую трату (`spent_usd`, `next_batch_usd`, `batches_left`), и только потом `break` — ошибка не
|
||||
возвращается, отчёт не подавляется. То, что мне хотелось назвать §2.5, — это «решение принято позже,
|
||||
чем могло быть», а это другое правило, и его в законе нет. **Заводить его я не стала: одна строка
|
||||
возвращается, отчёт не подавляется. Похожее на §2.5 здесь — «решение принято позже, чем могло быть»,
|
||||
а это ДРУГОЕ правило, и его в законе нет. **Заводить его я не стала: одна строка
|
||||
корпуса — недостаточное основание для пятой обязанности, и честнее оставить дыру названной.**
|
||||
* **Потребитель:** оператор (поднять бюджет) + деньги.
|
||||
* **Канал:** существующий — план фазы усекается до влезающего ДО первого вызова, и строка называет
|
||||
|
|
@ -339,16 +332,14 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
`prompt_sha256`, `model`, `temperature`, `reasoning` и все прочие побайтно равны.
|
||||
Гард сказал бы «конфиг/промпты изменились» — и это ложь, доказанная его же хранилищем.
|
||||
* **Нарушено:** §2.2.
|
||||
* **Потребитель — ДВОЕ, и это поправка к моей первой редакции («только оператор»), снятая адверсариальным
|
||||
проходом и проверенная мной по реестру платформы.** `PD-422` дословно: движковый джоб-гард останавливает
|
||||
* **Потребитель — ДВОЕ, не «только оператор»** (проверено по реестру платформы). `PD-422` дословно: движковый джоб-гард останавливает
|
||||
прогон, и платформа видит **`exit 1` ⇒ `failed`** — то есть ложную причину читает не только человек,
|
||||
причём резолвится она как «инфра-сбой», а не как «нужен `--resnapshot`». ⚠ Строка помечена там же как
|
||||
сегодня БЕСПРЕДМЕТНАЯ: проводка `--max-units` на платформе загейчена, и вторая покупка этой формы пока
|
||||
не возникает.
|
||||
* **Канал:** оператору — текст гарда (stderr, класс «новое число»); платформе — отдельный вопрос, и он НЕ
|
||||
этого пака: её половина уже заведена строкой `PD-422` в чужой зоне.
|
||||
* ⚠ **Ловушка для исполнителя, снятая адверсариальным проходом и проверенная мной по коду:** готового
|
||||
дифа полей НЕТ, вопреки моей первой формулировке. `classifySnapshotMove` (`repin.go`) ходит по КАРТЕ и
|
||||
* ⚠ **Ловушка для исполнителя (проверена по коду):** готового дифа полей НЕТ. `classifySnapshotMove` (`repin.go`) ходит по КАРТЕ и
|
||||
делает `return moveOther` на ПЕРВОМ несовпавшем ключе — он не собирает МНОЖЕСТВО разошедшихся полей, а
|
||||
какой ключ встретится первым, у Go-мапы недетерминировано. Диф для сообщения обязан быть НОВЫМ и
|
||||
ДЕТЕРМИНИРОВАННЫМ (сортировка ключей), а не этим циклом.
|
||||
|
|
@ -375,8 +366,8 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
пару «код выхода ↔ кадр», а кода заводить нельзя. Числа словаря не имеют. Форма:
|
||||
кадр `finished` получает поля леджера доставки (`max_units · delivered · reworked · flagged · free ·
|
||||
left_fresh · left_rework`).
|
||||
⛔ **ПОПРАВКА, снятая адверсариальным проходом и проверенная мной по коду.** Я предложила потребителю
|
||||
выводить стоп предикатом `delivered+reworked == max_units && left_fresh+left_rework > 0`. **Он ЛОЖЕН
|
||||
⛔ **ЛОВУШКА ПОТРЕБИТЕЛЯ (проверена по коду).** Напрашивающийся предикат
|
||||
`delivered+reworked == max_units && left_fresh+left_rework > 0` **ЛОЖЕН
|
||||
ровно на том прогоне, ради которого A5 заведён:** `reconcile()` (`volume.go`) ПОСЛЕ волн переносит
|
||||
оплаченный, но флагнутый юнит ИЗ `Delivered`/`Reworked` в `Flagged`, а улика A5 — это `--max-units 3`
|
||||
с одним флагнутым чанком, где `delivered+reworked = 2 ≠ 3`. Потребитель прочёл бы объёмный стоп как
|
||||
|
|
@ -451,14 +442,14 @@ number up; a class this build has never heard of still lands inside the band and
|
|||
при сдвиге снапшота реально пере-покупаются.
|
||||
* **Нарушено:** §2.1.
|
||||
* **Потребитель:** оператор (согласие) + деньги.
|
||||
* ⛔ **Канал — НЕ тот, который я назвала первой редакцией, и это проверено на данных.** Я написала
|
||||
«существующие `projected_book_usd` / `rebill_*`». Обе фигуры считаются ИЗ `chunk_status`
|
||||
* ⛔ **Канал — НЕ «существующие `projected_book_usd` / `rebill_*`», и это проверено на данных.** Обе
|
||||
фигуры считаются ИЗ `chunk_status`
|
||||
(`projectRebill` принимает `statuses []store.ChunkStatus`), а `chunk_status` этого прогона содержит
|
||||
РОВНО draft(20) + edit(3) строк и НИ ОДНОЙ терминологической, тогда как `checkpoints` держит 9
|
||||
терминологических. ⇒ контур $0.04980482 для этих носителей **структурно невидим**, и положить его туда
|
||||
нельзя, не сменив саму деривацию. **Носитель придётся строить от `checkpoints ⋈ jobs`** (там роль и
|
||||
стадия есть) — то есть A10 дороже, чем «новое число», и это надо знать ДО планирования правки.
|
||||
* **Канал (исправлено):** новая деривация поверх `checkpoints ⋈ jobs`, публикуемая рядом с
|
||||
* **Канал:** новая деривация поверх `checkpoints ⋈ jobs`, публикуемая рядом с
|
||||
`projected_book_usd`.
|
||||
* **Класс правки:** новое число (сессия вправе). ⚠ Замер этого прогона: терминологический контур —
|
||||
$0.04980482 из $0.43610966 = **11.42% захода**, и ни цента из этого в проекцию не входило.
|
||||
|
|
@ -545,11 +536,9 @@ a CLASS it knows, never on band membership». Платформенная коп
|
|||
|
||||
**Диспозиция:** правка платформенного файла — ЧУЖАЯ ЗОНА, я её не трогаю. Уезжает пингом.
|
||||
|
||||
⚠ **И честная оговорка о его отношении к ЗАКОНУ, снятая адверсариальным проходом и мной принятая:
|
||||
A15 — НЕ экземпляр закона.** Ст. 1 определяет подотчётный факт как ЗНАЧЕНИЕ, которое движок вычислил или
|
||||
⚠ **И честная оговорка о его отношении к ЗАКОНУ: A15 — НЕ экземпляр закона.** Ст. 1 определяет подотчётный факт как ЗНАЧЕНИЕ, которое движок вычислил или
|
||||
выводит из своих строк; «два рукописных комментария о словаре разъехались» — не значение, не выводится ни
|
||||
из одной строки и не имеет канала. Первая редакция назвала его «экземпляром §2.4 на уровне словаря» — это
|
||||
натяжка, и я её снимаю. **A15 остаётся находкой первого класса и НЕ становится доводом за закон.** Что из
|
||||
из одной строки и не имеет канала (натяжка «экземпляр §2.4 на уровне словаря» снята). **A15 остаётся находкой первого класса и НЕ становится доводом за закон.** Что из
|
||||
него следует для закона: у Г1 обязана быть сверка с ЗЕРКАЛОМ чужого словаря (§7), иначе следующий разъезд
|
||||
будет так же тихим, — но это требование к гейту, а не подведение факта под статью.
|
||||
|
||||
|
|
@ -598,11 +587,10 @@ translation»*, и `LogRequest` — *«insert, WARN on failure, never propagate
|
|||
**Почему рефлексия, а не анализатор:** список полей опубликованного документа — это в точности набор
|
||||
json-тегов его типа, и рефлексия читает его без единой эвристики.
|
||||
|
||||
⛔ **И ЧЕГО РЕФЛЕКСИЯ НЕ УМЕЕТ — названо, потому что первая редакция этого не сказала и гейт читался
|
||||
сильнее, чем он есть (снято адверсариальным проходом, проверено мной):**
|
||||
⛔ **ЧЕГО РЕФЛЕКСИЯ НЕ УМЕЕТ — названо, иначе гейт читается сильнее, чем он есть:**
|
||||
* **рефлексия перечисляет ПОЛЯ названного типа, но не ТИПЫ.** Список документов остаётся РУЧНЫМ, а
|
||||
«кто-то забыл дописать тип» — та же тихая дыра, ради которой гейт заводится. Первая редакция это уже и
|
||||
продемонстрировала: её собственный перечень пропустил `PhaseProgress`, `WaveCounter` и `ManifestChapter`;
|
||||
«кто-то забыл дописать тип» — та же тихая дыра, ради которой гейт заводится (первый же перечень этого
|
||||
дока пропустил `PhaseProgress`, `WaveCounter` и `ManifestChapter`);
|
||||
* **payload'ы потока спрятаны за `Envelope.Data json.RawMessage`** — обход по `Envelope` не видит НИ ОДНОГО
|
||||
payload'а, а НОВЫЙ тип кадра (ровно туда садится рекомендация A5) невидим полностью;
|
||||
⇒ **честная форма Г1: реестр перечисляет ТИПЫ руками, а рефлексия проверяет ПОЛЯ каждого.** Ручная
|
||||
|
|
@ -621,8 +609,7 @@ json-тегов его типа, и рефлексия читает его бе
|
|||
Для каждого поля payload'а `buildSnapshotID`, КОТОРОЕ ФИКСТУРА МОЖЕТ СДВИНУТЬ: сдвинуть ровно его →
|
||||
снять сообщение гарда → утверждать, что оно НАЗЫВАЕТ это поле. Это машинная форма §2.2.
|
||||
|
||||
⚠ **Оговорка, без которой гейт описан сильнее, чем он есть (снята адверсариальным проходом, проверена
|
||||
мной):** «~30 плоских осей» — неверно дважды. Payload — ДЕРЕВО (`contextSnap` · `segmentationSnap` ·
|
||||
⚠ **Оговорка, без которой гейт описан сильнее, чем он есть:** «~30 плоских осей» — неверно дважды. Payload — ДЕРЕВО (`contextSnap` · `segmentationSnap` ·
|
||||
`coverageSnap` · `sanitizerSnap` · `banknoteSnap` · `repairSnap` · `[]stageSnap`), и заметная часть его
|
||||
листьев — КОДОВЫЕ КОНСТАНТЫ (`chunker_version` · `estimator_version` · `max_tokens_policy` ·
|
||||
`classifier_version` · `style_check_version` · `render_format_version` · `embedded_version` ·
|
||||
|
|
@ -641,8 +628,8 @@ json-тегов его типа, и рефлексия читает его бе
|
|||
|
||||
### ⛔ ГЛАВНОЕ ОГРАНИЧЕНИЕ ГЕЙТА, и первая редакция его не назвала
|
||||
|
||||
**Гейты покрывают НЕ ТЕ каналы, в которые закон маршрутизирует большинство корпуса.** Снято
|
||||
адверсариальным проходом, проверено мной сверкой §5 против §7: шесть строк из десяти закон отправляет в
|
||||
**Гейты покрывают НЕ ТЕ каналы, в которые закон маршрутизирует большинство корпуса** (сверка §5 против
|
||||
§7): шесть строк из десяти закон отправляет в
|
||||
канал, за которым не стоит НИ ОДИН из четырёх гейтов — A0 → секция `report`, A2 → строка об усечении,
|
||||
A3(а) → отчёт + WARN, A3(б) → строка сборки, A4 → текст гарда (stderr), A8 → репо-гейт (свой собственный).
|
||||
Г1/Г2 стерегут JSON-структуры и колонки БД, Г3 — одну ось одного сообщения.
|
||||
|
|
@ -650,8 +637,7 @@ A3(а) → отчёт + WARN, A3(б) → строка сборки, A4 → те
|
|||
⛔ **И ЧЕТВЁРТЫЙ ГЕЙТ НАЗЫВАЮ НЕПОСТРОЕННЫМ ВСЛУХ, потому что Ст. 4 этого требует буквально.** **Г4
|
||||
(анализатор «необратимое до ошибки») НЕ ПОСТРОЕН** — он спроектирован и отложен, и §2.5 остаётся
|
||||
**НЕЗАГЕЙЧЕННОЙ статьёй**: сегодня её держит одна точечная посадка на `build` (A3а), а не машина, которая
|
||||
поймала бы СЛЕДУЮЩИЙ экземпляр в другом месте. Первая редакция этого абзаца сказала «Г4 предложен
|
||||
последним» — это не то же самое, что «не построен», и приёмка справедливо потребовала назвать прямо.
|
||||
поймала бы СЛЕДУЮЩИЙ экземпляр в другом месте.
|
||||
Статус на 31.08: **Г1 не построен · Г2 не построен · Г3 построен точечно (A4, по снапшотной оси) ·
|
||||
репо-гейт A8 построен · Г4 не построен.**
|
||||
|
||||
|
|
@ -684,19 +670,10 @@ A3(а) → отчёт + WARN, A3(б) → строка сборки, A4 → те
|
|||
что закон и предписывает. Условие — «ни одна фигура, которую читает платформа, не смеет сменить смысл» —
|
||||
выполнено и предъявлено тестом (`committed_usd` остаётся `SUM(checkpoints)` до микро-доллара).
|
||||
|
||||
### Прежний текст пункта (как уезжал)
|
||||
|
||||
1. **A5 — поля леджера доставки в кадре `finished`** (класс «новое поле», ст. 3). Без них признак
|
||||
объёмного стопа не выражается ни одним разрешённым классом.
|
||||
2. **A7/A12 — поле `config_drift_basis` в `status --json`** (класс «новое поле»). Внутри движка базис
|
||||
можно посчитать сразу, но опубликовать его — расширение шва.
|
||||
3. **Сам закон** — норма зоны; ратифицирует владелец через оркестратора.
|
||||
|
||||
## 9. Что я в этом дизайне НЕ проверила
|
||||
|
||||
* **Не проверяла, согласится ли платформа** декодировать предложенные поля — чужая зона, вопрос уехал
|
||||
пингом вместе с дизайном.
|
||||
* **Не строила** ни одного из четырёх гейтов — фаза 1 их проектирует, а не пишет.
|
||||
* **A13 и A14 помечены PLAUSIBLE**: они выведены из кода и комментариев, живьём не воспроизводились.
|
||||
* Реестр Г1 оценён по составу документов, но **не написан**; цена «одна запись на поле» — оценка, а не
|
||||
замер.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
# Отчёт: бэкенд-пак «ДЕНЬГИ И ЧЕСТНОСТЬ ВЫДАЧИ»
|
||||
|
||||
Сессия `textmachine-main-8a`, роль БЭКЕНД. Промт `docs/BACKEND_MONEY_HONESTY_SESSION_PROMPT.md`
|
||||
(оркестратор №21, 31.08). Записка-план — `backend/docs/MONEY_HONESTY_PLAN-NOTE.md`, написана до первой правки.
|
||||
Дизайн фазы 1 — `backend/docs/DISCLOSURE_LAW_DESIGN.md`.
|
||||
Сессия `textmachine-main-8a`, роль БЭКЕНД, 31.08, оркестратор №21. Промт —
|
||||
`docs/archive/prompts/BACKEND_MONEY_HONESTY_SESSION_PROMPT.md`. Записка-план (пре-регистрация, до первой
|
||||
правки) — `backend/docs/MONEY_HONESTY_PLAN-NOTE.md`; дизайн фазы 1 — `backend/docs/DISCLOSURE_LAW_DESIGN.md`.
|
||||
|
||||
**Старт:** HEAD `9d27c0b`, дерево чисто. **Пак $0: платных вызовов ноль**, ни одного ключа не открыто.
|
||||
**Заленджен `bb541a8`, принят нотой D39.182; закон ратифицирован D39.181.**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -39,25 +40,7 @@
|
|||
|
||||
**38 новых тестов, каждый проверен КРАСНОТОЙ под своей мутацией. Удалённых тестов НОЛЬ.**
|
||||
|
||||
⚠ **ПАК ПРОШЁЛ ПРИЁМКУ И БЫЛ ВОЗВРАЩЁН НА ДОРАБОТКУ по ТРЁМ блокерам — все три подтверждены мной
|
||||
исполнением и закрыты; разбор §9.11.** Два из них — дефекты В МОЁМ ЖЕ ЛЕКАРСТВЕ: разложение денег A0
|
||||
называло потерей весь глоссарный контур (завышение 59.8% — хуже наивного среза, который тот же файл
|
||||
отвергает за 29.2%), а починка A6 работала на читающей поверхности и была мертва на денежной. Третий —
|
||||
вердикт «предъявлено» поверх неработающего пути. Плюс пять дофиксов, из которых Д1 — я добавила поле в
|
||||
поток и не бампнула его версию, при том что правило записано в комментарии над самой константой.
|
||||
|
||||
⚠ **Мид-флайт ратификация — отдельным пунктом, как требует промт §12.** Ответ пришёл релеем через
|
||||
оркестратора №21 (он же нёс дизайн владельцу), я его эхо-подтвердила отдельным сообщением до первой
|
||||
правки фазы 2. Ратифицировано три вещи: закон как норма зоны · поля леджера доставки в кадре `finished` ·
|
||||
`config_drift_basis` в `status --json`. A10 оркестратор отдельно отнёс к пункту 1 (исправление ДЕРИВАЦИИ
|
||||
существующей фигуры, не новое поле) с проверяемым условием — условие выполнено и предъявлено тестом.
|
||||
|
||||
⚠ **И одна поправка к МОЕМУ ЖЕ закону, которую внёс оркестратор при чтении дизайна:** Ст. 3 удешевляла
|
||||
рост полосы 10–19 до подписи оркестратора, ссылаясь на то, что незнакомый номер поглощается членством в
|
||||
полосе. Это верно по оси НОМЕРА и неверно по оси ОБЕЩАНИЯ — что доказала моя же находка A15. Оговорка
|
||||
дописана: пока копии словаря расходятся, новый класс вводится только вместе со сверкой обеих копий.
|
||||
|
||||
## 0.1 Батарея и дифф `^func Test` — ИСПОЛНЕНИЕМ (промт §7.2/§7.3), а не по памяти
|
||||
## 0.1 Батарея — ИСПОЛНЕНИЕМ (промт §7.2), а не по памяти
|
||||
|
||||
**`make battery` гонялась СЕМЬ раз; последняя — ПОСЛЕ доработки по приёмке:**
|
||||
```
|
||||
|
|
@ -69,66 +52,17 @@ MAKE_EXIT=0 # снят с САМОГО make (echo "MAKE_EXIT=$?"), не
|
|||
--- SKIP: TestHelperKillLoop
|
||||
```
|
||||
Корпусные измерения (`TM_MINER_PARITY=1`, `TM_CHECKER_LABELS=1`) НЕ гонялись.
|
||||
⚠ **Первый прогон был КРАСНЫМ** — моя правка A11 уронила чужой ратифицированный тест (разбор §4.3).
|
||||
Клейм «зелено» без пере-прогона после последней правки был бы ровно тем, за что этот пак заведён.
|
||||
⚠ **Фоновая обёртка печатает `[exited with code 0]` и на КРАСНОЙ батарее** — я это наблюдала лично.
|
||||
Это та же мина, на которой ошиблась сессия холодного прогона.
|
||||
|
||||
**Дифф тестов, снят ЧЕТЫРЕЖДЫ (после фазы 2, после адверсариального прохода, после десяти экземпляров,
|
||||
после доработки по приёмке):**
|
||||
```
|
||||
$ git grep -h '^func Test' HEAD -- 'backend/**/*_test.go' | sort > tests-head.txt # 1045
|
||||
$ grep -rh '^func Test' backend --include=*_test.go | sort > tests-now.txt # 1083
|
||||
$ comm -23 tests-head.txt tests-now.txt # УДАЛЁННЫЕ
|
||||
(пусто)
|
||||
$ comm -13 tests-head.txt tests-now.txt | wc -l # ДОБАВЛЕННЫЕ
|
||||
38
|
||||
```
|
||||
**Удалённых НОЛЬ** — ни один тест не снят и не переименован за весь пак, включая доработку по приёмке.
|
||||
Добавлено **38**, поимённо они стоят при своих пунктах в §3, §4, §9 и §9.11.
|
||||
|
||||
## 1. Сверка с заказом по пунктам (промт §2 и §8) — вердикты по трёхисходной шкале §6
|
||||
|
||||
| пункт | вердикт §6 | посадки | где |
|
||||
|---|---|---|---|
|
||||
| **Фаза 1 — закон + гейт** | **предъявлено** (ратифицирован D39.181) | — | `DISCLOSURE_LAW_DESIGN.md` |
|
||||
| **Фаза 1 — 11-й экземпляр** | **предъявлено ×4** (A12·A15·A13·A14) | — | закон §6 |
|
||||
| **A0** хвост неудач | **предъявлено** | 3 | §9.1 |
|
||||
| **A1** дефолт эхо-регена | **предъявлено** | 4 | §3 |
|
||||
| **A2** фаза стартует, не влезая | **предъявлено** | 2 (+1 чужая предпосылка) | §9.2 |
|
||||
| **A3(а)** `build` лжёт кодом выхода | **предъявлено** | 1 | §9.3 |
|
||||
| **A3(б)** `book_files` | **ОПРОВЕРГНУТО** как дефект `book_files`; настоящий дефект рядом — **предъявлено** | 1 | §9.3 |
|
||||
| **A4** гард врёт о причине | **предъявлено** | 4 | §9.4 |
|
||||
| **A5** объёмный стоп | **предъявлено** (после ратификации) | 3 | §9.5 |
|
||||
| **A6** строка 238 | **предъявлено** | 2 | §9.6 |
|
||||
| **A7** строка 239 | **предъявлено** | 2 (+2 на ловушку) | §9.7 |
|
||||
| **A8** `prompt_version` | **предъявлено** | 1 | §9.8 |
|
||||
| **A9** строка 233 | **диагноз предъявлен, кода нет — решение с доводом**; долг назван | 0 | §5, §8 п.3 |
|
||||
| **A10** строка 194 | **предъявлено**; ось строки **ОПРОВЕРГНУТА** | 2 | §9.9 |
|
||||
| **A11** строка 232 | **предъявлено** | 4 | §4 |
|
||||
| **A12** (11-й) `config_drift` без базиса | **предъявлено** | 4 | §9.7 |
|
||||
| строка 197 (ФЧ-1…ФЧ-8) | **не взята** — решение с доводом | — | §6 |
|
||||
|
||||
## 2. Вердикт по снапшоту (промт §7.1 — первым пунктом) — МАШИННЫЙ, не грепом
|
||||
|
||||
**Ручка `regenerate_echo_before_escalate` снапшот НЕ ДВИГАЕТ.**
|
||||
|
||||
Грепом (недостаточно, но с него начала):
|
||||
```
|
||||
$ grep -c 'Retries' backend/internal/pipeline/snapshot.go
|
||||
0
|
||||
```
|
||||
**Машинно, как велит §5 промта** — snapshot ID на фикстуре ДО и ПОСЛЕ, и это не разовый замер, а
|
||||
постоянный тест `TestEchoRegenBudgetMovesNoSnapshot` (`internal/pipeline/echoregen_test.go`): рендерит
|
||||
`snapshotIDForWave` обеих волн при ручке 0, затем 1, затем 7, и сравнивает байты.
|
||||
|
||||
**Посадка проверена ИСПОЛНЕНИЕМ мутации** — я свернула ЗНАЧЕНИЕ ручки в payload `buildSnapshotID` и получила:
|
||||
```
|
||||
--- FAIL: TestEchoRegenBudgetMovesNoSnapshot
|
||||
a re-generation budget of 1 moved a wave snapshot — turning it on would re-buy every paid checkpoint
|
||||
```
|
||||
после чего файл восстановлен (`git diff --stat internal/pipeline/snapshot.go` → пусто).
|
||||
|
||||
⚠ **И ЧЕСТНАЯ ГРАНИЦА, которую я обязана назвать, потому что промт спрашивает именно о ней.** Ручка вне
|
||||
снапшота ⇒ два прогона с РАЗНЫМ числом ре-генов дают ОДИН снапшот и по нему неразличимы. Это:
|
||||
* **честно для ДЕНЕГ** — `attempt` входит в request_hash (`checkpoints.attempt`, DDL: «регенерации Фазы 1:
|
||||
|
|
@ -166,9 +100,8 @@ A0, и свёртку трогать не нужно. Свёртку я не т
|
|||
| эхнутые черновые попытки (`ok=0`) | 5 шт, $0.01070788 |
|
||||
| эхо-частота свежих черновых вызовов | **5 из 20 = 25%** |
|
||||
|
||||
⛔ **И ГЛАВНАЯ ПОПРАВКА К ЭТОМУ ПУНКТУ, снятая адверсариальным проходом и проверенная мной по конфигам:
|
||||
в ПЯТИ файлах, которые я правила, эскалация ВЫКЛЮЧЕНА.** Все пять несут `escalation.budget_usd: 0`, а
|
||||
комментарий самого `pipeline-c1.yaml` говорит, что это значит: «budget_usd=0 ⇒ эскалация НЕ исполняется
|
||||
⛔ **ГЛАВНОЕ ПО ЭТОМУ ПУНКТУ: в ПЯТИ файлах, которые я правила, эскалация ВЫКЛЮЧЕНА.** Все пять несут
|
||||
`escalation.budget_usd: 0`, а комментарий самого `pipeline-c1.yaml` говорит, что это значит: «budget_usd=0 ⇒ эскалация НЕ исполняется
|
||||
(НИ chains, НИ stage.escalate_to)». ⇒ **в этих файлах ре-ген не ЗАМЕНЯЕТ хоп — хопа там нет.** Число 5.40×
|
||||
снято на КНИЖНОМ конфиге прогона, где стояло `budget_usd: 0.08`, и этого конфига среди пяти НЕТ.
|
||||
|
||||
|
|
@ -177,22 +110,20 @@ A0, и свёртку трогать не нужно. Свёртку я не т
|
|||
budget_usd>0, иначе echo-эскалация черновика не выстрелит») — ре-ген заменяет хоп ценой 5.40× ⇒ экономия;
|
||||
* **книга с `budget_usd: 0`** (дефолт шаблона, держащий CI зелёным без чужих ключей) — эхо сегодня просто
|
||||
ФЛАГАЕТСЯ, и чанк уезжает дырой в `--partial`. Ре-ген там не экономит, а **выкупает дыру за один дешёвый
|
||||
вызов flash** (≈$0.0038). Это тоже выгодная сделка, но это ДРУГАЯ сделка, и первая редакция комментария
|
||||
в конфигах называла только первую.
|
||||
⇒ Комментарии в пяти конфигах исправлены: они называют оба режима.
|
||||
вызов flash** (≈$0.0038). Это тоже выгодная сделка, но это ДРУГАЯ сделка.
|
||||
⇒ Комментарии в пяти конфигах называют ОБА режима.
|
||||
|
||||
⚠ **Я НЕ повторяю «7.6×» из квирков**: то число снято на ИЮЛЬСКИХ ценах при `effort:low`. Моё — с этого
|
||||
прогона, в сегодняшних ценах, на конфиге, которым он куплен. Оба указывают в одну сторону; в конфиг
|
||||
вписано МОЁ, с командой.
|
||||
⚠ **И честная граница арифметики выгоды, ИСПРАВЛЕННАЯ:** 25% — книжная частота, не независимая
|
||||
вероятность на вызов; в этом прогоне эхнули ОБА чанка главы 8, что согласуется с по-чанковой
|
||||
предрасположенностью. ⛔ Я писала «направление выгоды переживает любое p<1» — **это неверно, снято
|
||||
адверсариальным проходом.** Когда ре-ген эхает ПОВТОРНО, цикл выходит и `maybeEscalate` всё равно
|
||||
стреляет: платится ре-ген И хоп. Направление выживает, только пока вероятность восстановления с ре-гена
|
||||
выше `цена_регена/цена_хопа ≈ 1/5.4 ≈ 18.5%`. Замеренные 25% дефолт оправдывают, но порог существует, и
|
||||
⚠ **Честная граница арифметики выгоды:** 25% — книжная частота, не независимая вероятность на вызов;
|
||||
в этом прогоне эхнули ОБА чанка главы 8, что согласуется с по-чанковой предрасположенностью. Когда
|
||||
ре-ген эхает ПОВТОРНО, цикл выходит и `maybeEscalate` всё равно стреляет: платится ре-ген И хоп ⇒
|
||||
**направление выгоды выживает только пока вероятность восстановления с ре-гена выше
|
||||
`цена_регена/цена_хопа ≈ 1/5.4 ≈ 18.5%`.** Замеренные 25% дефолт оправдывают, но порог существует, и
|
||||
не-восстанавливающееся плечо в паке НЕ протестировано. Я не заявляю «сэкономит 56%».
|
||||
|
||||
### 3.4 Посадки — ТРИ, каждая проверена КРАСНОТОЙ под своей мутацией
|
||||
### 3.4 Посадки — ЧЕТЫРЕ, каждая проверена КРАСНОТОЙ под своей мутацией
|
||||
| посадка | мутация | результат мутации |
|
||||
|---|---|---|
|
||||
| `TestEchoRegenReplacesTheHop` | убрать ветку `FlagCJKArtifact && attempt < echoRegen` | `--- FAIL … primary draft calls = 1, want 2 (echo_regen=1)` |
|
||||
|
|
@ -200,13 +131,6 @@ A0, и свёртку трогать не нужно. Свёртку я не т
|
|||
| `TestShippingPipelinesRegenerateEchoBeforeEscalating` | снять ключ из `pipeline-arm-glm.yaml` | `--- FAIL … pipeline-arm-glm.yaml: … = 0, want 1` |
|
||||
| `TestEchoRegenFiresONLYForEcho` | снять проверку ПРИЧИНЫ, оставив `attempt < echoRegen` | `--- FAIL … primary calls = 2, want 1` |
|
||||
|
||||
⚠ **Четвёртая добавлена ПОСЛЕ адверсариального прохода** (§6.2 находка 2): без неё реализация, ре-генящая
|
||||
на ЛЮБОМ флаге — то есть покупающая гарантированный повторный отказ (D2.2) на каждом отказанном чанке
|
||||
каждой книги, — оставляла всю батарею зелёной.
|
||||
⚠ **И различение, которое §6 требует, а первая редакция стирала:** буквально «красная на состоянии ДО
|
||||
правки» здесь только ОДНА — пин конфигов, потому что правка A1 есть ДАННЫЕ. Остальные три держат
|
||||
МЕХАНИЗМ, которым правка пользуется, и краснеют на мутациях кода. Разбор — §6.3.
|
||||
|
||||
⚠ **Ручка была БЕЗ ЕДИНОГО ТЕСТА** до этого пака (`grep -rn RegenerateEchoBeforeEscalate --include=*_test.go` → пусто).
|
||||
Включать в шиппинг ручку на денежном пути, которую держит только чтение кода, я не стала.
|
||||
|
||||
|
|
@ -214,10 +138,9 @@ A0, и свёртку трогать не нужно. Свёртку я не т
|
|||
* **Фикстурная мина, найденная собственной падающей проверкой:** общий `newJSONProvider` всегда отвечает
|
||||
`"model":"fake-model"`, а деньги считаются по ОТВЕТИВШЕЙ модели ⇒ хоп в фикстуре стоил ровно как
|
||||
праймари. Локальный `newPricedProvider` (только в моём файле) отвечает моделью ЗАПРОСА. Общий хелпер не
|
||||
тронут. ⚠ **Поправка к моей же формулировке:** я написала «ассерт на цену ПРОШЁЛ БЫ на двух равных
|
||||
числах» — это НЕВЕРНО и снято адверсариальным проходом: ассерт строгий (`spend[1] < spend[0]`), поэтому
|
||||
на равных числах он КРАСНЕЕТ, громко, с обоими числами в тексте — что и произошло. Комментарий в самом
|
||||
тесте это описывает правильно; неверна была фраза в отчёте.
|
||||
тронут. ⚠ Ассерт цены строгий (`spend[1] < spend[0]`) — на двух равных числах он КРАСНЕЕТ громко, с
|
||||
обоими числами в тексте; различие двух провайдеров описано в докстринге `newPricedProvider`
|
||||
(`internal/pipeline/echoregen_test.go`).
|
||||
* **Бюджет эхо-регена — порог на ТОЙ ЖЕ оси попыток**, что `regenerate_before_escalate`: чанк, уже
|
||||
регенерированный по `length`, приходит к эхо-проверке на `attempt=1` и второго шанса не получает.
|
||||
Записано в комментарий конфига и в тест, поведение не менялось.
|
||||
|
|
@ -245,25 +168,16 @@ A0, и свёртку трогать не нужно. Свёртку я не т
|
|||
reported as delivery
|
||||
```
|
||||
|
||||
### 4.3 ⚠ ГЛАВНОЕ ПО ЭТОМУ ПУНКТУ: моя первая редакция уронила ЧУЖОЙ тест, и я его НЕ ПРАВИЛА
|
||||
Первая версия считала анонс достаточным. `make battery` дала:
|
||||
```
|
||||
--- FAIL: TestARunThatRePaysNothingIsNotAskedForConsent
|
||||
volume_test.go:907: the grant should have gone entirely to fresh delivery
|
||||
```
|
||||
Тот тест «раз-доставляет» два юнита через `ResetChunkStages` и ожидает, что они снова СВЕЖИЕ.
|
||||
|
||||
**По §5 промта тест — не мой, править его ради зелени недопустимо.** Я пошла разбираться, кто прав, и
|
||||
ответ оказался в коде: `ResetChunkStages` **УДАЛЯЕТ и `chunk_status`, и `checkpoints`**
|
||||
(`internal/store/chunkstatus.go`, два `DELETE FROM` в одной транзакции). ⇒ после редрайва отгруженного
|
||||
текста у юнита НЕТ ВООБЩЕ — экспорт по нему пуст. Называть такой юнит «уже доставленной пере-делкой»
|
||||
было бы зеркальной ложью, ровно того класса, который эта ось и убирает.
|
||||
|
||||
⇒ **предикат сужен по СУЩЕСТВУ, а не подогнан под зелень**: доставлен = *читателю сказали* **И** *то, о
|
||||
чём сказали, ещё существует*. Обе половины теперь в докстринге `deliveredUnits`, вместе с признанием, что
|
||||
первая версия была шире и что поймала её именно батарея.
|
||||
⚠ **Отдельная запись для приёмки: чужой тест не изменён ни байтом** (`git status` не показывает
|
||||
`volume_test.go`).
|
||||
### 4.3 Почему предикат сужен ПО СУЩЕСТВУ, а не подогнан под зелень
|
||||
Первая версия оси считала АНОНС достаточным и уронила чужой ратифицированный
|
||||
`TestARunThatRePaysNothingIsNotAskedForConsent` (он «раз-доставляет» два юнита через `ResetChunkStages` и
|
||||
ожидает, что они снова СВЕЖИЕ). Тест не мой, править его ради зелени недопустимо (§5 промта) — ответ
|
||||
нашёлся в коде: `ResetChunkStages` **УДАЛЯЕТ и `chunk_status`, и `checkpoints`**
|
||||
(`internal/store/chunkstatus.go`, два `DELETE FROM` в одной транзакции) ⇒ после редрайва отгруженного
|
||||
текста у юнита НЕТ ВООБЩЕ, экспорт по нему пуст, и звать такой юнит «уже доставленной пере-делкой» было
|
||||
бы зеркальной ложью того же класса, который эта ось убирает.
|
||||
⇒ предикат сужен: доставлен = *читателю сказали* **И** *то, о чём сказали, ещё существует*. Обе половины
|
||||
стоят в докстринге `deliveredUnits` (`internal/pipeline/volume.go`). Чужой тест не изменён ни байтом.
|
||||
|
||||
### 4.4 ВТОРАЯ дыра того же предиката, найденная мной ПОСЛЕ первой — и тоже не рассуждением
|
||||
Разобравшись с редрайвом, я прошла путь анонса до конца и нашла зеркальную дыру: **`unit_done` пишется
|
||||
|
|
@ -310,11 +224,8 @@ payload'а, а не условием. ⇒ анонс сам по себе не
|
|||
термы — консолидируется всё, каждый раз.
|
||||
|
||||
⛔ **И это ОПРОВЕРГАЕТ ось, записанную в строке 194** («на сдвиге снапшота они реально пере-покупаются»).
|
||||
⚠ **Первая редакция этого абзаца доказывала опровержение через П3 («там снапшот сдвинулся, а терминология
|
||||
стоила $0») — это БЫЛО НЕВЕРНО, снято адверсариальным проходом и проверено мной.** Терминология адресована
|
||||
под ЧЕРНОВЫМ снапшотом (`internal/pipeline/mining.go`, греп `runTerminologist(ctx, draftSnapshot`), а в П3
|
||||
сдвинулся РЕДАКТОРСКИЙ — то есть П3 к вопросу об оси отношения не имеет.
|
||||
|
||||
⚠ Считать по П3 нельзя: терминология адресована под ЧЕРНОВЫМ снапшотом (`internal/pipeline/mining.go`,
|
||||
греп `runTerminologist(ctx, draftSnapshot`), а в П3 сдвинулся РЕДАКТОРСКИЙ.
|
||||
**Опровержение стоит на П2 и на прямой улике из таблицы `jobs`:**
|
||||
```
|
||||
sqlite3 'file:…?mode=ro' "SELECT stage,COUNT(*),COUNT(DISTINCT snapshot_id) FROM jobs GROUP BY stage;"
|
||||
|
|
@ -333,7 +244,7 @@ WARN'а, процитированного промтом. Следующий б
|
|||
⇒ **ответ на прямой вопрос промта («накопленное это или трата ЭТОГО прохода — пере-выведи»): НАКОПЛЕННОЕ,
|
||||
по книге и роли, через покупки.** Пере-выведено арифметикой из строк, а не принято со слов.
|
||||
|
||||
⚠ **ДВЕ ПОПРАВКИ К ЭТОМУ ЖЕ АБЗАЦУ, обе сняты адверсариальным проходом и проверены мной:**
|
||||
⚠ **ДВЕ ГРАНИЦЫ ЭТОГО АБЗАЦА, обе проверены по леджеру:**
|
||||
* **Исчерпан был бюджет КЛАССИФИКАТОРА, а не терминолога.** У них РАЗНЫЕ ключи: `classify_budget_usd`
|
||||
($0.02, пробит) и `gates.terminology.budget_usd` ($0.05, при пожизненной трате терминолога
|
||||
`0.01570228 + 0.02491426 = $0.04061654` — НЕ пробит). Формулировка «книга исчерпывает свой
|
||||
|
|
@ -349,17 +260,13 @@ WARN'а, процитированного промтом. Следующий б
|
|||
терм, консолидированный по трём главам, при десяти главах может быть отрендерен лучше. Пропускать
|
||||
уже консолидированные термы — значит фиксировать ранний рендер. Это решение владельца, не сессии, и
|
||||
пак прямо не про качество.
|
||||
3. ⛔ **ТРЕТИЙ ДОВОД Я СНИМАЮ САМА.** Я написала: «лечение A9 и лечение A2 — ОДИН механизм, а A2 за
|
||||
стоп-точкой» (на момент написания она ещё стояла). Адверсариальный проход это опроверг, и я
|
||||
проверила — он прав: рычаги РАЗНЫЕ и не
|
||||
пересекаются. Рычаг A2 — одно сравнение внутри `runBankRoleBatches` (`spent+want > plan.budgetUSD`).
|
||||
Рычаг A9 — ВЫШЕ по течению и другой: КАКИЕ кандидаты попадают в батчи (`buildBankCandidates`) и КАК
|
||||
они пакуются (`terminology.Batch` — жадная пере-упаковка по всему упорядоченному списку). Правка
|
||||
второго бюджета не трогает. **Довод был удобным, а не верным, и он был назван решающим — это худший
|
||||
вид ошибки в отчёте, поэтому называю прямо.**
|
||||
⇒ **Что остаётся после снятия третьего довода:** первые два (калибровка запрещена паком; вторая половина
|
||||
диспозиции — качественная развилка владельца). Их ХВАТАЕТ, чтобы не писать код, но НЕ хватает, чтобы не
|
||||
писать посадку — см. §8 п.3, где я называю этот долг прямо.
|
||||
3. ⚠ **A9 и A2 — РАЗНЫЕ рычаги, и A9 чинится ОТДЕЛЬНО** (проверено по коду; обратный довод первой
|
||||
редакции — «один механизм» — снят): рычаг A2 — одно сравнение внутри `runBankRoleBatches`
|
||||
(`spent+want > plan.budgetUSD`); рычаг A9 — ВЫШЕ по течению: КАКИЕ кандидаты попадают в батчи
|
||||
(`buildBankCandidates`) и КАК они пакуются (`terminology.Batch` — жадная пере-упаковка по всему
|
||||
упорядоченному списку). Правка второго бюджета не трогает.
|
||||
⇒ Двух первых доводов ХВАТАЕТ, чтобы не писать код, но НЕ хватает, чтобы не писать посадку — долг назван
|
||||
в §8 п.1.
|
||||
⇒ Отдаю пингом ГОТОВЫЙ диагноз с числами и названной развилкой. Это дороже, чем «≈1.5×» в реестре.
|
||||
|
||||
---
|
||||
|
|
@ -373,8 +280,8 @@ WARN'а, процитированного промтом. Следующий б
|
|||
— исключение из эхо-правила выдано только терминологу, хотя формат ответа классификатора тот же.
|
||||
Плюс одна строка редактора `degraded=sanitizer_stripped` ($0.01865424) — её текст ОТГРУЖЕН.
|
||||
⇒ наивная поверхность назвала бы оператору **на 29.2% больше потерь, чем было**
|
||||
(`0.12316089 / 0.09531838 = 1.2921`). ⚠ Испр.: первая редакция делила на НАИВНУЮ цифру и печатала
|
||||
22.6% — это доля завышения В САМОЙ наивной цифре, ответ на другой вопрос. Слагаемые не менялись.
|
||||
(`0.12316089 / 0.09531838 = 1.2921`). ⚠ «22.6%», стоящие в записке-плане, — доля завышения В САМОЙ
|
||||
наивной цифре, ответ на ДРУГОЙ вопрос; слагаемые те же.
|
||||
⛔ **Не чинила и не могла:** правка эхо-правила двигает `classifierVersion` — поле снапшота ⇒ ярус B
|
||||
(и это ровно цена, записанная в строке бэклога 105).
|
||||
|
||||
|
|
@ -388,136 +295,29 @@ WARN'а, процитированного промтом. Следующий б
|
|||
|
||||
---
|
||||
|
||||
## 6.1 Собственные посадки и находки ВНЕ списка промта (§7.4 требует не меньше трёх)
|
||||
## 7. ПИНГИ оркестратору №21 — доставлены; открытыми остались ДВА
|
||||
|
||||
**Посадки, которых промт не заказывал:**
|
||||
1. `TestEchoRegenBudgetMovesNoSnapshot` — промт просил РАЗОВЫЙ замер snapshot ID до/после. Я сделала его
|
||||
постоянным гейтом: он краснеет, если КТО-ТО ПОЗЖЕ свернёт ручку в снапшот. Разовый замер этого не ловит.
|
||||
2. `TestAnAnnouncedButFLAGGEDUnitIsStillNewBook` — целиком моя находка: `unit_done` пишется и для
|
||||
ФЛАГНУТОГО юнита, значит анонс сам по себе не значит «читателю есть что открыть». В тексте промта про
|
||||
флагнутые юниты нет ничего.
|
||||
3. `TestShippingPipelinesRegenerateEchoBeforeEscalating` — промт заказывал РЕШЕНИЕ о дефолте; гейт на само
|
||||
решение не заказывал. Без него данные откатываются молча.
|
||||
Отработаны и потому здесь не пересказываются: **A15** (две копии полосы 10–19 обещают разное) — строка
|
||||
бэклога **246**, разбор в законе §6; **A5 · A3(б) · A4 · A7** построены (§9); ось строки **194**
|
||||
опровергнута (§5.1, ратифицировано D39.181 §3); пинг «A9 и A2 — один механизм» снят как неверный
|
||||
(§5.3 п.3).
|
||||
|
||||
**Находки вне списка, не оформленные тестами:**
|
||||
4. Срез `ok=0 AND cost_usd>0` контаминирован мис-вердиктом классификатора — предъявлено ПРЯМОЙ уликой
|
||||
(ответы в `checkpoints.response_text`), §5.4.
|
||||
5. **A15** — две копии полосы 10–19 обещают разное (пинг 1).
|
||||
6. **A12** — `config_drift` без базиса, и он портит `stale` в `build` (пинг 3).
|
||||
7. Комментарий `export.go` называет потребителя (`полигон`), которого в дереве НЕТ (пинг 3).
|
||||
8. **Дефект в моём собственном диффе, найденный собственным чтением диффа:** хелпер `unitShipped` попал
|
||||
ВНУТРЬ докстринга `deliveredUnits`, из-за чего вся объяснительная часть прицепилась не к той функции.
|
||||
`gofmt`, `go vet` и линтер это пропускают. Исправлено, порядок блоков предъявлен командой.
|
||||
|
||||
## 6.2 Адверсариальный проход по СВОЕЙ ГОТОВОЙ работе (промт §7.5) — обязательный артефакт
|
||||
|
||||
**Модель:** ⚠ **явно я её НЕ задавала** — агенты унаследовали модель сессии (Opus 5). Промт §7 велит
|
||||
задавать модель ИМЕНЕМ; я этого не сделала и называю это отступлением, а не деталью. Канон просит Fable 5;
|
||||
по записке `textmachine-36` в канале `claude-fable-5` на этом аккаунте недоступен, но проверять это я не
|
||||
пробовала, так что оправданием не считаю.
|
||||
|
||||
**Сколько агентов и что дано на вход. Два веера, 29 агентов суммарно.**
|
||||
* **Веер 1 — грунтовка корпуса (22 агента):** 2 картографа каналов (движок / платформа) + 10 читателей по
|
||||
строке корпуса + 10 адверсариальных верификаторов ПОВЕРХ отчёта каждого читателя. Вход: код HEAD обеих
|
||||
зон read-only, БД прогона `?mode=ro`, текст промта КАК ПРИОР с прямым мандатом «автор трижды ошибся
|
||||
сегодня, проверяй каждый якорь».
|
||||
* **Веер 2 — проход по ГОТОВОЙ работе (7 агентов):** шесть линз (посадки · каждое число · закон против
|
||||
своего корпуса · код-дифф · заказ против выдачи · решение по A9) + седьмой, механическая сверка с
|
||||
заказом по трёхисходной шкале §6 — **это и есть интервальная сверка, отданная субагенту с явными
|
||||
критериями (промт §7.8)**. Вход: мои три дока, `git diff`, новые тесты, текст промта; мандат дословно —
|
||||
«найди, где она выдаёт непроверенное за проверенное». Линзе посадок было велено КОПИРОВАТЬ дерево в
|
||||
`/tmp` и мутировать копию; реальное дерево агенты не трогали (проверено ими же по md5).
|
||||
|
||||
**Вердикты линз:** 2 × `MATERIALLY_WRONG` (закон против корпуса; код-дифф), 4 × `SOUND_WITH_CORRECTIONS`.
|
||||
Ноль линз не нашли ничего.
|
||||
|
||||
### Находки и диспозиции — каждая, дословно по существу
|
||||
|
||||
| # | находка линзы | диспозиция |
|
||||
|---|---|---|
|
||||
| 1 | **БЛОКЕР (код).** `unitShipped` сканировал ВСЕ строки юнита, включая draft ⇒ обычная форма «draft ok + edit флагнут» читалась как уже доставленная пере-делка, хотя экспорт по ней пуст | **ПРИНЯТО, ПОЧИНЕНО.** `unitShipped` читает строку ОТГРУЖАЮЩЕЙ стадии; добавлена посадка `TestAUnitWhoseEDITFlaggedIsStillNewBook`, красная на пред-фиксной форме (`Delivered=0 Reworked=1`) |
|
||||
| 2 | **БЛОКЕР (тест).** Посадка эхо-регена держала только БЮДЖЕТНУЮ половину ветки: снятие проверки ПРИЧИНЫ оставляет всю батарею зелёной, а такая реализация ре-генит на любом флаге (D2.2 «re-refuse and re-bill») | **ПРИНЯТО, ЗАКРЫТО.** `TestEchoRegenFiresONLYForEcho`; мутация даёт `primary calls = 2, want 1` |
|
||||
| 3 | **БЛОКЕР (тест).** `TestEchoRegenBudgetMovesNoSnapshot` тыкал ПОЛЕ СТРУКТУРЫ; фолд, вычисленный НА ЗАГРУЗКЕ, проходил насквозь. Заказанный промтом замер «ДО и ПОСЛЕ СВОЕГО ДИФФА» (а дифф — пять YAML) не выполнялся | **ПРИНЯТО, ПЕРЕПИСАНО.** Плечо 1 теперь грузит ДВА конфига-фикстуры и сравнивает id; проверено мутацией — фолд значения ручки красит именно это плечо |
|
||||
| 4 | **БЛОКЕР (код+довод).** В пяти правленых конфигах `escalation.budget_usd: 0` ⇒ эскалации там НЕТ, и ре-ген ничего не заменяет; 5.40× снято на КНИЖНОМ конфиге прогона, которого среди пяти нет | **ПРИНЯТО.** §3.3 переписан, комментарии в пяти конфигах называют ОБА режима. Решение не откатываю: во втором режиме ручка выкупает дыру за один дешёвый вызов — довод другой, но выгода реальна |
|
||||
| 5 | **БЛОКЕР (A11).** Развилка `finalStageWave` — та, которую промт приказал решить, — не имела посадки вовсе; удаление ветки оставляло батарею зелёной | **ПРИНЯТО, ЗАКРЫТО.** `TestDeliveryIsReadFromTheSHIPPINGWaveOnADraftOnlyPipeline`; мутация даёт `Delivered=1 LeftFresh=2`, и это ЕДИНСТВЕННЫЙ тест в репозитории, который её ловит |
|
||||
| 6 | **БЛОКЕР (A9).** «В П3 снапшот сдвинулся, а терминология стоила $0» — неверно: терминология адресована под ЧЕРНОВЫМ снапшотом, а сдвинулся редакторский | **ПРИНЯТО, ДОВОД ЗАМЕНЁН НА СИЛЬНЕЙШИЙ.** Опровержение теперь стоит на таблице `jobs`: `draft|10|1` — черновой снапшот не двигался НИ РАЗУ, при этом П2 пере-купила контур целиком |
|
||||
| 7 | **БЛОКЕР (A9).** «Лечение A9 и A2 — один механизм» не подтверждается кодом: рычаги (бюджетное сравнение против отбора/упаковки кандидатов) не пересекаются | **ПРИНЯТО, ДОВОД СНЯТ МНОЮ** (§5.3 п.3). Он был назван решающим — худший вид ошибки, поэтому снят вслух, а не тихо |
|
||||
| 8 | **ВАЖНОЕ (A9).** Пред-регистрированное в записке-плане обязательство «воспроизведение перерасхода фикстурой + посадка» не выполнено и в obstacles не названо | **ПРИНЯТО ЧАСТИЧНО, см. §8 п.3.** Посадку не пишу: она пиннила бы ДЕФЕКТ, и её пришлось бы удалять при починке — в зоне, где удаление теста запрещено правилом. Долг назван прямо |
|
||||
| 9 | **ВАЖНОЕ (числа).** «16 термов» — чужое число из отчёта прогона, без команды и без пометки, а промт называет именно его примером | **ПРИНЯТО.** Помечено «со слов прогона», вывод на нём не строится |
|
||||
| 10 | **ВАЖНОЕ (числа).** «на 22.6% больше потерь» — база не та: правильная величина завышения 29.2% | **ПРИНЯТО, исправлено в обоих доках** |
|
||||
| 11 | **ВАЖНОЕ (закон).** §2.4 — частный случай §2.1, критерия разделения нет, перечни экземпляров расходятся | **ПРИНЯТО.** Отношение названо явно: §2.4 — процедура исполнения §2.1, перечни пересекаются НАМЕРЕННО |
|
||||
| 12 | **ВАЖНОЕ (закон).** A2 не нарушает §2.5 как он написан: фаза как раз отчитывается о трате до `break` | **ПРИНЯТО.** A2 переведён на §2.3; пятую обязанность заводить не стала — одной строки корпуса мало, дыра названа |
|
||||
| 13 | **ВАЖНОЕ (закон).** Предикат вывода объёмного стопа ЛОЖЕН на самом прогоне A5: `reconcile` выносит флагнутое из `Delivered`/`Reworked` | **ПРИНЯТО.** Рекомендация переписана: слать готовый признак числом, а не заставлять потребителя воспроизводить арифметику `reconcile` |
|
||||
| 14 | **ВАЖНОЕ (закон).** Канал A10 (`projected_book_usd`/`rebill_*`) факт НЕ несёт: обе фигуры считаются из `chunk_status`, где терминологических строк НОЛЬ | **ПРИНЯТО.** Канал исправлен на деривацию от `checkpoints ⋈ jobs`; названо, что A10 дороже класса «новое число» |
|
||||
| 15 | **ВАЖНОЕ (закон).** Г1 на рефлексии не перечисляет ТИПЫ, payload'ы потока спрятаны за `json.RawMessage`, а собственный перечень дока уже забыл три типа | **ПРИНЯТО.** Ограничение вписано в §7; названо, что ручная половина полной защиты не даёт |
|
||||
| 16 | **ВАЖНОЕ (закон).** Г3 не реализуем как описан: payload — дерево, часть листьев — кодовые константы, фикстурой не сдвигаемые | **ПРИНЯТО.** Область Г3 сужена до конфигурируемого подмножества; для константных осей предложено требование к сообщению, а не тест |
|
||||
| 17 | **ВАЖНОЕ (закон).** Набор гейтов не покрывает шесть из десяти рекомендованных каналов | **ПРИНЯТО, и это самая дорогая правка дока.** Вписано вслух: «закон загейчен на 40%» |
|
||||
| 18 | **ВАЖНОЕ (закон).** A15 не подводится ни под одну статью: это не значение и не выводится из строк | **ПРИНЯТО, натяжка снята.** A15 остаётся находкой первого класса и перестаёт быть доводом ЗА закон |
|
||||
| 19 | **ВАЖНОЕ (закон).** «Закон есть обобщение `RebillBasis`» — лесть: родословная есть только у §2.3, а сам `RebillBasis` богаче | **ПРИНЯТО, формулировка сужена до §2.3** |
|
||||
| 20 | **ВАЖНОЕ (заказ).** Пинг A5 приказан в `docs/PROGRESS.md` и там отсутствует | **ПРИНЯТО, добавлен** |
|
||||
| 21 | **ВАЖНОЕ (заказ).** Слово «не предъявлено» не использовано ни разу; семь строк несли «разобран» — слово вне шкалы | **ПРИНЯТО.** Восемь строк переведены на «не предъявлено (стоп-точка)» |
|
||||
| 22 | **ВАЖНОЕ (заказ).** §7.5 и §7.8 не имели артефакта в отчёте | **ПРИНЯТО — это она** |
|
||||
| 23 | **МЕЛКОЕ.** «Мутация: добавить поле в payload» — неверно: константа тест не красит | **ПРИНЯТО, описание мутации исправлено** |
|
||||
| 24 | **МЕЛКОЕ.** §3.5 утверждал, что на общем провайдере ассерт цены «прошёл бы» — на деле он краснеет громко | **ПРИНЯТО, инверсия исправлена** |
|
||||
| 25 | **МЕЛКОЕ.** `TestEchoRegenReplacesTheHop` на состоянии ДО правки ПРОХОДИТ — он ловит мутацию КОДА, а не откат данных | **ПРИНЯТО, см. §6.3** |
|
||||
|
||||
### 6.3 Что из требований §6 я НЕ выполняю буквально — с доводом
|
||||
§6 требует, чтобы посадка для A1–A5 краснела на состоянии **ДО правки**. Для A1 правка — это ДАННЫЕ, и
|
||||
буквально этому условию отвечает ОДНА посадка из трёх: `TestShippingPipelinesRegenerateEchoBeforeEscalating`
|
||||
краснеет на конфигах HEAD пятью строками, по одной на файл. Две другие (`TestEchoRegenReplacesTheHop`,
|
||||
`TestEchoRegenFiresONLYForEcho`) на состоянии ДО правки ЗЕЛЁНЫЕ — они держат МЕХАНИЗМ, которым правка
|
||||
пользуется, и краснеют на мутациях кода. **Это не подгонка, а разные предметы**, но отчёт обязан их
|
||||
различать, а первая редакция лила все три в одну строку «проверены краснотой».
|
||||
|
||||
## 7. ПИНГИ оркестратору №21
|
||||
|
||||
1. ⛔ **A15 — САМЫЙ СРОЧНЫЙ, и он на шве. Две копии полосы 10–19 обещают РАЗНОЕ.** Движок
|
||||
(`backend/cmd/tmctl/main.go`, греп `The refusal band`): «**«Nothing was written» is NOT the band's
|
||||
promise any more** … exit 15 legitimately answers with files on disk». Платформа
|
||||
(`platform/internal/ingest/exit.go`, греп `The refusal band`): «… **and nothing this process would
|
||||
have written was written**». Потребитель держит гарантию, которую производитель отозвал, а по `PD-196`
|
||||
интейк действует по полосе РАЗРУШИТЕЛЬНО. Правка — чужая зона.
|
||||
⚠ Денежная половина («nothing was spent») цела в обеих копиях; запрет отказывать в A2 классом полосы стоит.
|
||||
⚠ Хвост: движок объявляет `exitBookIncomplete = 16`, у платформы константы с этим номером нет вовсе.
|
||||
2. **A5 — пинг с домашней заготовкой** (полная таблица носителей — закон §5 A5). Кратко: новый код выхода
|
||||
нельзя; **новое значение `Finished.Outcome` тоже нельзя** — но НЕ потому, что пара биективна (она не
|
||||
биективна, `OutcomeRefused` двойника не имеет), а потому, что значение только в потоке заставило бы два
|
||||
канала назвать РАЗНЫЙ исход одного прогона. ⇒ рекомендую **ЧИСЛА**: леджер доставки
|
||||
(`max_units · delivered · reworked · flagged · free · left_fresh · left_rework`) полями кадра `finished`.
|
||||
Класс — «новое поле» ⇒ ваша ратификация.
|
||||
⚠ И поправка к срочности: **платформа сегодня `--max-units` НЕ ШЛЁТ вообще** (`TranslateArgs`, вся зона
|
||||
`platform/` — ни одного вхождения вне комментария). Это дефект будущего потребителя.
|
||||
3. **Комментарий `export.go` называет несуществующего потребителя.** Он утверждает, что `ConfigDrift`
|
||||
читает полигон; `grep -rn 'config_drift\|ConfigDrift' eval/` даёт НОЛЬ хитов. Настоящие потребители —
|
||||
человеческий рендер и **`build`** (`staleUnits` начинается с `if exp.ConfigDrift { return nil, true }`),
|
||||
а значит тихое `config_drift=false` заставляет `build` печатать `stale: 0` вместо `stale: UNKNOWN`:
|
||||
поле БЕЗ базиса портит поле, у которого базис есть.
|
||||
4. **A3(б) — ОПРОВЕРГНУТО как дефект `book_files`.** Контракт «карта МЕСТ, не присутствия» написан ОБЕИМИ
|
||||
сторонами с доводом (гонка check-then-open), и платформа `book_files` не декодирует вовсе. Настоящий
|
||||
дефект в том же месте: `build --format epub` МОЛЧА удаляет соседний `.txt`, различая «файл был» от
|
||||
«файла не было» и выбрасывая различение.
|
||||
5. **Строка 194: названная в ней ось ОПРОВЕРГНУТА** живыми данными (§5.1). Ось — байты батча, не сдвиг снапшота.
|
||||
6. **A7: наивная правка заводит НОВУЮ ложь.** `projectRebill` пропускает ровно те строки, на которые
|
||||
сработает новое правило ⇒ `config_drift=true` при `rebill_units=0`, а человеческий рендер превращает
|
||||
этот флаг в утверждение о пере-оплате, которой не будет. Правка A7 обязана идти вместе с базисом.
|
||||
7. **A4: готового дифа полей НЕТ.** `classifySnapshotMove` возвращает `moveOther` на ПЕРВОМ несовпавшем
|
||||
ключе, ходя по Go-мапе ⇒ множества разошедшихся полей не собирает, и порядок недетерминирован. Диф для
|
||||
сообщения — новый и сортированный.
|
||||
8. ⚠ **ЭТОТ ПИНГ БЫЛ НЕВЕРЕН И СНЯТ МНОЙ ЖЕ.** В первой редакции он гласил «A9/A2 — один механизм,
|
||||
разводить их по разным пакам значит чинить половину». Адверсариальный проход это опроверг, я проверила
|
||||
и согласилась (§5.3 п.3): рычаг A2 — одно сравнение бюджета внутри `runBankRoleBatches`; рычаг A9 —
|
||||
выше по течению и другой (отбор кандидатов и упаковка батчей). Они НЕ пересекаются, и A9 можно чинить
|
||||
отдельно. Пинг пережил снятие довода, на котором стоял, — поймано приёмкой; исправляю, а не удаляю,
|
||||
чтобы след ошибки остался.
|
||||
9. **Вопрос про `books/`:** предыдущая сессия спрашивала, кто коммитит репозиторий книг. Я туда не писала;
|
||||
вопрос остаётся открытым.
|
||||
1. **Комментарий `export.go` называет несуществующего потребителя — ОТКРЫТО.** Он утверждает, что
|
||||
`ConfigDrift` читает полигон; `grep -rn 'config_drift\|ConfigDrift' eval/` даёт НОЛЬ хитов (контроль:
|
||||
тот же греп по `export` в `eval/` хиты даёт — инструмент в этой области работает). Настоящие
|
||||
потребители — человеческий рендер и **`build`** (`staleUnits` начинается с
|
||||
`if exp.ConfigDrift { return nil, true }`). Комментарий на месте до сих пор
|
||||
(`internal/pipeline/export.go`, греп `polygon's extraction, which uses ConfigDrift`); полный разбор —
|
||||
закон §6 A12 п.4.
|
||||
2. **Вопрос про `books/` — ОТКРЫТ:** предыдущая сессия спрашивала, кто коммитит репозиторий книг.
|
||||
Я туда не писала.
|
||||
|
||||
---
|
||||
|
||||
## 8. Obstacle reporting — что НЕ удалось и что НЕ проверено
|
||||
|
||||
1. ⛔ **Пред-регистрированная посадка A9 не написана.** Моя же записка-план обещала «воспроизведение
|
||||
перерасхода фикстурой + посадка». Ратификации она не требует, так что три довода §5.3 её НЕ покрывают.
|
||||
перерасхода фикстурой + посадка». Ратификации она не требует, так что доводы §5.3 её НЕ покрывают.
|
||||
Причина, которую даю вместо них: она пиннила бы ДЕЙСТВУЮЩИЙ дефект, и при починке следующей сессии
|
||||
пришлось бы её удалить — в зоне, где удаление теста запрещено правилом, это ловушка. Довод слабее
|
||||
остальных, и я подаю его таким. Живая улика (`jobs`: `draft|10|1`) сильнее фикстуры, но она не гейт.
|
||||
|
|
@ -533,12 +333,10 @@ WARN'а, процитированного промтом. Следующий б
|
|||
7. **Корпусные тесты батареи не гонялись** (три скипа названы).
|
||||
8. **Экономика A1 — направление доказано, величина нет**; порог выгоды ≈18.5%, не-восстанавливающееся
|
||||
плечо не протестировано.
|
||||
9. ⚠ **Модель субагентам я НЕ задавала явно** — унаследовали модель сессии. Промт §7 велит задавать именем.
|
||||
10. **A10 добавляет к проекции УЖЕ ПОТРАЧЕННОЕ, а не прогноз контура** — это нижняя граница, и названа
|
||||
9. **A10 добавляет к проекции УЖЕ ПОТРАЧЕННОЕ, а не прогноз контура** — это нижняя граница, и названа
|
||||
таковой в коде. Прогноз контура требует калибровки, запрещённой этому паку.
|
||||
11. **Живого платного прогона не было ни одного** — пак $0. Всякий клейм о рантайме здесь либо снят с
|
||||
10. **Живого платного прогона не было ни одного** — пак $0. Всякий клейм о рантайме здесь либо снят с
|
||||
ЛЕДЖЕРА чужого прогона read-only, либо получен исполнением ТЕСТА.
|
||||
12. **Ничего не закоммичено.** Лендит оркестратор.
|
||||
|
||||
## 9. ФАЗА 2 — десять экземпляров закона, по одному
|
||||
|
||||
|
|
@ -559,6 +357,22 @@ bought-nothing-shippable …` и, когда есть потери, называ
|
|||
Плюс тест сверяет сумму разложения с `committed` — чтобы разложение не стало вторым, дрейфующим
|
||||
определением траты книги.
|
||||
|
||||
⚠ **ЧЕТВЁРТЫЙ КЛАСС — BANK («купил терминологию, не текст»), и без него разложение несло ХУДШУЮ версию
|
||||
болезни, от которой построено** (найдено приёмкой): банк-роли `chunk_status` **не пишут вовсе**
|
||||
(`grep -c UpsertChunkStatus terminologist.go` → 0 при контроле `stagerun.go` → 2), а «отгружено»
|
||||
определялось через `FinalHash` из `chunk_status` ⇒ весь терминологический контур ПО ПОСТРОЕНИЮ уезжал в
|
||||
потери: $0.04980482 из «потерь» $0.133 — **завышение 59.8%**, хуже наивного среза `ok=0` (29.2%), который
|
||||
этот же файл в шапке за это и отвергает; на ЗДОРОВОЙ книге оператор читал «85.7% did NOT become shipped
|
||||
text». Класс опознаётся по синтетической стадии и исключён из `LostUSD`
|
||||
(`internal/pipeline/paidtail.go`, греп `BANK — it bought the book's TERMINOLOGY`).
|
||||
⚠ Суперсед банк-батча ОСТАЁТСЯ потерей — контур пере-покупается с ростом черновика (строка 233).
|
||||
**Посадки:** `TestAHealthyGlossaryPassIsNotReportedAsALoss` (мутация «убрать класс» даёт
|
||||
`WorstPosition:book/batch0/terminology` — сурфейс указывает оператору на здоровый батч) ·
|
||||
`TestAReboughtGlossaryBatchIsStillALoss`.
|
||||
⚠ `TestTheDecompositionIsNotTheOkColumn` ПИННИЛ дефект (требовал `WithheldUSD == 0.009` про успешный
|
||||
вызов классификатора). Смена его утверждения **разрешена оркестратором ЯВНО при приёмке** (D39.182 §2 п.2),
|
||||
ссылка стоит в комментарии самого теста — это не подгонка под зелень и не прецедент «так можно».
|
||||
|
||||
### 9.2 A2 — фаза стартовала, зная, что не влезает
|
||||
**Стало:** план режется до влезающего **ДО первого вызова**; строка называет `batches_planned`,
|
||||
`batches_running`, `batches_dropped`, `budget_usd`; уже оплаченные батчи допускаются всегда.
|
||||
|
|
@ -570,6 +384,10 @@ consolidated» — потому что `unanswered` в одиночку чита
|
|||
Вторая — это ось «никакая частичная работа не оплачена», предъявленная фикстурой, а не рассуждением:
|
||||
мутация «стартовать всё равно» даёт `--- FAIL … a plan that fits nothing must spend NOTHING … got $0.005460`.
|
||||
|
||||
⚠ Обрезка называется ДВАЖДЫ: у классификатора СВОЙ бюджет (`classify_budget_usd`), и инцидент прогона был
|
||||
именно на нём, поэтому в результате отдельное поле `ClassifyBatchesDropped`
|
||||
(`internal/pipeline/terminologist.go`) и оба числа в логе.
|
||||
|
||||
### 9.3 A3 — `build`
|
||||
**(а) Стало:** сбой уборки больше не возвращается ошибкой. Файлы уже закоммичены, уборка — housekeeping,
|
||||
и её сбой не смеет превратить записанную книгу в «инфра-сбой, ничего не записано». Отчёт выживает и несёт
|
||||
|
|
@ -599,6 +417,10 @@ consolidated» — потому что `unanswered` в одиночку чита
|
|||
(без него «присутствие = признак» ничего не значит) · `TestTheLedgerIsOmittedNotNulled` (ключ ОТСУТСТВУЕТ,
|
||||
а не `null`).
|
||||
|
||||
⚠ Новое поле кадра бампает МИНОР потока: `StreamVersion` = `1.2` (`internal/runevents/runevents.go`) —
|
||||
правило записано в комментарии над самой константой, и первая редакция правки его нарушила. Платформенное
|
||||
зеркало не тронуто: мажор совпадает.
|
||||
|
||||
### 9.6 A6 — деньги слепы к правке исходника на месте
|
||||
**Стало:** ветка совпавшего снапшота сверяет контент-хеш — тот же предикат, что применяет сам прогон.
|
||||
⚠ **Дорогая сверка гейтится дешёвым зондом:** валидность сохранённого манифеста (его ключ фолдит SHA
|
||||
|
|
@ -607,6 +429,14 @@ consolidated» — потому что `unanswered` в одиночку чита
|
|||
**Посадки:** `TestTheProjectionSeesAnInPlaceSourceEdit` (плюс проверка, что прогон РЕАЛЬНО платит — иначе
|
||||
проекция была бы права) · `TestAnUntouchedSourceStillCostsNoReChunk` (зонд).
|
||||
|
||||
⚠ **Ответ зонда обязан быть ЗАФИКСИРОВАН ДО перезаписи сайдкара.** Зонд спрашивает о ВАЛИДНОСТИ
|
||||
сохранённого манифеста, а `translate` персистит манифест РАНЬШЕ гейта согласия — значит к моменту вопроса
|
||||
сайдкар уже описывал НОВЫЙ исходник: зонд отвечал «ничего не двигалось», дорогая сверка пропускалась, и **гейт согласия на пере-оплату не срабатывал на правке исходника на месте** — ровно на
|
||||
сценарии, ради которого A6 заведён. Найдено приёмкой; первый тест этого не ловил, потому что бил в
|
||||
`Status`, а не в `TranslateBook`. Лечение — `noteSourceVintage()` перед `persistManifest`
|
||||
(`internal/pipeline/bookrun.go`) плюс кэш ответа, который заодно снял хеширование всего исходника ПО
|
||||
КАЖДОЙ СТРОКЕ на $0-пути. **Посадка написана ДО правки и была красной:** `TestTheCONSENTGateSeesAnInPlaceSourceEdit`.
|
||||
|
||||
### 9.7 A7 + A12 — одним касанием, как потребовал оркестратор
|
||||
**Стало:** правило осиротевшей стадии поднято в ОДНО определение (`orphanStageRows`), общее для `status` и
|
||||
`export`. ⛔ Свёртка банка НЕ унифицирована — `export.go` объявляет это расхождение сознательным и просит
|
||||
|
|
@ -622,6 +452,10 @@ basis="none"` — дословно дефект прогона) · `TestACleanBo
|
|||
`TestABookWithNoRowsCannotHaveItsDriftChecked` · `TestTheDriftBasisVocabularyIsClosed`; плюс в `cmd/tmctl`
|
||||
`TestDriftDoesNotClaimARePaymentItNeverComputed` · `TestAnUnknownDriftBasisIsSaidOutLoud`.
|
||||
|
||||
⚠ Обе поверхности спрашивают ОДНУ предпосылку `driftCheckable` (`internal/pipeline/driftbasis.go`): без
|
||||
неё базис расходился на одной книге (`unknown` против `none`) — то есть строка 239 воспроизводилась В
|
||||
ЛЕКАРСТВЕ ОТ НЕЁ. Посадка `TestBothSurfacesReachTheSameBasisOnTheSameBook` на трёх состояниях книги.
|
||||
|
||||
### 9.8 A8 — метка не отслеживала байты промпта
|
||||
**Стало:** репо-гейт `TestPromptLabelsPinTheirBytes` с реестром `testdata/prompt-labels.json`, ключ
|
||||
`(пара, роль, метка)` → sha256 канонического промпта. Обновление легитимного бампа —
|
||||
|
|
@ -645,6 +479,12 @@ basis="none"` — дословно дефект прогона) · `TestACleanBo
|
|||
`SUM(checkpoints)`; `TestABookWithNoBankRolesProjectsExactlyAsBefore` — на книге без банк-ролей ничего не
|
||||
сдвинулось.
|
||||
|
||||
⚠ **Порог согласия берётся ДО слагаемого A10** (решение оркестратора при приёмке, D39.182 §3): порог
|
||||
управляет ПЕРЕ-оплатой, а контур ею не является, и слагаемое в базе порога сделало бы денежный гейт слабее.
|
||||
Публикуемая проекция контур сохраняет (`internal/pipeline/rebill.go`, греп `contour before the threshold
|
||||
was taken`). Посадка `TestTheContourDoesNotWeakenTheConsentGate`: мутация «свернуть контур в базу порога»
|
||||
даёт `got: <nil>` — пере-оплата проходит НЕСПРОШЕННОЙ.
|
||||
|
||||
### 9.10 ⚠ ЧУЖОЙ ТЕСТ, КОТОРОГО Я КОСНУЛАСЬ — называю сама
|
||||
`TestTerminologistBudgetCutIsNotReportedAsAnEmptyReply` (`bankfixpack_test.go`) проверял свою
|
||||
ПРЕДПОСЫЛКУ грепом по логу — искал `budget would be exceeded`. Правка A2 эту строку не переживает по
|
||||
|
|
@ -654,15 +494,11 @@ basis="none"` — дословно дефект прогона) · `TestACleanBo
|
|||
Я не стала печатать старую фразу рядом с новой ради совпадения грепа: это было бы вводить в заблуждение
|
||||
ради зелени, то есть нарушать закон, который я же пишу. Предпосылка переведена с подстроки на ФАКТ
|
||||
(`lastTerminology.BatchesDropped == 0`) — строго сильнее и ровно то, что предписывает D39.171.
|
||||
**Отправлено пингом оркестратору с прямым предложением откатить.** Он правку ОСТАВИЛ, проверив дифф сам:
|
||||
удалены ровно две строки предпосылки, утверждение стоит контекстной строкой диффа. Его разбор:
|
||||
запрет канона бьёт по УТВЕРЖДЕНИЮ теста, а я поменяла МЕХАНИЗМ ПРЕДПОСЫЛКИ — и поменяла с механизма,
|
||||
который проект ратифицированно считает дефектным (D39.171), на структурный факт. Общую норму «правка
|
||||
предпосылки ≠ правка утверждения» он сам не устанавливает и несёт владельцу как вопрос.
|
||||
|
||||
⚠ **И ПОРЯДОК БЫЛ НЕВЕРНЫЙ — фиксирую без смягчения.** Правило говорит «пинг, НЕ правка», а я сделала
|
||||
правку и пинг. То, что я вынесла это сама и предложила откатить, объясняет, почему ответ соразмерный, но
|
||||
не отменяет, что порядок нарушен. На будущее: пинговать ДО правки, даже когда уверена.
|
||||
Оркестратор правку ОСТАВИЛ, проверив дифф сам (удалены ровно две строки предпосылки, утверждение стоит
|
||||
контекстной строкой): запрет канона бьёт по УТВЕРЖДЕНИЮ теста, а сменён был МЕХАНИЗМ ПРЕДПОСЫЛКИ — с
|
||||
механизма, который проект ратифицированно считает дефектным (D39.171), на структурный факт. ⚠ Общей нормы
|
||||
«правка предпосылки ≠ правка утверждения» он НЕ устанавливает — она унесена владельцу вопросом (D39.182
|
||||
§2). ⚠ Порядок был нарушен: правка, потом пинг, а правило говорит «пинг, НЕ правка».
|
||||
|
||||
⚠ **ВТОРАЯ ПОЛОВИНА ТОГО ЖЕ ТЕСТА ОСТАВЛЕНА НА ТОЙ ЖЕ БОЛЕЗНИ — СОЗНАТЕЛЬНО, и это строка для следующего.**
|
||||
Сохранённое утверждение `strings.Contains(out, "EMPTY completion")` стоит на ТОМ ЖЕ механизме, который я
|
||||
|
|
@ -671,83 +507,6 @@ basis="none"` — дословно дефект прогона) · `TestACleanBo
|
|||
Найдено оркестратором при чтении диффа; названо здесь, чтобы следующий, кто придёт сюда по D39.171, видел,
|
||||
что половина известна и оставлена намеренно, а не пропущена.
|
||||
|
||||
## 9.11 ПРИЁМКА: три блокера и пять дофиксов — что было не так и что сделано
|
||||
|
||||
Приёмка вернула пак на доработку. **Все три блокера подтверждены мной исполнением, а не приняты на слово**,
|
||||
и каждый закрыт с посадкой.
|
||||
|
||||
### Блокер 1 — A0 содержал ХУДШУЮ версию болезни, от которой построен
|
||||
Банк-роли `chunk_status` **не пишут вовсе** (`grep -c UpsertChunkStatus terminologist.go` → 0; контроль:
|
||||
`stagerun.go` → 2, инструмент работает). А `shipped` определялся через `FinalHash` из `chunk_status` ⇒
|
||||
**весь терминологический контур по построению не мог быть «отгружен»** и целиком уезжал в потери:
|
||||
$0.04980482 из «потерь» $0.133 — **завышение 59.8%**, хуже, чем 29.2% наивного среза `ok=0`, который мой
|
||||
же файл в шапке за это отвергает. На ЗДОРОВОЙ книге оператору печаталось «85.7% did NOT become shipped text».
|
||||
**Сделано:** четвёртый класс **BANK** («купил терминологию, не текст»), опознаваемый по синтетической
|
||||
стадии; `LostUSD` его исключает; текст сменён на «bought NOTHING — neither text nor terminology».
|
||||
⚠ Суперсед банк-батча ОСТАЁТСЯ потерей — контур пере-покупается с ростом черновика (строка 233), и
|
||||
амнистии тут быть не должно.
|
||||
**Посадки:** `TestAHealthyGlossaryPassIsNotReportedAsALoss` (мутация «убрать класс» даёт
|
||||
`WorstPosition:book/batch0/terminology` — сурфейс указывает оператору на здоровый батч) ·
|
||||
`TestAReboughtGlossaryBatchIsStillALoss`.
|
||||
⚠ **САНКЦИЯ НА СМЕНУ УТВЕРЖДЕНИЯ.** Мой `TestTheDecompositionIsNotTheOkColumn` ПИННИЛ дефект — требовал
|
||||
`WithheldUSD == 0.009` про успешный вызов классификатора. Смена утверждения **разрешена оркестратором
|
||||
явно 31.08** при приёмке (тест фиксировал поведение, признанное неверным); ссылка стоит в комментарии
|
||||
самого теста. Это не подгонка под зелень, и запись здесь — чтобы следующая сессия не прочла это как
|
||||
прецедент «так можно».
|
||||
|
||||
### Блокер 2 — A6 был починен на ЧИТАЮЩЕЙ поверхности и мёртв на ДЕНЕЖНОЙ
|
||||
Зонд `sourceMovedUnderTheRows()` спрашивал о ВАЛИДНОСТИ манифеста, а `translate` персистит манифест
|
||||
**раньше** гейта согласия (`bookrun.go:187` против `:222` — проверено). ⇒ к моменту вопроса сайдкар уже
|
||||
описывал НОВЫЙ исходник, зонд отвечал «ничего не двигалось», дорогая сверка пропускалась, и **гейт
|
||||
согласия на пере-оплату не срабатывал на правке исходника на месте** — то есть ровно там, ради чего A6 и
|
||||
заведён. Мой первый тест этого не поймал, потому что бил в `Status`, а не в `TranslateBook`.
|
||||
**Сделано:** ответ зонда ФИКСИРУЕТСЯ до перезаписи сайдкара (`noteSourceVintage()` перед
|
||||
`persistManifest`) и кэшируется — это же закрывает **Д4** (зонд спрашивался ПО СТРОКЕ и каждый раз хешировал
|
||||
весь исходник, O(строк × байт) на $0-пути).
|
||||
**Посадка написана ДО правки и была красной:** `TestTheCONSENTGateSeesAnInPlaceSourceEdit`.
|
||||
|
||||
### Блокер 3 — вердикт «предъявлено» против неработающего пути
|
||||
Снят вместе с блокером 2; в §1 вердикты A0 и A6 стояли «предъявлено» на неполной проверке. Оба
|
||||
пере-предъявлены посадками выше.
|
||||
|
||||
### Дофиксы
|
||||
* **Д1 — `StreamVersion` не был бампнут.** Я добавила поле `volume` в кадр `finished` и оставила `"1.1"` —
|
||||
при том что правило «поле бампает минор» записано ДОСЛОВНО в комментарии НАД этой же константой, в
|
||||
файле, который я правила. Поток нёс факт, о котором его собственная версия говорила, что его там нет —
|
||||
ирония по существу пака. **`"1.2"` + абзац.** Платформенное зеркало не тронуто (мажор совпадает).
|
||||
* **Д2 — базис расходился между `status` и `export`** на одной книге: `unknown` против `none`. Это строка
|
||||
239, воспроизведённая В ЛЕКАРСТВЕ ОТ НЕЁ. **Сделано:** одна общая предпосылка `driftCheckable`.
|
||||
Посадка `TestBothSurfacesReachTheSameBasisOnTheSameBook` на трёх состояниях книги; мутация даёт ровно
|
||||
`status="unknown" export="none"`.
|
||||
* **Д3 — носитель обрезки доехал только для рендера**, а инцидент прогона был на КЛАССИФИКАТОРЕ (у него
|
||||
свой бюджет `classify_budget_usd`, и пробит был именно он). **Сделано:** отдельное поле
|
||||
`ClassifyBatchesDropped`, оба названы в логе.
|
||||
* **Д4** — закрыт вместе с блокером 2 (кэш); слово «cheap» из комментария убрано.
|
||||
* **Д5** — пинг 8 пережил снятие довода §5.3 п.3: исправлен НА МЕСТЕ, а не удалён, чтобы след ошибки
|
||||
остался. «Незагейченность» названа полностью: **Г1 не построен · Г2 не построен · Г3 построен точечно ·
|
||||
A8 построен · Г4 НЕ ПОСТРОЕН**, и §2.5 объявлена НЕЗАГЕЙЧЕННОЙ статьёй.
|
||||
|
||||
### Решение оркестратора, которое я НЕ принимала сама: порог согласия БЕЗ контура
|
||||
Мой слагаемый A10 попал не только в проекцию, но и в БАЗУ порога согласия — 5% считались от суммы с
|
||||
контуром, то есть **денежный гейт стал слабее, и я этого не назвала.** Решение оркестратора: порог
|
||||
governs ПЕРЕ-оплату, а контур ею не является. **Сделано:** порог берётся до слагаемого; публикуемая
|
||||
проекция контур сохраняет. Посадка `TestTheContourDoesNotWeakenTheConsentGate` — мутация «свернуть контур
|
||||
в базу порога» даёт `got: <nil>`, то есть пере-оплата проходит НЕСПРОШЕННОЙ.
|
||||
|
||||
### ⚠ ТРИ ЧУЖИХ ТЕСТА — САНКЦИОНИРОВАННАЯ ПРАВКА СЦЕНАРИЯ (не утверждения)
|
||||
Починка блокера 2 меняет поведение денежного пути, и три ратифицированных теста падали — все на одном:
|
||||
их сценарий правит исходник и ждёт, что `translate` пройдёт. Ни один не про согласие.
|
||||
**Я пингнула ДО правки** (в отличие от первого случая за этот пак) и предложила три варианта с доводами,
|
||||
включая довод против собственного предпочтения. Оркестратор выбрал (а) с двумя условиями, обе выполнены:
|
||||
* **условие 1 — тронут только сценарий.** Предъявлено диффом: `runner_test.go` и `bookbuild_test.go` —
|
||||
**0 удалённых строк**, ровно по одной добавленной строке `AcceptRebill` каждая; `bankfixpack_test.go` —
|
||||
та же одна строка (его 2 удалённые относятся к ОТДЕЛЬНО санкционированной правке предпосылки, §9.10).
|
||||
Ни одна строка `t.Error`/`t.Fatal` не тронута.
|
||||
* **условие 2 — гарантия стала явной.** Все три ссылаются в комментарии на
|
||||
`TestTheCONSENTGateSeesAnInPlaceSourceEdit`, чтобы читатель видел, КУДА уехала гарантия.
|
||||
⚠ **Санкция оркестратора от 31.08, при приёмке этого пака.** Три касания чужих тестов за пак — много, и
|
||||
каждое обязано читаться как разрешённое, а не как прецедент.
|
||||
|
||||
## 10. Изменённые файлы
|
||||
|
||||
| файл | что |
|
||||
|
|
@ -769,19 +528,22 @@ governs ПЕРЕ-оплату, а контур ею не является. **С
|
|||
| `internal/store/outbox.go` | A11: `AnnouncedOnceKeys()` — читающий метод строки 232 |
|
||||
| `cmd/tmctl/render.go` | A7: строка дрейфа больше не утверждает пере-оплату; A12: базис вслух; A0: секция денег |
|
||||
| 11 новых `*_test.go` + `testdata/prompt-labels.json` | 33 посадки |
|
||||
| `internal/pipeline/bankfixpack_test.go` | ⚠ ЕДИНСТВЕННОЕ касание чужого теста — ПРЕДПОСЫЛКА, разбор §9.10 |
|
||||
| `internal/pipeline/bankfixpack_test.go` | ⚠ касание чужого теста — ПРЕДПОСЫЛКА, разбор §9.10 |
|
||||
| `backend/docs/*.md` (3) | записка-план, дизайн закона, этот отчёт |
|
||||
| `docs/PROGRESS.md` | секция «Бэкенд» — единственное исключение канона |
|
||||
|
||||
**Чужого не тронуто, кроме одной предпосылки, названной в §9.10 и оставленной оркестратором.**
|
||||
Ни `platform/`, ни `frontend/`, ни `eval/`, ни `books/`, ни остальное в `docs/`.
|
||||
**Касаний ЧУЖИХ тестов три класса, все санкционированы ЯВНО и ни одно не тихое** (условия и разбор —
|
||||
D39.182 §2): ПРЕДПОСЫЛКА `bankfixpack_test.go` (§9.10) · УТВЕРЖДЕНИЕ `TestTheDecompositionIsNotTheOkColumn`
|
||||
(§9.1) · СЦЕНАРИЙ трёх ратифицированных тестов, которых починка A6 заставила проходить гейт согласия
|
||||
(`runner_test.go`, `bookbuild_test.go`, `bankfixpack_test.go` — по ОДНОЙ добавленной строке `AcceptRebill`,
|
||||
ноль удалённых строк, ни одна `t.Error`/`t.Fatal` не тронута; каждый ссылается в комментарии на
|
||||
`TestTheCONSENTGateSeesAnInPlaceSourceEdit`, куда уехала гарантия).
|
||||
Ни `platform/`, ни `frontend/`, ни `eval/`, ни `books/`, ни остальное в `docs/` не тронуто.
|
||||
|
||||
## 11. Последний абзац — состояние, не план
|
||||
## 11. Состояние на закрытии пака
|
||||
|
||||
Пак закрыт обеими фазами. Закон ратифицирован и применён к десяти экземплярам; корпус вырос до
|
||||
Обе фазы отработаны. Закон ратифицирован (D39.181) и применён к десяти экземплярам; корпус вырос до
|
||||
четырнадцати, и четыре лишних нашла мерка, а не заказ. Тридцать три посадки, каждая красная под своей
|
||||
мутацией; батарея зелёная с кодом, снятым с самого `make`, и тремя названными скипами. Три довода я сняла
|
||||
как неверные — по A9, по биективности словарей и по 22.6% — и все три были моими собственными и
|
||||
названными сильными. Один порядок действий я нарушила и зафиксировала это без смягчения. Долг по посадке
|
||||
A9 и вторая половина чужого теста на дефектном механизме оставлены НАЗВАННЫМИ, а не закрытыми. Ничего не
|
||||
закоммичено; лендинг за оркестратором.
|
||||
мутацией; батарея зелёная с кодом, снятым с самого `make`, и тремя названными скипами. Открытое оставлено
|
||||
НАЗВАННЫМ, а не закрытым: долг по посадке A9 (§8 п.1) и вторая половина чужого теста на дефектном
|
||||
механизме (§9.10). Пак принят и заленджен 31.08 — `bb541a8`, нота D39.182.
|
||||
|
|
|
|||
|
|
@ -1,80 +1,20 @@
|
|||
# План дофикса-2 входной двери шва (промт BACKEND_SEAM_FIX2_SESSION_PROMPT.md)
|
||||
# Записка-план дофикса-2 входной двери шва (13 пунктов §4)
|
||||
|
||||
> Записка-план по §7 промта. Комплектность против §4 сверена механически:
|
||||
> `grep -cE '^### 4\.' docs/BACKEND_SEAM_FIX2_SESSION_PROMPT.md` → **13**.
|
||||
> Ответ на развилку §7 (один пак или два): **один пак**, довод промта принимаю и добавляю свой —
|
||||
> §4.3 (авто-провод при поднятом флаге) меняет ту же ветку `runBankMiningStop`, чьё сообщение стопа
|
||||
> переписывает §4.12, а отчёт двери (§4.5) обязан узнать класс §4.7 — раздельные паки резали бы
|
||||
> одну функцию и один enum пополам.
|
||||
> ⚠ **Записка ОТРАБОТАВШЕЙ сессии, а не задание: не исполнять.** Дофикс-2 закончен, принят и залендён —
|
||||
> D39.158 (стоп банка — флажок; полоса в два яруса и класс 15; отчёт двери v2; пути решений — только
|
||||
> конвенцией). Что реально сделано, с доводами и остатками — `backend/docs/SEAM_PACK_FINDINGS.md`:
|
||||
> состав и пофайловый список §36, решения §4.1–§4.3 с доводами §37, замеры §38, живые пробы §39,
|
||||
> «что НЕ удалось» §41, попунктный чек всех тринадцати §43. Промт архивирован:
|
||||
> `docs/archive/prompts/BACKEND_SEAM_FIX2_SESSION_PROMPT_2026-08-27.md`.
|
||||
|
||||
## Порядок работ (зависимость §4.2 соблюдена: атомарность карты — первой)
|
||||
## Названные заранее развилки — и что с ними стало
|
||||
|
||||
1. **§4.10** — карта подписи: `writeFileAtomic` вместо голого `os.WriteFile`; конверт
|
||||
`seed.SignatureMap{map_version, map_id}` с инлайн-телом прежней схемы; `map_id` = sha256 от
|
||||
отрендеренного тела (идентичность содержимого, не криптодоказательство). Легаси-карта без
|
||||
конверта читается (страховка апгрейда посреди подписи). Карта НЕ накопитель — слияния нет.
|
||||
2. **§4.9** — (а) `filepath.Clean` в резолве абсолютных путей `LoadBook` (Join и так чистит);
|
||||
(б) ключи `mined_delta`/`mined_rejects` СНЯТЫ: retired-key отказ по прецеденту `adult:`
|
||||
(громкое имя лечения, а не голый strict-decode), пути — только конвенцией от каталога и
|
||||
`book_id`; `*Declared` умирает, `decisionFilePresent` упрощается.
|
||||
3. **§4.1–§4.3** — миграция v16: таблица `bank_stop_presented (book_id, surface)` — плоское
|
||||
множество нормализованных поверхностей всех предъявленных кластеров (Src + Aliases); рост —
|
||||
только вширь, обрезки нет. Предикат «есть ли новое» = существует терм ИТОГОВОЙ карты (обе
|
||||
секции, после потолков), чей кластер не пересекается с памятью. Стоп и авто-провод — ДВА
|
||||
решения: стоп = флаг ∧ editWave ∧ новое; авто-провод (авто-банк + пере-сид + экспорт) — на
|
||||
ЛЮБОМ неостановившемся прогоне, включая «флаг поднят, нового нет» (новая явная строка лога).
|
||||
Порядок записи: карта (атомарно, §4.10) → память, в момент СТОПА. Развилки, решённые здесь:
|
||||
отказ записи памяти НЕ валит состоявшийся стоп (громкая строка; повтор — доброкачественный
|
||||
лишний стоп); остановившийся прогон авто-банк НЕ пишет (граница владельца; возобновление без
|
||||
решений догонит на следующем прогоне — названное решение, не случайность); черновая волна без
|
||||
editWave: карта пишется, стопа и памяти нет (доброкачественно, названо).
|
||||
4. **§4.5 + §4.7 + §4.8** — отчёт делится на вердикт (`decisionVerdict`) и исход; исходы —
|
||||
явный тип (projection · refused · noop · stopped · written · write-failed), ОДИН конструктор
|
||||
`finishReport` заполняет исходные поля свитчем; для «записано» пост-состояние — перечитанные
|
||||
файлы. Отчёт получает `written_delta`/`written_rejects` (пофайловая правда §4.7) и честные
|
||||
значения `mode`; версия отчёта → v2 (словарь mode расширился — конверт обязан двинуться).
|
||||
Полоса: пол переформулирован («нет работы на откат; повтор безопасен»), классы объявляют свои
|
||||
инварианты, новый класс `write_incomplete` (exit 15 — ратификация значения на оркестраторе при
|
||||
лендинге) на оба исхода записи; отказ по обоим капам печатает отчёт (сведение контракта к
|
||||
одному носителю). Запись: подготовить ОБА temp-файла (write+sync), потом два rename, потом
|
||||
fsync каталога; отказ каталожного синка — класс `write_incomplete` с оговоркой долговечности.
|
||||
5. **§4.6** — `SignatureState` пере-документируется: `undecided` считает нерешённые поверхности
|
||||
последней карты (информация для экрана подписи) и БОЛЬШЕ НЕ отвечает на вопрос о стопе —
|
||||
ответ требовал бы намайненного набора СЛЕДУЮЩЕГО прогона, которого нет ни у двери, ни у
|
||||
памяти; память дверь не читает (и потому read-only контракт не трогается). `Unreadable`
|
||||
расширяется до «не измерено» (нужно кап-отчётам §4.7). Поле не удаляется.
|
||||
6. **§4.12** — снос наследия СПИСКОМ: шапка mining.go · комментарий у loadMinedRejects ·
|
||||
хвост unsignedEngineSurfaces · сообщение стопа · renderSignatureStop · doc WaveSignatureStop;
|
||||
цепной тест переписывается под новую семантику (премисс-проверки фикстуры сохраняются) +
|
||||
вторая цепь «владелец не решил ничего — стоп гаснет памятью»; пинги чужим зонам с ПОРЯДКОМ
|
||||
(сброс флага платформой умирает только ПОСЛЕ движкового лендинга §4.3) и миграционная нота
|
||||
(пустая память → один доброкачественный стоп; v16 → `tmctl migrate`).
|
||||
7. **§4.11 + §4.4 + §4.13** — посадки и пины по таблице слепых пятен + пин семантики §4.1
|
||||
(краснеет при возврате старой формулы); §4.4 не лечится — пере-замер своей командой (числа
|
||||
промта без первоисточника) и пинг; платных вызовов ноль — фейковый провайдер, харнесс
|
||||
miningstop_join, живая проба на копии стенда.
|
||||
|
||||
## Пофайлово
|
||||
|
||||
- `internal/seed/seed.go|decode.go` — `SignatureMap` + `DecodeSignatureMap` + `SignatureMapID`.
|
||||
- `internal/miner/miner_emit.go` — `DeltaFile` (структура), `DeltaYAML` = рендер её же.
|
||||
- `internal/pipeline/mining.go` — конверт+атомарная запись карты; предикат новизны; разделение
|
||||
стопа и авто-провода; запись памяти; новые строки лога; снос формул старой модели.
|
||||
- `internal/store/migrate.go` + новый `stopmemory.go` — v16, `StopPresentedSurfaces`,
|
||||
`MarkStopPresented`.
|
||||
- `internal/pipeline/bankdecisions.go` — вердикт/исход/конструктор; кап-отчёты; staged-запись;
|
||||
`written_*`; версия отчёта v2; пере-док SignatureState.
|
||||
- `internal/pipeline/refusal.go` + `cmd/tmctl/main.go` — ярусы полосы, `write_incomplete`/15.
|
||||
- `internal/pipeline/artifact.go` — staged-вариант атомарной записи + fsync каталога.
|
||||
- `internal/config/book.go` — Clean; retired-ключи; конвенция путей решений.
|
||||
- `cmd/tmctl/render.go|bankapply.go` — тексты и контракт печати отчёта.
|
||||
- Тесты: `bankchain_test.go` (переписать) · пины §4.11 · пин семантики §4.1 ·
|
||||
`cmd/tmmutate/mutations.json` (+записи на каждую правку §4).
|
||||
|
||||
## Развилки, которые вижу заранее
|
||||
|
||||
- Конверт ломает жанр карты для внешних читателей (`eval/bank_autonomy/parse_common.py`) — пинг,
|
||||
не правка (чужая зона); движковые читатели переведены все (единственный — signatureState).
|
||||
- `seed-lint` карту с конвертом не примет (его предмет — сид и дельта владельца, не карта);
|
||||
названо, не чинится.
|
||||
- Числа §4.4 пере-меряю своей командой до пинга; если картина та же — пинг в прежней формулировке.
|
||||
- **Конверт карты подписи ломает её жанр для внешних читателей** (`eval/bank_autonomy/parse_common.py`
|
||||
парсит `mined-signature.yaml`) — чужая зона, ушло пингом полигону, а не правкой; пинг записан в
|
||||
`docs/archive/PROGRESS-2026-08-backend.md` (искать `parse_common`). Движковые читатели переведены все.
|
||||
- **⚠ Живой остаток: `seed-lint` карту подписи с конвертом не примет** — его предмет сид и дельта
|
||||
владельца, а не карта. Названо и сознательно НЕ чинилось; носителя этого факта, кроме этой строки,
|
||||
нет.
|
||||
- Числа хвоста за потолком, которые заказ цитировал без первоисточника, сессия пере-мерила своей
|
||||
командой (§38) и положила первоисточник в дерево постоянным якорем-пином
|
||||
`internal/miner/emissioncap_test.go`; сам хвост заведён строкой бэклога 223 (D39.158 п.9).
|
||||
|
|
|
|||
|
|
@ -1,30 +1,12 @@
|
|||
# План фикс3 (промт BACKEND_SEAM_FIX3_SESSION_PROMPT.md)
|
||||
# Записка-план фикс3 «входная дверь шва» (6 пунктов)
|
||||
|
||||
> Комплектность: `grep -cE '^### 4\.' docs/BACKEND_SEAM_FIX3_SESSION_PROMPT.md` → **6**.
|
||||
> ⚠ **Записка ОТРАБОТАВШЕЙ сессии, а не задание: не исполнять.** Пак закончен, принят и залендён —
|
||||
> D39.158. Что реально сделано по каждому из шести пунктов, с командами, остатками и проверкой
|
||||
> закрытия — `backend/docs/SEAM_PACK_FINDINGS.md` §46. Промт архивирован:
|
||||
> `docs/archive/prompts/BACKEND_SEAM_FIX3_SESSION_PROMPT_2026-08-27.md`.
|
||||
|
||||
Порядок — сначала два пина (воспроизведение мутации ДО пина, правило «сначала посадка»), потом снос,
|
||||
потом тексты, потом §4.6.
|
||||
|
||||
1. **§4.1** — воспроизвести мутацию приёмки (отказ записи карты → WarnContext) и убедиться в зелёной
|
||||
батарее; пин приёмом приёмки: путь карты занят непустым каталогом → прогон обязан вернуть ошибку,
|
||||
`StopPresentedSurfaces` книги обязан остаться пуст. Запись каталога FX23.
|
||||
2. **§4.2** — воспроизвести утверждение панели (docsReRead → docsFromResult на исходе write_incomplete
|
||||
→ существующие пины зелёные); пин: карта с нерешённой поверхностью + документ, решающий её + отказ
|
||||
записи (не легло ничего) → `signature.undecided` обязан быть 1 (диск), не 0 (намерение). FX24.
|
||||
3. **§4.5** — снос машинной таблицы `.bank-stop.json`: писатель, дисциплина отказа, пути, поле
|
||||
`TableJSONPath`, строка рендера, json-теги DTO, тесты таблицы. `.bank-stop.txt` не трогаю.
|
||||
Проверка «читателя нет» — свой греп по всем зонам до сноса.
|
||||
4. **§4.4** — зачистка грепом: формы `re-fire`/`re-fires`/`refire` + `stop clears`/`clears the stop` +
|
||||
`never.*stop` рядом с decline/reject + русские следы; правильный текст — из D39.144 (отказ
|
||||
исключает терм из ЭМИССИИ: он не возвращается в карту и в авто-банк; про стоп он не говорит ничего —
|
||||
стоп это вопрос памяти).
|
||||
5. **§4.3** — `runner.go:206` и `panic_exit_test.go:78` → двухъярусная формулировка.
|
||||
6. **§4.6** — проверить утверждение консилиума по `bankexport.go`; если подтверждается — аддитивные
|
||||
поля идентичности границы (run id + метка границы, обе уже есть у прогона, детерминизм не задет);
|
||||
версию конверта не двигать (добавление аддитивно).
|
||||
|
||||
Развилки: у §4.5 возможен читатель, которого не нашла приёмка — ищу сам до сноса, нахожу → пинг, не
|
||||
молчаливое сохранение. У §4.6 законен отказ с аргументом — решу после чтения фактуры.
|
||||
|
||||
Финал: батарея + стенд-батарея + tmmutate (60 записей) на копии + FINDINGS §46 + итог в журнал +
|
||||
проверка закрытия отдельным не-чинившим агентом.
|
||||
Порядок, выбранный до кода: два пина (мутация воспроизводится ДО пина — правило «сначала посадка,
|
||||
потом пин») → снос машинной таблицы `.bank-stop.json` → зачистка отменённой формулы стопа в текстах →
|
||||
якорь свежести банк-экспорта. Обе названные развилки решены исполнением и описаны в §46: читателя
|
||||
сносимой таблицы сессия искала своим грепом по всем зонам ДО сноса, у §4.6 отказ с аргументом был
|
||||
законен и не понадобился.
|
||||
|
|
|
|||
|
|
@ -1,82 +1,15 @@
|
|||
# План дофикса «входная дверь шва» (по промту `docs/BACKEND_SEAM_FIX_SESSION_PROMPT.md`)
|
||||
# Записка-план дофикса «входная дверь шва» (16 пунктов §4)
|
||||
|
||||
Бэкенд-сессия 25.08.2026, продолжает незакоммиченное дерево пака. Заказ — 16 пунктов §4
|
||||
(`grep -cE '^### 4\.'` → 16). Записка обязана быть комплектной механически, поэтому таблица ниже
|
||||
перечисляет ВСЕ шестнадцать, включая те, которые заканчиваются аргументированным отказом.
|
||||
> ⚠ **Записка ОТРАБОТАВШЕЙ сессии (25.08.2026), а не задание: не исполнять.** Дофикс закончен, принят и
|
||||
> залендён — D39.158. Что реально сделано по каждому из шестнадцати пунктов, с командами и остатками —
|
||||
> `backend/docs/SEAM_PACK_FINDINGS.md` §26 (попунктный чек), §15 (замер и механика корня формата
|
||||
> `yaml.v3` — шире и точнее этой записки), §24 (что НЕ удалось), §23 (пинги). Промт архивирован:
|
||||
> `docs/archive/prompts/BACKEND_SEAM_FIX_SESSION_PROMPT_2026-08-27.md`.
|
||||
|
||||
## Базовая точка (снята ДО правок)
|
||||
## Чего этот дофикс НЕ делал — и это осталось верным
|
||||
|
||||
`make battery` на нетронутом дереве пака: `EXIT=2`, красен ровно
|
||||
`TestKillMinus9LosesAtMostOneCall` — один из двух названных промтом пред-существующих `-race`-флейков
|
||||
(`internal/store`). То есть флейк воспроизвёлся на дереве, к которому я ещё не прикасался; это моя
|
||||
собственная атрибуция, а не наследованная.
|
||||
|
||||
## Что уже замерено до кода (§4.1, корень)
|
||||
|
||||
`gopkg.in/yaml.v3 v3.0.1`, проба вне рабочего дерева, матрица «значение → рендер → разбор» на обоих
|
||||
документах. Итог шире, чем говорит промт, и шире, чем говорила записка прошлой сессии:
|
||||
|
||||
| значение поля | что рендерится | round-trip |
|
||||
|---|---|---|
|
||||
| `"\nтекст"` | `note: \|4-` + строка | **не разбирается** (`did not find expected key`) |
|
||||
| `"\n\nтекст"` | `\|4-` + пустая строка | **не разбирается** |
|
||||
| `"\n\tx"` | `\|4-` + таб | **не разбирается** |
|
||||
| `"\n"` | `\|4+` | разбирается, но **значение `""`** — тихая потеря |
|
||||
| `"\n x"` | `\|4-` + 10 пробелов | разбирается, но **значение `"x"`** — тихая потеря |
|
||||
| `"текст\n"`, `"a\nb"`, `" x"`, `"\tx"`, `"\r\nx"` | скаляр/блок | ок |
|
||||
|
||||
Два вывода, оба несущие:
|
||||
|
||||
1. **Клейм промта «бьёт по ЛЮБОМУ свободному текстовому полю» ВЕРЕН**, а поправка записки прошлой
|
||||
сессии («`dst` и `sense` не ломаются») — НЕТ: ломается любое строковое поле обоих документов
|
||||
(проверено на `src`/`dst`/`sense`/`note` и на `rejects[].note`). Триггер — ведущий `\n`, а не поле.
|
||||
2. **«Документ разбирается» — недостаточный инвариант.** Две формы разбираются и МЕНЯЮТ значение.
|
||||
Заказанная §4.1 проверка `render → parse` их пропустит: дверь отчитается `applied`, файл загрузится,
|
||||
а заметка владельца будет другой. Инвариант обязан быть «прочиталось И совпало».
|
||||
|
||||
Механика (тоже замерена): дефект — рассогласование индикатора отступа блочного скаляра с реальным
|
||||
отступом родителя внутри элемента последовательности; на глубине 1 (`{note: "\nx"}` без `- `) тот же
|
||||
вход рендерится и читается корректно, а `SetIndent(2)` случайно попадает в согласие. **Путь «починить
|
||||
рендер стилями `yaml.Node`» закрыт:** `(*yaml.Node).Encode` внутри сам гоняет marshal→unmarshal и
|
||||
падает на том же входе — узел построить нельзя.
|
||||
|
||||
## Порядок работ
|
||||
|
||||
Волнами, снизу вверх: формат → чистая семантика → конфиг/CLI → обвязка → пины. Батарея после каждой
|
||||
волны, `make battery-stand` в конце.
|
||||
|
||||
| № | что делаю | где |
|
||||
|---|---|---|
|
||||
| **4.1** | нормализация текстовых полей документа (`TrimSpace`, ОДНО правило на все поля обеих схем) + рендер, ДОКАЗЫВАЮЩИЙ себя: `parse(render(A))` обязан совпасть с нормализованным `A`, иначе ошибка. Проверка распространяется на ОБА документа; байты, которые дверь проверила, она же и пишет (рендер один, не два). Фаззер пути ДВЕРИ: произвольные строки полей `Decision` → `ApplyDecisions` → рендер → разбор | `seed`, `membank` |
|
||||
| **4.2** | пред-существующая проблема опознаётся по СУБЪЕКТУ: многосубъектный вердикт загружаемости раскладывается по термам до сравнения `до/после` | `membank` |
|
||||
| **4.3** | `config.LoadBook` отказывает при совпадении путей. Шире буквы заказа на одну строку: попарно различны должны быть четыре пути, которые движок пишет или читает как РАЗНЫЕ форматы (`project_db`, `glossary_seed`, `mined_delta`, `mined_rejects`) — `project_db == mined_delta` сегодня означало бы YAML поверх sqlite. Проверю на всех `book.yaml` репозитория и стенда, что живых нарушителей нет | `config` |
|
||||
| **4.4** | оба гарда — на ПРИСУТСТВИЕ флага через `fs.Visit` (прецедент `ceilingGiven` в том же файле) | `cmd/tmctl` |
|
||||
| **4.5** | кап на размер документа решений + строка отказа полосой. Число выбираю после СВОЕГО замера памяти (методика будет названа); хвост про exit 2 при OOM — пингом | `pipeline` |
|
||||
| **4.6** | конверт путей на поверхности, которую потребитель читает (`manifest --json`). Компромисс назову вслух: манифест — про дерево глав, путь артефакта там гость | `pipeline` |
|
||||
| **4.7** | правило алиасов судит НАБОР: одобряемые тем же вызовом термы участвуют в проверке `aliasOwner` | `membank` |
|
||||
| **4.8** | перевёрнутое окно глав (`until < since`, оба ненулевые) — отказ | `membank` |
|
||||
| **4.9** | **вероятно отклоню как предсказание и заменю на факт.** Дверь не знает, сколько поверхностей осталось за капом реверс-секции — это знает майнер на следующем проходе. Кандидат: отчёт называет, что решил ЭТОТ вызов, и не читается как «стоп погас». Решу замером, видит ли дверь остаток вообще | `pipeline` |
|
||||
| **4.10** | обработчик `SIGTERM`: бросить работу, отпустить лок, не записать ничего. **Сначала замерю длительность вызова ПОСЛЕ капа §4.5** — если максимум по капу это десятки миллисекунд, скажу это аргументом | `pipeline`/`cmd` |
|
||||
| **4.11** | десять посадок (строка (д) — три), пин на каждую, каждый краснеет на своей мутации. Харнесс мутаций пишу заново с отпечатком целей до/после; кладу его в репозиторий — приёмка сажает мутации тоже, а инструмент каждый раз пишется с нуля | все |
|
||||
| **4.12** | тест цепи на фейковом провайдере (`miningstop_join_test.go`-харнесс): стоп → `bank-apply` → резюм → стоп погас, редакторская волна пошла. Плюс явная фиксация, что карта подписи после погасшего стопа остаётся на диске | `pipeline` |
|
||||
| **4.13** | восемь мелочей: по каждой решение и довод, чиню или отклоняю — списком в отчёте, без «кажется» | разные |
|
||||
| **4.14** | довод отказа `--keys-file` покрывает всех, кого ветка отвергает (`redrive` — платный, `backup`/`migrate` — деплой-шаги). Развилку про канал ключей `redrive` НЕ решаю | `cmd/tmctl` |
|
||||
| **4.15** | три существующих пина: вердикт `Preexisting` исполнить всеми четырьмя проверками · четвёртый оракул фаззера снять с тавтологии · `TestDecisionByBankID` сверять с НЕЗАВИСИМО посчитанным id | тесты |
|
||||
| **4.16** | платных вызовов ноль. Рантайм по платному пути остаётся PLAUSIBLE | — |
|
||||
|
||||
## Развилки, которые понесу владельцу/оркестратору (§11)
|
||||
|
||||
1. **§4.1 шире заказа.** Заказанный round-trip `render → parse` не ловит две тихие потери значения;
|
||||
делаю строже («прочиталось И совпало») и говорю об этом прямо, потому что это меняет ответ двери
|
||||
на входы, которые заказ считал безопасными.
|
||||
2. **§4.3 шире буквы** на одну проверку — см. таблицу.
|
||||
3. **§4.9** — скорее всего отказ от предсказания в пользу факта.
|
||||
4. **§4.10** — возможен ответ «механизм без носителя после §4.5»; решит замер, не рассуждение.
|
||||
5. **§4.6** — сделаю, компромисс назову.
|
||||
|
||||
## Чего НЕ делаю
|
||||
|
||||
Пинги приложения «дофикс НЕ исполняет» (exit 2 при OOM, `readEngine` платформы, канал ключей
|
||||
`redrive`, `rubyToCandidates`, слепота `TestDispatchCommandsCoversTheSwitch` к константам, схема сида
|
||||
без `omitempty`, лок на проекции, карта подписи после стопа) — не «допиливаю попутно». Механизм против
|
||||
капа реверс-секции не строю. Пере-именование банк-экспорта не трогаю. Словарь решений не расширяю.
|
||||
Пинги, которые дофикс сознательно НЕ исполнял: `exit 2` при OOM · `readEngine` платформы · канал ключей
|
||||
`redrive` · `rubyToCandidates` · слепота `TestDispatchCommandsCoversTheSwitch` к константам · схема сида
|
||||
без `omitempty` · лок на проекции · карта подписи после стопа. Тела и диспозиции — FINDINGS §10 и §23.
|
||||
Механизм против капа реверс-секции не строился, пере-именование банк-экспорта не трогалось, словарь
|
||||
решений не расширялся.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,70 +1,22 @@
|
|||
# Записка-план: бэкенд-пак «входная дверь шва» (движковая половина D39.156)
|
||||
|
||||
Сессия бэкенда, 24.08.2026. Промт — `docs/BACKEND_SEAM_PACK_SESSION_PROMPT.md`.
|
||||
Доказательная база и посадки — `backend/docs/SEAM_PACK_FINDINGS.md` (пишется по ходу).
|
||||
> ⚠ **Записка ОТРАБОТАВШЕЙ сессии (24.08.2026), а не задание: не исполнять.** Пак закончен, принят и
|
||||
> залендён — D39.158. Что реально построено, чем доказано и что осталось — доказательная база
|
||||
> `backend/docs/SEAM_PACK_FINDINGS.md` (состав §0, попунктный чек заказа §12, пинги §10). Промт
|
||||
> архивирован: `docs/archive/prompts/BACKEND_SEAM_PACK_SESSION_PROMPT_2026-08-27.md`.
|
||||
|
||||
## 0. Точка отсчёта, снятая ИСПОЛНЕНИЕМ (до правок)
|
||||
## Развилки, которые сессия решала своим доводом
|
||||
|
||||
| факт | команда |
|
||||
|---|---|
|
||||
| `go build ./...` · `go vet ./...` · `go test ./... -count=1` — зелены | из `backend/` |
|
||||
| стенд-батарея с переопределениями: красен ровно `TestMinerFullBookParity`, причина — отсутствующий `eval/exp16/data/jieba_dict_general_zh.txt` | `TM_MINER_PARITY=1 TM_CHECKER_LABELS=1 TM_CHECKER_LABELS_DIR=<repo>/books/gu-zhenren/labels TM_MINER_PARITY_RECORDS=<repo>/books/gu-zhenren/rerun/records.json TM_MINER_PARITY_SEED=<repo>/books/gu-zhenren/guzhenren-seed-v2.yaml go test ./... -count=1` |
|
||||
| рабочее дерево `backend/` чистое; незакоммиченная чужая работа — только в `eval/` | `git status --porcelain` |
|
||||
**(а) Имена файлов решений — каталог книги, а не сайдкар при базе.** Все банк-сайдкары движка висят на
|
||||
`project_db` (`.bank.json`, `.auto-bank.yaml`, `.mined-signature.yaml`), но `project_db` может указывать
|
||||
КУДА УГОДНО (в т.ч. за пределы каталога книги), а решения пользователя — это его данные, они обязаны
|
||||
ехать с книгой в бэкапе и экспорте каталога. Отсюда `<dir книги>/<book_id>.mined-delta.yaml` и
|
||||
`<book_id>.mined-rejects.yaml`: префикс `book_id` повторяет механизм `<book_id>.db` и не даёт двум
|
||||
книгам в одном каталоге столкнуться. ⚠ Объявляемые ключи `mined_delta`/`mined_rejects`, которые эта
|
||||
записка ещё предполагала, СНЯТЫ фикс2 — путь стал чистой функцией каталога и `book_id` (D39.158 п.5);
|
||||
довод конвенции пережил снятие ключей, форма — нет.
|
||||
|
||||
## 1. Комплектность против §4 промта (сверка МЕХАНИЧЕСКАЯ)
|
||||
|
||||
| § | заказ | форма, которую я выбрал | где |
|
||||
|---|---|---|---|
|
||||
| 4.1 | дефолты пустых ключей `mined_delta`/`mined_rejects` по конвенции каталога книги | `<dir книги>/<book_id>.mined-delta.yaml` и `<book_id>.mined-rejects.yaml`; дефолт ТОЛЬКО на пустом ключе; отсутствующий дефолтный файл = «решений нет» | `internal/config/book.go`, `internal/pipeline/mining.go` |
|
||||
| 4.2 | $0-глагол приёма правок банка | `tmctl bank-apply --config <book.yaml> --decisions <decisions.json> [--dry-run]` | `internal/membank/decisions.go` (чистая логика), `internal/pipeline/bankdecisions.go` (обвязка), `cmd/tmctl/bankapply.go` |
|
||||
| 4.3 | путь к файлу ключей аргументом | `--keys-file <path>` ТОЛЬКО у `translate`; грузится ПЕРВЫМ; названный и нечитаемый = отказ конфигом (10) | `cmd/tmctl/invocation.go`, `cmd/tmctl/dotenv.go`, `cmd/tmctl/main.go` |
|
||||
| 4.4 | строгость загрузчика сида + тест на unknown-key | strict-декодер схемы в `internal/seed` (`seed.DecodeFile`), им же читается reject-файл | `internal/seed/decode.go`, `internal/membank/memseed.go`, `internal/pipeline/mining.go` |
|
||||
| 4.5 | путь артефакта и версия документа в `status --json` | `status_version` + аддитивный объект `artifacts{project_db,bank_export}` (абсолютные пути) | `internal/pipeline/status.go` |
|
||||
| 4.6 | дефолт стендового корпуса в трёх тест-хелперах | маркерный резолв корня репозитория (`repoFile`), корпус — `<repo>/books` | `internal/miner/miner_parity_test.go`, `internal/checks/labelharness_test.go`, `internal/membank/labelharness_test.go` |
|
||||
| 4.7 | платных вызовов ноль | глагол $0 по построению; `--keys-file` — юнит-тесты + фейковые ключи | — |
|
||||
|
||||
## 2. Порядок работ
|
||||
|
||||
1. §4.6 (дешёвая, независимая) → стенд-батарея зеленеет без переопределений.
|
||||
2. §4.4 строгость схемы — она нужна ДО глагола: глагол читает и пишет те же файлы, и нестрогий
|
||||
читатель обесценил бы строгого писателя.
|
||||
3. §4.1 дефолты путей — без них глаголу некуда писать на книге, которая ключей не объявляла.
|
||||
4. §4.2 глагол (основной кусок).
|
||||
5. §4.3 `--keys-file`.
|
||||
6. §4.5 версия и пути артефактов в `status --json`.
|
||||
7. Адверсариальные посадки, живая проба на копии стендовой книги, отчёт.
|
||||
|
||||
## 3. Развилки, которые я вижу, и как решаю
|
||||
|
||||
**(а) Имена дефолтных файлов — каталог книги или сайдкар при базе?**
|
||||
Все банк-сайдкары движка висят на `project_db` (`.bank.json`, `.auto-bank.yaml`, `.mined-signature.yaml`).
|
||||
Беру всё-таки КАТАЛОГ КНИГИ с префиксом `book_id`, ровно как `project_db` по умолчанию:
|
||||
`project_db` может указывать КУДА УГОДНО (в т.ч. за пределы каталога книги), а решения пользователя —
|
||||
это его данные, они обязаны ехать с книгой в бэкапе и экспорте каталога. Префикс `book_id` повторяет
|
||||
механизм `<book_id>.db` и не даёт двум книгам в одном каталоге столкнуться.
|
||||
|
||||
**(б) Форма проекции до мутации.** `--dry-run`, прецедент — `redrive --dry-run` и строка 124(в)
|
||||
(`resnapshot --dry-run` поименован там дословно). Проекция получается БЕЗ мутации: с флагом не
|
||||
пишется ни один байт.
|
||||
|
||||
**(в) Код выхода для отвергнутого набора решений.** Занятый лок — ровно 12 (заказано). Для
|
||||
отвергнутых решений НЕ завожу новый номер полосы: беру 10 (`config_invalid`). Довод по оси, которая
|
||||
у D39.134 несущая, — КТО ДЕЙСТВУЕТ: при 12 действует время («подожди и повтори»), при 10 действует
|
||||
человек. Набор решений, конфликтующий с подписанной строкой сида, чинит человек, а не время.
|
||||
Отчёт при этом печатается в stdout ВСЕГДА и называет каждый отказ поимённо (прецедент: `status --json`
|
||||
печатает отчёт и выходит 2).
|
||||
|
||||
**(г) Словарь входа глагола.** Ровно словарь УЖЕ публикуемой поверхности банк-экспорта
|
||||
**(б) Словарь входа глагола.** Ровно словарь УЖЕ публикуемой поверхности банк-экспорта
|
||||
(`id`/`src`/`dst`/`kind`/`sense`/`since_chapter`/`until_chapter`/`aliases`) плюс `note`. Поля, которого
|
||||
движок не публикует, во входе нет — в частности `gender` (строка 210: ось мертва в производителях);
|
||||
строить «на вырост» запрещено §4.3.
|
||||
|
||||
**(д) Канонизация файла.** Глагол — единственный писатель своей схемы, поэтому при изменении файл
|
||||
пере-рендерится целиком из разобранной схемы (комментарии оператора не переживают первую правку).
|
||||
Это ВИДНО до мутации: проекция несёт `canonical_rewrite`. Порядок термов сохраняется (замена — на
|
||||
месте, добавление — в хвост), чтобы правка не выглядела как переписывание всего файла.
|
||||
|
||||
**(е) Что я НЕ делаю и почему.** Не проектирую «глубину до черновика» (§4.2, прямое слово владельца):
|
||||
правка едет через `mined_delta` до РЕДАКТОРСКОЙ волны, и ответ глагола говорит это явным полем
|
||||
`depth: edit_wave`. Не трогаю `redrive` флагом ключей (промт: «флаг только у `translate`») — наблюдение
|
||||
о том, что `redrive` тоже платный путь, уходит ПИНГОМ, а не тихой правкой.
|
||||
движок не публикует, во входе нет — в частности `gender`: ось мертва в производителях, а строить
|
||||
«на вырост» запрещено заказом.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue