diff --git a/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md new file mode 100644 index 0000000..af6bf6f --- /dev/null +++ b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md @@ -0,0 +1,273 @@ +# Observatory: четыре этапа создания полного real-time Perception-профиля + +Дата: 2026-09-01; обновлено 2026-09-02 00:41 МСК. Текущая цель — переносимые полные профили и снижение задержек всей цепочки; допустимый лабораторный overload не блокирует разработку и не выдаётся за real-time PASS. В двух новых source-paced пилотах с перекрытием CPU и последовательного GPU этапа получены 128/128 результатов без drops; source→local receiver p95 143.32/153.44 ms, p99 198.22/194.25 ms. Среднее ожидание очереди 7.20/8.31 ms против 13.65/25.48 ms в serial-контролях. Это перспективный экспериментальный scheduler, не квалификация и не замена рабочего runtime. Этап 1 частично выполнен; этапы 2–4 не начаты. Static-obstacle слой и coarse `hard_surface` остаются достаточными для сельского прототипа; профиль не сводится к одной модели. + +Текущий evidence: [отчёт этапа 1](../experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md), [ADR 0049](adr/0049-stream-first-perception-profiles.md), [candidate manifest](../config/perception/k1-perception-ddrnet39-rfdetr-tgs-prototype-v1.json). Запрет full-source preload закреплён в новом контракте; старый batch materializer пока не удалён и продуктовый путь не переключён. + +## Цель и граница завершения + +Собрать отдельный самостоятельный Docker-профиль полного восприятия рига: DDRNet-39 GOOSE + RF-DETR native + LiDAR-ассоциация/метрические расстояния + TGS/costmap + temporal/motion + диагностическая оценка препятствий и mission-policy. Совместимый источник поступает потоком на выделенный Worker; все выходы рассчитываются в этом запуске, без подмешивания ранее рассчитанных масок, детекций, local-surface или threat-ledgers. Запись подаёт наблюдения по исходному времени с темпом 1× и заменяет физический источник, но не меняет вычислительный граф. + +Сценарий владельца: записывать множество маршрутов K1 с камерой, точками и pose; в Observatory последовательно применять разные профили и сравнивать результаты; затем выбрать проверенную версию того же профиля в будущей live-миссии с зарегистрированным оборудованием. Конкретная запись — вход запуска, а не зашитый компонент Docker. Размер коллекции (в том числе 500 записей) не требует 500 приложений или 500 исполняемых адаптеров. Во время будущего движения профиль обрабатывает новые живые наблюдения, а не воспроизводит старые решения для маршрута. + +Первый результат — один полный, измеренный на RTX 4090 прототип с общим runtime и потоковыми результатами, пригодный для последующей проверки на полигоне. Управление моторами, автопилот, построение маршрута и реализация всего конфигуратора миссии в этот прототип не входят. EoMT-L Cityscapes сохраняется как отдельный резервный вариант; его упаковка/оптимизация не блокирует первый профиль и не запускается рядом с DDRNet. Сборка Docker и совпадение digest не являются доказательствами real-time; успешный replay не является допуском к автономному движению. + +Приёмка первого прототипа требует: самостоятельного образа; реального расчёта всех заявленных слоёв; одного live-compatible контракта для replay и будущего физического источника; воспроизведения нескольких совместимых записей без правки кода; bounded latency/queues/memory; явных unknown/degraded состояний; сохранённого отчёта производительности и обнаруженных ошибок. Отсутствующий сейчас беспилотник не блокирует приёмку replay-прототипа, но physical-live, качество в поле и actuation остаются явно непроверенными. + +## Авторитетный контекст и подтверждённое CURRENT + +Рабочий репозиторий: `/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory`. На момент обзора: ветка `codex/m5-1-observatory`, HEAD `7025e173a3370a1b70afaad8579db20903436157`, множество существующих tracked/untracked изменений. Выводы относятся к прочитанному рабочему дереву, не только к HEAD. Чужие изменения сохраняются. + +Источники и их назначение: + +- [Последний отчёт](/Users/dcconstructions/Desktop/MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md) — история предыдущих запусков и актуализированная цель полного профиля. Исторические измерения не являются новой проверкой текущего состояния Worker. +- [Предыдущая архитектурная итерация](/Users/dcconstructions/Desktop/MISSING_CORE_OBSERVATORY_DOCKER_LABS_ARCHITECTURE_2026-09-01.md) — история и идеи, не распоряжения к выполнению и не актуальное подтверждение готовности. +- [Правила репозитория](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/AGENTS.md), [существующие gates проекта](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/docs/01_IMPLEMENTATION_PLAN.md) — действующие ограничения. Этот план не открывает навигационные, actuator- или quality/truth-gates проекта. +- `/Users/dcconstructions/Desktop/CODEX_V5` — прочитаны все пять документов. Применены разделение CURRENT/TARGET, приоритет цели и доказательств над процедурами, этапы с проверяемым выходом и один поддерживаемый ExecPlan. Шаблоны не копируются поверх правил проекта. +- Последние уточнения владельца от 2026-09-01 имеют приоритет: один активный полный профиль, внутри него детектор + выбранная сегментация + LiDAR/TGS; EoMT и DDRNet остаются альтернативами. Не переносить старое ошибочное ограничение «одна модель/AI-процесс» на состав полного профиля. + +Проверенная по локальному коду карта: + +| Участок | CURRENT | Следствие для TARGET | +| --- | --- | --- | +| Portable definition / preflight | Есть идентичность source/model/executor и проверка совместимости, но нет полного timing-контракта и измеренного real-time допуска; `ready` в основном структурный | Сохранить идентичность и admission, добавить отдельную квалификацию конкретного профиля на конкретном runtime/hardware | +| Передача источника / runtime | Полная материализация → выполнение → финальная публикация | Инкрементальный data plane с ограниченными буферами, без обязательной подготовки всей записи | +| Installed LAB package | Одноразовые контейнеры: prepare → весь EoMT → весь DDRNet → assemble | Сначала один постоянный полный DDRNet/RF-DETR/LiDAR/TGS runtime; EoMT — отдельный будущий вариант, без зависимости DDRNet от его результата | +| Модельные адаптеры | Все кадры, PNG/маски/overlay и итоговые архивы на критическом пути | Обработка поступающих наблюдений и выдача результата до окончания источника; архивирование не задаёт темп inference | +| Backend / Worker | В claim есть глобальный запрет второго активного job; Worker 006 зашит в части контракта | Эксклюзивность и fencing на уровне `worker_id`; не глобальный запрет работы независимых Worker | +| Frontend | Выбор setup и terminal job/result; нет достаточного контракта потокового состояния | Общие состояния и renderer capabilities, без отдельного микроприложения для каждой модели | +| Ранее существовавшие эксперименты | Есть pacing 1×, bounded queues, freshness/age и multirate измерения | Переиспользовать проверенные механизмы, но не совмещать EoMT с DDRNet или разные профили; RF-DETR и DDRNet входят в один полный профиль. Чужие бюджеты автоматически не копируются | + +Опорные файлы для продолжения: + +- [Portable contracts](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/portable_run_definitions.py), [runtime](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/portable_worker_runtime.py), [source transport](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/worker_http_transport.py). +- [Queue / ownership](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/recorded_jobs.py), [Worker agent](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/worker_agent.py), [preflight API](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/web/observatory_api.py). +- [Installed runner](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/installed_lab_package_runner.py), [combined package builder](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/worker/observatory_portable/promote_installed_lab_v1_package.py). +- [EoMT adapter](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/worker/observatory_portable/run_portable_lab_v1_eomt_component.py), [DDRNet adapter](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/worker/observatory_portable/run_portable_lab_v1_ddrnet_component.py). +- [Observation graph](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/perception/graph.py), [recorded source](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/perception/recorded_source.py), [E9 runner](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/worker/run_e9_multirate_perception.py), [E21 envelope](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/e21_realtime_envelope_profile.json). +- [Equipment/capture compatibility](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/sessions/equipment.py), [Observatory workspace](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx). + +Из последнего отчёта: источник `20260828T130511Z_viewer_live` содержит 6830 кадров за 808.779495667 s, средняя частота ≈8.4448 FPS. Остановленный запуск после примерно 32 min 54 s ещё не дошёл до DDRNet/публикации. Это свидетельство непригодности прежнего полного пути для поставленной задачи, но не изолированный benchmark самой модели. + +Последующий read-only аудит 2026-09-01 проверил Docker inventory, mounts и фактические installed manifests на Worker 006 через strict-pinned `mission-gpu`. Portable M4.9 содержит TGS и `models: []`; LAB V1 выполняет `prepare → EoMT → DDRNet → assemble`, без detector/geometry/threat stages. Legacy perception Worker и Triton существуют отдельно, со значимыми host mounts; это не самостоятельный полный portable-профиль. Никакие контейнеры при аудите не запускались и не останавливались. + +Скриншот M4.9T5 показывает композицию результатов: собственный CPU TGS, отдельный M4 detector/geometry/threat и заранее рассчитанный E47/EoMT. Отдельный [RF-DETR reference runtime](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/perception/m48s_reference_graph_runtime.py:209) реально собирает geometry, temporal, motion, rolling и threat. Сохранённый [M49 integrated result](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/.runtime/m49-integrated-12fps-003/result.json:72) сообщает 4489/4489 кадров, 11.860865 FPS и p95 совместной готовности 46.825886 ms. Это historical RF-DETR + CPU TGS shadow на подготовленных входах, не полный новый профиль: TGS не меняет graph state, EoMT там не вычисляется, `local-surface.npz` подготовлен заранее. + +Ближайший сохранённый [multirate candidate](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/config/perception/lab-v1-vegetation-integrated-multirate-phased-shadow-v3.json:12) добавляет DDRNet 6 Hz к RF-DETR/TGS timeline 12 Hz с phase offset 40 ms, но `semantic_output_persisted=false`: это исходная точка исследования нагрузки, а не доказанная сквозная реализация нового продукта. + +Во время read-only проверки на Worker также работали `sentinel-frigate` и `sentinel-ollama` с GPU DeviceRequests; общая занятая VRAM составляла 9256 MiB. Это не доказывает их одновременный inference, но чистое GPU-окно не установлено. Перед измерением требуется согласованное освобождение ресурса; этот план не разрешает самостоятельно останавливать сервисы другого продукта. + +## Жёсткие границы и принятый TARGET + +Уточнение владельца 2026-09-02 (МСК): проект — экспериментальная платформа +переносимых профилей, применяемых к разным совместимым записям. Текущий приоритет — +снижение задержек всей цепочки, прозрачное измерение и оптимизация runtime, +IPC/сети, копирований и оркестрации. Вычислительно тяжёлый профиль не удаляется +из-за FAIL на 4090: результат сохраняется вместе с hardware/transport-specific +квалификацией. Возможен перенос на более мощный Worker или бортовой компьютер. +Локальное размещение устраняет внешний сетевой участок, но не само по себе +декодирование, внутренний IPC, очереди и вычисления. + +Лабораторный эксперимент с ограниченной перегрузкой допустим и не блокирует +разработку упаковки/общего runtime. Разделяем **функциональную готовность**, +**готовность к лабораторным сравнениям** и **real-time qualification на конкретной +связке profile/config/hardware/source/transport**. Бюджеты 125 ms и остальные +исходные критерии остаются измерительными ориентирами, а FAIL не превращается +в PASS. По-прежнему обязательны bounded memory/queues, учёт drops/unknown, +исходный clock 1×, отсутствие подмены старых данных новыми и отсутствие actuation. + +- Текущий аппаратный baseline — один Worker 006 с RTX 4090, один активный полный профиль одного источника. RF-DETR и DDRNet являются компонентами этого профиля и могут быть прогреты одновременно; GPU-работа в первом прототипе подчинена одному сериализованному scheduler. CPU-геометрия/TGS и транспорт имеют свои ограниченные очереди, не создавая второй конкурирующий AI-профиль. Нет EoMT+DDRNet вместе, фоновых моделей, обучения или параллельных benchmark. Неактивный профиль не удерживает GPU. Новый профиль не стартует до подтверждённого освобождения предыдущего. +- Один беспилотник обслуживается одним независимым Worker. Масштабирование на десять устройств означает десять Worker, а не десять потоков на 4090. Сейчас не строится полноценная система управления флотом; контракты и тесты не должны закрепить глобальный singleton. +- Профиль — полный вычислительный граф и его входные/выходные требования, а не одна модель. DDRNet и EoMT — альтернативные сегментационные ветви разных профилей. Общий runtime/SDK и инфраструктурный агент допустимы; профильные backend/frontend приложения — нет. На первом этапе нужен один новый полный Docker-профиль, не обязательная разработка сразу двадцати вариантов. +- Переносимы образ/контракт/конфигурация, а не произвольный hardware performance claim. RTX 5090 и Apple Silicon не являются условиями успеха. Для иной GPU/платформы нужна отдельная проверка; CUDA-образ не объявляется автоматически совместимым с Metal. +- Запись и live различаются адаптером входа, не реализацией inference. Реальная совместимость определяется объявленными каналами, форматами, временем, калибровкой и capture-параметрами, не названием LAB или единственным session ID. +- Работа остаётся в локальном контуре Mission Core + Worker 006; нет Synology/external-server rollout и deploy-canon workflow. План не является командой на запуск Worker или изменение оборудования. На Mac нет модельной нагрузки, тяжёлых параллельных работ и новых временных серверов; канонический сервис 8000 сохраняется. +- Существующие записи, raw evidence, секреты, результаты и рабочие изменения сохраняются. Нет управления движением, изменения scanner-протокола или самостоятельного запуска физического сканирования. Старые доказательства не переименовываются в новые успешные испытания. + +Предлагаемая схема имён, согласованная с обязательным namespace `ndc-`: + +| Название профиля в приложении | Docker image | Экземпляр на Worker 006 | +| --- | --- | --- | +| K1 Perception — DDRNet-39 + RF-DETR + TGS | `ndc-k1-perception-ddrnet39-rfdetr-tgs:prototype-v1` | `ndc-k1-perception-ddrnet39-rfdetr-tgs-worker006` | +| K1 Perception — EoMT-L + RF-DETR + TGS, резервный TARGET | `ndc-k1-perception-eomt-rfdetr-tgs:` | `ndc-k1-perception-eomt-rfdetr-tgs-worker006` | + +Машинный profile ID стабилен и связан с display name; runtime выбирается по sealed manifest/image digest, не только по изменяемому tag. Существенное изменение весов, preprocessing, output labels, precision или execution policy меняет версию профиля и требует нового свидетельства. `K1` в названии описывает capture-совместимость, но не должен зашивать K1 в общий runtime. + +Первый прототип поставляется одним самостоятельным образом и запускается одним контейнером: runtime, обе модели, TGS, preprocessing/postprocessing, конфигурация и manifest находятся внутри образа. Нет зависимости от чужого Triton, checkout, скрытого host-cache, готовой LAB или скачивания моделей на первом запуске. Внутренние supervised процессы/изолированные Python environments допустимы, если решают одну задачу восприятия и управляются общим lifecycle; broker, БД и приложение в этот образ не добавляются. Снаружи только Docker/NVIDIA runtime, входной поток/запись, выходы и явно переданные секреты. Shared base layers допустимы для будущих профильных образов. Сохраняются ownership labels `com.nodedc.product`, `com.nodedc.stack`, `com.nodedc.role`, `com.nodedc.managed-by`. Текущие контейнеры не переименовываются этим планом. + +## Контракт первого полного профиля + +| Слой | Обязательный выход | Граница интерпретации | +| --- | --- | --- | +| DDRNet-39 GOOSE | Semantic mask, существующее coarse material mapping, freshness и исходные class IDs для evidence | В первом сельском прототипе `hard_surface` допустим без разделения асфальта/тротуара/велодорожки; геометрическое препятствие всё равно блокирует | +| RF-DETR native | Объекты, class, confidence, bbox и source frame identity | Person/cat/dog и существующие классы; точное название статического препятствия не требуется, дополнительный bollard-классификатор не нужен | +| LiDAR + calibration + pose | 3D support, расстояние с определённым estimator/frame, неизвестные геометрические препятствия и связь с детекциями | Нет подходящих точек/калибровки/синхронизации — range unavailable, а не придуманное расстояние или free | +| Temporal / motion | Track identity, оценка движения, current/held/stale/unknown | Тип объекта не доказывает движение: стоящая машина и движущийся человек требуют измерения во времени | +| TGS + rolling geometry | Ground support, occupied, rejected, unobserved; локальная costmap и свежесть каждой ячейки | Ground support не равен traversable; map может запретить, но сама не выполняет объезд | +| Fusion / policy shadow | Общая scene, согласованные слои, объяснимый allowed-candidate/high-cost/blocked/unknown и advisory events | Не direct motor/control commands; unknown/stale не создают разрешение двигаться | + +Входы: camera frames/encoded chunks, registered point increments, pose, intrinsics/extrinsics, coordinate frames и timestamps с clock mapping. Нужно различать sensor→camera калибровку и будущую sensor→vehicle/body калибровку. Для прототипа виртуальный footprint допускается только с явной отметкой simulation; реальный зазор до корпуса не заявляется до измеренного mount/vehicle profile. + +Решение владельца для первого сельского прототипа: используем существующий coarse `hard_surface` (`asphalt`, `sidewalk`, `bikeway`, `cobble`) как допустимый материал. Разделение дорог, тротуаров и велодорожек, городские правила движения, дополнительная сегментационная модель и обязательный новый road-only классификатор не нужны и не блокируют реализацию. Сохранять исходные class IDs полезно для evidence, но создавать отдельную fine-grained policy сейчас не требуется. Остальные материалы определяются явным выбранным preset/config; слово «сельский» само по себе не разрешает все грунты/растительность. Camera semantics никогда не снимает occupied/unknown запрет геометрии. + +Для столбиков и других неподвижных препятствий переиспользуется существующее представление `static_obstacle` / `static.unknown`, уже присутствующее в vocabulary и визуальном слое; точное имя предмета не требуется. Пользователь ссылается на сохранённый RAV004 как имеющий это поведение. Задача нового профиля — воспроизвести этот слой из текущего потока и проверить его, а не изобрести ещё одну taxonomy, обучить распознаватель столбиков или загрузить старые masks вместо вычисления. Геометрическое препятствие сохраняется независимо от того, нашёл ли detector узнаваемое имя. + +Профиль содержит измерительные модели/алгоритмы и возможности policy; выбранное правило миссии, оборудование, footprint и thresholds входят в effective run configuration. Пара `(immutable profile + effective mission/equipment configuration)` одинакова в Observatory и последующем live; изменение значимого параметра требует нового сравнения/квалификации. Запись не содержит «разрешение будущему автопилоту», только воспроизводимые входы и свидетельство проверки. + +## Этап 1 — Полный состав профиля, контракты и технический baseline + +**Цель:** закрыть состав первого полного профиля и оставшиеся технические разрывы до изменения продуктового пути; получить исходную точку для измерений на 4090. + +**Вход:** локальный обзор, оба отчёта, существующие pinned weights и source-paced эксперименты. Новые измерения требуют доступного выделенного Worker без другой AI-нагрузки. + +**Работа:** + +- Завершить матрицу CURRENT → TARGET для backend, frontend, Worker, recording/live adapters, model runtime и хранения. Зафиксировать keep/replace/deprecate, не переписывая устойчивые admission/publication механизмы. +- Описать versioned observation/result contracts: source/stream/epoch/sequence, timestamp/clock domain, payload formats, camera/cloud/pose, calibration и coordinate-frame references; на выходе все слои таблицы выше. Для полного первого профиля cloud и pose необходимы. Не привязывать совместимость к одному session ID или байтам media-init, не существенным для capabilities. +- Описать lifecycle с одним владельцем Worker, правило переключения профиля, incremental result contract и различие «установлен», «работоспособен», «прошёл real-time квалификацию», «экспериментальный/не прошёл». Состояния availability, qualification и running/busy не сводить в один флаг `ready`. +- Зафиксировать до приёмки численные бюджеты каждого профиля: входной поток, требуемая частота результатов, p95/p99 end-to-end age, допустимые пропуски, очередь, startup/warmup, память и stop-time. Не снижать требования задним числом ради зелёного результата. Неопределённые продуктовые компромиссы выносить владельцу, а не скрывать в scheduler. +- Разделить reusable online algorithms и recorded-only подготовку. Проследить, чем заменяются чтение готового `local-surface.npz`, заранее подготовленные TGS rolling inputs, E47 masks и M4 ledgers. Vendor-registered исходные точки/pose допустимы как вход K1; собственные perception-результаты должны вычисляться текущим запуском. +- Проверить совместимость зависимостей в одном образе: текущий DDRNet использует Python 3.9 / PyTorch 1.13.1 cu117 / super-gradients 3.2.0, RF-DETR — TensorRT 11, TGS — C++. Не объявлять их совместимыми в одном interpreter без проверки. Выбрать минимальную изоляцию внутри одного контейнера либо доказанное преобразование модели с parity check; не менять веса/качество молча ради сборки. +- После согласованного освобождения GPU выполнить короткие baseline компонентов первого профиля последовательно и пилот общего расписания. Разделить decode/preprocess, H2D, inference каждой модели, online geometry/TGS, fusion/policy и доставку результата. Отдельно измерить cold startup и warmed steady state; не начинать с полного старого batch-run. +- Сохранить существующие EoMT artifacts и точный checkpoint. Его отдельное исследование/упаковка — последующий вариант профиля, не обязательная ветка первого прототипа. Не запускать EoMT во время работ DDRNet-профиля. +- Проверить текущие class/score/box-size/FOV фильтры RF-DETR на требования прототипа, включая близкий крупный объект и маленькое животное; наличие имени класса в модели не доказывает достаточное обнаружение. Не менять пороги без новой версии и сравнительного evidence. + +**Результат и evidence:** точный manifest первого полного профиля, карта входов/выходов и owner boundaries, план единого образа с проверенной dependency strategy, численные инженерные критерии и baseline первого состава. Зафиксированы class coverage, distance estimators, unknown policy и отсутствие motor authority. + +**Выход / зависимость:** GO на этап 2 после фиксации состава, существенных контрактных границ и воспроизводимого baseline. По уточнению владельца от 2026-09-02 performance FAIL на текущем железе не является запретом на развитие лабораторной платформы/упаковки и не требует выбрасывать профиль. На 2026-09-01 выполнены карта/reuse, executable contract, candidate manifest, component baseline и совместный causal pilot полного графа. Дальше измеряем и уменьшаем задержки, исправляем preroll/layered freshness и сохраняем отрицательные результаты; real-time статус выдаётся отдельно, только по факту прохождения критериев. Network whole-path и самостоятельная упаковка относятся к следующему runtime и не объявляются проверенными по локальному collector. Диагностический контейнер с mounts не является runtime этапа 2. + +## Этап 2 — Самостоятельный Docker с полным потоковым вычислением + +**Цель:** один самостоятельный контейнер принимает поток и реально рассчитывает DDRNet, детекции, расстояния, motion, TGS/costmap и policy-shadow; ничего не дорисовывается из старых LAB. + +**Вход:** контракты и baseline этапа 1. + +**Работа:** + +- Реализовать общий lifecycle open/warmup/process/flush/stop, stage interfaces и supervisor. RF-DETR и DDRNet загружаются один раз при активации полного профиля. GPU inference сериализован; CPU TGS/geometry и I/O не блокируют GPU через неограниченную очередь. Разные частоты слоёв задаются явно и измеряются; retained mask не считается новым inference. +- Подключить recorded adapter с исходными timestamp и pacing 1×; live adapter подаёт тот же тип наблюдений без знания длительности/конца записи. Не требовать полного tar/download, конкатенации всей камеры, полного PNG-cache или полного source hash-pass перед первым результатом. Допустить ограниченный декодерный pre-roll для codec dependencies, не просмотр будущих наблюдений моделью. +- Выбрать и проверить бинарный data plane по реальным объёмам video/cloud, CPU cost и latency. Control plane остаётся отдельным. У модели нет произвольного доступа к сети/host; поток приходит через контролируемый proxy/IPC или явно ограниченный transport. Не включать privileged/host-network ради удобства. +- Реализовать online local-surface/geometry и causal rolling TGS из поступивших points/pose. Сохранять неизвестные геометрические препятствия без semantic class. Camera–LiDAR association, distance estimator, track/motion и footprint references выдаются явно; отсутствие поддержки не подменяется нулём/бесконечностью. +- Связать результаты слоёв в общий scene contract во время исполнения, а не только склеить тайминги после завершения. Привязать semantic labels к текущей геометрии с temporal/coordinate validity и bounded TTL. TGS и semantic policy становятся реальными входами диагностического rule evaluation, не только соседними слоями viewer. +- Подключить существующее coarse material mapping и простую advisory policy: `hard_surface` — допустимый материал для первого сельского прототипа; geometry/TGS occupied и missing/stale evidence имеют приоритет над этим допуском. Тротуар и велодорожка не являются отдельными отказными случаями. Не добавлять второй segmenter или новую fine-grained road policy. Допуск поверхности не выбирает объезд и не выдаёт motor commands. +- Сделать ограниченные очереди, явные cadence/drop/TTL правила, backpressure и stop/cancel. Завершение lease, смерть процесса и смена владельца должны прекращать старое исполнение; новый профиль не стартует, пока старый GPU-владелец не освобождён. Restart не воспроизводит накопившийся устаревший live backlog. +- Выдавать результаты и технические метрики до EOF; хранение/overlay/video export не блокируют inference. Для сохранения evidence тоже задаётся ограничение ресурсов и честное состояние при переполнении. Не выдавать повтор предыдущей маски за новое измерение. +- Упаковать первый полный образ с pinned model assets, TGS/runtime и нужными библиотеками. Проверить запуск без developer checkout, host model cache, внешнего Triton и model downloads. Не добавлять backend/БД/broker в контейнер. EoMT остаётся сохранённым отдельным вариантом вне активного первого профиля. + +**Результат и evidence:** короткий replay 1× выдаёт все заявленные результаты до конца источника, память и очереди ограничены. Каждый слой имеет trace от inputs этого запуска; старые E47/M4/local-surface artifacts не предоставляются. Проверяются person/cat/dog, существующее static-obstacle представление без точного имени, допустимый `hard_surface` и препятствие поверх него, missing LiDAR, stale mask, burst/gap/out-of-order/cancel/lease-loss. Synthetic tests на Mac не загружают тяжёлые модели; реальные модельные случаи проверяются на Worker. + +**Выход / зависимость:** GO на этап 3 после подтверждения работоспособности самостоятельного полного образа, streaming lifecycle и GPU ownership. Если полный граф не проходит короткий budget, сначала локализуется причина внутри этапа; FPS одного DDRNet и добавление UI не закрывают этот gate. + +## Этап 3 — Сквозное подключение backend и frontend без LAB-микроприложений + +**Цель:** приложение выбирает совместимый профиль и показывает его работу через общие контракты. + +**Вход:** полный standalone runtime и образ первого профиля из этапа 2. + +**Работа:** + +- Расширить generic registry/preflight/claim: требуемые input capabilities, pinned executor identity, актуальная доступность Worker и соответствующее performance evidence. Совместимость, установленность и real-time квалификация проверяются отдельно; несовпадение capture/weights/runtime/hardware делает прежний допуск неприменимым. +- Привязать leases, fencing, ограничения активности и live/recorded ownership к конкретному `worker_id`. Исключить двойной запуск на одном Worker. Независимые Worker не блокируют друг друга глобальным SQL/константой. Проверить эту независимость лёгкими fake-worker тестами, не параллельными GPU-запусками. +- Интегрировать incremental results/progress/cancel и последующую immutable publication. Потоковое отображение не ожидает terminal archive. Существующие provenance, digest validation и восстановление публикации сохраняются. +- В едином Observatory показать полный состав профиля и понятное название, совместимость источника, effective mission-rule, занятость Worker и qualification status. Один recording можно запускать на разных версиях профиля, один профиль — на разных совместимых recordings. Наличие двадцати профилей не создаёт двадцать приложений. +- Расширить общие renderer/result capabilities: semantic mask, boxes/class/track, LiDAR support/ranges, TGS/costmap, motion и policy-shadow с явной свежестью. Все слои ссылаются на текущий run; исторический overlay разрешён только как явно выбранное сравнение, не скрытый fallback. EoMT и DDRNet не считаются одной ontology. +- Сохранять run matrix с recording/capture/profile/effective mission configuration, техническими результатами и инженерной оценкой ошибок. Подготовить versioned profile reference для будущего mission configurator: он должен выбирать тот же immutable image/config, а не другой «live вариант» с тем же названием. Сам конфигуратор миссии и управление оборудованием в этом этапе не реализуются. +- Применить UI skill и действующие архитектурные/UI документы перед UI-реализацией. Технические counters/p95/drop reasons размещать в соответствующих деталях, не превращать основное рабочее место в консоль отладки. + +**Результат и evidence:** несколько совместимых recordings последовательно запускаются через приложение на одном полном профиле без правки кода; до конца записи видны все слои текущего run. Несовместимый источник и второй профиль на занятом Worker отклоняются. Видимый qualification-status совпадает с evidence; результат и сравнение версий сохраняются после перезапуска. Второй реальный модельный профиль не требуется придумывать ради этого gate: независимость каталога проверяется контрактными fixtures. + +**Выход / зависимость:** GO на этап 4 после интеграционных, контрактных и последовательных browser-проверок общего пользовательского пути. Успешный UI smoke ещё не означает full-session real-time acceptance. + +## Этап 4 — Квалификация полного прототипа на записях и подготовка к полигону + +**Цель:** доказать вычислительную работоспособность полного профиля на 4090, найти его ошибки на записях и передать воспроизводимый прототип для последующего полигона, не объявляя готовую автономию. + +**Вход:** сквозной путь этапа 3; численные критерии заморожены до испытаний. + +**Работа:** + +- Перед каждым профилем/испытанием проверить единственного владельца GPU, версии, питание/ограничения и warmup. Запуски строго последовательные. Сначала bounded canary; полный recording только после его прохождения. Не повторять заведомо неуспешный длинный EoMT-run ради завершения плана. +- Провести full-session replay 1× всего профиля DDRNet + RF-DETR + geometry/motion + TGS + fusion/policy с учётом всех наблюдений. Проверить отсутствие растущего отставания, cadence/age/drop/memory budgets каждого слоя и общего выхода до приложения. Отдельно измерить startup, steady state и export; prepared geometry/masks не выдаются за online вычисление. +- Проверить смысловые сценарии: допустимый `hard_surface` без препятствия и с препятствием, static-объект без уточнения имени, человек/животное, движение и неподвижность, отсутствие LiDAR/pose, истёкшая маска и конфликт семантики с геометрией. Тротуар/велодорожка относятся к принятой coarse категории, а не к отрицательным road-only случаям. Это инженерная проверка сельского прототипа, не общая accuracy и не городской автопилот. Новая разметка/обучение не являются условием первого запуска. +- Проверить другую совместимую запись без изменения прикладного кода и отрицательные случаи: отсутствующий канал, неверная калибровка/формат, изменённые веса, другой hardware. Если второй источник отсутствует, соответствующее доказательство остаётся pending. Проверка другой машины/платформы не симулируется заявлением «это Docker». +- Проверить interruption/reconnect, медленный consumer, burst/loss, stop, lease-loss, restart и публикацию. Проверить live-compatible вход с неизвестной заранее длительностью, без чтения будущего, на том же runtime. Физический live через K1/роутер/беспилотник проводится позже при доступности оборудования и согласованного окна; его отсутствие не блокирует replay-прототип. Целевые 300–500 Mbps не являются доказанным каналом: физический gate потребует uplink/jitter/loss/clock alignment/end-to-end age. +- После приёмки нового пути убрать combined EoMT→DDRNet setup из активного real-time каталога, затем ограниченно вывести устаревшие adapters/микроприложения. Исторические записи/результаты и проверенный legacy M4.9 не удалять. Изменять конкретные declarations; для каждой runtime-миграции иметь точный predecessor и восстановление, без массового docker rename/delete. + +**Результат и evidence:** один standalone image полного профиля, его manifest и инструкция запуска; таблица проверенных recordings/условий/ошибок; честный статус replay-prototype-qualified либо blocked. Подтверждены sequential exclusivity, переносимость на совместимые записи и регрессии сохранённых результатов. EoMT сохранён отдельно, не потерян и не включён в нагрузку первого профиля. + +**Выход:** закрыть scope первого прототипа только при прохождении его replay/standalone gates. Отдельно оставить `physical-live-pending`, `independent-quality-pending`, `vehicle-integration-pending`, `actuation-disabled`. Ни новый известный маршрут, ни прошлый успешный recording, ни хороший FPS не включают автономию. Будущие EoMT/другие профили проходят те же gates отдельно, без расширения текущего этапа до бесконечного поиска моделей. + +## Как измеряем и принимаем результат + +Для каждого испытания сохраняются точный profile/image/weights/config digest, effective mission policy, equipment/capture/calibration identity, Worker/hardware, драйверы/runtime, source identity, интервалы и численные критерии, cold/warm режим, исходные counters и итоговый verdict. Изменение значимого измерительного контекста требует новой квалификации, а не ручного `ready=true`. FPS измеряется для полного output contract; отсутствие обязательного слоя не считается ускорением профиля. + +Считаются source cadence, released/received/selected/inferred/emitted/dropped/expired/failed observations, queue depth, release lag, decode/preprocess/inference/postprocess, online geometry/TGS/fusion/policy и доставка результата до приложения, RSS/VRAM и объём передачи. Все входы должны быть учтены по однозначным терминальным категориям; processed FPS, successful-result cadence и fresh-result cadence — разные величины. У общего scene-result сохраняются возраст и source sequence каждого вложенного слоя, а не только свежий timestamp оболочки. + +P95/p99 model-time не заменяет end-to-end age. Для разных машин нельзя вычитать несогласованные часы: clock mapping и его погрешность входят в evidence; внутрипроцессные интервалы измеряются monotonic clock. Startup/warmup не скрывается, но не смешивается с steady-state FPS. Устройство/модель не считается ready до завершения warmup. + +Разрешённые пропуски определяются контрактом до запуска. К примеру, 6830/808.779495667/5 ≈1.689 результата/s: прежнее требование EoMT ≥1.8 FPS несовместимо со stride 5 на этом среднем исходном потоке. Требуется согласованная cadence-политика, а не механический перенос прежнего профиля. Quality-check для оптимизированных весов/precision/preprocessing отдельный: этот рефакторинг не создаёт ground truth и не даёт навигационную безопасность. + +Проверки идут от дешёвых схем/negative/unit tests к isolated Worker canary, затем integration/full replay и доступному physical live. На Mac запускаются только ограниченные релевантные проверки; никаких model benchmark или full stress suite. После каждого этапа фиксируются выполненный результат, ссылки на evidence, известные ограничения и GO/PAUSE/BLOCKED. Следующий этап не начинается при незакрытом обязательном критерии предыдущего. + +## EoMT: проверенные внешние сведения и предел вывода + +EoMT — семейство ViT-моделей сегментации изображений; архитектура применяется к semantic, instance и panoptic segmentation. Наш конкретный checkpoint — Cityscapes semantic EoMT-L 1024, а не универсальное обещание качества на любой камере/домене. Это следует из [карточки конкретной модели](https://huggingface.co/tue-mps/cityscapes_semantic_eomt_large_1024) и [исходной статьи](https://arxiv.org/html/2503.19108v1). + +В [официальном DINOv2 model zoo](https://github.com/tue-mps/eomt/blob/master/model_zoo/dinov2.md) для Cityscapes EoMT-L 1024×1024 указаны 25 FPS; условия таблицы — NVIDIA H100 с default `torch.compile`, если не оговорено иное. Это не показатель RTX 4090 и не end-to-end скорость нашей системы. Поэтому оснований объявить всё семейство «не real-time» нет, но и оснований квалифицировать наш профиль по этой цифре нет. Сохранение EoMT — отдельный исследовательский/резервный профиль, без обязательства неограниченно его ускорять. + +## Progress + +- 2026-09-01 18:15 UTC: локальный обзор backend/frontend/Worker и двух документов выполнен в предыдущей итерации; ограничения и отсутствие свежей Worker-проверки перенесены в этот план. +- 2026-09-01 18:15 UTC: прочитаны все пять документов CODEX_V5; уточнение владельца о взаимоисключающих профилях внесено в TARGET. Проверены первичные источники EoMT. Создан план ровно из четырёх этапов. +- 2026-09-01, последующий аудит: прочитаны M4.9T5/E47/M4 и integrated artifacts; через SSH выполнены только read-only Docker inventory/inspect, чтение installed manifests и GPU status. Подтверждено расхождение между viewer composition, reusable graph и portable package; выявлены другие GPU-capable сервисы. +- 2026-09-01 18:48 UTC: по уточнённому сценарию владельца план переработан под один полный standalone Perception-профиль DDRNet + RF-DETR + geometry/motion + TGS + policy-shadow. Два обязательных сегментационных образа больше не являются целью первого прототипа. Road-only/coarse-material разрыв и dependency compatibility включены в этап 1. +- 2026-09-01, следующее решение владельца: fine-grained road-only исключён из первого прототипа; coarse `hard_surface` принят, сельская среда — текущий контекст. Static-obstacle представление переиспользуется без распознавания отдельных видов предметов. Предыдущее требование road-vs-sidewalk gate снято; dependency compatibility остаётся технической задачей. +- 2026-09-01 19:15–19:58 UTC, этап 1: по прямому разрешению владельца остановлены Ollama/Frigate, Docker restart=no закреплён в runtime и Compose, добавлены manual-only profiles. Данные/модели/записи сохранены. После замеров эти два сервиса не восстанавливаются; остальные временно остановленные Mission Core Worker-контейнеры восстановлены. +- 2026-09-01 19:31–19:57 UTC: выполнены последовательные 64-sample baseline DDRNet, RF-DETR, TGS core и synthetic online local-surface. Ограничение BLAS/OMP/MKL до одного потока снизило mean synthetic local-surface с 198.0 до 63.2 ms без изменения алгоритмических порогов. Полный профиль этими цифрами не измерен. +- 2026-09-01 19:49–19:57 UTC: построен локальный диагностический image с Python 3.9 DDRNet environment, TensorRT 11/native Triton base, Python 3.12 geometry и C++ TGS. Все четыре исполнились отдельными последовательными probes одного image ID; DDRNet masks совпали на 64 кадрах. Модели ещё монтируются явно, общего supervisor/IPC нет; standalone/full-profile статус не присвоен. +- 2026-09-01: добавлены ADR 0049, transport-neutral stream/freshness/measurement contracts и pinned candidate manifest без image digest/active registry mutation. 78 focused tests прошли (51 новых contract + 27 существующих live-ingress/synchronizer/shadow); Ruff и mypy новых контрактов прошли. Модельные baseline и нагрузочные проверки на Mac не выполнялись. +- 2026-09-01 20:51 UTC: совместный граф выполнен на исходных camera/point/pose arrivals 1×. Исправлена bounded causal body history для motion/threat и векторизован costmap lookup. До оптимизации 120/128, 8 drops, p95/p99 353.98/401.19 ms; после — 128/128, 0 drops, 174.09/190.62 ms. Fresh input у 75/128 кадров; остальные явно unavailable. 86 focused tests прошли. Все результаты и отрицательные gates сохранены в отчёте этапа 1. +- 2026-09-02 00:20–00:41 МСК: уточнение владельца о долгосрочном экспериментариуме внесено в план, ADR, Desktop status и candidate `experiment_policy`. Тяжёлые профили сохраняются; functional, quality и hardware/source/transport-specific performance статусы независимы. +- 2026-09-02: добавлены CUDA-event/host-IPC timing и экспериментальные варианты DDRNet layout/CUDA Graph; оба не показали устойчивого выигрыша полного графа и не стали defaults. Затем реализован `--schedule overlap-cpu`: один serial GPU worker, один chronological CPU consumer, общий бюджет двух pending кадров, единый bounded учёт входов. Первый fixed-slot вариант потерял один кадр и сохранён как отрицательный результат; dynamic shared-slot вариант дважды дал 128/128 без drops. Маски, proposals, metric observations, tracks, threats, costmap и non-timing TGS output совпали с reference на всех 128 кадрах; age-based policy проверяется отдельно. +- 2026-09-02: 91 focused tests PASS (12 pilot, 52 contract, 27 existing live-ingress/synchronizer/shadow), Ruff PASS, Python 3.9 child lint PASS. Семь последовательных Worker runs и версии кода сохранены в `.runtime/perception-latency-20260902T0020MSK/manifest.json`. Worker-сервисы восстановлены, Triton ready=200, local 8000=200; Frigate/Ollama exited/restart=no. Никаких продуктовых defaults/registry cutover. +- Этап 1: частично выполнен; совместный пилот и ограниченный latency experiment выполнены. Performance gate остаётся FAIL, но сам по себе больше не является запретом экспериментальной упаковки. Следующие задачи: устранить source-adapter preroll/layered-freshness разрыв, перенести измеренное расписание в общий runtime, затем измерить transport/application boundary. DDRNet/online-surface jitter остаётся отдельным profiling направлением. Нельзя закрывать whole-path gate по compute-only метрике или отсутствию drops. +- Этапы 2, 3, 4: не начаты. Продуктовый backend/frontend path, active registry, canonical local 8000 и физический источник не переключались. Старый full-source materializer остаётся legacy; новый streaming transport ещё не реализован. + +## Surprises / открытые вопросы + +- Глобальная блокировка очереди противоречит независимости будущих Worker; нужно перенести ownership scope, а не просто оставить `max_concurrency=1` во всех слоях. +- Старые combined-package manifests сохраняют batch-семантику и не исполняют detector/geometry/TGS/threat. Красивый общий viewer использует отдельные сохранённые результаты; это не готовый профиль. +- FPS исходного recording и старые sampling/min-FPS требования математически расходятся. Численные product budgets должны быть закрыты в этапе 1; пользователь не задал их в этом уточнении. +- Чистое GPU-окно для ограниченных component probes получено: после остановки сторонних и старых Mission Core GPU-процессов 0% utilization и около 529–531 MiB системного/display VRAM. Ollama/Frigate отключены постоянно из автозапуска по явному разрешению владельца. Source uplink, clock alignment и долгий эксклюзивный full-profile run не подтверждены; 300–500 Mbps и будущее hardware остаются гипотезами до проверки. +- Существующий `static_obstacle` достаточен для неподвижных препятствий; точные semantic имена не являются пробелом scope первого прототипа. Динамика определяется temporal evidence, не классом объекта. +- Потеря различия дорога/тротуар/велодорожка в `hard_surface` — осознанно принятый владельцем компромисс сельского прототипа, не блокер. Геометрический запрет остаётся выше material allowance. +- Самостоятельный полный образ ещё не построен. Совместные lifecycle/IPC, resident модели и последовательный GPU schedule проверены в bounded пилоте с mounts, но performance gate FAIL. Экспорт нового образа заблокирован отсутствующим cached Triton blob / NVCR 403. Будущая поставка обязана включить веса и явно задать scratch/cache; рабочий mounted probe не равен standalone. В Triton base отсутствуют Python grpc/protobuf/cv2/TensorRT SDK: native trtexec не означает их наличия. Внутренний RF-DETR HTTP adapter позволил выполнить пилот без них. +- CPU online local-surface — выявленный latency risk даже после ограничения BLAS threads. TGS core около 1 ms на prepared clouds не включает online rolling preparation/costmap; нельзя подставлять эту цифру как стоимость всего геометрического слоя. + +## Decision log + +- 2026-09-01, решение владельца: EoMT и DDRNet не считаются вместе на Worker 006. Первоначальная трактовка «никаких двух моделей внутри профиля» отменена последующим уточнением: RF-DETR и DDRNet нужны внутри одного полного профиля; запрет сохраняется для альтернативных профилей и EoMT+DDRNet. +- 2026-09-01, решение владельца: один дрон — один Worker; текущий baseline RTX 4090. Следствие: worker-scoped exclusivity, без GPU-multiplexing и без зависимости от покупки hardware. +- 2026-09-01, решение владельца: EoMT сохранить отдельно, даже если не проходит real-time на текущей карте. Следствие: отрицательный benchmark оформляется как честный статус, а не повод блокировать DDRNet или бесконечно оптимизировать. +- 2026-09-01, рабочее решение плана: сначала контракты и baseline, затем runtime, затем продуктовая интеграция, затем квалификация и ограниченная миграция. Ровно четыре этапа; уточнения ведутся внутри них в этом же документе. +- 2026-09-01, решение владельца: первым нужен самостоятельный Docker с DDRNet, объектной детекцией, LiDAR-расстояниями и TGS для проверки многих записей K1 и последующего полигона. Следствие: цель — полный Perception-профиль, а не голая сегментация; нет зависимости от прежних вычисленных LAB результатов. +- 2026-09-01, решение владельца: беспилотника и motor integration сейчас нет. Следствие: текущий scope заканчивается проверенным perception/policy-shadow прототипом; actuator commands, autonomy acceptance и полный mission configurator — будущие отдельные gates, не скрытая часть этой реализации. +- 2026-09-01, рабочее решение прототипа: в одном контейнере допускаются несколько внутренних runtime-процессов одной задачи для сохранения модельной совместимости; все имеют одного supervisor и одного GPU scheduler. Изолированные среды не превращаются в отдельно устанавливаемые LAB-сервисы. +- 2026-09-01, решение владельца: никаких новых классов для столбиков/подобных предметов; существующего static-object / obstacle достаточно. Следствие: reuse текущего слоя и regression на RAV004, не новая модель/разметка перед первым прототипом. +- 2026-09-01, решение владельца: coarse `hard_surface` достаточен в сельской среде, включая тротуары/велодорожки. Следствие: прежние обязательные road-only/fine-class требования отменены; один segmenter DDRNet, без urban autonomy scope. Геометрия и unknown/freshness сохраняют приоритет. +- 2026-09-01, решение владельца: Ollama и Frigate больше не нужны в постоянной нагрузке. Остановить сейчас, убрать автозапуск после reboot, не восстанавливать после benchmark; сохранить данные для ручного использования. Выполнено и проверено по Docker/Compose, без физического reboot системы. +- 2026-09-01, инженерное решение: стартовый replay stride=1, source clock=1×, ≤16 MiB inflight и два pending camera frames; whole-path p95/p99 ≤125 ms остаются preregistered candidate. Перегрузка должна быть видна и проваливать strict gate; нельзя скрыто замедлить источник/сменить stride/подменить слой старым результатом. + +## Восстановление и остановки + +При неудаче короткого canary остановить только принадлежащий испытанию профиль, сохранить диагностику и проверить освобождение GPU; не убивать посторонние процессы и не продолжать full-session. Неясный владелец GPU или потеря lease требуют fail-closed остановки нового запуска, а не захвата ресурса поверх старого процесса. Переключение на другой профиль — отдельная последовательная операция, не автоматический GPU fallback. + +Новые схемы/декларации вводятся версионно. Возврат к точному предыдущему образу/конфигурации не превращает старый batch-путь в real-time; при откате сохраняется честный статус unavailable/not-qualified. Общую старую очередь нельзя ослаблять без worker-scoped fencing. Опубликованная история и исходники записи не переписываются для прохождения проверок. + +Новый scope, изменение аппаратной/операторской границы, необходимость физического действия, отсутствие нужного доступа или существенный выбор latency/quality — повод остановить соответствующую часть и запросить решение владельца. Обычные локальные исправления внутри согласованных границ не требуют переписывания плана. Настоящий прогресс, evidence и решения обновляются здесь, без новых параллельных планов на каждую проверку. + +## Outcomes / retrospective + +Результат этапа 1 на текущий момент: исполняемые invariants, pinned manifest-кандидат, component baseline и измеренный совместный граф с bounded causal history, очередью и исходным 1× clock. Локальная оптимизация убрала drops на 128 кадрах, но real-time gate не прошёл. Transport, network end-to-end, переносимость по нескольким записям и standalone packaging остаются непроверенными. Экспорт image дополнительно упёрся в отсутствующий cached Triton blob / NVCR 403; временный mounted pilot не заменяет поставляемый образ. Ollama/Frigate остались выключенными, остальной временно остановленный Mission Core-контур восстановлен. + +После этапа 4 здесь будут перечислены digest самостоятельного полного образа, измеренные статусы и ошибки по recordings, реально проверенные source/hardware/config комбинации, состояние сохранённого EoMT-варианта и оставшиеся physical-live/quality/vehicle-integration ограничения. Готовый Docker и готовая автономия не отождествляются. diff --git a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md new file mode 100644 index 0000000..5b4eba8 --- /dev/null +++ b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md @@ -0,0 +1,509 @@ +# Stream-first Perception — этап 1, контракты и ограниченный baseline + +Дата: 2026-09-01. Experiment ID: `perception-stream-stage1-20260901T1930Z`. +Worker: RTX 4090, 24564 MiB, NVIDIA driver 610.47. +Статус: **частичный результат этапа 1; не полный runtime и не real-time qualification**. +Обновление 20:51 UTC: совместный source-paced пилот выполнен. После оптимизации +128/128 кадров без drops; p95/p99 174.09/190.62 ms — FAIL исходного latency gate. +Подробности и evidence нового experiment `perception-joint-pilot-20260901T2040Z` +находятся ниже. Последнее дополнение — 2026-09-02 00:41 МСК: семь bounded +latency runs; shared-budget CPU overlap дважды дал 128/128 без drops, +но p99 194.25–198.22 ms не проходит исходные 125 ms. Подробности — в последнем +разделе. Это не product cutover и не самостоятельный образ. + +## Решение и сделанный объём + +Первый профиль зафиксирован как `K1 Perception — DDRNet-39 + RF-DETR + TGS`: +одна сегментация, детектор, online LiDAR/расстояния/static obstacles, +temporal/motion, TGS/costmap и advisory policy. EoMT не запускался и не удалялся. +Моторы, автопилот и Synology deployment не затрагивались. + +Добавлены: + +- [Версионные контракты](../../src/k1link/perception/realtime_contract.py): + bounded start без размера/длительности/полного архива, обязательные каналы, + epoch/lease/profile bindings, шесть выходных слоёв, causal freshness и + отрицательные критерии whole-path real-time проверки. +- [Candidate manifest](../../config/perception/k1-perception-ddrnet39-rfdetr-tgs-prototype-v1.json): + pinned модели/алгоритмы, accepted coarse `hard_surface`, static.unknown, + serial GPU policy, исходные фильтры, пределы памяти/очередей/задержки. + Он не зарегистрирован как готовый executor; image digest остаётся `null`. +- [ADR 0049](../../docs/adr/0049-stream-first-perception-profiles.md): карта + CURRENT → TARGET, reuse существующего raw-first ingress, lifecycle, + no-preload правило и стратегия изоляции зависимостей внутри одного образа. +- [Ограниченные диагностические программы](worker/streaming_profile_stage1/). + +**Старый `source_materializer.materialize(job)` не удалён и рабочий LAB-путь +не переключён.** Запрет полного предварительного копирования сейчас закреплён +в новом контракте и тестах. Реального нового сетевого runtime эти изменения +ещё не создают. gRPC остаётся кандидатом, а не проверенным транспортом. + +Новый путь должен выдавать текущие результаты до EOF; полное хеширование, +распаковка, PNG-cache и конечная публикация не могут быть условием первого +inference. Текущие запись и raw-first hooks сохраняются; второй acquisition +контур для K1 не создаётся. Защита от перегрузки обязана учитывать суммарные +байты, а не только число сообщений. + +## Условия измерений + +Все модельные проверки выполнены **последовательно**, только на Worker. +На Mac — лишь ограниченные unit/regression проверки, без моделей и нагрузки. +На время GPU-проб останавливались старый Triton, perception-worker и installed +LAB agent; после проб они восстановлены. До нагрузки GPU utilization был 0%, +память около 529–531 MiB (системный/display остаток). Независимые профили не +запускались вместе. Внутренние CUDA auxiliary streams одного RF-DETR engine +не означают параллельные профили. + +Контейнеры проб: `--rm`, фиксированные image IDs, labels `mission-core` / +`observatory`, `--network none`, read-only root/assets, dropped capabilities, +ограниченные CPU/RAM/PIDs/tmpfs. GPU-пробы: 6 CPU / 8 GiB; CPU-пробы: +2 CPU / 2 GiB. Никакие веса не скачивались. Использовались уже имеющиеся на +Worker входы; полная запись не пересылалась и не хешировалась перед пробой. + +Это короткий component baseline, **не source-paced replay**. Восемь warmup +итераций DDRNet не входят в 64 измеренных кадра; декодировано 65 исходных +кадров. RF-DETR измерен на синтетическом uint8 tensor. TGS использовал первые +64 уже подготовленных causal rolling clouds: это разрешено для изолированного +замера ядра, но запрещено как замена online preparation в полном профиле. +Local-surface использовал 64 синтетических облака по 4000 точек, stationary +sensor, seed `20260901`; логические timestamps 10 Hz не были pacing-механизмом. + +## Компонентные результаты + +Время в миллисекундах. Здесь нельзя складывать p95 или обращать отдельные +значения в обещанный FPS полного профиля. Для сохранённых массивов использован +nearest-rank percentile `ceil(q*N)-1`; RF-DETR — percentiles самого trtexec. +При N=64 p99 nearest-rank равен максимуму и не характеризует редкие хвосты. + +| Проверка | Среднее | p95 | p99 | Что не включено | +| --- | ---: | ---: | ---: | --- | +| DDRNet, исходный image, FP32, decode/preprocess/H2D/forward/post/D2H | 21.523 | 43.064 | 47.150 | Сеть, остальные слои, публикация | +| RF-DETR TRT11, DMA включён | 2.301 | 2.505 | 2.986 | Реальное изображение/качество, host filtering, сеть | +| TGS C++ на prepared rolling clouds | 1.034 | 1.242 | 1.519 | Подготовка rolling cloud, costmap, транспорт | +| Online local-surface, synthetic, BLAS threads=1 | 63.219 | 66.066 | 73.904 | Реальная траектория, object association, motion/policy | + +DDRNet load + first decode + model warmup: 9.160 s, без создания/распаковки +Docker-контейнера и без сетевого старта. Torch allocated peak 276.35 MiB, +reserved 316 MiB — **не** общий VRAM peak профиля. Существующий runner сохраняет +floor-percentiles; таблица пересчитана из его 64 raw rows, не из округлённых +агрегатов. Веса, preprocessing и FP32 не менялись. + +RF-DETR: `--warmUp=1000 --duration=0 --iterations=64 --avgRuns=1 +--percentile=95,99 --includeDataTransfers --noCudaGraph --noSpinWait`. +TRT11 по умолчанию отключает transfers и включает CUDA graph/spin-wait; +первый диагностический результат без DMA не принят как сравнимый baseline. +В принятом запуске средние H2D / GPU / D2H: 0.120 / 2.173 / 0.009 ms. +Это engine latency, не latency готовых объектов в приложении. + +С default numeric-library threading synthetic local-surface занимал в среднем +198.043 ms. При `OPENBLAS_NUM_THREADS=1`, `OMP_NUM_THREADS=1`, +`MKL_NUM_THREADS=1` — 63.219 ms. Пороги геометрии не менялись; bitwise parity +геометрических выходов не проверялась. Все 64 состояния — valid. +Thread limits добавлены в candidate execution policy. CPU-геометрия остаётся +существенным риском бюджета: это уже больше времени, чем оба отдельных +модельных измерения, а online association/motion/fusion ещё не замерены вместе. + +## Проверка общей базы образа + +Собран **диагностический**, не самостоятельный продуктовый образ: +`ndc-perception-stage1-dependency-probe:20260901`, local image ID +`sha256:664824aa25de1db178f177d67a81b01541a938b479812b9383ddbf03f6b59dbe`. +Создан 2026-09-01 19:49:38 UTC; сборка без network/pull из существующих баз: + +| База | Проверенный local image ID | +| --- | --- | +| Installed DDRNet step | `e6c986100613ec804f0e0076ca8695abf43ff88ef9d5d85f6857e0b41db74051` | +| TRAVEL TGS | `7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f` | +| Triton 26.06 | `58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794` | + +В final base скопированы старое `/opt/conda` и C++ TGS binary. Проверены +отдельными последовательными запусками **одного и того же image ID**: + +- DDRNet Python 3.9 / Torch 1.13.1 cu117: 64 кадра; среднее 20.781 ms, + p95 39.665 ms, p99 47.251 ms; model-load/first-decode/warmup 8.422 s. + SHA последовательности masks совпал с исходным image: + `7b4cc5e10f0ee7a5cc20ff0679f4b972607975555b7d16670fff19e4ca491adb`. + Это ограниченный parity check 64 кадров, не всего датасета. +- RF-DETR native TRT11: 64 synthetic queries, среднее 2.303 ms, p95 2.356 ms, + p99 2.794 ms, те же явные флаги DMA/graph/spin-wait. +- Python 3.12 online local-surface: 64 valid состояния, mean 63.518 ms. +- Скопированный C++ TGS binary: 64 prepared clouds, mean 1.060 ms. + +Таким образом, базовый ABI/import/execution разрыв решаем через изолированные +процессы/interpreters в **одном образе**, без обновления DDRNet checkpoint. +**Совместно resident модели, общий supervisor/IPC/scheduler и полный граф в +одном экземпляре контейнера не проверены.** Пробы используют явные read-only +mounts весов, runner и входов; они не доказывают standalone packaging. +Диагностический image сохранён для воспроизводимости, активного контейнера нет. + +Выявленные требования к настоящей сборке: + +- Старый DDRNet image не содержит checkpoint в объявленном logical asset path. + Начальная проба image-only завершилась до inference. Веса/runner должны быть + внутри нового образа, а не неявным host-cache. +- Super-gradients требует writable log directory; предоставлялся ограниченный + tmpfs `/root/sg_logs`. Matplotlib использовал temporary cache; будущий runtime + должен явно задавать writable scratch/cache paths и их ограничения. +- В Triton base есть native trtexec/server и Python 3.12/NumPy, но не найдены + Python `tensorrt`, `grpc`, `cv2`, `google.protobuf`. Нельзя считать SDK/codec + окружение готовым. Допустим внутренний supervised native Triton; зависимости + supervisor/transport необходимо явно включить и проверить. +- TensorRT plan связан с runtime/hardware совместимостью. Переносимость Docker + не означает автоматическую совместимость engine с другой GPU/Apple Silicon. + +## Ollama / Frigate: изменение по прямому разрешению владельца + +Оба сервиса остановлены и **не восстановлены** после измерений: +`sentinel-ollama`, `sentinel-frigate`. Docker restart policy обоих — `no`. +Данные, модели и записи камер не удалялись. + +Изменён источник Compose на Worker: +`D:\_PROJ\NODEDC\NODEDC_AEGIS\docker\docker-compose.frigate.yml`. +Frigate получил `profiles: [manual-frigate]`, Ollama — `[manual-ollama]`, +оба `restart: "no"`. Проверка 2026-09-01 19:58:13 UTC: обычный +`compose config --services` не включает ни одного из этих сервисов; +явные manual profiles содержат нужные сервисы с restart=no. +Проверенные task/startup entries по именам сервисов не обнаружены. +Физическая перезагрузка Windows не выполнялась: проверена конфигурация +автозапуска, а не результат реального reboot. + +Backup сохранён рядом: +`docker-compose.frigate.yml.before-manual-only-20260901T1915Z`. +SHA-256 до: `2f762ca0361411091a6ca184fbef73fdce7739957476bc25270b9464ad3c205b`. +После: `5e5b1f52e5d328a1fcae8a026a71dec81342734e6770a8fbf3bb8ddd38e7c331`. +Не заменять весь Compose слепо при будущем rollback: сначала проверить drift. +Редкое использование Ollama требует явного ручного запуска; это не повод +возвращать её в постоянную GPU-нагрузку. + +Остальной durable Mission Core Worker-контур восстановлен. Triton readiness +проверен HTTP; локальный canonical Mission Core `127.0.0.1:8000` возвращает 200. +У legacy perception-worker до проб наблюдался restart loop (387 restarts); +восстановление контейнера не означает исправления этого прежнего дефекта. +Не связанные с задачей сервисы/данные не менялись. + +## Проверки и evidence + +78 focused tests прошли: новый contract suite (51) плюс существующие +`test_live_perception`, `test_live_perception_synchronizer`, +`test_live_perception_shadow` (27). Ruff новых contract/test и обеих Python +probe программ — PASS; mypy contract module — PASS. Для DDRNet probe lint +использует Python 3.9 target, не несовместимый с ним `datetime.UTC`. +Это не полный backend/frontend suite и не нагрузочный тест. + +Unit tests показывают, среди прочего, что существующий raw-first ingress +отдаёт наблюдение до `end_session`, а новый contract не принимает batch mode, +full-source fields, cross-epoch/future/stale relabeling, неполный scene, +скрытые пропуски, замедленный replay и превышение инженерных бюджетов. +Они не доказывают доставку application ↔ Worker по сети. + +Raw timings/logs и replay commands сохранены вне Git: +`.runtime/perception-stream-stage1-20260901/`. UTC/monotonic anchors DDRNet: +baseline `2026-09-01T19:31:47.850689+00:00`, monotonic +`43059737808266` → `43070282556549`; combined-image +`2026-09-01T19:54:58.292953+00:00`, `44450232680793` → `44459991768361`. +Эти monotonic значения не вычитаются из часов Mac. trtexec logs содержат UTC +и device-local durations; межмашинный clock mapping ими не измерен. + +| Raw artifact | SHA-256 | +| --- | --- | +| ddrnet-baseline.json | `6c33cd98c09bbe91c4a0ef45a75dcdc8426b8b3227988e772225b011167da528` | +| rfdetr-trtexec.log | `078f6a311cb00ad7326d5b9d99799bf45c97546a6f244f5507037b56ebe9917a` | +| tgs-baseline.json | `fe264d31a6a5215edea68c5497eb5c862d5f002a4711190e95dbd0ac952a9430` | +| surface-default-threads.json | `aa7df56e250b8a179f6e61ddd34a312c0594d409122259813e366d75511e066c` | +| surface-single-thread.json | `190794710cd3dbb40313bdbba57fe7e182e2f3dc32c7809b246ae5d257368b19` | +| ddrnet-combined-image.json | `72930d502ce3aab5b146c4c18a8a2b24abfc7bda25b3c6a16425a2e7f8ac6c2e` | +| rfdetr-combined-image.log | `cbff78a8644a6a59132cda64717fd4f206589c52f6fbc5426457445fc451b6a8` | +| surface-combined-image.json | `5d76520bceee57d2f39e2404eb9fa8776d38d2f837a3b116a295538c040463da` | +| tgs-combined-image.csv | `c80faa6cc54860d86af57079954d6654db1a58eecccd432d3992684ba941267a` | + +Model/config pins находятся в candidate manifest; существующие raw recordings, +clouds и приватные logs не добавлялись в Git. + +## Оставшиеся gates: не объявлять этап 1 или real-time автоматически закрытыми + +1. Численные budgets зафиксированы **как инженерный candidate**, не как + измеренное достижение или vehicle safety approval: whole-path p95/p99 + ≤125 ms, layer age ≤250 ms, release lag ≤25 ms, inflight ≤16 MiB, + camera pending ≤2, zero capacity drops при начальном stride 1. + Их нельзя ослаблять задним числом ради успешного прогона. +2. Совместный causal pilot выполнен 2026-09-01 в 20:51 UTC; его результаты + приведены ниже. Оба модельных процесса resident, GPU inference последователен. + После локальной оптимизации получены 128/128 результатов, но p95/p99 + 174.09/190.62 ms и backlog growth 51.44 ms не проходят исходные бюджеты. + Измерение выполнено; real-time qualification не получена. +3. Риски detector filters для маленького животного/близкого крупного объекта + установлены по коду (min box 64 px, max fraction 0.5, FOV 0.5), но quality + acceptance на этих случаях не выполнен; пороги сохранены без изменений. +4. Standalone упаковка всех assets, streaming transport/codec/clock mapping, + per-worker fencing, общий supervisor и end-to-end receiver timestamps + остаются следующими реализационными задачами. Нет автоматического GO на + полный recording-run, UI cutover, физический live или автономное движение. + +Этапы 2–4 не объявляются начатыми/пройденными за счёт диагностического image. +Существующие исторические результаты и batch acceptance сохранены без +переписывания. Продолжение ведётся в одном +[четырёхэтапном ExecPlan](../../docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md). + +## Совместный потоковый пилот — 2026-09-01, 20:51 UTC + +**Результат:** полный вычислительный граф действительно исполняется в одном +временном контейнере на RTX 4090. Это уже не сумма отдельных model benchmarks. +Оптимизированный запуск завершил окно 128 кадров без capacity drops, но +**performance gate остаётся FAIL**. Продуктовый batch-путь не переключён. + +### Граница и метод + +- Один контейнер `ndc-k1-ddrnet-rfdetr-tgs-joint-pilot`, один supervisor, + постоянный DDRNet Python 3.9, native RF-DETR TensorRT/Triton, CPU supervisor + Python 3.12 и C++ TGS. DDRNet завершается до вызова RF-DETR; EoMT отсутствует. +- Рассчитываются DDRNet masks → RF-DETR proposals → online local surface → + LiDAR association/ranges → temporal/motion/rolling obstacles → simulated + threat assessment → TGS/costmap → hard-surface-only advisory policy. + На каждой камере работают обе модели. При отсутствии допустимых текущих + cloud/pose метрические слои возвращают unavailable, а не выдуманный результат. +- Источник RAVNOVES00, session `20260720T065719Z_viewer_live`: существующее + camera video `cadd1696…`, camera index из job + `recorded-camera-602ac89026ed12978619801d`, normalized LiDAR replay v2 + `8fc0fb418578b8ee2ac88d502d2acbc63ae533437a9da14f1a9f9d8916f613ce`. + Из архива последовательно читаются original host-arrival timestamps, + point increments и pose. Старый E10 pack используется **только** для трёх + малых статических calibration arrays. Нет готовых masks, surface, TGS, + detections или threat ledgers в качестве входа графа. +- Источник подаётся отдельным producer по исходным временам 1×, не по окончанию + inference. Камерное окно занимает 12.684938 s между первым и последним кадром. + Интервалы: min 2.724 ms, median 99.594 ms, max 215.529 ms; 10 интервалов + короче 50 ms. Поэтому равномерный synthetic 10 Hz не эквивалентен этой записи. +- Прогрев моделей предшествует admission. Начальный sensor preroll ≤500 ms; + raw rolling cloud ≤1 s / 64000 points; pending camera ≤2; aggregate queued + + active observation bytes ≤16 MiB. Один кадр декодируется после его due time. + В финальном запуске прочитано 229/4570 point records, 241/4598 poses, + 545590/10751258 XYZ rows, включая отброшенный начальный sensor prefix. + Полная запись не копировалась, не хешировалась и не декодировалась до старта. +- Scene сериализуется и разбирается фактическим **локальным** collector внутри + контейнера. `source_due_to_receiver_ms` включает release/decode/queue/весь граф + и этот collector, **не включает сеть Mission Core ↔ Worker и viewer**. + Сохранение диагностического JSONL происходит после receiver timestamp; + его возможная задержка следующего кадра остаётся видна в queue timings. +- CPU libraries: BLAS/OMP/MKL=1; container 8 CPUs / 8 GiB. CPU quota throttling + в финальном измерении отсутствовал (`nr_throttled=0`). Это не доказывает + отсутствие любого host/driver jitter. Измеренная memory — cgroup memory, + не сумма RSS процессов; sampled VRAM содержит системную/display составляющую. + +### Исправления, которые выявил именно совместный запуск + +1. Разделены `PYTHONPATH` Python 3.9/3.12: общий путь к Pillow 3.12 ломал DDRNet + при загрузке. Первый canary остановился до admission, без кадров. +2. Threat/motion использует прошлую body pose. Адаптер «только текущая поза» + остановил первое 128-frame окно после 63 результатов. Добавлена bounded + история 64 уже вычисленных body frames; запрос будущего frame запрещён. + Body frame — только camera-forward simulation с прежними height/slope + ограничениями, **не** future-trajectory resolver и не реальная установка рига. +3. Vectorized lookup заменил Python tuple/dict loop по точкам costmap, сохранив + grid membership, holes и индексы. Synthetic exact-parity test прошёл; + DDRNet masks совпали на всех 120 общих кадрах двух запусков. Это не полная + parity всей temporal scene: набор обработанных кадров различался из-за drops. +4. Publication guard учитывает возраст камеры **и** исходных cloud/pose. + Устаревшее evidence остаётся доступным для диагностики, но все его terrain + actions принудительно NO_GO. Только coarse hard_surface с поддержанной + геометрией может быть ALLOW_candidate; rural bare_soil здесь не разрешён. + +### Измерения (nearest-rank percentiles, без отбрасывания медленных кадров) + +| Запуск | Результаты / вход | Drops | Source→local receiver p95 / p99 | Решение | +| --- | --- | --- | --- | --- | +| Canary 32, рабочий ABI | 32 / 32 | 0 | 232.39 / 253.02 ms | FAIL latency/backlog | +| 128, bounded causal body history | 120 / 128 | 8 | 353.98 / 401.19 ms | FAIL latency/overflow | +| 128, vectorized costmap | 128 / 128 | 0 | 174.09 / 190.62 ms | FAIL latency/backlog | + +Финальный запуск `joint-pilot-128-vectorized`, UTC start +`2026-09-01T20:51:35.734802+00:00`, Worker monotonic start `47847791349665`. +Replay mapping: source zero `200950673923333` → Worker zero `47857207269471`. +Последний result `47870540878573`. Часы разных машин не вычитаются напрямую. + +Дополнительные результаты финального окна: + +- mean source→receiver 87.94 ms; max 213.89 ms. Compute→receiver p95/p99 + 115.25/122.98 ms, но **этой более узкой метрикой нельзя заменить end-to-end**. +- Queue wait p95/p99 68.68/90.36 ms; прирост средней очереди последних восьми + относительно первых восьми кадров 51.44 ms при лимите 25 ms. +- Source release max 12.78 ms по всем трём каналам — PASS ≤25 ms. +- Первый результат через 546.12 ms от начала sensor-preroll clock, до конца + пилотного окна и до EOF записи. Model/runtime warmup 9.36 s; stop 4.07 s. +- Peak sampled GPU memory 1932 MiB; peak cgroup memory 3342.25 MiB; + observation inflight 7194040 bytes (6.86 MiB), pending peak 2; residual 0. +- TGS/costmap/policy среднее по всем кадрам снизилось с 21.25 до 4.09 ms; + эти средние включают unavailable-кадры. Модельные веса и detector filters + не менялись. Новые бюджеты для получения PASS не вводились. + +### Что реально посчитано и чего этот результат не доказывает + +75/128 кадров имели допустимую текущую cloud/pose пару; для них рассчитаны +online surface и TGS. На 53 кадрах — unavailable. В записи 43 камеры без нового +point increment и 39 с pose age >100 ms (множества пересекаются). Отдельно первый +кадр отвергнут из-за объединённых preroll increments возрастом до 408 ms — +это ограничение текущего адаптера, не доказательство неисправности сенсора. +Не следует повышать свежесть до «current» повторной маркировкой старого облака. + +Опубликованы 398 метрических obstacle observations, из них 275 geometry-only; +детектор на данном отрезке выдавал `person`, `car`, `truck`. Рассчитаны motion +и simulated threats; 62 assessment имели decision=threat, но это **не** +подтверждённые физические угрозы или accuracy score. Cat/dog/близкий крупный +объект и регрессия RAV004 этим отрезком не квалифицированы. Повторяющиеся +наблюдения не считаются уникальными физическими объектами. + +21 scene получили stale publication guard, в том числе 3 с допустимым входом, +устаревшим в вычислениях/очереди; ни у одной stale scene нет ALLOW. Body/threat +qualification относится к виртуальному corridor contract, не к полигону. +Scene lineage сохраняет реальные времена точек/pose; старые domain-observation +timestamps всё ещё привязаны к camera anchor. Общий layered freshness ABI +этапа 2 должен учитывать это явно, а не объявлять текущий адаптер финальным. + +### Packaging и состояние системы + +Native bases проверены по ранее зафиксированным image IDs. Сборка кода, +Pillow и C++ прошла, но экспорт нового полного image остановлен: у Docker +Desktop отсутствует compressed layer `0e5f8475…` исходного Triton, а NVCR +возвращает 403. Настройки/секреты авторизации не менялись. Pilot-assets (33.52 MB) +экспортированы из уже доступных локальных build files и подключены read-only +к работоспособной общей базе `sha256:664824aa25de1db178f177d67a81b01541a938b479812b9383ddbf03f6b59dbe`. +Веса также explicit read-only mounts. Это **не самостоятельный поставляемый +Docker** и не обход отсутствующего image-release gate. Для обычного образа +Dockerfile требует `--target pilot`; `--target pilot-assets` — только диагностика. + +До model runs: 533 MiB VRAM, 0% GPU; прежние Mission Core GPU-сервисы временно +остановлены. После проб временных контейнеров нет; Triton и два Mission Core +worker agents восстановлены, Triton ready=200 / healthy, local Mac 8000=200. +Прежние transport/restart проблемы agents зафиксированы до остановки +(perception-worker 33 restarts, installed-agent 3), но не ремонтировались этим +пилотом. Frigate/Ollama остаются stopped/restart=no, данные сохранены. + +### Evidence, проверки и следующий gate + +Raw reports, scenes и subprocess logs: +`.runtime/perception-joint-pilot-20260901T2040Z/`; такие же run directories +сохранены на Worker под `D:/NDC_MISSIONCORE/runtime/experiments/`. +Команды, pins и ограничения — в `manifest.json` этого evidence directory. + +| Артефакт | SHA-256 | +| --- | --- | +| joint-pilot-128-causal-history/report.json | `370bbd97dab1f7881614b18932e0b841dc791b9e5bfebf3e80707c7b437252e8` | +| joint-pilot-128-vectorized/report.json | `80d6843d793dea50a738a4bdf77dc3c6e1bd3a186b8dd58b89ba400611eaacd9` | +| joint-pilot-128-vectorized/scenes.jsonl | `d8cf53dee06cc08bd244d8676e8469a455f610328c44442f0192b2f37ed4afc7` | +| pilot_graph.py, финальная версия | `fd4d5307d4135250791cce73607c04c46f037481860cac691fc50d25e1daa1c4` | +| run_joint_pilot.py, финальная версия | `9ae8d62ea90a5140e90c09f035c29d933887392fe5d2d15635cf912c94d73808` | +| C++ pilot-tgs binary | `1ecb25a1db8dd90609754d4a98aa4ac24f50feb3023cf445a669c6c1cf72aa20` | + +Focused verification: 86 tests (8 новых pilot + 51 contract + 27 existing +ingress/synchronizer/shadow); Ruff, включая Python 3.9 child target. Full +backend/frontend suite и field/physical-live не выполнялись. + +**Итог gate:** совместный пилот как измерение выполнен; stage-1 performance +приёмка остаётся открытой. Следующая техническая работа — стоимость/джиттер +DDRNet и online surface, расписание единого графа при реальных burst intervals, +отдельные arrivals/age/unknown для модальностей и корректный preroll admission. +Не разрешены скрытый stride, замедление clock, повышение порогов или подмена +метрик. После этого повторить тот же bounded pilot, затем переходить к +standalone/transport этапа 2. Полная запись и автономный выезд не разрешены +самим фактом 128 успешных callback результатов. + +## Дополнение 2026-09-02: снижение задержек, не отсечение тяжёлых профилей + +Уточнение владельца: Observatory — долгосрочный экспериментариум переносимых +полных профилей для разных совместимых записей. Overload на 4090 допускается +как явно измеренный результат и не блокирует экспериментальную упаковку. +Functional readiness, качество и real-time qualification на конкретной связке +profile/config/hardware/source/transport фиксируются раздельно. Перенос на борт +может убрать внешнюю сеть, но не отменяет decode, IPC, queues и compute. +Это уточнение заменяет прежнюю зависимость «обязательно performance PASS до +развития этапа 2»; gates и запрет actuation при этом не ослаблены. + +### Что изменено и проверено + +- `pilot_ddrnet_runtime.py`: host/CUDA-event timing отдельно для H2D, model, + sigmoid, layout, argmax и D2H. Измерение модельного GPU-интервала не является + profiler-доказательством compute saturation: в нём возможны scheduling gaps. +- Исследованы перестановка scores перед argmax и локальный CUDA Graph capture + фиксированного FP32 DDRNet. Sigmoid сохранён: его saturated ties могут сделать + `argmax(logits)` неэквивалентным исходной модели. Реальная GPU tie-проверка и + все 128 mask hashes у обоих вариантов совпали с reference. +- `pilot_scheduler.py`: один GPU thread исполняет DDRNet → RF-DETR строго + последовательно, CPU association/surface/motion/TGS/policy обрабатывает + предыдущий кадр в исходном порядке. Второго профиля и GPU concurrency нет. +- Очередь завершённых GPU результатов и ingress делят **два pending места**; + output slot резервируется до следующего GPU вызова, поэтому скрытого + «третьего готового кадра в заблокированном put» нет. Активные входные payloads + остаются в общем 16 MiB учёте до окончания CPU; Docker ограничен 8 GiB. +- Backlog growth в последней версии учитывает ожидание и ingress, и GPU→CPU. + Старые raw reports не переписаны. Запись не замедлялась, кадры не прореживались, + веса, FP32 DDRNet, RF-DETR engine и алгоритмические пороги не изменены. + +### Все семь прогонов, включая отрицательные + +Одна исходная запись, первые 128 camera frames, original host-arrival clock 1×, +12.685 s camera window, те же raw points/pose/calibration и локальный collector. +Прогоны последовательные, короткие, не рандомизированные: это инженерный +эксперимент, не статистически завершённая performance qualification. + +| Run | Results / 128 | Drops | Mean source→collector | p95 | p99 | Mean ingress wait | +| --- | --- | --- | --- | --- | --- | --- | +| reference-128, serial eager | 128 | 0 | 93.75 ms | 157.82 ms | 189.69 ms | 13.65 ms | +| channels-last-128, serial eager | 128 | 0 | 87.68 ms | 190.56 ms | 203.23 ms | 11.95 ms | +| cuda-graph-128, serial | 128 | 0 | 93.38 ms | 175.32 ms | 213.41 ms | 15.22 ms | +| overlap-cpu-128, fixed 1+1 slots | 127 | 1 | 79.57 ms | 121.21 ms | 131.42 ms | 4.74 ms | +| overlap-shared-128, shared 2 slots | 128 | 0 | 81.30 ms | 143.32 ms | 198.22 ms | 7.20 ms | +| serial-repeat-128 | 128 | 0 | 105.08 ms | 232.29 ms | 256.86 ms | 25.48 ms | +| overlap-shared-repeat-128 | 128 | 0 | 83.54 ms | 153.44 ms | 194.25 ms | 8.31 ms | + +Вывод: layout и CUDA Graph не дали устойчивого whole-graph выигрыша; defaults +не изменены. Fixed-slot p95 ≤125 ms нельзя выдавать за успех — он потерял кадр +и провалил p99. Shared-budget overlap перспективен по очереди/средней задержке, +но его p99 хуже первого serial reference и лучше serial repeat. Поэтому нет +утверждения о гарантированном ускорении tails. Все варианты пока — явные flags +диагностического стенда; default остаётся serial/eager/reference. + +У обоих shared-budget runs все 128 масок, source lineage, proposals, +метрические observations, tracks, threats, costmap states/materials и TGS counts +без `algorithm_ms` совпали с reference. Runtime age и соответствующая policy +естественно различаются и не исключаются из safety guard. В повторе 16 stale +scenes; ни одной с ALLOW. Все actuation/commands=false. Это output parity на +данном окне, не quality/accuracy acceptance. + +Последний повтор: fresh cloud/pose 75/128, 398 metric observations; preroll и +layered freshness остаются открыты. Warmup 11.34 s, первый result 549.58 ms +от начала bounded preroll, stop 4.07 s; source-release max 8.72 ms. Pending +peak 2, input payload peak 5,202,376 bytes, residual bytes/slots 0; backlog +growth 0.224 ms. Sampled VRAM peak 1932 MiB; GPU utilization mean 34.88%, +max 83%; cgroup memory peak 6410.07 MiB (не только Python heap). +Таким образом, **«менее 5% загрузки GPU» не подтверждено**: доля VRAM и +GPU utilization — разные метрики. Исчерпание 24 GiB тоже не наблюдалось. + +### Evidence и эксплуатационное состояние + +Raw reports/scenes/logs, точные команды, SHA и пять code snapshots сохранены +в `.runtime/perception-latency-20260902T0020MSK/manifest.json`; копия evidence +на Worker: `D:/NDC_MISSIONCORE/runtime/experiments/perception-latency-20260902T0020MSK`. +Domain-code assets и model pins прежние; snapshots отражают именно версию +probe каждого прогона. Никакие raw reports не заменены «лучшими» результатами. + +| Артефакт | SHA-256 | +| --- | --- | +| reference-128/report.json | `50ed0cb20ecafda6b011f4658a01629816fbd10b11a63f90196ea700738bf2b6` | +| overlap-shared-128/report.json | `76c9309fe6ef2281798b81c40e4f5c97b6289f9babe76f917db3f6bc3d7ffe7e` | +| serial-repeat-128/report.json | `28f0af8dec12db63de5142637d92245e31fac9389f16b9e845e68a8da1ee5acd` | +| overlap-shared-repeat-128/report.json | `e7fea02198c816f82e7f2a54d81ed0f1467867fb84bf5fe3252f06e9905cec2e` | +| overlap-shared-repeat-128/scenes.jsonl | `87b9a14091b37337a2a0df5f80b56b7ea3ec52fc4e0d369d88e77afe45a2dc10` | +| shared-budget-v2-code.tar.gz | `be7058b92352064580bca832e0db2f76c99485ad2f97e28cc4fa894dbf196860` | + +91 focused tests PASS: 12 pilot, 52 contract, 27 existing live-ingress/ +synchronizer/shadow. Ruff PASS, child lint с Python 3.9 target PASS. Mac не +выполнял модельной нагрузки. Full frontend/backend suite, другие маршруты, +network benchmark, physical-live и actuation в этих пробах не проверены. + +Временный pilot-контейнер удалён штатно `--rm`. Три временно остановленных +Mission Core контейнера восстановлены; Triton ready=200, canonical Mac 8000=200. +Frigate/Ollama по решению владельца остаются exited/restart=no; reboot не +выполнялся. Продуктовые defaults, registry и backend/frontend не переключены. +Standalone image и приложение↔Worker transport всё ещё не реализованы этим +стендом. Следующая работа — preroll/layered freshness, общий runtime с +измеряемыми очередями и реальный binary data plane; performance FAIL на 4090 +не повод выбросить профиль или остановить развитие экспериментариума.