13 KiB
Промт платформа-сессии: РАННЕР — транзиентные юниты · реконсилятор · очередь · первые ручки /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).
Работы
- Транзиентный 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). - Очередь River + воркер (П-3/П-7): пин подтверждён — добавь в go.mod; гард «один живой прогон на книгу» (
runs_one_live_per_book) — исполнением; холд ДО спавна на сумму потолка (PD-79 закрыт в P3 — путь открыт), интеграция с юнитом п.1. - Реконсилятор (строка 138): на КАЖДЫЙ выход юнита (ExecStopPost-маркер/D-Bus — реши сам) и на БУТЕ — перезапуск прерванных прогонов; источник истины на буте = каталоги книг + Postgres, НЕ состояние systemd (research/25). До появления эмиттера live-статус добирается периодическим
status --json-резюнком (твойresync.go) — честно, с меткой давности. - Тейлер
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— твой резюнк-канал. - Первые ручки
/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-modeldocs/experiments/08-cost-model-v2.md, поделив на главы, с комментом-провенансом), НЕ выдумывай движковую поверхность и НЕ ходи в SQLite движка; потребность в честной движковой оценке — строкой зонного бэклога, оркестратор заведёт её движку. - Реестр 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-строки после пака (счёт скриптом) · каждое ЧИСЛО отчёта — с командой, которой получено (приёмка пере-ранит). СТОП — приёмка оркестратора (адверсариальная, со своими посадками).