Correct the architecture docs the audit caught: the emitter exit contract, the money path's missing operator verdict and the target-architecture banners

This commit is contained in:
Claude (backend session) 2026-08-22 18:32:33 +03:00
parent 3c6e72a864
commit 0e31a8b1cc
3 changed files with 18 additions and 7 deletions

View file

@ -7,7 +7,7 @@
>
> Это карта «куда и почему», а не пошаговая спека. Спеки — в хендофф-промтах сессий; контракт — в D-логе.
> **СТАТУС СТРОЙКИ (освежён 20.08 оркестратором №18: **пак P7 платформы ПРИНЯТ и ЗАЛЕНДЕН** — читающая поверхность построена целиком (главы · юниты · замечания · проекция банка · SSE · модель ошибок · условные чтения · идемпотентность), D39.153; **канон контракта — 0.4.0**, ратифицирован D39.152; пак движка «честные числа и статусы» принят с фикс-листом, D39.149. Предыдущий срез — 16.08 оркестратором №17: контракт-ревью ПРИНЯТО (research/28, D39.138), ломающий батч 0.3.0 ИСПОЛНЕН и принят с дофиксом (D39.142145: конвейер снят с провода, машинная модель ошибок, /capabilities, поток на книгу, подпись банка = один ОК D39.144; жанр из продукта ВЫКИНУТ — строка 184); P7 платформы ЗАПУЩЕН по финальному канону. Ранее 15.08: эмиттер шва ПОСТРОЕН И ПРИНЯТ — `events.jsonl` StreamVersion 1.1, exit 4/5 + полоса отказов 1019 (D39.131); платформа P6 + дофикс приняты — потребительская половина шва, интейк формы Б, дев-стенд, PD-113/PD-196 закрыты (D39.132); `tmctl migrate` принят — exit 13 финализирован, деадлок деплоя v15 разорван (D39.134); фронт S4 принят — путь «файл → загрузка → запуск → прогресс» в мире моков, контракт **0.2.3** в каноне (D39.135). Ранее 14.08 №16: платформа достроена до интейка книг P5 — `POST /books` с сентинелом хранилища, стоп/резюм с намерением, Prometheus, Go-floor 1.26.6 (D39.130); фронт — S3.5S3.7 приняты (оболочка · слой данных · i18n; D39.127/129). Ранее 09.08, пост-D39.125: шов движок↔платформа ратифицирован — транзиентный systemd-юнит на прогон + `events.jsonl`-outbox в каталоге книги, платформа НЕ родитель (D39.106); платформа достроена до раннера P4 (D39.109/114/123 — River-очередь, холд-до-спавна, реконсилятор; дефекты — `platform/docs/DEFECT_REGISTER.md`); фронт — слой данных S3, контракт 0.2.0→0.2.1 (D39.115/123); движок отдал блокеры контракта — `tm-manifest-v2`, `unit.id` с тегом разреза, пофазные счётчики на главу, `--ceiling-usd` (D39.122); слой 4 добит фикс-паком банка — семьи термов со-батчатся юнитами, bankdata-плоскость (D39.118). Ранее 04.08, пост-D39.105: слои 4/5 добраны паками банка/чекеров D39.69/78/82; репо на стандартах — `make battery`, tmvet/archguard, D39.96/97; контракт API v0 = `14-api-contract/` (D39.99), платформа = зона `platform/`, открыта D39.100. Баннер — не переписывание, тело ниже = замысел арх-ресета 13.07).** Карта «слой → статус → пак/D»:
> **СТАТУС СТРОЙКИ (освежён 22.08 оркестратором №18: **пак платформы P8-FIX ПРИНЯТ и ЗАЛЕНДЕН** — голодание свипа `PD-169` закрыто четырьмя механизмами (фазы прохода · отсрочка с бэкоффом · порог `StalledAfter` с гейджем и CLI · терминальный вердикт оператора `run abandon`), оба бюджета стали операторскими ручками, снят пер-термный write-путь банка по D39.144 — открытой осталась контрактная половина `PD-370` (строка 206). Ранее 20.08: **пак P7 платформы ПРИНЯТ и ЗАЛЕНДЕН** — читающая поверхность построена целиком (главы · юниты · замечания · проекция банка · SSE · модель ошибок · условные чтения · идемпотентность), D39.153; **канон контракта — 0.4.0**, ратифицирован D39.152; пак движка «честные числа и статусы» принят с фикс-листом, D39.149. Предыдущий срез — 16.08 оркестратором №17: контракт-ревью ПРИНЯТО (research/28, D39.138), ломающий батч 0.3.0 ИСПОЛНЕН и принят с дофиксом (D39.142145: конвейер снят с провода, машинная модель ошибок, /capabilities, поток на книгу, подпись банка = один ОК D39.144; жанр из продукта ВЫКИНУТ — строка 184); P7 платформы ЗАПУЩЕН по финальному канону. Ранее 15.08: эмиттер шва ПОСТРОЕН И ПРИНЯТ — `events.jsonl` StreamVersion 1.1, exit 4/5 + полоса отказов 1019 (D39.131); платформа P6 + дофикс приняты — потребительская половина шва, интейк формы Б, дев-стенд, PD-113/PD-196 закрыты (D39.132); `tmctl migrate` принят — exit 13 финализирован, деадлок деплоя v15 разорван (D39.134); фронт S4 принят — путь «файл → загрузка → запуск → прогресс» в мире моков, контракт **0.2.3** в каноне (D39.135). Ранее 14.08 №16: платформа достроена до интейка книг P5 — `POST /books` с сентинелом хранилища, стоп/резюм с намерением, Prometheus, Go-floor 1.26.6 (D39.130); фронт — S3.5S3.7 приняты (оболочка · слой данных · i18n; D39.127/129). Ранее 09.08, пост-D39.125: шов движок↔платформа ратифицирован — транзиентный systemd-юнит на прогон + `events.jsonl`-outbox в каталоге книги, платформа НЕ родитель (D39.106); платформа достроена до раннера P4 (D39.109/114/123 — River-очередь, холд-до-спавна, реконсилятор; дефекты — `platform/docs/DEFECT_REGISTER.md`); фронт — слой данных S3, контракт 0.2.0→0.2.1 (D39.115/123); движок отдал блокеры контракта — `tm-manifest-v2`, `unit.id` с тегом разреза, пофазные счётчики на главу, `--ceiling-usd` (D39.122); слой 4 добит фикс-паком банка — семьи термов со-батчатся юнитами, bankdata-плоскость (D39.118). Ранее 04.08, пост-D39.105: слои 4/5 добраны паками банка/чекеров D39.69/78/82; репо на стандартах — `make battery`, tmvet/archguard, D39.96/97; контракт API v0 = `14-api-contract/` (D39.99), платформа = зона `platform/`, открыта D39.100. Баннер — не переписывание, тело ниже = замысел арх-ресета 13.07).** Карта «слой → статус → пак/D»:
> | Слой | Статус | Пак / D |
> |---|---|---|
> | 1 Сегментация | ✅ ПОСТРОЕН: бюджет в выходных токенах снапшот-folded (`chunk.SegBudget`), edit-единицы декаплены; когезия/carryover — НЕ строится (D39.7/8: эффекты под floor 0.126; кнобы `STMDepth`/`OverlapTokens` УДАЛЕНЫ, WS2 §2а), граница `logical` — не рычаг (exp15), greedy остался | пак-11 (D39.13 WS2 · D39.17 волны · D39.18 c-lite) |
@ -87,6 +87,13 @@ snapshot-дисциплина, эталонные сеамы `config→stage-lis
## 2. Целевая архитектура — 7 слоёв с чистыми сеамами
> ⚠ **ЧИТАТЬ КАК ЗАМЫСЕЛ 13.07, А НЕ КАК ДЕЙСТВУЮЩЕЕ ПРЕДПИСАНИЕ** (баннер дописан 22.08 аудитом
> доков: у §1 и §4 такие оговорки были, у §2 не было — и его читали как норму). Что этот раздел
> предписывает, а стройка с тех пор отменила, видно из ШАПКИ-ТАБЛИЦЫ ЭТОГО ЖЕ ФАЙЛА: например
> меж-единичная когезия («оживить `STMDepth`/`OverlapTokens`») — эти кнобы УДАЛЕНЫ, эффекты замерены
> под флором и когезия НЕ строится (D39.7/D39.8, слой 1). **При расхождении раздела с шапкой первична
> шапка, при расхождении шапки с D-логом — D-лог.**
Вместо 65 заплаток — слои, каждый первоклассный, независимо конфигурируемый и снапшот-folded. Ровно они закрывают
5 концернов.

View file

@ -24,9 +24,11 @@
4. **Холд прироста ДО спавна.** `holdTx` пишет отрицательную строку `('hold', -amount)` и тем же знаком двигает кэш баланса (`credits.go:163-206,375-385`); нехватка — `ErrInsufficientCredit`. Холд + прогон + попытка + очередь — одна транзакция (`pgstore/runs.go:104` StartRun, `:338` рестарт; форма D39.123 п.2д).
5. **Аргумент движку: `bookCap = committed + прирост×ставка`, БЕЗ reserved — PD-158, дословно из кода: `return m.committed + increment`** (`platform/internal/runs/spawn.go:195-196`). Обе фигуры читаются ОДНИМ вызовом `status --json` перед стартом (`bookMeter`, `spawn.go:206-223`); отсутствие любой из них = отказ спавна («absent is not zero», PD-40). Почему без reserved: write-open движка занулит leftover до первой резервации, значит цифра из read-only status к моменту сравнения уже мертва; ратифицированная ранее формула с reserved переплачивала запасом ровно на leftover сверх холда — исполнено обеими формулами против гейта (D39.123 п.2б, поправка к D39.122(в)). Аргумент ≠ холд: он больше холда на committed (глоссарий `:50`). Фактически ушедшее значение хранится в `run_attempts.ceiling_arg_micro_usd` (PD-144, миграция 00011); потолок уходит argv-шаблоном `{{usd}}` (`config.go` `CeilingArg`, `spawn.go:132-150`); строка 145 закрыта D39.122.
6. **Baseline и списание.** `baseline = committed` книги на старте попытки (`spawn.go:74`); списание попытки = разница счётчика с baseline; счётчик ниже baseline = подменённая БД, сеттлится в ноль с WARN — сами цифры в лог не идут (D39.84; `reconcile.go:308-316`).
7. **Settle по фигуре движка.** `reconcile.settle` (`platform/internal/runs/reconcile.go:277+`) читает committed из status; `credits.Settle` одной транзакцией закрывает резервацию, возвращает холд и списывает spent; **spent > холда — капится холдом** с явной пометкой «capped at the hold; the engine reported …» (`credits.go:214-234`), перерасход движка счётом не абсорбируется.
8. **SpendBound (PD-159).** Отложенный settle читает пожизненный счётчик КНИГИ и без границы оплатил бы работу прогона-преемника (замер: $2.10 за прогон ценой $0.10, и преемник платил снова). Граница = наименьший baseline попыток той же книги, стартовавших ПОЗЖЕ: `committed = min(счётчик сейчас, SpendBound)` (`reconcile.go:293-307`; `pgstore/runs.go:268`).
9. **Открытое — эскроу/intent (строка 136, `docs/PROGRESS.md:85`):** write-ahead intent + состояние `uncertain`-эскроу + `closing`; холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка. Стройка по research/25, «скоро». До эмиттера (строка 103) платформа между спавном и settle слепа — защита держится холдом и потолком движка (§1).
7. ⚠ **Терминальный вердикт ОПЕРАТОРА — путь холда мимо settle (добавлено 22.08, P8-FIX/D39.154).** Прогон, чей движок не ответит уже никогда, закрывает человек: `tmplatformctl run abandon --run <id> --reason <текст> [--release-hold]`. Команда ОТКАЗЫВАЕТ, если попытка ещё называет юнит или несёт базовую линию траты — над живым движком прогон не закрывают. Холд возвращается ЦЕЛИКОМ в обоих случаях (к abandon допускается только попытка, не дошедшая до движка, значит она ничего не потратила), а флаг решает лишь КОГДА — сразу или на ближайшем свипе. До этого пака такого пути не было вовсе: холд чужого аккаунта висел, пока кто-нибудь не залезет в БД руками.
8. **Settle по фигуре движка.** `reconcile.settle` (`platform/internal/runs/reconcile.go:277+`) читает committed из status; `credits.Settle` одной транзакцией закрывает резервацию, возвращает холд и списывает spent; **spent > холда — капится холдом** с явной пометкой «capped at the hold; the engine reported …» (`credits.go:214-234`), перерасход движка счётом не абсорбируется.
9. **SpendBound (PD-159).** Отложенный settle читает пожизненный счётчик КНИГИ и без границы оплатил бы работу прогона-преемника (замер: $2.10 за прогон ценой $0.10, и преемник платил снова). Граница = наименьший baseline попыток той же книги, стартовавших ПОЗЖЕ: `committed = min(счётчик сейчас, SpendBound)` (`reconcile.go:293-307`; `pgstore/runs.go:268`).
10. **Открытое — эскроу/intent (строка 136, `docs/PROGRESS.md:85`):** write-ahead intent + состояние `uncertain`-эскроу + `closing`; холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка. Стройка по research/25, «скоро». До эмиттера (строка 103) платформа между спавном и settle слепа — защита держится холдом и потолком движка (§1).
## 4. Фронт (зона `frontend/`)
@ -36,12 +38,12 @@
| Дыра | Носитель |
|---|---|
| ~~PD-113 (major)~~ **ЗАКРЫТ P6/D39.132** (испр. оркестратором 15.08): обе половины построены — событие `ceiling{scope}` + exit 4 (движок, D39.131) и потребитель (платформа, П-15): потолочный стоп = `paused` двумя независимыми каналами, причина пишется одним оператором со статусом и перечитывается после drain; открытых major в регистре платформы 0 | `platform/docs/DEFECT_REGISTER.md` (эра P6), D39.132 |
| ~~PD-113 (major)~~ **ЗАКРЫТ P6/D39.132** (испр. оркестратором 15.08): обе половины построены — событие `ceiling{scope}` + exit 4 (движок, D39.131) и потребитель (платформа, П-15): потолочный стоп = `paused` двумя независимыми каналами, причина пишется одним оператором со статусом и перечитывается после drain. ⚠ **Хвост «открытых major в регистре платформы 0» СНЯТ 22.08 — он протух:** открытый мажор есть, это `PD-370` (канон объявляет снятую ручку банка), и держать счёт чужого регистра здесь — лишний носитель, который протухает молча; счёт печатает `python3 docs/scripts/counts.py` | `platform/docs/DEFECT_REGISTER.md` (эра P6), D39.132 |
| ~~Строка 165~~ **ЗАКРЫТА D39.131** (испр. оркестратором 14.08): exit 4 = потолок · 5 = graceful stop · 1019 полоса отказов; потребительская половина построена P6 (D39.132) — шов закрыт с обеих сторон; ⚠ exit 13 (`schema_mismatch`) едет паком migrate, ратификация направления — D39.132 | D39.131, D39.132 |
| **Строка 166** — движковая поверхность оценки $/глава; $0.03 — временная мера беты (П-10 зоны) | `docs/PROGRESS.md:114` |
| **PD-104** — фри-тир: док↔код закрыто, продуктовая половина (ноль на бете · агрегатный потолок · счётчик) на владельце | `DEFECT_REGISTER.md:115`, D39.110 п.3 |
| **Строка 78** — леджер = нижняя граница (биллящийся decode-fail мимо request_log, ≤13% захода на ре-пробе) | `docs/PROGRESS.md:41` |
| **Строка 136** — эскроу/intent (см. §3 п.9) | `docs/PROGRESS.md:85` |
| **Строка 136** — эскроу/intent (см. §3 п.10) | `docs/PROGRESS.md:85` |
| *(добавка сборщика)* **PD-157 (minor)**`day_usd` книги флагом не перекрывается, платформой не виден и не задаётся; в `status --json` дневной фигуры нет | `DEFECT_REGISTER.md:168` |
## 6. Карта носителей темы

View file

@ -71,7 +71,7 @@
> «**Различимые exit-коды tmctl: потолочная остановка и graceful-stop** (сегодня оба = exit 1 ⇒ платформа отдаёт `failed` и на штатный стоп, и на исчерпание потолка — PD-113 платформы; после поправки формулы потолка (D39.123, PD-158) стоп по потолку = ровно исчерпание холда, цена неразличимости выросла; вскрыто приёмкой раннера на РЕАЛЬНОМ tmctl — фейк пробы умирал от сигнала)».
Действующий exit-контракт движка, чтобы новый код не столкнулся с занятыми: 0 clean · 2 completed-with-flags (`*pipeline.CompletedWithFlags`) · 3 signature-stop банка (`*pipeline.WaveSignatureStop`) · 1 — infra failure и всё прочее (`backend/cmd/tmctl/main.go:30-52`).
**ЭТОТ АБЗАЦ — СНИМОК ДО ПАКА, а не действующий контракт (испр. 22.08 аудитом доков; исходный текст оставлен, потому что документ — заказ эмиттер-сессии, а не справочник).** Пак D39.131 РАСШИРИЛ словарь ровно так, как этот раздел и просил: добавлены **exit 4** (потолочная остановка) и **exit 5** (graceful stop), плюс полоса отказов **1019**; действующий словарь читать в коде движка и в `platform/internal/ingest/exit.go`. Ниже — состояние на момент постановки задачи: 0 clean · 2 completed-with-flags (`*pipeline.CompletedWithFlags`) · 3 signature-stop банка (`*pipeline.WaveSignatureStop`) · 1 — infra failure и всё прочее (`backend/cmd/tmctl/main.go:30-52`).
**Семантика `--ceiling-usd`** (эмиттер-сессия трогает потолочную окрестность — знать обязана). D39.122 п.2(в) (`05-decisions-log.md:416`):
@ -93,6 +93,8 @@
**PD-107 (открыт; гейт, смежный с деньгами шва)** — `DEFECT_REGISTER.md:118`: «**Удаление аккаунта обходит защиту PD-25** … прогон, идущий против этого холда, останется без того, кто его закроет. Кода удаления аккаунта в дереве нет вовсе (грепнуто) ⇒ строка = гейт перед появлением такой операции». Прямых обязанностей эмиттеру не назначает; в чек-листе — потому что входит в ратифицированный список пре-чтения (D39.123 п.4).
> ⚠ **§5 и §6 ниже — ОТРАБОТАННЫЙ ХЕНДОФФ** (пометка 22.08): эмиттер-сессия исполнена и принята (D39.131, `9cfe080`), все пять развилок решены, чек-лист входного чтения исполнен. Разделы оставлены как провенанс заказа — исполнять их не нужно.
## 5. Открытые развилки дизайна — отданы эмиттер-сессии
1. **Формат журнала** — главная развилка, «решить дизайном» (строка 103). `research/25:74-76` (GPT): «**формат — развилка строки 103 (GPT):** одиночный JSONL с ftruncate-ремонтом имеет гонку живого читателя и слеп к битой записи с валидным `\n`; альтернативы — пофайловые события (`events/<seq>.json`, temp+rename) либо CRC-фрейминг; побайтовая идентичность не требуется». ⚠ Учесть: тейлер и декодер платформы УЖЕ построены под одиночный `events.jsonl` (`tail.go:17`); выбор пофайловой/CRC-формы = согласованное изменение обеих сторон, пингом через оркестратора.