diff --git a/docs/ORCHESTRATOR_SESSION_PROMPT.md b/docs/ORCHESTRATOR_SESSION_PROMPT.md index 6aec4d29..be45a6b8 100644 --- a/docs/ORCHESTRATOR_SESSION_PROMPT.md +++ b/docs/ORCHESTRATOR_SESSION_PROMPT.md @@ -1,6 +1,6 @@ # Промт: роль ОРКЕСТРАТОР TextMachine (канонический счётчик №N — в первой строке ниже) -> **Счётчик ролей — канонический ОДИН:** «оркестратор №N» (сейчас №15 — хендофф 06.08.2026, №14 закрыт после D39.107; состояние передачи — D39.107 (⚠ PROGRESS CURRENT-STATE НЕ обновлён: файл занят живым полигоном — обновить при его лендинге); очередь №15 — D39.107 п.3). +> **Счётчик ролей — канонический ОДИН, и номер выдаёт тот, кто пишет промт** (норма D39.112 п.6: №15 однажды вписал в CURRENT-STATE «№16» для параллельной сессии, которой промта не писал — это второй носитель состояния; параллельного оркестратора называть РОЛЬЮ, пока номер не выдан): «оркестратор №N» (сейчас №15 — хендофф 06.08.2026, №14 закрыт после D39.107; состояние передачи — D39.107 (⚠ PROGRESS CURRENT-STATE НЕ обновлён: файл занят живым полигоном — обновить при его лендинге); очередь №15 — D39.107 п.3). **Позиция и первые задачи хендоффа №8→№9 (26.07) — ИСТОРИЧНЫ И ИСПОЛНЕНЫ** (малая пачка 14а+14б → D39.54 · пак-19 → D39.55/56 · холодный мини-прогон → D39.58 · пак-21 «чекеры» → растворён D39.62, исполнен пакетом D39.78) — здесь не пересказываются (историзировано D39.80: файл нёс протухшую очередь как второй носитель состояния). **ЕДИНЫЙ БЭКЛОГ = секция «Бэклог» в PROGRESS.md — единственный трекер.** Текущее состояние и очередь — ТОЛЬКО PROGRESS CURRENT-STATE; онбординг стандартный (CLAUDE.md → README → CURRENT-STATE → голова D-лога). diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 4bd4b51c..a2934d0f 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,7 +1,7 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-08-07, голова D39.110; хендофф №14→№15 — D39.107). ⚠ **Оркестраторов сейчас ДВА, зоны разведены явно (решение владельца 07.08):** №15 — приёмка ПЛАТФОРМЫ (исполнена, D39.109) · №16 — приёмка ПОЛИГОНА (эксп-21, ждёт результатов; его пинг лежит в секции «Полигон» незакоммиченным). Одновременно не запускаются; CURRENT-STATE ведут оба, каждый пишет про свою зону и чужую строку не трогает. -> - **Сессия №15 (07.08, ИСПОЛНЕНА):** **приёмка платформы P1+P2 — ПРИНЯТО и ЗАЛЕНДЕНО `fcdab81`** (62 файла, +7066/−252; D39.109). Адверсариально: своя батарея с живым PostgreSQL 18.4 (скипов ноль) · 45 СВОИХ мутаций (33 поймано, 8 выжило, 4 моих посадки негодны и разобраны) · живые пробы на боевом бинаре (PD-2 отпускает на 30.0 с; RFC 9207 сверен у Google) · панель 7 линз с опровергателем на каждую находку. Ратифицировано 6 решений (срок сессии 30 суток — CONFIRM владельца 07.08 · `iss` авторизационного ответа + миграция 00008 · §13 политики сессий · ломающие изменения зоны · `MemoryMax=80%`+`OOMPolicy=continue` · PD-71 риском). Регистр зоны → **PD-107**: 37 открыто, из них **1 major** (PD-80: вход выключается ~3 rps, и 429 колбэка добивает начатые входы). **Живой уязвимости нет.** ⚠ **ЭРРАТА 07.08 (поймано вопросом владельца, не процессом):** приёмка пропустила, что **D39.106 п.3 снял пайп-транспорт** («PD-59 superseded; пайп-путь `supervisor.go` P1 = дев-режим»), и приняла зонную секцию «канал остаётся stdout» как живое решение. Ратифицированная форма — транзиентный systemd-юнит на прогон, платформа НЕ родитель, события = `events.jsonl` каталога книги, платформа ТЕЙЛИТ с курсором (`research/25` §Форма; родитель+пайп 0/15 голосов). Исправлено: секция журнала помечена superseded, PD-95 переписан и поднят в вес, PD-92 понижен до info, PD-105 повышен, PD-60 пере-диспозиционирован; вердикт лендинга не меняется (код и был дев-путём по D39.107 п.3). ⚠ Пять строк реестра — движковые по существу и должны быть разрулены ДО промта эмиттера (строка 103): PD-95 (транспортная история зоны устарела против D39.106 в двух местах — эмиттер-сессия прочтёт её как задание) · PD-105 (дубль `seq` = убитый платный прогон против норматива «дубль не ошибка»; при тейле файла повторная доставка — норма) · PD-79 (строковый `"null"` в цене = ноль денег) · PD-99 (argv на INFO — деньги/book-id при воркере) · PD-107 (удаление аккаунта обходит гарантию PD-25). **Потолок прогона РЕШЁН владельцем 07.08 и ратифицирован формой (D39.110):** шкала в интерфейсе от минимума (ноль нельзя) до баланса аккаунта ⇒ Р7 не амендируется, «выключено» не существует как состояние. Добор: единица шкалы — ГЛАВЫ, не доллары (иначе амендмент D39.84) · потолок в `book.yaml` НЕ пишется, движку нужен приём на прогон — НОВАЯ строка **145** · максимум шкалы = баланс минус открытые холды. **Фри-тир:** ответ дан нормой (автогрант без якоря — не стандарт; `email_verified` Google якорем не является), предложение оркестратора — на бете дефолт в НОЛЬ и начисление руками, при платежах $5 вместе с суточным потолком; **ждёт слова владельца** (PD-104, там же расхождение док↔код: реестр обещает ноль, код начисляет $5) · **приёмка экспов 18/19/20 ИСПОЛНЕНА и залендена** (D39.108: приняты с ревью-шапками; §5.2 экспа 20 — «со слов»; деньги сессии полигона $2.0720; квирк §3б отозван, §3а в силе; D21.4/D21.10 закрыты) · **эксп-21 «топология ролей» — промт выдан** (`POLYGON_ROLE_TOPOLOGY_SESSION_PROMPT.md`: скрин моделей по 7 ключам → бейк-офф топологий на невиданном срезе; потолки ПРЕДВАРИТЕЛЬНЫЕ ≈$7.3 стадиями; **ЗАПУСК = слово владельца**) · строки 135–144 заведены, 103/106/134/65/55/12 пере-диспозиционированы · дальше по D39.107 п.3: промты эмиттера (бэкенд) и денег шва (платформа) — по команде · запуск S3 (промт готов, `6ac26f3`) · вахта deepseek-v4-pro — пере-проба маппинга вшита в Ф1 эксп-21 · мини-проба флора 44 — одобрена, промт не выдан. **Открыто на владельце:** запуск эксп-21 (потолки + готовность слепого чтения ~50 пар) · передача платформы · Приложение А `14-api-contract` (незакоммичено) · запуск S3 · 116 (порог подан) · мини-проба 44 · подпись денежного шага 46 · лист В-3+К-6 · вопрос платформы (авто-резюме `paused`). +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-08-07, голова D39.112; хендофф №14→№15 — D39.107). ⚠ **Оркестраторов сейчас ДВА, зоны разведены явно (решение владельца 07.08):** №15 — приёмка ПЛАТФОРМЫ (исполнена, D39.109–D39.112; записи верифицированы независимым агентом, поправки — D39.112) · ВТОРОЙ, параллельный — приёмка ПОЛИГОНА (эксп-21, ждёт результатов; его пинг лежит в секции «Полигон» незакоммиченным). **Номер второму НЕ выдан намеренно:** канонический счётчик один и живёт в `ORCHESTRATOR_SESSION_PROMPT.md`, а выдавать номер сессии, которой я не писал промт, — второй носитель состояния. Одновременно не запускаются; CURRENT-STATE ведут оба, каждый пишет про свою зону и чужую строку не трогает. +> - **Сессия №15 (07.08, ИСПОЛНЕНА):** **приёмка платформы P1+P2 — ПРИНЯТО и ЗАЛЕНДЕНО `fcdab81`** (62 файла, +7066/−252; D39.109). Адверсариально: своя батарея с живым PostgreSQL 18.4 (скипов ноль) · 45 СВОИХ мутаций (33 поймано, 8 выжило, 4 моих посадки негодны и разобраны) · живые пробы на боевом бинаре (PD-2 отпускает на 30.0 с; RFC 9207 сверен у Google) · панель 7 линз с опровергателем на каждую находку. Ратифицировано 6 решений (срок сессии 30 суток — **CONFIRM владельца 07.08 получен** · `iss` авторизационного ответа + миграция 00008 · §13 политики сессий · ломающие изменения зоны · `MemoryMax=80%`+`OOMPolicy=continue` · PD-71 риском). Регистр зоны → **PD-107**: 37 открыто, из них **3 major** (PD-80: вход выключается ~3 rps, и 429 колбэка добивает начатые входы; PD-95 и PD-105 подняты эрратой как задание эмиттеру), 14 minor, 20 info. **Живой уязвимости нет.** ⚠ **ЭРРАТА 07.08 (поймано вопросом владельца, не процессом):** приёмка пропустила, что **D39.106 п.3 снял пайп-транспорт** («PD-59 superseded; пайп-путь `supervisor.go` P1 = дев-режим»), и приняла зонную секцию «канал остаётся stdout» как живое решение. Ратифицированная форма — транзиентный systemd-юнит на прогон, платформа НЕ родитель, события = `events.jsonl` каталога книги, платформа ТЕЙЛИТ с курсором (`research/25` §Форма; родитель+пайп 0/15 голосов). Исправлено: секция журнала помечена superseded, PD-95 переписан и поднят в вес, PD-92 понижен до info, PD-105 повышен, PD-60 пере-диспозиционирован; вердикт лендинга не меняется (код и был дев-путём по D39.107 п.3). ⚠ Пять строк реестра — движковые по существу и должны быть разрулены ДО промта эмиттера (строка 103): PD-95 (транспортная история зоны устарела против D39.106 в двух местах — эмиттер-сессия прочтёт её как задание) · PD-105 (дубль `seq` = убитый платный прогон против норматива «дубль не ошибка»; при тейле файла повторная доставка — норма) · PD-79 (строковый `"null"` в цене = ноль денег) · PD-99 (argv на INFO — деньги/book-id при воркере) · PD-107 (удаление аккаунта обходит гарантию PD-25) · **PD-60 и PD-61** (обратное давление и сброс буфера — свойства эмиттера, задаются дешевле ДО постройки, чем миграцией после; PD-60 переформулируется под файл-транспорт). **Потолок прогона РЕШЁН владельцем 07.08 и ратифицирован формой (D39.110):** шкала в интерфейсе от минимума (ноль нельзя) до баланса аккаунта ⇒ Р7 не амендируется, «выключено» не существует как состояние. Добор: единица шкалы — ГЛАВЫ, не доллары (иначе амендмент D39.84) · потолок в `book.yaml` НЕ пишется, движку нужен приём на прогон — НОВАЯ строка **145** · максимум шкалы = баланс минус открытые холды. **Фри-тир:** ответ дан нормой (автогрант без якоря — не стандарт; `email_verified` Google якорем не является), предложение оркестратора — на бете дефолт в НОЛЬ и начисление руками, при платежах $5 вместе с суточным потолком; **ждёт слова владельца** (PD-104, там же расхождение док↔код: реестр обещает ноль, код начисляет $5) · **приёмка экспов 18/19/20 ИСПОЛНЕНА и залендена** (D39.108: приняты с ревью-шапками; §5.2 экспа 20 — «со слов»; деньги сессии полигона $2.0720; квирк §3б отозван, §3а в силе; D21.4/D21.10 закрыты) · **эксп-21 «топология ролей» — промт выдан** (`POLYGON_ROLE_TOPOLOGY_SESSION_PROMPT.md`: скрин моделей по 7 ключам → бейк-офф топологий на невиданном срезе; потолки ПРЕДВАРИТЕЛЬНЫЕ ≈$7.3 стадиями; **ЗАПУСК = слово владельца**) · строки 135–144 заведены, 103/106/134/65/55/12 пере-диспозиционированы · дальше по D39.107 п.3: промты эмиттера (бэкенд) и денег шва (платформа) — по команде · запуск S3 (промт готов, `6ac26f3`) · вахта deepseek-v4-pro — пере-проба маппинга вшита в Ф1 эксп-21 · мини-проба флора 44 — одобрена, промт не выдан. **Открыто на владельце:** запуск эксп-21 (потолки + готовность слепого чтения ~50 пар) · передача платформы · Приложение А `14-api-contract` (незакоммичено) · запуск S3 · 116 (порог подан) · мини-проба 44 · подпись денежного шага 46 · лист В-3+К-6 · вопрос платформы (авто-резюме `paused`). > - **Сделано (сводно; детали — D-лог и архив-слайсы):** Ф0 ✅ · Ф1-инфра ✅ · арх-ресет D39 (7 слоёв, паки 11–16) ✅ · паки 17 «канал B» · 18 «долги» · 19 «голос/состояние» · 20 «банк+терминолог» ✅ (D39.26–28/31/41–56) · мини-прогон (D39.37) и ХОЛОДНЫЙ прогон (D39.58: recall банка 0.918/0.980, банк приходит переведённым) приняты · полигон-пакеты 5–8, ToS-речек (D39.57), Р6+P4 (D39.61) закрыты · **карта языковой привязки движка (D39.60): 149 сайтов/45 файлов, книго-ось чиста (4), ja→ru безопасно без правки Go, en→ru — нет** · Р1–Р4 закрыты целиком (D39.63: Р2 = ЗНАЧЕНИЕ, Р4 = норма потолка recall) · **ФАЗА 2 ОБЩНОСТИ ✅ (D39.64: П0 эмбед-хеш · П1 цель-шов · П2 скрипт-шов, ko-баг закрыт · П3 нарезка · П4 манифест-по-каналам; голден вердикт-нейтрален 0/172, майнер-парити EXACT)** · жанровый словарь отменён как класс (D39.47) · петля ремонта построена и НЕ включена (D39.38). > - **Курс:** ОБЩНОСТЬ ✅ → КАЧЕСТВО БАНКА ✅ → ПАКЕТ-ЧЕКЕРОВ ✅ (D39.59–78) → **ФРОНТ-ЭРА открыта** (D39.81–100: зоны `frontend/`+`platform/` живые, контракт API ратифицирован). Развилка блокера 0731 решена вариантом (б) и ИСПОЛНЕНА (D39.87/91: `reasoning_effort:"low"` черновику + ручка эффорта бэнк-ролям, код `553f1a3`); отладочный прогон C не стартовал ⇒ **строка 16 жива и оси голоса 13б без данных**; пак экрана 46 — дизайн заморожен (D39.92 п.1 + D39.93), промт ждёт выдачи; coldrun-b фаза C заморожена чекпойнтом — легитимный исход (D39.86); эталон денег/поведения — coldrun-a (read-only). Числа и хроника закрытых паков — D-лог D39.79–97, сюда НЕ дублируются. > - **Горизонт (D39.62/67, освежён D39.95):** ре-проба flash ИСПОЛНЕНА и строка 74 закрыта (D39.86/91; порог 6/6 → пере-ратификация выборочным, строка 116; проба Q2 ИСПОЛНЕНА — research/24, D39.102: семейства не окупаются, остаток = рецензент спорных кластеров при ре-пробе 74; эмиссия Q7 — по слову) → **ДОБОР ИДЕАЛА** (первым прогоном: оси голоса 24 · авто-режим · итерация №2 редакторов 65 · цена 16 · веса K1–K12 13а · вне-претрейн чекпоинт 55) → ВТОРАЯ ПАРА живьём (ja→ru; преп 81) → МАСШТАБ → пилот Ф2.5 (гейт резюме-строки 80; строки 62–68, 85) → Ф3 ридер-IDE (69–71). **Стоячие:** ToS-триггер 25.10 · Ш-2 до go1.27 (⚠ + x/text-таблицы Unicode 17 тем же тулчейном — строка 119/реестр 108) · проба провода исполнена и 117 закрыта (D39.97), конфиги 112 залендены — платные прогоны разблокированы. @@ -128,7 +128,7 @@ | 102 | **Приём внешнего trace-контекста в tmctl**: TraceID минтится заново каждым вызовом (`main.go:67-70`; внутри вызова трасса цельная, `request_log.trace_id` есть) — прогон, запущенный платформой, должен быть одной трассой | бэкенд | когда-нибудь (Ф3, с 96) | малое касание | релей фронта 02.08, D39.84 | | 103 | **NDJSON-эмиттер прогонных событий со стабильным словарём** (машинный канал живого статуса для платформы, `research/23` §2): NDJSON-логи уже есть (`LOG_FORMAT=json`, авто-оси trace/book/chapter/stage/role — `obs/logging.go:15-54`), но сообщения прозой, version-хендшейка нет, а **событие потолка отсутствует вовсе** (деньги только в тексте ошибки `stagerun.go:472-494`); нужен словарь-enum + version-хендшейк первой строкой (образец terraform -json: минор = ignore-unknown, мажор = reject) + событие потолка; все границы — единичные call-sites в pipeline рядом с готовыми slog; человеческие логи уже на stderr — stdout-дисциплина соблюдена. **Форма ратифицирована D39.106 (research/25 §эмиттер):** `events.jsonl` каталога книги = outbox-проекция коммитов SQLite (та же транзакция, что чекпойнт) · fsync/seq/hello-версия · события денег и потолка · развилка формата (JSONL против пофайловых/CRC-фрейминга) — решить дизайном · `status --json` отдельным каналом (ремонт, тот же flock) | бэкенд | скоро (промт бэкенду — по команде владельца, D39.107 п.3) | стройка по D39.106 + research/25 | research/23, D39.85, **D39.106** | | 125 | **Артефакт экспорта БАНКА** (полный банк тремя статусами — канал чтения `/bank` контракта 14): строка 101 это таблица ПОДПИСИ (кап 20 stdout, `cmd/tmctl/render.go:98`), не экспорт; сам банк в приватном SQLite, платформе закрыт (D39.85) — нужен экспорт-артефакт движка на границе стадии/стопе | бэкенд | скоро (БЛОКЕР контракта API, D39.99) | дизайн + малое касание export | ревью контракта 04.08, D39.99 | -| 126 | **Потолок прогона — УПРАВЛЯЕМЫЙ, решение владельца 07.08: настройка в интерфейсе фронта, шкала от минимума (ноль выбрать НЕЛЬЗЯ, подсвечен серым) до максимума баланса аккаунта.** Форма снимает конфликт с Р7 бесплатно: максимум = баланс ⇒ движок всегда получает положительное число и состояния «выключено» не существует, валидатор `book.go:250` не правится. **Три следствия, ратифицированы формой (D39.110):** (а) **единица — НЕ доллары**, а главы (или % баланса): тогда минимум объясняет себя сам («одна глава»), а D39.84 цел — читатель не видит структуру расходов; доллары на пользовательском экране = осознанный амендмент D39.84, не побочный эффект виджета; (б) это потолок ПРОГОНА ⇒ в `book.yaml` он не пишется, движку нужен приём потолка на прогон — строка 145; (в) **максимум шкалы = баланс МИНУС открытые холды**, иначе ползунок в упоре запирает весь баланс на одну книгу и вторую начать нельзя (холд берётся ДО спавна; `ReadAccount` уже возвращает `Balance` и `Reserved` раздельно). Прежнее тело строки (механизм поднятия потолка для resume после ceiling-стопа: движок продолжает «once the ceiling is raised», `stagerun.go:488-489`) — половина этой же работы. Продуктовое слово стопа — К-8 у владельца | платформа/фронт/бэкенд | скоро (форма решена, стройка — промтами) | дизайн-вход П-1 + правка спеки + строка 145 | ревью контракта 04.08, D39.99, **D39.110** | +| 126 | **Потолок прогона — УПРАВЛЯЕМЫЙ, решение владельца 07.08: настройка в интерфейсе фронта, шкала от минимума (ноль выбрать НЕЛЬЗЯ, подсвечен серым) до максимума баланса аккаунта.** Форма снимает конфликт с Р7 бесплатно: максимум = баланс ⇒ движок всегда получает положительное число и состояния «выключено» не существует, валидатор `book.go:250` не правится. **Три следствия, ратифицированы формой (D39.110):** (а) **единица — НЕ доллары**, а главы (или % баланса): тогда минимум объясняет себя сам («одна глава»), а D39.84 цел — читатель не видит структуру расходов; доллары на пользовательском экране = осознанный амендмент D39.84, не побочный эффект виджета; (б) это потолок ПРОГОНА ⇒ в `book.yaml` он не пишется, движку нужен приём потолка на прогон — строка 145; (в) **максимум шкалы = баланс МИНУС открытые холды**, иначе ползунок в упоре запирает весь баланс на одну книгу и вторую начать нельзя (холд берётся ДО спавна; `ReadAccount` уже возвращает `Balance` и `Reserved` раздельно). **НОСИТЕЛЬ ПЕРЕСЧЁТА НАЗВАН (добор после верификации 07.08):** «сколько глав влезает в доступный остаток» считает ПЛАТФОРМА (по оценке движка) и отдаёт фронту ГРАНИЦЫ шкалы и выбранное значение в главах; сама формула наружу не выходит. Ручки под это в контракте НЕТ — сегодняшний `GET /v0/usage` несёт только процент, поэтому поверхность объявляется при правке спеки вместе с созданием прогона (работа П-1 + S3), и до её объявления фронт максимум шкалы взять неоткуда. Прежнее тело строки (механизм поднятия потолка для resume после ceiling-стопа: движок продолжает «once the ceiling is raised», `stagerun.go:488-489`) — половина этой же работы. Продуктовое слово стопа — К-8 у владельца | платформа/фронт/бэкенд | скоро (форма решена, стройка — промтами) | дизайн-вход П-1 + правка спеки + строка 145 | ревью контракта 04.08, D39.99, **D39.110** | | 127 | **Устаревший DDL-коммент `glossary.source`** (`migrate.go:193`: «seed|ruby|auto», фактические пути записи — seed/ruby/mined, `auto` не пишет никто; фантом уже утёк во фронт-доки дважды) — поправить коммент | бэкенд | когда-нибудь (попутно любым паком store) | однострочная правка | ревью контракта 04.08, D39.99 | | 105 | **Роль `classifier` мис-вердиктится как эхо + честность двух новых строк наблюдаемости (D39.86).** (а) `classifyOutput` даёт поблажку `SourceEchoExpected` только `roleTerminologist` (`chunkrun.go:37`), а ответ классификатора по формату состоит из исходных ханьских термов ⇒ доля исходного письма 0.20–0.29 > порога 0.15 на каждом батче: живой артефакт пробы 6/6 несёт `verdict=cjk_artifact` при `bad_lines=0`. Ущерб узкий — `runBankRoleBatches` кладёт `run.texts[i] = att.text` без проверки диспозиции (`terminologist.go:603`), посчитанные эхо-ставки (`quality.go:313-321`) берутся из `chunk_status`, куда бэнк-путь не пишет ⇒ портятся только строки `tmctl report`/лога; **латентно** (`classify_types` выключен во всех шиппинг-конфигах). ⚠ Цена дисциплинированного фикса, которую надо знать заранее: бамп `classifierVersion` (литерал, сам не двигается) меняет payload снапшота → snapshot id → `RequestHash` ⇒ промах ВСЕХ чекпойнтов книги, то есть `--resnapshot` + пере-покупка. (б) тем же касанием — честность поверхностей: строка `VOICE` берёт `rules=` из конфига ВРЕМЕНИ ОТЧЁТА (`quality.go:436`), поэтому включение `gates.voice` после прогона печатает «измерено, чисто» для неизмеренной книги (воспроизведено); и она печатается при выключенном гейте, если `SpoilerLeaks>0` (дизъюнкция — поведение верное, формулировка отчёта/коммента неверна); знаменатель `BANKNOTE` = `len(states)` включая призрачные строки `retrieval_state`, тогда как соседний агрегатор их фильтрует (`quality.go:259-260`) ⇒ после пере-чанковки покрытие занижается | бэкенд | когда-нибудь (ближайшее касание банка/наблюдаемости; (б) — дешёвая часть, вердиктов не двигает) | малое касание + вердикт-двигающая половина (а) через СТОП-решение | D39.86 | | 106 | **Слой 3 НЕ достроен: контракт редактора = full-regen, а целевой — узкие мандаты + ДИФФЫ.** `09-target-architecture.md:121-126` дословно: «research/07 предписывает узкие мандаты + диффы, а не полную перегенерацию — сейчас ровно наоборот (4 мандата, full-regen), что и породило хвост инверсий»; целевой контракт — редактор правит anchored search/replace-спанами с детерминированным Go-apply (ограниченный blast-radius, дешевле, аудируемо, структурно omission-safe). Пак-16 построил петлю РЕМОНТА (починка флагнутого спана постфактум), а не diff-контракт роли ⇒ это разные вещи. **Строки не было ни одной** — дыра учёта, найденная сверкой 02.08 (грепы `diff`/`мандат`/`span` по бэклогу = 0). Смежное: арм Q4b «diff-fidelity+style редактор» (`exp15:108`) не прогонялся НИ РАЗУ, хотя трек B объявлен завершённым. **ЭМПИРИКА ПОЛУЧЕНА (D39.108, экспы 19/20):** дифф-контракт механически исправен (комплаенс 0.966 на боевой единице, аппликатор 15/15), но по замороженному гейту Q4b диффы ОТЛОЖЕНЫ (fidelity-trap 11/12; дороже full-regen на dspro×ru ×2.5–2.9 при невскрытой причине; D21.4/D21.10 закрыты явно). Дальше — эксп-21 (топология) → решение владельца | владелец → бэкенд | гейт: эксп-21 | решение владельца по бейк-оффу эксп-21 | 09 §Слой 3, D39.90, **D39.108** | diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index 0459e226..49597079 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1,4 +1,4 @@ -# Журнал решений оркестратора — контракт D1–D39.111 (развязки 04.07 · пакеты 09–10.07 · приёмка/качество-первым/пивот/эмпирика 11–12.07 · арх-ресет+стройка пере-прогонного стека 13–19.07) +# Журнал решений оркестратора — контракт D1–D39.112 (развязки 04.07 · пакеты 09–10.07 · приёмка/качество-первым/пивот/эмпирика 11–12.07 · арх-ресет+стройка пере-прогонного стека 13–19.07) > **⟶ КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Читая контракт целиком, держи под рукой, что чем перекрыто: > ⚠ **Навигация (актуализация 04.08):** два supersede-указателя эры D39.9x: **D39.88/D39.84 п.8 (право самокоммита фронта/платформы) → отозвано, коммитит ТОЛЬКО оркестратор** (D39.98 п.3; тела переписаны на месте с санкцией владельца, pre-rewrite — git `2b166b7`) · **норма 30.07 «короткая приёмка» → амендирована владельцем 03.08: приёмка всегда адверсариальная** (носитель — промт оркестратора §Анти-паттерны + D39.101 п.1) — упоминания «короткой приёмки» в телах читать через эту пометку · **двухсекционная редакторская инъекция и смягчающая роль маркера ⟨проверить⟩ → доктрина инжекта D39.104**: банк на проводе = ЗАКОН для всех ролей независимо от статуса строки, право «перевести иначе» упразднено, блок редактора — ЕДИНЫЙ, маркер с провода снимается (статусы строк и подписная таблица не меняются; внесение в движок — строка 134 после пробы 18) — упоминания двухсекционки/смягчения в телах читать через это. @@ -1571,3 +1571,19 @@ API-529-долг закрыт: 8-осевой refute-by-default воркфлоу **2. Фикс-пак платформы передан ЗАПИСКОЙ, а не отдельным промтом** — по прецеденту №14 (восемь пунктов жили разделом зонного журнала и были отработаны) и по норме пропорциональности: это точечные фиксы, а не дизайн. Носитель — раздел «Ратификация приёмкой P2» зонного журнала, фикс-лист там же с порядком. Состав: **PD-80** (единственная major — доступность входа: лимитер прежде очистки login-куки плюс раздельные ведра) · **PD-79** (строковый `"null"` = ноль денег, до появления вызывающего у `Settle`) · **PD-100** (колбэк глотает ошибки стора и discovery — класс PD-5, закрытый в `auth/`, но не в `login/`) · **PD-83/84/85** (три «закрыто, но не запинено» по собственному правилу зоны) · **PD-106** (админ-CLI — единственный писатель денег — без единого теста) · **PD-91** (установка по наброску даёт нестартующий юнит; `ProtectHome` против «книги в `~/books`») · **PD-95** (транспортный доккоммент — ДО промта эмиттера, иначе эмиттер-сессия прочтёт его как задание). **Граница пака названа явно:** PD-92/93/96/99/102/105/107 НЕ трогать — они латентны за воркером и эмиттером, и правка сейчас означала бы угадывание формы, которую задаёт строка 103. **3. Условный пункт:** если владелец подтверждает предложение по фри-тиру (D39.110 п.3), в тот же пак заходит дефолт `SignupGrantMicroUSD` в НОЛЬ; расхождение док↔код (PD-104) чинится независимо от ответа. + +## D39.112 — ВЕРИФИКАЦИЯ ЗАПИСЕЙ №15 НЕЗАВИСИМЫМ АГЕНТОМ: восемь фактических правок и восемь пробелов закрыты; поправка к D39.109/D39.110 (07.08). ✅ + +**1. Заказ владельца:** один чистый агент читает промт оркестратора и доки «где мы сейчас» и проверяет записи №15 по четырём осям — факты, пробелы, понятность холодной сессии, вода. Вердикт агента: «можно доверять С ПРАВКАМИ». Он пере-считал очередь своим скриптом (120 · 62/79 · «скоро» 32 — сошлось до строки), механически сверил ВСЕ `file:line` новых строк реестра (все существуют и говорят заявленное), пере-проверил номера норм по первоисточникам, прогнал `build`/`vet`/`test`/`golangci-lint` в зоне (0 issues) и подтвердил существование всех пинов ратифицированных решений. Не заверено им (стенд без Postgres): 45 мутаций, 26 БД-тестов, живые пробы на бинаре, `make vuln`, счёт фаззеров — остаются со слов приёмки, и так и помечено. + +**2. Поправки к D39.109 — принять как исправление, буква нот не переписывается (D23.3).** **(а) п.3 пере-формулировал NIST.** Сказано «30 суток — БУКВА NIST AAL1»; по первоисточнику SP 800-63B-4 §2.1.3 буква иная: SHALL — только «установить определённый reauthentication overall timeout», сами 30 суток — **SHOULD**, и это интервал ре-аутентификации, который успешная ре-аутентификация СБРАСЫВАЕТ, а не неснимаемый предел; термин «absolute maximum session lifetime» принадлежит ASVS, не NIST. Верная формулировка: **30 суток — SHOULD-планка ре-аутентификации AAL1, а наш жёсткий абсолютный срок 30 суток строже неё.** Зонные носителя (`STACK_DECISIONS §13`, `config.go:62-64`) цитируют верно — ошибка была только в ноте, то есть в источнике истины №1. Номера разделов всех трёх норм верны. **Замечание по прицелу:** 7.1.x требуют ДОКУМЕНТА, величину требуют 7.3.1/7.3.2 — если §13 будут судить как соответствие ЗНАЧЕНИЮ, ссылка нужна на 7.3.2, её нет ни в одном доке. **(б) п.4 сохранил снятое основание** «доккоммент предлагает то, что PD-59 уже отклонил»: PD-59 сам superseded (D39.106 п.3), эррата это признала и переписала строку реестра, но текст п.4 остался — читать через эту поправку. **(в) «Живой уязвимости приёмка не нашла»** — термин не определён и гасит единственную major. Верно так: уязвимости с потерей денег, данных или захватом сессии нет; отказ в обслуживании входа ЕСТЬ и воспроизведён (PD-80, класс `vuln`). Формулировка в зонном журнале и CURRENT-STATE исправлена. + +**3. Поправка к D39.110:** п.1 назван «решение владельца (дословно по смыслу)» — оксюморон, запрещённый нормой «цитаты только дословные, овер-атрибуция — типовой провал»; читать как **пересказ** решения. Форма и три следствия не меняются. + +**4. Закрытые пробелы (все — в носителях, а не в нотах, потому что сессии зон читают носители).** PD-100 объявлялся в составе фикс-пака, а в фикс-листе зонного журнала отсутствовал — **добавлен пунктом 7** · граница пака («PD-92/93/96/99/102/105/107 не трогать») жила только в D-логе, а фикс-лист говорил обратное «остальное по весу строк» — **перенесена в журнал пунктом 8, формулировка «по весу» снята** · пункт 6 фикс-листа был одиннадцатью строками истории моей ошибки без задания — **сжат до задания** («переписать доккоммент `events.go:6-12` под форму D39.106 ДО промта эмиттера») · «три строки блокируют деплой и воркер» не называли, какие — **названы поимённо** (PD-91 деплой · PD-79 воркер · PD-95 промт эмиттера) · счёт весов регистра отстал от эрраты — **пере-считан скриптом: 37 открытых, 3 major, 14 minor, 20 info**, исправлен в двух местах · PD-105 нёс `minor` в колонке при «повышен» в теле — **колонка приведена** · словарь классов в шапке реестра не знал `doc`/`standards`, введённых новыми строками — **дописан** · PD-60/PD-61 выпали из списка «разрулить до промта эмиттера» — **возвращены** · пересчёт «главы → деньги» и ручка границ шкалы не были поручены никому — **носитель назван в строке 126** (считает платформа, поверхность объявляется правкой спеки; ручки в контракте сегодня нет) · «CONFIRM владельца на 30 суток» стоял в CURRENT-STATE как полученный, а в ноте и журнале — как открытый вопрос: **confirm получен 07.08, тексты сведены**. + +**5. Два пробела класса «повторил свой же урок».** **(а)** Эррата D39.109 ввела правило «каждый вывод зонного дока, спорящий со швом, грепается на supersede ДО ратификации» — и не применила его к ПОТОЛКУ: раздел П-5 зонного журнала продолжал объявлять платформу владельцем `book.yaml`, хотя D39.110 п.2(б) это отменил в тот же день. Абзац помечен SUPERSEDED. **(б)** Голова CURRENT-STATE отставала — **третий раз в истории проекта** (после D39.81 и D39.83, оба названы в промте оркестратора): нота D39.111 была ратифицирована, а шапка показывала D39.110. Механический чек головы обязателен ПОСЛЕ каждого аппенда, а не после «важных». + +**6. Не минтить номера чужим сессиям.** CURRENT-STATE ввёл «оркестратор №16» для параллельной приёмки полигона — при том что счётчик объявлен каноническим и ОДНИМ, живёт в промте оркестратора и показывает №15, а по D-логу №16 не существует. Номер снят: второй оркестратор назван ролью («параллельный, приёмка полигона»), номер выдаёт тот, кто пишет ему промт. + +**7. Долг, оставленный сознательно:** срез хроники PROGRESS в архивный слайс (живой хвост несёт №11–№13, эра D39.91–105, всё закрытое) — НЕ сделан, потому что файл держит живая полигон-сессия, а срез это перекладывание сотни строк в контендящемся файле. Режет тот, кто лендит полигон. Туда же: архивация отработанного `PLATFORM_SESSION_PROMPT.md` (баннер-исход на нём стоит) — после приёмки фикс-пака, чтобы не ломать ссылку живой сессии. diff --git a/platform/docs/DEFECT_REGISTER.md b/platform/docs/DEFECT_REGISTER.md index 486abf44..8b32aced 100644 --- a/platform/docs/DEFECT_REGISTER.md +++ b/platform/docs/DEFECT_REGISTER.md @@ -4,7 +4,8 @@ > Правила: каждая находка любой сессии/приёмки/аудита — строкой сюда ДО закрытия; ID стабилен навсегда; > закрытие — только с коммитом фикса и тестом, пинящим свойство (урок PD-1: свойство без пинящего теста > считается НЕ закрытым). Класс: `vuln` — эксплуатируемо или ослабляет защиту · `bug` — неверное поведение · -> `hardening` — защита в глубину / латентное. Статус: `open` · `fixed()` · `accepted-risk(<кем, когда>)`. +> `hardening` — защита в глубину / латентное · `doc` — док лжёт о коде · `standards` — расхождение с +> объявленной нормой зоны (введены приёмкой P2; словарь отставал от строк — испр. оркестратором №15). Статус: `open` · `fixed()` · `accepted-risk(<кем, когда>)`. | ID | Класс | Серьёзность | Где | Суть | Статус | Источник | |---|---|---|---|---|---|---| @@ -111,7 +112,7 @@ | PD-101 | bug | minor | `internal/login/login.go:507` | `login_events.ip_prefix` берётся из `r.RemoteAddr`, а в задуманном деплое перед сервисом стоит edge-прокси ⇒ префикс всегда сеть прокси. Журнал входов заведён как ответ на «откуда примерно я входил» — в шипуемой форме он систематически отвечает неверно. `X-Forwarded-For`/`Forwarded` нигде не читаются и доверенного прокси в конфиге нет (это правильный дефолт: доверять заголовку без edge нельзя) — значит решение про edge и про этот столбец принимается вместе | open | приёмка P2 (панель) | | PD-102 | doc | minor | `internal/httpapi/serve.go:36-38` | Доккоммент `DefaultTimeouts` утверждает, что «an upload extends its own deadline as it makes progress» — это НЕВЕРНО: `ReadTimeout` в `net/http` (Go 1.26.5, `server.go:990` `wholeReqDeadline = t0.Add(ReadTimeout)`) выставляется один раз и по мере прихода байтов не продлевается. Комментарий несущий: он объясняет, почему `Read` короткий, и на нём будущая ручка загрузки книги (23 МБ по контракту) построит неверное ожидание — ей понадобится собственный дедлайн через `ResponseController`, а не «прогресс продлевает» | open | приёмка P2 (панель, сверено с исходником Go) | | PD-103 | hardening | minor | `internal/auth/middleware.go:43,66` | У обращений к БД на аутентифицированном пути (`Lookup`/`Touch`) нет собственного дедлайна — только голый `r.Context()`, а `WriteTimeout` у сервера отсутствует по проекту (SSE) и `TimeoutHandler` в цепочке нет. Зависший Postgres паркует хендлеры и ждущих в пуле, пока клиент сам не уйдёт. `readyz` свой таймаут получил (PD-14) — горячий путь нет | open | приёмка P2 (панель) | -| PD-104 | bug | **minor, но с расхождением док↔код** | `internal/login/login.go:285-288`, `internal/config/config.go:73` | **Фри-тир начисляется АВТОМАТИЧЕСКИ, а реестр обещает обратное.** Код: дефолт `SignupGrantMicroUSD: 5 * 1_000_000` (`config.go:73`) проведён в демона (`main.go:99`) и логин отдаёт его в стор на каждой новой подтверждённой паре `(provider, subject)` — то есть аккаунт создаётся С $5. Строка PD-30 при закрытии утверждает «аккаунт создаётся с нулём, начисление руками из админки» — **один из двух текстов лжёт**. Ограничитель у автоматического начисления один — лимитер входа; агрегатного потолка суммы грантов, счётчика и алерта нет нигде (грепнуто). Деньги при этом предоплаченные ключи владельца. ⚠ **Индустриальная норма:** автоматический промо-грант нормален, но только с ЯКОРЕМ, который стоит абьюзеру денег (карта на файле — AWS/GCP; телефон — OpenAI добавил его к своим $5 после фарминга; инвайт), плюс бюджет кампании отдельной суммой и алерт. `email_verified` от Google якорем НЕ является: аккаунты бесплатны и делаются пачками. **Предложение оркестратора №15 (ждёт confirm владельца):** на бете дефолт в НОЛЬ и начисление руками — платёжного инструмента нет, значит между скриптом и ключами нет ничего; при появлении платежей дефолт возвращается к $5 ВМЕСТЕ с суточным агрегатным потолком (якорь и потолок приезжают по одному поводу). Расхождение док↔код чинить независимо от ответа | open | приёмка P2 (панель; расхождение и норма — оркестратор №15, 07.08) | -| PD-105 | standards | minor | `internal/ingest/decoder.go:96` | **Декодер и норматив зоны расходятся на дубле `seq`:** декодер объявляет его фатальным `ErrStreamGap`, а `ENGINEERING_STANDARDS §2` ратифицирует «at-least-once — норма, дубль — не ошибка». После фикса PD-12 цена выросла: сбой ингеста ОСТАНАВЛИВАЕТ прогон, поэтому одна задублированная строка убивает платный прогон, хотя ратифицированный путь ремонта — `status --json`. Внутри одного пайпа передоставки нет, так что отказ декодера защитим; непропорциональна РЕАКЦИЯ. Разрешать ратификацией вместе с промтом эмиттера (строка 103), не молча. ⚠ **Пере-диспозиция (эррата №15): вес ПОВЫШЕН до major-для-эмиттера** — при ратифицированном транспорте (тейл `events.jsonl` с курсором, D39.106) повторное чтение строк после краша читателя — НОРМА, а не аномалия пайпа, поэтому норматив «at-least-once, дубль не ошибка» буквально верен, и фатальный отказ декодера прямо ему противоречит | open | приёмка P2 (панель) | +| PD-104 | bug | **minor, расхождение док↔код** | `internal/login/login.go:285-288`, `internal/config/config.go:73` | **Фри-тир начисляется АВТОМАТИЧЕСКИ, а реестр обещает обратное.** Код: дефолт `SignupGrantMicroUSD: 5 * 1_000_000` (`config.go:73`) проведён в демона (`main.go:99`) и логин отдаёт его в стор на каждой новой подтверждённой паре `(provider, subject)` — аккаунт создаётся С $5. Строка PD-30 при закрытии утверждает «аккаунт создаётся с нулём, начисление руками из админки» — один из двух текстов лжёт, и это чинится независимо от продуктового решения. Ограничитель у автогранта один — лимитер входа; агрегатного потолка, счётчика и алерта нет (грепнуто). **Разбор нормы и предложение «на бете дефолт в НОЛЬ» — D39.110 п.3, здесь не дублируется; ждёт слова владельца** | open | приёмка P2 (панель; расхождение — оркестратор №15) | +| PD-105 | standards | **major (для промта эмиттера)** | `internal/ingest/decoder.go:96` | **Декодер и норматив зоны расходятся на дубле `seq`:** декодер объявляет его фатальным `ErrStreamGap`, а `ENGINEERING_STANDARDS §2` ратифицирует «at-least-once — норма, дубль — не ошибка». После фикса PD-12 цена выросла: сбой ингеста ОСТАНАВЛИВАЕТ прогон, поэтому одна задублированная строка убивает платный прогон, хотя ратифицированный путь ремонта — `status --json`. Внутри одного пайпа передоставки нет, так что отказ декодера защитим; непропорциональна РЕАКЦИЯ. Разрешать ратификацией вместе с промтом эмиттера (строка 103), не молча. ⚠ **Пере-диспозиция (эррата №15): вес ПОВЫШЕН до major-для-эмиттера** — при ратифицированном транспорте (тейл `events.jsonl` с курсором, D39.106) повторное чтение строк после краша читателя — НОРМА, а не аномалия пайпа, поэтому норматив «at-least-once, дубль не ошибка» буквально верен, и фатальный отказ декодера прямо ему противоречит | open | приёмка P2 (панель) | | PD-106 | standards | minor | `cmd/tmplatformctl/` | **Админ-CLI — единственный писатель денег в дереве — не имеет ни одного теста.** В том числе не покрыто правило, которое он сам называет несущим («после коммита команда не может отчитаться провалом», фикс PD-75), и разбор флагов, и формат вывода. Батарея зоны его не видит вовсе (`[no test files]`) | open | приёмка P2 (панель) | | PD-107 | hardening | info | `internal/pgstore/migrations/00007_credits.sql:85`, `00002_readmodel.sql:13` | **Удаление аккаунта обходит защиту PD-25:** составной FK `reservations → books(id, owner_id) on delete restrict` блокирует `DeleteBook`, но `users` каскадит в `reservations` НАПРЯМУЮ, поэтому `delete from users` уносит и ОТКРЫТУЮ резервацию. Замерено приёмкой: аккаунт с открытым холдом удаляется. Учётной дыры нет — леджер и кэш баланса каскадятся тем же удалением, — но прогон, идущий против этого холда, останется без того, кто его закроет. Кода удаления аккаунта в дереве нет вовсе (грепнуто) ⇒ строка = гейт перед появлением такой операции (и перед ASVS 7.4.2 в полной форме). ⚠ Заодно ОПРОВЕРГНУТА обратная версия этой находки от панели («удаление падает на композитном FK даже при закрытых резервациях») — мой прогон: удаляется и с закрытой резервацией, и без неё | open | приёмка P2 (замер оркестратора №15; версия панели опровергнута) | diff --git a/platform/docs/platform-PROGRESS.md b/platform/docs/platform-PROGRESS.md index df04e429..a8dbcfc4 100644 --- a/platform/docs/platform-PROGRESS.md +++ b/platform/docs/platform-PROGRESS.md @@ -10,7 +10,7 @@ вердикт, метод, что ратифицировано, фикс-лист, что опровергнуто. Два вопроса ушли владельцу: срок сессии 30 суток и агрегатный потолок фри-тира (PD-104). - **Регистр после приёмки — 107 строк** (скриптом по таблице): 66 закрыто · 3 приняты риском · - 1 закрыт ратификацией (PD-59) · **37 открыто** — из них **1 major** (PD-80), 17 minor, 19 info. + 1 закрыт ратификацией (PD-59) · **37 открыто** — из них **3 major** (PD-80 · PD-95 · PD-105; две последние подняты эрратой 07.08), 14 minor, 20 info. Прежние восемь (PD-6 · PD-23 · PD-43 · PD-44 · PD-45 · PD-60/61 · PD-72) плюс 29 новых PD-79…PD-107. Первые в очереди зоны — фикс-лист приёмки, порядок там же. - **P2 отработала очередь приёмки P1 целиком плюс ДВА собственных адверсариальных ревью** (05.08) — @@ -50,9 +50,14 @@ (`87be7b9`/`6469479`). Строки регистра формулировку не завышали — они честно говорят `fixed(P1, дерево сессии)`. -**Живой уязвимости приёмка не нашла.** Найденное — 29 строк регистра **PD-79…PD-107**: одна major -(доступность входа, PD-80), остальные minor/info. Лендинг не блокирует ничего; три строки блокируют -первый реальный деплой и постройку воркера — названы в фикс-листе. Метод панели: семь линз с +**Уязвимости с потерей денег, данных или захватом сессии приёмка не нашла** — и это ровно то, что +фраза означает; отказ в обслуживании при этом ЕСТЬ (PD-80, класс `vuln`, воспроизведён на бинаре). +Найденное — 29 строк регистра **PD-79…PD-107**. Счёт весов ПОСЛЕ эрраты (скриптом по колонкам): +открытых 37 — **3 major** (PD-80 доступность входа · PD-95 и PD-105 подняты эрратой как задание +эмиттеру), 14 minor, 20 info. Лендинг не блокирует ничего. Блокируют дальнейшее ТРИ поимённо: **PD-91** — первый реальный +деплой (установка по наброску даёт нестартующий юнит) · **PD-79** — постройку воркера (строковый +`"null"` = ноль денег на пути расчёта) · **PD-95** — выдачу промта эмиттера (доккоммент несёт +снятую форму транспорта). Метод панели: семь линз с зажатыми промтами (отчётные доки зоны им запрещены), затем адверсариальный опровергатель на КАЖДУЮ находку весом minor и выше — 20 подтверждено, 2 опровергнуто, плюс мои собственные замеры. @@ -111,7 +116,7 @@ **Вынесено владельцу — два вопроса.** (1) Сроки сессии: не заходивший месяц человек увидит экран входа; если это против замысла — одна переменная `TM_PLATFORM_SESSION_MAX_AGE` и явная запись -отклонения в §13. (2) **Новое, из PD-105:** фри-тир печатается НЕАУТЕНТИФИЦИРОВАННЫМ потоком по $5 +отклонения в §13. (2) **Новое, из PD-104:** фри-тир печатается НЕАУТЕНТИФИЦИРОВАННЫМ потоком по $5 за каждую новую подтверждённую пару `(provider, subject)`, и агрегатного потолка нет нигде — нужен ли суточный лимит грантов и счётчик аномалий до открытия беты. @@ -129,18 +134,19 @@ «книги в `~/books`». 5. **PD-106 — админ-CLI, единственный писатель денег в дереве, не имеет ни одного теста** — включая правило «после коммита нельзя отчитаться провалом», которое сам же называет несущим. -6. **PD-95 — ПЕРВЫМ в промт эмиттера, и это эррата к самой приёмке.** Транспортная история зоны - устарела против D39.106 в двух местах: доккоммент `events.go` предлагает переезд на fd/сокет - (в `research/25` — 0 голосов), а секция журнала «Транспорт потока событий» доказывает «остаётся - stdout», опираясь на PD-59, который тем же D39.106 п.3 объявлен superseded вместе с пайп-путём - `supervisor.go` («дев-режим»). Ратифицированная форма — `events.jsonl` в каталоге книги, который - платформа ТЕЙЛИТ, а движок поднимается транзиентным systemd-юнитом и платформе не ребёнок. - **Я это при лендинге пропустил и в первой редакции PD-95 сам сослался на снятый PD-59** — - поймано вопросом владельца 07.08, а не процессом; секция журнала помечена superseded, PD-95 - переписан, PD-92 понижен до info (дефект дев-пути), PD-105 повышен (при тейле файла повторная - доставка строк — норма, значит норматив «дубль не ошибка» буквально верен), PD-60 - переформулируется вместе со строкой 103. -7. Остальное — по весу строк. +6. **PD-95 — переписать доккоммент `events.go:6-12` под форму D39.106, и это ЕДИНСТВЕННОЕ, что тут + осталось на зону.** Ратифицированный транспорт: `events.jsonl` в каталоге книги как + outbox-проекция коммитов SQLite, платформа его ТЕЙЛИТ, движок — транзиентный systemd-юнит и + платформе не ребёнок; «родитель + пайп» и «выделенный fd» отвергнуты с нулём голосов + (`research/25` §Форма). Секцию журнала про stdout и строки PD-92/PD-105/PD-60 уже пере-поставил + я — тебе их не трогать. Срок: ДО того, как владелец выдаст промт эмиттера, иначе та сессия + прочтёт доккоммент как задание. +7. **PD-100** — колбэк глотает ошибку стора и ошибку discovery, репортя их обычным отказом. Это + класс PD-5, который зона закрыла в `auth/`, но не в `login/`. +8. **Граница пака — жёсткая, это не «по весу строк».** НЕ трогать: **PD-92 · PD-93 · PD-96 · + PD-99 · PD-102 · PD-105 · PD-107**. Все они латентны за воркером и эмиттером, и правка сейчас + означает угадывание формы, которую задаёт строка 103 единого бэклога. Остальные открытые строки + реестра — тоже не в этом паке: он закрыт списком выше. **Опровергнуто приёмкой — включая свои промахи (дисциплина «заявление=команда» действует и на приёмку).** @@ -867,6 +873,16 @@ research/23 §2 + запрет INFO-денег), а словарь строки - **Источник цифр.** Поток событий денег не несёт и не должен (кадр `ceiling` — только факт), поэтому платформа метрит из `tmctl status --json` (`committed_usd`) на границах попыток и на ре-синке; хранит целыми микро-долларами в леджере (`credit_ledger`, миграция `00007`). +> ⚠ **АБЗАЦ НИЖЕ SUPERSEDED — D39.110 п.2(б) (07.08).** «Платформа владеет `book.yaml` и правит +> `ceilings.book_usd`» отменено: потолок принадлежит ПРОГОНУ и едет аргументом прогона (движку это +> ещё предстоит уметь — строка 145 единого бэклога), а не постоянной записью в конфиге книги, иначе +> пользовательское число оседает в данных движка против D39.81/D39.85. И это НЕ «политика платформы, +> не кнопка на экране»: владелец 07.08 решил обратное — управляемая шкала В ИНТЕРФЕЙСЕ, от минимума +> до доступного остатка, в ГЛАВАХ (строка 126). Верным в абзаце остаётся только проверенный факт: +> `Ceilings` в `BriefHash` не входит, поэтому смена потолка не двигает снапшот и не вызывает ре-билл. +> ⚠ Помечено при повторной верификации: эррата 07.08 применила правило «грепать зонный вывод на +> supersede» к транспорту и пропустила его здесь же, на потолке. + - **Поднятие потолка — политика платформы, не кнопка на экране.** Платформа сама владеет `book.yaml`, поднимает `ceilings.book_usd` и перезапускает прогон. **Проверено кодом, что это безопасно:** `Ceilings` объявлен в `backend/internal/config/book.go:106`, а в канон `BriefHash`