# Промт платформа-сессии: РАННЕР — транзиентные юниты · реконсилятор · очередь · первые ручки /v0 **Выдан 08.08.2026, оркестратор №15, по слову владельца 08.08 (D39.119; санкция направления — D39.107 п.3(3)).** Ты — платформа-сессия. Зона записи: `platform/` + зонный журнал `platform/docs/platform-PROGRESS.md` (итоги/пинги ТОЛЬКО туда, в `docs/PROGRESS.md` не пишешь — D39.100). **НЕ коммитишь** — дерево готовишь, лендит оркестратор; своё в git-индексе не держи (стейдж = риск чужого коммита). **Деньги: $0** — LLM-вызовов нет; PostgreSQL стенда — рецепт без root в `platform/docs/STACK_DECISIONS.md`. ⚠ Живые соседи по дереву: полигон эксп-22 (`eval/`, `docs/experiments/22-*`) и, возможно, бэкенд-пак «блокеры контракта» (см. §Координация) — чужого не трогать и не «прибирать» (инцидент D39.113: откачено семь файлов, шесть потеряны). **Пространства имён:** «строка N» = ЕДИНЫЙ БЭКЛОГ `docs/PROGRESS.md` (таблица «Бэклог») · «PD-N» = `platform/docs/DEFECT_REGISTER.md` · «П-N» = `platform/BACKLOG.md`. **Первый деливерабл — эхо-блок ≤10 строк ПЕРВЫМ СООБЩЕНИЕМ сессии** (скоуп · инварианты · не-делать; подтверждения не жди — работай дальше). ⚠ Все `file:line`/якоря промта — ОТПРАВНЫЕ ТОЧКИ, код первичен: протухший якорь — сверка, не блокер. ## Онбординг: какую проблему решаем и что решит твой результат Платформа — SaaS control plane над движком перевода: пользователи/кредиты/HTTP уже стоят (P0–P3 приняты, D39.107/109/114), но ПРОГОН движка платформа пока умеет запускать только дев-пайпом (`internal/ingest/supervisor.go` — явный DEV MODE). Ратифицированная форма шва — D39.106: движок = **транзиентный systemd-юнит на прогон** (платформа НЕ родитель), события — `events.jsonl` каталога книги (эмиттер движка ещё НЕ построен — строка 103, промт будет отдельно), платформа ТЕЙЛИТ с курсором, а ремонт-канал — `tmctl status --json` (уже существует и читается твоим `resync.go`). Твой пак строит ПРОДОВУЮ половину раннера и первые контрактные ручки — после него фронт сможет говорить с живой платформой, а не моками, не дожидаясь эмиттера. Карта чтения (≤5): `platform/README.md` + зонный журнал (шапка; там же — отчёты P0–P3, вкл. замер PD-91) → `docs/research/25-*.md` (§Форма · §Обязательные механизмы, включая абзац «Опс:» внутри неё — читать ПЕРЕД любым кодом стыка) → D-лог грепом: D39.106 · D39.110 · D39.115 п.4 (форма run-options/CeilingBounds) → контракт `docs/architecture/14-api-contract/` (openapi 0.2.0 + компаньон 2.14–2.16) → реестр `platform/docs/DEFECT_REGISTER.md` (открытые PD-строки твоих поверхностей; счёт — `python3 docs/scripts/counts.py`). ## Работы 1. **Транзиентный systemd-юнит на прогон**: `Restart=no`, SIGTERM (D39.106 §2); щедрый `TimeoutStopSec` (research/25 §Форма); cgroup-лимиты прогона — ответ PD-13 живёт здесь (D39.106 §3). **Privilege-модель реши ДО постройки** — research/25 называет два варианта: linger-пользователь либо узкое polkit-правило; зафиксируй выбор в `STACK_DECISIONS`. Свойства юнита меряй исполнением на стенде без root — метод замера `systemd-run --user` уже отработан на PD-91 (P3, зонный журнал). Пиннинг прогона к версионированному пути бинаря движка + резюм другой версией только явным флагом (строка 139). 2. **Очередь River + воркер** (П-3/П-7): пин подтверждён — добавь в go.mod; гард «один живой прогон на книгу» (`runs_one_live_per_book`) — исполнением; **холд ДО спавна** на сумму потолка (PD-79 закрыт в P3 — путь открыт), интеграция с юнитом п.1. 3. **Реконсилятор** (строка 138): на КАЖДЫЙ выход юнита (ExecStopPost-маркер/D-Bus — реши сам) и на БУТЕ — перезапуск прерванных прогонов; источник истины на буте = каталоги книг + Postgres, НЕ состояние systemd (research/25). До появления эмиттера live-статус добирается периодическим `status --json`-резюнком (твой `resync.go`) — честно, с меткой давности. 4. **Тейлер `events.jsonl`** — строится против словаря `platform/internal/ingest/events.go` (словарь = ПРЕДЛОЖЕНИЕ платформы движку; сам ТРАНСПОРТ ратифицирован D39.106) и лежит наготове: курсор `(engine_run_id, seq)` коммитится в ОДНОЙ транзакции с эффектом (контракт `Sink` + `run_attempts.last_seq` уже это предвосхищают); файла пока нет — тейлер обязан спокойно ждать его появления. **Ратификация PD-105 (этим промтом, D39.119): доставка at-least-once, ДУБЛЬ `seq` = НОРМА повторного чтения — декодер принимает его идемпотентно, БЕЗ фатала;** тот же `seq` с ДРУГИМ payload = карантин прогона (research/25). Реестр предписывал ратифицировать это «вместе с промтом эмиттера» — девиация осознанная (тейлер-сторона строится сейчас); строку PD-105 реестра обнови этим паком. Дев-пайп `platform/internal/ingest/supervisor.go` не удаляется — остаётся дев-режимом; `resync.go` — твой резюнк-канал. 5. **Первые ручки `/v0` по контракту 0.2.0** (П-1/П-5; гейт «ждёт ратификации» снят D39.115): библиотека/карточка книги · `GET /books/{id}/run-options` → `CeilingBounds` (максимум = `Balance` КАК ЕСТЬ — ⚠ НЕ «минус Reserved», это вычитание дважды, D39.115 п.2а; `max_chapters` отдаётся УЖЕ подрезанным, клиенту подрезать второй раз запрещено) · старт прогона с обязательным `ceiling_chapters` (потолок в USD передаётся движку аргументом прогона — см. §Координация) · `GET /usage` · статус/прогресс прогона из read-model. Формы ответов — СТРОГО спека; расхождение спеки с твоим кодом = вопрос оркестратору, не правка спеки. **Две границы, размеченные явно:** (а) **интейк книг** — библиотека обязана читать книги, заведённые ЛЮБЫМ путём (дев-скрипт/руками в каталоге + строка read-model; заведи такой скрипт как дев-инструмент); сам `POST /books` (multipart-загрузка) бери ТОЛЬКО если ложится чисто, иначе — явная строка зонного бэклога с обоснованием, ручки сдаются без него; (б) **пересчёт «главы→доллары»**: движковой поверхности оценки $/глава НЕ СУЩЕСТВУЕТ — на бету источник = конфиг-константа платформы (правит оператор; дефолт возьми из cost-model `docs/experiments/08-cost-model-v2.md`, поделив на главы, с комментом-провенансом), НЕ выдумывай движковую поверхность и НЕ ходи в SQLite движка; потребность в честной движковой оценке — строкой зонного бэклога, оркестратор заведёт её движку. 6. **Реестр PD:** возьми строки, чья латентность снимается ЭТИМ паком (PD-99 — argv с деньгами/book-id на INFO при появлении воркера — обязательно; остальные сверь сам по реестру и возьми/оставь с обоснованием). Строки эмиттер-стороны (PD-60/61) НЕ трогать — они задание движку. **Вне скоупа:** эмиттер (движок, строка 103) · uncertain-эскроу/ночная сверка (строки 136/137 — следующий денежный промт) · SSE на фронт · SPA-отдача. **Инварианты:** движок дёргается ТОЛЬКО процессами (никаких импортов backend) · живой SQLite движка не читать (D39.85) · `book.yaml` платформа НЕ правит (D39.110). ## §Координация с бэкенд-паком (живой шов) Параллельно (возможно) идёт бэкенд-пак «блокеры контракта» (промт `docs/BACKEND_CONTRACT_BLOCKERS_SESSION_PROMPT.md`): он строит потолок-аргумент прогона (строка 145), пофазный прогресс в `status --json` (99), манифест глав (100) и экспорт банка (125). Правило до его лендинга: свою логику доводи ДО шва целиком, сам шов — за узким интерфейсом с дев-стабом и пометкой `TODO(145)`/`TODO(99)`… (стаб = заглушка твоего интерфейса, НЕ имитация wire-формы движка — форму молча не выдумывай). Ручка старта прогона сдаётся полной, передача потолка движку — через такой интерфейс. Форму ПРИНИМАТЬ только из HEAD (залендённого); чужое незакоммиченное дерево `backend/` читать для сверки МОЖНО (норма D39.115 п.3), но копировать его форму нельзя — расхождение твоего стаба с их черновиком = вопрос, не молчаливая подгонка. Писать в `backend/` нельзя. ## Самопроверка и СТОП Мандат 12.07: ревью ИСПОЛНЕНИЕМ (код + живые пробы на собранном бинаре + systemd-run-замеры). Дифф `^func Test` до/после — исполнением, не памятью; батарея `make check` зелёная целиком с живым PG (скипов ноль — рецепт в STACK_DECISIONS); `make vuln` чист. По правилу зоны: закрытая PD-строка = запиненное свойство (тест поимённо). **Канал вопросов:** непонятно / конфликт промта с кодом-доками-спекой / privilege-модель упирается в стенд → СТОП по ЭТОМУ пункту (остальные продолжай), вопрос — строкой в зонный журнал плюс устно владельцу (он релеит оркестратору); НЕ тихая интерпретация. Отчёт в зонный журнал: по работам с `file:line` · девиации · открытые PD-строки после пака (счёт скриптом) · каждое ЧИСЛО отчёта — с командой, которой получено (приёмка пере-ранит). **СТОП — приёмка оркестратора** (адверсариальная, со своими посадками).